1## Copyright (C) 2014 Carnë Draug <carandraug+dev@gmail.com> 2## 3## This program is free software; you can redistribute it and/or modify it under 4## the terms of the GNU General Public License as published by the Free Software 5## Foundation; either version 3 of the License, or (at your option) any later 6## version. 7## 8## This program is distributed in the hope that it will be useful, but WITHOUT 9## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 11## details. 12## 13## You should have received a copy of the GNU General Public License along with 14## this program; if not, see <http://www.gnu.org/licenses/>. 15 16## -*- texinfo -*- 17## @deftypefn {Function File} {} imcast (@var{img}, @var{type}) 18## @deftypefnx {Function File} {} imcast (@var{img}, @var{type}, "indexed") 19## Convert image to specific data type @var{type}. 20## 21## Converts a valid image @var{img} into another class @var{type}. A valid 22## image must be of class logical, uint8, uint16, int16, single, or double. 23## 24## If the image is indexed, the last argument may be the string 25## @qcode{"indexed"}. An indexed image may not be of class int16, 26## single, or logical (see @code{isind} for details). 27## 28## Details on how the conversion is performed is class dependent, and 29## can be seen on the help text of @code{im2double}, @code{im2single}, 30## @code{im2uint8}, @code{im2uint16}, and @code{im2int16}. For the 31## case of logical, conversion to logical is equivalent to simply 32## casting @var{img} to logical data type. Conversion from logical, 33## true elements are converted to 1 in the case of floating point, or 34## the maximum value in the case of integer types. 35## 36## @seealso{im2bw, im2uint8, im2double, im2int16, im2single, im2uint16} 37## @end deftypefn 38 39function imout = imcast (img, outcls, varargin) 40 41 if (nargin < 2 || nargin > 3) 42 print_usage (); 43 elseif (nargin == 3 && ! strcmpi (varargin{1}, "indexed")) 44 error ("imcast: third argument must be the string \"indexed\""); 45 endif 46 47 incls = class (img); 48 if (strcmp (outcls, incls)) 49 imout = img; 50 return 51 endif 52 53 ## we are dealing with indexed images 54 if (nargin == 3) 55 if (! isind (img)) 56 error ("imcast: input should have been an indexed image but it is not."); 57 endif 58 59 ## Check that the new class is enough to hold all the previous indices 60 ## If we are converting to floating point, then we don't bother 61 ## check the range of indices. Also, note that indexed images of 62 ## integer class are always unsigned. 63 64 ## we will be converting a floating point image to integer class 65 if (strcmp (outcls, "single") || strcmp (outcls, "double")) 66 if (isinteger (img)) 67 imout = cast (img, outcls) +1; 68 else 69 imout = cast (img, outcls); 70 endif 71 72 ## we will be converting an indexed image to integer class 73 else 74 if (isinteger (img) && intmax (incls) > intmax (outcls) && max (img(:)) > intmax (outcls)) 75 error ("imcast: IMG has too many colours '%d' for the range of values in %s", 76 max (img(:)), outcls); 77 elseif (isfloat (img)) 78 imax = max (img(:)) -1; 79 if (imax > intmax (outcls)) 80 error ("imcast: IMG has too many colours '%d' for the range of values in %s", 81 imax, outcls); 82 endif 83 img -= 1; 84 endif 85 imout = cast (img, outcls); 86 endif 87 88 ## we are dealing with "normal" images 89 else 90 problem = false; # did we found a bad conversion? 91 switch (incls) 92 93 case {"double", "single"} 94 switch (outcls) 95 case "uint8", imout = uint8 (img * 255); 96 case "uint16", imout = uint16 (img * 65535); 97 case "int16", imout = int16 (double (img * uint16 (65535)) -32768); 98 case {"double", "single"}, imout = cast (img, outcls); 99 case "logical", imout = logical (img); 100 otherwise, problem = true; 101 endswitch 102 103 case {"uint8"} 104 switch (outcls) 105 case "double", imout = double (img) / 255; 106 case "single", imout = single (img) / 255; 107 case "uint16", imout = uint16 (img) * 257; # 257 comes from 65535/255 108 case "int16", imout = int16 ((double (img) * 257) -32768); # 257 comes from 65535/255 109 case "logical", imout = logical (img); 110 otherwise, problem = true; 111 endswitch 112 113 case {"uint16"} 114 switch (outcls) 115 case "double", imout = double (img) / 65535; 116 case "single", imout = single (img) / 65535; 117 case "uint8", imout = uint8 (img / 257); # 257 comes from 65535/255 118 case "int16", imout = int16 (double (img) -32768); 119 case "logical", imout = logical (img); 120 otherwise, problem = true; 121 endswitch 122 123 case {"logical"} 124 switch (outcls) 125 case {"double", "single"} 126 imout = cast (img, outcls); 127 case {"uint8", "uint16", "int16"} 128 imout = repmat (intmin (outcls), size (img)); 129 imout(img) = intmax (outcls); 130 otherwise 131 problem = true; 132 endswitch 133 134 case {"int16"} 135 switch (outcls) 136 case "double", imout = (double (img) + 32768) / 65535; 137 case "single", imout = (single (img) + 32768) / 65535; 138 case "uint8", imout = uint8 ((double (img) + 32768) / 257); # 257 comes from 65535/255 139 case "uint16", imout = uint16 (double (img) + 32768); 140 case "logical", imout = logical (img); 141 otherwise, problem = true; 142 endswitch 143 144 otherwise 145 error ("imcast: unknown image of class \"%s\"", incls); 146 147 endswitch 148 if (problem) 149 error ("imcast: unsupported TYPE \"%s\"", outcls); 150 endif 151 endif 152 153endfunction 154 155%!test 156%! im = randi ([0 255], 40, "uint8"); 157%! assert (imcast (im, "uint8"), im2uint8 (im)) 158%! assert (imcast (im, "uint16"), im2uint16 (im)) 159%! assert (imcast (im, "single"), im2single (im)) 160%! assert (imcast (im, "uint8", "indexed"), im2uint8 (im, "indexed")) 161%! assert (imcast (im, "uint16", "indexed"), im2uint16 (im, "indexed")) 162%! assert (imcast (im, "single", "indexed"), im2single (im, "indexed")) 163 164%!test 165%! im = randi ([1 256], 40, "double"); 166%! assert (imcast (im, "uint8"), im2uint8 (im)) 167%! assert (imcast (im, "uint8", "indexed"), im2uint8 (im, "indexed")) 168%! assert (imcast (im, "single", "indexed"), im2single (im, "indexed")) 169 170%!test 171%! im = randi ([0 65535], 40, "uint16"); 172%! assert (imcast (im, "uint8"), im2uint8 (im)) 173%! assert (imcast (im, "single"), im2single (im)) 174%! assert (imcast (im, "single", "indexed"), im2single (im, "indexed")) 175 176%!test 177%! im = randi ([1 255], 40, "double"); 178%! assert (imcast (im, "uint8", "indexed"), im2uint8 (im, "indexed")) 179%! assert (imcast (im, "single", "indexed"), im2single (im, "indexed")) 180 181%!test 182%! im = rand (40); 183%! assert (imcast (im, "uint8"), im2uint8 (im)) 184 185%!error <unknown image of class> imcast (randi (127, 40, "int8"), "uint8") 186%!error <unsupported TYPE> imcast (randi (255, 40, "uint8"), "uint32") 187%!error <unsupported TYPE> imcast (randi (255, 40, "uint8"), "not a class") 188%!error <range of values> imcast (randi ([0 65535], 40, "uint16"), "uint8", "indexed") 189 190%!assert (imcast ([0 1 .2; 2 -0 Inf], "logical"), logical ([0 1 1; 1 0 1])) 191