Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Map value to color scale

Tags:

php

colors

I have a list of values which should be plotted to a map with a certain color. The plotting to the map is already done, but I need to figure out a way to map the value n to a color that represents its value.

An example and my solution so far is to normalize the values based on the min and max and then assign them to hex color 0 for the lowest and 255 for the highest. This of course limits my self to the grey scale. Here is the code:

$color = ($value / $max) * 255    // (min is zero)

But how to do this if the values should go from blue to red for instance? Is there any common libraries or tools that can solve this? So far I haven't been able to locate any.

like image 209
CodeTower Avatar asked Oct 06 '13 15:10

CodeTower


People also ask

How many colors should a map be?

In mathematics, the four color theorem, or the four color map theorem, states that no more than four colors are required to color the regions of any map so that no two adjacent regions have the same color.

What is a scale color?

Several of the coloring methods, including `Beta', `Charge', and `Occupancy', describe a range of floating point values rather than a set of names. These are colored via the color scale, which is a list of 1024 smoothly changing colors. There are many color gradations available.

What is the best Colour scale which can be used for nominal data?

Qualitative colour Schemes Qualitative schemes are best suited to represent nominal or categorical data, they have no inherent ordering. It is best to not have more than 10 colours as it then becomes hard to distinguish between categories.


2 Answers

There might be libs to do that. However let's get a short warm up into the general principles. In general you have following options:

  1. A predefined color index, e.g. $coloridx=array(0=>'#FFFFFF',1=>'#FFEE00',...);
  2. Any algorithm, e.g. linear gradient, which is basically an iterations based adaption of all three RGB channels (R = red, G = green, B = blue).
  3. A combination of both, which usually puts the result of any complex algorithm to the color index and then goes from there.

If you include algorithms in your considerations you must understand that there is no true or false. It all depends on what you would like to implement. There might be occasions where it makes sense to render variations of green into n=0..10 and then have red to black in everything beyond n>10. Caps and multipliers help to set accents. Things like that.

One way of implementing a linear gradient would be:

function lineargradient($ra,$ga,$ba,$rz,$gz,$bz,$iterationnr) {
  $colorindex = array();
  for($iterationc=1; $iterationc<=$iterationnr; $iterationc++) {
     $iterationdiff = $iterationnr-$iterationc;
     $colorindex[] = '#'.
        dechex(intval((($ra*$iterationc)+($rz*$iterationdiff))/$iterationnr)).
        dechex(intval((($ga*$iterationc)+($gz*$iterationdiff))/$iterationnr)).
        dechex(intval((($ba*$iterationc)+($bz*$iterationdiff))/$iterationnr));
  }
  return $colorindex;
}

$colorindex = lineargradient(
  100, 0, 0,   // rgb of the start color
  0, 255, 255, // rgb of the end color
  256          // number of colors in your linear gradient
);

$color = $colorindex[$value];

I UPDATED the code to add dechex, which feeds back on the comments.

like image 89
Quicker Avatar answered Oct 09 '22 00:10

Quicker


Colors values are representations. Numeric colors as well as hexadecimal colors. A "not grayscale" color contains at least 2 different informations: Red value, green value or blue values may be different. Performing operation on its representation gives wrong result. The 'Mapping" must then be performed on each pieces of information. You need to extract red, green and blue values, perform the mapping seperatly, then build the representation of the result color. Here is a quick helper that use a "min color" and "max color", performs mapping on red, green and blue values, according to the "n" value you need to work with, then return the result color in hexadecimal string. It works for any colors or gray scale color as well.

function linear_color($from, $to, $ratio) {
        // normalize ralio
        $ratio = $ratio<0?0:($ratio>1?1:$ratio);
        // unsure colors are numeric values
        if(!is_numeric($from))$from=hexdec($from);
        if(!is_numeric($to))$to=hexdec($to);

        $rf = 0xFF & ($from >> 0x10);
        $gf = 0xFF & ($from >> 0x8);
        $bf = 0xFF & $from;
        $rt = 0xFF & ($to >> 0x10);
        $gt = 0xFF & ($to >> 0x8);
        $bt = 0xFF & $to;
        return str_pad( dechex(($bf + (($bt-$bf)*$ratio)) + ($gf + (($gt-$gf)*$ratio) << 0x8) + ($rf + (($rt-$rf)*$ratio) << 0x10)), 6,'0',STR_PAD_LEFT);
}

Just specify 2 colors as numeric value or hexadecimal string (without hash!) like this :

$color_from = hexdec('c2c2c2');
$color_to = hexdec('1eb02b');
for($i=-0.2; $i<=1.3; $i+=0.04){
        echo '<div style="background-color: #';
        echo linear_color($color_from, $color_to, $i);
        echo '">';
        echo 'Result color when n = <strong>'.$i.'</strong>';
        echo '</div>';
    }
like image 30
Simmoniz Avatar answered Oct 08 '22 23:10

Simmoniz