Search code examples
matlabcolor-mapping

How to create a custom colormap programmatically?


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

Solution

  • 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