aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--doc/info/chap/colour-spaces.texinfo13
-rw-r--r--doc/info/chap/functions.texinfo6
-rw-r--r--src/convert.c68
-rw-r--r--src/libcolour.c46
-rw-r--r--src/libcolour.h84
-rw-r--r--src/test.c200
6 files changed, 325 insertions, 92 deletions
diff --git a/doc/info/chap/colour-spaces.texinfo b/doc/info/chap/colour-spaces.texinfo
index eb26ba0..a214feb 100644
--- a/doc/info/chap/colour-spaces.texinfo
+++ b/doc/info/chap/colour-spaces.texinfo
@@ -403,21 +403,8 @@ function is available for your use:
@table @code
@item double libcolour_srgb_encode(double x)
Applies the sRGB transfer function.
-It's full code is
-@example
-return x <= 0.0031306684425217108
- ? 12.92 * x
- : 1.055 * pow(x, 1 / 2.4) - 0.055;
-@end example
-
@item double libcolour_srgb_decode(double x)
Unapplies the sRGB transfer function.
-It's full code is
-@example
-return x <= 0.040448236277380506
- ? x / 12.92
- : pow((x + 0.055) / 1.055, 2.4);
-@end example
@end table
diff --git a/doc/info/chap/functions.texinfo b/doc/info/chap/functions.texinfo
index b47a584..9ddefdf 100644
--- a/doc/info/chap/functions.texinfo
+++ b/doc/info/chap/functions.texinfo
@@ -18,7 +18,11 @@ Described in @ref{sRGB}.
@item int libcolour_delta_e(const libcolour_colour_t*, const libcolour_colour_t*, double*)
Calculates the @math{\Delta E^*_{ab}} distance
-(the distance in CIE L*a*b*) of two colours.
+(the distance in CIE L*a*b*) of two colours,
+and outputs it to the last parameter.
+Returns 0 on success and @math{-1} one error.
+This function fails if and only if
+@code{libcolour_convert} fails.
@item int libcolour_proper(libcolour_colour_t*)
Sets any member or submember that may be
diff --git a/src/convert.c b/src/convert.c
index 0ca9ef1..e229583 100644
--- a/src/convert.c
+++ b/src/convert.c
@@ -84,9 +84,9 @@ static void to_rgb(const libcolour_colour_t* restrict from, libcolour_rgb_t* res
to->B = pow(to->B, 1 / to->gamma);
break;
case LIBCOLOUR_ENCODING_TYPE_REGULAR:
- to->R <= to->transition ? to->slope * to->R : (1 + to->offset) * pow(to->R, 1 / to->gamma) - to->offset;
- to->G <= to->transition ? to->slope * to->G : (1 + to->offset) * pow(to->G, 1 / to->gamma) - to->offset;
- to->B <= to->transition ? to->slope * to->B : (1 + to->offset) * pow(to->B, 1 / to->gamma) - to->offset;
+ to->R = to->R <= to->transition ? to->slope * to->R : (1 + to->offset) * pow(to->R, 1 / to->gamma) - to->offset;
+ to->G = to->G <= to->transition ? to->slope * to->G : (1 + to->offset) * pow(to->G, 1 / to->gamma) - to->offset;
+ to->B = to->B <= to->transition ? to->slope * to->B : (1 + to->offset) * pow(to->B, 1 / to->gamma) - to->offset;
break;
case LIBCOLOUR_ENCODING_TYPE_CUSTOM:
to->R = (to->to_encoded_red)(to->R);
@@ -107,9 +107,9 @@ static void to_rgb(const libcolour_colour_t* restrict from, libcolour_rgb_t* res
to->B = pow(to->B, to->gamma);
break;
case LIBCOLOUR_ENCODING_TYPE_REGULAR:
- to->R <= to->transitioninv ? to->R * to->slope : pow((to->R + to->offset) / (1 + to->offset), to->gamma);
- to->G <= to->transitioninv ? to->G * to->slope : pow((to->G + to->offset) / (1 + to->offset), to->gamma);
- to->B <= to->transitioninv ? to->B * to->slope : pow((to->B + to->offset) / (1 + to->offset), to->gamma);
+ to->R = to->R <= to->transitioninv ? to->R * to->slope : pow((to->R + to->offset) / (1 + to->offset), to->gamma);
+ to->G = to->G <= to->transitioninv ? to->G * to->slope : pow((to->G + to->offset) / (1 + to->offset), to->gamma);
+ to->B = to->B <= to->transitioninv ? to->B * to->slope : pow((to->B + to->offset) / (1 + to->offset), to->gamma);
break;
case LIBCOLOUR_ENCODING_TYPE_CUSTOM:
to->R = (to->to_decoded_red)(to->R);
@@ -128,19 +128,33 @@ static void to_rgb(const libcolour_colour_t* restrict from, libcolour_rgb_t* res
static void ciexyz_to_srgb(const libcolour_ciexyz_t* restrict from, libcolour_srgb_t* restrict to)
{
double X = from->X, Y = from->Y, Z = from->Z;
- to->R = 3.240450 * X + -1.537140 * Y + -0.4985320 * Z;
- to->G = -0.969266 * X + 1.876010 * Y + 0.0415561 * Z;
- to->B = 0.0556434 * X + -0.204026 * Y + 1.0572300 * Z;
+#define MULTIPLY(CX, CY, CZ) ((CX) * X + (CY) * Y + (CZ) * Z)
+ to->R = MULTIPLY(3.240446254647737500675930277794, -1.537134761820080575134284117667, -0.498530193022728718155178739835);
+ to->G = MULTIPLY(-0.969266606244679751469561779231, 1.876011959788370209167851498933, 0.041556042214430065351304932619);
+ to->B = MULTIPLY(0.055643503564352832235773149705, -0.204026179735960239147729566866, 1.057226567722703292062647051353);
+#undef MULTIPLY
}
-static inline double srgb_encode(double x)
+static inline double srgb_encode(double t)
{
- return x <= 0.0031306684425217108 ? 12.92 * x : 1.055 * pow(x, 1 / 2.4) - 0.055;
+ double sign = 1;
+ if (t < 0) {
+ t = -t;
+ sign = -1;
+ }
+ t = t <= 0.0031306684425217108 ? 12.92 * t : 1.055 * pow(t, 1 / 2.4) - 0.055;
+ return t * sign;
}
-static inline double srgb_decode(double x)
+static inline double srgb_decode(double t)
{
- return x <= 0.040448236277380506 ? x / 12.92 : pow((x + 0.055) / 1.055, 2.4);
+ double sign = 1;
+ if (t < 0) {
+ t = -t;
+ sign = -1;
+ }
+ t = t <= 0.040448236277380506 ? t / 12.92 : pow((t + 0.055) / 1.055, 2.4);
+ return t * sign;
}
static void srgb_to_srgb(const libcolour_srgb_t* restrict from, libcolour_srgb_t* restrict to)
@@ -161,9 +175,13 @@ static void srgb_to_srgb(const libcolour_srgb_t* restrict from, libcolour_srgb_t
static void yiq_to_srgb(const libcolour_yiq_t* restrict from, libcolour_srgb_t* restrict to)
{
double Y = from->Y, I = from->I, Q = from->Q;
- to->R = Y + I * 0.956 + Q * 0.621;
- to->G = Y - I * 0.272 - Q * 0.647;
- to->B = Y - I * 1.106 + Q * 1.703;
+ to->R = Y + I * 0.95629483232089407263032398986979387700557708740234 + Q * 0.62102512544472865396727456754888407886028289794922;
+ to->G = Y - I * 0.27212147408397735492968649850809015333652496337891 - Q * 0.64738095351761570928061928498209454119205474853516;
+ to->B = Y - I * 1.10698990856712820018969978264067322015762329101562 + Q * 1.70461497549882934343656870623817667365074157714844;
+ /* ⎛1 1000 cos 33° / 877 1000 sin 33° / 877 ⎞
+ ⎜1 9500 sin 33° / 24067 - 299000 * cos 33° / 514799 -9500 cos 33° / 24067 - 299000 * sin 33° / 514799⎟
+ ⎝1 -250 sin 33° / 123 250 cos 33° / 123 ⎠
+ */
}
static void ydbdr_to_srgb(const libcolour_ydbdr_t* restrict from, libcolour_srgb_t* restrict to)
@@ -318,9 +336,11 @@ static void srgb_to_ciexyz(const libcolour_srgb_t* restrict from, libcolour_ciex
} else {
R = from->R, G = from->G, B = from->B;
}
- to->X = 0.4124564 * R + 0.3575761 * G + 0.1804375 * B;
- to->Y = 0.2126729 * R + 0.7151522 * G + 0.0721750 * B;
- to->Z = 0.0193339 * R + 0.1191920 * G + 0.9503041 * B;
+#define MULTIPLIY(CR, CG, CB) ((CR) * R + (CG) * G + (CB) * B)
+ to->X = MULTIPLIY(0.412457445582367576708548995157, 0.357575865245515878143578447634, 0.180437247826399665973085006954);
+ to->Y = MULTIPLIY(0.212673370378408277403536885686, 0.715151730491031756287156895269, 0.072174899130559869164791564344);
+ to->Z = MULTIPLIY(0.019333942761673460208893260415, 0.119191955081838593666354597644, 0.950302838552371742508739771438);
+#undef MULTIPLIY
}
static void ciexyy_to_ciexyz(const libcolour_ciexyy_t* restrict from, libcolour_ciexyz_t* restrict to)
@@ -630,9 +650,13 @@ static void to_yiq(const libcolour_colour_t* restrict from, libcolour_yiq_t* res
r = tmp.srgb.R;
g = tmp.srgb.G;
b = tmp.srgb.B;
- to->Y = r * 0.29893602129377540 + g * 0.5870430744511212 + b * 0.11402090425510336;
- to->I = r * 0.59594574307079930 - g * 0.2743886357457892 - b * 0.32155710732501010;
- to->Q = r * 0.21149734030682846 - g * 0.5229106903029739 + b * 0.31141334999614540;
+ to->Y = r * 0.299 + g * 0.587 + b * 0.114;
+ to->I = r * 0.59571613491277464191853141528554260730743408203125 /* (0.877 cos 33°)(1 - 0.299) - (0.492 sin 33°)(-0.299) */
+ - g * 0.27445283783925644716106262421817518770694732666016 /* (0.877 cos 33°)(-0.587) - (0.492 sin 33°)(-0.587) */
+ - b * 0.32126329707351808373516632855171337723731994628906; /* (0.877 cos 33°)(-0.114) - (0.492 sin 33°)(1 - 0.114) */
+ to->Q = r * 0.21145640212011795888713550084503367543220520019531 /* (0.877 sin 33°)(1 - 0.299) + (0.492 cos 33°)(-0.299) */
+ - g * 0.52259104529161115593183239980135113000869750976562 /* (0.877 sin 33°)(-0.587) + (0.492 cos 33°)(-0.587) */
+ + b * 0.31113464317149330806699936147197149693965911865234; /* (0.877 sin 33°)(-0.114) + (0.492 cos 33°)(1 - 0.114) */
return;
}
}
diff --git a/src/libcolour.c b/src/libcolour.c
index 4ccb158..60dab61 100644
--- a/src/libcolour.c
+++ b/src/libcolour.c
@@ -26,14 +26,26 @@
-double libcolour_srgb_encode(double x)
+double libcolour_srgb_encode(double t)
{
- return x <= 0.0031306684425217108 ? 12.92 * x : 1.055 * pow(x, 1 / 2.4) - 0.055;
+ double sign = 1;
+ if (t < 0) {
+ t = -t;
+ sign = -1;
+ }
+ t = t <= 0.0031306684425217108 ? 12.92 * t : 1.055 * pow(t, 1 / 2.4) - 0.055;
+ return t * sign;
}
-double libcolour_srgb_decode(double x)
+double libcolour_srgb_decode(double t)
{
- return x <= 0.040448236277380506 ? x / 12.92 : pow((x + 0.055) / 1.055, 2.4);
+ double sign = 1;
+ if (t < 0) {
+ t = -t;
+ sign = -1;
+ }
+ t = t <= 0.040448236277380506 ? t / 12.92 : pow((t + 0.055) / 1.055, 2.4);
+ return t * sign;
}
@@ -264,14 +276,24 @@ static int invert_(size_t n, double (*Minvp)[n][n], double (*Mp)[n][n])
static double transfer_function_l_star(double t)
{
- t = (t > 216. / 24389.) ? cbrt(t) : t * 841. / 108. + 4. / 29.;
- return t * 1.16 - 0.16;
+ double sign = 1;
+ if (t < 0) {
+ t = -t;
+ sign = -1;
+ }
+ t = t > 216. / 24389. ? 1.16 * cbrt(t) - 0.16 : t * 24389. / 2700.;
+ return t * sign;
}
static double invtransfer_function_l_star(double t)
{
- t = (t + 0.16) / 1.16;
- return (t > 6. / 29.) ? t * t * t : (t - 4. / 29.) * 108 / 841;
+ double sign = 1;
+ if (t < 0) {
+ t = -t;
+ sign = -1;
+ }
+ t = t > 0.08 ? (((1000000. * t + 480000.) * t + 76800.) * t + 4096.) / 1560896.0 : t * 2700. / 24389.;
+ return t * sign;
}
@@ -306,16 +328,22 @@ int libcolour_get_rgb_colour_space(libcolour_rgb_t* cs, libcolour_rgb_colour_spa
case LIBCOLOUR_RGB_COLOUR_SPACE_CUSTOM_FROM_MEASUREMENTS:
if (get_matrices(cs))
return -1;
+ if (cs->encoding_type == LIBCOLOUR_ENCODING_TYPE_REGULAR)
+ cs->transitioninv = cs->transition * cs->slope;
return 0;
case LIBCOLOUR_RGB_COLOUR_SPACE_CUSTOM_FROM_MATRIX:
if (invert(cs->Minv, cs->M, 3) || get_primaries(cs))
return -1;
+ if (cs->encoding_type == LIBCOLOUR_ENCODING_TYPE_REGULAR)
+ cs->transitioninv = cs->transition * cs->slope;
return 0;
case LIBCOLOUR_RGB_COLOUR_SPACE_CUSTOM_FROM_INV_MATRIX:
if (invert(cs->M, cs->Minv, 3) || get_primaries(cs))
return -1;
+ if (cs->encoding_type == LIBCOLOUR_ENCODING_TYPE_REGULAR)
+ cs->transitioninv = cs->transition * cs->slope;
return 0;
case LIBCOLOUR_RGB_COLOUR_SPACE_SRGB:
@@ -377,7 +405,7 @@ int libcolour_get_rgb_colour_space(libcolour_rgb_t* cs, libcolour_rgb_colour_spa
case LIBCOLOUR_RGB_COLOUR_SPACE_CIE_RGB:
cs->red = XYY(0.7350, 0.2650);
- cs->green = XYY(0.2640, 0.7170);
+ cs->green = XYY(0.2740, 0.7170);
cs->blue = XYY(0.1670, 0.0090);
cs->white = LIBCOLOUR_ILLUMINANT_E;
cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_SIMPLE;
diff --git a/src/libcolour.h b/src/libcolour.h
index c68cf11..fe53a4e 100644
--- a/src/libcolour.h
+++ b/src/libcolour.h
@@ -22,47 +22,49 @@
-#define LIBCOLOUR_ILLUMINANT_A (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.44757, .y = 0.40745, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_B (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.34842, .y = 0.35161, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_C (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.31006, .y = 0.31616, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_D50 (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.34567, .y = 0.35850, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_D55 (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.33242, .y = 0.34743, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_D65 (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.31271, .y = 0.32902, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_D75 (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.29902, .y = 0.31485, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_E (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 1. / 3, .y = 1. / 3, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_F1 (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.31310, .y = 0.33727, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_F2 (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.37208, .y = 0.37529, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_F3 (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.40910, .y = 0.39430, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_F4 (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.44018, .y = 0.40329, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_F5 (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.31379, .y = 0.34531, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_F6 (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.37790, .y = 0.38835, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_F7 (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.31292, .y = 0.32933, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_F8 (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.34588, .y = 0.35875, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_F9 (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.37417, .y = 0.37281, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_F10 (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.34609, .y = 0.35986, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_F11 (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.38052, .y = 0.37713, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_F12 (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.43695, .y = 0.40441, .Y = 1}
-
-#define LIBCOLOUR_ILLUMINANT_A_10DEG_OBS (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.45117, .y = 0.40594, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_B_10DEG_OBS (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.34980, .y = 0.35270, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_C_10DEG_OBS (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.31039, .y = 0.31905, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_D50_10DEG_OBS (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.34773, .y = 0.35952, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_D55_10DEG_OBS (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.33411, .y = 0.34877, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_D65_10DEG_OBS (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.31382, .y = 0.33100, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_D75_10DEG_OBS (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.29968, .y = 0.31740, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_E_10DEG_OBS (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 1. / 3, .y = 1. / 3, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_F1_10DEG_OBS (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.31811, .y = 0.33559, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_F2_10DEG_OBS (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.37925, .y = 0.36733, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_F3_10DEG_OBS (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.41761, .y = 0.38324, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_F4_10DEG_OBS (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.44920, .y = 0.39074, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_F5_10DEG_OBS (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.31975, .y = 0.34246, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_F6_10DEG_OBS (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.38660, .y = 0.37847, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_F7_10DEG_OBS (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.31569, .y = 0.32960, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_F8_10DEG_OBS (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.34902, .y = 0.35939, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_F9_10DEG_OBS (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.37829, .y = 0.37045, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_F10_10DEG_OBS (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.35090, .y = 0.35444, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_F11_10DEG_OBS (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.38541, .y = 0.37123, .Y = 1}
-#define LIBCOLOUR_ILLUMINANT_F12_10DEG_OBS (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = 0.44256, .y = 0.39717, .Y = 1}
+#define LIBCOLOUR_ILLUMINANT__(x__, y__) (libcolour_ciexyy_t){.model = LIBCOLOUR_CIEXYY, .x = x__, .y = y__, .Y = 1}
+
+#define LIBCOLOUR_ILLUMINANT_A LIBCOLOUR_ILLUMINANT__(0.447573514098910552050369915378, 0.407439444306660847328060981454)
+#define LIBCOLOUR_ILLUMINANT_B LIBCOLOUR_ILLUMINANT__(0.348407693041403399014654951316, 0.351617234807268863594487129376)
+#define LIBCOLOUR_ILLUMINANT_C LIBCOLOUR_ILLUMINANT__(0.310058473730255412803558101587, 0.316149707523236456196968902077)
+#define LIBCOLOUR_ILLUMINANT_D50 LIBCOLOUR_ILLUMINANT__(0.345668037029273123028616510055, 0.358496838937619077825047497754)
+#define LIBCOLOUR_ILLUMINANT_D55 LIBCOLOUR_ILLUMINANT__(0.332424102468830251488896010414, 0.347428039087666229445261478759)
+#define LIBCOLOUR_ILLUMINANT_D65 LIBCOLOUR_ILLUMINANT__(0.312726871026564878786047074755, 0.329023206641284038376227272238)
+#define LIBCOLOUR_ILLUMINANT_D75 LIBCOLOUR_ILLUMINANT__(0.299022300412497055166483050925, 0.314852737888341893679466920730)
+#define LIBCOLOUR_ILLUMINANT_E LIBCOLOUR_ILLUMINANT__(1. / 3, 1. / 3)
+#define LIBCOLOUR_ILLUMINANT_F1 LIBCOLOUR_ILLUMINANT__(0.313062433035651010992950205036, 0.337106477918307445573731229160)
+#define LIBCOLOUR_ILLUMINANT_F2 LIBCOLOUR_ILLUMINANT__(0.372068154452825539113547392844, 0.375122558203110079144693145281)
+#define LIBCOLOUR_ILLUMINANT_F3 LIBCOLOUR_ILLUMINANT__(0.409090035308107391465171076561, 0.394117134255365986206243178458)
+#define LIBCOLOUR_ILLUMINANT_F4 LIBCOLOUR_ILLUMINANT__(0.440181095827666568620628595454, 0.403090691158138336724903183494)
+#define LIBCOLOUR_ILLUMINANT_F5 LIBCOLOUR_ILLUMINANT__(0.313756583095696484075887155996, 0.345160794752101929283583103825)
+#define LIBCOLOUR_ILLUMINANT_F6 LIBCOLOUR_ILLUMINANT__(0.377882361062687466279896852939, 0.388192885537868959122675960316)
+#define LIBCOLOUR_ILLUMINANT_F7 LIBCOLOUR_ILLUMINANT__(0.312852472915475354753311876266, 0.329174178033567632617462095368)
+#define LIBCOLOUR_ILLUMINANT_F8 LIBCOLOUR_ILLUMINANT__(0.345805753550315952971061506105, 0.358617583214377477762724311106)
+#define LIBCOLOUR_ILLUMINANT_F9 LIBCOLOUR_ILLUMINANT__(0.374105245592801061160770359493, 0.372672400924498159469067104510)
+#define LIBCOLOUR_ILLUMINANT_F10 LIBCOLOUR_ILLUMINANT__(0.346086913993929323751785886998, 0.358751605952200347537939251197)
+#define LIBCOLOUR_ILLUMINANT_F11 LIBCOLOUR_ILLUMINANT__(0.380537485483030235577928124258, 0.376915309293930078649026427229)
+#define LIBCOLOUR_ILLUMINANT_F12 LIBCOLOUR_ILLUMINANT__(0.437023901312296902954557253906, 0.404214327891585678553809657387)
+
+#define LIBCOLOUR_ILLUMINANT_A_10DEG_OBS LIBCOLOUR_ILLUMINANT__(0.451173939693730152722395132514, 0.405936604212625562482230634487)
+#define LIBCOLOUR_ILLUMINANT_B_10DEG_OBS LIBCOLOUR_ILLUMINANT__(0.349819801494100579564161535018, 0.352687989927865819250740742063)
+#define LIBCOLOUR_ILLUMINANT_C_10DEG_OBS LIBCOLOUR_ILLUMINANT__(0.310388663270034004248998371622, 0.319050711366790695766582075521)
+#define LIBCOLOUR_ILLUMINANT_D50_10DEG_OBS LIBCOLOUR_ILLUMINANT__(0.347729429961154856698613002663, 0.359522508516545380441442603114)
+#define LIBCOLOUR_ILLUMINANT_D55_10DEG_OBS LIBCOLOUR_ILLUMINANT__(0.334116336430253457745465084372, 0.348766090975953568786849245953)
+#define LIBCOLOUR_ILLUMINANT_D65_10DEG_OBS LIBCOLOUR_ILLUMINANT__(0.313823646938709621689866935412, 0.330998985489933561510156323493)
+#define LIBCOLOUR_ILLUMINANT_D75_10DEG_OBS LIBCOLOUR_ILLUMINANT__(0.299679971345752860223399238748, 0.317403239854836705102769656150)
+#define LIBCOLOUR_ILLUMINANT_E_10DEG_OBS LIBCOLOUR_ILLUMINANT__(1. / 3, 1. / 3)
+#define LIBCOLOUR_ILLUMINANT_F1_10DEG_OBS LIBCOLOUR_ILLUMINANT__(0.318098801070991199502202562144, 0.335489451474129951602520804954)
+#define LIBCOLOUR_ILLUMINANT_F2_10DEG_OBS LIBCOLOUR_ILLUMINANT__(0.379274832262508854174853922814, 0.367227934400669309145115448700)
+#define LIBCOLOUR_ILLUMINANT_F3_10DEG_OBS LIBCOLOUR_ILLUMINANT__(0.417644682102624287267644831445, 0.383124504918675723441623404142)
+#define LIBCOLOUR_ILLUMINANT_F4_10DEG_OBS LIBCOLOUR_ILLUMINANT__(0.449247699162001246087072559021, 0.390605475879083674506375700730)
+#define LIBCOLOUR_ILLUMINANT_F5_10DEG_OBS LIBCOLOUR_ILLUMINANT__(0.319739939104951298443069163113, 0.342367055369128092667807550242)
+#define LIBCOLOUR_ILLUMINANT_F6_10DEG_OBS LIBCOLOUR_ILLUMINANT__(0.386626908526034762658696308790, 0.378372201588893453116924092683)
+#define LIBCOLOUR_ILLUMINANT_F7_10DEG_OBS LIBCOLOUR_ILLUMINANT__(0.315645637312390425766039925293, 0.329508145132134222521358424274)
+#define LIBCOLOUR_ILLUMINANT_F8_10DEG_OBS LIBCOLOUR_ILLUMINANT__(0.348965563721531868424108324689, 0.359317299140994528272585739614)
+#define LIBCOLOUR_ILLUMINANT_F9_10DEG_OBS LIBCOLOUR_ILLUMINANT__(0.378258900384649654480284652891, 0.370371375730762564248976786985)
+#define LIBCOLOUR_ILLUMINANT_F10_10DEG_OBS LIBCOLOUR_ILLUMINANT__(0.350893389986753234666139178444, 0.354302210111646531665030579461)
+#define LIBCOLOUR_ILLUMINANT_F11_10DEG_OBS LIBCOLOUR_ILLUMINANT__(0.385435391037903751776383387551, 0.371094786781121399599214782938)
+#define LIBCOLOUR_ILLUMINANT_F12_10DEG_OBS LIBCOLOUR_ILLUMINANT__(0.442654456042513022584472537346, 0.397060737666593277506166259627)
#define LIBCOLOUR_LIST_MODELS\
diff --git a/src/test.c b/src/test.c
index b5591e0..7d5517c 100644
--- a/src/test.c
+++ b/src/test.c
@@ -16,9 +16,11 @@
*/
#include "libcolour.h"
+#include <math.h>
#include <stdio.h>
+#ifndef SKIP_CONVERT
static int test_convert(libcolour_colour_t* c1, libcolour_colour_t* c2, libcolour_colour_t* c3)
{
double ch1, ch2, ch3;
@@ -230,6 +232,64 @@ static int test_convert_nm_all(void)
return rc;
#undef N
}
+#endif
+
+
+static inline int ftest(double a, double b, double l)
+{
+ return a - l <= b && b <= a + l;
+}
+
+
+#define test_rgb(COLOUR_SPACE, ...) test_rgb_(COLOUR_SPACE, #COLOUR_SPACE, __VA_ARGS__)
+static int test_rgb_(enum libcolour_rgb_colour_space colour_space, const char* name,
+ double r, double g, double b, double x, double y, double z,
+ double xx, double yy, double zz)
+{
+ libcolour_colour_t c1, c2;
+
+ c1.model = LIBCOLOUR_RGB;
+ c2.model = LIBCOLOUR_CIEXYZ;
+ c1.rgb.with_gamma = 0;
+ c1.rgb.R = r, c1.rgb.G = g, c1.rgb.B = b;
+ if (libcolour_get_rgb_colour_space(&c1.rgb, colour_space) ||
+ libcolour_convert(&c1, &c2)) {
+ printf("%s failed without gamma\n", name);
+ return 0;
+ } else if (!ftest(c2.ciexyz.X, x, 0.0001) ||
+ !ftest(c2.ciexyz.Y, y, 0.0001) ||
+ !ftest(c2.ciexyz.Z, z, 0.0001)) {
+ printf("%s failed without gamma\n", name);
+ printf("%.6lf, %.6lf, %.6lf\n", c2.ciexyz.X, c2.ciexyz.Y, c2.ciexyz.Z);
+ return 0;
+ }
+
+ c1.model = LIBCOLOUR_RGB;
+ c2.model = LIBCOLOUR_CIEXYZ;
+ c1.rgb.with_gamma = 1;
+ c1.rgb.R = r, c1.rgb.G = g, c1.rgb.B = b;
+ if (libcolour_get_rgb_colour_space(&c1.rgb, colour_space) ||
+ libcolour_convert(&c1, &c2)) {
+ printf("%s failed with gamma\n", name);
+ return 0;
+ } else if (!ftest(c2.ciexyz.X, xx, 0.0001) ||
+ !ftest(c2.ciexyz.Y, yy, 0.0001) ||
+ !ftest(c2.ciexyz.Z, zz, 0.0001)) {
+ printf("%s failed with gamma\n", name);
+ printf("%.6lf, %.6lf, %.6lf\n", c2.ciexyz.X, c2.ciexyz.Y, c2.ciexyz.Z);
+ return 0;
+ }
+
+ if (libcolour_convert(&c2, &c1) ||
+ !ftest(c1.rgb.R, r, 0.0000001) ||
+ !ftest(c1.rgb.G, g, 0.0000001) ||
+ !ftest(c1.rgb.B, b, 0.0000001)) {
+ printf("%s failed, encode\n", name);
+ return 0;
+ }
+
+ return 1;
+}
/**
@@ -242,23 +302,151 @@ static int test_convert_nm_all(void)
int main(int argc, char* argv[])
{
int r, rc = 0;
+ libcolour_colour_t c1, c2;
+ double t1, t2;
+#ifndef SKIP_CONVERT
r = test_convert_nm_all();
if (r < 0)
goto fail;
if (!r)
rc = 1;
+#else
+ (void) r;
+#endif
+
+ c1.model = LIBCOLOUR_SRGB;
+ c1.srgb.R = 0.02, c1.srgb.G = 0.5, c1.srgb.B = 0.9;
+ c1.srgb.with_gamma = 0;
+ c2.model = LIBCOLOUR_RGB;
+ c2.rgb.with_gamma = 0;
+ if (libcolour_get_rgb_colour_space(&c2.rgb, LIBCOLOUR_RGB_COLOUR_SPACE_SRGB)) {
+ printf("LIBCOLOUR_RGB_COLOUR_SPACE_SRGB failed\n"), rc = 0;
+ goto colour_spaces_done;
+ }
+ if (c2.rgb.white_r != 1 || c2.rgb.white_g != 1 || c2.rgb.white_b != 1 ||
+ c2.rgb.red.model != LIBCOLOUR_CIEXYY || c2.rgb.green.model != LIBCOLOUR_CIEXYY ||
+ c2.rgb.blue.model != LIBCOLOUR_CIEXYY || c2.rgb.white.model != LIBCOLOUR_CIEXYY ||
+ c2.rgb.colour_space != LIBCOLOUR_RGB_COLOUR_SPACE_SRGB || c2.rgb.gamma != 2.4 ||
+ c2.rgb.encoding_type != LIBCOLOUR_ENCODING_TYPE_REGULAR || c2.rgb.slope != 12.92
+ || c2.rgb.offset != 0.055 || c2.rgb.transitioninv != c2.rgb.transition * c2.rgb.slope ||
+ !ftest(c2.rgb.transition, 0.00313067, 0.00000001)) {
+ printf("LIBCOLOUR_RGB_COLOUR_SPACE_SRGB failed\n"), rc = 0;
+ goto colour_spaces_done;
+ }
+ t1 = c2.rgb.transition * c2.rgb.slope;
+ t2 = (1 + c2.rgb.offset) * pow(c2.rgb.transition, 1 / c2.rgb.gamma) - c2.rgb.offset;
+ if (!ftest(t1, t2, 0.0000001) || c2.rgb.white.Y != 1 ||
+ c2.rgb.red.x != 0.64 || c2.rgb.red.y != 0.33 || !ftest(c2.rgb.red.Y, 0.21265, 0.00005) ||
+ c2.rgb.green.x != 0.30 || c2.rgb.green.y != 0.60 || !ftest(c2.rgb.green.Y, 0.71515, 0.00005) ||
+ c2.rgb.blue.x != 0.15 || c2.rgb.blue.y != 0.06 || !ftest(c2.rgb.blue.Y, 0.07215, 0.00005) ||
+ !ftest(c2.rgb.white.x, 0.312727, 0.000001) || !ftest(c2.rgb.white.y, 0.329023, 0.000001) ||
+ !ftest(c2.rgb.red.Y + c2.rgb.green.Y + c2.rgb.blue.Y, 1, 0.00000001)) {
+ printf("LIBCOLOUR_RGB_COLOUR_SPACE_SRGB failed\n"), rc = 0;
+ goto colour_spaces_done;
+ }
+ if (libcolour_convert(&c1, &c2) ||
+ !ftest(c1.srgb.R, c2.rgb.R, 0.0000001) ||
+ !ftest(c1.srgb.G, c2.rgb.G, 0.0000001) ||
+ !ftest(c1.srgb.B, c2.rgb.B, 0.0000001)) {
+ printf("LIBCOLOUR_RGB_COLOUR_SPACE_SRGB failed\n"), rc = 0;
+ goto colour_spaces_done;
+ }
+ if (libcolour_convert(&c2, &c1) ||
+ !ftest(c1.srgb.R, c2.rgb.R, 0.0000001) ||
+ !ftest(c1.srgb.G, c2.rgb.G, 0.0000001) ||
+ !ftest(c1.srgb.B, c2.rgb.B, 0.0000001)) {
+ printf("LIBCOLOUR_RGB_COLOUR_SPACE_SRGB failed\n"), rc = 0;
+ goto colour_spaces_done;
+ }
+
+ c1.model = c2.model = LIBCOLOUR_CIELAB;
+ c1.cielab.L = 30, c2.cielab.L = 80;
+ c1.cielab.a = 40, c2.cielab.a = -10;
+ c1.cielab.b = -50, c2.cielab.b = -40;
+ if (libcolour_delta_e(&c1, &c2, &t1) || !ftest(t1, 71.4142842854285, 0.0000001))
+ printf("libcolour_delta_e failed\n"), rc = 0;
+
+ rc &= test_rgb(LIBCOLOUR_RGB_COLOUR_SPACE_ADOBE_RGB, 0.3, 0.2, 0.9,
+ 0.379497, 0.282430, 0.914245, 0.195429, 0.098925, 0.790020);
+
+ rc &= test_rgb(LIBCOLOUR_RGB_COLOUR_SPACE_APPLE_RGB, 0.3, 0.2, 0.9,
+ 0.364212, 0.282789, 0.866008, 0.221570, 0.134028, 0.773782);
+
+ rc &= test_rgb(LIBCOLOUR_RGB_COLOUR_SPACE_BEST_RGB, 0.3, 0.2, 0.9,
+ 0.345007, 0.246779, 0.736029, 0.151406, 0.064655, 0.647212);
+
+ rc &= test_rgb(LIBCOLOUR_RGB_COLOUR_SPACE_BETA_RGB, 0.3, 0.2, 0.9,
+ 0.342837, 0.253386, 0.714198, 0.146437, 0.066824, 0.623382);
+
+ rc &= test_rgb(LIBCOLOUR_RGB_COLOUR_SPACE_BRUCE_RGB, 0.3, 0.2, 0.9,
+ 0.368857, 0.276910, 0.915272, 0.191184, 0.096699, 0.791486);
+
+ rc &= test_rgb(LIBCOLOUR_RGB_COLOUR_SPACE_CIE_RGB, 0.3, 0.2, 0.9,
+ 0.389293, 0.225188, 0.892857, 0.202678, 0.044608, 0.785312);
+
+ rc &= test_rgb(LIBCOLOUR_RGB_COLOUR_SPACE_COLORMATCH_RGB, 0.3, 0.2, 0.9,
+ 0.337557, 0.274378, 0.651989, 0.186858, 0.123210, 0.581381);
+
+ rc &= test_rgb(LIBCOLOUR_RGB_COLOUR_SPACE_DON_RGB_4, 0.3, 0.2, 0.9,
+ 0.344990, 0.251411, 0.727872, 0.150504, 0.066348, 0.638058);
+
+ rc &= test_rgb(LIBCOLOUR_RGB_COLOUR_SPACE_ECI_RGB, 0.3, 0.2, 0.9,
+ 0.353021, 0.286400, 0.695202, 0.196733, 0.134157, 0.630279);
+
+ rc &= test_rgb(LIBCOLOUR_RGB_COLOUR_SPACE_ECI_RGB_V2, 0.3, 0.2, 0.9,
+ 0.353021, 0.286400, 0.695202, 0.149594, 0.097238, 0.579927);
+
+ rc &= test_rgb(LIBCOLOUR_RGB_COLOUR_SPACE_EKTA_SPACE_PS5, 0.3, 0.2, 0.9,
+ 0.320377, 0.229160, 0.713291, 0.127134, 0.043253, 0.622392);
+
+ rc &= test_rgb(LIBCOLOUR_RGB_COLOUR_SPACE_NTSC_RGB, 0.3, 0.2, 0.9,
+ 0.397081, 0.310031, 1.017821, 0.235650, 0.156675, 0.906707);
+
+ rc &= test_rgb(LIBCOLOUR_RGB_COLOUR_SPACE_PAL_SECAM_RGB, 0.3, 0.2, 0.9,
+ 0.357972, 0.272130, 0.877151, 0.208580, 0.120322, 0.769056);
+
+ rc &= test_rgb(LIBCOLOUR_RGB_COLOUR_SPACE_PROPHOTO_RGB, 0.3, 0.2, 0.9,
+ 0.294559, 0.228864, 0.742689, 0.124735, 0.072340, 0.682655);
+
+ rc &= test_rgb(LIBCOLOUR_RGB_COLOUR_SPACE_SMPTE_C_RGB, 0.3, 0.2, 0.9,
+ 0.363595, 0.281822, 0.890350, 0.216773, 0.131311, 0.783348);
+
+ rc &= test_rgb(LIBCOLOUR_RGB_COLOUR_SPACE_WIDE_GAMUT_RGB, 0.3, 0.2, 0.9,
+ 0.367485, 0.237631, 0.706442, 0.170318, 0.052665, 0.614915);
+
+ rc &= test_rgb(LIBCOLOUR_RGB_COLOUR_SPACE_LIGHTROOM_RGB, 0.3, 0.2, 0.9,
+ 0.294559, 0.228864, 0.742689, 0.294559, 0.228864, 0.742689);
+
+ /*
+ TODO test LIBCOLOUR_RGB_COLOUR_SPACE_CUSTOM_FROM_MEASUREMENTS
+ TODO test LIBCOLOUR_RGB_COLOUR_SPACE_CUSTOM_FROM_MATRIX
+ TODO test LIBCOLOUR_RGB_COLOUR_SPACE_CUSTOM_FROM_INV_MATRIX
+ TODO test LIBCOLOUR_RGB_COLOUR_SPACE_DCI_P3_D65
+ TODO test LIBCOLOUR_RGB_COLOUR_SPACE_DCI_P3_THEATER
+ TODO test LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_601_625_LINE
+ TODO test LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_601_525_LINE
+ TODO test LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_709
+ TODO test LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2020
+ TODO test LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2100_EOTF_PQ
+ TODO test LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2100_OOTF_PQ
+ TODO test LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2100_OETF_PQ
+ TODO test LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2100_EOTF_HLG
+ TODO test LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2100_OOTF_HLG
+ TODO test LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2100_OETF_HLG
+ TODO test LIBCOLOUR_RGB_COLOUR_SPACE_SGI_RGB
+ TODO test LIBCOLOUR_RGB_COLOUR_SPACE_SMPTE_240M_RGB
+ */
+
+ /* TODO test transfer functions more rigorously */
+
+ /* TODO test libcolour_convert with single conversions */
+ colour_spaces_done:
/* TODO test libcolour_srgb_encode */
/* TODO test libcolour_srgb_decode */
- /* TODO test libcolour_srgb -> libcolour_rgb[srgb] */
- /* TODO test libcolour_rgb[srgb] -> libcolour_srgb */
- /* TODO test RGB colour spaces */
- /* TODO test libcolour_delta_e */
/* TODO test libcolour_marshal */
/* TODO test libcolour_unmarshal */
- /* TODO test libcolour_convert with single conversions */
-
return rc;
fail:
perror(*argv);