Convert a 'z' coordinate to RGB values for a heatmap

Hello.
I have a function here that takes the 'val' and converts into RGB so that I can print out a heat map. After some reading up, I figured that I needed to first normalize 'val' to get it between 0 an 1, invert and group it and then use the integer and fraction part as part of the rgb values. However this bit of code gives me a totally white image.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
void Volume::setRGB(png_byte *rgb, float val){

  rgb[0] = 255;
  rgb[1] = 255;
  rgb[2] = 255;

  double normalized_z = (val - min_z) / (max_z - min_z);

  double inverted_group=(1-normalized_z)/0.25;     //invert and group

  int decimal_part=floor(inverted_group); //this is the integer part
  
  //fractional_part part from 0 to 255
  int fractional_part=floor(255*(inverted_group-decimal_part));

  switch(decimal_part)
  {
    case 0:
      rgb[0]=255;
      rgb[1]=fractional_part;
      rgb[2]=0;
      break;
    case 1:
      rgb[0]=255-fractional_part;
      rgb[1]=255;
      rgb[2]=0;
      break;
    case 2:
      rgb[0]=0;
      rgb[1]=255;
      rgb[2]=fractional_part;
      break;
    case 3:
      rgb[0]=0;
      rgb[1]=255-fractional_part;
      rgb[2]=255;
      break;
    case 4:
      rgb[0]=0;
      rgb[1]=0;
      rgb[2]=255;
      break;
  }
}


On the other hand, if I just changed the rgb values based on val, I'm getting a proper image generated.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
...
if(val > 0 && val <40){
    rgb[0] = 255;
    rgb[1] = 204;
    rgb[2] = 204;
  }
  if(val >= 41 && val <80){
    rgb[0] = 255;
    rgb[1] = 153;
    rgb[2] = 153;
  }
  if(val > 81 && val <120){
    rgb[0] = 255;
    rgb[1] = 102;
    rgb[2] = 102;
  }
  if(val >= 121 && val <160){
    rgb[0] = 255;
    rgb[1] = 51;
    rgb[2] = 51;
   ...
   ...
  }


I think my RGB code is totally messed up and any help or direction will be appreciated
Last edited on
For one, your two examples seem to have different colour scales.

Lets say that the scale is this:
1
2
3
0.0 blue
0.5 green
1.0 red

That table could be in a std::map.
The map has upper_bound() http://www.cplusplus.com/reference/map/map/upper_bound/

Test lookups with upper_bound:
k<0.0 it==begin() (i.e. blue)
0.0<=k<0.5 (green)
0.5<=k<1.0 (red)
1.0<=k it==end()

Edge cases:
if ( it==begin() ) use *begin() (blue)
if ( it==end() ) use *rbegin() (red)

Otherwise look at element and previous. Say k=0.4
We look at (0.0, blue) and (0.5, green).
0.4 is at 80% from 0.0 to 0.5

Interpolate: colour = 0.8 * green + 0.2 * blue

Lets make this more illustrative by changing the 0.5 colour to (200,200,200):
1
2
3
colour = 0.8 * (200,200,200) + 0.2 * (0,0,255)
       = (160,160,160) + (0,0,51)
       = (160,160,211)
Topic archived. No new replies allowed.