aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/convert.c1068
-rw-r--r--src/libcolour.c717
-rw-r--r--src/libcolour.h301
-rw-r--r--src/test.c657
4 files changed, 0 insertions, 2743 deletions
diff --git a/src/convert.c b/src/convert.c
deleted file mode 100644
index 6d9be16..0000000
--- a/src/convert.c
+++ /dev/null
@@ -1,1068 +0,0 @@
-/**
- * Copyright © 2016 Mattias Andrée <maandree@kth.se>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-#include "libcolour.h"
-
-#include <errno.h>
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-
-#define WASDIV0(x) (isinf(x) || isnan(x))
-#define PI (3.14159265358979323846)
-#define PI2 (2 * PI)
-
-
-
-static void to_rgb(const libcolour_colour_t* restrict from, libcolour_rgb_t* restrict to);
-static void to_srgb(const libcolour_colour_t* restrict from, libcolour_srgb_t* restrict to);
-static void to_ciexyy(const libcolour_colour_t* restrict from, libcolour_ciexyy_t* restrict to);
-static void to_ciexyz(const libcolour_colour_t* restrict from, libcolour_ciexyz_t* restrict to);
-static void to_cielab(const libcolour_colour_t* restrict from, libcolour_cielab_t* restrict to);
-static void to_cieluv(const libcolour_colour_t* restrict from, libcolour_cieluv_t* restrict to);
-static void to_cielchuv(const libcolour_colour_t* restrict from, libcolour_cielchuv_t* restrict to);
-static void to_yiq(const libcolour_colour_t* restrict from, libcolour_yiq_t* restrict to);
-static void to_ydbdr(const libcolour_colour_t* restrict from, libcolour_ydbdr_t* restrict to);
-static void to_yuv(const libcolour_colour_t* restrict from, libcolour_yuv_t* restrict to);
-static void to_ypbpr(const libcolour_colour_t* restrict from, libcolour_ypbpr_t* restrict to);
-static void to_ycgco(const libcolour_colour_t* restrict from, libcolour_ycgco_t* restrict to);
-static void to_cie1960ucs(const libcolour_colour_t* restrict from, libcolour_cie1960ucs_t* restrict to);
-static void to_cieuvw(const libcolour_colour_t* restrict from, libcolour_cieuvw_t* restrict to);
-
-
-static void ciexyz_to_rgb(const libcolour_ciexyz_t* restrict from, libcolour_rgb_t* restrict to)
-{
- double X = from->X, Y = from->Y, Z = from->Z;
- to->R = to->Minv[0][0] * X + to->Minv[0][1] * Y + to->Minv[0][2] * Z;
- to->G = to->Minv[1][0] * X + to->Minv[1][1] * Y + to->Minv[1][2] * Z;
- to->B = to->Minv[2][0] * X + to->Minv[2][1] * Y + to->Minv[2][2] * Z;
-}
-
-#define REGULAR(s, t) ((t) <= (s)->transition ? (s)->slope * (t) : (1 + (s)->offset) * pow((t), 1 / (s)->gamma) - (s)->offset)
-#define INVREGULAR(s, t) ((t) <= (s)->transitioninv ? (t) / (s)->slope : pow(((t) + (s)->offset) / (1 + (s)->offset), (s)->gamma))
-
-static void rgb_encode(libcolour_rgb_t* restrict colour, const libcolour_rgb_t* restrict space)
-{
- double r_sign = 1, g_sign = 1, b_sign = 1;
- switch (space->encoding_type) {
- case LIBCOLOUR_ENCODING_TYPE_LINEAR:
- break;
- case LIBCOLOUR_ENCODING_TYPE_SIMPLE:
- case LIBCOLOUR_ENCODING_TYPE_REGULAR:
- if (colour->R < 0) r_sign = -1, colour->R = -colour->R;
- if (colour->G < 0) g_sign = -1, colour->G = -colour->G;
- if (colour->B < 0) b_sign = -1, colour->B = -colour->B;
- if (space->encoding_type == LIBCOLOUR_ENCODING_TYPE_SIMPLE) {
- colour->R = pow(colour->R, 1 / space->gamma);
- colour->G = pow(colour->G, 1 / space->gamma);
- colour->B = pow(colour->B, 1 / space->gamma);
- } else {
- colour->R = REGULAR(space, colour->R);
- colour->G = REGULAR(space, colour->G);
- colour->B = REGULAR(space, colour->B);
- }
- colour->R *= r_sign;
- colour->G *= g_sign;
- colour->B *= b_sign;
- break;
- case LIBCOLOUR_ENCODING_TYPE_CUSTOM:
- colour->R = (space->to_encoded_red)(colour->R);
- colour->G = (space->to_encoded_green)(colour->G);
- colour->B = (space->to_encoded_blue)(colour->B);
- break;
- default:
- fprintf(stderr, "libcolour: invalid encoding type\n");
- abort();
- }
-}
-
-static void rgb_decode(libcolour_rgb_t* restrict colour, const libcolour_rgb_t* restrict space)
-{
- double r_sign = 1, g_sign = 1, b_sign = 1;
- switch (space->encoding_type) {
- case LIBCOLOUR_ENCODING_TYPE_LINEAR:
- break;
- case LIBCOLOUR_ENCODING_TYPE_SIMPLE:
- case LIBCOLOUR_ENCODING_TYPE_REGULAR:
- if (colour->R < 0) r_sign = -1, colour->R = -colour->R;
- if (colour->G < 0) g_sign = -1, colour->G = -colour->G;
- if (colour->B < 0) b_sign = -1, colour->B = -colour->B;
- if (space->encoding_type == LIBCOLOUR_ENCODING_TYPE_SIMPLE) {
- colour->R = pow(colour->R, space->gamma);
- colour->G = pow(colour->G, space->gamma);
- colour->B = pow(colour->B, space->gamma);
- } else {
- colour->R = INVREGULAR(space, colour->R);
- colour->G = INVREGULAR(space, colour->G);
- colour->B = INVREGULAR(space, colour->B);
- }
- colour->R *= r_sign;
- colour->G *= g_sign;
- colour->B *= b_sign;
- break;
- case LIBCOLOUR_ENCODING_TYPE_CUSTOM:
- colour->R = (space->to_decoded_red)(colour->R);
- colour->G = (space->to_decoded_green)(colour->G);
- colour->B = (space->to_decoded_blue)(colour->B);
- break;
- default:
- fprintf(stderr, "libcolour: invalid encoding type\n");
- abort();
- }
-}
-
-#undef REGULAR
-#undef INVREGULAR
-
-static int rgb_same_gamma(const libcolour_rgb_t* restrict a, const libcolour_rgb_t* restrict b)
-{
- if (a->encoding_type != b->encoding_type)
- return 0;
- switch (a->encoding_type) {
- case LIBCOLOUR_ENCODING_TYPE_SIMPLE:
- return a->gamma == b->gamma;
- case LIBCOLOUR_ENCODING_TYPE_REGULAR:
- return a->gamma == b->gamma &&
- a->offset == b->offset &&
- a->slope == b->slope &&
- a->transition == b->transition;
- case LIBCOLOUR_ENCODING_TYPE_CUSTOM:
- return a->to_encoded_red == b->to_encoded_red &&
- a->to_encoded_green == b->to_encoded_green &&
- a->to_encoded_blue == b->to_encoded_blue &&
- a->to_decoded_red == b->to_decoded_red &&
- a->to_decoded_green == b->to_decoded_green &&
- a->to_decoded_blue == b->to_decoded_blue;
- default:
- return 1;
- }
-}
-
-static void to_rgb(const libcolour_colour_t* restrict from, libcolour_rgb_t* restrict to)
-{
- int have_gamma = 0, with_gamma = to->with_gamma;
- libcolour_ciexyz_t tmp;
- switch (from->model) {
- case LIBCOLOUR_CIEXYZ:
- ciexyz_to_rgb(&from->ciexyz, to);
- break;
- case LIBCOLOUR_RGB:
- if (!memcmp(from->rgb.M, to->M, sizeof(double[3][3]))) {
- have_gamma = from->rgb.with_gamma;
- to->R = from->rgb.R;
- to->G = from->rgb.G;
- to->B = from->rgb.B;
- if (have_gamma && with_gamma && !rgb_same_gamma(&from->rgb, to))
- rgb_decode(to, &from->rgb), have_gamma = 0;
- break;
- }
- /* fall through */
- default:
- tmp.model = LIBCOLOUR_CIEXYZ;
- to_ciexyz(from, &tmp);
- ciexyz_to_rgb(&tmp, to);
- break;
- }
-
- if (have_gamma != with_gamma) {
- if (with_gamma) {
- rgb_encode(to, to);
- } else {
- rgb_decode(to, &from->rgb);
- }
- }
-}
-
-
-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;
-#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 t)
-{
- 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 t)
-{
- double sign = 1;
- if (t < 0) {
- t = -t;
- sign = -1;
- }
- t = t <= 0.0031306684425217108 * 12.92 ? 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)
-{
- if (from->with_gamma == to->with_gamma) {
- *to = *from;
- } else if (to->with_gamma) {
- to->R = srgb_encode(from->R);
- to->G = srgb_encode(from->G);
- to->B = srgb_encode(from->B);
- } else {
- to->R = srgb_decode(from->R);
- to->G = srgb_decode(from->G);
- to->B = srgb_decode(from->B);
- }
-}
-
-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.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)
-{
- double Y = from->Y, Db = from->Db, Dr = from->Dr;
- to->R = Y + Db * 0.000092303716148 - Dr * 0.525912630661865;
- to->G = Y - Db * 0.129132898890509 + Dr * 0.267899328207599;
- to->B = Y + Db * 0.664679059978955 - Dr * 0.000079202543533;
-}
-
-static void ypbpr_to_srgb(const libcolour_ypbpr_t* restrict from, libcolour_srgb_t* restrict to)
-{
- double Y = from->Y, Pb = from->Pb, Pr = from->Pr;
- to->R = Pr + Y;
- to->B = Pb + Y;
- to->G = (Y - to->R * 0.2126 - to->B * 0.0722) / 0.7152;
-}
-
-static void yuv_to_srgb(const libcolour_yuv_t* restrict from, libcolour_srgb_t* restrict to)
-{
- double Y = from->Y, U = from->U, V = from->V;
- to->R = Y + U * 0.00028328010485821202317155420580263580632163211703 + V * 1.14070449590558520291949662350816652178764343261719;
- to->G = Y - U * 0.39630886669497211727275498560629785060882568359375 - V * 0.58107364288228224857846271333983168005943298339844;
- to->B = Y + U * 2.03990003507541306504435851820744574069976806640625 + V * 0.00017179031692307700847528739718228507626918144524;
-}
-
-static void ycgco_to_srgb(const libcolour_ycgco_t* restrict from, libcolour_srgb_t* restrict to)
-{
- double Y = from->Y, Cg = from->Cg, Co = from->Co;
- to->R = Y - Cg + Co;
- to->G = Y + Cg;
- to->B = Y - Cg - Co;
-}
-
-static void other_to_srgb(const libcolour_colour_t* restrict from, libcolour_srgb_t* restrict to)
-{
- libcolour_ciexyz_t tmp;
- tmp.model = LIBCOLOUR_CIEXYZ;
- to_ciexyz(from, &tmp);
- ciexyz_to_srgb(&tmp, to);
-}
-
-static void to_srgb(const libcolour_colour_t* restrict from, libcolour_srgb_t* restrict to)
-{
- libcolour_srgb_t tmp;
- switch (from->model) {
- case LIBCOLOUR_CIEXYZ:
- ciexyz_to_srgb(&from->ciexyz, to);
- break;
- case LIBCOLOUR_SRGB:
- srgb_to_srgb(&from->srgb, to);
- return;
- case LIBCOLOUR_YIQ:
- yiq_to_srgb(&from->yiq, to);
- break;
- case LIBCOLOUR_YDBDR:
- ydbdr_to_srgb(&from->ydbdr, to);
- break;
- case LIBCOLOUR_YPBPR:
- ypbpr_to_srgb(&from->ypbpr, to);
- break;
- case LIBCOLOUR_YUV:
- yuv_to_srgb(&from->yuv, to);
- break;
- case LIBCOLOUR_YCGCO:
- ycgco_to_srgb(&from->ycgco, to);
- break;
- default:
- other_to_srgb(from, to);
- break;
- }
- if (to->with_gamma) {
- tmp = *to;
- tmp.with_gamma = 0;
- srgb_to_srgb(&tmp, to);
- }
-}
-
-
-static void ciexyz_to_ciexyy(const libcolour_ciexyz_t* restrict from, libcolour_ciexyy_t* restrict to)
-{
- double X = from->X, Y = from->Y, Z = from->Z;
- double s = X + Y + Z;
- to->x = X / s;
- to->y = Y / s;
- to->Y = Y;
- if (WASDIV0(to->x) || WASDIV0(to->y))
- to->x = to->y = 0;
-}
-
-static void other_to_ciexyy(const libcolour_colour_t* restrict from, libcolour_ciexyy_t* restrict to)
-{
- libcolour_ciexyz_t tmp;
- tmp.model = LIBCOLOUR_CIEXYZ;
- to_ciexyz(from, &tmp);
- ciexyz_to_ciexyy(&tmp, to);
-}
-
-static void srgb_to_ciexyy(const libcolour_srgb_t* restrict from, libcolour_ciexyy_t* restrict to)
-{
- libcolour_srgb_t tmp;
- tmp.model = LIBCOLOUR_SRGB;
- if (from->with_gamma) {
- tmp.with_gamma = 0;
- to_srgb((const libcolour_colour_t*)from, &tmp);
- } else {
- tmp = *from;
- }
- if (tmp.R == 0 && tmp.G == 0 && tmp.B == 0) {
- to->x = 0.31272660439158;
- to->y = 0.32902315240275;
- to->Y = 0;
- } else {
- other_to_ciexyy((const libcolour_colour_t*)&tmp, to);
- }
-}
-
-static void to_ciexyy(const libcolour_colour_t* restrict from, libcolour_ciexyy_t* restrict to)
-{
- switch (from->model) {
- case LIBCOLOUR_CIEXYY:
- *to = from->ciexyy;
- return;
- case LIBCOLOUR_CIEXYZ:
- ciexyz_to_ciexyy(&from->ciexyz, to);
- return;
- case LIBCOLOUR_SRGB:
- srgb_to_ciexyy(&from->srgb, to);
- return;
- default:
- other_to_ciexyy(from, to);
- return;
- }
-}
-
-
-static void rgb_to_ciexyz(const libcolour_rgb_t* restrict from, libcolour_ciexyz_t* restrict to)
-{
- libcolour_rgb_t tmp;
- double R, G, B;
- if (from->with_gamma) {
- tmp = *from;
- tmp.with_gamma = 0;
- to_rgb((const libcolour_colour_t*)from, &tmp);
- R = tmp.R, G = tmp.G, B = tmp.B;
- } else {
- R = from->R, G = from->G, B = from->B;
- }
- to->X = from->M[0][0] * R + from->M[0][1] * G + from->M[0][2] * B;
- to->Y = from->M[1][0] * R + from->M[1][1] * G + from->M[1][2] * B;
- to->Z = from->M[2][0] * R + from->M[2][1] * G + from->M[2][2] * B;
-}
-
-static void srgb_to_ciexyz(const libcolour_srgb_t* restrict from, libcolour_ciexyz_t* restrict to)
-{
- libcolour_srgb_t tmp;
- double R, G, B;
- if (from->with_gamma) {
- tmp.model = LIBCOLOUR_SRGB;
- tmp.with_gamma = 0;
- to_srgb((const libcolour_colour_t*)from, &tmp);
- R = tmp.R, G = tmp.G, B = tmp.B;
- } else {
- R = from->R, G = from->G, B = from->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)
-{
- double x = from->x, y = from->y, Y = from->Y;
- double Yy = Y / y;
- if (WASDIV0(Yy)) {
- to->X = to->Y = to->Z = Y;
- } else {
- to->X = x * Yy;
- to->Y = Y;
- to->Z = (1 - x - y) * Yy;
- }
-}
-
-static inline double cielab_finv(double t)
-{
- return (t > 6. / 29.) ? t * t * t : (t - 4. / 29.) * 108 / 841;
-}
-
-static void cielab_to_ciexyz(const libcolour_cielab_t* restrict from, libcolour_ciexyz_t* restrict to)
-{
- double L = from->L, a = from->a, b = from->b;
- to->Y = (L + 16) / 116;
- to->X = to->Y + a / 500;
- to->Z = to->Y - b / 200;
- to->X = cielab_finv(to->X) * 0.95047;
- to->Y = cielab_finv(to->Y);
- to->Z = cielab_finv(to->Z) * 1.08883;
-}
-
-static void cieluv_to_ciexyz(const libcolour_cieluv_t* restrict from, libcolour_ciexyz_t* restrict to)
-{
- double X = from->white.X, Y = from->white.Y, L = from->L, L13 = from->L * 13;
- double t = X + 15 * Y + 3 * from->white.Z;
- double u = from->u / L13 + 4 * X / t;
- double v = from->v / L13 + 9 * Y / t;
- if (L <= 8) {
- Y *= L * 27 / 24389;
- } else {
- L = (L + 16) / 116;
- Y *= L * L * L;
- }
- to->X = 2.25 * Y * u / v;
- to->Y = Y;
- to->Z = Y * (3 / v - 0.75 * u / v - 5);
-}
-
-static void cielchuv_to_ciexyz(const libcolour_cielchuv_t* restrict from, libcolour_ciexyz_t* restrict to)
-{
- libcolour_cieluv_t tmp;
- tmp.model = LIBCOLOUR_CIELUV;
- tmp.white = from->white;
- to_cieluv((const libcolour_colour_t*)from, &tmp);
- cieluv_to_ciexyz(&tmp, to);
-}
-
-static void yiq_to_ciexyz(const libcolour_yiq_t* restrict from, libcolour_ciexyz_t* restrict to)
-{
-#define MULTIPLIY(CY, CI, CQ) ((CY) * from->Y + (CI) * from->I + (CQ) * from->Q)
- to->X = MULTIPLIY(0.95047055865428309306963683411595411598682403564453, 0.09738463974178063198294807989441324025392532348633, 0.33223466706854809515903070860076695680618286132812);
- to->Y = MULTIPLIY(0.99999999999999988897769753748434595763683319091797, -0.07112658301916767455974621725545148365199565887451, -0.20786968876398304040264974901219829916954040527344);
- to->Z = MULTIPLIY(1.08882873639588373393394249433185905218124389648438, -1.06592139332461721679123911599162966012954711914062, 1.55474471255181900808395312196807935833930969238281);
-#undef MULTIPLIY
-}
-
-static void ydbdr_to_ciexyz(const libcolour_ydbdr_t* restrict from, libcolour_ciexyz_t* restrict to)
-{
-#define MULTIPLIY(CY, CDB, CDR) ((CY) * from->Y + (CDB) * from->Db + (CDR) * from->Dr)
- to->X = MULTIPLIY(0.95047055865428309306963683411595411598682403564453, 0.07379612357298576119646327242662664502859115600586, -0.12113653724874726136384595065464964136481285095215);
- to->Y = MULTIPLIY(0.99999999999999988897769753748434595763683319091797, -0.04435684145428285540813106990754022262990474700928, 0.07973534004202506575431641522300196811556816101074);
- to->Z = MULTIPLIY(1.08882873639588373393394249433185905218124389648438, 0.61625657933494271123464613992837257683277130126953, 0.02168821359337728266192257819966471288353204727173);
-#undef MULTIPLIY
-}
-
-static void yuv_to_ciexyz(const libcolour_yuv_t* restrict from, libcolour_ciexyz_t* restrict to)
-{
-#define MULTIPLIY(CY, CU, CV) ((CY) * from->Y + (CU) * from->U + (CV) * from->V)
- to->X = MULTIPLIY(0.95047055865428309306963683411595411598682403564453, 0.22648030324549334180161963558930438011884689331055, 0.26274514929253273143316960158699657768011093139648);
- to->Y = MULTIPLIY(0.99999999999999988897769753748434595763683319091797, -0.13613114642319409930415474718756740912795066833496, -0.17294595255115238763288232348713790997862815856934);
- to->Z = MULTIPLIY(1.08882873639588373393394249433185905218124389648438, 1.89129144197893928058817891724174842238426208496094, -0.04704173528403532422714761196402832865715026855469);
-#undef MULTIPLIY
-}
-
-static void ypbpr_to_ciexyz(const libcolour_ypbpr_t* restrict from, libcolour_ciexyz_t* restrict to)
-{
-#define MULTIPLIY(CY, CPB, CPR) ((CY) * from->Y + (CPB) * from->Pb + (CPR) * from->Pr)
- to->X = MULTIPLIY(0.95047055865428298204733437160030007362365722656250, 0.14433968424876231217979238863335922360420227050781, 0.30616461986760712399302519770571961998939514160156);
- to->Y = MULTIPLIY(0.99999999999999977795539507496869191527366638183594, -0.00002022802471486617736928792510298080742359161377, 0.00008771894888734421691367515450110659003257751465);
- to->Z = MULTIPLIY(1.08882873639588373393394249433185905218124389648438, 0.93827031735982591165168287261622026562690734863281, -0.01609699914324668607035206946420657914131879806519);
-#undef MULTIPLIY
-}
-
-static void ycgco_to_ciexyz(const libcolour_ycgco_t* restrict from, libcolour_ciexyz_t* restrict to)
-{
-#define MULTIPLIY(CY, CCG, CCO) ((CY) * from->Y + (CCG) * from->Cg + (CCO) * from->Co)
- to->X = MULTIPLIY(0.95047055865428309306963683411595411598682403564453, -0.23531882816325136453805555447615915909409523010254, 0.23202019775596791073546398820326430723071098327637);
- to->Y = MULTIPLIY(0.99999999999999988897769753748434595763683319091797, 0.43030346098206362359661625305307097733020782470703, 0.14049847124784842211653312915586866438388824462891);
- to->Z = MULTIPLIY(1.08882873639588373393394249433185905218124389648438, -0.85044482623220662986796014592982828617095947265625, -0.93096889579069830311652822274481877684593200683594);
-#undef MULTIPLIY
-}
-
-static void cie1960ucs_to_ciexyz(const libcolour_cie1960ucs_t* restrict from, libcolour_ciexyz_t* restrict to)
-{
- double u = from->u, v = from->v, Y = from->Y;
- to->X = 1.5 * Y * u / v;
- to->Y = Y;
- to->Z = (4 * Y - Y * u - 10 * Y * v) / (2 * v);
-}
-
-static void cieuvw_to_ciexyz(const libcolour_cieuvw_t* restrict from, libcolour_ciexyz_t* restrict to)
-{
- libcolour_cie1960ucs_t tmp;
- tmp.model = LIBCOLOUR_CIE1960UCS;
- to_cie1960ucs((const libcolour_colour_t*)from, &tmp);
- cie1960ucs_to_ciexyz(&tmp, to);
-}
-
-static void other_to_ciexyz(const libcolour_colour_t* restrict from, libcolour_ciexyz_t* restrict to)
-{
- libcolour_srgb_t tmp;
- tmp.model = LIBCOLOUR_SRGB;
- tmp.with_gamma = 0;
- to_srgb(from, &tmp);
- srgb_to_ciexyz(&tmp, to);
-}
-
-static void to_ciexyz(const libcolour_colour_t* restrict from, libcolour_ciexyz_t* restrict to)
-{
- switch (from->model) {
- case LIBCOLOUR_RGB:
- rgb_to_ciexyz(&from->rgb, to);
- break;
- case LIBCOLOUR_SRGB:
- srgb_to_ciexyz(&from->srgb, to);
- break;
- case LIBCOLOUR_CIEXYY:
- ciexyy_to_ciexyz(&from->ciexyy, to);
- break;
- case LIBCOLOUR_CIEXYZ:
- *to = from->ciexyz;
- break;
- case LIBCOLOUR_CIELAB:
- cielab_to_ciexyz(&from->cielab, to);
- break;
- case LIBCOLOUR_CIELUV:
- cieluv_to_ciexyz(&from->cieluv, to);
- break;
- case LIBCOLOUR_CIELCHUV:
- cielchuv_to_ciexyz(&from->cielchuv, to);
- break;
- case LIBCOLOUR_YIQ:
- yiq_to_ciexyz(&from->yiq, to);
- break;
- case LIBCOLOUR_YDBDR:
- ydbdr_to_ciexyz(&from->ydbdr, to);
- break;
- case LIBCOLOUR_YUV:
- yuv_to_ciexyz(&from->yuv, to);
- break;
- case LIBCOLOUR_YPBPR:
- ypbpr_to_ciexyz(&from->ypbpr, to);
- break;
- case LIBCOLOUR_YCGCO:
- ycgco_to_ciexyz(&from->ycgco, to);
- break;
- case LIBCOLOUR_CIE1960UCS:
- cie1960ucs_to_ciexyz(&from->cie1960ucs, to);
- break;
- case LIBCOLOUR_CIEUVW:
- cieuvw_to_ciexyz(&from->cieuvw, to);
- break;
- default:
- other_to_ciexyz(from, to);
- break;
- }
-}
-
-
-static inline double cielab_f(double t)
-{
- return (t > 216. / 24389.) ? cbrt(t) : t * 841. / 108. + 4. / 29.;
-}
-
-static void ciexyz_to_cielab(const libcolour_ciexyz_t* restrict from, libcolour_cielab_t* restrict to)
-{
- double X = from->X, Y = from->Y, Z = from->Z;
- X /= 0.95047;
- Z /= 1.08883;
- Y = cielab_f(Y);
- to->L = 116 * Y - 16;
- to->a = 500 * (cielab_f(X) - Y);
- to->b = 200 * (Y - cielab_f(Z));
-}
-
-static void other_to_cielab(const libcolour_colour_t* restrict from, libcolour_cielab_t* restrict to)
-{
- libcolour_ciexyz_t tmp;
- tmp.model = LIBCOLOUR_CIEXYZ;
- to_ciexyz(from, &tmp);
- ciexyz_to_cielab(&tmp, to);
-}
-
-static void to_cielab(const libcolour_colour_t* restrict from, libcolour_cielab_t* restrict to)
-{
- switch (from->model) {
- case LIBCOLOUR_CIEXYZ:
- ciexyz_to_cielab(&from->ciexyz, to);
- return;
- case LIBCOLOUR_CIELAB:
- *to = from->cielab;
- return;
- default:
- other_to_cielab(from, to);
- return;
- }
-}
-
-
-static void ciexyz_to_cieluv(const libcolour_ciexyz_t* restrict from, libcolour_cieluv_t* restrict to)
-{
- double t, u, v, y, y2;
- t = to->white.X + 15 * to->white.Y + 3 * to->white.Z;
- u = 4 * to->white.X / t;
- v = 9 * to->white.Y / t;
- t = from->X + 15 * from->Y + 3 * from->Z;
- u = 4 * from->X / t - u;
- v = 9 * from->Y / t - v;
- y = from->Y / to->white.Y;
- y2 = y * 24389;
- y = y2 <= 216 ? y2 / 27 : cbrt(y) * 116 - 16;
- to->L = y;
- y *= 13;
- to->u = u * y;
- to->v = v * y;
-}
-
-static void cielchuv_to_cieluv(const libcolour_cielchuv_t* restrict from, libcolour_cieluv_t* restrict to)
-{
- libcolour_ciexyz_t tmp;
- libcolour_cielchuv_t tmp2;
- double L, C, h;
- if (to->white.X != from->white.X || to->white.Y != from->white.Y || to->white.Z != from->white.Z) {
- tmp.model = LIBCOLOUR_CIEXYZ;
- tmp2.model = LIBCOLOUR_CIELCHUV;
- tmp2.white = to->white;
- tmp2.one_revolution = PI2;
- to_ciexyz((const libcolour_colour_t*)from, &tmp);
- to_cielchuv((const libcolour_colour_t*)&tmp, &tmp2);
- L = tmp2.L, C = tmp2.C, h = tmp2.h;
- } else {
- L = from->L, C = from->C, h = from->h * PI2 / from->one_revolution;
- }
- to->L = L;
- to->u = C * cos(h);
- to->v = C * sin(h);
-}
-
-static void other_to_cieluv(const libcolour_colour_t* restrict from, libcolour_cieluv_t* restrict to)
-{
- libcolour_ciexyz_t tmp;
- tmp.model = LIBCOLOUR_CIEXYZ;
- to_ciexyz(from, &tmp);
- ciexyz_to_cieluv(&tmp, to);
-}
-
-static void to_cieluv(const libcolour_colour_t* restrict from, libcolour_cieluv_t* restrict to)
-{
- switch (from->model) {
- case LIBCOLOUR_CIEXYZ:
- ciexyz_to_cieluv(&from->ciexyz, to);
- break;
- case LIBCOLOUR_CIELCHUV:
- cielchuv_to_cieluv(&from->cielchuv, to);
- break;
- case LIBCOLOUR_CIELUV:
- if (to->white.X == from->cieluv.white.X &&
- to->white.Y == from->cieluv.white.Y &&
- to->white.Z == from->cieluv.white.Z) {
- *to = from->cieluv;
- break;
- }
- /* fall through */
- default:
- other_to_cieluv(from, to);
- break;
- }
-}
-
-
-static void cieluv_to_cielchuv(const libcolour_cieluv_t* restrict from, libcolour_cielchuv_t* restrict to)
-{
- libcolour_cieluv_t tmp;
- double L, u, v;
- if (to->white.X != from->white.X || to->white.Y != from->white.Y || to->white.Z != from->white.Z) {
- tmp.model = LIBCOLOUR_CIELUV;
- tmp.white = to->white;
- to_cieluv((const libcolour_colour_t*)from, &tmp);
- L = tmp.L, u = tmp.u, v = tmp.v;
- } else {
- L = from->L, u = from->u, v = from->v;
- }
- to->L = L;
- to->C = sqrt(u * u + v * v);
- to->h = atan2(v, u) / PI2 * to->one_revolution;
- if (!isnan(to->h) && !isinf(to->h) && (to->h < 0))
- to->h += to->one_revolution;
-}
-
-static void other_to_cielchuv(const libcolour_colour_t* restrict from, libcolour_cielchuv_t* restrict to)
-{
- libcolour_cieluv_t tmp;
- tmp.model = LIBCOLOUR_CIELUV;
- tmp.white = to->white;
- to_cieluv(from, &tmp);
- cieluv_to_cielchuv(&tmp, to);
-}
-
-static void to_cielchuv(const libcolour_colour_t* restrict from, libcolour_cielchuv_t* restrict to)
-{
- double one_revolution;
- switch (from->model) {
- case LIBCOLOUR_CIELUV:
- cieluv_to_cielchuv(&from->cieluv, to);
- break;
- case LIBCOLOUR_CIELCHUV:
- if (to->white.X == from->cielchuv.white.X &&
- to->white.Y == from->cielchuv.white.Y &&
- to->white.Z == from->cielchuv.white.Z) {
- if (to->one_revolution == from->cielchuv.one_revolution) {
- *to = from->cielchuv;
- } else {
- one_revolution = to->one_revolution;
- *to = from->cielchuv;
- to->one_revolution = one_revolution;
- to->h = to->h / from->cielchuv.one_revolution * one_revolution;
- }
- break;
- }
- /* fall through */
- default:
- other_to_cielchuv(from, to);
- break;
- }
-}
-
-
-static void to_yiq(const libcolour_colour_t* restrict from, libcolour_yiq_t* restrict to)
-{
- double x, y, z;
- libcolour_colour_t tmp = *from;
- switch (from->model) {
- case LIBCOLOUR_YIQ:
- *to = from->yiq;
- break;
- case LIBCOLOUR_SRGB:
- if (tmp.srgb.with_gamma) {
- tmp.srgb.with_gamma = 0;
- to_srgb(from, &tmp.srgb);
- }
- x = tmp.srgb.R;
- y = tmp.srgb.G;
- z = tmp.srgb.B;
- to->Y = x * 0.299 + y * 0.587 + z * 0.114;
- to->I = x * 0.59571613491277464191853141528554260730743408203125 /* (0.877 cos 33°)(1 - 0.299) - (0.492 sin 33°)(-0.299) */
- - y * 0.27445283783925644716106262421817518770694732666016 /* (0.877 cos 33°)(-0.587) - (0.492 sin 33°)(-0.587) */
- - z * 0.32126329707351808373516632855171337723731994628906; /* (0.877 cos 33°)(-0.114) - (0.492 sin 33°)(1 - 0.114) */
- to->Q = x * 0.21145640212011795888713550084503367543220520019531 /* (0.877 sin 33°)(1 - 0.299) + (0.492 cos 33°)(-0.299) */
- - y * 0.52259104529161115593183239980135113000869750976562 /* (0.877 sin 33°)(-0.587) + (0.492 cos 33°)(-0.587) */
- + z * 0.31113464317149330806699936147197149693965911865234; /* (0.877 sin 33°)(-0.114) + (0.492 cos 33°)(1 - 0.114) */
- break;
- default:
- tmp.model = LIBCOLOUR_CIEXYZ;
- to_ciexyz(from, &tmp.ciexyz);
- /* fall through */
- case LIBCOLOUR_CIEXYZ:
- x = tmp.ciexyz.X;
- y = tmp.ciexyz.Y;
- z = tmp.ciexyz.Z;
-#define MULTIPLIY(CX, CY, CZ) ((CX) * x + (CY) * y + (CZ) * z)
- to->Y = MULTIPLIY(0.40627729168038273499519164033699780702590942382812, 0.61835674212166968910509012857801280915737152099609, -0.00414330221353725880462093300593551248311996459961);
- to->I = MULTIPLIY(2.17852787350219845308174626552499830722808837890625, -1.36502666214454104753883711964590474963188171386719, -0.64803574634025240541745915834326297044754028320312);
- to->Q = MULTIPLIY(1.20905577682138853923277110880007967352867126464844, -1.36890364998339797431015085749095305800437927246094, 0.20180559439597040016778350945969577878713607788086);
-#undef MULTIPLIY
- break;
- }
-}
-
-
-static void to_ydbdr(const libcolour_colour_t* restrict from, libcolour_ydbdr_t* restrict to)
-{
- double x, y, z;
- libcolour_colour_t tmp = *from;
- switch (from->model) {
- case LIBCOLOUR_YDBDR:
- *to = from->ydbdr;
- break;
- case LIBCOLOUR_SRGB:
- if (tmp.srgb.with_gamma) {
- tmp.srgb.with_gamma = 0;
- to_srgb(from, &tmp.srgb);
- }
- x = tmp.srgb.R;
- y = tmp.srgb.G;
- z = tmp.srgb.B;
- to->Y = x * 0.299 + y * 0.587 + z * 0.114;
- to->Db = -x * 0.450 - y * 0.883 + z * 1.333;
- to->Dr = -x * 1.333 + y * 1.116 + z * 0.217;
- break;
- case LIBCOLOUR_YUV:
- to->Y = tmp.yuv.Y;
- to->Db = tmp.yuv.U * 3.069;
- to->Dr = -tmp.yuv.V * 2.169;
- break;
- default:
- tmp.model = LIBCOLOUR_CIEXYZ;
- to_ciexyz(from, &tmp.ciexyz);
- /* fall through */
- case LIBCOLOUR_CIEXYZ:
- x = tmp.ciexyz.X;
- y = tmp.ciexyz.Y;
- z = tmp.ciexyz.Z;
-#define MULTIPLY(CX, CY, CZ) ((CX) * x + (CY) * y + (CZ) * z)
- to->Y = MULTIPLY(0.40627729168038273499519164033699780702590942382812, 0.61835674212166968910509012857801280915737152099609, -0.00414330221353725880462093300593551248311996459961);
- to->Db = MULTIPLY(-0.52816561102614745237815441214479506015777587890625, -1.23677481526212962315014465275453403592109680175781, 1.59692761635924940222253098909277468919754028320312);
- to->Dr = MULTIPLY(-5.38914174974103143966885909321717917919158935546875, 4.09835630362728497999569299281574785709381103515625, 0.94033545560642795013706063400604762136936187744141);
-#undef MULTIPLY
- break;
- }
-}
-
-
-static void to_yuv(const libcolour_colour_t* restrict from, libcolour_yuv_t* restrict to)
-{
- libcolour_colour_t tmp = *from;
- switch (from->model) {
- case LIBCOLOUR_YUV:
- *to = from->yuv;
- break;
- case LIBCOLOUR_YDBDR:
- to->Y = from->ydbdr.Y;
- to->U = from->ydbdr.Db / 3.069;
- to->V = from->ydbdr.Dr / -2.169;
- break;
- case LIBCOLOUR_SRGB:
- if (tmp.srgb.with_gamma) {
- tmp.srgb.with_gamma = 0;
- to_srgb(from, &tmp.srgb);
- }
-#define MULTIPLY(CR, CG, CB) ((CR) * tmp.srgb.R + (CG) * tmp.srgb.G + (CB) * tmp.srgb.B)
- to->Y = MULTIPLY(0.29899999999999998800959133404830936342477798461914, 0.58699999999999996624922005139524117112159729003906, 0.11400000000000000410782519111307919956743717193604);
- to->U = MULTIPLY(-0.14662756598240470062854967636667424812912940979004, -0.28771586836102963635752871596196200698614120483398, 0.43434343434343436474165400795754976570606231689453);
- to->V = MULTIPLY(0.61456892577224520035628074765554629266262054443359, -0.51452282157676354490405401520547457039356231689453, -0.10004610419548178035231700278018251992762088775635);
-#undef MULTIPLY
- break;
- default:
- tmp.model = LIBCOLOUR_CIEXYZ;
- to_ciexyz(from, &tmp.ciexyz);
- /* fall through */
- case LIBCOLOUR_CIEXYZ:
-#define MULTIPLY(CX, CY, CZ) ((CX) * tmp.ciexyz.X + (CY) * tmp.ciexyz.Y + (CZ) * tmp.ciexyz.Z)
- to->Y = MULTIPLY(0.40627729168038273499519164033699780702590942382812, 0.61835674212166968910509012857801280915737152099609, -0.00414330221353725880462093300593551248311996459961);
- to->U = MULTIPLY(-0.17209697328971895746718701047939248383045196533203, -0.40298951295605395239718404809536878019571304321289, 0.52034135430408912093014350830344483256340026855469);
- to->V = MULTIPLY(2.48462044709130047692724474472925066947937011718750, -1.88951420176453876997868519538315013051033020019531, -0.43353409663735725798616726933687459677457809448242);
-#undef MULTIPLY
- break;
- }
-}
-
-
-static void to_ypbpr(const libcolour_colour_t* restrict from, libcolour_ypbpr_t* restrict to)
-{
- libcolour_colour_t tmp = *from;
- switch (from->model) {
- case LIBCOLOUR_YPBPR:
- *to = from->ypbpr;
- break;
- case LIBCOLOUR_SRGB:
- if (tmp.srgb.with_gamma) {
- tmp.srgb.with_gamma = 0;
- to_srgb(from, &tmp.srgb);
- }
- to->Y = tmp.srgb.R * 0.2126 + tmp.srgb.G * 0.7152 + tmp.srgb.B * 0.0722;
- to->Pb = tmp.srgb.B - to->Y;
- to->Pr = tmp.srgb.R - to->Y;
- break;
- default:
- tmp.model = LIBCOLOUR_CIEXYZ;
- to_ciexyz(from, &tmp.ciexyz);
- /* fall through */
- case LIBCOLOUR_CIEXYZ:
-#define MULTIPLY(CX, CY, CZ) ((CX) * tmp.ciexyz.X + (CY) * tmp.ciexyz.Y + (CZ) * tmp.ciexyz.Z)
- to->Y = MULTIPLY(-0.00028314209073960778378920011277841695118695497513, 1.00019821310075673892470149439759552478790283203125, 0.00006512054470741990286342115723527967929840087891);
- to->Pb = MULTIPLY(0.05592664565509243568275365987574332393705844879150, -1.20422439283671711685030913940863683819770812988281, 1.05716144717799576113748116767965257167816162109375);
- to->Pr = MULTIPLY(3.24072939673847715269516811531502753496170043945312, -2.53733297492083753610359053709544241428375244140625, -0.49859531356743613805804216099204495549201965332031);
-#undef MULTIPLY
- break;
- }
-}
-
-
-static void to_ycgco(const libcolour_colour_t* restrict from, libcolour_ycgco_t* restrict to)
-{
- libcolour_colour_t tmp = *from;
- switch (from->model) {
- case LIBCOLOUR_YCGCO:
- *to = from->ycgco;
- break;
- case LIBCOLOUR_SRGB:
- if (tmp.srgb.with_gamma) {
- tmp.srgb.with_gamma = 0;
- to_srgb(from, &tmp.srgb);
- }
- to->Y = tmp.srgb.R / 4 + tmp.srgb.G / 2 + tmp.srgb.B / 4;
- to->Cg = -tmp.srgb.R / 4 + tmp.srgb.G / 2 - tmp.srgb.B / 4;
- to->Co = tmp.srgb.R / 2 - tmp.srgb.B / 2;
- break;
- default:
- tmp.model = LIBCOLOUR_CIEXYZ;
- to_ciexyz(from, &tmp.ciexyz);
- /* fall through */
- case LIBCOLOUR_CIEXYZ:
-#define MULTIPLY(CX, CY, CZ) ((CX) * tmp.ciexyz.X + (CY) * tmp.ciexyz.Y + (CZ) * tmp.ciexyz.Z)
- to->Y = MULTIPLY(0.33938913643068269188063368346774950623512268066406, 0.50271574450517486631895280879689380526542663574219, 0.16045211478220866574417868832824751734733581542969);
- to->Cg = MULTIPLY(-1.30865574267536244335019546269904822111129760742188, 1.37329621528319534284889869013568386435508728027344, -0.11889607256777862120955546743061859160661697387695);
- to->Co = MULTIPLY(1.59240137554169236544510113162687048316001892089844, -0.66655429104206020962664069884340278804302215576172, -0.77787838037271606062006412685150280594825744628906);
-#undef MULTIPLY
- break;
- }
-}
-
-
-static void to_cie1960ucs(const libcolour_colour_t* restrict from, libcolour_cie1960ucs_t* restrict to)
-{
- libcolour_colour_t tmp = *from;
- double u, v, w, y;
- switch (from->model) {
- case LIBCOLOUR_CIE1960UCS:
- *to = from->cie1960ucs;
- return;
- case LIBCOLOUR_CIEUVW:
- u = from->cieuvw.U, v = from->cieuvw.V, w = from->cieuvw.W;
- y = (w + 17) / 25;
- y *= y * y;
- w *= 13;
- to->u = u / w + from->cieuvw.u0;
- to->v = v / w + from->cieuvw.v0;
- to->Y = y;
- return;
- default:
- tmp.model = LIBCOLOUR_CIEXYZ;
- to_ciexyz(from, &tmp.ciexyz);
- /* fall through */
- case LIBCOLOUR_CIEXYZ:
- w = tmp.ciexyz.X + 15 * tmp.ciexyz.Y + 3 * tmp.ciexyz.Z;
- to->u = 4 * tmp.ciexyz.X / w;
- to->v = 6 * tmp.ciexyz.Y / w;
- to->Y = tmp.ciexyz.Y;
- return;
- }
-}
-
-
-static void to_cieuvw(const libcolour_colour_t* restrict from, libcolour_cieuvw_t* restrict to)
-{
- double U, V, W, w;
- libcolour_colour_t tmp = *from;
- switch (from->model) {
- case LIBCOLOUR_CIEUVW:
- U = from->cieuvw.U, V = from->cieuvw.V, W = from->cieuvw.W;
- w = W * 13;
- U += w * (from->cieuvw.u0 - to->u0);
- V += w * (from->cieuvw.v0 - to->v0);
- to->U = U, to->V = V, to->W = W;
- break;
- default:
- tmp.model = LIBCOLOUR_CIE1960UCS;
- to_cie1960ucs(from, &tmp.cie1960ucs);
- /* fall through */
- case LIBCOLOUR_CIE1960UCS:
- U = tmp.cie1960ucs.u, V = tmp.cie1960ucs.v, W = tmp.cie1960ucs.Y;
- W = 25 * cbrt(W) - 17;
- w = W * 13;
- to->U = w * (U - to->u0);
- to->V = w * (V - to->v0);
- to->W = W;
- break;
- }
-}
-
-
-
-int libcolour_convert(const libcolour_colour_t* restrict from, libcolour_colour_t* restrict to)
-{
-#define X(C, T) 1 +
- if (from->model < 0 || from->model > LIBCOLOUR_LIST_MODELS 0) {
-#undef X
- errno = EINVAL;
- return -1;
- }
- switch (to->model) {
- case LIBCOLOUR_RGB:
- to_rgb(from, &to->rgb);
- break;
- case LIBCOLOUR_SRGB:
- to_srgb(from, &to->srgb);
- break;
- case LIBCOLOUR_CIEXYY:
- to_ciexyy(from, &to->ciexyy);
- break;
- case LIBCOLOUR_CIEXYZ:
- to_ciexyz(from, &to->ciexyz);
- break;
- case LIBCOLOUR_CIELAB:
- to_cielab(from, &to->cielab);
- break;
- case LIBCOLOUR_CIELUV:
- to_cieluv(from, &to->cieluv);
- break;
- case LIBCOLOUR_CIELCHUV:
- to_cielchuv(from, &to->cielchuv);
- break;
- case LIBCOLOUR_YIQ:
- to_yiq(from, &to->yiq);
- break;
- case LIBCOLOUR_YDBDR:
- to_ydbdr(from, &to->ydbdr);
- break;
- case LIBCOLOUR_YUV:
- to_yuv(from, &to->yuv);
- break;
- case LIBCOLOUR_YPBPR:
- to_ypbpr(from, &to->ypbpr);
- break;
- case LIBCOLOUR_YCGCO:
- to_ycgco(from, &to->ycgco);
- break;
- case LIBCOLOUR_CIE1960UCS:
- to_cie1960ucs(from, &to->cie1960ucs);
- break;
- case LIBCOLOUR_CIEUVW:
- to_cieuvw(from, &to->cieuvw);
- break;
- default:
- errno = EINVAL;
- return -1;
- }
- return 0;
-}
-
diff --git a/src/libcolour.c b/src/libcolour.c
deleted file mode 100644
index 867e280..0000000
--- a/src/libcolour.c
+++ /dev/null
@@ -1,717 +0,0 @@
-/**
- * Copyright © 2016 Mattias Andrée <maandree@kth.se>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-#include "libcolour.h"
-
-#include <alloca.h>
-#include <errno.h>
-#include <math.h>
-#include <string.h>
-
-
-#define MARSHAL_VERSION 0
-
-
-
-double libcolour_srgb_encode(double t)
-{
- 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 t)
-{
- double sign = 1;
- if (t < 0) {
- t = -t;
- sign = -1;
- }
- t = t <= 0.0031306684425217108 * 12.92 ? t / 12.92 : pow((t + 0.055) / 1.055, 2.4);
- return t * sign;
-}
-
-
-int libcolour_delta_e(const libcolour_colour_t* a, const libcolour_colour_t* b, double* e)
-{
- libcolour_cielab_t u, v;
- u.model = v.model = LIBCOLOUR_CIELAB;
- if (libcolour_convert(a, (libcolour_colour_t*)&u))
- return -1;
- if (libcolour_convert(b, (libcolour_colour_t*)&v))
- return -1;
- u.L -= v.L, u.L *= u.L;
- u.a -= v.a, u.a *= u.a;
- u.b -= v.b, u.b *= u.b;
- *e = sqrt(u.L + u.a + u.b);
- return 0;
-}
-
-
-#define eliminate(M, n, m) eliminate_(n, m, &(M))
-static int eliminate_(size_t n, size_t m, double (*Mp)[n][m])
-{
-#define M (*Mp)
- size_t r1, r2, c;
- double d;
- double* R1;
- double* R2;
- for (r1 = 0; r1 < n; r1++) {
- R1 = M[r1];
- if (R1[r1] == 0) {
- for (r2 = r1 + 1; r2 < n; r2++)
- if (M[r2][r1] != 0)
- break;
- if (r2 == n) {
- errno = EDOM;
- return -1;
- }
- R2 = M[r2];
- for (c = 0; c < m; c++)
- d = R1[c], R1[c] = R2[c], R2[c] = d;
- }
- d = R1[r1];
- for (c = 0; c < m; c++)
- R1[c] /= d;
- for (r2 = r1 + 1; r2 < n; r2++) {
- R2 = M[r2];
- d = R2[r1];
- for (c = 0; c < m; c++)
- R2[c] -= R1[c] * d;
- }
- }
- for (r1 = n; --r1;) {
- R1 = M[r1];
- for (r2 = r1; r2--;) {
- R2 = M[r2];
- d = R2[r1];
- for (c = 0; c < m; c++)
- R2[c] -= R1[c] * d;
- }
- }
- return 0;
-#undef M
-}
-
-
-int libcolour_proper(libcolour_colour_t* colour)
-{
- libcolour_colour_t r, g, b, w;
- double m[3][4];
- switch (colour->model) {
- case LIBCOLOUR_CIELUV:
- colour->cieluv.white.model = LIBCOLOUR_CIEXYZ;
- break;
- case LIBCOLOUR_CIELCHUV:
- colour->cielchuv.white.model = LIBCOLOUR_CIEXYZ;
- if (colour->cielchuv.one_revolution == 0.)
- colour->cielchuv.one_revolution = 360.;
- break;
- case LIBCOLOUR_RGB:
- colour->rgb.red.model = LIBCOLOUR_CIEXYY;
- colour->rgb.green.model = LIBCOLOUR_CIEXYY;
- colour->rgb.blue.model = LIBCOLOUR_CIEXYY;
- colour->rgb.white.model = LIBCOLOUR_CIEXYY;
- colour->rgb.red.Y = 1;
- colour->rgb.green.Y = 1;
- colour->rgb.blue.Y = 1;
- r.model = g.model = b.model = w.model = LIBCOLOUR_CIEXYZ;
- libcolour_convert((const libcolour_colour_t*)&colour->rgb.red, &r);
- libcolour_convert((const libcolour_colour_t*)&colour->rgb.green, &g);
- libcolour_convert((const libcolour_colour_t*)&colour->rgb.blue, &b);
- libcolour_convert((const libcolour_colour_t*)&colour->rgb.white, &w);
- m[0][0] = r.ciexyz.X, m[0][1] = g.ciexyz.X, m[0][2] = b.ciexyz.X, m[0][3] = w.ciexyz.X;
- m[1][0] = r.ciexyz.Y, m[1][1] = g.ciexyz.Y, m[1][2] = b.ciexyz.Y, m[1][3] = w.ciexyz.Y;
- m[2][0] = r.ciexyz.Z, m[2][1] = g.ciexyz.Z, m[2][2] = b.ciexyz.Z, m[2][3] = w.ciexyz.Z;
- if (eliminate(m, 3, 4))
- return -1;
- colour->rgb.red.Y = m[0][3];
- colour->rgb.green.Y = m[1][3];
- colour->rgb.blue.Y = m[2][3];
- break;
- default:
- break;
- }
- return 0;
-}
-
-
-static int get_primaries(libcolour_rgb_t* cs)
-{
- libcolour_colour_t r, g, b, w;
- double Sr, Sg, Sb;
- double M[3][6];
-
- r.model = g.model = b.model = w.model = LIBCOLOUR_CIEXYZ;
- r.ciexyz.Y = 1;
- g.ciexyz.Y = 1;
- b.ciexyz.Y = 1;
-
- Sr = cs->M[1][0] * cs->white_r;
- Sg = cs->M[1][1] * cs->white_g;
- Sb = cs->M[1][2] * cs->white_b;
-
- r.ciexyz.X = cs->M[0][0] / Sr, r.ciexyz.Z = cs->M[2][0] / Sr;
- g.ciexyz.X = cs->M[0][1] / Sg, g.ciexyz.Z = cs->M[2][1] / Sg;
- b.ciexyz.X = cs->M[0][2] / Sb, b.ciexyz.Z = cs->M[2][2] / Sb;
-
- M[0][0] = r.ciexyz.X, M[0][1] = g.ciexyz.X, M[0][2] = b.ciexyz.X, M[0][3] = 1, M[0][4] = 0, M[0][5] = 0;
- M[1][0] = r.ciexyz.Y, M[1][1] = g.ciexyz.Y, M[1][2] = b.ciexyz.Y, M[1][3] = 0, M[1][4] = 1, M[1][5] = 0;
- M[2][0] = r.ciexyz.Z, M[2][1] = g.ciexyz.Z, M[2][2] = b.ciexyz.Z, M[2][3] = 0, M[2][4] = 0, M[2][5] = 1;
-
- if (eliminate(M, 3, 6))
- return -1;
-
- memcpy(M[0], M[0] + 3, 3 * sizeof(double)), M[0][3] = Sr;
- memcpy(M[1], M[1] + 3, 3 * sizeof(double)), M[1][3] = Sg;
- memcpy(M[2], M[2] + 3, 3 * sizeof(double)), M[2][3] = Sb;
-
- if (eliminate(M, 3, 4))
- return -1;
-
- w.ciexyz.X = M[0][3];
- w.ciexyz.Y = M[1][3];
- w.ciexyz.Z = M[2][3];
-
- cs->red.model = LIBCOLOUR_CIEXYY;
- cs->green.model = LIBCOLOUR_CIEXYY;
- cs->blue.model = LIBCOLOUR_CIEXYY;
- cs->white.model = LIBCOLOUR_CIEXYY;
-
- libcolour_convert(&r, (libcolour_colour_t*)&cs->red);
- libcolour_convert(&g, (libcolour_colour_t*)&cs->green);
- libcolour_convert(&b, (libcolour_colour_t*)&cs->blue);
- libcolour_convert(&w, (libcolour_colour_t*)&cs->white);
-
- return 0;
-}
-
-
-static int get_matrices(libcolour_rgb_t* cs)
-{
- libcolour_colour_t r, g, b, w;
- double M[3][6];
- double Sr, Sg, Sb;
-
- r.model = g.model = b.model = LIBCOLOUR_CIEXYZ;
- w.model = LIBCOLOUR_CIEXYY;
- libcolour_convert((const libcolour_colour_t*)&cs->red, &w), w.ciexyy.Y = 1, libcolour_convert(&w, &r);
- libcolour_convert((const libcolour_colour_t*)&cs->green, &w), w.ciexyy.Y = 1, libcolour_convert(&w, &g);
- libcolour_convert((const libcolour_colour_t*)&cs->blue, &w), w.ciexyy.Y = 1, libcolour_convert(&w, &b);
- w.model = LIBCOLOUR_CIEXYZ;
- libcolour_convert((const libcolour_colour_t*)&cs->white, &w);
-
- M[0][0] = r.ciexyz.X, M[0][1] = g.ciexyz.X, M[0][2] = b.ciexyz.X, M[0][3] = 1, M[0][4] = 0, M[0][5] = 0;
- M[1][0] = r.ciexyz.Y, M[1][1] = g.ciexyz.Y, M[1][2] = b.ciexyz.Y, M[1][3] = 0, M[1][4] = 1, M[1][5] = 0;
- M[2][0] = r.ciexyz.Z, M[2][1] = g.ciexyz.Z, M[2][2] = b.ciexyz.Z, M[2][3] = 0, M[2][4] = 0, M[2][5] = 1;
-
- if (eliminate(M, 3, 6))
- return -1;
-
- Sr = M[0][3] * w.ciexyz.X + M[0][4] * w.ciexyz.Y + M[0][5] * w.ciexyz.Z;
- Sg = M[1][3] * w.ciexyz.X + M[1][4] * w.ciexyz.Y + M[1][5] * w.ciexyz.Z;
- Sb = M[2][3] * w.ciexyz.X + M[2][4] * w.ciexyz.Y + M[2][5] * w.ciexyz.Z;
-
- Sr /= cs->white_r;
- Sg /= cs->white_g;
- Sb /= cs->white_b;
-
- cs->M[0][0] = Sr * r.ciexyz.X, cs->M[0][1] = Sg * g.ciexyz.X, cs->M[0][2] = Sb * b.ciexyz.X;
- cs->M[1][0] = Sr * r.ciexyz.Y, cs->M[1][1] = Sg * g.ciexyz.Y, cs->M[1][2] = Sb * b.ciexyz.Y;
- cs->M[2][0] = Sr * r.ciexyz.Z, cs->M[2][1] = Sg * g.ciexyz.Z, cs->M[2][2] = Sb * b.ciexyz.Z;
-
- memcpy(M[0], cs->M[0], 3 * sizeof(double)), M[0][3] = 1, M[0][4] = 0, M[0][5] = 0;
- memcpy(M[1], cs->M[1], 3 * sizeof(double)), M[1][3] = 0, M[1][4] = 1, M[1][5] = 0;
- memcpy(M[2], cs->M[2], 3 * sizeof(double)), M[2][3] = 0, M[2][4] = 0, M[2][5] = 1;
-
- if (eliminate(M, 3, 6))
- return -1;
-
- memcpy(cs->Minv[0], M[0] + 3, 3 * sizeof(double));
- memcpy(cs->Minv[1], M[1] + 3, 3 * sizeof(double));
- memcpy(cs->Minv[2], M[2] + 3, 3 * sizeof(double));
-
- return 0;
-}
-
-
-#define invert(Minv, M, n) invert_(n, &(Minv), &(M))
-static int invert_(size_t n, double (*Minvp)[n][n], double (*Mp)[n][n])
-{
-#define Minv (*Minvp)
-#define M (*Mp)
-#define J (*Jp)
- double J[n][2 * n] = alloca(sizeof(double[n][2 * n]));
- size_t i;
- for (i = 0; i < n; i++) {
- memcpy(J[i], M[i], n * sizeof(double));
- memset(J[i] + n, 0, n * sizeof(double));
- J[i][n + i] = 1;
- }
- if (eliminate(J, n, 2 * n))
- return -1;
- for (i = 0; i < n; i++)
- memcpy(Minv[i], J[i] + n, n * sizeof(double));
- return 0;
-#undef J
-#undef M
-#undef Minv
-}
-
-
-static double transfer_function_l_star(double t)
-{
- 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)
-{
- 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;
-}
-
-static double transfer_function_oetf_hlg(double t)
-{
- double sign = 1;
- if (t < 0) {
- t = -t;
- sign = -1;
- }
- t = 12 * t <= 1 ? sqrt(3 * t) : 0.17883277 * log(t - 0.02372241) + 1.004293468902569985701234145381;
- return t * sign;
-}
-
-static double invtransfer_function_oetf_hlg(double t)
-{
- double sign = 1;
- if (t < 0) {
- t = -t;
- sign = -1;
- }
- t = t <= 0.5 ? t * t / 3 : exp(t - 1.004293468902569985701234145381) / 0.17883277 + 0.02372241;
- return t * sign;
-}
-
-
-static void get_transfer_function(libcolour_colour_t* cs)
-{
- if (cs->model == LIBCOLOUR_RGB) {
- switch (cs->rgb.colour_space) {
- case LIBCOLOUR_RGB_COLOUR_SPACE_ECI_RGB_V2:
- cs->rgb.to_encoded_red = cs->rgb.to_encoded_green = cs->rgb.to_encoded_blue = transfer_function_l_star;
- cs->rgb.to_decoded_red = cs->rgb.to_decoded_green = cs->rgb.to_decoded_blue = invtransfer_function_l_star;
- break;
- case LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2100_EOTF_PQ:
- case LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2100_OOTF_PQ:
- case LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2100_OETF_PQ:
- case LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2100_EOTF_HLG:
- case LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2100_OOTF_HLG:
- /* TODO http://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.2100-0-201607-I!!PDF-E.pdf */
- break;
- case LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2100_OETF_HLG:
- cs->rgb.to_encoded_red = cs->rgb.to_encoded_green = cs->rgb.to_encoded_blue = transfer_function_oetf_hlg;
- cs->rgb.to_decoded_red = cs->rgb.to_decoded_green = cs->rgb.to_decoded_blue = invtransfer_function_oetf_hlg;
- break;
- default:
- break;
- }
- }
-}
-
-
-int libcolour_get_rgb_colour_space(libcolour_rgb_t* cs, libcolour_rgb_colour_space_t space)
-{
-#define XYY(XVALUE, YVALUE) (libcolour_ciexyy_t){ .model = LIBCOLOUR_CIEXYY, .x = XVALUE, .y = YVALUE, .Y = 1}
-
- switch (space) {
- 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:
- cs->red = XYY(0.6400, 0.3300);
- cs->green = XYY(0.3000, 0.6000);
- cs->blue = XYY(0.1500, 0.0600);
- cs->white = LIBCOLOUR_ILLUMINANT_D65;
- cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_REGULAR;
- cs->offset = 0.055;
- cs->gamma = 2.4;
- cs->slope = 12.92;
- cs->transition = 0.0031306684425217108;
- break;
-
- case LIBCOLOUR_RGB_COLOUR_SPACE_ADOBE_RGB:
- cs->red = XYY(0.6400, 0.3300);
- cs->green = XYY(0.2100, 0.7100);
- cs->blue = XYY(0.1500, 0.0600);
- cs->white = LIBCOLOUR_ILLUMINANT_D65;
- cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_SIMPLE;
- cs->gamma = 2.2;
- break;
-
- case LIBCOLOUR_RGB_COLOUR_SPACE_APPLE_RGB:
- cs->red = XYY(0.6250, 0.3400);
- cs->green = XYY(0.2800, 0.5950);
- cs->blue = XYY(0.1550, 0.0700);
- cs->white = LIBCOLOUR_ILLUMINANT_D65;
- cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_SIMPLE;
- cs->gamma = 1.8;
- break;
-
- case LIBCOLOUR_RGB_COLOUR_SPACE_BEST_RGB:
- cs->red = XYY(0.7347, 0.2653);
- cs->green = XYY(0.2150, 0.7750);
- cs->blue = XYY(0.1300, 0.0350);
- cs->white = LIBCOLOUR_ILLUMINANT_D50;
- cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_SIMPLE;
- cs->gamma = 2.2;
- break;
-
- case LIBCOLOUR_RGB_COLOUR_SPACE_BETA_RGB:
- cs->red = XYY(0.6888, 0.3112);
- cs->green = XYY(0.1986, 0.7551);
- cs->blue = XYY(0.1265, 0.0352);
- cs->white = LIBCOLOUR_ILLUMINANT_D50;
- cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_SIMPLE;
- cs->gamma = 2.2;
- break;
-
- case LIBCOLOUR_RGB_COLOUR_SPACE_BRUCE_RGB:
- cs->red = XYY(0.6400, 0.3300);
- cs->green = XYY(0.2800, 0.6500);
- cs->blue = XYY(0.1500, 0.0600);
- cs->white = LIBCOLOUR_ILLUMINANT_D65;
- cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_SIMPLE;
- cs->gamma = 2.2;
- break;
-
- case LIBCOLOUR_RGB_COLOUR_SPACE_CIE_RGB:
- cs->red = XYY(0.7350, 0.2650);
- 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;
- cs->gamma = 2.2;
- break;
-
- case LIBCOLOUR_RGB_COLOUR_SPACE_COLORMATCH_RGB:
- cs->red = XYY(0.6300, 0.3400);
- cs->green = XYY(0.2950, 0.6050);
- cs->blue = XYY(0.1500, 0.0750);
- cs->white = LIBCOLOUR_ILLUMINANT_D50;
- cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_SIMPLE;
- cs->gamma = 1.8;
- break;
-
- case LIBCOLOUR_RGB_COLOUR_SPACE_DCI_P3_D65:
- cs->red = XYY(0.6380, 0.3200);
- cs->green = XYY(0.2650, 0.6900);
- cs->blue = XYY(0.1500, 0.0600);
- cs->white = LIBCOLOUR_ILLUMINANT_D65;
- cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_SIMPLE;
- cs->gamma = 2.6;
- break;
-
- case LIBCOLOUR_RGB_COLOUR_SPACE_DCI_P3_THEATER:
- cs->red = XYY(0.6380, 0.3200);
- cs->green = XYY(0.2650, 0.6900);
- cs->blue = XYY(0.1500, 0.0600);
- cs->white = XYY(0.314, 0.351);
- cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_SIMPLE;
- cs->gamma = 2.6;
- break;
-
- case LIBCOLOUR_RGB_COLOUR_SPACE_DON_RGB_4:
- cs->red = XYY(0.6960, 0.3000);
- cs->green = XYY(0.2150, 0.7650);
- cs->blue = XYY(0.1300, 0.0350);
- cs->white = LIBCOLOUR_ILLUMINANT_D50;
- cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_SIMPLE;
- cs->gamma = 2.2;
- break;
-
- case LIBCOLOUR_RGB_COLOUR_SPACE_ECI_RGB:
- cs->red = XYY(0.6700, 0.3300);
- cs->green = XYY(0.2100, 0.7100);
- cs->blue = XYY(0.1400, 0.0800);
- cs->white = LIBCOLOUR_ILLUMINANT_D50;
- cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_SIMPLE;
- cs->gamma = 1.8;
- break;
-
- case LIBCOLOUR_RGB_COLOUR_SPACE_ECI_RGB_V2:
- cs->red = XYY(0.6700, 0.3300);
- cs->green = XYY(0.2100, 0.7100);
- cs->blue = XYY(0.1400, 0.0800);
- cs->white = LIBCOLOUR_ILLUMINANT_D50;
- cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_CUSTOM;
- break;
-
- case LIBCOLOUR_RGB_COLOUR_SPACE_EKTA_SPACE_PS5:
- cs->red = XYY(0.6950, 0.3050);
- cs->green = XYY(0.2600, 0.7000);
- cs->blue = XYY(0.1100, 0.0050);
- cs->white = LIBCOLOUR_ILLUMINANT_D50;
- cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_SIMPLE;
- cs->gamma = 2.2;
- break;
-
- case LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_601_625_LINE:
- cs->red = XYY(0.6400, 0.3300);
- cs->green = XYY(0.2900, 0.6000);
- cs->blue = XYY(0.1500, 0.0060);
- cs->white = LIBCOLOUR_ILLUMINANT_D65;
- cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_REGULAR;
- cs->gamma = 1 / 0.45;
- cs->offset = 0.09929682680944;
- cs->slope = 4.5;
- cs->transition = 0.018053968510807;
- break;
-
- case LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_601_525_LINE:
- cs->red = XYY(0.6300, 0.3400);
- cs->green = XYY(0.3100, 0.5950);
- cs->blue = XYY(0.1550, 0.0700);
- cs->white = LIBCOLOUR_ILLUMINANT_D65;
- cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_REGULAR;
- cs->gamma = 1 / 0.45;
- cs->offset = 0.09929682680944;
- cs->slope = 4.5;
- cs->transition = 0.018053968510807;
- break;
-
- case LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_709:
- cs->red = XYY(0.6300, 0.3300);
- cs->green = XYY(0.3000, 0.6000);
- cs->blue = XYY(0.1500, 0.0600);
- cs->white = LIBCOLOUR_ILLUMINANT_D65;
- cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_REGULAR;
- cs->gamma = 1 / 0.45;
- cs->offset = 0.09929682680944;
- cs->slope = 4.5;
- cs->transition = 0.018053968510807;
- break;
-
- case LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2020:
- cs->red = XYY(0.7080, 0.2920);
- cs->green = XYY(0.1700, 0.7970);
- cs->blue = XYY(0.1310, 0.0460);
- cs->white = LIBCOLOUR_ILLUMINANT_D65;
- cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_REGULAR;
- cs->gamma = 1 / 0.45;
- cs->offset = 0.09929682680944;
- cs->slope = 4.5;
- cs->transition = 0.018053968510807;
- break;
-
- case LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2100_EOTF_PQ:
- case LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2100_OOTF_PQ:
- case LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2100_OETF_PQ:
- case LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2100_EOTF_HLG:
- case LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2100_OOTF_HLG:
- case LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2100_OETF_HLG:
- cs->red = XYY(0.7080, 0.2920);
- cs->green = XYY(0.1700, 0.7970);
- cs->blue = XYY(0.1310, 0.0460);
- cs->white = LIBCOLOUR_ILLUMINANT_D65;
- cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_CUSTOM;
- break;
-
- case LIBCOLOUR_RGB_COLOUR_SPACE_LIGHTROOM_RGB:
- cs->red = XYY(0.7347, 0.2653);
- cs->green = XYY(0.1596, 0.8404);
- cs->blue = XYY(0.0366, 0.0001);
- cs->white = LIBCOLOUR_ILLUMINANT_D50;
- cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_LINEAR;
- break;
-
- case LIBCOLOUR_RGB_COLOUR_SPACE_NTSC_RGB:
- cs->red = XYY(0.6700, 0.3300);
- cs->green = XYY(0.2100, 0.7100);
- cs->blue = XYY(0.1400, 0.0800);
- cs->white = LIBCOLOUR_ILLUMINANT_C;
- cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_REGULAR;
- cs->gamma = 1 / 0.45;
- cs->offset = 0.09929682680944;
- cs->slope = 4.5;
- cs->transition = 0.018053968510807;
- break;
-
- case LIBCOLOUR_RGB_COLOUR_SPACE_PAL_SECAM_RGB:
- cs->red = XYY(0.6400, 0.3300);
- cs->green = XYY(0.2900, 0.6000);
- cs->blue = XYY(0.1500, 0.0600);
- cs->white = LIBCOLOUR_ILLUMINANT_D65;
- cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_REGULAR;
- cs->gamma = 1 / 0.45;
- cs->offset = 0.09929682680944;
- cs->slope = 4.5;
- cs->transition = 0.018053968510807;
- break;
-
- case LIBCOLOUR_RGB_COLOUR_SPACE_PROPHOTO_RGB:
- cs->red = XYY(0.7347, 0.2653);
- cs->green = XYY(0.1596, 0.8404);
- cs->blue = XYY(0.0366, 0.0001);
- cs->white = LIBCOLOUR_ILLUMINANT_D50;
- cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_SIMPLE;
- cs->gamma = 1.8;
- break;
-
- case LIBCOLOUR_RGB_COLOUR_SPACE_SGI_RGB:
- cs->red = XYY(0.6250, 0.3400);
- cs->green = XYY(0.2800, 0.5950);
- cs->blue = XYY(0.1550, 0.0700);
- cs->white = LIBCOLOUR_ILLUMINANT_D50;
- cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_SIMPLE;
- cs->gamma = 1.47;
- break;
-
- case LIBCOLOUR_RGB_COLOUR_SPACE_SMPTE_240M_RGB:
- cs->red = XYY(0.6300, 0.3400);
- cs->green = XYY(0.3100, 0.5950);
- cs->blue = XYY(0.1550, 0.0700);
- cs->white = LIBCOLOUR_ILLUMINANT_D65;
- cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_REGULAR;
- cs->gamma = 1 / 0.45;
- cs->offset = 0.1115721957735072;
- cs->slope = 4.0;
- cs->transition = 0.022821585552393633;
- break;
-
- case LIBCOLOUR_RGB_COLOUR_SPACE_SMPTE_C_RGB:
- cs->red = XYY(0.6300, 0.3400);
- cs->green = XYY(0.3100, 0.5950);
- cs->blue = XYY(0.1550, 0.0700);
- cs->white = LIBCOLOUR_ILLUMINANT_D65;
- cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_REGULAR;
- cs->gamma = 1 / 0.45;
- cs->offset = 0.09929682680944;
- cs->slope = 4.5;
- cs->transition = 0.018053968510807;
- break;
-
- case LIBCOLOUR_RGB_COLOUR_SPACE_WIDE_GAMUT_RGB:
- cs->red = XYY(0.7350, 0.2650);
- cs->green = XYY(0.1150, 0.8260);
- cs->blue = XYY(0.1570, 0.0180);
- cs->white = LIBCOLOUR_ILLUMINANT_D50;
- cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_SIMPLE;
- cs->gamma = 2.19921875;
- break;
-
- default:
- errno = EINVAL;
- return -1;
- }
- if (cs->encoding_type == LIBCOLOUR_ENCODING_TYPE_REGULAR)
- cs->transitioninv = cs->transition * cs->slope;
- cs->colour_space = space;
- cs->white_r = cs->white_g = cs->white_b = 1;
- if (get_matrices(cs) || libcolour_proper((libcolour_colour_t*)cs))
- return -1;
- get_transfer_function((libcolour_colour_t*)cs);
- return 0;
-
-#undef XYY
-}
-
-
-size_t libcolour_marshal(const libcolour_colour_t* colour, void* buf)
-{
- if (buf)
- *(int*)buf = MARSHAL_VERSION;
- switch (colour->model) {
-#define X(C, T)\
- case C:\
- if (buf)\
- memcpy((char*)buf + sizeof(int), colour, sizeof(T));\
- return sizeof(int) + sizeof(T);
- LIBCOLOUR_LIST_MODELS
-#undef X
- default:
- errno = EINVAL;
- return 0;
- }
-}
-
-
-size_t libcolour_unmarshal(libcolour_colour_t* colour, const void* buf)
-{
- enum libcolour_model model;
- size_t r;
- int ver;
- ver = *(int*)buf;
- if (ver != MARSHAL_VERSION) {
- errno = EINVAL;
- return 0;
- }
- model = *(enum libcolour_model*)((char*)buf + sizeof(int));
- switch (model) {
-#define X(C, T)\
- case C:\
- if (colour)\
- memcpy(colour, (char*)buf + sizeof(int), sizeof(T));\
- r = sizeof(int) + sizeof(T);\
- break;
- LIBCOLOUR_LIST_MODELS
-#undef X
- default:
- errno = EINVAL;
- return 0;
- }
- if (colour) {
- if (colour->model == LIBCOLOUR_RGB) {
- colour->rgb.to_encoded_red = colour->rgb.to_encoded_green = colour->rgb.to_encoded_blue = NULL;
- colour->rgb.to_decoded_red = colour->rgb.to_decoded_green = colour->rgb.to_decoded_blue = NULL;
- }
- get_transfer_function(colour);
- }
- return r;
-}
-
diff --git a/src/libcolour.h b/src/libcolour.h
deleted file mode 100644
index 6387151..0000000
--- a/src/libcolour.h
+++ /dev/null
@@ -1,301 +0,0 @@
-/**
- * Copyright © 2016 Mattias Andrée <maandree@kth.se>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef LIBCOLOUR_H
-#define LIBCOLOUR_H
-
-
-#include <stddef.h>
-
-
-
-#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\
- X(LIBCOLOUR_RGB, libcolour_rgb_t)\
- X(LIBCOLOUR_SRGB, libcolour_srgb_t)\
- X(LIBCOLOUR_CIEXYY, libcolour_ciexyy_t)\
- X(LIBCOLOUR_CIEXYZ, libcolour_ciexyz_t)\
- X(LIBCOLOUR_CIELAB, libcolour_cielab_t)\
- X(LIBCOLOUR_CIELUV, libcolour_cieluv_t)\
- X(LIBCOLOUR_CIELCHUV, libcolour_cielchuv_t)\
- X(LIBCOLOUR_YIQ, libcolour_yiq_t)\
- X(LIBCOLOUR_YDBDR, libcolour_ydbdr_t)\
- X(LIBCOLOUR_YUV, libcolour_yuv_t)\
- X(LIBCOLOUR_YPBPR, libcolour_ypbpr_t)\
- X(LIBCOLOUR_YCGCO, libcolour_ycgco_t)\
- X(LIBCOLOUR_CIE1960UCS, libcolour_cie1960ucs_t)\
- X(LIBCOLOUR_CIEUVW, libcolour_cieuvw_t)
-
-
-typedef enum libcolour_model {
-#define X(C, T) C,
- LIBCOLOUR_LIST_MODELS
-#undef X
-} libcolour_model_t;
-
-
-typedef enum libcolour_encoding_type {
- LIBCOLOUR_ENCODING_TYPE_LINEAR,
- LIBCOLOUR_ENCODING_TYPE_SIMPLE,
- LIBCOLOUR_ENCODING_TYPE_REGULAR,
- LIBCOLOUR_ENCODING_TYPE_CUSTOM
-} libcolour_encoding_type;
-
-
-typedef enum libcolour_rgb_colour_space {
- LIBCOLOUR_RGB_COLOUR_SPACE_CUSTOM_FROM_MEASUREMENTS,
- LIBCOLOUR_RGB_COLOUR_SPACE_CUSTOM_FROM_MATRIX,
- LIBCOLOUR_RGB_COLOUR_SPACE_CUSTOM_FROM_INV_MATRIX,
- LIBCOLOUR_RGB_COLOUR_SPACE_SRGB,
- LIBCOLOUR_RGB_COLOUR_SPACE_ADOBE_RGB,
- LIBCOLOUR_RGB_COLOUR_SPACE_APPLE_RGB,
- LIBCOLOUR_RGB_COLOUR_SPACE_BEST_RGB,
- LIBCOLOUR_RGB_COLOUR_SPACE_BETA_RGB,
- LIBCOLOUR_RGB_COLOUR_SPACE_BRUCE_RGB,
- LIBCOLOUR_RGB_COLOUR_SPACE_CIE_RGB,
- LIBCOLOUR_RGB_COLOUR_SPACE_COLORMATCH_RGB,
- LIBCOLOUR_RGB_COLOUR_SPACE_DCI_P3_D65,
- LIBCOLOUR_RGB_COLOUR_SPACE_DCI_P3_THEATER,
- LIBCOLOUR_RGB_COLOUR_SPACE_DON_RGB_4,
- LIBCOLOUR_RGB_COLOUR_SPACE_ECI_RGB,
- LIBCOLOUR_RGB_COLOUR_SPACE_ECI_RGB_V2,
- LIBCOLOUR_RGB_COLOUR_SPACE_EKTA_SPACE_PS5,
- LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_601_625_LINE,
- LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_601_525_LINE,
- LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_709,
- LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2020,
- LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2100_EOTF_PQ,
- LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2100_OOTF_PQ,
- LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2100_OETF_PQ,
- LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2100_EOTF_HLG,
- LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2100_OOTF_HLG,
- LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2100_OETF_HLG,
- LIBCOLOUR_RGB_COLOUR_SPACE_LIGHTROOM_RGB,
- LIBCOLOUR_RGB_COLOUR_SPACE_NTSC_RGB,
- LIBCOLOUR_RGB_COLOUR_SPACE_PAL_SECAM_RGB,
- LIBCOLOUR_RGB_COLOUR_SPACE_PROPHOTO_RGB,
- LIBCOLOUR_RGB_COLOUR_SPACE_SGI_RGB,
- LIBCOLOUR_RGB_COLOUR_SPACE_SMPTE_240M_RGB,
- LIBCOLOUR_RGB_COLOUR_SPACE_SMPTE_C_RGB,
- LIBCOLOUR_RGB_COLOUR_SPACE_WIDE_GAMUT_RGB
-} libcolour_rgb_colour_space_t;
-
-
-typedef struct libcolour_srgb {
- enum libcolour_model model;
- double R;
- double G;
- double B;
- int with_gamma;
-} libcolour_srgb_t;
-
-typedef struct libcolour_ciexyy {
- enum libcolour_model model;
- double x;
- double y;
- double Y;
-} libcolour_ciexyy_t;
-
-typedef struct libcolour_ciexyz {
- enum libcolour_model model;
- double X;
- double Y;
- double Z;
-} libcolour_ciexyz_t;
-
-typedef struct libcolour_cielab {
- enum libcolour_model model;
- double L;
- double a;
- double b;
-} libcolour_cielab_t;
-
-typedef struct libcolour_yiq {
- enum libcolour_model model;
- double Y;
- double I;
- double Q;
-} libcolour_yiq_t;
-
-typedef struct libcolour_ydbdr {
- enum libcolour_model model;
- double Y;
- double Db;
- double Dr;
-} libcolour_ydbdr_t;
-
-typedef struct libcolour_yuv {
- enum libcolour_model model;
- double Y;
- double U;
- double V;
-} libcolour_yuv_t;
-
-typedef struct libcolour_ypbpr {
- enum libcolour_model model;
- double Y;
- double Pb;
- double Pr;
-} libcolour_ypbpr_t;
-
-typedef struct libcolour_ycgco {
- enum libcolour_model model;
- double Y;
- double Cg;
- double Co;
-} libcolour_ycgco_t;
-
-typedef struct libcolour_cie1960ucs {
- enum libcolour_model model;
- double u;
- double v;
- double Y;
-} libcolour_cie1960ucs_t;
-
-typedef struct libcolour_cieuvw {
- enum libcolour_model model;
- double U;
- double V;
- double W;
- double u0;
- double v0;
-} libcolour_cieuvw_t;
-
-typedef struct libcolour_cieluv {
- enum libcolour_model model;
- double L;
- double u;
- double v;
- struct libcolour_ciexyz white;
-} libcolour_cieluv_t;
-
-typedef struct libcolour_cielchuv {
- enum libcolour_model model;
- double L;
- double C;
- double h;
- struct libcolour_ciexyz white;
- double one_revolution;
-} libcolour_cielchuv_t;
-
-typedef struct libcolour_rgb {
- enum libcolour_model model;
- double R;
- double G;
- double B;
- int with_gamma;
- enum libcolour_encoding_type encoding_type;
- double gamma;
- double offset;
- double slope;
- double transition;
- double transitioninv;
- double (*to_encoded_red)(double);
- double (*to_decoded_red)(double);
- double (*to_encoded_green)(double);
- double (*to_decoded_green)(double);
- double (*to_encoded_blue)(double);
- double (*to_decoded_blue)(double);
- struct libcolour_ciexyy red;
- struct libcolour_ciexyy green;
- struct libcolour_ciexyy blue;
- struct libcolour_ciexyy white;
- double white_r;
- double white_g;
- double white_b;
- double M[3][3];
- double Minv[3][3];
- enum libcolour_rgb_colour_space colour_space;
-} libcolour_rgb_t;
-
-
-typedef union libcolour_colour {
- enum libcolour_model model;
- struct libcolour_rgb rgb;
- struct libcolour_srgb srgb;
- struct libcolour_ciexyy ciexyy;
- struct libcolour_ciexyz ciexyz;
- struct libcolour_cielab cielab;
- struct libcolour_cieluv cieluv;
- struct libcolour_cielchuv cielchuv;
- struct libcolour_yiq yiq;
- struct libcolour_ydbdr ydbdr;
- struct libcolour_yuv yuv;
- struct libcolour_ypbpr ypbpr;
- struct libcolour_ycgco ycgco;
- struct libcolour_cie1960ucs cie1960ucs;
- struct libcolour_cieuvw cieuvw;
-} libcolour_colour_t;
-
-
-
-int libcolour_convert(const libcolour_colour_t* restrict from, libcolour_colour_t* restrict to);
-double libcolour_srgb_encode(double);
-double libcolour_srgb_decode(double);
-int libcolour_delta_e(const libcolour_colour_t*, const libcolour_colour_t*, double*);
-int libcolour_proper(libcolour_colour_t*);
-int libcolour_get_rgb_colour_space(libcolour_rgb_t*, libcolour_rgb_colour_space_t);
-size_t libcolour_marshal(const libcolour_colour_t*, void*);
-size_t libcolour_unmarshal(libcolour_colour_t*, const void*);
-
-
-
-#endif
-
diff --git a/src/test.c b/src/test.c
deleted file mode 100644
index ad7acfc..0000000
--- a/src/test.c
+++ /dev/null
@@ -1,657 +0,0 @@
-/**
- * Copyright © 2016 Mattias Andrée <maandree@kth.se>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-#include "libcolour.h"
-
-#include <math.h>
-#include <stdio.h>
-#include <string.h>
-
-
-#ifndef SKIP_2CONVERT
-static int test_2convert(libcolour_colour_t* c1, libcolour_colour_t* c2, libcolour_colour_t* c3)
-{
- double ch1, ch2, ch3;
- if (libcolour_convert(c1, c2))
- return -1;
- if (libcolour_convert(c2, c3))
- return -1;
- if ((c1->model == LIBCOLOUR_CIELCHUV) &&
- !isnan(c1->cielchuv.h) && !isnan(c3->cielchuv.h) &&
- !isinf(c1->cielchuv.h) && !isinf(c3->cielchuv.h) &&
- (c3->cielchuv.h / c3->cielchuv.one_revolution > 0.99999))
- c3->cielchuv.h = 0;
- ch1 = c1->srgb.R - c3->srgb.R;
- ch2 = c1->srgb.G - c3->srgb.G;
- ch3 = c1->srgb.B - c3->srgb.B;
- ch1 *= ch1;
- ch2 *= ch2;
- ch3 *= ch3;
- switch (c1->model) {
- case LIBCOLOUR_CIEXYY:
- if (c1->ciexyy.Y == 0)
- ch1 = ch2 = 0;
- if (c1->ciexyy.y == 0)
- ch1 = ch2 = ch3 = 0;
- break;
- case LIBCOLOUR_CIEXYZ:
- if (c1->ciexyz.Y == 0)
- ch1 = ch3 = 0;
- break;
- case LIBCOLOUR_CIE1960UCS:
- if (c1->cie1960ucs.v == 0)
- ch1 = ch2 = ch3 = 0;
- if (c1->cie1960ucs.Y == 0)
- ch1 = ch2 = 0;
- break;
- case LIBCOLOUR_CIEUVW:
- if (c1->cieuvw.W == 0)
- ch1 = ch2 = 0;
- break;
- case LIBCOLOUR_CIELCHUV:
- if (c1->cielchuv.C == 0)
- ch1 = ch3 = 0;
- break;
- case LIBCOLOUR_CIELAB:
- if (c1->cielchuv.L == 0)
- ch2 = ch3 = 0;
- break;
- default:
- break;
- }
- if (ch1 > 0.000001 ||
- ch2 > 0.000001 ||
- ch3 > 0.000001)
- return 0;
- return 1;
-}
-
-
-static int test_2convert_11(libcolour_colour_t* c1, libcolour_model_t model)
-{
- libcolour_colour_t c2, c3;
- int r1, r2;
- c3 = *c1;
- c2.model = model;
- switch (model) {
- case LIBCOLOUR_RGB:
- c2.rgb.with_gamma = 0;
- if (libcolour_get_rgb_colour_space(&c2.rgb, LIBCOLOUR_RGB_COLOUR_SPACE_SRGB) < 0)
- return -1;
- return test_2convert(c1, &c2, &c3);
- case LIBCOLOUR_SRGB:
- c2.srgb.with_gamma = 0;
- if (r1 = test_2convert(c1, &c2, &c3), r1 < 0)
- return -1;
- c2.srgb.with_gamma = 1;
- if (r2 = test_2convert(c1, &c2, &c3), r2 < 0)
- return -1;
- return r1 & r2;
- case LIBCOLOUR_CIELCHUV:
- c2.cielchuv.one_revolution = 360.;
- /* fall though */
- case LIBCOLOUR_CIELUV:
- c2.cieluv.white.model = LIBCOLOUR_CIEXYZ;
- c2.cieluv.white.X = 1.0294;
- c2.cieluv.white.Y = 1;
- c2.cieluv.white.Z = 0.9118;
- return test_2convert(c1, &c2, &c3);
- case LIBCOLOUR_CIEUVW:
- c2.cieuvw.u0 = 0.37;
- c2.cieuvw.v0 = 0.30;
- return test_2convert(c1, &c2, &c3);
- default:
- return test_2convert(c1, &c2, &c3);
- }
-}
-
-
-static int test_2convert_1n(libcolour_model_t model, const char* model_name, double ch1, double ch2, double ch3)
-{
- libcolour_colour_t c1;
- int run, r, rc = 1;
-
- c1.model = model;
- switch (model) {
- case LIBCOLOUR_CIELAB:
- c1.cielab.L = ch1 * 100, c1.cielab.a = ch2 * 100, c1.cielab.b = ch3 * 100;
- break;
- case LIBCOLOUR_CIELCHUV:
- if (ch3 > 0.9999)
- return 1;
- /* fall though */
- default:
- c1.srgb.R = ch1, c1.srgb.G = ch2, c1.srgb.B = ch3;
- break;
- }
-
- for (run = 0;; run++) {
- switch (model) {
- case LIBCOLOUR_RGB:
- if (run == 2)
- return rc;
- c1.rgb.with_gamma = run;
- if (libcolour_get_rgb_colour_space(&c1.rgb, LIBCOLOUR_RGB_COLOUR_SPACE_SRGB) < 0)
- return -1;
- break;
- case LIBCOLOUR_SRGB:
- if (run == 2)
- return rc;
- c1.srgb.with_gamma = run;
- break;
- case LIBCOLOUR_CIELCHUV:
- c1.cielchuv.one_revolution = run < 2 ? 360. : 2 * 3.14159265358979323846;
- c1.cielchuv.h *= c1.cielchuv.one_revolution;
- /* fall through */
- case LIBCOLOUR_CIELUV:
- c1.cieluv.white.model = LIBCOLOUR_CIEXYZ;
- if (run == 0) {
- c1.cieluv.white.X = 1.0294;
- c1.cieluv.white.Y = 1;
- c1.cieluv.white.Z = 0.9118;
- } else if (run == 1) {
- c1.cieluv.white.X = 1.03;
- c1.cieluv.white.Y = 0.8;
- c1.cieluv.white.Z = 0.92;
- } else if (run == 2 && model == LIBCOLOUR_CIELCHUV) {
- c1.cieluv.white.X = 1.0294;
- c1.cieluv.white.Y = 1;
- c1.cieluv.white.Z = 0.9118;
- } else if (run == 3 && model == LIBCOLOUR_CIELCHUV) {
- c1.cieluv.white.X = 1.03;
- c1.cieluv.white.Y = 0.8;
- c1.cieluv.white.Z = 0.92;
- } else {
- return rc;
- }
- break;
- case LIBCOLOUR_CIEUVW:
- if (run == 0) {
- c1.cieuvw.u0 = 0.37;
- c1.cieuvw.v0 = 0.30;
- } else if (run == 1) {
- c1.cieuvw.u0 = 0.47;
- c1.cieuvw.v0 = 0.31;
- } else {
- return rc;
- }
- break;
- default:
- if (run == 1)
- return rc;
- break;
- }
-
-#define X(ENUM, TYPE)\
- r = test_2convert_11(&c1, ENUM);\
- if (r < 0)\
- return -1;\
- if (!r)\
- printf("%s -> %s -> %s failed at run %i with (%lf, %lf, %lf)\n",\
- model_name, #ENUM, model_name, run, ch1, ch2, ch3), rc = 0;
- LIBCOLOUR_LIST_MODELS;
-#undef X
- }
-}
-
-
-static int test_2convert_nm(double ch1, double ch2, double ch3)
-{
- int r, rc = 1;
-
-#define X(ENUM, TYPE)\
- r = test_2convert_1n(ENUM, #ENUM, ch1, ch2, ch3);\
- if (r < 0)\
- return -1;\
- if (!r)\
- rc = 0;
- LIBCOLOUR_LIST_MODELS;
-#undef X
-
- return rc;
-}
-
-
-static int test_2convert_nm_all(void)
-{
-#define N 11
- int r, rc = 1;
- double ch1, ch2, ch3;
- int i, j, k;
-
- for (i = 0; i < N; i++) {
- for (j = 0; j < N; j++) {
- for (k = 0; k < N; k++) {
- ch1 = ((i + N / 2) % N) / (N - 1);
- ch2 = ((j + N / 2) % N) / (N - 1);
- ch3 = ((k + N / 2) % N) / (N - 1);
-
- if (ch1 > 0.999) ch1 = 1;
- if (ch2 > 0.999) ch2 = 1;
- if (ch3 > 0.999) ch3 = 1;
-
- r = test_2convert_nm(ch1, ch2, ch3);
- if (r < 0)
- return -1;
- if (!r)
- rc = 0;
- }
- }
- }
-
- 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);
- 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);
- 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;
-}
-
-
-static int test_1convert(libcolour_colour_t *c1, libcolour_model_t model, const char* name1,
- const char* name2, double ch1, double ch2, double ch3, double d1,
- double d2, double d3)
-{
- libcolour_colour_t c2, c3;
- int rc = 1;
- c3 = *c1;
- c2.model = model;
- switch (model) {
- case LIBCOLOUR_CIELCHUV:
- c2.cielchuv.one_revolution = 360;
- /* fall-through */
- case LIBCOLOUR_CIELUV:
- c2.cieluv.white.X = 0.9504705586542831;
- c2.cieluv.white.Y = 1;
- c2.cieluv.white.Z = 1.0888287363958837;
- break;
- default:
- break;
- }
- if (libcolour_convert(c1, &c2))
- return -1;
- if (!ftest(c2.srgb.R, ch1, d1) ||
- !ftest(c2.srgb.G, ch2, d2) ||
- !ftest(c2.srgb.B, ch3, d3)) {
- printf("%s -> %s failed\n", name1, name2), rc = 0;
- rc = 0;
- }
- if (libcolour_convert(&c2, &c3))
- return -1;
- if (!ftest(c3.srgb.R, c1->srgb.R, 0.00000001) ||
- !ftest(c3.srgb.G, c1->srgb.G, 0.00000001) ||
- !ftest(c3.srgb.B, c1->srgb.B, 0.00000001)) {
- printf("%s -> %s failed\n", name2, name1), rc = 0;
- rc = 0;
- }
- return rc;
-}
-
-
-/**
- * Test libcolour
- *
- * @return 0: All tests passed
- * 1: At least one test fail
- * 2: An error occurred
- */
-int main(int argc, char* argv[])
-{
- int r, rc = 0;
- libcolour_colour_t c1, c2, c3, c4;
- double t1, t2;
- size_t n;
- char buf[sizeof(int) + sizeof(libcolour_rgb_t)];
-
-#ifndef SKIP_2CONVERT
- r = test_2convert_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_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 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 transfer functions more rigorously */
-
- c1.model = c2.model = LIBCOLOUR_RGB;
- c3.model = c4.model = LIBCOLOUR_SRGB;
- c1.rgb.with_gamma = c3.srgb.with_gamma = 0;
- c2.rgb.with_gamma = c4.srgb.with_gamma = 1;
- if (libcolour_get_rgb_colour_space(&c1.rgb, LIBCOLOUR_RGB_COLOUR_SPACE_SRGB))
- goto fail;
- if (libcolour_get_rgb_colour_space(&c2.rgb, LIBCOLOUR_RGB_COLOUR_SPACE_SRGB))
- goto fail;
- for (t1 = 0; t1 <= 1; t1 += 0.001) {
- c1.rgb.R = c3.srgb.R = t1 - 1;
- c1.rgb.G = c3.srgb.G = t1;
- c1.rgb.B = c3.srgb.B = t1 + 1;
- if (libcolour_convert(&c1, &c2))
- goto fail;
- if (libcolour_convert(&c3, &c4))
- goto fail;
- if (!ftest(c2.rgb.R, c4.srgb.R, 0.00000000001) ||
- !ftest(c2.rgb.G, c4.srgb.G, 0.00000000001) ||
- !ftest(c2.rgb.B, c4.srgb.B, 0.00000000001) ||
- !ftest(libcolour_srgb_encode(c1.rgb.R), c2.srgb.R, 0.00000000001) ||
- !ftest(libcolour_srgb_encode(c1.rgb.G), c2.srgb.G, 0.00000000001) ||
- !ftest(libcolour_srgb_encode(c1.rgb.B), c2.srgb.B, 0.00000000001)) {
- printf("libcolour_srgb_encode failed\n"), rc = 0;
- goto colour_spaces_done;
- }
- if (libcolour_convert(&c2, &c1))
- goto fail;
- if (libcolour_convert(&c4, &c3))
- goto fail;
- if (!ftest(c1.rgb.R, c3.srgb.R, 0.00000000001) ||
- !ftest(c1.rgb.G, c3.srgb.G, 0.00000000001) ||
- !ftest(c1.rgb.B, c3.srgb.B, 0.00000000001) ||
- !ftest(libcolour_srgb_decode(c2.rgb.R), c1.srgb.R, 0.00000000001) ||
- !ftest(libcolour_srgb_decode(c2.rgb.G), c1.srgb.G, 0.00000000001) ||
- !ftest(libcolour_srgb_decode(c2.rgb.B), c1.srgb.B, 0.00000000001)) {
- printf("libcolour_srgb_decode failed\n"), rc = 0;
- goto colour_spaces_done;
- }
- }
-
- c1.rgb.encoding_type = LIBCOLOUR_ENCODING_TYPE_SIMPLE;
- c1.rgb.gamma = 2.2;
- c1.rgb.with_gamma = 0;
- c1.rgb.R = 0.25;
- c1.rgb.G = 0.5;
- c1.rgb.B = 0.75;
- c4 = c3 = c2 = c1;
- c2.rgb.with_gamma = c3.srgb.with_gamma = 1;
- c3.rgb.gamma = c4.rgb.gamma = 1.8;
- if (libcolour_convert(&c1, &c2))
- goto fail;
- if (libcolour_convert(&c2, &c3))
- goto fail;
- if (libcolour_convert(&c3, &c4))
- goto fail;
- if (!ftest(c1.rgb.R, c4.srgb.R, 0.0000001) ||
- !ftest(c1.rgb.G, c4.srgb.G, 0.0000001) ||
- !ftest(c1.rgb.B, c4.srgb.B, 0.0000001)) {
- printf("libcolour_convert failed to convert between two transfer functions\n"), rc = 0;
- goto colour_spaces_done;
- }
-
- if (libcolour_convert(&c1, &c4))
- goto fail;
- if (!ftest(c1.rgb.R, c4.srgb.R, 0.0000001) ||
- !ftest(c1.rgb.G, c4.srgb.G, 0.0000001) ||
- !ftest(c1.rgb.B, c4.srgb.B, 0.0000001)) {
- printf("libcolour_convert failed to convert when two different transfer functions are not applied\n"), rc = 0;
- goto colour_spaces_done;
- }
-
-#define TEST(TO, CH1, CH2, CH3, D1, D2, D3)\
- r = test_1convert(&c1, TO, "LIBCOLOUR_SRGB", #TO, CH1, CH2, CH3, D1, D2, D3);\
- if (r < 0)\
- goto fail;\
- if (!r)\
- rc = 1;
-
- c1.model = LIBCOLOUR_SRGB;
- c1.srgb.with_gamma = 0;
- c1.srgb.R = 0.3, c1.srgb.G = 0.2, c1.srgb.B = 0.7;
- TEST(LIBCOLOUR_CIEXYZ, 0.321558, 0.257355, 0.694851, 0.000001, 00000001, 0.000001);
- TEST(LIBCOLOUR_CIEXYY, 0.252447, 0.202043, 0.257355, 0.000001, 0.000001, 0.000001);
- TEST(LIBCOLOUR_CIELAB, 57.7851, 30.3599, -44.9740, 0.0001, 0.0001, 0.0001);
- TEST(LIBCOLOUR_CIELUV, 57.7851, 5.5723, -74.1571, 0.0001, 0.0001, 0.0001);
- TEST(LIBCOLOUR_CIELCHUV, 57.7851, 74.3662, 274.2972, 0.0001, 0.0001, 0.0001);
- /*
- * TODO convert test from sRGB to:
- * LChab 57.7851, 54.2622, 304.0215
- * YDbDr
- * YPbPr
- * YCgCo
- * CIE 1960 UCS
- * CIEUVW
- */
- c1.srgb.with_gamma = 0;
- c1.srgb.R = 32 / 255., c1.srgb.G = 65 / 255., c1.srgb.B = 32 / 255.;
- TEST(LIBCOLOUR_YIQ, 0.201, -0.035, -0.068, 0.001, 0.001, 0.001);
- TEST(LIBCOLOUR_YUV, 0.201, -0.037, -0.067, 0.001, 0.001, 0.001);
- /* XXX YCbCr(60, 118, 116) */
- /* XXX HSV(120, 0.508, 0.255) */
- /* XXX HSI(120, 0.256, 0.169) */
- /* XXX HSL(120, 0.340, 0.190) */
-
- if (rc)
- goto colour_spaces_done;
-
-#undef TEST
- colour_spaces_done:
-
- memset(&c1, 0, sizeof(c1));
- memset(&c2, 0, sizeof(c2));
- c1.model = LIBCOLOUR_RGB;
- if (libcolour_get_rgb_colour_space(&c1.rgb, LIBCOLOUR_RGB_COLOUR_SPACE_ECI_RGB_V2))
- goto fail;
- c3 = c1;
- c1.rgb.to_encoded_red = NULL;
- c1.rgb.to_encoded_green = NULL;
- c1.rgb.to_encoded_blue = NULL;
- c1.rgb.to_decoded_red = NULL;
- c1.rgb.to_decoded_green = NULL;
- c1.rgb.to_decoded_blue = NULL;
- if (libcolour_marshal(&c1, NULL) > sizeof(buf)) {
- printf("libcolour_marshal failed\n"), rc = 0;
- goto marshal_done;
- }
- n = libcolour_marshal(&c1, buf);
- if (n > sizeof(buf)) {
- printf("libcolour_marshal failed\n"), rc = 0;
- goto marshal_done;
- }
- if (libcolour_unmarshal(NULL, buf) != n) {
- printf("libcolour_unmarshal failed\n"), rc = 0;
- goto marshal_done;
- }
- if (libcolour_unmarshal(&c2, buf) != n) {
- printf("libcolour_unmarshal failed\n"), rc = 0;
- goto marshal_done;
- }
- if (memcmp(&c2, &c3, sizeof(c2))) {
- printf("libcolour_(un)marshal failed\n"), rc = 0;
- goto marshal_done;
- }
- marshal_done:
-
- return rc;
- fail:
- perror(*argv);
- return 2;
- (void) argc;
-}