changeset 17155:73a3c1580974

Correctly identify PNG image types (bug #32986, bug #36820 and bug #37689) * __magick_read_.cc (read_images): check original color type from PNG image attribute because GraphicsMagick changes it for optimization.
author Carnë Draug <carandraug@octave.org>
date Fri, 02 Aug 2013 19:05:42 +0100
parents fa14aa77b514
children e7723410ec32
files libinterp/dldfcn/__magick_read__.cc
diffstat 1 files changed, 38 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/dldfcn/__magick_read__.cc
+++ b/libinterp/dldfcn/__magick_read__.cc
@@ -223,6 +223,8 @@
   // using quantumOperator for the cases where we will be returning floating
   // point and want things in the range [0 1]. This is the same reason why
   // the divisor is of type double.
+  // uint64_t is used in expression because default 32-bit value overflows
+  // when depth() is 32.
   // TODO in the next release of GraphicsMagick, MaxRGB should be replaced
   //      with QuantumRange since MaxRGB is already deprecated in ImageMagick.
   const double divisor   = imvec[0].depth () == 32 ?
@@ -242,6 +244,42 @@
       type = Magick::GrayscaleMatteType;
     }
 
+  // FIXME: ImageType is the type being used to represent the image in memory
+  // by GM. The real type may be different (see among others bug #36820). For
+  // example, a png file where all channels are equal may report being
+  // grayscale or even bilevel. But we must always return the real image in
+  // file. In some cases, the original image attributes are stored in the
+  // attributes but this is undocumented. This should be fixed in GM so that
+  // a method such as original_type returns an actual Magick::ImageType
+  if (imvec[0].magick () == "PNG")
+    {
+      // These values come from libpng, not GM:
+      //      Grayscale         = 0
+      //      Palette           = 2 + 1
+      //      RGB               = 2
+      //      RGB + Alpha       = 2 + 4
+      //      Grayscale + Alpha = 4
+      // We won't bother with case 3 (palette) since those should be
+      // read by the function to read indexed images
+      const std::string type_str = imvec[0].attribute ("PNG:IHDR.color-type-orig");
+      if (type_str == "0")
+        {
+          type = Magick::GrayscaleType;
+        }
+      else if (type_str == "2")
+        {
+          type = Magick::TrueColorType;
+        }
+      else if (type_str == "6")
+        {
+          type = Magick::TrueColorMatteType;
+        }
+      else if (type_str == "4")
+        {
+          type = Magick::GrayscaleMatteType;
+        }
+    }
+
   // If the alpha channel was not requested, treat images as if
   // it doesn't exist.
   if (nargout < 3)