]> granicus.if.org Git - imagemagick/blobdiff - coders/jpeg.c
Check for sampling-factor option only if sampling-factor image property is NULL.
[imagemagick] / coders / jpeg.c
index 069d8c3445f206f6759323dbe527e983eb11b118..2ff4b6578a8d7d1c8fe2b8532ec0dd834ae3d963 100644 (file)
@@ -77,6 +77,7 @@
 #include "MagickCore/static.h"
 #include "MagickCore/string_.h"
 #include "MagickCore/string-private.h"
+#include "MagickCore/token.h"
 #include "MagickCore/utility.h"
 #include "MagickCore/xml-tree.h"
 #include "MagickCore/xml-tree-private.h"
@@ -85,8 +86,6 @@
 #define JPEG_INTERNAL_OPTIONS
 #if defined(__MINGW32__)
 # define XMD_H 1  /* Avoid conflicting typedef for INT32 */
-typedef unsigned char boolean;
-#define HAVE_BOOLEAN
 #endif
 #undef HAVE_STDLIB_H
 #include "jpeglib.h"
@@ -100,7 +99,7 @@ typedef unsigned char boolean;
 #define ICC_PROFILE  "ICC_PROFILE"
 #define IPTC_MARKER  (JPEG_APP0+13)
 #define XML_MARKER  (JPEG_APP0+1)
-#define MaxBufferExtent  8192
+#define MaxBufferExtent  16384
 \f
 /*
   Typedef declarations.
@@ -159,8 +158,10 @@ typedef struct _QuantizationTable
     width,
     height;
 
+  double
+    divisor;
+
   unsigned int
-    divisor,
     *levels;
 } QuantizationTable;
 \f
@@ -245,7 +246,7 @@ static boolean FillInputBuffer(j_decompress_ptr cinfo)
     MaxBufferExtent,source->buffer);
   if (source->manager.bytes_in_buffer == 0)
     {
-      if (source->start_of_blob != 0)
+      if (source->start_of_blob != FALSE)
         ERREXIT(cinfo,JERR_INPUT_EMPTY);
       WARNMS(cinfo,JWRN_JPEG_EOF);
       source->buffer[0]=(JOCTET) 0xff;
@@ -327,6 +328,8 @@ static void JPEGErrorHandler(j_common_ptr jpeg_info)
 
 static MagickBooleanType JPEGWarningHandler(j_common_ptr jpeg_info,int level)
 {
+#define JPEGExcessiveWarnings  1000
+
   char
     message[JMSG_LENGTH_MAX];
 
@@ -349,11 +352,10 @@ static MagickBooleanType JPEGWarningHandler(j_common_ptr jpeg_info,int level)
         Process warning message.
       */
       (jpeg_info->err->format_message)(jpeg_info,message);
-      if ((jpeg_info->err->num_warnings == 0) ||
-          (jpeg_info->err->trace_level >= 3))
-        ThrowBinaryException(CorruptImageWarning,(char *) message,
-          image->filename);
-      jpeg_info->err->num_warnings++;
+      if (jpeg_info->err->num_warnings++ > JPEGExcessiveWarnings)
+        JPEGErrorHandler(jpeg_info);
+      ThrowBinaryException(CorruptImageWarning,(char *) message,
+        image->filename);
     }
   else
     if ((image->debug != MagickFalse) &&
@@ -1061,14 +1063,6 @@ static Image *ReadJPEGImage(const ImageInfo *image_info,
       (image_info->colorspace == Rec601YCbCrColorspace) ||
       (image_info->colorspace == Rec709YCbCrColorspace))
     jpeg_info.out_color_space=JCS_YCbCr;
-  if (IsITUFaxImage(image) != MagickFalse)
-    {
-      image->colorspace=LabColorspace;
-      jpeg_info.out_color_space=JCS_YCbCr;
-    }
-  else
-    if (jpeg_info.out_color_space == JCS_CMYK)
-      image->colorspace=CMYKColorspace;
   /*
     Set image resolution.
   */
@@ -1151,12 +1145,7 @@ static Image *ReadJPEGImage(const ImageInfo *image_info,
       jpeg_info.desired_number_of_colors=(int) StringToUnsignedLong(option);
     }
   option=GetImageOption(image_info,"jpeg:block-smoothing");
-  if (option != (const char *) NULL)
-    {
-      jpeg_info.do_block_smoothing=MagickFalse;
-      if (IsMagickTrue(option) != MagickFalse)
-        jpeg_info.do_block_smoothing=MagickTrue;
-    }
+  jpeg_info.do_block_smoothing=IsStringTrue(option);
   jpeg_info.dct_method=JDCT_FLOAT;
   option=GetImageOption(image_info,"jpeg:dct-method");
   if (option != (const char *) NULL)
@@ -1189,20 +1178,40 @@ static Image *ReadJPEGImage(const ImageInfo *image_info,
       }
     }
   option=GetImageOption(image_info,"jpeg:fancy-upsampling");
-  if (option != (const char *) NULL)
-    {
-      jpeg_info.do_fancy_upsampling=MagickFalse;
-      if (IsMagickTrue(option) != MagickFalse)
-        jpeg_info.do_fancy_upsampling=MagickTrue;
-    }
+  jpeg_info.do_fancy_upsampling=IsStringTrue(option);
   (void) jpeg_start_decompress(&jpeg_info);
   image->columns=jpeg_info.output_width;
   image->rows=jpeg_info.output_height;
   image->depth=(size_t) jpeg_info.data_precision;
-  if (jpeg_info.out_color_space == JCS_YCbCr)
-    image->colorspace=YCbCrColorspace;
-  if (jpeg_info.out_color_space == JCS_CMYK)
-    image->colorspace=CMYKColorspace;
+  switch (jpeg_info.out_color_space)
+  {
+    case JCS_RGB:
+    default:
+    {
+      SetImageColorspace(image,sRGBColorspace,exception);
+      break;
+    }
+    case JCS_GRAYSCALE:
+    {
+      SetImageColorspace(image,GRAYColorspace,exception);
+      break;
+    }
+    case JCS_YCbCr:
+    {
+      SetImageColorspace(image,YCbCrColorspace,exception);
+      break;
+    }
+    case JCS_CMYK:
+    {
+      SetImageColorspace(image,CMYKColorspace,exception);
+      break;
+    }
+  }
+  if (IsITUFaxImage(image) != MagickFalse)
+    {
+      SetImageColorspace(image,LabColorspace,exception);
+      jpeg_info.out_color_space=JCS_YCbCr;
+    }
   option=GetImageOption(image_info,"jpeg:colors");
   if (option != (const char *) NULL)
     if (AcquireImageColormap(image,StringToUnsignedLong(option),exception)
@@ -1715,8 +1724,8 @@ static QuantizationTable *GetQuantizationTable(const char *filename,
       xml=DestroyString(xml);
       return(table);
     }
-  table->divisor=(unsigned int) StringToLong(attribute);
-  if (table->divisor < 1)
+  table->divisor=InterpretLocaleValue(attribute,(char **) NULL);
+  if (table->divisor == 0.0)
     {
       (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
         "XmlInvalidAttribute", "<levels divisor>, table \"%s\"",slot);
@@ -1738,25 +1747,22 @@ static QuantizationTable *GetQuantizationTable(const char *filename,
   length=(size_t) table->width*table->height;
   if (length < 64)
     length=64;
-  table->levels=(unsigned int *) AcquireQuantumMemory(length*
+  table->levels=(unsigned int *) AcquireQuantumMemory(length,
     sizeof(*table->levels));
   if (table->levels == (unsigned int *) NULL)
     ThrowFatalException(ResourceLimitFatalError,
       "UnableToAcquireQuantizationTable");
   for (i=0; i < (ssize_t) (table->width*table->height); i++)
   {
-    table->levels[i]=(unsigned int) strtol(content,&p,10);
-    if (table->divisor != 1)
-      table->levels[i]/=table->divisor;
+    table->levels[i]=(unsigned int) (InterpretLocaleValue(content,&p)/
+      table->divisor+0.5);
     while (isspace((int) ((unsigned char) *p)) != 0)
       p++;
     if (*p == ',')
       p++;
     content=p;
   }
-  for (j=i; i < 64; i++)
-    table->levels[j]=table->levels[j-1];
-  value=(double) strtol(content,&p,10);
+  value=InterpretLocaleValue(content,&p);
   (void) value;
   if (p != content)
     {
@@ -1767,6 +1773,8 @@ static QuantizationTable *GetQuantizationTable(const char *filename,
      xml=DestroyString(xml);
      return(table);
    }
+  for (j=i; j < 64; j++)
+    table->levels[j]=table->levels[j-1];
   quantization_tables=DestroyXMLTree(quantization_tables);
   xml=DestroyString(xml);
   return(table);
@@ -2097,7 +2105,7 @@ static MagickBooleanType WriteJPEGImage(const ImageInfo *image_info,
     }
     default:
     {
-      if (IsRGBColorspace(image->colorspace) == MagickFalse)
+      if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
         (void) TransformImageColorspace(image,sRGBColorspace,exception);
       break;
     }
@@ -2165,11 +2173,7 @@ static MagickBooleanType WriteJPEGImage(const ImageInfo *image_info,
     }
   option=GetImageOption(image_info,"jpeg:optimize-coding");
   if (option != (const char *) NULL)
-    {
-      jpeg_info.optimize_coding=MagickFalse;
-      if (IsMagickTrue(option) != MagickFalse)
-        jpeg_info.optimize_coding=MagickTrue;
-    }
+    jpeg_info.optimize_coding=IsStringTrue(option);
   else
     {
       MagickSizeType
@@ -2183,9 +2187,8 @@ static MagickBooleanType WriteJPEGImage(const ImageInfo *image_info,
             Perform optimization only if available memory resources permit it.
           */
           status=AcquireMagickResource(MemoryResource,length);
-          if (status != MagickFalse)
-            jpeg_info.optimize_coding=MagickTrue;
           RelinquishMagickResource(MemoryResource,length);
+          jpeg_info.optimize_coding=status;
         }
     }
 #if (JPEG_LIB_VERSION >= 61) && defined(C_PROGRESSIVE_SUPPORTED)
@@ -2291,8 +2294,34 @@ static MagickBooleanType WriteJPEGImage(const ImageInfo *image_info,
 #endif
     }
   jpeg_set_quality(&jpeg_info,quality,MagickTrue);
+#if (JPEG_LIB_VERSION >= 70)
+  option=GetImageOption(image_info,"quality");
+  if (option != (const char *) NULL)
+    {
+      GeometryInfo
+        geometry_info;
+
+      int
+        flags;
+
+      /*
+        Set quality scaling for luminance and chrominance separately.
+      */
+      flags=ParseGeometry(option,&geometry_info);
+      if (((flags & RhoValue) != 0) && ((flags & SigmaValue) != 0))
+        {
+          jpeg_info.q_scale_factor[0]=jpeg_quality_scaling((int)
+            (geometry_info.rho+0.5));
+          jpeg_info.q_scale_factor[1]=jpeg_quality_scaling((int)
+            (geometry_info.sigma+0.5));
+          jpeg_default_qtables(&jpeg_info,MagickTrue);
+        }
+    }
+#endif
   sampling_factor=(const char *) NULL;
   value=GetImageProperty(image,"jpeg:sampling-factor",exception);
+  if (value == (char *) NULL)
+    value=GetImageOption(image_info,"jpeg:sampling-factor");
   if (value != (char *) NULL)
     {
       sampling_factor=value;