# HG changeset patch # User Rik # Date 1354471377 28800 # Node ID b1cd65881592a3c0b28677fa13c92d734e89a339 # Parent 168e380c8f1875b572404fe9eeb77261652209a7 Clean up scripts in image directory. Use Octave coding conventions. Redo docstrings. Add %!tests. * brighten.m: Put input validation first. Use iscolormap to simplify input checking. * cmunique.m: Use faster method of validating input class. * colormap.m: Tweak docstring. Improve input validation. * contrast.m: Tweak docstring. Use cmap instead of map as variable name for clarity. * gray2ind.m: Wrap long lines. Use faster method of validating input class. Delete unreachable code for n>65536. * hsv2rgb.m: Use faster method of validating input class. * imwrite.m: Tweak FIXME notes. * ind2gray.m: Use correct caller name for ind2x. Update %!tests with new 2-input calling convention. * ind2rgb.m: Tweak docstring. Update %!tests with new 2-input calling convention. * iscolormap.m: Tweak docstring. Re-order validation tests. * ntsc2rgb.m: Use faster method of validating input class. Better input validation. Add %!tests. * private/ind2x.m: Use more descriptive variable names. * rgb2hsv.m: Tweak docstring. Use faster method of validating input class. * rgb2ind.m: Tweak docstring. Wrap long lines. * rgb2ntsc.m: Use faster method of validating input class. Improve input validation. Add %!tests. * rgbplot.m: Match variable names in docstring to those in function prototype. diff --git a/scripts/image/brighten.m b/scripts/image/brighten.m --- a/scripts/image/brighten.m +++ b/scripts/image/brighten.m @@ -34,22 +34,24 @@ function rmap = brighten (arg1, beta) + if (nargin < 1 || nargin > 2) + print_usage (); + endif + h = -1; if (nargin == 1) beta = arg1; - m = colormap; + m = colormap (); h = gcf (); - elseif (nargin == 2) + else if (ishandle (arg1)) h = arg1; m = get (h, "colormap"); - elseif (ismatrix (arg1) && columns (arg1) == 3) + elseif (iscolormap (arg1)) m = arg1; else - error ("brighten: first argument must be an Nx3 matrix or a handle"); + error ("brighten: first argument must be a colormap or a graphics handle"); endif - else - print_usage (); endif if (! isscalar (beta) || beta <= -1 || beta >= 1) diff --git a/scripts/image/cmunique.m b/scripts/image/cmunique.m --- a/scripts/image/cmunique.m +++ b/scripts/image/cmunique.m @@ -62,7 +62,7 @@ cls = class (X); ## FIXME: Documentation accepts only 3 classes. Could easily add 'single'. - if (! any (isa (X, {"uint8", "uint16", "double"}))) + if (! any (strcmp (cls, {"uint8", "uint16", "double"}))) error ("cmunique: X is of invalid data type '%s'", cls); endif diff --git a/scripts/image/colormap.m b/scripts/image/colormap.m --- a/scripts/image/colormap.m +++ b/scripts/image/colormap.m @@ -22,8 +22,8 @@ ## @deftypefnx {Function File} {@var{cmap} =} colormap (@var{map}) ## @deftypefnx {Function File} {@var{cmap} =} colormap ("default") ## @deftypefnx {Function File} {@var{cmap} =} colormap ("list") -## @deftypefnx {Function File} {@var{cmap} =} colormap ("register", "name") -## @deftypefnx {Function File} {@var{cmap} =} colormap ("unregister", "name") +## @deftypefnx {Function File} {@var{cmap} =} colormap ("register", "@var{name}") +## @deftypefnx {Function File} {@var{cmap} =} colormap ("unregister", "@var{name}") ## Query or set the current colormap. ## ## @code{colormap (@var{map})} sets the current colormap to @var{map}. The @@ -68,8 +68,9 @@ endif if (! isempty (map)) - if (! ismatrix (map) || ndims (map) != 2 || columns (map) != 3) - error ("colormap: MAP must be an N x 3 ([R,G,B]) matrix"); + if (! (isnumeric (map) && isreal (map) + && ndims (map) == 2 && columns (map) == 3)) + error ("colormap: MAP must be a real-valued N x 3 ([R,G,B]) matrix"); endif if (any (map(:) < 0) || any (map(:) > 1)) error ("colormap: all MAP values must be in the range [0,1]"); @@ -98,4 +99,4 @@ endfunction -%% +%% FIXME: Need some demos/tests diff --git a/scripts/image/contrast.m b/scripts/image/contrast.m --- a/scripts/image/contrast.m +++ b/scripts/image/contrast.m @@ -17,18 +17,18 @@ ## . ## -*- texinfo -*- -## @deftypefn {Function File} {@var{map} =} contrast (@var{x}) -## @deftypefnx {Function File} {@var{map} =} contrast (@var{x}, @var{n}) +## @deftypefn {Function File} {@var{cmap} =} contrast (@var{x}) +## @deftypefnx {Function File} {@var{cmap} =} contrast (@var{x}, @var{n}) ## Return a gray colormap that maximizes the contrast in an image. The ## returned colormap will have @var{n} rows. If @var{n} is not defined ## then the size of the current colormap is used. ## @seealso{colormap, brighten} ## @end deftypefn -function map = contrast (x, n) +function cmap = contrast (x, n) if (nargin == 1) - n = rows (colormap); + n = rows (colormap ()); elseif (nargin == 2) if (! isscalar (n)) error ("contrast: N must be a scalar"); @@ -39,10 +39,10 @@ x = x(:); minx = min (x); - map = find (diff (sort ([round(n * ((x - minx) ./ (max(x) - minx))); [0:n]']))); - minm = min (map); - map = (map - minm) ./ (max (map) - minm); - map = [map, map, map]; + cmap = find (diff (sort ([round(n * ((x - minx) ./ (max(x) - minx))); [0:n]']))); + minm = min (cmap); + cmap = (cmap - minm) ./ (max (cmap) - minm); + cmap = [cmap, cmap, cmap]; endfunction diff --git a/scripts/image/gray2ind.m b/scripts/image/gray2ind.m --- a/scripts/image/gray2ind.m +++ b/scripts/image/gray2ind.m @@ -28,8 +28,8 @@ ## If not given @var{n} defaults to 64 for grayscale images or 2 for ## binary black and white images. ## -## The output @var{img} is of class uint8 or uint 16 if @var{n} is less than or -## equal to 256 or 65536 respectively. Otherwise, the output is of class double. +## The output @var{img} is of class uint8 if @var{n} is less than or +## equal to 256; Otherwise the return class is uint16. ## @seealso{ind2gray, rgb2ind} ## @end deftypefn @@ -46,7 +46,7 @@ elseif (! isscalar (n) || n < 1 || n > 65536) error ("gray2ind: N must be a positive integer in the range [1, 65536]"); elseif (! ismatrix (I) || ndims (I) != 2) - error ("gray2ind: first input argument must be a gray scale image"); + error ("gray2ind: I must be a grayscale or binary image"); endif ## default n is different if image is logical @@ -54,12 +54,8 @@ n = 2; endif - if (! isscalar (n) || n < 0) - error ("gray2ind: second input argument must be a positive integer"); - endif - cls = class (I); - if (! any (isa (I, {"logical", "uint8", "uint16", "int16", "single", "double"}))) + if (! any (strcmp (cls, {"logical", "uint8", "uint16", "int16", "single", "double"}))) error ("gray2ind: invalid data type '%s'", cls); elseif (isfloat (I) && (min (I(:) < 0) || max (I(:) > 1))) error ("gray2ind: floating point images may only contain values between 0 and 1"); @@ -75,20 +71,19 @@ else scale = 1; endif + I *= (n-1)/scale; + ## Note: no separate call to round () necessary because ## type conversion does that automatically. - I = I * ((n-1)/scale); if (n < 256) I = uint8 (I); - elseif (n < 65536) + else I = uint16 (I); - else - ## if uint16 is not enough, we return double in which case index - ## values should start at 1. - I = round (I) + 1; endif + endfunction + %!assert (gray2ind ([0 0.25 0.5 1]), uint8 ([0 16 32 63])) %!assert (gray2ind ([0 0.25 0.5 1], 400), uint16 ([0 100 200 399])) %!assert (gray2ind (logical ([1 0 0 1])), uint8 ([1 0 0 1])) diff --git a/scripts/image/hsv2rgb.m b/scripts/image/hsv2rgb.m --- a/scripts/image/hsv2rgb.m +++ b/scripts/image/hsv2rgb.m @@ -46,7 +46,7 @@ endif cls = class (hsv_map); - if (! any (isa (hsv_map, {"uint8", "uint16", "single", "double"}))) + if (! any (strcmp (cls, {"uint8", "uint16", "single", "double"}))) error ("hsv2rgb: invalid data type '%s'", cls); elseif (isfloat (hsv_map) && (any (hsv_map(:) < 0) || any (hsv_map(:) > 1))) error ("hsv2rgb: floating point images may only contain values between 0 and 1"); @@ -96,6 +96,8 @@ + (hue >= 1/6 & hue < 1/2) + (hue >= 1/2 & hue < 2/3) .* (4 - 6 * hue)); + ## FIXME: hsv2rgb does not preserve class of image. + ## Should it also convert back to uint8, uint16 for integer images? ## If input was an image, convert it back into one. if (is_image) rgb_map = reshape (rgb_map, sz); diff --git a/scripts/image/imwrite.m b/scripts/image/imwrite.m --- a/scripts/image/imwrite.m +++ b/scripts/image/imwrite.m @@ -135,7 +135,7 @@ if ((nd == 2 || nd == 3) && strcmp (img_class, "double")) img = uint8 (img * 255); endif - ## FIXME -- should we handle color images w/ alpha channel here? + ## FIXME: should we handle color images with alpha channel here? if (nd == 3 && size (img, 3) < 3) error ("imwrite: invalid dimensions for truecolor image"); endif @@ -165,8 +165,8 @@ error ("imwrite: invalid indexed image colormap"); endif - ## FIXME -- we should really be writing indexed images here but - ## __magick_write__ needs to be fixed to handle them. + ## FIXME: we should really be writing indexed images here but + ## __magick_write__ needs to be fixed to handle them. [r, g, b] = ind2rgb (img, map); tmp = uint8 (cat (3, r, g, b) * 255); diff --git a/scripts/image/ind2gray.m b/scripts/image/ind2gray.m --- a/scripts/image/ind2gray.m +++ b/scripts/image/ind2gray.m @@ -45,13 +45,13 @@ if (nargin != 2) print_usage (); endif - [x, map] = ind2x ("ind2rgb", x, map); + [x, map] = ind2x ("ind2gray", x, map); ## Convert colormap to luminance intensity values map *= [0.29894; 0.58704; 0.11402]; - ## Convert colormap to same class as that of input so that when reshape - ## later, produces output of the same type as the input + ## Convert colormap to same class as that of input so that reshape + ## will produce output of the same type as the input. cls = class (x); if (isinteger (x)) ## if we later add support for int16 images, this will not work. Look into @@ -66,19 +66,21 @@ endfunction + %!shared i2g %! i2g = ind2gray (1:100, gray (100)); %!assert (i2g, 0:1/99:1, eps); %!assert (gray2ind (i2g, 100), uint8 (0:99)); -%%test input validation +%% Test input validation %!error ind2gray () +%!error ind2gray (1) %!error ind2gray (1,2,3) -%!error ind2gray ({1}) -%!error ind2gray (1+i) -%!error ind2gray (sparse (1)) -%!error ind2gray (0) -%!error ind2gray (1.1) +%!error ind2gray ({1}, 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, {1}) %!error ind2gray (1, 1+i) %!error ind2gray (1, ones (2,2,2)) diff --git a/scripts/image/ind2rgb.m b/scripts/image/ind2rgb.m --- a/scripts/image/ind2rgb.m +++ b/scripts/image/ind2rgb.m @@ -18,11 +18,11 @@ ## -*- texinfo -*- ## @deftypefn {Function File} {@var{rgb} =} ind2rgb (@var{x}, @var{map}) -## @deftypefnx {Function File} {[@var{R}, @var{G}, @var{B}] =} ind2rgb (@dots{}) +## @deftypefnx {Function File} {[@var{R}, @var{G}, @var{B}] =} ind2rgb (@var{x}, @var{map}) ## Convert an indexed image to red, green, and blue color components. ## ## The image @var{x} must be an indexed image which will be converted using the -## colormap @var{cmap}. If @var{cmap} does not contain enough colors for the +## colormap @var{map}. If @var{map} does not contain enough colors for the ## image, pixels in @var{x} outside the range are mapped to the last color in ## the map. ## @@ -59,6 +59,7 @@ endfunction + %!shared img, map, ergb, rgb, r, g, b %! img = [2 4 5; 3 2 5; 1 2 4]; %! map = [0.0 0.0 0.0 @@ -79,19 +80,20 @@ %! [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)") +%!fail ("[rgb] = ind2rgb (double(img), map)") -%%test input validation +%% Test input validation %!error ind2rgb () %!error ind2rgb (1,2,3) -%!error ind2rgb ({1}) -%!error ind2rgb (1+i) -%!error ind2rgb (sparse (1)) -%!error ind2rgb (0) -%!error ind2rgb (1.1) +%!error ind2rgb ({1}, 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, {1}) %!error ind2rgb (1, 1+i) %!error ind2rgb (1, ones (2,2,2)) %!error ind2rgb (1, ones (2,4)) %!error ind2rgb (1, [-1]) %!error ind2rgb (1, [2]) + diff --git a/scripts/image/iscolormap.m b/scripts/image/iscolormap.m --- a/scripts/image/iscolormap.m +++ b/scripts/image/iscolormap.m @@ -20,10 +20,10 @@ ## @deftypefn {Function File} {} iscolormap (@var{cmap}) ## Return true if @var{cmap} is a colormap. ## -## A colormap is an @var{n} row by 3 column matrix. The columns contain red, -## green, and blue intensities respectively. All entries must be between 0 -## and 1 inclusive. -## +## A colormap is a real matrix with @var{n} rows and 3 columns. +## Each row represents a single color. The columns contain red, green, +## and blue intensities respectively. All entries must be between 0 and 1 +## inclusive. ## @seealso{colormap, rgbplot} ## @end deftypefn @@ -36,7 +36,7 @@ endif retval = (isnumeric (cmap) && isreal (cmap) && - columns (cmap) == 3 && ndims (cmap) == 2 && isa (cmap, "double") && + ndims (cmap) == 2 && columns (cmap) == 3 && isa (cmap, "double") && min (cmap(:)) >= 0 && max (cmap(:)) <= 1); endfunction @@ -45,8 +45,9 @@ %!assert (iscolormap (jet (64))) %!assert (iscolormap ({0 1 0}), false) %!assert (iscolormap ([0 1i 0]), false) +%!assert (iscolormap (ones (3,3,3)), false) %!assert (iscolormap (ones (3,4)), false) -%!assert (iscolormap (ones (3,3,3)), false) %!assert (iscolormap (single (jet (64))), false) %!assert (iscolormap ([0 0 -2]), false) %!assert (iscolormap ([0 0 2]), false) + diff --git a/scripts/image/ntsc2rgb.m b/scripts/image/ntsc2rgb.m --- a/scripts/image/ntsc2rgb.m +++ b/scripts/image/ntsc2rgb.m @@ -46,7 +46,7 @@ endif cls = class (yiq); - if (! any (isa (yiq, {"uint8", "uint16", "single", "double"}))) + if (! any (strcmp (cls, {"uint8", "uint16", "single", "double"}))) error ("ntsc2rgb: invalid data type '%s'", cls); endif @@ -57,7 +57,6 @@ yiq = [yiq(:,:,1)(:), yiq(:,:,2)(:), yiq(:,:,3)(:)]; ## Convert to a double image. if (isinteger (yiq)) - cls = class (yiq); low = double (intmin (cls)); high = double (intmax (cls)); yiq = (double (yiq) - low) / (high - low); @@ -66,12 +65,12 @@ is_image = false; endif - if (! ismatrix (yiq) || columns (yiq) != 3) - error ("ntsc2rgb: argument must be a matrix of size Nx3 or NxMx3"); + if (! isreal (yiq) || columns (yiq) != 3 || issparse (yiq)) + error ("ntsc2rgb: input must be a matrix of size Nx3 or NxMx3"); endif - ## Conversion matrix constructed from 'inv (rgb2ntsc matrix)'. See - ## programming notes in rgb2ntsc.m. Note: Matlab matrix for inverse + ## Conversion matrix constructed from 'inv (rgb2ntsc matrix)'. + ## See programming notes in rgb2ntsc.m. Note: Matlab matrix for inverse ## is slightly different. We prefer this matrix so that ## x == ntsc2rgb (rgb2ntsc (x)) rather than maintaining strict compatibility ## with Matlab. @@ -81,6 +80,8 @@ rgb = yiq * trans; + ## FIXME: ntsc2rgb does not preserve class of image. + ## Should it also convert back to uint8, uint16 for integer images? ## If input was an image, convert it back into one. if (is_image) rgb = reshape (rgb, sz); @@ -89,6 +90,11 @@ endfunction +%% Test pure R, G, B colors +%!assert (ntsc2rgb ([.299 .596 .211]), [1 0 0], 1e-5) +%!assert (ntsc2rgb ([.587 -.274 -.523]), [0 1 0], 1e-5) +%!assert (ntsc2rgb ([.114 -.322 .312]), [0 0 1], 1e-5) + %!test %! rgb_map = rand (64, 3); %! assert (ntsc2rgb (rgb2ntsc (rgb_map)), rgb_map, 1e-3); @@ -97,14 +103,6 @@ %! rgb_img = rand (64, 64, 3); %! assert (ntsc2rgb (rgb2ntsc (rgb_img)), rgb_img, 1e-3); -%%!test -%%! ntsc_map = rand (64, 3); -%%! assert (rgb2ntsc (ntsc2rgb (ntsc_map)), ntsc_map, 1e-3); -% -%%!test -%%! ntsc_img = rand (64, 64, 3); -%%! assert (rgb2ntsc (ntsc2rgb (ntsc_img)), ntsc_img, 1e-3); - %% Test input validation %!error ntsc2rgb () %!error ntsc2rgb (1,2) diff --git a/scripts/image/private/ind2x.m b/scripts/image/private/ind2x.m --- a/scripts/image/private/ind2x.m +++ b/scripts/image/private/ind2x.m @@ -17,26 +17,25 @@ ## along with Octave; see the file COPYING. If not, see ## . -## private function for the ind2something functions which have a lot of code -## in common +## private function for the ind2XXX functions which have a lot of code in common -function [x, map] = ind2x (name, x, map) +function [x, map] = ind2x (caller, x, map) ## Check if X is an indexed image. if (ndims (x) != 2 || issparse (x) || (isfloat (x) && ! isindex (x)) || - ! ismember (class (x), {"double", "single", "uint8", "uint16"})) - error ("%s: X must be an indexed image", name); + ! any (strcmp (class (x), {"uint8", "uint16", "single", "double"}))) + error ("%s: X must be an indexed image", caller); endif - ## Check the color map. + ## Check if map is a valid colormap. if (! iscolormap (map)) - error ("%s: MAP must be a valid colormap", name); + 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 its enough for both uint8 and uint16 + ## to single precision since that is enough for both uint8 and uint16. maxidx = max (x(:)); if (isinteger (x)) if (maxidx == intmax (class (x))) @@ -46,10 +45,10 @@ maxidx += 1; endif - rm = rows (map); - if (rm < maxidx) + num_colors = rows (map); + if (num_colors < maxidx) ## Pad with the last color in the map for matlab compatibility - pad = repmat (map(end,:), maxidx-rm, 1); + pad = repmat (map(end,:), maxidx - num_colors, 1); map(end+1:maxidx, :) = pad; endif diff --git a/scripts/image/rgb2hsv.m b/scripts/image/rgb2hsv.m --- a/scripts/image/rgb2hsv.m +++ b/scripts/image/rgb2hsv.m @@ -24,7 +24,7 @@ ## ## A color in the RGB space consists of red, green, and blue intensities. ## -## A color in HSV space is represented by hue, saturation and value +## A color in HSV space is represented by hue, saturation, and value ## (brightness) levels. Value gives the amount of light in the color. Hue ## describes the dominant wavelength. Saturation is the amount of hue mixed ## into the color. @@ -41,7 +41,7 @@ endif cls = class (rgb); - if (! any (isa (rgb, {"uint8", "uint16", "single", "double"}))) + if (! any (strcmp (cls, {"uint8", "uint16", "single", "double"}))) error ("rgb2hsv: invalid data type '%s'", cls); elseif (isfloat (rgb) && (any (rgb(:) < 0) || any (rgb(:) > 1))) error ("rgb2hsv: floating point images may only contain values between 0 and 1"); @@ -54,7 +54,6 @@ rgb = [rgb(:,:,1)(:), rgb(:,:,2)(:), rgb(:,:,3)(:)]; ## Convert to a double image. if (isinteger (rgb)) - cls = class (rgb); low = double (intmin (cls)); high = double (intmax (cls)); rgb = (double (rgb) - low) / (high - low); @@ -64,7 +63,7 @@ endif if (! ismatrix (rgb) || columns (rgb) != 3 || issparse (rgb)) - error ("rgb2hsv: input must be a matrix of size Nx3"); + error ("rgb2hsv: input must be a matrix of size Nx3 or MxNx3"); endif ## get the max and min for each row @@ -100,6 +99,8 @@ hsv_map = [h, s, v]; + ## FIXME: rgb2hsv does not preserve class of image. + ## Should it also convert back to uint8, uint16 for integer images? ## If input was an image, convert it back into one. if (is_image) hsv_map = reshape (hsv_map, sz); diff --git a/scripts/image/rgb2ind.m b/scripts/image/rgb2ind.m --- a/scripts/image/rgb2ind.m +++ b/scripts/image/rgb2ind.m @@ -20,12 +20,14 @@ ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{x}, @var{map}] =} rgb2ind (@var{rgb}) ## @deftypefnx {Function File} {[@var{x}, @var{map}] =} rgb2ind (@var{R}, @var{G}, @var{B}) -## Convert an image in red-green-blue (RGB) space to an indexed image. +## Convert an image in red-green-blue (RGB) color space to an indexed image. ## @seealso{ind2rgb, rgb2hsv, rgb2ntsc} ## @end deftypefn -## FIXME: This function has a very different syntax than the Matlab one of the same name. -## Octave function does no support N, MAP, DITHER, or TOL arguments +## FIXME: This function has a very different syntax than the Matlab +## one of the same name. +## Octave function does not support N, MAP, DITHER, or TOL arguments. + ## Author: Tony Richardson ## Created: July 1994 ## Adapted-By: jwe @@ -51,7 +53,7 @@ x = reshape (1:numel (R), size (R)); - map = unique([R(:) G(:) B(:)], "rows"); + map = unique ([R(:) G(:) B(:)], "rows"); [~, x] = ismember ([R(:) G(:) B(:)], map, "rows"); x = reshape (x, size (R)); @@ -78,11 +80,14 @@ else ## leave it as double endif + endfunction + %% FIXME: Need some functional tests or %!demo blocks %% Test input validation %!error rgb2ind () %!error rgb2ind (1,2) %!error rgb2ind (1,2,3,4) + diff --git a/scripts/image/rgb2ntsc.m b/scripts/image/rgb2ntsc.m --- a/scripts/image/rgb2ntsc.m +++ b/scripts/image/rgb2ntsc.m @@ -51,7 +51,7 @@ endif cls = class (rgb); - if (! any (isa (rgb, {"uint8", "uint16", "single", "double"}))) + if (! any (strcmp (cls, {"uint8", "uint16", "single", "double"}))) error ("rgb2ntsc: invalid data type '%s'", cls); elseif (isfloat (rgb) && (any (rgb(:) < 0) || any (rgb(:) > 1))) error ("rgb2ntsc: floating point images may only contain values between 0 and 1"); @@ -72,8 +72,8 @@ is_image = false; endif - if (! ismatrix (rgb) || columns (rgb) != 3 || issparse (rgb)) - error ("rgb2ntsc: argument must be a matrix of size Nx3 or NxMx3"); + if (! isreal (rgb) || columns (rgb) != 3 || issparse (rgb)) + error ("rgb2ntsc: input must be a matrix of size Nx3 or NxMx3"); endif ## Reference matrix for transformation from http://en.wikipedia.org/wiki/YIQ @@ -86,6 +86,8 @@ ## Convert data. yiq = rgb * trans; + ## FIXME: rgb2ntsc does not preserve class of image. + ## Should it also convert back to uint8, uint16 for integer images? ## If input was an image, convert it back into one. if (is_image) yiq = reshape (yiq, sz); @@ -94,8 +96,10 @@ endfunction -%% Test RED conversion -%assert (rgb2ntsc ([1 0 0]), [0.299 0.587 0.114]) +%% Test pure RED, GREEN, BLUE colors +%assert (rgb2ntsc ([1 0 0]), [.299 .587 .114]) +%assert (rgb2ntsc ([0 1 0]), [.596 -.274 -.322]) +%assert (rgb2ntsc ([1 0 1]), [.211 -.523 .312]) %!test %! rgb_map = rand (64, 3); diff --git a/scripts/image/rgbplot.m b/scripts/image/rgbplot.m --- a/scripts/image/rgbplot.m +++ b/scripts/image/rgbplot.m @@ -50,7 +50,7 @@ endif if (! iscolormap (cmap)) - error ("rgbplot: CMAP must be a colormap"); + error ("rgbplot: CMAP must be a valid colormap"); elseif (! ischar (style)) error ("rgbplot: STYLE must be a string"); endif @@ -69,7 +69,7 @@ xlabel ("color index"); if (nargout > 0) - retval = h; + h = htmp; endif endfunction @@ -81,7 +81,8 @@ %! subplot (1, 2, 2) %! rgbplot (ocean, "composite"); -%%test input validation +%% Test input validation %!error rgbplot () %!error rgbplot (1,2) -%!error rgbplot ({0 1 0}) +%!error rgbplot ({0 1 0}) +