How to create a custom colormap programmatically?

ispanico picture ispanico · Jun 21, 2013 · Viewed 41.6k times · Source

I'd like to create a colormap in matlab. I want to fade the color according to gray level of pixel.

For example:

from 255 to 160 -> white 
from 159 to 120 -> pink
from 119 to 50 -> brown
from 49 to 0 -> dark

Answer

Dan picture Dan · Jun 21, 2013

From the docs:

A colormap is an m-by-3 matrix of real numbers between 0.0 and 1.0. Each row is an RGB vector that defines one color. The kth row of the colormap defines the kth color, where map(k,:) = [r(k) g(k) b(k)]) specifies the intensity of red, green, and blue.

OK so to start we are going to create an m-by-3 matrix, in your case m is 161:

m = 161;
map = zeros(m , 3);

Now you want the bottom to be dark (I'm going with black) and the 50th point to be brown. but lets go with red as an example as it's easier. RGB triples for black and red respectively: [0,0,0] and [1,0,0]

OK so currently our enitre colormap is black. We know we want map(50,:) = [1, 0 ,0] i.e. red but now we want a gradient in between right? So lets use linspace for this (note that there is a better method using interp1 instead of linspace at the end of this answer):

R0to50 = linspace(0,1,50)';

putting this in the map:

map(1:50, 1) = R0to50;

So now lets use brown instead of red, to get the triple from that link divide each colour component by 255 so our triple is t = [101, 67, 33]./255. OK so now just repeat that linspace procedure for each colour:

R = linspace(0,t(1),50);
G = linspace(0,t(2),50);
B = linspace(0,t(3),50);

T = [R', G', B'];

map(1:50, :) = T;

And now repeat for each of your other nodes.

For example:

I = linspace(0,1,161);
imagesc(I(:, ones(10)))
colormap(map)

enter image description here


An alternative to using linspace once per channel individually and repeating this for each colour is to use linear interpolation.

Create a matrix where each row is a color triple

T = [0,   0,   0          %// dark
     101, 67,  33         %// brown
     255, 105, 180        %// pink
     255, 255, 255        %// white
     255, 255, 255]./255; %// white again  -> note that this means values between 161 and 255 will be indistinguishable

And now make a vector of what range each color should be at (i.e. this vector defines the spacing of the colours, they need not be regularly/equally spaced):

x = [0
     50
     120
     160
     255];

And finally you can create the entire map with one simple interpolation:

map = interp1(x/255,T,linspace(0,1,255));

testing

I = linspace(0,1,255);
imagesc(I(ones(1,10),:)')
colormap(map)

enter image description here