Mercurial > hg > octave-nkf
comparison scripts/image/gray2ind.m @ 15693:a1b634240352
maint: merge default into image-overhaul head, specially changeset 806ea52. Resolving many conflicts and fixing bugs related to correctly indexing on image class (float vs integer have different offset)
author | Carnë Draug <carandraug+dev@gmail.com> |
---|---|
date | Wed, 28 Nov 2012 06:01:09 +0100 |
parents | dffb28f47ea8 806ea52af230 |
children | b1cd65881592 |
comparison
equal
deleted
inserted
replaced
15692:37a21f615d67 | 15693:a1b634240352 |
---|---|
15 ## You should have received a copy of the GNU General Public License | 15 ## You should have received a copy of the GNU General Public License |
16 ## along with Octave; see the file COPYING. If not, see | 16 ## along with Octave; see the file COPYING. If not, see |
17 ## <http://www.gnu.org/licenses/>. | 17 ## <http://www.gnu.org/licenses/>. |
18 | 18 |
19 ## -*- texinfo -*- | 19 ## -*- texinfo -*- |
20 ## @deftypefn {Function File} {[@var{img} =} gray2ind (@var{I}) | 20 ## @deftypefn {Function File} {@var{img} =} gray2ind (@var{I}) |
21 ## @deftypefnx {Function File} {[@var{img} =} gray2ind (@var{I}, @var{n}) | 21 ## @deftypefnx {Function File} {@var{img} =} gray2ind (@var{I}, @var{n}) |
22 ## @deftypefnx {Function File} {[@var{img}, @var{map} =} gray2ind (@dots{}) | 22 ## @deftypefnx {Function File} {@var{img} =} gray2ind (@var{BW}) |
23 ## Convert a gray scale or binary image to an indexed image. | 23 ## @deftypefnx {Function File} {@var{img} =} gray2ind (@var{BW}, @var{n}) |
24 ## @deftypefnx {Function File} {[@var{img}, @var{map}] =} gray2ind (@dots{}) | |
25 ## Convert a grayscale or binary intensity image to an indexed image. | |
26 ## | |
27 ## The indexed image will consist of @var{n} different intensity values. | |
28 ## If not given @var{n} defaults to 64 for grayscale images or 2 for | |
29 ## binary black and white images. | |
24 ## | 30 ## |
25 ## The indexed image will consist of @var{n} different intensity values. | 31 ## The output @var{img} is of class uint8 or uint 16 if @var{n} is less than or |
26 ## If not given @var{n} defaults to 64 and 2 for gray scale and binary images | 32 ## equal to 256 or 65536 respectively. Otherwise, the output is of class double. |
27 ## respectively. Its class will be uint8, uint16 or double in order of which | 33 ## @seealso{ind2gray, rgb2ind} |
28 ## one is necessary to fit @var{n} different intensities. | |
29 ## | |
30 ## @seealso{ind2gray, rgb2ind} | |
31 ## @end deftypefn | 34 ## @end deftypefn |
32 | 35 |
33 ## Author: Tony Richardson <arichard@stark.cc.oh.us> | 36 ## Author: Tony Richardson <arichard@stark.cc.oh.us> |
34 ## Created: July 1994 | 37 ## Created: July 1994 |
35 ## Adapted-By: jwe | 38 ## Adapted-By: jwe |
36 | 39 |
37 function [X, map] = gray2ind (I, n = 64) | 40 function [I, map] = gray2ind (I, n = 64) |
38 ## Check input | 41 |
39 if (nargin < 1 || nargin > 2) | 42 if (nargin < 1 || nargin > 2) |
40 print_usage (); | 43 print_usage (); |
44 elseif (! isreal (I) || issparse (I)) | |
45 error ("gray2ind: I must be a grayscale or binary image"); | |
46 elseif (! isscalar (n) || n < 1 || n > 65536) | |
47 error ("gray2ind: N must be a positive integer in the range [1, 65536]"); | |
48 elseif (! ismatrix (I) || ndims (I) != 2) | |
49 error ("gray2ind: first input argument must be a gray scale image"); | |
41 endif | 50 endif |
42 | 51 |
43 ## default n is different if image is logical | 52 ## default n is different if image is logical |
44 if (nargin < 2 && isa (I, "logical")) | 53 if (nargin == 1 && islogical (I)) |
45 n = 2; | 54 n = 2; |
46 endif | 55 endif |
47 | 56 |
48 C = class (I); | |
49 if (! ismatrix (I) || ndims (I) != 2) | |
50 error ("gray2ind: first input argument must be a gray scale image"); | |
51 endif | |
52 if (! isscalar (n) || n < 0) | 57 if (! isscalar (n) || n < 0) |
53 error ("gray2ind: second input argument must be a positive integer"); | 58 error ("gray2ind: second input argument must be a positive integer"); |
54 endif | 59 endif |
55 ints = {"uint8", "uint16", "int8", "int16"}; | 60 |
56 floats = {"double", "single"}; | 61 cls = class (I); |
57 if (! ismember (C, {ints{:}, floats{:}, "logical"})) | 62 if (! any (isa (I, {"logical", "uint8", "uint16", "int16", "single", "double"}))) |
58 error ("gray2ind: invalid data type '%s'", C); | 63 error ("gray2ind: invalid data type '%s'", cls); |
59 endif | 64 elseif (isfloat (I) && (min (I(:) < 0) || max (I(:) > 1))) |
60 if (ismember (C, floats) && (min (I(:)) < 0 || max (I(:)) > 1)) | |
61 error ("gray2ind: floating point images may only contain values between 0 and 1"); | 65 error ("gray2ind: floating point images may only contain values between 0 and 1"); |
62 endif | 66 endif |
63 | 67 |
64 ## Convert data | |
65 map = gray (n); | 68 map = gray (n); |
66 ## If @var{I} is an integer matrix convert it to a double matrix with values in [0, 1] | 69 |
67 if (ismember (C, ints)) | 70 ## Set up scale factor |
68 low = double (intmin (C)); | 71 if (isinteger (I)) |
69 high = double (intmax (C)); | 72 low = double (intmin (cls)); |
70 I = (double (I) - low) / (high - low); | 73 scale = double (intmax (cls)) - low; |
74 I = double (I) - low; | |
75 else | |
76 scale = 1; | |
71 endif | 77 endif |
72 X = round (I*(n-1)); | 78 ## Note: no separate call to round () necessary because |
79 ## type conversion does that automatically. | |
80 I = I * ((n-1)/scale); | |
73 if (n < 256) | 81 if (n < 256) |
74 X = uint8 (X); | 82 I = uint8 (I); |
75 elseif (n < 65536) | 83 elseif (n < 65536) |
76 X = uint16 (X); | 84 I = uint16 (I); |
77 else | 85 else |
78 ## if uint16 is not enough, we return double in which case there's no 0 | 86 ## if uint16 is not enough, we return double in which case index |
79 X += 1; | 87 ## values should start at 1. |
88 I = round (I) + 1; | |
80 endif | 89 endif |
81 endfunction | 90 endfunction |
91 | |
92 %!assert (gray2ind ([0 0.25 0.5 1]), uint8 ([0 16 32 63])) | |
93 %!assert (gray2ind ([0 0.25 0.5 1], 400), uint16 ([0 100 200 399])) | |
94 %!assert (gray2ind (logical ([1 0 0 1])), uint8 ([1 0 0 1])) | |
95 %!assert (gray2ind (uint8 ([0 64 128 192 255])), uint8 ([0 16 32 47 63])) | |
96 | |
97 %!test | |
98 %! i2g = ind2gray (1:100, gray (100)); | |
99 %! g2i = gray2ind (i2g, 100); | |
100 %! assert (g2i, uint8 (0:99)); | |
101 | |
102 %% Test input validation | |
103 %!error gray2ind () | |
104 %!error gray2ind (1,2,3) | |
105 %!error <I must be a grayscale or binary image> gray2ind ({1}) | |
106 %!error <I must be a grayscale or binary image> gray2ind ([1+i]) | |
107 %!error <I must be a grayscale or binary image> gray2ind (sparse ([1])) | |
108 %!error <N must be a positive integer> gray2ind (1, ones (2,2)) | |
109 %!error <N must be a positive integer> gray2ind (1, 0) | |
110 %!error <N must be a positive integer> gray2ind (1, 65537) | |
111 %!error <invalid data type> gray2ind (uint32 (1)) | |
112 %!error <values between 0 and 1> gray2ind (-1) | |
113 %!error <values between 0 and 1> gray2ind (2) | |
114 |