diff options
author | scuri <scuri> | 2008-11-18 13:15:46 +0000 |
---|---|---|
committer | scuri <scuri> | 2008-11-18 13:15:46 +0000 |
commit | 950d6181e32222c659df5720752dc43f0e92b8b6 (patch) | |
tree | 2365c0aca49755d821226ce703ac3b5c1136a826 /src/im_colorhsi.cpp | |
parent | c2c3ee4f509d743a5924b38ed839ae72360a873a (diff) |
*** empty log message ***
Diffstat (limited to 'src/im_colorhsi.cpp')
-rw-r--r-- | src/im_colorhsi.cpp | 120 |
1 files changed, 71 insertions, 49 deletions
diff --git a/src/im_colorhsi.cpp b/src/im_colorhsi.cpp index 3852527..953bb2c 100644 --- a/src/im_colorhsi.cpp +++ b/src/im_colorhsi.cpp @@ -2,7 +2,7 @@ * \brief HSI Color Manipulation * * See Copyright Notice in im_lib.h - * $Id: im_colorhsi.cpp,v 1.1 2008/10/17 06:10:16 scuri Exp $ + * $Id: im_colorhsi.cpp,v 1.2 2008/11/18 13:15:46 scuri Exp $ */ @@ -18,12 +18,25 @@ static const float rad240 = 4.1887902f; static const float rad300 = 5.2359877f; static const float rad360 = 6.2831853f; static const float sqrt3 = 1.7320508f; +static const float rad2deg = 57.2957795131f; + + +static double iColorNormHue(double H) +{ + while (H < 0.0) + H += rad360; + + if (H > rad360) + H = fmod(H, (double)rad360); + + return H; +} /**********************************/ /* HSI MAX S */ /**********************************/ -static void iSmax01(float h, float hr, float hb, float hg, float *h0, float *h1) +static void iColorSmax01(float h, float hr, float hb, float hg, float *h0, float *h1) { if (h < rad60) { @@ -57,22 +70,24 @@ static void iSmax01(float h, float hr, float hb, float hg, float *h0, float *h1) } } -float imColorHSI_Smax(float h, double cosh, double sinh, float i) +static float iColorHSI_Smax(float h, double cosH, double sinH, float i) { float hr, hb, hg, imax, h0, h1; + /* i here is normalized between 0-1 */ + if (i == 0 || i == 1) return 0.0f; - if (i == 1.0f/3.0f || i == 2.0f/3.0f) - return 1.0f; + /* Making r=0, g=0, b=0, r=1, g=1 or b=1 in the parametric equations and + writting s in function of H and I. */ - hr = (float)(cosh / 1.5); - hg = (float)((-cosh + sinh*sqrt3)/ 3.0); - hb = (float)((-cosh - sinh*sqrt3)/ 3.0); + hr = (float)(cosH / 1.5); + hg = (float)((-cosH + sinH*sqrt3)/ 3.0); + hb = (float)((-cosH - sinH*sqrt3)/ 3.0); /* at bottom */ - if (i < 1.0f/3.0f) + if (i <= 1.0f/3.0f) { /* face B=0 */ if (h < rad120) @@ -87,7 +102,7 @@ float imColorHSI_Smax(float h, double cosh, double sinh, float i) } /* at top */ - if (i > 2.0f/3.0f) + if (i >= 2.0f/3.0f) { /* face R=1 */ if (h < rad60 || h > rad300) @@ -103,7 +118,7 @@ float imColorHSI_Smax(float h, double cosh, double sinh, float i) /* in the middle */ - iSmax01(h, hr, hb, hg, &h0, &h1); + iColorSmax01(h, hr, hb, hg, &h0, &h1); if (h == 0 || h == rad120 || h == rad240) imax = 1.0f/3.0f; @@ -118,7 +133,7 @@ float imColorHSI_Smax(float h, double cosh, double sinh, float i) return (1-i)/h1; } -float imColorHSI_ImaxS(float h, double cosh, double sinh) +float imColorHSI_ImaxS(float h, double cosH, double sinH) { float i, h0, h1; float hr, hb, hg; @@ -129,11 +144,11 @@ float imColorHSI_ImaxS(float h, double cosh, double sinh) if (h == rad60 || h == rad180 || h == rad300) return 2.0f/3.0f; - hr = (float)(cosh / 1.5f); - hg = (float)((-cosh + sinh*sqrt3)/ 3.0); - hb = (float)((-cosh - sinh*sqrt3)/ 3.0); + hr = (float)(cosH / 1.5f); + hg = (float)((-cosH + sinH*sqrt3)/ 3.0); + hb = (float)((-cosH - sinH*sqrt3)/ 3.0); - iSmax01(h, hr, hb, hg, &h0, &h1); + iColorSmax01(h, hr, hb, hg, &h0, &h1); i = h0 / (h0 - h1); @@ -149,19 +164,31 @@ void imColorRGB2HSI(float r, float g, float b, float *h, float *s, float *i) float v, u; double H; + /* Parametric equations */ v = r - (g + b)/2; u = (g - b) * (sqrt3/2); - *i = (r + g + b)/3; - *s = (float)sqrt(v*v + u*u); + *i = (r + g + b)/3; /* already normalized to 0-1 */ + *s = (float)sqrt(v*v + u*u); /* s is between 0-1, it is linear in the cube and it is in u,v space. */ if (*s == 0) *h = 360.0f; /* by definition */ else { H = atan2(u, v); - if (H < 0.0f) H += rad360; - *h = (float)(H * 57.2957795131); + H = iColorNormHue(H); + *h = (float)(H * rad2deg); + + /* must scale S from 0-Smax to 0-1 */ + float Smax = iColorHSI_Smax((float)H, cos(H), sin(H), *i); + if (Smax == 0.0f) + *s = 0.0f; + else + { + if (*s > Smax) /* because of round problems when calculating s and Smax */ + *s = Smax; + *s /= Smax; + } } } @@ -180,15 +207,13 @@ void imColorRGB2HSIbyte(unsigned char r, unsigned char g, unsigned char b, float void imColorHSI2RGB(float h, float s, float i, float *r, float *g, float *b) { - static int first = 1; - static double _sqrt3; - double cosh, sinh, H, v, u; + double cosH, sinH, H, v, u; - if (first) - { - _sqrt3 = sqrt(3.0); - first = 0; - } + if (i < 0) i = 0; + else if (i > 1) i = 1; + + if (s < 0) s = 0; + else if (s > 1) s = 1; if (s == 0.0f || i == 1.0f || i == 0.0f || (int)h == 360) { @@ -198,33 +223,30 @@ void imColorHSI2RGB(float h, float s, float i, float *r, float *g, float *b) return; } - if (i < 0) i = 0; - if (i > 1) i = 1; - - if (h > 360) h = (float)fmod(h, 360); - if (h < 0.0f) h += 360; - - H = h / 57.2957795131; + H = h/rad2deg; + H = iColorNormHue(H); - cosh = cos(H); - sinh = sin(H); + cosH = cos(H); + sinH = sin(H); - { - float smax = imColorHSI_Smax((float)H, cosh, sinh, i); - if (s < 0) s = 0; - if (s > smax) s = smax; - } + /* must scale S from 0-1 to 0-Smax */ + float Smax = iColorHSI_Smax((float)H, cosH, sinH, i); + s *= Smax; + if (s > 1.0f) /* because of round problems when calculating s and Smax */ + s = 1.0f; - v = s * cosh; - u = s * sinh * _sqrt3; + v = s * cosH; + u = s * sinH; + /* Inverse of the Parametric equations, using i normalized to 0-1 */ *r = (float)(i + v/1.5); - *g = (float)(i - (v - u)/3.0); - *b = (float)(i - (v + u)/3.0); + *g = (float)(i - (v - u*sqrt3)/3.0); + *b = (float)(i - (v + u*sqrt3)/3.0); - if (*r < 0) *r = -*r; - if (*g < 0) *g = -*g; - if (*b < 0) *b = -*b; + /* fix round errors */ + if (*r < 0) *r = 0; + if (*g < 0) *g = 0; + if (*b < 0) *b = 0; if (*r > 1) *r = 1.0f; if (*g > 1) *g = 1.0f; |