/* STColor Color conversions and value->color maps Stilianos Louca September 2011 */ #ifndef ST_COLOR #define ST_COLOR #include #include #include #include using namespace std; namespace ST{ #ifndef PI #define PI 3.141592653589793238462643 #endif #ifndef EPSILON #define EPSILON 1e-15 #endif //Predefined color palettes, inspired from gnuplot. //Each palette is given as a triplet of mappings [0,1] -> [0,1]. //Mappings are named by numbers from -36 to 36. //For more info about these codes type 'show palette rgbformulae' into gnuplot. //The function paletteMapping() below provides with a translation of these codes into a mapping, as a direct implementation of the gnuplot manual. typedef enum _ColorPalette{ ColorPaletteGrey, // ~ gnuplot rgbformulae 3,3,3 ColorPaletteHeat, // ~ gnuplot rgbformulae 21,22,23 ColorPaletteOcean, // ~ gnuplot rgbformulae 23,28,3 ColorPaletteRainbow, // ~ gnuplot rgbformulae 33,13,10 ColorPaletteColorPrintableOnGrey, // ~ gnuplot rgbformulae 30,31,32 ColorPaletteParrot, // ~ gnuplot rgbformulae 7,5,15 ColorPalettePassionFruit, // ~ gnuplot rgbformulae 3,11,6 ColorPaletteIGrey, // ~ gnuplot rgbformulae -3,-3,-3 ColorPaletteIHeat, // ~ gnuplot rgbformulae -21,-22,-23 ColorPaletteIOcean, // ~ gnuplot rgbformulae -23,-28,-3 ColorPaletteIRainbow, // ~ gnuplot rgbformulae -33,-13,-10 ColorPaletteIColorPrintableOnGrey, // ~ gnuplot rgbformulae -30,-31,-32 ColorPaletteIParrot, // ~ gnuplot rgbformulae -7,-5,-15 ColorPaletteIPassionFruit // ~ gnuplot rgbformulae -3,-11,-6 } ColorPalette; typedef enum _VectorColoring{ VectorColoringNone, VectorColoringNormGrey, VectorColoringXGrey, VectorColoringYGrey, VectorColoringZGrey, VectorColoringNormHeat, VectorColoringXHeat, VectorColoringYHeat, VectorColoringZHeat, VectorColoringNormOcean, VectorColoringXOcean, VectorColoringYOcean, VectorColoringZOcean, VectorColoringXYRedBlue, VectorColoringXZRedBlue, VectorColoringYZRedBlue, VectorColoringXYHeat, VectorColoringXZHeat, VectorColoringYZHeat, VectorColoringXYZRGB } VectorColoring; typedef enum _ColorBlindness{ ColorBlindnessNone, ColorBlindnessDeuteranope, ColorBlindnessProtanope, ColorBlindnessTritanope } ColorBlindness; //forward declarations class Color; extern const long N_STCOLOR_DISCRETE_COLOR_PALETTE; extern char const * const STCOLOR_DISCRETE_COLOR_PALETTE[]; extern const long N_STCOLOR_DISCRETE_COLOR_PALETTE_DARK; extern char const * const STCOLOR_DISCRETE_COLOR_PALETTE_DARK[]; #pragma mark - #pragma mark Color conversion #pragma mark - //Returns integer value within [0, 256^3 - 1] corresponding to RGB-color passed, as used for example by gnuplot. //r,g,b should each be within [0,1]. unsigned int RGB2ColorNumber(double r, double g, double b); //Inverse of RGB2ColorNumber. colorNumber should be within [0, 256^3 - 1]. //Returned (r,g,b) tripled is within [0,1]^3 void colorNumber2RGB(unsigned int colorNumber, double &r, double &g, double &b); //Hue-Saturation-Value from & to Red-Green-Blue transformations // (h,s,v) \in [0,1]^3 // (r,g,b) \in [0,1]^3 void RGB2HSV(double r, double g, double b, double &h, double &s, double &v); void HSV2RGB(double h, double s, double v, double &r, double &g, double &b); #pragma mark - #pragma mark Complex numbers to colors #pragma mark - //Mapping complex numbers (or 2D-vectors) to colors via the HSV color cylinder. 0 equals black, \infty equals white. //zeroRadius controls the transition radius from black (0) to bright colors. //inftyRadius controls the transition radius from saturated to white (INFTY). //Default values for zeroRadius & inftyRadius are 0 and 1. void complex2HSV(double realPart, double imaginaryPart, double &h, double &s, double &v); void complex2HSV(double realPart, double imaginaryPart, double zeroRadius, double inftyRadius, double &h, double &s, double &v); void complex2HSV(complex z, double zeroRadius, double inftyRadius, double &h, double &s, double &v); void complexPolar2HSV(double argument, double norm, double zeroRadius, double inftyRadius, double &h, double &s, double &v); void complex2RGB(double realPart, double imaginaryPart, double &r, double &g, double &b); void complex2RGB(double realPart, double imaginaryPart, double zeroRadius, double inftyRadius, double &r, double &g, double &b); void complex2RGB(complex z, double zeroRadius, double inftyRadius, double &r, double &g, double &b); void complexPolar2RGB(double argument, double norm, double zeroRadius, double inftyRadius, double &r, double &g, double &b); #pragma mark - #pragma mark Color palettes #pragma mark - //RGB color mappings [0,1] -> [0,1] used by gnuplot rgbformulae //For more info type 'show palette rgbformulae' into gnuplot double paletteMapping(int mappingCode, double x); //returns corresponding gnuplot-palette codes for palette passed void colorPalette2PaletteCodes(ColorPalette palette, int &redCode, int &greenCode, int &blueCode); //Transforms value \in [0,1] to RGB triplet in [0,1]^3, using the palette requested void value2RGBViaPalette(double value, ColorPalette palette, double &r, double &g, double &b); //Transforms value \in [0,1] to colorNumber in [0, 256^3 - 1], using the palette requested //Note the relation: value2ColorNumberViaPalette() = RGB2ColorNumber() o value2RGBViaPalette() unsigned int value2ColorNumberViaPalette(double value, ColorPalette palette); int paletteBrighteningDirection(ColorPalette palette); #pragma mark Color class #pragma mark - class Color{ private: double red, green, blue; //values in [0,1] //returns 2-digit hexadecimal version of number d=0,..,255 as two-char string string decimal2hex(unsigned int d) const; bool isHexChar(char c); int hexchar2int(char hex) const; //returns -1 on error public: //Constructors Color(): red(0), green(0), blue(0) {}; Color(double r, double g, double b); Color(const string &HexRGB); //6-digit hex code (2 digits per RGB channel) // get a nice color for plotting // guaranteed to be deterministic, but will repeat itself periodically static Color getNicePlotColor(unsigned long number); //Modifiers. All of them return false if input is invalid (in which case internal state does not change) bool setRGB(double r, double g, double b); //rgb values within [0,1] bool setHSV(double H, double S, double V); //hsv values within [0,1] bool setHex(const string &hexRGB); //format XXXXXX, where X is 0,1,..,9,A,B,C,D,E,F static Color white(); static Color black(); // change saturation by given factor void saturate(double factor); // turn color to gray scale void turnGray(); //Daltonize color (i.e. make suitable for color-blind) //based on: http://scien.stanford.edu/class/psych221/projects/05/ofidaner/project_report.pdf void daltonize(ColorBlindness CB); //Getting values void getRGB(double &r, double &g, double &b) const; void getHSV(double &H, double &S, double &V) const; string getHex() const; bool isWhite() const; bool isBlack() const; //printing void printRGB(ostream &s, bool bracket) const; }; #pragma mark Color creation #pragma mark - //returns color for vector (vx, vy, vz) \in [0,1]^3 Color vector2RGBColor(double vx, double vy, double vz, double norm, VectorColoring coloring); //generate a sequence of colors from a palette, e.g. for multiple curve coloring //if random==false, colors are picked uniformly in the order as they appear in the palette //if random==true, colors are picked from the palette at random (but still on a regular grid) void generateDiscreteColors(long count, ColorPalette palette, bool random, bool preferDark, vector &colors); //get a collection of colors, e.g. for plotting multiple curves //if the requested number is low enough, colors are picked from a pre-defined 'nice' palette //otherwise, a default gradient palette is used void generateDiscreteColors(long count, bool preferDark, vector &colors, ColorBlindness correctForColorBlindness); }//end of namespace ST #endif