changeset 20373:a7770c66cb3d

Saturated red channel on RGB image, makes imread() return logical (bug #41584) * libinterp/dldfcn/__magick_read__.cc (get_depth): this function tries to second guess GM when reporting the actual bitdepth of an image in the file (see comments for full discussion). We assumed we could check only red from RGB but if the channel was saturated, it would return depth of 1, so we really need to check all 3 channels. Unfortunately, 3 saturated channels may still lead to images incorrectly read as logical. * scripts/image/imread.m: add test for this bug.
author Carnë Draug <carandraug@octave.org>
date Fri, 10 Jul 2015 16:46:24 +0100
parents 8e056730f27c
children 3904d83e47d1
files libinterp/dldfcn/__magick_read__.cc scripts/image/imread.m
diffstat 2 files changed, 20 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/dldfcn/__magick_read__.cc	Sun Jul 12 19:57:48 2015 -0700
+++ b/libinterp/dldfcn/__magick_read__.cc	Fri Jul 10 16:46:24 2015 +0100
@@ -115,15 +115,20 @@
 //  all to 1. So we will guess that if all channels have depth of 1,
 //  then we must have a binary image.
 //  Note that we can't use AllChannels it doesn't work for this.
-//  Instead of checking all of the individual channels, we check one
-//  from RGB, CMYK, grayscale, and transparency.
+//  We also can't check only one from RGB, one from CMYK, and grayscale
+// and transparency, we really need to check all of the channels (bug #41584).
 static octave_idx_type
 get_depth (Magick::Image& img)
 {
   octave_idx_type depth = img.depth ();
   if (depth == 8
       && img.channelDepth (Magick::RedChannel)     == 1
+      && img.channelDepth (Magick::GreenChannel)   == 1
+      && img.channelDepth (Magick::BlueChannel)    == 1
       && img.channelDepth (Magick::CyanChannel)    == 1
+      && img.channelDepth (Magick::MagentaChannel) == 1
+      && img.channelDepth (Magick::YellowChannel)  == 1
+      && img.channelDepth (Magick::BlackChannel)   == 1
       && img.channelDepth (Magick::OpacityChannel) == 1
       && img.channelDepth (Magick::GrayChannel)    == 1)
     depth = 1;
--- a/scripts/image/imread.m	Sun Jul 12 19:57:48 2015 -0700
+++ b/scripts/image/imread.m	Fri Jul 10 16:46:24 2015 +0100
@@ -108,7 +108,6 @@
 
 endfunction
 
-
 %!testif HAVE_MAGICK
 %! vpng = [ ...
 %!  137,  80,  78,  71,  13,  10,  26,  10,   0,   0, ...
@@ -140,8 +139,8 @@
 %! assert (A(:,:,2), uint8 ([0, 255, 0; 255,  28, 255; 0, 255, 0]));
 %! assert (A(:,:,3), uint8 ([0, 255, 0; 255,  36, 255; 0, 255, 0]));
 
-%!function [r, cmap, a] = write_and_read (w, varargin)
-%!  filename = [tempname() ".tif"];
+%!function [r, cmap, a] = write_and_read (w, f_ext, varargin)
+%!  filename = [tempname() "." f_ext];
 %!  unwind_protect
 %!    imwrite (w, filename);
 %!    [r, cmap, a] = imread (filename, varargin{:});
@@ -153,9 +152,9 @@
 ## test PixelRegion option
 %!testif HAVE_MAGICK
 %! w = randi (255, 100, 100, "uint8");
-%! [r, cmap, a] = write_and_read (w, "PixelRegion", {[50 70] [20 40]});
+%! [r, cmap, a] = write_and_read (w, "tif", "PixelRegion", {[50 70] [20 40]});
 %! assert (r, w(50:70, 20:40))
-%! [r, cmap, a] = write_and_read (w, "PixelRegion", {[50 2 70] [20 3 40]});
+%! [r, cmap, a] = write_and_read (w, "tif", "PixelRegion", {[50 2 70] [20 3 40]});
 %! assert (r, w(50:2:70, 20:3:40))
 
 ## If a file does not exist, it's the job of imread to check the file
@@ -203,3 +202,12 @@
 %!   imformats (def_fmt);
 %! end_unwind_protect
 
+## Test for bug #41584 (some GM coders report saturated channels as binary)
+%!testif HAVE_MAGICK
+%! im = zeros ([16 16 3], "uint8");
+%! im(:,:,1) = 255;
+%! im(:,:,3) = repmat (0:16:255, [16 1]);
+%! [r, cmap, a] = write_and_read (im, "png");
+%! assert (class (r), "uint8");
+%! assert (isempty (cmap))
+%! assert (isempty (a))