TLIGHT_PRODUCTS / WS281X
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ColorLib.cpp Source File

ColorLib.cpp

00001 /* ColorLib.cpp
00002  * mbed Microcontroller Library
00003  * Copyright (c) 2016 muetch, t.kuroki, MIT License
00004  *
00005  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
00006  * and associated documentation files (the "Software"), to deal in the Software without restriction,
00007  * including without limitation the rights to use, copy, modify, merge, publish, distribute,
00008  * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
00009  * furnished to do so, subject to the following conditions:
00010  *
00011  * The above copyright notice and this permission notice shall be included in all copies or
00012  * substantial portions of the Software.
00013  *
00014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
00015  * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00016  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
00017  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00018  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00019  */
00020 
00021 #include <stdlib.h>
00022 #include "ColorLib.h"
00023 
00024 //----------------------------------------------------------------------------
00025 /*
00026 #define RGB_MAX_VAL     255
00027 #define HSV_MAX_HUE     3600
00028 #define HSV_MAX_SAT     255
00029 #define HSV_MAX_VAL     255
00030 */
00031 
00032 #define MAX_COLOR(r, g, b)  (((r) > (g)) ? (((r) > (b)) ? (r) : (b)) : (((g) > (b)) ? (g) : (b)))
00033 #define MIN_COLOR(r, g, b)  (((r) < (g)) ? (((r) < (b)) ? (r) : (b)) : (((g) < (b)) ? (g) : (b)))
00034 
00035 inline __attribute__((always_inline))
00036 static int MulDiv(int nNumber, int nNumerator, int nDenominator)
00037 {
00038     return (nNumber * nNumerator) / nDenominator;
00039 }
00040 
00041 //#define constrain(amt, low, high) ((amt) < (low) ? (low) : ((amt) > (high) ? (high) : (amt)))
00042 template<class T>
00043 __attribute__((always_inline))
00044 inline const T& constrain(const T& x, const T& a, const T& b)
00045 {
00046     return (x < a) ? a : ((b < x) ? b : x);
00047 }
00048 
00049 //----------------------------------------------------------------------------
00050 // Integer version
00051 
00052 void rgb2hsv(RGBColor const& rgb, HSVColor& hsv)
00053 {
00054     int r, g, b;        // rgb : 0 - 255
00055     int h, s, v;        // h: 0 - 3600, sv: 0 - 255
00056     int min, max, delta;
00057 
00058     r = rgb.r;
00059     g = rgb.g;
00060     b = rgb.b;
00061 
00062     max = MAX_COLOR(r, g, b);
00063     min = MIN_COLOR(r, g, b);
00064     delta = max - min;
00065 
00066     v = MulDiv(max, HSV_MAX_VAL, RGB_MAX_VAL);
00067     s = (max == 0) ? 0 : MulDiv(delta, HSV_MAX_SAT, max);
00068 
00069     if (s == 0)
00070         h = 0;
00071     else
00072     {
00073 #define MAXHUE_DIV_6    (int)(HSV_MAX_HUE/6.00f+0.5f)
00074 #define MAXHUE_1of3     (int)(HSV_MAX_HUE/3.00f+0.5f)
00075 #define MAXHUE_2of3     (int)(2.0f*HSV_MAX_HUE/3.00f+0.5f)
00076         if (r >= max)                       // > is bogus, just keeps compilor happy
00077             h = MulDiv(g - b, MAXHUE_DIV_6, delta);         // between yellow & magenta
00078         else if (g >= max)
00079             h = MAXHUE_1of3 + MulDiv(b - r, MAXHUE_DIV_6, delta);   // between cyan & yellow
00080         else
00081             h = MAXHUE_2of3 + MulDiv(r - g, MAXHUE_DIV_6, delta);   // between magenta & cyan
00082 
00083         if (h < 0)
00084             h += HSV_MAX_HUE;
00085     }
00086     hsv.h = h;
00087     hsv.s = s;
00088     hsv.v = v;
00089 }
00090 
00091 void hsv2rgb(HSVColor const& hsv, RGBColor& rgb)
00092 {
00093     const int DIVISOR = 255 * (HSV_MAX_HUE/6);
00094     int h, s, v;
00095     int p, q, t;
00096 
00097     h = hsv.h;
00098     s = hsv.s;
00099     v = hsv.v;
00100 
00101     //  H = 0 to 3600 (corresponding to 0..3600 degrees around hexcone)
00102     //      0 (undefined) for S = 0
00103     //  S = 0 (shade of gray) to 255 (pure color)
00104     //  V = 0 (black) to 255 (white)
00105 
00106     if (s <= 0 || v <= 0)       // < is bogus, just shuts up warnings
00107     {
00108         if (v < 0)
00109             v = 0;
00110         rgb.r = rgb.g = rgb.b = v;
00111         return;
00112     }
00113 
00114     if (h < 0)
00115         h = HSV_MAX_HUE - (-h % HSV_MAX_HUE);
00116     h %= HSV_MAX_HUE;
00117 
00118     div_t hh = div(h, (HSV_MAX_HUE/6)); // quot:0..6, rem:0..599
00119     int vs = v * s;
00120     p = v - vs / 255;                                       // p = v * (1 - s)
00121     q = v - MulDiv(vs, hh.rem, DIVISOR);                    // q = v * (1 - s*f)
00122     t = v - MulDiv(vs, (HSV_MAX_HUE/6) - hh.rem, DIVISOR);  // t = v * (1 - s * (1 - f))
00123 
00124     switch (hh.quot)
00125     {
00126         case  0: rgb.r = v; rgb.g = t; rgb.b = p; break;
00127         case  1: rgb.r = q; rgb.g = v; rgb.b = p; break;
00128         case  2: rgb.r = p; rgb.g = v; rgb.b = t; break;
00129         case  3: rgb.r = p; rgb.g = q; rgb.b = v; break;
00130         case  4: rgb.r = t; rgb.g = p; rgb.b = v; break;
00131         default: rgb.r = v; rgb.g = p; rgb.b = q; break;
00132     }
00133 }
00134 
00135 //----------------------------------------------------------------------------
00136 //----------------------------------------------------------------------------
00137 // Gamma 2.0
00138 const uint8_t gamma20_table[256] =
00139 {
00140       0,   1,   1,   1,   1,   1,   1,   1,  1,   1,   1,   1,   1,   2,   2,   2,
00141       2,   2,   2,   2,   2,   3,   3,   3,  3,   3,   3,   4,   4,   4,   4,   5,
00142       5,   5,   5,   6,   6,   6,   6,   7,  7,   7,   8,   8,   8,   9,   9,   9,
00143      10,  10,  10,  11,  11,  12,  12,  12, 13,  13,  14,  14,  15,  15,  16,  16,
00144      17,  17,  18,  18,  19,  19,  20,  20, 21,  21,  22,  23,  23,  24,  24,  25,
00145      26,  26,  27,  27,  28,  29,  29,  30, 31,  31,  32,  33,  34,  34,  35,  36,
00146      37,  37,  38,  39,  40,  40,  41,  42, 43,  44,  44,  45,  46,  47,  48,  49,
00147      50,  50,  51,  52,  53,  54,  55,  56, 57,  58,  59,  60,  61,  62,  63,  64,
00148      65,  66,  67,  68,  69,  70,  71,  72, 73,  74,  75,  76,  77,  78,  79,  80,
00149      82,  83,  84,  85,  86,  87,  88,  90, 91,  92,  93,  94,  96,  97,  98,  99,
00150     101, 102, 103, 104, 106, 107, 108, 109,111, 112, 113, 115, 116, 117, 119, 120,
00151     122, 123, 124, 126, 127, 129, 130, 131,133, 134, 136, 137, 139, 140, 142, 143,
00152     145, 146, 148, 149, 151, 152, 154, 155,157, 158, 160, 162, 163, 165, 166, 168,
00153     170, 171, 173, 175, 176, 178, 180, 181,183, 185, 186, 188, 190, 192, 193, 195,
00154     197, 199, 200, 202, 204, 206, 207, 209,211, 213, 215, 217, 218, 220, 222, 224,
00155     226, 228, 230, 232, 233, 235, 237, 239,241, 243, 245, 247, 249, 251, 253, 255
00156 };
00157 
00158 //----------------------------------------------------------------------------
00159 #define GAMMA(c)    gamma20_table[c]
00160 //#define GAMMA(c)    ((((c)+1)*((c)+1)-1)>>8)
00161 
00162 RGBColor GammaColor(RGBColor color)
00163 {
00164     RGBColor ret;
00165 
00166     ret.red   = GAMMA(color.red);
00167     ret.green = GAMMA(color.green);
00168     ret.blue  = GAMMA(color.blue);
00169     return ret;
00170 }
00171 
00172 RGBColor GammaColor(RGBColor color, int brightness)
00173 {
00174     HSVColor hsv(color);
00175     hsv.val = (brightness < 0) ? 0 : (brightness > 255) ? 255 : brightness;
00176     return GammaColor(hsv);
00177 }
00178 
00179 RGBColor* GammaCorrection(RGBColor *color, int size)
00180 {
00181     if (color && size > 0)
00182     {
00183         RGBColor *p = color;
00184         for (int i = 0; i < size; ++i)
00185         {
00186             p->red   = GAMMA(p->red);
00187             p->green = GAMMA(p->green);
00188             p->blue  = GAMMA(p->blue);
00189             ++p;
00190         }
00191     }
00192     return color;
00193 }
00194 
00195 HSVColor* GammaCorrection(HSVColor *color, int size)
00196 {
00197     if (color && size > 0)
00198     {
00199         HSVColor *p = color;
00200         for (int i = 0; i < size; ++i)
00201         {
00202             p->val = GAMMA(p->val);
00203             ++p;
00204         }
00205     }
00206     return color;
00207 }
00208 
00209 //----------------------------------------------------------------------------