imcast.m 6.7 KB

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