|
@@ -0,0 +1,185 @@
|
|
|
+% Copyright (C) 2000, 2001 Kai Habel <kai.habel@gmx.de>
|
|
|
+% Copyright (C) 2012 Carn?? Draug <carandraug+dev@gmail.com>
|
|
|
+%
|
|
|
+% This program is free software; you can redistribute it and/or modify it under
|
|
|
+% the terms of the GNU General Public License as published by the Free Software
|
|
|
+% Foundation; either version 3 of the License, or (at your option) any later
|
|
|
+% version.
|
|
|
+%
|
|
|
+% This program is distributed in the hope that it will be useful, but WITHOUT
|
|
|
+% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
+% FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
|
+% details.
|
|
|
+%
|
|
|
+% You should have received a copy of the GNU General Public License along with
|
|
|
+% this program; if not, see <http://www.gnu.org/licenses/>.
|
|
|
+
|
|
|
+% -*- texinfo -*-
|
|
|
+% @deftypefn {Function File} {} imcast (@var{img}, @var{type})
|
|
|
+% @deftypefnx {Function File} {} imcast (@var{img}, @var{type}, "indexed")
|
|
|
+% Convert image to specific data type @var{type}.
|
|
|
+%
|
|
|
+% Converts a valid image @var{img} into another class @var{type}. A valid
|
|
|
+% image must be of class logical, uint8, uint16, int16, single, or double.
|
|
|
+% Conversion of images of class logical is valid, but not the inverse, i.e.,
|
|
|
+% conversion of images into logical class is not supported. Use of
|
|
|
+% @code{im2bw} is recommended for such cases.
|
|
|
+%
|
|
|
+% If the image is indexed, the last argument may be the string
|
|
|
+% @qcode{"indexed"}. An indexed image may not be of class int16 or
|
|
|
+% single (see @code{isind} for details).
|
|
|
+%
|
|
|
+% Details on how the conversion is performed is class dependent, and can
|
|
|
+% be seen on the help text of @code{im2double}, @code{im2single},
|
|
|
+% @code{im2uint8}, @code{im2uint16}, and @code{im2int16}.
|
|
|
+%
|
|
|
+% @seealso{im2bw, im2uint8, im2double, im2int16, im2single, im2uint16}
|
|
|
+% @end deftypefn
|
|
|
+
|
|
|
+function imout = imcast (img, outcls, varargin)
|
|
|
+
|
|
|
+ if (nargin < 2 || nargin > 3)
|
|
|
+ print_usage ();
|
|
|
+ elseif (nargin == 3 && ~ strcmpi (varargin{1}, 'indexed'))
|
|
|
+ error ('imcast: third argument must be the string \"indexed\"');
|
|
|
+ end
|
|
|
+
|
|
|
+ incls = class (img);
|
|
|
+ if (strcmp (outcls, incls))
|
|
|
+ imout = img;
|
|
|
+ return
|
|
|
+ end
|
|
|
+
|
|
|
+ % we are dealing with indexed images
|
|
|
+ if (nargin == 3)
|
|
|
+ if (~ isind (img))
|
|
|
+ error ('imcast: input should have been an indexed image but it is not.');
|
|
|
+ end
|
|
|
+
|
|
|
+ % Check that the new class is enough to hold all the previous indices
|
|
|
+ % If we are converting to floating point, then we don't bother
|
|
|
+ % check the range of indices. Also, note that indexed images of
|
|
|
+ % integer class are always unsigned.
|
|
|
+
|
|
|
+ % we will be converting a floating point image to integer class
|
|
|
+ if (strcmp (outcls, 'single') || strcmp (outcls, 'double'))
|
|
|
+ if (isinteger (img))
|
|
|
+ imout = cast (img, outcls) +1;
|
|
|
+ else
|
|
|
+ imout = cast (img, outcls);
|
|
|
+ end
|
|
|
+
|
|
|
+ % we will be converting an indexed image to integer class
|
|
|
+ else
|
|
|
+ if (isinteger (img) && intmax (incls) > intmax (outcls) && max (img(:)) > intmax (outcls))
|
|
|
+ error ('imcast: IMG has too many colours %d for the range of values in %s',...
|
|
|
+ max (img(:)), outcls);
|
|
|
+ elseif (isfloat (img))
|
|
|
+ imax = max (img(:)) -1;
|
|
|
+ if (imax > intmax (outcls))
|
|
|
+ error ('imcast: IMG has too many colours %d for the range of values in %s',...
|
|
|
+ imax, outcls);
|
|
|
+ end
|
|
|
+ img = img-1;
|
|
|
+ end
|
|
|
+ imout = cast (img, outcls);
|
|
|
+ end
|
|
|
+
|
|
|
+ % we are dealing with "normal" images
|
|
|
+ else
|
|
|
+ problem = false; % did we found a bad conversion?
|
|
|
+ switch (incls)
|
|
|
+
|
|
|
+ case {'double', 'single'}
|
|
|
+ switch (outcls)
|
|
|
+ case 'uint8', imout = uint8 (img * 255);
|
|
|
+ case 'uint16', imout = uint16 (img * 65535);
|
|
|
+ case 'int16', imout = int16 (double (img * uint16 (65535)) -32768);
|
|
|
+ case {'double', 'single'}, imout = cast (img, outcls);
|
|
|
+ otherwise, problem = true;
|
|
|
+ end
|
|
|
+
|
|
|
+ case {'uint8'}
|
|
|
+ switch (outcls)
|
|
|
+ case 'double', imout = double (img) / 255;
|
|
|
+ case 'single', imout = single (img) / 255;
|
|
|
+ case 'uint16', imout = uint16 (img) * 257; % 257 comes from 65535/255
|
|
|
+ case 'int16', imout = int16 ((double (img) * 257) -32768); % 257 comes from 65535/255
|
|
|
+ otherwise, problem = true;
|
|
|
+ end
|
|
|
+
|
|
|
+ case {'uint16'}
|
|
|
+ switch (outcls)
|
|
|
+ case 'double', imout = double (img) / 65535;
|
|
|
+ case 'single', imout = single (img) / 65535;
|
|
|
+ case 'uint8', imout = uint8 (img / 257); % 257 comes from 65535/255
|
|
|
+ case 'int16', imout = int16 (double (img) -32768);
|
|
|
+ otherwise, problem = true;
|
|
|
+ end
|
|
|
+
|
|
|
+ case {'logical'}
|
|
|
+ switch (outcls)
|
|
|
+ case {'double', 'single'}
|
|
|
+ imout = cast (img, outcls);
|
|
|
+ case {'uint8', 'uint16', 'int16'}
|
|
|
+ imout = repmat (intmin (outcls), size (img));
|
|
|
+ imout(img) = intmax (outcls);
|
|
|
+ otherwise
|
|
|
+ problem = true;
|
|
|
+ end
|
|
|
+
|
|
|
+ case {'int16'}
|
|
|
+ switch (outcls)
|
|
|
+ case 'double', imout = (double (img) + 32768) / 65535;
|
|
|
+ case 'single', imout = (single (img) + 32768) / 65535;
|
|
|
+ case 'uint8', imout = uint8 ((double (img) + 32768) / 257); % 257 comes from 65535/255
|
|
|
+ case 'uint16', imout = uint16 (double (img) + 32768);
|
|
|
+ otherwise, problem = true;
|
|
|
+ end
|
|
|
+
|
|
|
+ otherwise
|
|
|
+ error ('imcast: unknown image of class \"%s\"', incls);
|
|
|
+
|
|
|
+ end
|
|
|
+ if (problem)
|
|
|
+ error ('imcast: unsupported TYPE \"%s\"', outcls);
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+end
|
|
|
+
|
|
|
+%!test
|
|
|
+%! im = randi ([0 255], 40, "uint8");
|
|
|
+%! assert (imcast (im, "uint8"), im2uint8 (im))
|
|
|
+%! assert (imcast (im, "uint16"), im2uint16 (im))
|
|
|
+%! assert (imcast (im, "single"), im2single (im))
|
|
|
+%! assert (imcast (im, "uint8", "indexed"), im2uint8 (im, "indexed"))
|
|
|
+%! assert (imcast (im, "uint16", "indexed"), im2uint16 (im, "indexed"))
|
|
|
+%! assert (imcast (im, "single", "indexed"), im2single (im, "indexed"))
|
|
|
+
|
|
|
+%!test
|
|
|
+%! im = randi ([1 256], 40, "double");
|
|
|
+%! assert (imcast (im, "uint8"), im2uint8 (im))
|
|
|
+%! assert (imcast (im, "uint8", "indexed"), im2uint8 (im, "indexed"))
|
|
|
+%! assert (imcast (im, "single", "indexed"), im2single (im, "indexed"))
|
|
|
+
|
|
|
+%!test
|
|
|
+%! im = randi ([0 65535], 40, "uint16");
|
|
|
+%! assert (imcast (im, "uint8"), im2uint8 (im))
|
|
|
+%! assert (imcast (im, "single"), im2single (im))
|
|
|
+%! assert (imcast (im, "single", "indexed"), im2single (im, "indexed"))
|
|
|
+
|
|
|
+%!test
|
|
|
+%! im = randi ([1 255], 40, "double");
|
|
|
+%! assert (imcast (im, "uint8", "indexed"), im2uint8 (im, "indexed"))
|
|
|
+%! assert (imcast (im, "single", "indexed"), im2single (im, "indexed"))
|
|
|
+
|
|
|
+%!test
|
|
|
+%! im = rand (40);
|
|
|
+%! assert (imcast (im, "uint8"), im2uint8 (im))
|
|
|
+
|
|
|
+%!error <unknown image of class> imcast (randi (127, 40, "int8"), "uint8")
|
|
|
+%!error <unsupported TYPE> imcast (randi (255, 40, "uint8"), "uint32")
|
|
|
+%!error <unsupported TYPE> imcast (randi (255, 40, "uint8"), "not a class")
|
|
|
+%!error <range of values> imcast (randi ([0 65535], 40, "uint16"), "uint8", "indexed")
|
|
|
+
|