Introduction
A class that interpolates between a single value (an unsigned 16 bit integer) and an RGB color value on a color scale that can be defined.
Source code
Due to the simplicity of the class, I'm displaying it here so that you don't have to download a zip file and extract that. This code should go into a file called Gradient.h.
#ifndef GRADIENT_H_
#define GRADIENT_H_
#include <vector>
typedef struct rgb {
uint8_t red;
uint8_t green;
uint8_t blue;
bool operator==(rgb lhr)
{
return this == &lhr;
}
}rgb;
static rgb INVALID_COLOR = {0, 0, 0};
class Gradient
{
private:
uint16_t m_min;
rgb m_minColor;
rgb m_minOutlierColor;
uint16_t m_max;
rgb m_maxColor;
rgb m_maxOutlierColor;
std::vector<rgb> m_stops;
rgb interpolate(rgb c1, rgb c2, float normalized_value){
if( normalized_value <= 0.0 ){ return c1; }
if( normalized_value >= 1.0 ){ return c2; }
uint8_t red = (uint8_t)((1.0-normalized_value)*c1.red +
normalized_value*c2.red);
uint8_t green = (uint8_t)((1.0-normalized_value)*c1.green +
normalized_value*c2.green);
uint8_t blue = (uint8_t)((1.0-normalized_value)*c1.blue +
normalized_value*c2.blue);
return (rgb){red, green, blue};
}
public:
Gradient(){}
void initialize(uint16_t min, uint16_t max, std::vector<rgb> stops,
rgb minOutlierColor=INVALID_COLOR, rgb maxOutlierColor=INVALID_COLOR){
m_min = min;
m_max = max;
m_stops = stops;
m_minOutlierColor = minOutlierColor;
m_maxOutlierColor = maxOutlierColor;
}
Gradient(uint16_t min, uint16_t max, std::vector<rgb> stops,
rgb minOutlierColor=INVALID_COLOR, rgb maxOutlierColor=INVALID_COLOR){
initialize(min, max, stops, minOutlierColor, maxOutlierColor);
}
virtual ~Gradient(){}
rgb getRgb(uint16_t value){
if( value < m_min ){ return m_minOutlierColor ==
INVALID_COLOR ? m_stops.front() : m_minOutlierColor; }
if( value > m_max ){ return m_maxOutlierColor ==
INVALID_COLOR ? m_stops.back() : m_maxOutlierColor; }
uint16_t range = m_max - m_min;
uint16_t v = value - m_min;
float step = range / (float)(m_stops.size()-1);
int bin = (int)(v / step);
float normalized_v = (v - bin*step) / step;
return interpolate(m_stops[bin], m_stops[bin+1], normalized_v);
}
};
#endif /*GRADIENT_H_*/
Using the code
Here's an example of the code in action:
#include <Gradient.h>
[...]
std::vector<rgb> stops;
stops.push_back((rgb){255,255,255}); stops.push_back((rgb){255,0,0}); stops.push_back((rgb){255,255,0}); stops.push_back((rgb){0,255,0}); stops.push_back((rgb){0,0,255}); stops.push_back((rgb){75,25,150});
Gradient grad;
grad.initialize(0x000f, 0xfff0, stops, (rgb){0,0,0}, (rgb){0,0,0});
rgb color = grad.getRgb(123456);
Known bugs
The Gradient
class currently only works for interpolating uint16_t
integral values to color. It's quite possible that this could be made more flexible (for example, by making the class a template class). There are some other potential bugs in it that have to do with an integer overflow, so any comments or improvements on the code are welcome.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.