## Copyright (C) 2004 Josep Mones i Teixidor ## ## 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 2 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, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{Y}, @var{newmap}] = } cmunique (@var{X},@var{map}) ## @deftypefnx {Function File} {[@var{Y}, @var{newmap}] = } cmunique (@var{RGB}) ## @deftypefnx {Function File} {[@var{Y}, @var{newmap}] = } cmunique (@var{I}) ## Finds colormap with unique colors and corresponding image ## ## @code{[Y,newmap]=cmunique(X,map)} returns an indexed image @var{y} ## along with its associated colormap @var{newmap} equivalent (which ## produce the same image) to supplied @var{X} and its colormap ## @var{map}; but eliminating any repeated rows in colormap colors and ## adjusting indices in the image matrix as needed. ## ## @code{[Y,newmap]=cmunique(RGB)} returns an indexed image @var{y} ## along with its associated colormap @var{newmap} computed from a ## true-color image @var{RGB} (a m-by-n-by-3 array), where @var{newmap} ## is the smallest colormap possible (alhough it could be as long as ## number of pixels in image). ## ## @code{[Y,newmap]=cmunique(I)} returns an indexed image @var{y} ## along with its associated colormap @var{newmap} computed from a ## intensity image @var{I}, where @var{newmap} is the smallest ## colormap possible (alhough it could be as long as number of pixels ## in image). ## ## @strong{Notes:} ## ## @var{newmap} is always a @var{m}-by-3 matrix, even if input image is ## a intensity grey-scale image @var{I} (all three RGB planes are ## assigned the same value). ## ## @var{newmap} is always of class double. If we use a RGB or intensity ## image of class uint8 or uint16, the colors in the colormap will be of ## class double in the range [0,1] (they are divided by intmax("uint8") ## and intmax("uint16") respectively. ## ## @end deftypefn ## Author: Josep Mones i Teixidor function [Y, newmap] = cmunique(P1, P2) if (nargin<1 || nargin>2) usage("[Y, newmap] = cmunique(X, map), [Y, newmap] = cmunique(RGB), [Y, newmap] = cmunique(I)"); endif if(nargin==2) ## (X, map) case [newmap,i,j]=unique(P2,'rows'); ## calculate unique colormap if(isa(P1,"double")) Y=j(P1); ## find new indices else Y=j(double(P1)+1); ## find new indices endif else switch(size(P1,3)) case(1) ## I case [newmap,i,j]=unique(P1); ## calculate unique colormap newmap=repmat(newmap,1,3); ## get a RGB colormap Y=reshape(j,rows(P1),columns(P1)); ## Y is j reshaped case(3) ## RGB case map=[P1(:,:,1)(:), P1(:,:,2)(:), P1(:,:,3)(:)]; ## build a map with all values [newmap,i,j]=unique(map, 'rows'); ## calculate unique colormap Y=reshape(j,rows(P1),columns(P1)); ## Y is j reshaped otherwise error("cmunique: first parameter is invalid."); endswitch ## if image was uint8 or uint16 we have to convert newmap to [0,1] range if(!isa(P1,"double")) newmap=double(newmap)/double(intmax(class(P1))); endif endif if(rows(newmap)<=256) ## convert Y to uint8 (0-based indices then) Y=uint8(Y-1); endif endfunction %!demo %! [Y,newmap]=cmunique([1:4;5:8],[hot(4);hot(4)]) %! # Both rows are equal since map maps colors to the same value %! # cmunique will give the same indices to both %!# This triggers invalid first parameter %!error(cmunique(zeros(3,3,2))); %!# Check that output is uint8 in short colormaps %!test %! [Y,newmap]=cmunique([1:4;5:8], [hot(4);hot(4)]); %! assert(Y,uint8([0:3;0:3])); %! assert(newmap,hot(4)); %!# Check that output is double in bigger %!test %! [Y,newmap]=cmunique([1:300;301:600], [hot(300);hot(300)]); %! assert(Y,[1:300;1:300]); %! assert(newmap,hot(300)); %!# Check boundary case 256 %!test %! [Y,newmap]=cmunique([1:256;257:512], [hot(256);hot(256)]); %! assert(Y,uint8([0:255;0:255])); %! assert(newmap,hot(256)); %!# Check boundary case 257 %!test %! [Y,newmap]=cmunique([1:257;258:514], [hot(257);hot(257)]); %! assert(Y,[1:257;1:257]); %! assert(newmap,hot(257)); %!# Random RGB image %!test %! RGB=rand(10,10,3); %! [Y,newmap]=cmunique(RGB); %! assert(RGB(:,:,1),newmap(:,1)(Y+1)); %! assert(RGB(:,:,2),newmap(:,2)(Y+1)); %! assert(RGB(:,:,3),newmap(:,3)(Y+1)); %!# Random uint8 RGB image %!test %! RGB=uint8(rand(10,10,3)*255); %! RGBd=double(RGB)/255; %! [Y,newmap]=cmunique(RGB); %! assert(RGBd(:,:,1),newmap(:,1)(Y+1)); %! assert(RGBd(:,:,2),newmap(:,2)(Y+1)); %! assert(RGBd(:,:,3),newmap(:,3)(Y+1)); %!# Random uint16 RGB image %!test %! RGB=uint16(rand(10,10,3)*65535); %! RGBd=double(RGB)/65535; %! [Y,newmap]=cmunique(RGB); %! assert(RGBd(:,:,1),newmap(:,1)(Y+1)); %! assert(RGBd(:,:,2),newmap(:,2)(Y+1)); %! assert(RGBd(:,:,3),newmap(:,3)(Y+1)); %!# Random I image %!test %! I=rand(10,10); %! [Y,newmap]=cmunique(I); %! assert(I,newmap(:,1)(Y+1)); %! assert(I,newmap(:,2)(Y+1)); %! assert(I,newmap(:,3)(Y+1)); %!# Random uint8 I image %!test %! I=uint8(rand(10,10)*256); %! Id=double(I)/255; %! [Y,newmap]=cmunique(I); %! assert(Id,newmap(:,1)(Y+1)); %! assert(Id,newmap(:,2)(Y+1)); %! assert(Id,newmap(:,3)(Y+1)); %!# Random uint16 I image %!test %! I=uint16(rand(10,10)*65535); %! Id=double(I)/65535; %! [Y,newmap]=cmunique(I); %! assert(Id,newmap(:,1)(Y+1)); %! assert(Id,newmap(:,2)(Y+1)); %! assert(Id,newmap(:,3)(Y+1)); % % $Log: cmunique.m,v $ % Revision 1.4 2004/09/08 16:06:31 jmones % Solved problem with uint8 indexing and reduced tests on types (suggested by P. Kienzle) % % Revision 1.3 2004/09/03 17:07:26 jmones % Support for uint8 and uint16 types added. % % Revision 1.2 2004/08/17 15:48:03 jmones % Clarified expected data for RGB images in doc % % Revision 1.1 2004/08/17 15:45:40 jmones % cmunique: Finds colormap with unique colors and corresponding image % %