# HG changeset patch # User Carnë Draug # Date 1395103873 0 # Node ID 40269ff6760d2a3675fb9e793c3f660be4bc7f7a # Parent 0ed283edee13a5c562b51521a457d5d996fcf022 imcast: new function to convert image between arbitrary classes. * imcast.m: new function acting as wrapper for im2double, im2single, im2uint8, im2uint16, and im2int16. * imcast.m, imnoise.m, imrotate.m: replace ugly hack using feval with call to imcast. * COPYING: specify license of new function. * INDEX: add new function. * NEWS: add note about new function for release 2.4.0. diff --git a/COPYING b/COPYING --- a/COPYING +++ b/COPYING @@ -73,6 +73,7 @@ inst/imadd.m GPLv3+ inst/imadjust.m GPLv3+ inst/imbothat.m GPLv3+ +inst/imcast.m GPLv3+ inst/imclose.m GPLv3+ inst/imcomplement.m GPLv3+ inst/imcrop.m GPLv3+ diff --git a/INDEX b/INDEX --- a/INDEX +++ b/INDEX @@ -133,6 +133,7 @@ im2single im2uint8 im2uint16 + imcast imdither isbw isgray diff --git a/NEWS b/NEWS --- a/NEWS +++ b/NEWS @@ -1,6 +1,10 @@ Summary of important user-visible changes for image 2.4.0 (yyyy/mm/dd): ------------------------------------------------------------------------- + ** The following functions are new: + + imcast + ** The implementation of normxcorr2 has been changed. The new method is Matlab compatible and will return values in the range [-1 1]. diff --git a/inst/imcast.m b/inst/imcast.m new file mode 100644 --- /dev/null +++ b/inst/imcast.m @@ -0,0 +1,90 @@ +## Copyright (C) 2014 Carnë Draug +## +## 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 . + +## -*- 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}. +## +## This is the same as calling one of the following +## +## @itemize @bullet +## @item im2double +## @item im2int16 +## @item im2single +## @item im2uint8 +## @item im2uint16 +## @end itemize +## +## @seealso{im2uint8, im2double, im2int16, im2single, im2uint16} +## @end deftypefn + +function img = imcast (img, itype, varargin) + + if (nargin < 2 || nargin > 3) + print_usage (); + elseif (nargin == 3 && ! strcmpi (varargin{1}, "indexed")) + error ("imcast: third argument must be the string \"indexed\""); + endif + + ## We could confirm that the image really is an indexed image in + ## case the user says so, but the functions im2xxx already do it. + + switch itype + case "double", img = im2double (img, varargin{:}); + case "uint8", img = im2uint8 (img, varargin{:}); + case "uint16", img = im2uint16 (img, varargin{:}); + case "single", img = im2single (img, varargin{:}); + case "int16", img = im2int16 (img, varargin{:}); + otherwise + error ("imcast: unsupported TYPE \"%s\"", itype); + endswitch + +endfunction + +%!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, "uint8", "indexed"), im2uint8 (im, "indexed")) +%! 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 imcast (randi (255, 40, "uint8"), "uint32") +%!error imcast (randi (255, 40, "uint8"), "not a class") + diff --git a/inst/imnoise.m b/inst/imnoise.m --- a/inst/imnoise.m +++ b/inst/imnoise.m @@ -105,16 +105,13 @@ endswitch if (fix_class) - ## we probably should do this in a safer way... but hardcoding the list of - ## im2xxxx functions might not be a good idea since it then it requires to - ## be added here if a new im2xxx function is implemented - A = feval (["im2" in_class], A); + A = imcast (A, in_class); elseif (isfloat (A)) ## this includes not even cases where the noise made it go outside of the ## [0 1] range, but also images that were already originally outside that ## range. This is by design and matlab compatibility. And we do this after - ## fixing class because the im2XX functions already take care of such - ## adjustemt + ## fixing class because the imcast functions already take care of such + ## adjustment A(A < 0) = cast (0, class (A)); A(A > 1) = cast (1, class (A)); endif diff --git a/inst/imrotate.m b/inst/imrotate.m --- a/inst/imrotate.m +++ b/inst/imrotate.m @@ -154,10 +154,7 @@ endif valid = NA; - ## we probably should do this in a safer way... but hardcoding the list of - ## im2xxxx functions might not be a good idea since it then it requires to - ## be added here if a new im2xxx function is implemented - imgPost = feval (["im2" in_class], imgPost); + imgPost = imcast (imgPost, in_class); else [imgPost, valid] = imperspectivewarp(imgPre, H, interp, bbox, extrapval); endif