Mercurial > hg > octave-image
changeset 866:2d08c21bbec7 stable
Compute complement of signed integers correctly.
* imcomplement.m: signed integers require handling different from unsigned
integers. Also, remove unecessary ismatrix check, add tests, expand on
documentation.
* NEWS: add this to the NEWS for the next patch release.
author | Carnë Draug <carandraug@octave.org> |
---|---|
date | Fri, 31 Jan 2014 21:09:12 +0000 |
parents | a17b71b7e407 |
children | 6f961cf68af0 |
files | NEWS inst/imcomplement.m |
diffstat | 2 files changed, 62 insertions(+), 19 deletions(-) [+] |
line wrap: on
line diff
--- a/NEWS +++ b/NEWS @@ -8,6 +8,8 @@ for the cropping in addition to the cropped image. It will no longer loop forever until it gets two valid coordinates for the bounding box. + ** Fixed bug in imcomplement to compute the complement of signed integers + correctly. Summary of important user-visible changes for image 2.2.0 (2014/01/08): -------------------------------------------------------------------------
--- a/inst/imcomplement.m +++ b/inst/imcomplement.m @@ -1,4 +1,5 @@ ## Copyright (C) 2008 Søren Hauberg <soren@hauberg.org> +## Copyright (C) 2014 Carnë Draug <carandraug@octave.org> ## ## 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 @@ -14,33 +15,73 @@ ## this program; if not, see <http://www.gnu.org/licenses/>. ## -*- texinfo -*- -## @deftypefn {Function File} @var{B} = imcomplement(@var{A}) -## Computes the complement image. Intuitively this corresponds to the intensity -## of bright and dark regions being reversed. +## @deftypefn {Function File} {} imcomplement (@var{A}) +## Compute image complement or negative. +## +## Intuitively this corresponds to the intensity of bright and dark +## regions being reversed. The exact operation performed is dependent +## on the class of the image. ## -## For binary images, the complement is computed as @code{!@var{A}}, for floating -## point images it is computed as @code{1 - @var{A}}, and for integer images as -## @code{intmax(class(@var{A})) - @var{A}}. +## @table @asis +## @item floating point +## Since floating point images are meant to have values in the range [0 1], +## this is equivalent @code{A -1}. This leads to values within the range +## to be inverted while others to equally distance from the limits. +## +## @item logical +## Equivalent to @code{! A} +## +## @item integer +## Inverts the values within the range of the data. This is a different +## depending whether it's signed or unsigned integers class. +## @end table +## ## @seealso{imadd, imdivide, imlincomb, immultiply, imsubtract} ## @end deftypefn -function B = imcomplement(A) - ## Check input +function B = imcomplement (A) + if (nargin != 1) - error("imcomplement: not enough input arguments"); - endif - if (!ismatrix(A)) - error("imcomplement: input must be an array"); + print_usage (); endif - ## Take action depending on the class of A - if (isa(A, "double") || isa(A, "single")) + if (isfloat (A)) B = 1 - A; - elseif (islogical(A)) - B = !A; - elseif (isinteger(A)) - B = intmax(class(A)) - A; + elseif (islogical (A)) + B = ! A; + elseif (any (isa (A, {"int8", "int16", "int32", "int64"}))) + ## Signed integers are different. We have all this extra work to avoid + ## conversion into another class which may not fit in memory. And seems + ## like it it still performs faster. + cl = class (A); + B = zeros (size (A), cl); + m = (A != intmin (cl)); + + B(! m) = intmax (cl); + B(m) = -A -1; + + elseif (isinteger (A)) + B = intmax (class (A)) - A; else - error("imcomplement: unsupported input class: '%s'", class(A)); + error("imcomplement: A must be an image but is of class `%s'", class (A)); endif + endfunction + +%!assert (imcomplement (10), -9); +%!assert (imcomplement (single (10)), single (-9)); +%!assert (imcomplement (0.2), 0.8); +%!assert (imcomplement (uint8 (0)), uint8 (255)); +%!assert (imcomplement (uint8 (1)), uint8 (254)); +%!assert (imcomplement (uint16 (0)), uint16 (65535)); +%!assert (imcomplement (uint16 (1)), uint16 (65534)); + +%!assert (imcomplement (int8 (-128)), int8 ( 127)); +%!assert (imcomplement (int8 ( 127)), int8 (-128)); +%!assert (imcomplement (int16 (-1)), int16 ( 0)); +%!assert (imcomplement (int16 ( 0)), int16 (-1)); +%!assert (imcomplement (int16 ( 1)), int16 (-2)); + +%!assert (imcomplement ([true false true]), [false true false]) + +%!error <must be an image> imcomplement ("not an image")