]> granicus.if.org Git - imagemagick/blobdiff - coders/png.c
(no commit message)
[imagemagick] / coders / png.c
index 4b19548d34aeab37705df0367877f6aadc8aa4b6..8ab45502459b2cfba3433e37f4e5e782d8260421 100644 (file)
@@ -1953,6 +1953,9 @@ static int read_vpag_chunk_callback(png_struct *ping, png_unknown_chunkp chunk)
      Note that libpng has already taken care of the CRC handling.
   */
 
+  LogMagickEvent(CoderEvent,GetMagickModule(),
+     " read_vpag_chunk: found %c%c%c%c chunk",
+       chunk->name[0],chunk->name[1],chunk->name[2],chunk->name[3]);
 
   if (chunk->name[0] != 118 || chunk->name[1] != 112 ||
       chunk->name[2] != 65 ||chunk-> name[3] != 103)
@@ -2025,6 +2028,13 @@ static Image *ReadOnePNGImage(MngInfo *mng_info,
   Image
     *image;
 
+  char
+    im_vers[32],
+    libpng_runv[32],
+    libpng_vers[32],
+    zlib_runv[32],
+    zlib_vers[32];
+
   int
     intent, /* "PNG Rendering intent", which is ICC intent + 1 */
     num_raw_profiles,
@@ -2051,6 +2061,7 @@ static Image *ReadOnePNGImage(MngInfo *mng_info,
     ping_found_gAMA,
     ping_found_iCCP,
     ping_found_sRGB,
+    ping_found_sRGB_cHRM,
     status;
 
   PixelInfo
@@ -2130,6 +2141,49 @@ static Image *ReadOnePNGImage(MngInfo *mng_info,
   logging=LogMagickEvent(CoderEvent,GetMagickModule(),
     "  Enter ReadOnePNGImage()");
 
+  /* Define these outside of the following "if logging()" block so they will
+   * show in debuggers.
+   */
+  *im_vers='\0';
+  (void) ConcatenateMagickString(im_vers,
+         MagickLibVersionText,32);
+  (void) ConcatenateMagickString(im_vers,
+         MagickLibAddendum,32);
+
+  *libpng_vers='\0';
+  (void) ConcatenateMagickString(libpng_vers,
+         PNG_LIBPNG_VER_STRING,32);
+  *libpng_runv='\0';
+  (void) ConcatenateMagickString(libpng_runv,
+         png_get_libpng_ver(NULL),32);
+
+  *zlib_vers='\0';
+  (void) ConcatenateMagickString(zlib_vers,
+         ZLIB_VERSION,32);
+  *zlib_runv='\0';
+  (void) ConcatenateMagickString(zlib_runv,
+         zlib_version,32);
+
+  if (logging)
+    {
+       LogMagickEvent(CoderEvent,GetMagickModule(),"    IM version     = %s",
+           im_vers);
+       LogMagickEvent(CoderEvent,GetMagickModule(),"    Libpng version = %s",
+           libpng_vers);
+       if (LocaleCompare(libpng_vers,libpng_runv) != 0)
+       {
+       LogMagickEvent(CoderEvent,GetMagickModule(),"      running with   %s",
+           libpng_runv);
+       }
+       LogMagickEvent(CoderEvent,GetMagickModule(),"    Zlib version   = %s",
+           zlib_vers);
+       if (LocaleCompare(zlib_vers,zlib_runv) != 0)
+       {
+       LogMagickEvent(CoderEvent,GetMagickModule(),"      running with   %s",
+           zlib_runv);
+       }
+    }
+
 #if (PNG_LIBPNG_VER < 10200)
   if (image_info->verbose)
     printf("Your PNG library (libpng-%s) is rather old.\n",
@@ -2154,13 +2208,19 @@ static Image *ReadOnePNGImage(MngInfo *mng_info,
   if (logging != MagickFalse)
   {
     (void)LogMagickEvent(CoderEvent,GetMagickModule(),
-      "  image->alpha_trait=%d",(int) image->alpha_trait);
+      "    Before reading:");
 
     (void)LogMagickEvent(CoderEvent,GetMagickModule(),
-      "  image->rendering_intent=%d",(int) image->rendering_intent);
+      "      image->alpha_trait=%d",(int) image->alpha_trait);
 
     (void)LogMagickEvent(CoderEvent,GetMagickModule(),
-      "  image->colorspace=%d",(int) image->colorspace);
+      "      image->rendering_intent=%d",(int) image->rendering_intent);
+
+    (void)LogMagickEvent(CoderEvent,GetMagickModule(),
+      "      image->colorspace=%d",(int) image->colorspace);
+
+    (void)LogMagickEvent(CoderEvent,GetMagickModule(),
+      "      image->gamma=%f", image->gamma);
   }
   intent=Magick_RenderingIntent_to_PNG_RenderingIntent(image->rendering_intent);
 
@@ -2281,7 +2341,11 @@ static Image *ReadOnePNGImage(MngInfo *mng_info,
 
 #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
   /* Ignore unused chunks and all unknown chunks except for vpAg */
+#if PNG_LIBPNG_VER < 10700 /* Avoid libpng16 warning */
+  png_set_keep_unknown_chunks(ping, 2, NULL, 0);
+#else
   png_set_keep_unknown_chunks(ping, 1, NULL, 0);
+#endif
   png_set_keep_unknown_chunks(ping, 2, mng_vpAg, 1);
   png_set_keep_unknown_chunks(ping, 1, unused_chunks,
      (int)sizeof(unused_chunks)/5);
@@ -2525,20 +2589,45 @@ static Image *ReadOnePNGImage(MngInfo *mng_info,
         &image->chromaticity.blue_primary.x,
         &image->chromaticity.blue_primary.y);
 
+       if (image->chromaticity.red_primary.x>0.6399f &&
+           image->chromaticity.red_primary.x<0.6401f &&
+           image->chromaticity.red_primary.y>0.3299f &&
+           image->chromaticity.red_primary.y<0.3301f &&
+           image->chromaticity.green_primary.x>0.2999f &&
+           image->chromaticity.green_primary.x<0.3001f &&
+           image->chromaticity.green_primary.y>0.5999f &&
+           image->chromaticity.green_primary.y<0.6001f &&
+           image->chromaticity.blue_primary.x>0.1499f &&
+           image->chromaticity.blue_primary.x<0.1501f &&
+           image->chromaticity.blue_primary.y>0.0599f &&
+           image->chromaticity.blue_primary.y<0.0601f &&
+           image->chromaticity.white_point.x>0.3126f &&
+           image->chromaticity.white_point.x<0.3128f &&
+           image->chromaticity.white_point.y>0.3289f &&
+           image->chromaticity.white_point.y<0.3291f)
+          ping_found_sRGB_cHRM=MagickTrue;
+
       ping_found_cHRM=MagickTrue;
     }
 
   if (image->rendering_intent != UndefinedIntent)
     {
-      if (ping_found_sRGB != MagickTrue)
+      if (ping_found_sRGB != MagickTrue &&
+          (ping_found_gAMA != MagickTrue ||
+          (image->gamma > .45 && image->gamma < .46)) &&
+          (ping_found_cHRM != MagickTrue ||
+          ping_found_sRGB_cHRM == MagickTrue) &&
+          ping_found_iCCP != MagickTrue)
       {
          png_set_sRGB(ping,ping_info,
             Magick_RenderingIntent_to_PNG_RenderingIntent
             (image->rendering_intent));
-         png_set_gAMA(ping,ping_info,1.000f/2.200f);
+         if (ping_found_gAMA != MagickTrue)
+            png_set_gAMA(ping,ping_info,1.000f/2.200f);
          file_gamma=1.000f/2.200f;
          ping_found_sRGB=MagickTrue;
-         ping_found_cHRM=MagickTrue;
+         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+           "    Setting sRGB and gAMA as if in input");
       }
     }
 
@@ -2831,8 +2920,7 @@ static Image *ReadOnePNGImage(MngInfo *mng_info,
       ((int) ping_color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
     {
       if ((!png_get_valid(ping,ping_info,PNG_INFO_gAMA) ||
-          image->gamma == 1.0) &&
-          ping_found_cHRM != MagickTrue && ping_found_sRGB != MagickTrue)
+          image->gamma == 1.0) && ping_found_sRGB != MagickTrue)
         {
           /* Set image->gamma to 1.0, image->rendering_intent to Undefined,
            * image->colorspace to GRAY, and reset image->chromaticity.
@@ -3867,7 +3955,23 @@ static Image *ReadPNGImage(const ImageInfo *image_info,ExceptionInfo *exception)
     }
 
   if ((IssRGBColorspace(image->colorspace) != MagickFalse) &&
-      ((image->gamma < .45) || (image->gamma > .46)))
+      ((image->gamma < .45) || (image->gamma > .46)) &&
+           !(image->chromaticity.red_primary.x>0.6399f &&
+           image->chromaticity.red_primary.x<0.6401f &&
+           image->chromaticity.red_primary.y>0.3299f &&
+           image->chromaticity.red_primary.y<0.3301f &&
+           image->chromaticity.green_primary.x>0.2999f &&
+           image->chromaticity.green_primary.x<0.3001f &&
+           image->chromaticity.green_primary.y>0.5999f &&
+           image->chromaticity.green_primary.y<0.6001f &&
+           image->chromaticity.blue_primary.x>0.1499f &&
+           image->chromaticity.blue_primary.x<0.1501f &&
+           image->chromaticity.blue_primary.y>0.0599f &&
+           image->chromaticity.blue_primary.y<0.0601f &&
+           image->chromaticity.white_point.x>0.3126f &&
+           image->chromaticity.white_point.x<0.3128f &&
+           image->chromaticity.white_point.y>0.3289f &&
+           image->chromaticity.white_point.y<0.3291f))
     SetImageColorspace(image,RGBColorspace,exception);
 
   if (logging != MagickFalse)
@@ -7737,6 +7841,13 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
   unsigned char
     *volatile ping_pixels;
 
+  char
+    im_vers[32],
+    libpng_runv[32],
+    libpng_vers[32],
+    zlib_runv[32],
+    zlib_vers[32];
+
   volatile int
     image_colors,
     ping_bit_depth,
@@ -7775,6 +7886,49 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
   if (image_info == (ImageInfo *) NULL)
      ThrowWriterException(ResourceLimitError, "MemoryAllocationFailed");
 
+  /* Define these outside of the following "if logging()" block so they will
+   * show in debuggers.
+   */
+  *im_vers='\0';
+  (void) ConcatenateMagickString(im_vers,
+         MagickLibVersionText,MaxTextExtent);
+  (void) ConcatenateMagickString(im_vers,
+         MagickLibAddendum,MaxTextExtent);
+
+  *libpng_vers='\0';
+  (void) ConcatenateMagickString(libpng_vers,
+         PNG_LIBPNG_VER_STRING,32);
+  *libpng_runv='\0';
+  (void) ConcatenateMagickString(libpng_runv,
+         png_get_libpng_ver(NULL),32);
+
+  *zlib_vers='\0';
+  (void) ConcatenateMagickString(zlib_vers,
+         ZLIB_VERSION,32);
+  *zlib_runv='\0';
+  (void) ConcatenateMagickString(zlib_runv,
+         zlib_version,32);
+
+  if (logging)
+    {
+       LogMagickEvent(CoderEvent,GetMagickModule(),"    IM version     = %s",
+           im_vers);
+       LogMagickEvent(CoderEvent,GetMagickModule(),"    Libpng version = %s",
+           libpng_vers);
+       if (LocaleCompare(libpng_vers,libpng_runv) != 0)
+       {
+       LogMagickEvent(CoderEvent,GetMagickModule(),"      running with   %s",
+           libpng_runv);
+       }
+       LogMagickEvent(CoderEvent,GetMagickModule(),"    Zlib version   = %s",
+           zlib_vers);
+       if (LocaleCompare(zlib_vers,zlib_runv) != 0)
+       {
+       LogMagickEvent(CoderEvent,GetMagickModule(),"      running with   %s",
+           zlib_runv);
+       }
+    }
+
   /* Initialize some stuff */
   ping_bit_depth=0,
   ping_color_type=0,
@@ -9789,16 +9943,7 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
             */
             ping_color_type=(png_byte) PNG_COLOR_TYPE_PALETTE;
 
-            if (mng_info->have_write_global_plte && matte == MagickFalse)
-              {
-                png_set_PLTE(ping,ping_info,NULL,0);
-
-                if (logging != MagickFalse)
-                  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                    "  Setting up empty PLTE chunk");
-              }
-
-            else
+            if (!(mng_info->have_write_global_plte && matte == MagickFalse))
               {
                 for (i=0; i < (ssize_t) number_colors; i++)
                 {
@@ -10151,9 +10296,128 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
     png_set_compression_strategy(ping,
        mng_info->write_png_compression_strategy-1);
 
+  ping_interlace_method=image_info->interlace != NoInterlace;
+
+  if (mng_info->write_mng)
+    png_set_sig_bytes(ping,8);
+
+  /* Bail out if cannot meet defined png:bit-depth or png:color-type */
+
+  if (mng_info->write_png_colortype != 0)
+    {
+     if (mng_info->write_png_colortype-1 == PNG_COLOR_TYPE_GRAY)
+       if (ping_have_color != MagickFalse)
+         {
+           ping_color_type = PNG_COLOR_TYPE_RGB;
+
+           if (ping_bit_depth < 8)
+             ping_bit_depth=8;
+         }
+
+     if (mng_info->write_png_colortype-1 == PNG_COLOR_TYPE_GRAY_ALPHA)
+       if (ping_have_color != MagickFalse)
+         ping_color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+    }
+
+  if (ping_need_colortype_warning != MagickFalse ||
+     ((mng_info->write_png_depth &&
+     (int) mng_info->write_png_depth != ping_bit_depth) ||
+     (mng_info->write_png_colortype &&
+     ((int) mng_info->write_png_colortype-1 != ping_color_type &&
+      mng_info->write_png_colortype != 7 &&
+      !(mng_info->write_png_colortype == 5 && ping_color_type == 0)))))
+    {
+      if (logging != MagickFalse)
+        {
+          if (ping_need_colortype_warning != MagickFalse)
+            {
+              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                 "  Image has transparency but tRNS chunk was excluded");
+            }
+
+          if (mng_info->write_png_depth)
+            {
+              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                  "  Defined png:bit-depth=%u, Computed depth=%u",
+                  mng_info->write_png_depth,
+                  ping_bit_depth);
+            }
+
+          if (mng_info->write_png_colortype)
+            {
+              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                  "  Defined png:color-type=%u, Computed color type=%u",
+                  mng_info->write_png_colortype-1,
+                  ping_color_type);
+            }
+        }
+
+      png_warning(ping,
+        "Cannot write image with defined png:bit-depth or png:color-type.");
+    }
+
+  if (image_matte != MagickFalse && image->alpha_trait != BlendPixelTrait)
+    {
+      /* Add an opaque matte channel */
+      image->alpha_trait = BlendPixelTrait;
+      (void) SetImageAlpha(image,OpaqueAlpha,exception);
+
+      if (logging != MagickFalse)
+        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+          "  Added an opaque matte channel");
+    }
+
+  if (number_transparent != 0 || number_semitransparent != 0)
+    {
+      if (ping_color_type < 4)
+        {
+           ping_have_tRNS=MagickTrue;
+           if (logging != MagickFalse)
+             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+               "  Setting ping_have_tRNS=MagickTrue.");
+        }
+    }
+
+  if (logging != MagickFalse)
+    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+      "  Writing PNG header chunks");
+
+  png_set_IHDR(ping,ping_info,ping_width,ping_height,
+               ping_bit_depth,ping_color_type,
+               ping_interlace_method,ping_compression_method,
+               ping_filter_method);
+
+  if (ping_color_type == 3 && ping_have_PLTE != MagickFalse)
+    {
+      png_set_PLTE(ping,ping_info,palette,number_colors);
+
+      if (logging != MagickFalse)
+        {
+          for (i=0; i< (ssize_t) number_colors; i++)
+          {
+            if (i < ping_num_trans)
+              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                "     PLTE[%d] = (%d,%d,%d), tRNS[%d] = (%d)",
+                      (int) i,
+                      (int) palette[i].red,
+                      (int) palette[i].green,
+                      (int) palette[i].blue,
+                      (int) i,
+                      (int) ping_trans_alpha[i]);
+             else
+              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                "     PLTE[%d] = (%d,%d,%d)",
+                      (int) i,
+                      (int) palette[i].red,
+                      (int) palette[i].green,
+                      (int) palette[i].blue);
+           }
+         }
+    }
+
   /* Only write the iCCP chunk if we are not writing the sRGB chunk. */
   if (ping_exclude_sRGB != MagickFalse ||
-     (image->rendering_intent == UndefinedIntent))
+     (!png_get_valid(ping,ping_info,PNG_INFO_sRGB)))
   {
     if ((ping_exclude_tEXt == MagickFalse ||
        ping_exclude_zTXt == MagickFalse) &&
@@ -10205,7 +10469,7 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
 
 #if defined(PNG_WRITE_sRGB_SUPPORTED)
   if ((mng_info->have_write_global_srgb == 0) &&
-      (image->rendering_intent != UndefinedIntent))
+      (png_get_valid(ping,ping_info,PNG_INFO_sRGB)))
     {
       if (ping_exclude_sRGB == MagickFalse)
         {
@@ -10273,125 +10537,6 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
         }
     }
 
-  ping_interlace_method=image_info->interlace != NoInterlace;
-
-  if (mng_info->write_mng)
-    png_set_sig_bytes(ping,8);
-
-  /* Bail out if cannot meet defined png:bit-depth or png:color-type */
-
-  if (mng_info->write_png_colortype != 0)
-    {
-     if (mng_info->write_png_colortype-1 == PNG_COLOR_TYPE_GRAY)
-       if (ping_have_color != MagickFalse)
-         {
-           ping_color_type = PNG_COLOR_TYPE_RGB;
-
-           if (ping_bit_depth < 8)
-             ping_bit_depth=8;
-         }
-
-     if (mng_info->write_png_colortype-1 == PNG_COLOR_TYPE_GRAY_ALPHA)
-       if (ping_have_color != MagickFalse)
-         ping_color_type = PNG_COLOR_TYPE_RGB_ALPHA;
-    }
-
-  if (ping_need_colortype_warning != MagickFalse ||
-     ((mng_info->write_png_depth &&
-     (int) mng_info->write_png_depth != ping_bit_depth) ||
-     (mng_info->write_png_colortype &&
-     ((int) mng_info->write_png_colortype-1 != ping_color_type &&
-      mng_info->write_png_colortype != 7 &&
-      !(mng_info->write_png_colortype == 5 && ping_color_type == 0)))))
-    {
-      if (logging != MagickFalse)
-        {
-          if (ping_need_colortype_warning != MagickFalse)
-            {
-              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                 "  Image has transparency but tRNS chunk was excluded");
-            }
-
-          if (mng_info->write_png_depth)
-            {
-              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                  "  Defined png:bit-depth=%u, Computed depth=%u",
-                  mng_info->write_png_depth,
-                  ping_bit_depth);
-            }
-
-          if (mng_info->write_png_colortype)
-            {
-              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                  "  Defined png:color-type=%u, Computed color type=%u",
-                  mng_info->write_png_colortype-1,
-                  ping_color_type);
-            }
-        }
-
-      png_warning(ping,
-        "Cannot write image with defined png:bit-depth or png:color-type.");
-    }
-
-  if (image_matte != MagickFalse && image->alpha_trait != BlendPixelTrait)
-    {
-      /* Add an opaque matte channel */
-      image->alpha_trait = BlendPixelTrait;
-      (void) SetImageAlpha(image,OpaqueAlpha,exception);
-
-      if (logging != MagickFalse)
-        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-          "  Added an opaque matte channel");
-    }
-
-  if (number_transparent != 0 || number_semitransparent != 0)
-    {
-      if (ping_color_type < 4)
-        {
-           ping_have_tRNS=MagickTrue;
-           if (logging != MagickFalse)
-             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-               "  Setting ping_have_tRNS=MagickTrue.");
-        }
-    }
-
-  if (logging != MagickFalse)
-    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-      "  Writing PNG header chunks");
-
-  png_set_IHDR(ping,ping_info,ping_width,ping_height,
-               ping_bit_depth,ping_color_type,
-               ping_interlace_method,ping_compression_method,
-               ping_filter_method);
-
-  if (ping_color_type == 3 && ping_have_PLTE != MagickFalse)
-    {
-      png_set_PLTE(ping,ping_info,palette,number_colors);
-
-      if (logging != MagickFalse)
-        {
-          for (i=0; i< (ssize_t) number_colors; i++)
-          {
-            if (i < ping_num_trans)
-              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                "     PLTE[%d] = (%d,%d,%d), tRNS[%d] = (%d)",
-                      (int) i,
-                      (int) palette[i].red,
-                      (int) palette[i].green,
-                      (int) palette[i].blue,
-                      (int) i,
-                      (int) ping_trans_alpha[i]);
-             else
-              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                "     PLTE[%d] = (%d,%d,%d)",
-                      (int) i,
-                      (int) palette[i].red,
-                      (int) palette[i].green,
-                      (int) palette[i].blue);
-           }
-         }
-    }
-
   if (ping_exclude_bKGD == MagickFalse)
     {
       if (ping_have_bKGD != MagickFalse)