diff options
Diffstat (limited to '')
-rw-r--r-- | src/convert.c | 1068 | ||||
-rw-r--r-- | src/libcolour.c | 717 | ||||
-rw-r--r-- | src/libcolour.h | 301 | ||||
-rw-r--r-- | src/test.c | 657 |
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; -} |