From bug-request at octave dot org Sun Apr 3 09:33:11 2005 Subject: Re: bug in imshow with all negative values From: Stefan van der Walt To: "John W. Eaton" Cc: octave bug mailing list Date: Sun, 3 Apr 2005 16:30:11 +0200 --8t9RHnE3ZwKMSgU+ Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Here's the new patch. I added the function __im_numeric_limits to imshow.m. This can be replaced with 'numeric_limits' once it is done. I only made use of the 'max' attribute. Regards Stefan On Thu, Mar 31, 2005 at 11:07:08AM -0500, John W. Eaton wrote: > On 31-Mar-2005, Stefan van der Walt wrote: > > | I have taken out the depth guessing in my latest patch to imshow. > | > | John, are you comfortable with the latest version of the patch? > | Should I implement a function similar to "classmax" in bitfcns.cc? > > Sorry for the delay. > > Yes, the patch to imshow looks OK to me. But rather than introducing > a function that can only return the max value, how about something > like this: > > s = numeric_limits (class (pi)) > > => s.epsilon = 2.2204e-16 > s.is_exact = false > s.is_integer = false > s.is_signed = true > s.min = 2.2251e-308 > s.max = 1.7977e+308 > > s = numeric_limits (class (uint8 (1))) > > => s.epsilon = 0 > s.is_exact = true > s.is_integer = true > s.is_signed = false > s.min = 0 > s.max = 255 > > and perhaps include all the fields that are available in the C++ > numeric_limits class defined in the header? > > This function would return an error if given a class that was not a > numeric type. > > It should be implemented in the octave_value class hierarchy (I could > do this part; for now you could just write a .m file fucntion that > used a switch statement for the common class names and that returned > the info you are interested in). > > Comments? > > jwe --8t9RHnE3ZwKMSgU+ Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="imshow.m.diff" --- imshow.old.m 2005-03-16 23:54:24.000000000 +0200 +++ imshow.m 2005-04-03 16:28:18.000000000 +0200 at @ -20,13 +20,15 @@ ## -*- texinfo -*- ## at deftypefn {Function File} {} imshow (@var{i}) ## at deftypefnx {Function File} {} imshow (@var{x}, @var{map}) -## at deftypefnx {Function File} {} imshow (@var{x}, @var{n}) -## at deftypefnx {Function File} {} imshow (@var{i}, @var{n}) +## at deftypefnx {Function File} {} imshow (@var{i}, @var{N}) ## at deftypefnx {Function File} {} imshow (@var{r}, @var{g}, @var{b}) ## Display an image. ## -## at code{imshow (@var{x})} displays an intensity image, estimating the -## number of gray levels. +## at code{imshow (@var{x})} displays an image @var{x}. +## The numerical class of the image determines its bit-depth: 1 for +## "logical", 8 for "uint8" and "logical", and 16 for "double" or "uint16". +## If at var{x} has dimensions MxNx3, the three matrices represent the red, +## green and blue components of the image. ## ## at code{imshow (@var{x}, @var{map})} displays an indexed image using the ## specified colormap. at @ -63,57 +65,89 @@ if (mvars < 1 || mvars > 3) usage (usage_str); endif - - ## All except imshow (r, g, b) + + ## Determine image depth + imclass = class (varargin{1}); + s = __im_numeric_limits (imclass); + if (!isfield (s, "max")) + error ("imshow: cannot handle image class '%s'", imclass); + endif - if (mvars != 3) - I = varargin{1}; - if (iscomplex (I)) - warning ("imshow: displaying real part of complex image"); - I = real (I); - endif - if (max (I(:)) <= 1) - ## image in [0-1]; scale to [0-255] - I = I * 255; - M = gray (256); + ## Maximum bit-depth is 16 + if (s.max > 65535) + s.max = 65535; + endif + + imdepth = log (s.max+1) / log (2); + if (imdepth - floor (imdepth) != 0) + error ("imshow: cannot determine image colour depth"); + endif + + ## Remove complex parts of arguments + realwarning = false; + for i = 1:mvars + if (iscomplex (varargin{i})) + if (!realwarning) + warning ("imshow: displaying real part of complex image"); + realwarning = true; + endif + varargin{i} = real (varargin{i}); endif + endfor + + ## Pack r,g,b image into ND-matrix if necessary + if (mvars == 3) + I = []; + try + I = cat (3, varargin{1:3}); + catch + error ("imshow: r, g and b matrix dimensions must agree"); + end_try_catch + else + I = varargin{1}; + endif + I = double (I); + + ## Is the image specified as MxNx3 colour? + iscolour = false; + if (size (I,3) == 3) + iscolour = true; endif - if (mvars == 1) - ## imshow (x) - ## Grayscale image [0-N] -- estimate gray levels. - N = 2 ^ ceil (log2 (max (I(:)))); - if (N <= 65536) - M = gray (N); - else - M = gray (256); - I = I / max (I(:)) * 255; + ## Is the image indexed? + isindexed = false; + if (mvars == 2) + isindexed = true; + if (iscolour) + error ("imshow: cannot provide colour image and colourmap"); endif - elseif (mvars == 2) - ## imshow (x, map) or imshow (x, N) + endif + + ## Scale images of class "double" appropriately + if (!isindexed) + if (strcmp (imclass, "double") == 1) + if (max (I(:)) <= 1) + ## image in [0-1]; scale to [0 - 2^imdepth] + I = I * 2^imdepth; + else + ## image outside [0-1]; this is unexpected: scale to [0 - 2^imdepth] + I = I / max (I(:)) * 2^imdepth; + endif + endif + endif + + ## Generate colour map + if (isindexed) M = varargin{2}; if (isscalar (M)) M = gray (M); endif - elseif (mvars == 3) - ## imshow (r, g, b) - r = varargin{1}; - g = varargin{2}; - b = varargin{3}; - tmp = [r; g; b]; - if (iscomplex (tmp)) - warning ("imshow: displaying real part of complex rgb image"); - r = real (r); - g = real (g); - b = real (b); - endif - if (max (tmp(:)) > 1) - ## Normalise to [0-1]. - r = r / 255; - g = g / 255; - b = b / 255; - endif - [I, M] = rgb2ind (r, g, b); + elseif (iscolour) + I = I / 2^imdepth; + [I, M] = rgb2ind (I(:,:,1), I(:,:,2), I(:,:,3)); + else + I = I+1; ## index into colourmap + M = gray (2^imdepth); endif ## Check for "truesize". at @ -129,6 +163,23 @@ endfunction +function s = __im_numeric_limits (cname) + s = struct (); + switch (cname) + case ("double") + s.max = realmax; + case ("char") + s.max = 255; + case ("logical") + s.max = 1; + otherwise + try + s.max = double (intmax (cname)); + catch + end_try_catch + endswitch +endfunction + %!error imshow () # no arguments %!error imshow (1, 2, 3, 4, 5) # too many arguments %!error imshow ([1,2], [2,3], [3,4], [4,5]) # too many matrix arguments at @ -143,4 +194,17 @@ %!demo %! [I, M] = loadimage ("default.img"); -%! imshow(I, M); +%! imshow (I, M); + +%!demo +%! [I, M] = loadimage ("default.img"); +%! imshow (I, I*0.5, I*0.8); + +%!demo +%! [I, M] = loadimage ("default.img"); +%! X = []; +%! X = cat (3, X, I*0.8); +%! X = cat (3, X, I*0.8); +%! X = cat (3, X, I); +%! imshow (X); + --8t9RHnE3ZwKMSgU+-- ------------------------------------------------------------- Octave is freely available under the terms of the GNU GPL. Octave's home on the web: http://www.octave.org How to fund new projects: http://www.octave.org/funding.html Subscription information: http://www.octave.org/archive.html -------------------------------------------------------------