# HG changeset patch # User Rik # Date 1395072632 25200 # Node ID 875f4510d6dc85138943f1c89db6a14f3791e5ba # Parent 3a1a4d587c4e4f117c3d22c72cd66e41f672d714 Accept indexed images with color values below the first colormap entry (bug #41851). Change made for Matlab compatibility. * ind2gray.m: Change %!tests to accept an indexed image with colors below the first entry in the colormap. * ind2rgb.m: Change %!tests to accept an indexed image with colors below the first entry in the colormap. * ind2x.m: Change input validation to accept all floating point images with integer indices. Issue a warning if any of the indices are below the first entry in the colormap. Map all color indices below the first entry to the first color in the colormap. diff -r 3a1a4d587c4e -r 875f4510d6dc scripts/image/ind2gray.m --- a/scripts/image/ind2gray.m Sun Mar 16 11:44:11 2014 -0700 +++ b/scripts/image/ind2gray.m Mon Mar 17 09:10:32 2014 -0700 @@ -69,18 +69,19 @@ %!shared i2g %! i2g = ind2gray (1:100, gray (100)); -%!assert (i2g, 0:1/99:1, eps); -%!assert (gray2ind (i2g, 100), uint8 (0:99)); +%! +%!assert (i2g, 0:1/99:1, eps) +%!assert (gray2ind (i2g, 100), uint8 (0:99)) %% Test input validation %!error ind2gray () %!error ind2gray (1) %!error ind2gray (1,2,3) -%!error ind2gray ({1}, jet (64)) +%!error ind2gray (ones (3,3,3), jet (64)) %!error ind2gray (1+i, jet (64)) %!error ind2gray (sparse (1), jet (64)) -%!error ind2gray (0, jet (64)) %!error ind2gray (1.1, jet (64)) +%!error ind2gray ({1}, jet (64)) %!error ind2gray (1, {1}) %!error ind2gray (1, 1+i) %!error ind2gray (1, ones (2,2,2)) @@ -88,3 +89,7 @@ %!error ind2gray (1, [-1]) %!error ind2gray (1, [2]) +%!warning ind2gray ([0 1 2], gray (5)); +%!warning ind2gray ([1 2 6], gray (5)); +%!warning ind2gray (uint8 ([1 2 5]), gray (5)); + diff -r 3a1a4d587c4e -r 875f4510d6dc scripts/image/ind2rgb.m --- a/scripts/image/ind2rgb.m Sun Mar 16 11:44:11 2014 -0700 +++ b/scripts/image/ind2rgb.m Mon Mar 17 09:10:32 2014 -0700 @@ -82,23 +82,28 @@ %! ## test basic usage with 1 and 3 outputs %! [rgb] = ind2rgb (img, map); %! [r, g, b] = ind2rgb (img, map); -%!assert (ergb, rgb); -%!assert (ergb, reshape ([r(:) g(:) b(:)], [size(img) 3])); +%! +%!assert (ergb, rgb) +%!assert (ergb, reshape ([r(:) g(:) b(:)], [size(img) 3])) +%!test %! ## test correction for integers -%! img = uint8 (img -1); +%! img = uint8 (img - 1); %! [rgb] = ind2rgb (img, map); -%!assert (ergb, rgb); -%! ## check it fails when image is a float with an index value of 0 -%!fail ("[rgb] = ind2rgb (double(img), map)") +%! assert (ergb, rgb); +%!test +%! ## Check that values below lower bound are mapped to first color value +%! rgb = ind2rgb ([-1 0 2], gray (64)); +%! assert (rgb(:,1:2,:), zeros (1,2,3)); +%! assert (rgb(:,3,:), 1/63 * ones (1,1,3)); %% Test input validation %!error ind2rgb () %!error ind2rgb (1,2,3) -%!error ind2rgb ({1}, jet (64)) +%!error ind2rgb (ones (3,3,3), jet (64)) %!error ind2rgb (1+i, jet (64)) %!error ind2rgb (sparse (1), jet (64)) -%!error ind2rgb (0, jet (64)) %!error ind2rgb (1.1, jet (64)) +%!error ind2rgb ({1}, jet (64)) %!error ind2rgb (1, {1}) %!error ind2rgb (1, 1+i) %!error ind2rgb (1, ones (2,2,2)) @@ -106,3 +111,8 @@ %!error ind2rgb (1, [-1]) %!error ind2rgb (1, [2]) +%!warning ind2rgb ([-1 1], jet (64)); +%!warning ind2rgb ([0 1 2], gray (5)); +%!warning ind2rgb ([1 2 6], gray (5)); +%!warning ind2rgb (uint8 ([1 2 5]), gray (5)); + diff -r 3a1a4d587c4e -r 875f4510d6dc scripts/image/private/ind2x.m --- a/scripts/image/private/ind2x.m Sun Mar 16 11:44:11 2014 -0700 +++ b/scripts/image/private/ind2x.m Mon Mar 17 09:10:32 2014 -0700 @@ -22,12 +22,13 @@ function [x, map] = ind2x (caller, x, map) ## Check if X is an indexed image. - ## an indexed image is defined has having only 2D, and that's how Matlab + ## An indexed image is defined has having only 2D, and that's how Matlab ## behaves. But we want to support ND images, so we will allow up to 4D - ## and check that the 3rd is a singleton - if (all (ndims (x) != [2 4]) || size (x, 3) != 1 || issparse (x) || - (isfloat (x) && ! isindex (x)) || - ! any (strcmp (class (x), {"uint8", "uint16", "single", "double"}))) + ## and check that the 3rd dimension is a singleton. + if (all (ndims (x) != [2 4]) || size (x, 3) != 1 + || iscomplex (x) || issparse (x) + || (isfloat (x) && x != fix (x)) + || ! any (strcmp (class (x), {"uint8", "uint16", "single", "double"}))) error ("%s: X must be an indexed image", caller); endif @@ -36,10 +37,20 @@ error ("%s: MAP must be a valid colormap", caller); endif - ## Do we have enough colors in the color map? - ## there's an offset of 1 when the indexed image is an integer class so we fix - ## it now and convert it to float only if really necessary and even then only - ## to single precision since that is enough for both uint8 and uint16. + ## Any color indices below the lower bound of the color map are modified + ## to point to the first color in the map (see bug #41851). + if (isfloat (x)) + invalid_idx = x < 1; + if (any (invalid_idx(:))) + warning (["Octave:" caller ":invalid-idx-img"], + [caller ": indexed image contains colors outside of colormap"]); + x(invalid_idx) = 1; + endif + endif + + ## Switch to using 1-based indexing. + ## It is possible that an integer storage class may not have enough room + ## to make the switch, in which case we convert the data to single. maxidx = max (x(:)); if (isinteger (x)) if (maxidx == intmax (class (x))) @@ -49,9 +60,12 @@ maxidx += 1; endif + ## When there are more colors in the image, than there are in the map, + ## pad the colormap with the last color in the map for Matlab compatibility. num_colors = rows (map); if (num_colors < maxidx) - ## Pad with the last color in the map for Matlab compatibility + warning (["Octave:" caller ":invalid-idx-img"], + [caller ": indexed image contains colors outside of colormap"]); pad = repmat (map(end,:), maxidx - num_colors, 1); map(end+1:maxidx, :) = pad; endif