summaryrefslogtreecommitdiff
path: root/src/im_colorhsi.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/im_colorhsi.cpp')
-rw-r--r--src/im_colorhsi.cpp243
1 files changed, 243 insertions, 0 deletions
diff --git a/src/im_colorhsi.cpp b/src/im_colorhsi.cpp
new file mode 100644
index 0000000..3852527
--- /dev/null
+++ b/src/im_colorhsi.cpp
@@ -0,0 +1,243 @@
+/** \file
+ * \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 $
+ */
+
+
+#include <math.h>
+
+#include "im_colorhsi.h"
+#include "im_color.h"
+
+static const float rad60 = 1.0471975f;
+static const float rad120 = 2.0943951f;
+static const float rad180 = 3.1415926f;
+static const float rad240 = 4.1887902f;
+static const float rad300 = 5.2359877f;
+static const float rad360 = 6.2831853f;
+static const float sqrt3 = 1.7320508f;
+
+/**********************************/
+/* HSI MAX S */
+/**********************************/
+
+static void iSmax01(float h, float hr, float hb, float hg, float *h0, float *h1)
+{
+ if (h < rad60)
+ {
+ *h0 = hb;
+ *h1 = hr;
+ }
+ else if (h < rad120)
+ {
+ *h0 = hb;
+ *h1 = hg;
+ }
+ else if (h < rad180)
+ {
+ *h0 = hr;
+ *h1 = hg;
+ }
+ else if (h < rad240)
+ {
+ *h0 = hr;
+ *h1 = hb;
+ }
+ else if (h < rad300)
+ {
+ *h0 = hg;
+ *h1 = hb;
+ }
+ else
+ {
+ *h0 = hg;
+ *h1 = hr;
+ }
+}
+
+float imColorHSI_Smax(float h, double cosh, double sinh, float i)
+{
+ float hr, hb, hg, imax, h0, h1;
+
+ if (i == 0 || i == 1)
+ return 0.0f;
+
+ if (i == 1.0f/3.0f || i == 2.0f/3.0f)
+ return 1.0f;
+
+ 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)
+ {
+ /* face B=0 */
+ if (h < rad120)
+ return -i/hb;
+
+ /* face R=0 */
+ if (h < rad240)
+ return -i/hr;
+
+ /* face G=0 */
+ return -i/hg;
+ }
+
+ /* at top */
+ if (i > 2.0f/3.0f)
+ {
+ /* face R=1 */
+ if (h < rad60 || h > rad300)
+ return (1-i)/hr;
+
+ /* face G=1 */
+ if (h < rad180)
+ return (1-i)/hg;
+
+ /* face B=1 */
+ return (1-i)/hb;
+ }
+
+ /* in the middle */
+
+ iSmax01(h, hr, hb, hg, &h0, &h1);
+
+ if (h == 0 || h == rad120 || h == rad240)
+ imax = 1.0f/3.0f;
+ else if (h == rad60 || h == rad180 || h == rad300)
+ imax = 2.0f/3.0f;
+ else
+ imax = h0 / (h0 - h1);
+
+ if (i < imax)
+ return -i/h0;
+ else
+ return (1-i)/h1;
+}
+
+float imColorHSI_ImaxS(float h, double cosh, double sinh)
+{
+ float i, h0, h1;
+ float hr, hb, hg;
+
+ if (h == 0 || h == rad120 || h == rad240)
+ return 1.0f/3.0f;
+
+ 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);
+
+ iSmax01(h, hr, hb, hg, &h0, &h1);
+
+ i = h0 / (h0 - h1);
+
+ return i;
+}
+
+/**********************************/
+/* RGB 2 HSI */
+/**********************************/
+
+void imColorRGB2HSI(float r, float g, float b, float *h, float *s, float *i)
+{
+ float v, u;
+ double H;
+
+ v = r - (g + b)/2;
+ u = (g - b) * (sqrt3/2);
+
+ *i = (r + g + b)/3;
+ *s = (float)sqrt(v*v + u*u);
+
+ if (*s == 0)
+ *h = 360.0f; /* by definition */
+ else
+ {
+ H = atan2(u, v);
+ if (H < 0.0f) H += rad360;
+ *h = (float)(H * 57.2957795131);
+ }
+}
+
+void imColorRGB2HSIbyte(unsigned char r, unsigned char g, unsigned char b, float *h, float *s, float *i)
+{
+ float fr = imColorReconstruct(r, (imbyte)255);
+ float fg = imColorReconstruct(g, (imbyte)255);
+ float fb = imColorReconstruct(b, (imbyte)255);
+
+ imColorRGB2HSI(fr, fg, fb, h, s, i);
+}
+
+/**********************************/
+/* HSI 2 RGB */
+/**********************************/
+
+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;
+
+ if (first)
+ {
+ _sqrt3 = sqrt(3.0);
+ first = 0;
+ }
+
+ if (s == 0.0f || i == 1.0f || i == 0.0f || (int)h == 360)
+ {
+ *r = i;
+ *g = i;
+ *b = i;
+ 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;
+
+ 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;
+ }
+
+ v = s * cosh;
+ u = s * sinh * _sqrt3;
+
+ *r = (float)(i + v/1.5);
+ *g = (float)(i - (v - u)/3.0);
+ *b = (float)(i - (v + u)/3.0);
+
+ if (*r < 0) *r = -*r;
+ if (*g < 0) *g = -*g;
+ if (*b < 0) *b = -*b;
+
+ if (*r > 1) *r = 1.0f;
+ if (*g > 1) *g = 1.0f;
+ if (*b > 1) *b = 1.0f;
+}
+
+void imColorHSI2RGBbyte(float h, float s, float i, unsigned char *r, unsigned char *g, unsigned char *b)
+{
+ float fr, fg, fb;
+
+ imColorHSI2RGB(h, s, i, &fr, &fg, &fb);
+
+ *r = imColorQuantize(fr, (imbyte)255);
+ *g = imColorQuantize(fg, (imbyte)255);
+ *b = imColorQuantize(fb, (imbyte)255);
+}