1 ## Copyright (C) 2004 Josep Mones i Teixidor
3 ## This program is free software; you can redistribute it and/or modify
4 ## it under the terms of the GNU General Public License as published by
5 ## the Free Software Foundation; either version 2 of the License, or
6 ## (at your option) any later version.
8 ## This program is distributed in the hope that it will be useful,
9 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
10 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 ## GNU General Public License for more details.
13 ## You should have received a copy of the GNU General Public License
14 ## along with this program; If not, see <http://www.gnu.org/licenses/>.
17 ## @deftypefn {Function File} {[@var{Y}, @var{newmap}] = } cmunique (@var{X},@var{map})
18 ## @deftypefnx {Function File} {[@var{Y}, @var{newmap}] = } cmunique (@var{RGB})
19 ## @deftypefnx {Function File} {[@var{Y}, @var{newmap}] = } cmunique (@var{I})
20 ## Finds colormap with unique colors and corresponding image.
22 ## @code{[Y,newmap]=cmunique(X,map)} returns an indexed image @var{y}
23 ## along with its associated colormap @var{newmap} equivalent (which
24 ## produce the same image) to supplied @var{X} and its colormap
25 ## @var{map}; but eliminating any repeated rows in colormap colors and
26 ## adjusting indices in the image matrix as needed.
28 ## @code{[Y,newmap]=cmunique(RGB)} returns an indexed image @var{y}
29 ## along with its associated colormap @var{newmap} computed from a
30 ## true-color image @var{RGB} (a m-by-n-by-3 array), where @var{newmap}
31 ## is the smallest colormap possible (alhough it could be as long as
32 ## number of pixels in image).
34 ## @code{[Y,newmap]=cmunique(I)} returns an indexed image @var{y}
35 ## along with its associated colormap @var{newmap} computed from a
36 ## intensity image @var{I}, where @var{newmap} is the smallest
37 ## colormap possible (alhough it could be as long as number of pixels
42 ## @var{newmap} is always a @var{m}-by-3 matrix, even if input image is
43 ## a intensity grey-scale image @var{I} (all three RGB planes are
44 ## assigned the same value).
46 ## @var{newmap} is always of class double. If we use a RGB or intensity
47 ## image of class uint8 or uint16, the colors in the colormap will be of
48 ## class double in the range [0,1] (they are divided by intmax("uint8")
49 ## and intmax("uint16") respectively.
54 ## Author: Josep Mones i Teixidor <jmones@puntbarra.com>
56 function [Y, newmap] = cmunique(P1, P2)
57 if (nargin<1 || nargin>2)
58 usage("[Y, newmap] = cmunique(X, map), [Y, newmap] = cmunique(RGB), [Y, newmap] = cmunique(I)");
64 [newmap,i,j]=unique(P2,'rows'); ## calculate unique colormap
66 Y=j(P1); ## find new indices
68 Y=j(double(P1)+1); ## find new indices
74 [newmap,i,j]=unique(P1); ## calculate unique colormap
75 newmap=repmat(newmap,1,3); ## get a RGB colormap
76 Y=reshape(j,rows(P1),columns(P1)); ## Y is j reshaped
79 map=[P1(:,:,1)(:), P1(:,:,2)(:), P1(:,:,3)(:)]; ## build a map with all values
80 [newmap,i,j]=unique(map, 'rows'); ## calculate unique colormap
81 Y=reshape(j,rows(P1),columns(P1)); ## Y is j reshaped
83 error("cmunique: first parameter is invalid.");
86 ## if image was uint8 or uint16 we have to convert newmap to [0,1] range
88 newmap=double(newmap)/double(intmax(class(P1)));
93 ## convert Y to uint8 (0-based indices then)
102 %! [Y,newmap]=cmunique([1:4;5:8],[hot(4);hot(4)])
103 %! # Both rows are equal since map maps colors to the same value
104 %! # cmunique will give the same indices to both
107 %!# This triggers invalid first parameter
108 %!error(cmunique(zeros(3,3,2)));
110 %!# Check that output is uint8 in short colormaps
112 %! [Y,newmap]=cmunique([1:4;5:8], [hot(4);hot(4)]);
113 %! assert(Y,uint8([0:3;0:3]));
114 %! assert(newmap,hot(4));
116 %!# Check that output is double in bigger
118 %! [Y,newmap]=cmunique([1:300;301:600], [hot(300);hot(300)]);
119 %! assert(Y,[1:300;1:300]);
120 %! assert(newmap,hot(300));
122 %!# Check boundary case 256
124 %! [Y,newmap]=cmunique([1:256;257:512], [hot(256);hot(256)]);
125 %! assert(Y,uint8([0:255;0:255]));
126 %! assert(newmap,hot(256));
128 %!# Check boundary case 257
130 %! [Y,newmap]=cmunique([1:257;258:514], [hot(257);hot(257)]);
131 %! assert(Y,[1:257;1:257]);
132 %! assert(newmap,hot(257));
136 %! RGB=rand(10,10,3);
137 %! [Y,newmap]=cmunique(RGB);
138 %! assert(RGB(:,:,1),newmap(:,1)(Y+1));
139 %! assert(RGB(:,:,2),newmap(:,2)(Y+1));
140 %! assert(RGB(:,:,3),newmap(:,3)(Y+1));
142 %!# Random uint8 RGB image
144 %! RGB=uint8(rand(10,10,3)*255);
145 %! RGBd=double(RGB)/255;
146 %! [Y,newmap]=cmunique(RGB);
147 %! assert(RGBd(:,:,1),newmap(:,1)(Y+1));
148 %! assert(RGBd(:,:,2),newmap(:,2)(Y+1));
149 %! assert(RGBd(:,:,3),newmap(:,3)(Y+1));
151 %!# Random uint16 RGB image
153 %! RGB=uint16(rand(10,10,3)*65535);
154 %! RGBd=double(RGB)/65535;
155 %! [Y,newmap]=cmunique(RGB);
156 %! assert(RGBd(:,:,1),newmap(:,1)(Y+1));
157 %! assert(RGBd(:,:,2),newmap(:,2)(Y+1));
158 %! assert(RGBd(:,:,3),newmap(:,3)(Y+1));
163 %! [Y,newmap]=cmunique(I);
164 %! assert(I,newmap(:,1)(Y+1));
165 %! assert(I,newmap(:,2)(Y+1));
166 %! assert(I,newmap(:,3)(Y+1));
168 %!# Random uint8 I image
170 %! I=uint8(rand(10,10)*256);
172 %! [Y,newmap]=cmunique(I);
173 %! assert(Id,newmap(:,1)(Y+1));
174 %! assert(Id,newmap(:,2)(Y+1));
175 %! assert(Id,newmap(:,3)(Y+1));
177 %!# Random uint16 I image
179 %! I=uint16(rand(10,10)*65535);
180 %! Id=double(I)/65535;
181 %! [Y,newmap]=cmunique(I);
182 %! assert(Id,newmap(:,1)(Y+1));
183 %! assert(Id,newmap(:,2)(Y+1));
184 %! assert(Id,newmap(:,3)(Y+1));
188 % Revision 1.3 2007/03/23 16:14:36 adb014
189 % Update the FSF address
191 % Revision 1.2 2007/01/04 23:44:22 hauberg
192 % Minor changes in help text
194 % Revision 1.1 2006/08/20 12:59:32 hauberg
195 % Changed the structure to match the package system
197 % Revision 1.4 2004/09/08 16:06:31 jmones
198 % Solved problem with uint8 indexing and reduced tests on types (suggested by P. Kienzle)
200 % Revision 1.3 2004/09/03 17:07:26 jmones
201 % Support for uint8 and uint16 types added.
203 % Revision 1.2 2004/08/17 15:48:03 jmones
204 % Clarified expected data for RGB images in doc
206 % Revision 1.1 2004/08/17 15:45:40 jmones
207 % cmunique: Finds colormap with unique colors and corresponding image