*
* == Summary ==
* This file implements routines for color transformations between the spaces
- * sRGB, Y'UV, Y'CbCr, Y'PbPr, Y'DbDr, Y'IQ, HSV, HSL, HSI, CIEXYZ, CIELAB,
+ * sRGB, Y'UV, Y'CbCr, Y'PbPr, Y'DbDr, Y'IQ, HSV, HSL, HSI, CIEXYZ, CIELAB,
* CIELUV, CIELCH, and CIECAT02 LMS.
*
* == Usage ==
double S[3] = {173, 0.8, 0.5};
double D[3];
colortransform Trans;
-
+
if(!(GetColorTransform(&Trans, "HSI -> Lab")))
{
printf("Invalid syntax or unknown color space\n");
return;
- }
-
+ }
+
ApplyColorTransform(Trans, &D[0], &D[1], &D[2], S[0], S[1], S[2]);
@endcode
* "num" is a typedef defined at the beginning of colorspace.h that may be set
Lab2Rgb(&R, &G, &B, L, a, b);
@endcode
* Generally, the calling syntax is
-@code
+@code
Foo2Bar(&B0, &B1, &B2, F0, F1, F2);
-@endcode
+@endcode
* where (F0,F1,F2) are the coordinates of a color in space "Foo" and
- * (B0,B1,B2) are the transformed coordinates in space "Bar." For any
+ * (B0,B1,B2) are the transformed coordinates in space "Bar." For any
* transformation routine, its inverse has the sytax
-@code
+@code
Bar2Foo(&F0, &F1, &F2, B0, B1, B2);
-@endcode
+@endcode
*
* The conversion routines are consistently named with the first letter of a
* color space capitalized with following letters in lower case and omitting
* any transformation routine Foo2Bar, its inverse is Bar2Foo.
*
* All transformations assume a two degree observer angle and a D65 illuminant.
- * The white point can be changed by modifying the WHITEPOINT_X, WHITEPOINT_Y,
+ * The white point can be changed by modifying the WHITEPOINT_X, WHITEPOINT_Y,
* WHITEPOINT_Z definitions at the beginning of colorspace.h.
*
* == List of transformation routines ==
* - Xyz2Lab(double *L, double *a, double *b, double X, double Y, double Z)
* - Xyz2Luv(double *L, double *u, double *v, double X, double Y, double Z)
* - Xyz2Lch(double *L, double *C, double *h, double X, double Y, double Z)
- * - Xyz2Cat02lms(double *L, double *M, double *S, double X, double Y, double Z)
+ * - Xyz2Cat02lms(double *L, double *M, double *S, double X, double Y, double Z)
* - Rgb2Lab(double *L, double *a, double *b, double R, double G, double B)
* - Rgb2Luv(double *L, double *u, double *v, double R, double G, double B)
* - Rgb2Lch(double *L, double *C, double *h, double R, double G, double B)
- * - Rgb2Cat02lms(double *L, double *M, double *S, double R, double G, double B)
+ * - Rgb2Cat02lms(double *L, double *M, double *S, double R, double G, double B)
* (Similarly for the inverse transformations.)
*
* It is possible to transform between two arbitrary color spaces by first
* transforming from the source space to sRGB and then transforming from
* sRGB to the desired destination space. For transformations between CIE
* color spaces, it is convenient to use XYZ as the intermediate space. This
- * is the strategy used by GetColorTransform and ApplyColorTransform.
+ * is the strategy used by GetColorTransform and ApplyColorTransform.
*
* == References ==
* The definitions of these spaces and the many of the transformation formulas
- * can be found in
+ * can be found in
*
* Poynton, "Frequently Asked Questions About Gamma"
* http://www.poynton.com/notes/colour_and_gamma/GammaFAQ.html
* == License (BSD) ==
* Copyright (c) 2005-2010, Pascal Getreuer
* All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
+ *
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
+ *
+ * - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#define M_PI 3.14159265358979323846264338327950288
#endif
-/**
+/**
* @brief sRGB gamma correction, transforms R to R'
* http://en.wikipedia.org/wiki/SRGB
*/
(((t) <= 0.0031306684425005883) ? \
(12.92*(t)) : (1.055*pow((t), 0.416666666666666667) - 0.055))
-/**
- * @brief Inverse sRGB gamma correction, transforms R' to R
+/**
+ * @brief Inverse sRGB gamma correction, transforms R' to R
*/
#define INVGAMMACORRECTION(t) \
(((t) <= 0.0404482362771076) ? \
((t)/12.92) : pow(((t) + 0.055)/1.055, 2.4))
-/**
+/**
* @brief CIE L*a*b* f function (used to convert XYZ to L*a*b*)
* http://en.wikipedia.org/wiki/Lab_color_space
*/
((t >= 8.85645167903563082e-3) ? \
pow(t,0.333333333333333) : (841.0/108.0)*(t) + (4.0/29.0))
-/**
- * @brief CIE L*a*b* inverse f function
+/**
+ * @brief CIE L*a*b* inverse f function
* http://en.wikipedia.org/wiki/Lab_color_space
*/
#define LABINVF(t) \
/*
* == Linear color transformations ==
- *
+ *
* The following routines implement transformations between sRGB and
* the linearly-related color spaces Y'UV, Y'PbPr, Y'DbDr, and Y'IQ.
*/
/*
* == Hue Saturation Value/Lightness/Intensity color transformations ==
- *
+ *
* The following routines implement transformations between sRGB and
* color spaces HSV, HSL, and HSI.
*/
-/**
+/**
* @brief Convert an sRGB color to Hue-Saturation-Value (HSV)
- *
+ *
* @param H, S, V pointers to hold the result
* @param R, G, B the input sRGB values scaled in [0,1]
*
double Max = MAX3(R, G, B);
double Min = MIN3(R, G, B);
double C = Max - Min;
-
-
+
+
*V = Max;
-
+
if(C > 0)
{
if(Max == R)
{
*H = (G - B) / C;
-
+
if(G < B)
*H += 6;
}
*H = 2 + (B - R) / C;
else
*H = 4 + (R - G) / C;
-
+
*H *= 60;
*S = C / Max;
}
}
-/**
+/**
* @brief Convert a Hue-Saturation-Value (HSV) color to sRGB
- *
+ *
* @param R, G, B pointers to hold the result
* @param H, S, V the input HSV values
*
- * The input values are assumed to be scaled as
+ * The input values are assumed to be scaled as
* 0 <= H < 360,
* 0 <= S <= 1,
- * 0 <= V <= 1.
+ * 0 <= V <= 1.
* The output sRGB values are scaled between 0 and 1. This is the inverse
* transformation of Rgb2Hsv.
*
double C = S * V;
double Min = V - C;
double X;
-
-
+
+
H -= 360*floor(H/360);
H /= 60;
X = C*(1 - fabs(H - 2*floor(H/2) - 1));
-
+
switch((int)H)
{
case 0:
}
-/**
+/**
* @brief Convert an sRGB color to Hue-Saturation-Lightness (HSL)
- *
+ *
* @param H, S, L pointers to hold the result
* @param R, G, B the input sRGB values scaled in [0,1]
*
double Max = MAX3(R, G, B);
double Min = MIN3(R, G, B);
double C = Max - Min;
-
-
+
+
*L = (Max + Min)/2;
-
+
if(C > 0)
{
if(Max == R)
{
*H = (G - B) / C;
-
+
if(G < B)
*H += 6;
}
*H = 2 + (B - R) / C;
else
*H = 4 + (R - G) / C;
-
+
*H *= 60;
*S = (*L <= 0.5) ? (C/(2*(*L))) : (C/(2 - 2*(*L)));
}
}
-/**
+/**
* @brief Convert a Hue-Saturation-Lightness (HSL) color to sRGB
- *
+ *
* @param R, G, B pointers to hold the result
* @param H, S, L the input HSL values
*
- * The input values are assumed to be scaled as
+ * The input values are assumed to be scaled as
* 0 <= H < 360,
* 0 <= S <= 1,
- * 0 <= L <= 1.
+ * 0 <= L <= 1.
* The output sRGB values are scaled between 0 and 1. This is the inverse
* transformation of Rgb2Hsl.
*
double C = (L <= 0.5) ? (2*L*S) : ((2 - 2*L)*S);
double Min = L - 0.5*C;
double X;
-
-
+
+
H -= 360*floor(H/360);
H /= 60;
X = C*(1 - fabs(H - 2*floor(H/2) - 1));
-
+
switch((int)H)
{
case 0:
}
-/**
+/**
* @brief Convert an sRGB color to Hue-Saturation-Intensity (HSI)
- *
+ *
* @param H, S, I pointers to hold the result
* @param R, G, B the input sRGB values scaled in [0,1]
*
{
double alpha = 0.5*(2*R - G - B);
double beta = 0.866025403784439*(G - B);
-
-
+
+
*I = (R + G + B)/3;
-
+
if(*I > 0)
{
*S = 1 - MIN3(R,G,B) / *I;
*H = atan2(beta, alpha)*(180/M_PI);
-
+
if(*H < 0)
*H += 360;
}
}
-/**
+/**
* @brief Convert a Hue-Saturation-Intesity (HSI) color to sRGB
- *
+ *
* @param R, G, B pointers to hold the result
* @param H, S, I the input HSI values
*
- * The input values are assumed to be scaled as
+ * The input values are assumed to be scaled as
* 0 <= H < 360,
* 0 <= S <= 1,
- * 0 <= I <= 1.
+ * 0 <= I <= 1.
* The output sRGB values are scaled between 0 and 1. This is the inverse
* transformation of Rgb2Hsi.
*
void Hsi2Rgb(double *R, double *G, double *B, double H, double S, double I)
{
H -= 360*floor(H/360);
-
+
if(H < 120)
{
*B = I*(1 - S);
/*
* == CIE color transformations ==
- *
+ *
* The following routines implement transformations between sRGB and
- * the CIE color spaces XYZ, L*a*b, L*u*v*, and L*C*H*. These
+ * the CIE color spaces XYZ, L*a*b, L*u*v*, and L*C*H*. These
* transforms assume a 2 degree observer angle and a D65 illuminant.
*/
* @param X, Y, Z pointers to hold the result
* @param R, G, B the input sRGB values
*
- * Poynton, "Frequently Asked Questions About Color," page 10
+ * Poynton, "Frequently Asked Questions About Color," page 10
* Wikipedia: http://en.wikipedia.org/wiki/SRGB
* Wikipedia: http://en.wikipedia.org/wiki/CIE_1931_color_space
*/
* Wikipedia: http://en.wikipedia.org/wiki/CIE_1931_color_space
*/
void Xyz2Rgb(double *R, double *G, double *B, double X, double Y, double Z)
-{
+{
double R1, B1, G1, Min;
-
-
+
+
R1 = (double)( 3.2406*X - 1.5372*Y - 0.4986*Z);
G1 = (double)(-0.9689*X + 1.8758*Y + 0.0415*Z);
B1 = (double)( 0.0557*X - 0.2040*Y + 1.0570*Z);
-
+
Min = MIN3(R1, G1, B1);
-
+
/* Force nonnegative values so that gamma correction is well-defined. */
if(Min < 0)
{
* @param X, Y, Z pointers to hold the result
* @param L, a, b the input L*a*b* values
*
- * Wikipedia: http://en.wikipedia.org/wiki/Lab_color_space
+ * Wikipedia: http://en.wikipedia.org/wiki/Lab_color_space
*/
void Lab2Xyz(double *X, double *Y, double *Z, double L, double a, double b)
{
* Wikipedia: http://en.wikipedia.org/wiki/CIELUV_color_space
*/
void Xyz2Luv(double *L, double *u, double *v, double X, double Y, double Z)
-{
+{
double u1, v1, Denom;
-
+
if((Denom = X + 15*Y + 3*Z) > 0)
{
{
*Y = (L + 16)/116;
*Y = WHITEPOINT_Y*LABINVF(*Y);
-
+
if(L != 0)
{
u /= L;
v /= L;
}
-
+
u = u/13 + WHITEPOINT_U;
v = v/13 + WHITEPOINT_V;
*X = (*Y) * ((9*u)/(4*v));
void Xyz2Lch(double *L, double *C, double *H, double X, double Y, double Z)
{
double a, b;
-
-
+
+
Xyz2Lab(L, &a, &b, X, Y, Z);
*C = sqrt(a*a + b*b);
*H = atan2(b, a)*180.0/M_PI;
-
+
if(*H < 0)
*H += 360;
}
{
double a = C * cos(H*(M_PI/180.0));
double b = C * sin(H*(M_PI/180.0));
-
-
+
+
Lab2Xyz(X, Y, Z, L, a, b);
}
}
-/*
+/*
* == Glue functions for multi-stage transforms ==
*/