Home > voicebox > v_colormap.m

v_colormap

PURPOSE ^

V_COLORMAP set and plot color map

SYNOPSIS ^

function [rgb,y,l]=v_colormap(map,m,n,p)

DESCRIPTION ^

V_COLORMAP set and plot color map

   Usage: (1) v_colormap([],'g'); % plot the current color map
          (2) v_colormap([],'',256); % intepolate the current color map to 256 entries
          (3) v_colormap('copper','y'); % make copper color map linear in luminance
          (4) v_colormap('copper','L'); % make copper color map linear in lightness^2

  Inputs:
           map  Either an (r,3) array specifying the RGB colourmap entries
                or else a string specifying a bult-in colour map. Use []
                to leave the colour map unchanged.
                Standard maps are:
                   'Jet','HSV','Hot','Cool','Spring','Summer','Autumn',
                   'Winter','Gray','Bone','Copper','Pink','Lines','Parula'
                Additional maps, all with 64 entries, are:
                   'v_thermliny'  thermal scale that is linear in luminance
                                  Varies from black through blue, red, yellow to white.
                                  Luminance varies linearly from black to white.
                   'v_bipliny'    bipolar scale that is linear in luminance
                                  Negative values are blue/turquoise and postive value are orange/yellow.
                                  Luminance varies linearly from black to white with zero at 50.8% gray.
                   'v_bipveey'    bipolar scale that is V-shaped in luminance
                                  Negative values are blue/turqoise and positive values are red/yellow.
                                  Luminance is proportional to absolute value with zero=black.
                For the two bipolar scales, zero corresponds to entry 33 and so the range of values
                is -32:31 or, equivalently, either -1 to +0.96875 or -1.0323 to +1.

             m  Mode string:
                   'g' to plot information about the color map
                   'y' to force luminance^p to be linear or V-shaped (two linear segments)
                   'l' to force lightness^p to be linear or V-shaped (two linear segments)
                   'Y' like 'y' but with default p=0.667
                   'L' like 'l' but with default p=2
                   'f' flips the map to reverse its order
                   'b' make maximum luminance 0.05 (or 0.1 for 'B')
                   'w' make maximum luminance 0.95 (or 0.9 for 'W')

             n  the number of entries in the colourmap or the number in
                each linearly-interpolated segment excluding the entry shared
                with the previous segment. The total number of entries is n=sum(n).
                For modes 'y','Y','l','L' the number of segments must be 1
                or 2; otherwise the number of segments must be 1 or r-1.

             p  power law to use for linearized luminance or lightness [default p=1]
                see the description of 'y' and 'l' for its effect

 Outputs:
           rgb  RGB color map entries; one per row.
                All values will be in the range 0 to 1

             y  column vector of luminance values

             l  column vector of lightness values (lightness is the perceived brightness)

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function [rgb,y,l]=v_colormap(map,m,n,p)
0002 %V_COLORMAP set and plot color map
0003 %
0004 %   Usage: (1) v_colormap([],'g'); % plot the current color map
0005 %          (2) v_colormap([],'',256); % intepolate the current color map to 256 entries
0006 %          (3) v_colormap('copper','y'); % make copper color map linear in luminance
0007 %          (4) v_colormap('copper','L'); % make copper color map linear in lightness^2
0008 %
0009 %  Inputs:
0010 %           map  Either an (r,3) array specifying the RGB colourmap entries
0011 %                or else a string specifying a bult-in colour map. Use []
0012 %                to leave the colour map unchanged.
0013 %                Standard maps are:
0014 %                   'Jet','HSV','Hot','Cool','Spring','Summer','Autumn',
0015 %                   'Winter','Gray','Bone','Copper','Pink','Lines','Parula'
0016 %                Additional maps, all with 64 entries, are:
0017 %                   'v_thermliny'  thermal scale that is linear in luminance
0018 %                                  Varies from black through blue, red, yellow to white.
0019 %                                  Luminance varies linearly from black to white.
0020 %                   'v_bipliny'    bipolar scale that is linear in luminance
0021 %                                  Negative values are blue/turquoise and postive value are orange/yellow.
0022 %                                  Luminance varies linearly from black to white with zero at 50.8% gray.
0023 %                   'v_bipveey'    bipolar scale that is V-shaped in luminance
0024 %                                  Negative values are blue/turqoise and positive values are red/yellow.
0025 %                                  Luminance is proportional to absolute value with zero=black.
0026 %                For the two bipolar scales, zero corresponds to entry 33 and so the range of values
0027 %                is -32:31 or, equivalently, either -1 to +0.96875 or -1.0323 to +1.
0028 %
0029 %             m  Mode string:
0030 %                   'g' to plot information about the color map
0031 %                   'y' to force luminance^p to be linear or V-shaped (two linear segments)
0032 %                   'l' to force lightness^p to be linear or V-shaped (two linear segments)
0033 %                   'Y' like 'y' but with default p=0.667
0034 %                   'L' like 'l' but with default p=2
0035 %                   'f' flips the map to reverse its order
0036 %                   'b' make maximum luminance 0.05 (or 0.1 for 'B')
0037 %                   'w' make maximum luminance 0.95 (or 0.9 for 'W')
0038 %
0039 %             n  the number of entries in the colourmap or the number in
0040 %                each linearly-interpolated segment excluding the entry shared
0041 %                with the previous segment. The total number of entries is n=sum(n).
0042 %                For modes 'y','Y','l','L' the number of segments must be 1
0043 %                or 2; otherwise the number of segments must be 1 or r-1.
0044 %
0045 %             p  power law to use for linearized luminance or lightness [default p=1]
0046 %                see the description of 'y' and 'l' for its effect
0047 %
0048 % Outputs:
0049 %           rgb  RGB color map entries; one per row.
0050 %                All values will be in the range 0 to 1
0051 %
0052 %             y  column vector of luminance values
0053 %
0054 %             l  column vector of lightness values (lightness is the perceived brightness)
0055 
0056 % Bugs/Suggestions:
0057 % (1) add option to exclude black from the colormap
0058 
0059 %      Copyright (C) Mike Brookes 2012
0060 %      Version: $Id: v_colormap.m 7758 2016-04-12 07:11:33Z dmb $
0061 %
0062 %   VOICEBOX is a MATLAB toolbox for speech processing.
0063 %   Home page: http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html
0064 %
0065 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0066 %   This program is free software; you can redistribute it and/or modify
0067 %   it under the terms of the GNU General Public License as published by
0068 %   the Free Software Foundation; either version 2 of the License, or
0069 %   (at your option) any later version.
0070 %
0071 %   This program is distributed in the hope that it will be useful,
0072 %   but WITHOUT ANY WARRANTY; without even the implied warranty of
0073 %   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0074 %   GNU General Public License for more details.
0075 %
0076 %   You can obtain a copy of the GNU General Public License from
0077 %   http://www.gnu.org/copyleft/gpl.html or by writing to
0078 %   Free Software Foundation, Inc.,675 Mass Ave, Cambridge, MA 02139, USA.
0079 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0080 persistent maps nams mcal modes nszs pows la lb lc lci laci lk lq yv
0081 if isempty(maps)
0082     lk=(6/29)^3;
0083     la=841/108;
0084     lb=4/29;
0085     lc=1.16;
0086     lq=la*lc*lk;
0087     lci=1/lc;
0088     laci=lci/la;
0089     %     yv=inv([1.0 0.956 0.621; 1.0 -0.272 -0.647; 1.0 -1.106 1.703]);
0090     %     yv=yv(:,1);
0091     yv=[0.2126; 0.7152; 0.0722];
0092     nams={'v_thermliny','v_bipliny','v_bipveey'};
0093     % modified thermal with better grayscale linearity
0094     mcal=[1 1 1]; % +1 if need to calculate maps entry
0095     modes={'y' 'y' 'y'}; % modes for map calculation
0096     nszs={64 64 [33 31]};  % sizes for maps
0097     pows=[1 1 1];  % powers for maps
0098     maps{1}=[0 0 0; 72 0 167; 252 83 16; 255 249 0; 255 255 255]/255;
0099     % bipolar map with grayscale linearity
0100     maps{2}=[0 0 0; 0 2 203; 1 101 226; 128 128 128; 252 153 12; 252 245 0; 252 249 18; 252 252 252]/252;
0101     maps{3}=[0 0.95 1; 0 0 0.9; 0 0 0; 0.5 0 0; 0.80 0.78 0];
0102 end
0103 if nargin<2
0104     m='';
0105 end
0106 if nargin<4
0107     if any(m=='Y')
0108         p=2/3;
0109     elseif any(m=='L')
0110         p=2;
0111     else
0112         p=1;  % power to raise lightness/luminance to
0113     end
0114 end
0115 pr=1/p;
0116 um=m;
0117 m=lower(m);   % convert mode letters to lower case
0118 gotmap= nargin==0 || numel(map)==0;   % already got the map
0119 if ~gotmap && ischar(map)   % if map given as a string
0120     ix=find(strcmpi(map,nams),1); % check if it is one of ours
0121     if numel(ix)
0122         if mcal(ix)  % need to calculate the map the first time around
0123             maps{ix}=v_colormap(maps{ix},modes{ix},nszs{ix},pows(ix));
0124             mcal(ix)=0;  % don't calculate it again
0125         end
0126         colormap(maps{ix});
0127     else
0128         colormap(map); % not one of ours - just pass it on to standard colormap function
0129     end
0130     gotmap=1;
0131 end
0132 if any(m=='y') ||  any(m=='l') || (nargin>2 && numel(n)>0) % need to do linear interpolation
0133     if gotmap
0134         map=colormap;  % linearly interpolate the existing map
0135     end
0136     nm=size(map,1);
0137     if any(m=='y') ||  any(m=='l')
0138         y=map*yv;  % convert map to luminance
0139         up=y(2:nm)>y(1:nm-1); % find increasing
0140         ex=up(1:nm-2)~=up(2:nm-1); % +1 for a peak or valley
0141         yd=2*up(1)-1; % +1 if y initially increasing
0142         switch sum(ex)
0143             case 0 % monotonic
0144                 if nargin<3
0145                     r=nm;
0146                 else
0147                     r=n(1);
0148                 end
0149                 if any(m=='y')
0150                     l=y([1 nm]).^p;
0151                     tt=(l(1)+(0:r-1)'*(l(2)-l(1))/(r-1)).^pr; % target luminances
0152                 else
0153                     tt=y([1 nm]');
0154                     l=(lc*(la*tt+(tt>lk).*(tt.^(1/3)-la*tt-lb))).^p;
0155                     tt=(l(1)+(0:r-1)'*(l(2)-l(1))/(r-1)).^pr; % target lightnesses
0156                     tt=laci*tt+(tt>lq).*((lci*tt+lb).^3-laci*tt); % target luminances
0157                 end
0158                 [ss,ix]=sort([tt;y]*yd);
0159             case 1 % V-shaped
0160                 ipk=find(ex,1)+1;  % position of peak/valley in y
0161                 if nargin<3
0162                     n=[ipk nm-ipk];  % size of linear segments
0163                 end
0164                 r=n(1)+n(2);  % total size of map
0165                 if any(m=='y')
0166                     l=y([1 ipk nm]).^p;
0167                     tt=(l(2)+[(1-n(1):0)*(l(2)-l(1))/(n(1)-1) (1:n(2))*(l(3)-l(2))/(n(2))]').^pr; % target luminances
0168                 else
0169                     tt=y([1 ipk nm]');
0170                     l=(lc*(la*tt+(tt>lk).*(tt.^(1/3)-la*tt-lb))).^p;
0171                     tt=(l(2)+[(1-n(1):0)*(l(2)-l(1))/(n(1)-1) (1:n(2))*(l(3)-l(2))/(n(2))]').^pr; % target lightnesses
0172                     tt=laci*tt+(tt>lq).*((lci*tt+lb).^3-laci*tt); % target luminances
0173                 end
0174                 [ss,ix]=sort([tt(1:n(1))-y(ipk); y(ipk)-tt(n(1)+1:r);y(1:ipk)-y(ipk); y(ipk)-y(ipk+1:nm)]*yd);
0175             otherwise
0176                 error('luminance has more than two monotonic segments');
0177         end
0178     else                % just linearly interpolate the given values
0179         if numel(n)==nm-1
0180             r=sum(n);
0181             y=[1;cumsum(n(:))];
0182         else
0183             r=n(1);
0184             y=1+(0:nm-1)'*(r-1)/(nm-1);
0185         end
0186         tt=(1:r)';
0187         [ss,ix]=sort([tt;y]);
0188     end
0189     jx=zeros(size(ix));
0190     jx(ix)=1:numel(jx);
0191     jx=min(max(jx(1:r)-(1:r)',1),nm-1);
0192     al=(tt-y(jx))./(y(jx+1)-y(jx)); % fraction of upper sample to include
0193     map=map(jx,:)+(map(jx+1,:)-map(jx,:)).*al(:,ones(1,3));
0194     colormap(map);
0195     gotmap=1;
0196 end
0197 if ~gotmap
0198     colormap(map);  % directly specified numerical map
0199 end
0200 if any(m=='f')
0201     rgb=colormap; % get output values from the current colourmap
0202     colormap(rgb(end:-1:1,:))
0203 end
0204 rgb=colormap; % get output values from the current colourmap
0205 y=rgb*yv;  % convert RGB to luminance
0206 minyt=0.05*(any(m=='b')+any(um=='B')); % target minimum luminance
0207 maxyt=1-0.05*(any(m=='w')+any(um=='W')); % target maximum luminance
0208 maxy=max(y);
0209 miny=min(y);
0210 if maxy>maxyt || miny<minyt
0211     maxy=max(maxy,maxyt);
0212     miny=min(miny,minyt);
0213     rgb=(rgb-miny)*(maxyt-minyt)/(maxy-miny)+minyt;
0214     colormap(rgb);
0215     y=rgb*yv;  % convert RGB to luminance
0216 end
0217 l=lc*(la*y+(y>lk).*(y.^(1/3)-la*y-lb)); % convert luminance to lightness
0218 if any(m=='g')
0219     sp=[1 2 2];
0220     ssp=sum(sp);
0221     axw=0.05;
0222     nc=size(rgb,1);  % size of color map
0223     hsv=rgb2hsv(rgb);
0224     subplot(ssp,1,sp(1)+(1:sp(2)));
0225     plot(1:nc,y,'-k');
0226     hold on
0227     plot(1:nc,rgb(:,1),'-r');
0228     plot(1:nc,rgb(:,2),'-g');
0229     plot(1:nc,rgb(:,3),'-b');
0230     hold off
0231     axis([0.5 nc+0.5 -axw 1+axw]);
0232     ylabel('RGB + Y');
0233     subplot(ssp,1,sp(1)+sp(2)+1:ssp);
0234     plot(1:nc,l,'-k');
0235     hold on
0236     plot(1:nc,hsv(:,1),'-r');
0237     plot(1:nc,hsv(:,2),'-g');
0238     plot(1:nc,hsv(:,3),'-b');
0239     hold off
0240     axis([0.5 nc+0.5 -axw 1+axw]);
0241     ylabel('HSV + L*');
0242     subplot(ssp,1,1:sp(1));
0243     image(permute(reshape([rgb y(:,[1 1 1])],[nc,3,2]),[3 1 2]));
0244     set(gca,'YTick',[]);
0245 end

Generated on Fri 22-Sep-2017 19:37:38 by m2html © 2003