From 7871f5f946ce19c22c1b69a1019dee9cfa665731 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Mon, 12 Jun 2017 18:03:48 +0200 Subject: libcolour_convert uses libcolour_convert_en_masse instead of the other way around MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- Makefile | 4 +- TODO | 2 +- common.h | 413 ------------------------------ conversions.h | 382 ++++++++++++++++++++++++++++ convert-template.c | 633 ---------------------------------------------- double.c | 2 +- en_masse-template.c | 693 +++++++++++++++++++++++++++++++++++++++++++++++---- float.c | 2 +- libcolour-template.c | 12 + long-double.c | 2 +- test.c | 99 ++++++-- 11 files changed, 1122 insertions(+), 1122 deletions(-) create mode 100644 conversions.h delete mode 100644 convert-template.c diff --git a/Makefile b/Makefile index 91fde95..3c55d18 100644 --- a/Makefile +++ b/Makefile @@ -12,10 +12,10 @@ OBJ =\ HDR =\ libcolour.h\ - common.h + common.h\ + conversions.h TEMPLATES =\ - convert-template.c\ en_masse-template.c\ libcolour-template.c diff --git a/TODO b/TODO index 4a19de7..00d583f 100644 --- a/TODO +++ b/TODO @@ -21,5 +21,5 @@ Colour models and colour spaces: Support for generic additive colour spaces (3 channels and more) Support for generic subtractive colour spaces (3 channels and more) -Improve performance of libcolour_convert_en_masse GPU accelerate libcolour_convert_en_masse +Premulti matrices for faster conversion from and to RGB diff --git a/common.h b/common.h index 12c86a2..8e384c9 100644 --- a/common.h +++ b/common.h @@ -24,21 +24,6 @@ #define REGULAR(S, T) ((T) <= (S)->TRANSITION ? (S)->SLOPE * (T) : (1 + (S)->OFFSET) * xpow((T), 1 / (S)->GAMMA) - (S)->OFFSET) #define INVREGULAR(S, T) ((T) <= (S)->TRANSITIONINV ? (T) / (S)->SLOPE : xpow(((T) + (S)->OFFSET) / (1 + (S)->OFFSET), (S)->GAMMA)) -#define XTRANSFORM(X, Y, Z, A, B, C, R1C1, R1C2, R1C3, R2C1, R2C2, R2C3, R3C1, R3C2, R3C3)\ - do {\ - TYPE a__ = (A), b__ = (B), c__ = (C);\ - (X) = (R1C1) * a__ + (R1C2) * b__ + (R1C3) * c__;\ - (Y) = (R2C1) * a__ + (R2C2) * b__ + (R2C3) * c__;\ - (Z) = (R3C1) * a__ + (R3C2) * b__ + (R3C3) * c__;\ - } while (0) - -#define TRANSFORM(X, Y, Z, A, B, C, R1C1, R1C2, R1C3, R2C1, R2C2, R2C3, R3C1, R3C2, R3C3)\ - XTRANSFORM((X), (Y), (Z), (A), (B), (C),\ - D(R1C1), D(R1C2), D(R1C3),\ - D(R2C1), D(R2C2), D(R2C3),\ - D(R3C1), D(R3C2), D(R3C3)) - - #define SLOPE transfer.regular.slope #define TRANSITIONINV transfer.regular.transitioninv @@ -53,404 +38,6 @@ #define TO_DECODED_BLUE transfer.custom.to_decoded_blue - -#define CIEXYZ_TO_RGB(FROM_X, FROM_Y, FROM_Z, TO_R, TO_G, TO_B, TO_MINV)\ - XTRANSFORM((TO_R), (TO_G), (TO_B), (FROM_X), (FROM_Y), (FROM_Z),\ - (TO_MINV)[0][0], (TO_MINV)[0][1], (TO_MINV)[0][2],\ - (TO_MINV)[1][0], (TO_MINV)[1][1], (TO_MINV)[1][2],\ - (TO_MINV)[2][0], (TO_MINV)[2][1], (TO_MINV)[2][2]) - -#define CIEXYZ_TO_SRGB(FROM_X, FROM_Y, FROM_Z, TO_R, TO_G, TO_B)\ - TRANSFORM((TO_R), (TO_G), (TO_B), (FROM_X), (FROM_Y), (FROM_Z),\ - 3.240446254647737500675930277794, -1.537134761820080575134284117667, -0.498530193022728718155178739835,\ - -0.969266606244679751469561779231, 1.876011959788370209167851498933, 0.041556042214430065351304932619,\ - 0.055643503564352832235773149705, -0.204026179735960239147729566866, 1.057226567722703292062647051353) - -#define YIQ_TO_SRGB(FROM_Y, FROM_I, FROM_Q, TO_R, TO_G, TO_B)\ - TRANSFORM((TO_R), (TO_G), (TO_B), (FROM_Y), (FROM_I), (FROM_Q),\ - 1., 0.95629483232089407263032398986979387700557708740234, 0.62102512544472865396727456754888407886028289794922,\ - 1., -0.27212147408397735492968649850809015333652496337891, -0.64738095351761570928061928498209454119205474853516,\ - 1., -1.10698990856712820018969978264067322015762329101562, 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 ⎠ - */ - -#define YDBDR_TO_SRGB(FROM_Y, FROM_DB, FROM_DR, TO_R, TO_G, TO_B)\ - TRANSFORM((TO_R), (TO_G), (TO_B), (FROM_Y), (FROM_DB), (FROM_DR),\ - 1., 0.000092303716148, -0.525912630661865,\ - 1., -0.129132898890509, 0.267899328207599,\ - 1., 0.664679059978955, -0.000079202543533) - -#define YPBPR_TO_SRGB(FROM_Y, FROM_PB, FROM_PR, TO_R, TO_G, TO_B)\ - do {\ - TYPE y__ = (FROM_Y);\ - TYPE r__ = (FROM_PR) + y__;\ - TYPE b__ = (FROM_PB) + y__;\ - (TO_R) = r__;\ - (TO_B) = b__;\ - (TO_G) = (y__ - r__ * D(0.2126) - b__ * D(0.0722)) / D(0.7152);\ - } while (0) - -#define YUV_TO_SRGB(FROM_Y, FROM_U, FROM_V, TO_R, TO_G, TO_B)\ - TRANSFORM((TO_R), (TO_G), (TO_B), (FROM_Y), (FROM_U), (FROM_V),\ - 1., 0.00028328010485821202317155420580263580632163211703, 1.14070449590558520291949662350816652178764343261719,\ - 1., -0.39630886669497211727275498560629785060882568359375, -0.58107364288228224857846271333983168005943298339844,\ - 1., 2.03990003507541306504435851820744574069976806640625, 0.00017179031692307700847528739718228507626918144524) - -#define YCGCO_TO_SRGB(FROM_Y, FROM_CG, FROM_CO, TO_R, TO_G, TO_B)\ - TRANSFORM((TO_R), (TO_G), (TO_B), (FROM_Y), (FROM_CG), (FROM_CO),\ - 1., -1., 1.,\ - 1., 1., 0.,\ - 1., -1., -1.) - -#define CIEXYZ_TO_CIEXYY(FROM_X, FROM_Y, FROM_Z, TO_X, TO_Y, TO_YY)\ - do {\ - TYPE x__ = (FROM_X), y__ = (FROM_Y), z__ = (FROM_Z);\ - TYPE s__ = x__ + y__ + z__;\ - x__ = x__ / s__;\ - s__ = y__ / s__;\ - if (WASDIV0(x__) || WASDIV0(s__))\ - x__ = s__ = 0;\ - (TO_X) = x__;\ - (TO_Y) = s__;\ - (TO_YY) = y__;\ - } while (0) - -#define RGB_TO_CIEXYZ(FROM_R, FROM_G, FROM_B, TO_X, TO_Y, TO_Z, FROM_M)\ - XTRANSFORM((TO_X), (TO_Y), (TO_Z), (FROM_R), (FROM_G), (FROM_B),\ - (FROM_M)[0][0], (FROM_M)[0][1], (FROM_M)[0][2],\ - (FROM_M)[1][0], (FROM_M)[1][1], (FROM_M)[1][2],\ - (FROM_M)[2][0], (FROM_M)[2][1], (FROM_M)[2][2]) - -#define SRGB_TO_CIEXYZ(FROM_R, FROM_G, FROM_B, TO_X, TO_Y, TO_Z)\ - TRANSFORM((TO_X), (TO_Y), (TO_Z), (FROM_R), (FROM_G), (FROM_B),\ - 0.412457445582367576708548995157, 0.357575865245515878143578447634, 0.180437247826399665973085006954,\ - 0.212673370378408277403536885686, 0.715151730491031756287156895269, 0.072174899130559869164791564344,\ - 0.019333942761673460208893260415, 0.119191955081838593666354597644, 0.950302838552371742508739771438) - -#define CIEXYY_TO_CIEXYZ(FROM_X, FROM_Y, FROM_YY, TO_X, TO_Y, TO_Z)\ - do {\ - TYPE x__ = (FROM_X), y__ = (FROM_Y), Y__ = (FROM_YY);\ - TYPE 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__;\ - }\ - } while (0) - -#define CIELAB_TO_CIEXYZ(FROM_L, FROM_A, FROM_B, TO_X, TO_Y, TO_Z)\ - do {\ - TYPE Y__ = ((FROM_L) + 16) / 116;\ - TYPE X__ = Y__ + (FROM_A) / 500;\ - TYPE Z__ = Y__ - (FROM_B) / 200;\ - (TO_X) = cielab_finv(X__) * D(0.95047);\ - (TO_Y) = cielab_finv(Y__);\ - (TO_Z) = cielab_finv(Z__) * D(1.08883);\ - } while (0) - -#define CIELUV_TO_CIEXYZ(FROM_L, FROM_U, FROM_V, TO_X, TO_Y, TO_Z, FROM_WHITE_X, FROM_WHITE_Y, FROM_WHITE_Z)\ - do {\ - TYPE L__ = (FROM_L), X__ = (FROM_WHITE_X), Y__ = (FROM_WHITE_Y), Z__ = (FROM_WHITE_Z);\ - TYPE L13__ = L__ * 13;\ - TYPE t__ = X__ + 15 * Y__ + 3 * Z__;\ - TYPE u__ = (FROM_U) / L13__ + 4 * X__ / t__;\ - TYPE 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) = D(2.25) * Y__ * u__ / v__;\ - (TO_Y) = Y__;\ - (TO_Z) = Y__ * (3 / v__ - D(0.75) * u__ / v__ - 5);\ - } while (0) - -#define YIQ_TO_CIEXYZ(FROM_Y, FROM_I, FROM_Q, TO_X, TO_Y, TO_Z)\ - TRANSFORM((TO_X), (TO_Y), (TO_Z), (FROM_Y), (FROM_I), (FROM_Q),\ - 0.95047055865428309306963683411595411598682403564453,\ - 0.09738463974178063198294807989441324025392532348633,\ - 0.33223466706854809515903070860076695680618286132812,\ - 0.99999999999999988897769753748434595763683319091797,\ - -0.07112658301916767455974621725545148365199565887451,\ - -0.20786968876398304040264974901219829916954040527344,\ - 1.08882873639588373393394249433185905218124389648438,\ - -1.06592139332461721679123911599162966012954711914062,\ - 1.55474471255181900808395312196807935833930969238281) - -#define YDBDR_TO_CIEXYZ(FROM_Y, FROM_DB, FROM_DR, TO_X, TO_Y, TO_Z)\ - TRANSFORM((TO_X), (TO_Y), (TO_Z), (FROM_Y), (FROM_DB), (FROM_DR),\ - 0.95047055865428309306963683411595411598682403564453,\ - 0.07379612357298576119646327242662664502859115600586,\ - -0.12113653724874726136384595065464964136481285095215,\ - 0.99999999999999988897769753748434595763683319091797,\ - -0.04435684145428285540813106990754022262990474700928,\ - 0.07973534004202506575431641522300196811556816101074,\ - 1.08882873639588373393394249433185905218124389648438,\ - 0.61625657933494271123464613992837257683277130126953,\ - 0.02168821359337728266192257819966471288353204727173) - -#define YUV_TO_CIEXYZ(FROM_Y, FROM_U, FROM_V, TO_X, TO_Y, TO_Z)\ - TRANSFORM((TO_X), (TO_Y), (TO_Z), (FROM_Y), (FROM_U), (FROM_V),\ - 0.95047055865428309306963683411595411598682403564453,\ - 0.22648030324549334180161963558930438011884689331055,\ - 0.26274514929253273143316960158699657768011093139648,\ - 0.99999999999999988897769753748434595763683319091797,\ - -0.13613114642319409930415474718756740912795066833496,\ - -0.17294595255115238763288232348713790997862815856934,\ - 1.08882873639588373393394249433185905218124389648438,\ - 1.89129144197893928058817891724174842238426208496094,\ - -0.04704173528403532422714761196402832865715026855469) - -#define YPBPR_TO_CIEXYZ(FROM_Y, FROM_PB, FROM_PR, TO_X, TO_Y, TO_Z)\ - TRANSFORM((TO_X), (TO_Y), (TO_Z), (FROM_Y), (FROM_PB), (FROM_PR),\ - 0.95047055865428298204733437160030007362365722656250,\ - 0.14433968424876231217979238863335922360420227050781,\ - 0.30616461986760712399302519770571961998939514160156,\ - 0.99999999999999977795539507496869191527366638183594,\ - -0.00002022802471486617736928792510298080742359161377,\ - 0.00008771894888734421691367515450110659003257751465,\ - 1.08882873639588373393394249433185905218124389648438,\ - 0.93827031735982591165168287261622026562690734863281,\ - -0.01609699914324668607035206946420657914131879806519) - -#define YCGCO_TO_CIEXYZ(FROM_Y, FROM_CG, FROM_CO, TO_X, TO_Y, TO_Z)\ - TRANSFORM((TO_X), (TO_Y), (TO_Z), (FROM_Y), (FROM_CG), (FROM_CO),\ - 0.95047055865428309306963683411595411598682403564453,\ - -0.23531882816325136453805555447615915909409523010254,\ - 0.23202019775596791073546398820326430723071098327637,\ - 0.99999999999999988897769753748434595763683319091797,\ - 0.43030346098206362359661625305307097733020782470703,\ - 0.14049847124784842211653312915586866438388824462891,\ - 1.08882873639588373393394249433185905218124389648438,\ - -0.85044482623220662986796014592982828617095947265625,\ - -0.93096889579069830311652822274481877684593200683594) - -#define CIE1960UCS_TO_CIEXYZ(FROM_U, FROM_V, FROM_Y, TO_X, TO_Y, TO_Z)\ - do {\ - TYPE u__ = (FROM_U), v__ = (FROM_V), Y__ = (FROM_Y);\ - (TO_X) = D(1.5) * Y__ * u__ / v__;\ - (TO_Y) = Y__;\ - (TO_Z) = (4 * Y__ - Y__ * u__ - 10 * Y__ * v__) / (2 * v__);\ - } while (0) - -#define CIEXYZ_TO_CIELAB(FROM_X, FROM_Y, FROM_Z, TO_L, TO_A, TO_B)\ - do {\ - TYPE X__ = (FROM_X), Y__ = (FROM_Y), Z__ = (FROM_Z);\ - X__ /= D(0.95047);\ - Z__ /= D(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__));\ - } while (0) - -#define CIEXYZ_TO_CIELUV(FROM_X, FROM_Y, FROM_Z, TO_L, TO_U, TO_V, TO_WHITE_X, TO_WHITE_Y, TO_WHITE_Z)\ - do {\ - TYPE WX__ = (TO_WHITE_X), WY__ = (TO_WHITE_Y), WZ__ = (TO_WHITE_Z);\ - TYPE X__ = (FROM_X), Y__ = (FROM_Y), Z__ = (FROM_Z);\ - TYPE L2__, L__, u__, v__, t__;\ - t__ = WX__ + 15 * WY__ + 3 * WZ__;\ - u__ = 4 * WX__ / t__;\ - v__ = 9 * WY__ / t__;\ - t__ = X__ + 15 * Y__ + 3 * Z__;\ - u__ = 4 * X__ / t__ - u__;\ - v__ = 9 * Y__ / t__ - v__;\ - L__ = Y__ / WY__;\ - L2__ = L__ * 24389;\ - L__ = L2__ <= 216 ? L2__ / 27 : xcbrt(L__) * 116 - 16;\ - (TO_L) = L__;\ - L__ *= 13;\ - (TO_U) = u__ * L__;\ - (TO_V) = v__ * L__;\ - } while (0) - -#define CIELCHUV_TO_CIELUV(FROM_L, FROM_C, FROM_H, TO_L, TO_U, TO_V)\ - do {\ - TYPE C__ = (FROM_C), h__ = (FROM_H);\ - (TO_L) = (FROM_L);\ - (TO_U) = C__ * xcos(h__);\ - (TO_V) = C__ * xsin(h__);\ - } while (0) - -#define CIELUV_TO_CIELCHUV(FROM_L, FROM_U, FROM_V, TO_L, TO_C, TO_H, TO_ONE_REVOLUTION)\ - do {\ - TYPE u__ = (FROM_U), v__ = (FROM_V), rev__ = (TO_ONE_REVOLUTION), h__;\ - (TO_L) = (FROM_L);\ - (TO_C) = xsqrt(u__ * u__ + v__ * v__);\ - h__ = xatan2(v__, u__) / PI2 * rev__;\ - if (!WASDIV0(h__) && (h__ < 0))\ - h__ += rev__;\ - (TO_H) = h__;\ - } while (0) - -#define SRGB_TO_YIQ(FROM_R, FROM_G, FROM_B, TO_Y, TO_I, TO_Q)\ - TRANSFORM((TO_Y), (TO_I), (TO_Q), (FROM_R), (FROM_G), (FROM_B),\ - 0.299, 0.587, 0.114,\ - 0.59571613491277464191853141528554260730743408203125, /* (0.877 cos 33°)(1 - 0.299) - (0.492 sin 33°)(-0.299) */\ - -0.27445283783925644716106262421817518770694732666016, /* (0.877 cos 33°)(-0.587) - (0.492 sin 33°)(-0.587) */\ - -0.32126329707351808373516632855171337723731994628906, /* (0.877 cos 33°)(-0.114) - (0.492 sin 33°)(1 - 0.114) */\ - 0.21145640212011795888713550084503367543220520019531, /* (0.877 sin 33°)(1 - 0.299) + (0.492 cos 33°)(-0.299) */\ - -0.52259104529161115593183239980135113000869750976562, /* (0.877 sin 33°)(-0.587) + (0.492 cos 33°)(-0.587) */\ - 0.31113464317149330806699936147197149693965911865234) /* (0.877 sin 33°)(-0.114) + (0.492 cos 33°)(1 - 0.114) */ - -#define CIEXYZ_TO_YIQ(FROM_X, FROM_Y, FROM_Z, TO_Y, TO_I, TO_Q)\ - TRANSFORM((TO_Y), (TO_I), (TO_Q), (FROM_X), (FROM_Y), (FROM_Z),\ - 0.40627729168038273499519164033699780702590942382812,\ - 0.61835674212166968910509012857801280915737152099609,\ - -0.00414330221353725880462093300593551248311996459961,\ - 2.17852787350219845308174626552499830722808837890625,\ - -1.36502666214454104753883711964590474963188171386719,\ - -0.64803574634025240541745915834326297044754028320312,\ - 1.20905577682138853923277110880007967352867126464844,\ - -1.36890364998339797431015085749095305800437927246094,\ - 0.20180559439597040016778350945969577878713607788086) - -#define SRGB_TO_YDBDR(FROM_R, FROM_G, FROM_B, TO_Y, TO_DB, TO_DR)\ - TRANSFORM((TO_Y), (TO_DB), (TO_DR), (FROM_R), (FROM_G), (FROM_B),\ - 0.299, 0.587, 0.114,\ - -0.450, -0.883, 1.333,\ - -1.333, 1.116, 0.217) - -#define YUV_TO_YDBDR(FROM_Y, FROM_U, FROM_V, TO_Y, TO_DB, TO_DR)\ - do {\ - TYPE U__ = (FROM_U), V__ = (FROM_V);\ - (TO_Y) = (FROM_Y);\ - (TO_DB) = U__ * D(3.069);\ - (TO_DR) = V__ * D(-2.169);\ - } while (0) - -#define CIEXYZ_TO_YDBDR(FROM_X, FROM_Y, FROM_Z, TO_Y, TO_DB, TO_DR)\ - TRANSFORM((TO_Y), (TO_DB), (TO_DR), (FROM_X), (FROM_Y), (FROM_Z),\ - 0.40627729168038273499519164033699780702590942382812,\ - 0.61835674212166968910509012857801280915737152099609,\ - -0.00414330221353725880462093300593551248311996459961,\ - -0.52816561102614745237815441214479506015777587890625,\ - -1.23677481526212962315014465275453403592109680175781,\ - 1.59692761635924940222253098909277468919754028320312,\ - -5.38914174974103143966885909321717917919158935546875,\ - 4.09835630362728497999569299281574785709381103515625,\ - 0.94033545560642795013706063400604762136936187744141) - -#define YDBDR_TO_YUV(FROM_Y, FROM_DB, FROM_DR, TO_Y, TO_U, TO_V)\ - do {\ - TYPE DB__ = (FROM_DB), DR__ = (FROM_DR);\ - (TO_Y) = (FROM_Y);\ - (TO_U) = DB__ / D(3.069);\ - (TO_V) = DR__ / D(-2.169);\ - } while (0) - -#define SRGB_TO_YUV(FROM_R, FROM_G, FROM_B, TO_Y, TO_U, TO_V)\ - TRANSFORM((TO_Y), (TO_U), (TO_V), (FROM_R), (FROM_G), (FROM_B),\ - 0.29899999999999998800959133404830936342477798461914,\ - 0.58699999999999996624922005139524117112159729003906,\ - 0.11400000000000000410782519111307919956743717193604,\ - -0.14662756598240470062854967636667424812912940979004,\ - -0.28771586836102963635752871596196200698614120483398,\ - 0.43434343434343436474165400795754976570606231689453,\ - 0.61456892577224520035628074765554629266262054443359,\ - -0.51452282157676354490405401520547457039356231689453,\ - -0.10004610419548178035231700278018251992762088775635) - -#define CIEXYZ_TO_YUV(FROM_X, FROM_Y, FROM_Z, TO_Y, TO_U, TO_V)\ - TRANSFORM((TO_Y), (TO_U), (TO_V), (FROM_X), (FROM_Y), (FROM_Z),\ - 0.40627729168038273499519164033699780702590942382812,\ - 0.61835674212166968910509012857801280915737152099609,\ - -0.00414330221353725880462093300593551248311996459961,\ - -0.17209697328971895746718701047939248383045196533203,\ - -0.40298951295605395239718404809536878019571304321289,\ - 0.52034135430408912093014350830344483256340026855469,\ - 2.48462044709130047692724474472925066947937011718750,\ - -1.88951420176453876997868519538315013051033020019531,\ - -0.43353409663735725798616726933687459677457809448242) - -#define SRGB_TO_YPBPR(FROM_R, FROM_G, FROM_B, TO_Y, TO_PB, TO_PR)\ - do {\ - TYPE R__ = (FROM_R), G__ = (FROM_G), B__ = (FROM_B);\ - (TO_Y) = R__ * D(0.2126) +\ - G__ * D(0.7152) +\ - B__ * D(0.0722);\ - (TO_PB) = B__ - to->Y;\ - (TO_PR) = R__ - to->Y;\ - } while (0) - -#define CIEXYZ_TO_YPBPR(FROM_X, FROM_Y, FROM_Z, TO_Y, TO_PB, TO_PR)\ - TRANSFORM((TO_Y), (TO_PB), (TO_PR), (FROM_X), (FROM_Y), (FROM_Z),\ - -0.00028314209073960778378920011277841695118695497513,\ - 1.00019821310075673892470149439759552478790283203125,\ - 0.00006512054470741990286342115723527967929840087891,\ - 0.05592664565509243568275365987574332393705844879150,\ - -1.20422439283671711685030913940863683819770812988281,\ - 1.05716144717799576113748116767965257167816162109375,\ - 3.24072939673847715269516811531502753496170043945312,\ - -2.53733297492083753610359053709544241428375244140625,\ - -0.49859531356743613805804216099204495549201965332031) - -#define SRGB_TO_YCGCO(FROM_R, FROM_G, FROM_B, TO_Y, TO_CG, TO_CO)\ - TRANSFORM((TO_Y), (TO_CG), (TO_CO), (FROM_R), (FROM_G), (FROM_B),\ - 0.25, 0.50, 0.25,\ - -0.25, 0.50, -0.25,\ - 0.50, 0., -0.50) - -#define CIEXYZ_TO_YCGCO(FROM_X, FROM_Y, FROM_Z, TO_Y, TO_CG, TO_CO)\ - TRANSFORM((TO_Y), (TO_CG), (TO_CO), (FROM_X), (FROM_Y), (FROM_Z),\ - 0.33938913643068269188063368346774950623512268066406,\ - 0.50271574450517486631895280879689380526542663574219,\ - 0.16045211478220866574417868832824751734733581542969,\ - -1.30865574267536244335019546269904822111129760742188,\ - 1.37329621528319534284889869013568386435508728027344,\ - -0.11889607256777862120955546743061859160661697387695,\ - 1.59240137554169236544510113162687048316001892089844,\ - -0.66655429104206020962664069884340278804302215576172,\ - -0.77787838037271606062006412685150280594825744628906) - -#define CIEUVW_TO_CIE1960UCS(FROM_U, FROM_V, FROM_W, TO_U, TO_V, TO_Y, FROM_U0, FROM_V0)\ - do {\ - TYPE U__ = (FROM_U), V__ = (FROM_V), W__ = (FROM_W), Y__;\ - Y__ = (W__ + 17) / 25;\ - Y__ *= Y__ * Y__;\ - W__ *= 13;\ - (TO_U) = U__ / W__ + (FROM_U0);\ - (TO_V) = V__ / W__ + (FROM_V0);\ - (TO_Y) = Y__;\ - } while (0) - -#define CIEXYZ_TO_CIE1960UCS(FROM_X, FROM_Y, FROM_Z, TO_U, TO_V, TO_Y)\ - do {\ - TYPE X__ = (FROM_X), Y__ = (FROM_Y), w__;\ - w__ = X__ + 15 * Y__ + 3 * (FROM_Z);\ - (TO_U) = 4 * X__ / w__;\ - (TO_V) = 6 * Y__ / w__;\ - (TO_Y) = Y__;\ - } while (0) - -#define CIEUVW_TO_CIEUVW(FROM_U, FROM_V, FROM_W, TO_U, TO_V, TO_W, FROM_U0, FROM_V0, TO_U0, TO_V0)\ - do {\ - TYPE U__ = (FROM_U), V__ = (FROM_V), W__ = (FROM_W);\ - TYPE w__ = W__ * 13;\ - U__ += w__ * ((FROM_U0) - (TO_U0));\ - V__ += w__ * ((FROM_V0) - (TO_V0));\ - (TO_U) = U__;\ - (TO_V) = V__;\ - (TO_W) = W__;\ - } while (0) - -#define CIE1960UCS_TO_CIEUVW(FROM_U, FROM_V, FROM_Y, TO_U, TO_V, TO_W, TO_U0, TO_V0)\ - do {\ - TYPE U__ = (FROM_U), V__ = (FROM_V), u0__ = (TO_U0), v0__ = (TO_V0);\ - TYPE Y__ = 25 * xcbrt((FROM_Y)) - 17;\ - TYPE w__ = Y__ * 13;\ - (to->U) = w__ * (U__ - u0__);\ - (to->V) = w__ * (V__ - v0__);\ - (to->W) = Y__;\ - } while (0) - - - static inline TYPE srgb_encode(TYPE t) { diff --git a/conversions.h b/conversions.h new file mode 100644 index 0000000..99261e9 --- /dev/null +++ b/conversions.h @@ -0,0 +1,382 @@ +/* See LICENSE file for copyright and license details. */ + +#define MATRIX(M11, M12, M13, M21, M22, M23, M31, M32, M33)\ + D(M11), D(M12), D(M13),\ + D(M21), D(M22), D(M23),\ + D(M31), D(M32), D(M33) + + + +#define CIEXYZ_TO_RGB(TO_MINV)\ + (TO_MINV)[0][0], (TO_MINV)[0][1], (TO_MINV)[0][2],\ + (TO_MINV)[1][0], (TO_MINV)[1][1], (TO_MINV)[1][2],\ + (TO_MINV)[2][0], (TO_MINV)[2][1], (TO_MINV)[2][2] + +#define CIEXYZ_TO_SRGB\ + MATRIX( 3.240446254647737500675930277794, -1.537134761820080575134284117667, -0.498530193022728718155178739835,\ + -0.969266606244679751469561779231, 1.876011959788370209167851498933, 0.041556042214430065351304932619,\ + 0.055643503564352832235773149705, -0.204026179735960239147729566866, 1.057226567722703292062647051353) + +#define YIQ_TO_SRGB\ + MATRIX(1., 0.95629483232089407263032398986979387700557708740234, 0.62102512544472865396727456754888407886028289794922,\ + 1., -0.27212147408397735492968649850809015333652496337891, -0.64738095351761570928061928498209454119205474853516,\ + 1., -1.10698990856712820018969978264067322015762329101562, 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 ⎠ + */ + +#define YDBDR_TO_SRGB\ + MATRIX(1., 0.000092303716148, -0.525912630661865,\ + 1., -0.129132898890509, 0.267899328207599,\ + 1., 0.664679059978955, -0.000079202543533) + +#define YPBPR_TO_SRGB(FROM_Y, FROM_PB, FROM_PR, TO_R, TO_G, TO_B)\ + do {\ + TYPE y__ = (FROM_Y);\ + TYPE r__ = (FROM_PR) + y__;\ + TYPE b__ = (FROM_PB) + y__;\ + (TO_R) = r__;\ + (TO_B) = b__;\ + (TO_G) = (y__ - r__ * D(0.2126) - b__ * D(0.0722)) / D(0.7152);\ + } while (0) + +#define YUV_TO_SRGB\ + MATRIX(1., 0.00028328010485821202317155420580263580632163211703, 1.14070449590558520291949662350816652178764343261719,\ + 1., -0.39630886669497211727275498560629785060882568359375, -0.58107364288228224857846271333983168005943298339844,\ + 1., 2.03990003507541306504435851820744574069976806640625, 0.00017179031692307700847528739718228507626918144524) + +#define YCGCO_TO_SRGB\ + MATRIX(1., -1., 1.,\ + 1., 1., 0.,\ + 1., -1., -1.) + +#define CIEXYZ_TO_CIEXYY(FROM_X, FROM_Y, FROM_Z, TO_X, TO_Y, TO_YY)\ + do {\ + TYPE x__ = (FROM_X), y__ = (FROM_Y), z__ = (FROM_Z);\ + TYPE s__ = x__ + y__ + z__;\ + x__ = x__ / s__;\ + s__ = y__ / s__;\ + if (WASDIV0(x__) || WASDIV0(s__))\ + x__ = s__ = 0;\ + (TO_X) = x__;\ + (TO_Y) = s__;\ + (TO_YY) = y__;\ + } while (0) + +#define RGB_TO_CIEXYZ(FROM_M)\ + (FROM_M)[0][0], (FROM_M)[0][1], (FROM_M)[0][2],\ + (FROM_M)[1][0], (FROM_M)[1][1], (FROM_M)[1][2],\ + (FROM_M)[2][0], (FROM_M)[2][1], (FROM_M)[2][2] + +#define SRGB_TO_CIEXYZ\ + MATRIX(0.412457445582367576708548995157, 0.357575865245515878143578447634, 0.180437247826399665973085006954,\ + 0.212673370378408277403536885686, 0.715151730491031756287156895269, 0.072174899130559869164791564344,\ + 0.019333942761673460208893260415, 0.119191955081838593666354597644, 0.950302838552371742508739771438) + +#define CIEXYY_TO_CIEXYZ(FROM_X, FROM_Y, FROM_YY, TO_X, TO_Y, TO_Z)\ + do {\ + TYPE x__ = (FROM_X), y__ = (FROM_Y), Y__ = (FROM_YY);\ + TYPE 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__;\ + }\ + } while (0) + +#define CIELAB_TO_CIEXYZ(FROM_L, FROM_A, FROM_B, TO_X, TO_Y, TO_Z)\ + do {\ + TYPE Y__ = ((FROM_L) + 16) / 116;\ + TYPE X__ = Y__ + (FROM_A) / 500;\ + TYPE Z__ = Y__ - (FROM_B) / 200;\ + (TO_X) = cielab_finv(X__) * D(0.95047);\ + (TO_Y) = cielab_finv(Y__);\ + (TO_Z) = cielab_finv(Z__) * D(1.08883);\ + } while (0) + +#define CIELUV_TO_CIEXYZ(FROM_L, FROM_U, FROM_V, TO_X, TO_Y, TO_Z, FROM_WHITE_X, FROM_WHITE_Y, FROM_WHITE_Z)\ + do {\ + TYPE L__ = (FROM_L), X__ = (FROM_WHITE_X), Y__ = (FROM_WHITE_Y), Z__ = (FROM_WHITE_Z);\ + TYPE L13__ = L__ * 13;\ + TYPE t__ = X__ + 15 * Y__ + 3 * Z__;\ + TYPE u__ = (FROM_U) / L13__ + 4 * X__ / t__;\ + TYPE 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) = D(2.25) * Y__ * u__ / v__;\ + (TO_Y) = Y__;\ + (TO_Z) = Y__ * (3 / v__ - D(0.75) * u__ / v__ - 5);\ + } while (0) + +#define YIQ_TO_CIEXYZ\ + MATRIX( 0.95047055865428309306963683411595411598682403564453,\ + 0.09738463974178063198294807989441324025392532348633,\ + 0.33223466706854809515903070860076695680618286132812,\ + 0.99999999999999988897769753748434595763683319091797,\ + -0.07112658301916767455974621725545148365199565887451,\ + -0.20786968876398304040264974901219829916954040527344,\ + 1.08882873639588373393394249433185905218124389648438,\ + -1.06592139332461721679123911599162966012954711914062,\ + 1.55474471255181900808395312196807935833930969238281) + +#define YDBDR_TO_CIEXYZ\ + MATRIX( 0.95047055865428309306963683411595411598682403564453,\ + 0.07379612357298576119646327242662664502859115600586,\ + -0.12113653724874726136384595065464964136481285095215,\ + 0.99999999999999988897769753748434595763683319091797,\ + -0.04435684145428285540813106990754022262990474700928,\ + 0.07973534004202506575431641522300196811556816101074,\ + 1.08882873639588373393394249433185905218124389648438,\ + 0.61625657933494271123464613992837257683277130126953,\ + 0.02168821359337728266192257819966471288353204727173) + +#define YUV_TO_CIEXYZ\ + MATRIX( 0.95047055865428309306963683411595411598682403564453,\ + 0.22648030324549334180161963558930438011884689331055,\ + 0.26274514929253273143316960158699657768011093139648,\ + 0.99999999999999988897769753748434595763683319091797,\ + -0.13613114642319409930415474718756740912795066833496,\ + -0.17294595255115238763288232348713790997862815856934,\ + 1.08882873639588373393394249433185905218124389648438,\ + 1.89129144197893928058817891724174842238426208496094,\ + -0.04704173528403532422714761196402832865715026855469) + +#define YPBPR_TO_CIEXYZ\ + MATRIX( 0.95047055865428298204733437160030007362365722656250,\ + 0.14433968424876231217979238863335922360420227050781,\ + 0.30616461986760712399302519770571961998939514160156,\ + 0.99999999999999977795539507496869191527366638183594,\ + -0.00002022802471486617736928792510298080742359161377,\ + 0.00008771894888734421691367515450110659003257751465,\ + 1.08882873639588373393394249433185905218124389648438,\ + 0.93827031735982591165168287261622026562690734863281,\ + -0.01609699914324668607035206946420657914131879806519) + +#define YCGCO_TO_CIEXYZ\ + MATRIX( 0.95047055865428309306963683411595411598682403564453,\ + -0.23531882816325136453805555447615915909409523010254,\ + 0.23202019775596791073546398820326430723071098327637,\ + 0.99999999999999988897769753748434595763683319091797,\ + 0.43030346098206362359661625305307097733020782470703,\ + 0.14049847124784842211653312915586866438388824462891,\ + 1.08882873639588373393394249433185905218124389648438,\ + -0.85044482623220662986796014592982828617095947265625,\ + -0.93096889579069830311652822274481877684593200683594) + +#define CIE1960UCS_TO_CIEXYZ(FROM_U, FROM_V, FROM_Y, TO_X, TO_Y, TO_Z)\ + do {\ + TYPE u__ = (FROM_U), v__ = (FROM_V), Y__ = (FROM_Y);\ + (TO_X) = D(1.5) * Y__ * u__ / v__;\ + (TO_Y) = Y__;\ + (TO_Z) = (4 * Y__ - Y__ * u__ - 10 * Y__ * v__) / (2 * v__);\ + } while (0) + +#define CIEXYZ_TO_CIELAB(FROM_X, FROM_Y, FROM_Z, TO_L, TO_A, TO_B)\ + do {\ + TYPE X__ = (FROM_X), Y__ = (FROM_Y), Z__ = (FROM_Z);\ + X__ /= D(0.95047);\ + Z__ /= D(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__));\ + } while (0) + +#define CIEXYZ_TO_CIELUV(FROM_X, FROM_Y, FROM_Z, TO_L, TO_U, TO_V, TO_WHITE_X, TO_WHITE_Y, TO_WHITE_Z)\ + do {\ + TYPE WX__ = (TO_WHITE_X), WY__ = (TO_WHITE_Y), WZ__ = (TO_WHITE_Z);\ + TYPE X__ = (FROM_X), Y__ = (FROM_Y), Z__ = (FROM_Z);\ + TYPE L2__, L__, u__, v__, t__;\ + t__ = WX__ + 15 * WY__ + 3 * WZ__;\ + u__ = 4 * WX__ / t__;\ + v__ = 9 * WY__ / t__;\ + t__ = X__ + 15 * Y__ + 3 * Z__;\ + u__ = 4 * X__ / t__ - u__;\ + v__ = 9 * Y__ / t__ - v__;\ + L__ = Y__ / WY__;\ + L2__ = L__ * 24389;\ + L__ = L2__ <= 216 ? L2__ / 27 : xcbrt(L__) * 116 - 16;\ + (TO_L) = L__;\ + L__ *= 13;\ + (TO_U) = u__ * L__;\ + (TO_V) = v__ * L__;\ + } while (0) + +#define CIELCHUV_TO_CIELUV(FROM_L, FROM_C, FROM_H, TO_L, TO_U, TO_V)\ + do {\ + TYPE C__ = (FROM_C), h__ = (FROM_H);\ + (TO_L) = (FROM_L);\ + (TO_U) = C__ * xcos(h__);\ + (TO_V) = C__ * xsin(h__);\ + } while (0) + +#define CIELUV_TO_CIELCHUV(FROM_L, FROM_U, FROM_V, TO_L, TO_C, TO_H, TO_ONE_REVOLUTION)\ + do {\ + TYPE u__ = (FROM_U), v__ = (FROM_V), rev__ = (TO_ONE_REVOLUTION), h__;\ + (TO_L) = (FROM_L);\ + (TO_C) = xsqrt(u__ * u__ + v__ * v__);\ + h__ = xatan2(v__, u__) / PI2 * rev__;\ + if (!WASDIV0(h__) && (h__ < 0))\ + h__ += rev__;\ + (TO_H) = h__;\ + } while (0) + +#define SRGB_TO_YIQ\ + MATRIX( 0.299, 0.587, 0.114,\ + 0.59571613491277464191853141528554260730743408203125, /* (0.877 cos 33°)(1 - 0.299) - (0.492 sin 33°)(-0.299) */\ + -0.27445283783925644716106262421817518770694732666016, /* (0.877 cos 33°)(-0.587) - (0.492 sin 33°)(-0.587) */\ + -0.32126329707351808373516632855171337723731994628906, /* (0.877 cos 33°)(-0.114) - (0.492 sin 33°)(1 - 0.114) */\ + 0.21145640212011795888713550084503367543220520019531, /* (0.877 sin 33°)(1 - 0.299) + (0.492 cos 33°)(-0.299) */\ + -0.52259104529161115593183239980135113000869750976562, /* (0.877 sin 33°)(-0.587) + (0.492 cos 33°)(-0.587) */\ + 0.31113464317149330806699936147197149693965911865234) /* (0.877 sin 33°)(-0.114) + (0.492 cos 33°)(1 - 0.114) */ + +#define CIEXYZ_TO_YIQ\ + MATRIX( 0.40627729168038273499519164033699780702590942382812,\ + 0.61835674212166968910509012857801280915737152099609,\ + -0.00414330221353725880462093300593551248311996459961,\ + 2.17852787350219845308174626552499830722808837890625,\ + -1.36502666214454104753883711964590474963188171386719,\ + -0.64803574634025240541745915834326297044754028320312,\ + 1.20905577682138853923277110880007967352867126464844,\ + -1.36890364998339797431015085749095305800437927246094,\ + 0.20180559439597040016778350945969577878713607788086) + +#define SRGB_TO_YDBDR\ + MATRIX( 0.299, 0.587, 0.114,\ + -0.450, -0.883, 1.333,\ + -1.333, 1.116, 0.217) + +#define YUV_TO_YDBDR(FROM_Y, FROM_U, FROM_V, TO_Y, TO_DB, TO_DR)\ + do {\ + TYPE U__ = (FROM_U), V__ = (FROM_V);\ + (TO_Y) = (FROM_Y);\ + (TO_DB) = U__ * D(3.069);\ + (TO_DR) = V__ * D(-2.169);\ + } while (0) + +#define CIEXYZ_TO_YDBDR\ + MATRIX( 0.40627729168038273499519164033699780702590942382812,\ + 0.61835674212166968910509012857801280915737152099609,\ + -0.00414330221353725880462093300593551248311996459961,\ + -0.52816561102614745237815441214479506015777587890625,\ + -1.23677481526212962315014465275453403592109680175781,\ + 1.59692761635924940222253098909277468919754028320312,\ + -5.38914174974103143966885909321717917919158935546875,\ + 4.09835630362728497999569299281574785709381103515625,\ + 0.94033545560642795013706063400604762136936187744141) + +#define YDBDR_TO_YUV(FROM_Y, FROM_DB, FROM_DR, TO_Y, TO_U, TO_V)\ + do {\ + TYPE DB__ = (FROM_DB), DR__ = (FROM_DR);\ + (TO_Y) = (FROM_Y);\ + (TO_U) = DB__ / D(3.069);\ + (TO_V) = DR__ / D(-2.169);\ + } while (0) + +#define SRGB_TO_YUV\ + MATRIX( 0.29899999999999998800959133404830936342477798461914,\ + 0.58699999999999996624922005139524117112159729003906,\ + 0.11400000000000000410782519111307919956743717193604,\ + -0.14662756598240470062854967636667424812912940979004,\ + -0.28771586836102963635752871596196200698614120483398,\ + 0.43434343434343436474165400795754976570606231689453,\ + 0.61456892577224520035628074765554629266262054443359,\ + -0.51452282157676354490405401520547457039356231689453,\ + -0.10004610419548178035231700278018251992762088775635) + +#define CIEXYZ_TO_YUV\ + MATRIX( 0.40627729168038273499519164033699780702590942382812,\ + 0.61835674212166968910509012857801280915737152099609,\ + -0.00414330221353725880462093300593551248311996459961,\ + -0.17209697328971895746718701047939248383045196533203,\ + -0.40298951295605395239718404809536878019571304321289,\ + 0.52034135430408912093014350830344483256340026855469,\ + 2.48462044709130047692724474472925066947937011718750,\ + -1.88951420176453876997868519538315013051033020019531,\ + -0.43353409663735725798616726933687459677457809448242) + +#define SRGB_TO_YPBPR(FROM_R, FROM_G, FROM_B, TO_Y, TO_PB, TO_PR)\ + do {\ + TYPE R__ = (FROM_R), G__ = (FROM_G), B__ = (FROM_B);\ + TYPE Y__ = R__ * D(0.2126) +\ + G__ * D(0.7152) +\ + B__ * D(0.0722);\ + (TO_Y) = Y__;\ + (TO_PB) = B__ - Y__;\ + (TO_PR) = R__ - Y__;\ + } while (0) + +#define CIEXYZ_TO_YPBPR\ + MATRIX(-0.00028314209073960778378920011277841695118695497513,\ + 1.00019821310075673892470149439759552478790283203125,\ + 0.00006512054470741990286342115723527967929840087891,\ + 0.05592664565509243568275365987574332393705844879150,\ + -1.20422439283671711685030913940863683819770812988281,\ + 1.05716144717799576113748116767965257167816162109375,\ + 3.24072939673847715269516811531502753496170043945312,\ + -2.53733297492083753610359053709544241428375244140625,\ + -0.49859531356743613805804216099204495549201965332031) + +#define SRGB_TO_YCGCO\ + MATRIX( 0.25, 0.50, 0.25,\ + -0.25, 0.50, -0.25,\ + 0.50, 0., -0.50) + +#define CIEXYZ_TO_YCGCO\ + MATRIX( 0.33938913643068269188063368346774950623512268066406,\ + 0.50271574450517486631895280879689380526542663574219,\ + 0.16045211478220866574417868832824751734733581542969,\ + -1.30865574267536244335019546269904822111129760742188,\ + 1.37329621528319534284889869013568386435508728027344,\ + -0.11889607256777862120955546743061859160661697387695,\ + 1.59240137554169236544510113162687048316001892089844,\ + -0.66655429104206020962664069884340278804302215576172,\ + -0.77787838037271606062006412685150280594825744628906) + +#define CIEUVW_TO_CIE1960UCS(FROM_U, FROM_V, FROM_W, TO_U, TO_V, TO_Y, FROM_U0, FROM_V0)\ + do {\ + TYPE U__ = (FROM_U), V__ = (FROM_V), W__ = (FROM_W), Y__;\ + Y__ = (W__ + 17) / 25;\ + Y__ *= Y__ * Y__;\ + W__ *= 13;\ + (TO_U) = U__ / W__ + (FROM_U0);\ + (TO_V) = V__ / W__ + (FROM_V0);\ + (TO_Y) = Y__;\ + } while (0) + +#define CIEXYZ_TO_CIE1960UCS(FROM_X, FROM_Y, FROM_Z, TO_U, TO_V, TO_Y)\ + do {\ + TYPE X__ = (FROM_X), Y__ = (FROM_Y), w__;\ + w__ = X__ + 15 * Y__ + 3 * (FROM_Z);\ + (TO_U) = 4 * X__ / w__;\ + (TO_V) = 6 * Y__ / w__;\ + (TO_Y) = Y__;\ + } while (0) + +#define CIEUVW_TO_CIEUVW(FROM_U, FROM_V, FROM_W, TO_U, TO_V, TO_W, FROM_U0, FROM_V0, TO_U0, TO_V0)\ + do {\ + TYPE U__ = (FROM_U), V__ = (FROM_V), W__ = (FROM_W);\ + TYPE w__ = W__ * 13;\ + U__ += w__ * ((FROM_U0) - (TO_U0));\ + V__ += w__ * ((FROM_V0) - (TO_V0));\ + (TO_U) = U__;\ + (TO_V) = V__;\ + (TO_W) = W__;\ + } while (0) + +#define CIE1960UCS_TO_CIEUVW(FROM_U, FROM_V, FROM_Y, TO_U, TO_V, TO_W, TO_U0, TO_V0)\ + do {\ + TYPE U__ = (FROM_U), V__ = (FROM_V), u0__ = (TO_U0), v0__ = (TO_V0);\ + TYPE Y__ = 25 * xcbrt((FROM_Y)) - 17;\ + TYPE w__ = Y__ * 13;\ + (TO_U) = w__ * (U__ - u0__);\ + (TO_V) = w__ * (V__ - v0__);\ + (TO_W) = Y__;\ + } while (0) diff --git a/convert-template.c b/convert-template.c deleted file mode 100644 index ee6066d..0000000 --- a/convert-template.c +++ /dev/null @@ -1,633 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -#define X(C, T, N) static void to_##N(const libcolour_colour_t *restrict from, T *restrict to); -LIST_MODELS(X) -#undef X - - -#define CONV_0(MACRO, FROM, TO)\ - MACRO(((const libcolour_rgb_t *)(FROM))->R,\ - ((const libcolour_rgb_t *)(FROM))->G,\ - ((const libcolour_rgb_t *)(FROM))->B,\ - ((libcolour_rgb_t *)(TO))->R,\ - ((libcolour_rgb_t *)(TO))->G,\ - ((libcolour_rgb_t *)(TO))->B) - -#define CONV_N(MACRO, FROM, TO, ...)\ - MACRO(((const libcolour_rgb_t *)(FROM))->R,\ - ((const libcolour_rgb_t *)(FROM))->G,\ - ((const libcolour_rgb_t *)(FROM))->B,\ - ((libcolour_rgb_t *)(TO))->R,\ - ((libcolour_rgb_t *)(TO))->G,\ - ((libcolour_rgb_t *)(TO))->B,\ - __VA_ARGS__) - - -static void -rgb_encode(libcolour_rgb_t *restrict colour, const libcolour_rgb_t *restrict space) -{ - TYPE 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 = xpow(colour->R, 1 / space->GAMMA); - colour->G = xpow(colour->G, 1 / space->GAMMA); - colour->B = xpow(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) -{ - TYPE 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 = xpow(colour->R, space->GAMMA); - colour->G = xpow(colour->G, space->GAMMA); - colour->B = xpow(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(); - } -} - -static int -rgb_same_transfer(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_transfer = 0, with_transfer = to->with_transfer; - libcolour_ciexyz_t tmp; - switch (from->model) { - case LIBCOLOUR_RGB: - if (!memcmp(from->rgb.M, to->M, sizeof(TYPE[3][3]))) { - have_transfer = from->rgb.with_transfer; - to->R = from->rgb.R; - to->G = from->rgb.G; - to->B = from->rgb.B; - if (have_transfer && with_transfer && !rgb_same_transfer(&from->rgb, to)) - rgb_decode(to, &from->rgb), have_transfer = 0; - break; - } - /* fall through */ - default: - tmp.model = LIBCOLOUR_CIEXYZ; - to_ciexyz(from, &tmp); - from = (const void *)&tmp; - /* fall through */ - case LIBCOLOUR_CIEXYZ: - CONV_N(CIEXYZ_TO_RGB, from, to, to->Minv); - break; - } - - if (have_transfer != with_transfer) { - if (with_transfer) - rgb_encode(to, to); - else - rgb_decode(to, &from->rgb); - } -} - - -static void -to_srgb(const libcolour_colour_t *restrict from, libcolour_srgb_t *restrict to) -{ - libcolour_srgb_t tmp_srgb; - libcolour_ciexyz_t tmp_ciexyz; - switch (from->model) { - default: - tmp_ciexyz.model = LIBCOLOUR_CIEXYZ; - to_ciexyz(from, &tmp_ciexyz); - from = (const void *)&tmp_ciexyz; - /* fall through */ - case LIBCOLOUR_CIEXYZ: - CONV_0(CIEXYZ_TO_SRGB, from, to); - break; - case LIBCOLOUR_SRGB: - srgb_to_srgb: - if (from->srgb.with_transfer == to->with_transfer) { - *to = from->srgb; - } else if (to->with_transfer) { - to->R = srgb_encode(from->srgb.R); - to->G = srgb_encode(from->srgb.G); - to->B = srgb_encode(from->srgb.B); - } else { - to->R = srgb_decode(from->srgb.R); - to->G = srgb_decode(from->srgb.G); - to->B = srgb_decode(from->srgb.B); - } - return; - case LIBCOLOUR_YIQ: - CONV_0(YIQ_TO_SRGB, from, to); - break; - case LIBCOLOUR_YDBDR: - CONV_0(YDBDR_TO_SRGB, from, to); - break; - case LIBCOLOUR_YPBPR: - CONV_0(YPBPR_TO_SRGB, from, to); - break; - case LIBCOLOUR_YUV: - CONV_0(YUV_TO_SRGB, from, to); - break; - case LIBCOLOUR_YCGCO: - CONV_0(YCGCO_TO_SRGB, from, to); - break; - } - if (to->with_transfer) { - tmp_srgb = *to; - tmp_srgb.with_transfer = 0; - from = (const void *)&tmp_srgb; - goto srgb_to_srgb; - } -} - - -static void -to_ciexyy(const libcolour_colour_t *restrict from, libcolour_ciexyy_t *restrict to) -{ - libcolour_srgb_t tmp1; - libcolour_ciexyz_t tmp2; - switch (from->model) { - case LIBCOLOUR_CIEXYY: - *to = from->ciexyy; - break; - case LIBCOLOUR_SRGB: - tmp1.model = LIBCOLOUR_SRGB; - if (from->srgb.with_transfer) { - tmp1.with_transfer = 0; - to_srgb((const libcolour_colour_t *)from, &tmp1); - } else { - tmp1 = from->srgb; - } - if (tmp1.R == 0 && tmp1.G == 0 && tmp1.B == 0) { - to->x = D(0.31272660439158); - to->y = D(0.32902315240275); - to->Y = 0; - break; - } else { - from = (const void *)&tmp1; - } - /* fall through */ - default: - tmp2.model = LIBCOLOUR_CIEXYZ; - to_ciexyz(from, &tmp2); - from = (const void *)&tmp2; - /* fall through */ - case LIBCOLOUR_CIEXYZ: - CONV_0(CIEXYZ_TO_CIEXYY, from, to); - break; - } -} - - -static void -to_ciexyz(const libcolour_colour_t *restrict from, libcolour_ciexyz_t *restrict to) -{ - libcolour_colour_t tmp; - libcolour_srgb_t tmp_srgb; - TYPE R, G, B; - switch (from->model) { - case LIBCOLOUR_RGB: - if (from->rgb.with_transfer) { - tmp.rgb = from->rgb; - tmp.rgb.with_transfer = 0; - to_rgb(from, &tmp.rgb); - R = tmp.rgb.R, G = tmp.rgb.G, B = tmp.rgb.B; - } else { - R = from->rgb.R, G = from->rgb.G, B = from->rgb.B; - } - RGB_TO_CIEXYZ(R, G, B, to->X, to->Y, to->Z, from->rgb.M); - break; - default: - tmp.srgb.model = LIBCOLOUR_SRGB; - tmp.srgb.with_transfer = 0; - to_srgb(from, &tmp.srgb); - from = (const void *)&tmp.srgb; - /* fall through */ - case LIBCOLOUR_SRGB: - if (from->srgb.with_transfer) { - tmp_srgb.model = LIBCOLOUR_SRGB; - tmp_srgb.with_transfer = 0; - to_srgb(from, &tmp_srgb); - R = tmp_srgb.R, G = tmp_srgb.G, B = tmp_srgb.B; - } else { - R = from->srgb.R, G = from->srgb.G, B = from->srgb.B; - } - SRGB_TO_CIEXYZ(R, G, B, to->X, to->Y, to->Z); - break; - case LIBCOLOUR_CIEXYY: - CONV_0(CIEXYY_TO_CIEXYZ, from, to); - break; - case LIBCOLOUR_CIEXYZ: - *to = from->ciexyz; - break; - case LIBCOLOUR_CIELAB: - CONV_0(CIELAB_TO_CIEXYZ, from, to); - break; - case LIBCOLOUR_CIELCHUV: - tmp.cieluv.model = LIBCOLOUR_CIELUV; - tmp.cieluv.white = from->cielchuv.white; - to_cieluv(from, &tmp.cieluv); - from = (const void *)&tmp.cieluv; - /* fall through */ - case LIBCOLOUR_CIELUV: - CONV_N(CIELUV_TO_CIEXYZ, from, to, from->cieluv.white.X, from->cieluv.white.Y, from->cieluv.white.Z); - break; - case LIBCOLOUR_YIQ: - CONV_0(YIQ_TO_CIEXYZ, from, to); - break; - case LIBCOLOUR_YDBDR: - CONV_0(YDBDR_TO_CIEXYZ, from, to); - break; - case LIBCOLOUR_YUV: - CONV_0(YUV_TO_CIEXYZ, from, to); - break; - case LIBCOLOUR_YPBPR: - CONV_0(YPBPR_TO_CIEXYZ, from, to); - break; - case LIBCOLOUR_YCGCO: - CONV_0(YCGCO_TO_CIEXYZ, from, to); - break; - case LIBCOLOUR_CIEUVW: - tmp.cie1960ucs.model = LIBCOLOUR_CIE1960UCS; - to_cie1960ucs(from, &tmp.cie1960ucs); - from = (const void *)&tmp.cie1960ucs; - /* fall through */ - case LIBCOLOUR_CIE1960UCS: - CONV_0(CIE1960UCS_TO_CIEXYZ, from, to); - break; - } -} - - -static void -to_cielab(const libcolour_colour_t *restrict from, libcolour_cielab_t *restrict to) -{ - libcolour_ciexyz_t tmp; - switch (from->model) { - default: - tmp.model = LIBCOLOUR_CIEXYZ; - to_ciexyz(from, &tmp); - from = (const void *)&tmp; - /* fall through */ - case LIBCOLOUR_CIEXYZ: - CONV_0(CIEXYZ_TO_CIELAB, from, to); - break; - case LIBCOLOUR_CIELAB: - *to = from->cielab; - break; - } -} - - -static void -to_cieluv(const libcolour_colour_t *restrict from, libcolour_cieluv_t *restrict to) -{ - libcolour_ciexyz_t tmp; - libcolour_cielchuv_t tmp2; - TYPE L, C, h; - switch (from->model) { - 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) { - tmp.model = LIBCOLOUR_CIEXYZ; - tmp2.model = LIBCOLOUR_CIELCHUV; - tmp2.white = to->white; - tmp2.one_revolution = PI2; - to_ciexyz(from, &tmp); - to_cielchuv((const libcolour_colour_t *)&tmp, &tmp2); - L = tmp2.L, C = tmp2.C, h = tmp2.h; - } else { - L = from->cielchuv.L; - C = from->cielchuv.C; - h = from->cielchuv.h * PI2 / from->cielchuv.one_revolution; - } - CIELCHUV_TO_CIELUV(L, C, h, to->L, to->u, to->v); - 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: - tmp.model = LIBCOLOUR_CIEXYZ; - to_ciexyz(from, &tmp); - from = (const void *)&tmp; - /* fall through */ - case LIBCOLOUR_CIEXYZ: - CONV_N(CIEXYZ_TO_CIELUV, from, to, to->white.X, to->white.Y, to->white.Z); - break; - } -} - - -static void -to_cielchuv(const libcolour_colour_t *restrict from, libcolour_cielchuv_t *restrict to) -{ - libcolour_cieluv_t tmp1, tmp2; - TYPE one_revolution; - switch (from->model) { - 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 *= one_revolution; - to->h /= from->cielchuv.one_revolution; - } - break; - } - /* fall through */ - default: - tmp1.model = LIBCOLOUR_CIELUV; - tmp1.white = to->white; - to_cieluv(from, &tmp1); - from = (const void *)&tmp1; - /* fall through */ - 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) { - tmp2.model = LIBCOLOUR_CIELUV; - tmp2.white = to->white; - to_cieluv(from, &tmp2); - from = (const void *)&tmp2; - } - CONV_N(CIELUV_TO_CIELCHUV, from, to, to->one_revolution); - break; - } -} - - -static void -to_yiq(const libcolour_colour_t *restrict from, libcolour_yiq_t *restrict to) -{ - libcolour_colour_t tmp = *from; - switch (from->model) { - case LIBCOLOUR_YIQ: - *to = from->yiq; - break; - case LIBCOLOUR_SRGB: - if (tmp.srgb.with_transfer) { - tmp.srgb.with_transfer = 0; - to_srgb(from, &tmp.srgb); - } - CONV_0(SRGB_TO_YIQ, &tmp, to); - break; - default: - tmp.model = LIBCOLOUR_CIEXYZ; - to_ciexyz(from, &tmp.ciexyz); - /* fall through */ - case LIBCOLOUR_CIEXYZ: - CONV_0(CIEXYZ_TO_YIQ, &tmp, to); - break; - } -} - - -static void -to_ydbdr(const libcolour_colour_t *restrict from, libcolour_ydbdr_t *restrict to) -{ - libcolour_colour_t tmp = *from; - switch (from->model) { - case LIBCOLOUR_YDBDR: - *to = from->ydbdr; - break; - case LIBCOLOUR_SRGB: - if (tmp.srgb.with_transfer) { - tmp.srgb.with_transfer = 0; - to_srgb(from, &tmp.srgb); - } - CONV_0(SRGB_TO_YDBDR, &tmp, to); - break; - case LIBCOLOUR_YUV: - CONV_0(YUV_TO_YDBDR, &tmp, to); - break; - default: - tmp.model = LIBCOLOUR_CIEXYZ; - to_ciexyz(from, &tmp.ciexyz); - /* fall through */ - case LIBCOLOUR_CIEXYZ: - CONV_0(CIEXYZ_TO_YDBDR, &tmp, to); - 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: - CONV_0(YDBDR_TO_YUV, from, to); - break; - case LIBCOLOUR_SRGB: - if (tmp.srgb.with_transfer) { - tmp.srgb.with_transfer = 0; - to_srgb(from, &tmp.srgb); - } - CONV_0(SRGB_TO_YUV, &tmp, to); - break; - default: - tmp.model = LIBCOLOUR_CIEXYZ; - to_ciexyz(from, &tmp.ciexyz); - /* fall through */ - case LIBCOLOUR_CIEXYZ: - CONV_0(CIEXYZ_TO_YUV, &tmp, to); - 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_transfer) { - tmp.srgb.with_transfer = 0; - to_srgb(from, &tmp.srgb); - } - CONV_0(SRGB_TO_YPBPR, &tmp, to); - break; - default: - tmp.model = LIBCOLOUR_CIEXYZ; - to_ciexyz(from, &tmp.ciexyz); - /* fall through */ - case LIBCOLOUR_CIEXYZ: - CONV_0(CIEXYZ_TO_YPBPR, &tmp, to); - 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_transfer) { - tmp.srgb.with_transfer = 0; - to_srgb(from, &tmp.srgb); - } - CONV_0(SRGB_TO_YCGCO, &tmp, to); - break; - default: - tmp.model = LIBCOLOUR_CIEXYZ; - to_ciexyz(from, &tmp.ciexyz); - /* fall through */ - case LIBCOLOUR_CIEXYZ: - CONV_0(CIEXYZ_TO_YCGCO, &tmp, to); - break; - } -} - - -static void -to_cie1960ucs(const libcolour_colour_t *restrict from, libcolour_cie1960ucs_t *restrict to) -{ - libcolour_colour_t tmp = *from; - switch (from->model) { - case LIBCOLOUR_CIE1960UCS: - *to = from->cie1960ucs; - return; - case LIBCOLOUR_CIEUVW: - CONV_N(CIEUVW_TO_CIE1960UCS, from, to, from->cieuvw.u0, from->cieuvw.v0); - return; - default: - tmp.model = LIBCOLOUR_CIEXYZ; - to_ciexyz(from, &tmp.ciexyz); - /* fall through */ - case LIBCOLOUR_CIEXYZ: - CONV_0(CIEXYZ_TO_CIE1960UCS, &tmp, to); - return; - } -} - - -static void -to_cieuvw(const libcolour_colour_t *restrict from, libcolour_cieuvw_t *restrict to) -{ - libcolour_colour_t tmp = *from; - switch (from->model) { - case LIBCOLOUR_CIEUVW: - CONV_N(CIEUVW_TO_CIEUVW, from, to, from->cieuvw.u0, from->cieuvw.v0, to->u0, to->v0); - break; - default: - tmp.model = LIBCOLOUR_CIE1960UCS; - to_cie1960ucs(from, &tmp.cie1960ucs); - /* fall through */ - case LIBCOLOUR_CIE1960UCS: - CONV_N(CIE1960UCS_TO_CIEUVW, &tmp, to, to->u0, to->v0); - break; - } -} - - -int -libcolour_convert(const libcolour_colour_t *restrict from, libcolour_colour_t *restrict to) -{ -#define X(C, T, N) 1 + - if (from->model < 0 || from->model > LIST_MODELS(X) 0) { -#undef X - errno = EINVAL; - return -1; - } - switch (to->model) { -#define X(C, T, N) case C: to_##N(from, &to->N); break; - LIST_MODELS(X) -#undef X - default: - errno = EINVAL; - return -1; - } - return 0; -} diff --git a/double.c b/double.c index 9d37aed..30aa502 100644 --- a/double.c +++ b/double.c @@ -82,6 +82,6 @@ #define libcolour_convert_en_masse libcolour_convert_en_masse_lf #include "common.h" -#include "convert-template.c" +#include "conversions.h" #include "libcolour-template.c" #include "en_masse-template.c" diff --git a/en_masse-template.c b/en_masse-template.c index 9a9f17f..b539328 100644 --- a/en_masse-template.c +++ b/en_masse-template.c @@ -1,5 +1,620 @@ /* See LICENSE file for copyright and license details. */ +#define XPARAMETERS\ + size_t n, size_t width, TYPE *ch1, TYPE *ch2, TYPE *ch3 + +#define XARGUMENTS\ + (n), (width), (ch1), (ch2), (ch3) + +#define PARAMETERS(FROM_SPACE, TO_SPACE)\ + const libcolour_##FROM_SPACE##_t *from, const libcolour_##TO_SPACE##_t *to, XPARAMETERS + +#define ARGUMENTS(FROM, TO)\ + (FROM), (TO), XARGUMENTS + + +#define SIMPLE_LOOP(CH, INSTRUCTIONS)\ + do {\ + TYPE *ch = (CH);\ + size_t i__;\ + for (i__ = 0; i__ < n; i__++) {\ + INSTRUCTIONS;\ + (CH) += width;\ + }\ + (CH) = ch;\ + } while (0) + +#define LOOP(INSTRUCTIONS)\ + do {\ + TYPE *c1 = ch1, *c2 = ch2, *c3 = ch3;\ + size_t i__;\ + for (i__ = 0; i__ < n; i__++) {\ + INSTRUCTIONS;\ + ch1 += width;\ + ch2 += width;\ + ch3 += width;\ + }\ + ch1 = c1;\ + ch2 = c2;\ + ch3 = c3;\ + } while (0) + +#define CONV_0(MACRO)\ + LOOP(MACRO(*ch1, *ch2, *ch3, *ch1, *ch2, *ch3)) + +#define CONV_N(MACRO, ...)\ + LOOP(MACRO(*ch1, *ch2, *ch3, *ch1, *ch2, *ch3, __VA_ARGS__)) + + +#define LINEAR_SRGB\ + do {\ + if (from->srgb.with_transfer) {\ + libcolour_srgb_t srgb__ = from->srgb;\ + srgb__.with_transfer = 0;\ + to_srgb(ARGUMENTS(from, &srgb__));\ + }\ + } while (0) + + + +#define X(C, T, N) static void to_##N(const libcolour_colour_t *from, const T *to, XPARAMETERS); +LIST_MODELS(X) +#undef X + + + +static void +conversion_by_matrix(XPARAMETERS, TYPE m11, TYPE m12, TYPE m13, TYPE m21, TYPE m22, TYPE m23, TYPE m31, TYPE m32, TYPE m33) +{ + TYPE c1, c2, c3; + while (n--) { + c1 = *ch1; + c2 = *ch2; + c3 = *ch3; + *ch1 = m11 * c1 + m12 * c2 + m13 * c3; + *ch2 = m21 * c1 + m22 * c2 + m23 * c3; + *ch3 = m31 * c1 + m32 * c2 + m33 * c3; + ch1 += width; + ch2 += width; + ch3 += width; + } +} + + +static void +rgb_encode(XPARAMETERS, const libcolour_rgb_t *restrict space) +{ + TYPE r_sign, g_sign, b_sign; + switch (space->encoding_type) { + case LIBCOLOUR_ENCODING_TYPE_LINEAR: + break; + case LIBCOLOUR_ENCODING_TYPE_SIMPLE: + case LIBCOLOUR_ENCODING_TYPE_REGULAR: + LOOP(do { + (r_sign = 1, g_sign = 1, b_sign = 1); + if (*ch1 < 0) (r_sign = -1, *ch1 = -*ch1); + if (*ch2 < 0) (g_sign = -1, *ch2 = -*ch2); + if (*ch3 < 0) (b_sign = -1, *ch3 = -*ch3); + if (space->encoding_type == LIBCOLOUR_ENCODING_TYPE_SIMPLE) { + *ch1 = xpow(*ch1, 1 / space->GAMMA); + *ch2 = xpow(*ch2, 1 / space->GAMMA); + *ch3 = xpow(*ch3, 1 / space->GAMMA); + } else { + *ch1 = REGULAR(space, *ch1); + *ch2 = REGULAR(space, *ch2); + *ch3 = REGULAR(space, *ch3); + } + *ch1 *= r_sign; + *ch2 *= g_sign; + *ch3 *= b_sign; + } while (0)); + break; + case LIBCOLOUR_ENCODING_TYPE_CUSTOM: + LOOP((*ch1 = (space->TO_ENCODED_RED)(*ch1), + *ch2 = (space->TO_ENCODED_GREEN)(*ch2), + *ch3 = (space->TO_ENCODED_BLUE)(*ch3))); + break; + default: + fprintf(stderr, "libcolour: invalid encoding type\n"); + abort(); + } +} + +static void +rgb_decode(XPARAMETERS, const libcolour_rgb_t *restrict space) +{ + TYPE r_sign, g_sign, b_sign; + switch (space->encoding_type) { + case LIBCOLOUR_ENCODING_TYPE_LINEAR: + break; + case LIBCOLOUR_ENCODING_TYPE_SIMPLE: + case LIBCOLOUR_ENCODING_TYPE_REGULAR: + LOOP(do { + (r_sign = 1, g_sign = 1, b_sign = 1); + if (*ch1 < 0) (r_sign = -1, *ch1 = -*ch1); + if (*ch2 < 0) (g_sign = -1, *ch2 = -*ch2); + if (*ch3 < 0) (b_sign = -1, *ch3 = -*ch3); + if (space->encoding_type == LIBCOLOUR_ENCODING_TYPE_SIMPLE) { + *ch1 = xpow(*ch1, space->GAMMA); + *ch2 = xpow(*ch2, space->GAMMA); + *ch3 = xpow(*ch3, space->GAMMA); + } else { + *ch1 = INVREGULAR(space, *ch1); + *ch2 = INVREGULAR(space, *ch2); + *ch3 = INVREGULAR(space, *ch3); + } + *ch1 *= r_sign; + *ch2 *= g_sign; + *ch3 *= b_sign; + } while (0)); + break; + case LIBCOLOUR_ENCODING_TYPE_CUSTOM: + LOOP((*ch1 = (space->TO_DECODED_RED)(*ch1), + *ch2 = (space->TO_DECODED_GREEN)(*ch2), + *ch3 = (space->TO_DECODED_BLUE)(*ch3))); + break; + default: + fprintf(stderr, "libcolour: invalid encoding type\n"); + abort(); + } +} + +static int +rgb_same_transfer(const libcolour_rgb_t *a, const libcolour_rgb_t *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(PARAMETERS(colour, rgb)) +{ + int have_transfer = 0, with_transfer = to->with_transfer; + switch (from->model) { + case LIBCOLOUR_RGB: + if (!memcmp(from->rgb.M, to->M, sizeof(TYPE[3][3]))) { + have_transfer = from->rgb.with_transfer; + if (have_transfer && with_transfer && !rgb_same_transfer(&from->rgb, to)) { + rgb_decode(XARGUMENTS, &from->rgb); + have_transfer = 0; + } + break; + } + /* fall through */ + default: + to_ciexyz(ARGUMENTS(from, NULL)); + /* fall through */ + case LIBCOLOUR_CIEXYZ: + conversion_by_matrix(XARGUMENTS, CIEXYZ_TO_RGB(to->Minv)); + break; + } + + if (have_transfer != with_transfer) { + if (with_transfer) + rgb_encode(XARGUMENTS, to); + else + rgb_decode(XARGUMENTS, &from->rgb); + } +} + + +static void +to_srgb(PARAMETERS(colour, srgb)) +{ + libcolour_srgb_t tmp; + switch (from->model) { + default: + to_ciexyz(ARGUMENTS(from, NULL)); + /* fall through */ + case LIBCOLOUR_CIEXYZ: + conversion_by_matrix(XARGUMENTS, CIEXYZ_TO_SRGB); + break; + case LIBCOLOUR_SRGB: + srgb_to_srgb: + if (from->srgb.with_transfer != to->with_transfer) { + if (to->with_transfer) { + LOOP((*ch1 = srgb_encode(*ch1), + *ch2 = srgb_encode(*ch2), + *ch3 = srgb_encode(*ch3))); + } else { + LOOP((*ch1 = srgb_decode(*ch1), + *ch2 = srgb_decode(*ch2), + *ch3 = srgb_decode(*ch3))); + } + } + return; + case LIBCOLOUR_YIQ: + conversion_by_matrix(XARGUMENTS, YIQ_TO_SRGB); + break; + case LIBCOLOUR_YDBDR: + conversion_by_matrix(XARGUMENTS, YDBDR_TO_SRGB); + break; + case LIBCOLOUR_YPBPR: + CONV_0(YPBPR_TO_SRGB); + break; + case LIBCOLOUR_YUV: + conversion_by_matrix(XARGUMENTS, YUV_TO_SRGB); + break; + case LIBCOLOUR_YCGCO: + conversion_by_matrix(XARGUMENTS, YCGCO_TO_SRGB); + break; + } + if (to->with_transfer) { + tmp = *to; + tmp.with_transfer = 0; + from = (const void *)&tmp; + goto srgb_to_srgb; + } +} + + +static void +to_ciexyy(PARAMETERS(colour, ciexyy)) +{ + libcolour_srgb_t tmp; + size_t m, old_n; +beginning: + m = old_n = n; + switch (from->model) { + case LIBCOLOUR_CIEXYY: + break; + case LIBCOLOUR_SRGB: + tmp.model = LIBCOLOUR_SRGB; + tmp.with_transfer = 0; + if (from->srgb.with_transfer) + to_srgb(ARGUMENTS((const libcolour_colour_t *)from, &tmp)); + if (!*ch1 && !*ch2 && !*ch3) { + for (m = 1; m < n && !ch1[m * width] && !ch2[m * width] && !ch3[m * width]; m++); + n = m; + LOOP((*ch1 = D(0.31272660439158), + *ch2 = D(0.32902315240275), + *ch3 = 0)); + n = old_n; + break; + } else { + for (m = 1; m < n && (ch1[m * width] || ch2[m * width] || ch3[m * width]); m++); + n = m; + from = (const void *)&tmp; + } + /* fall through */ + default: + to_ciexyz(ARGUMENTS(from, NULL)); + /* fall through */ + case LIBCOLOUR_CIEXYZ: + CONV_0(CIEXYZ_TO_CIEXYY); + break; + } + if (m != old_n) { + n = old_n - m; + ch1 += m * width; + ch2 += m * width; + ch3 += m * width; + goto beginning; + } +} + + +static void +to_ciexyz(PARAMETERS(colour, ciexyz)) +{ + libcolour_colour_t tmp; + switch (from->model) { + case LIBCOLOUR_RGB: + if (from->rgb.with_transfer) { + tmp.rgb = from->rgb; + tmp.rgb.with_transfer = 0; + to_rgb(ARGUMENTS(from, &tmp.rgb)); + } + conversion_by_matrix(XARGUMENTS, RGB_TO_CIEXYZ(from->rgb.M)); + break; + default: + tmp.srgb.model = LIBCOLOUR_SRGB; + tmp.srgb.with_transfer = 0; + to_srgb(ARGUMENTS(from, &tmp.srgb)); + from = (const void *)&tmp.srgb; + /* fall through */ + case LIBCOLOUR_SRGB: + LINEAR_SRGB; + conversion_by_matrix(XARGUMENTS, SRGB_TO_CIEXYZ); + break; + case LIBCOLOUR_CIEXYY: + CONV_0(CIEXYY_TO_CIEXYZ); + break; + case LIBCOLOUR_CIEXYZ: + break; + case LIBCOLOUR_CIELAB: + CONV_0(CIELAB_TO_CIEXYZ); + break; + case LIBCOLOUR_CIELCHUV: + tmp.cieluv.model = LIBCOLOUR_CIELUV; + tmp.cieluv.white = from->cielchuv.white; + to_cieluv(ARGUMENTS(from, &tmp.cieluv)); + from = (const void *)&tmp.cieluv; + /* fall through */ + case LIBCOLOUR_CIELUV: + CONV_N(CIELUV_TO_CIEXYZ, from->cieluv.white.X, from->cieluv.white.Y, from->cieluv.white.Z); + break; + case LIBCOLOUR_YIQ: + conversion_by_matrix(XARGUMENTS, YIQ_TO_CIEXYZ); + break; + case LIBCOLOUR_YDBDR: + conversion_by_matrix(XARGUMENTS, YDBDR_TO_CIEXYZ); + break; + case LIBCOLOUR_YUV: + conversion_by_matrix(XARGUMENTS, YUV_TO_CIEXYZ); + break; + case LIBCOLOUR_YPBPR: + conversion_by_matrix(XARGUMENTS, YPBPR_TO_CIEXYZ); + break; + case LIBCOLOUR_YCGCO: + conversion_by_matrix(XARGUMENTS, YCGCO_TO_CIEXYZ); + break; + case LIBCOLOUR_CIEUVW: + tmp.cie1960ucs.model = LIBCOLOUR_CIE1960UCS; + to_cie1960ucs(ARGUMENTS(from, &tmp.cie1960ucs)); + from = (const void *)&tmp.cie1960ucs; + /* fall through */ + case LIBCOLOUR_CIE1960UCS: + CONV_0(CIE1960UCS_TO_CIEXYZ); + break; + } +} + + +static void +to_cielab(PARAMETERS(colour, cielab)) +{ + switch (from->model) { + default: + to_ciexyz(ARGUMENTS(from, NULL)); + /* fall through */ + case LIBCOLOUR_CIEXYZ: + CONV_0(CIEXYZ_TO_CIELAB); + break; + case LIBCOLOUR_CIELAB: + break; + } +} + + +static void +to_cieluv(PARAMETERS(colour, cieluv)) +{ + libcolour_ciexyz_t tmp; + libcolour_cielchuv_t tmp2; + TYPE m; + switch (from->model) { + 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) { + tmp.model = LIBCOLOUR_CIEXYZ; + tmp2.model = LIBCOLOUR_CIELCHUV; + tmp2.white = to->white; + tmp2.one_revolution = PI2; + to_ciexyz(ARGUMENTS(from, &tmp)); + to_cielchuv(ARGUMENTS((const libcolour_colour_t *)&tmp, &tmp2)); + } else if (from->cielchuv.one_revolution != PI2) { + m = PI2 / from->cielchuv.one_revolution; + SIMPLE_LOOP(ch3, *ch3 *= m); + } + CONV_0(CIELCHUV_TO_CIELUV); + 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) + break; + /* fall through */ + default: + to_ciexyz(ARGUMENTS(from, NULL)); + /* fall through */ + case LIBCOLOUR_CIEXYZ: + CONV_N(CIEXYZ_TO_CIELUV, to->white.X, to->white.Y, to->white.Z); + break; + } +} + + +static void +to_cielchuv(PARAMETERS(colour, cielchuv)) +{ + libcolour_cieluv_t tmp1, tmp2; + TYPE m; + switch (from->model) { + 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) { + m = to->one_revolution; + m /= from->cielchuv.one_revolution; + SIMPLE_LOOP(ch3, *ch3 *= m); + } + break; + } + /* fall through */ + default: + tmp1.model = LIBCOLOUR_CIELUV; + tmp1.white = to->white; + to_cieluv(ARGUMENTS(from, &tmp1)); + from = (const void *)&tmp1; + /* fall through */ + 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) { + tmp2.model = LIBCOLOUR_CIELUV; + tmp2.white = to->white; + to_cieluv(ARGUMENTS(from, &tmp2)); + from = (const void *)&tmp2; + } + CONV_N(CIELUV_TO_CIELCHUV, to->one_revolution); + break; + } +} + + +static void +to_yiq(PARAMETERS(colour, yiq)) +{ + switch (from->model) { + case LIBCOLOUR_YIQ: + break; + case LIBCOLOUR_SRGB: + LINEAR_SRGB; + conversion_by_matrix(XARGUMENTS, SRGB_TO_YIQ); + break; + default: + to_ciexyz(ARGUMENTS(from, NULL)); + /* fall through */ + case LIBCOLOUR_CIEXYZ: + conversion_by_matrix(XARGUMENTS, CIEXYZ_TO_YIQ); + break; + } +} + + +static void +to_ydbdr(PARAMETERS(colour, ydbdr)) +{ + switch (from->model) { + case LIBCOLOUR_YDBDR: + break; + case LIBCOLOUR_SRGB: + LINEAR_SRGB; + conversion_by_matrix(XARGUMENTS, SRGB_TO_YDBDR); + break; + case LIBCOLOUR_YUV: + CONV_0(YUV_TO_YDBDR); + break; + default: + to_ciexyz(ARGUMENTS(from, NULL)); + /* fall through */ + case LIBCOLOUR_CIEXYZ: + conversion_by_matrix(XARGUMENTS, CIEXYZ_TO_YDBDR); + break; + } +} + + +static void +to_yuv(PARAMETERS(colour, yuv)) +{ + switch (from->model) { + case LIBCOLOUR_YUV: + break; + case LIBCOLOUR_YDBDR: + CONV_0(YDBDR_TO_YUV); + break; + case LIBCOLOUR_SRGB: + LINEAR_SRGB; + conversion_by_matrix(XARGUMENTS, SRGB_TO_YUV); + break; + default: + to_ciexyz(ARGUMENTS(from, NULL)); + /* fall through */ + case LIBCOLOUR_CIEXYZ: + conversion_by_matrix(XARGUMENTS, CIEXYZ_TO_YUV); + break; + } +} + + +static void +to_ypbpr(PARAMETERS(colour, ypbpr)) +{ + switch (from->model) { + case LIBCOLOUR_YPBPR: + break; + case LIBCOLOUR_SRGB: + LINEAR_SRGB; + CONV_0(SRGB_TO_YPBPR); + break; + default: + to_ciexyz(ARGUMENTS(from, NULL)); + /* fall through */ + case LIBCOLOUR_CIEXYZ: + conversion_by_matrix(XARGUMENTS, CIEXYZ_TO_YPBPR); + break; + } +} + + +static void +to_ycgco(PARAMETERS(colour, ycgco)) +{ + switch (from->model) { + case LIBCOLOUR_YCGCO: + break; + case LIBCOLOUR_SRGB: + LINEAR_SRGB; + conversion_by_matrix(XARGUMENTS, SRGB_TO_YCGCO); + break; + default: + to_ciexyz(ARGUMENTS(from, NULL)); + /* fall through */ + case LIBCOLOUR_CIEXYZ: + conversion_by_matrix(XARGUMENTS, CIEXYZ_TO_YCGCO); + break; + } +} + + +static void +to_cie1960ucs(PARAMETERS(colour, cie1960ucs)) +{ + switch (from->model) { + case LIBCOLOUR_CIE1960UCS: + break; + case LIBCOLOUR_CIEUVW: + CONV_N(CIEUVW_TO_CIE1960UCS, from->cieuvw.u0, from->cieuvw.v0); + break; + default: + to_ciexyz(ARGUMENTS(from, NULL)); + /* fall through */ + case LIBCOLOUR_CIEXYZ: + CONV_0(CIEXYZ_TO_CIE1960UCS); + break; + } +} + + +static void +to_cieuvw(PARAMETERS(colour, cieuvw)) +{ + switch (from->model) { + case LIBCOLOUR_CIEUVW: + CONV_N(CIEUVW_TO_CIEUVW, from->cieuvw.u0, from->cieuvw.v0, to->u0, to->v0); + break; + default: + to_cie1960ucs(ARGUMENTS(from, NULL)); + /* fall through */ + case LIBCOLOUR_CIE1960UCS: + CONV_N(CIE1960UCS_TO_CIEUVW, to->u0, to->v0); + break; + } +} + + int libcolour_convert_en_masse(const libcolour_colour_t *from, const libcolour_colour_t *to, libcolour_convert_en_masse_mode_t mode, size_t n, ...) @@ -10,8 +625,8 @@ libcolour_convert_en_masse(const libcolour_colour_t *from, const libcolour_colou int no_override = mode & LIBCOLOUR_CONVERT_EN_MASSE_NO_OVERRIDE; va_list args; TYPE *in1, *in2, *in3, *in_alpha = NULL; - TYPE *out1, *out2, *out3, *out_alpha = NULL; - size_t width, i; + TYPE *ch1, *ch2, *ch3, *ch_alpha = NULL; + size_t width; if ((unsigned int)mode > 15U) { errno = EINVAL; @@ -49,28 +664,34 @@ libcolour_convert_en_masse(const libcolour_colour_t *from, const libcolour_colou } if (!no_override) { - out1 = in1; - out2 = in2; - out3 = in3; - out_alpha = in_alpha; + ch1 = in1; + ch2 = in2; + ch3 = in3; + ch_alpha = in_alpha; } else if (alpha_mode == LIBCOLOUR_CONVERT_EN_MASSE_NO_ALPHA) { - out1 = va_arg(args, TYPE *); - out2 = out1 + 1; - out3 = out1 + 2; + ch1 = va_arg(args, TYPE *); + ch2 = ch1 + 1; + ch3 = ch1 + 2; + memcpy(ch1, in1, n * 3 * sizeof(TYPE)); } else if (alpha_mode == LIBCOLOUR_CONVERT_EN_MASSE_ALPHA_FIRST) { - out_alpha = va_arg(args, TYPE *); - out1 = out_alpha + 1; - out2 = out_alpha + 2; - out3 = out_alpha + 3; + ch_alpha = va_arg(args, TYPE *); + ch1 = ch_alpha + 1; + ch2 = ch_alpha + 2; + ch3 = ch_alpha + 3; + memcpy(ch_alpha, in_alpha, n * 4 * sizeof(TYPE)); } else if (alpha_mode == LIBCOLOUR_CONVERT_EN_MASSE_ALPHA_LAST) { - out1 = va_arg(args, TYPE *); - out2 = out1 + 1; - out3 = out1 + 2; - out_alpha = out1 + 3; + ch1 = va_arg(args, TYPE *); + ch2 = ch1 + 1; + ch3 = ch1 + 2; + ch_alpha = ch1 + 3; + memcpy(ch1, in1, n * 4 * sizeof(TYPE)); } else { - out1 = va_arg(args, TYPE *); - out2 = va_arg(args, TYPE *); - out3 = va_arg(args, TYPE *); + ch1 = va_arg(args, TYPE *); + ch2 = va_arg(args, TYPE *); + ch3 = va_arg(args, TYPE *); + memcpy(ch1, in1, n * sizeof(TYPE)); + memcpy(ch2, in2, n * sizeof(TYPE)); + memcpy(ch3, in3, n * sizeof(TYPE)); } va_end(args); @@ -85,38 +706,18 @@ libcolour_convert_en_masse(const libcolour_colour_t *from, const libcolour_colou } switch (to->model) { -#define X(C, T, N) case C: memcpy(&tto, to, sizeof(T)); break; - LIST_MODELS(X) +#define X(C, T, N)\ + case C:\ + memcpy(&tto, to, sizeof(T));\ + to_##N(ARGUMENTS(&tfrom, &tto.N));\ + break; + LIST_MODELS(X) #undef X default: errno = EINVAL; return -1; } - if (in_alpha != out_alpha) { - for (i = 0; i < n; i++) { - *out_alpha = *in_alpha; - in_alpha += width; - out_alpha += width; - } - } - - while (n--) { - tfrom.rgb.R = *in1; - tfrom.rgb.G = *in2; - tfrom.rgb.B = *in3; - libcolour_convert(&tfrom, &tto); - *out1 = tto.rgb.R; - *out2 = tto.rgb.G; - *out3 = tto.rgb.B; - in1 += width; - in2 += width; - in3 += width; - out1 += width; - out2 += width; - out3 += width; - } - (void) on_cpu; return 0; } diff --git a/float.c b/float.c index 185423e..c1e28a5 100644 --- a/float.c +++ b/float.c @@ -82,6 +82,6 @@ #define libcolour_convert_en_masse libcolour_convert_en_masse_f #include "common.h" -#include "convert-template.c" +#include "conversions.h" #include "libcolour-template.c" #include "en_masse-template.c" diff --git a/libcolour-template.c b/libcolour-template.c index 9d0fb0b..bfbbd3e 100644 --- a/libcolour-template.c +++ b/libcolour-template.c @@ -7,6 +7,18 @@ TYPE libcolour_srgb_encode(TYPE t) { return srgb_encode(t); } TYPE libcolour_srgb_decode(TYPE t) { return srgb_decode(t); } +int +libcolour_convert(const libcolour_colour_t *from, libcolour_colour_t *to) +{ + return libcolour_convert_en_masse(from, to, + LIBCOLOUR_CONVERT_EN_MASSE_SEPARATED | + LIBCOLOUR_CONVERT_EN_MASSE_ON_CPU | + LIBCOLOUR_CONVERT_EN_MASSE_NO_OVERRIDE, 1, + &from->srgb.R, &from->srgb.G, &from->srgb.B, + &to->srgb.R, &to->srgb.G, &to->srgb.B); +} + + int libcolour_delta_e(const libcolour_colour_t *a, const libcolour_colour_t *b, TYPE *e) { diff --git a/long-double.c b/long-double.c index 65954c3..350ef87 100644 --- a/long-double.c +++ b/long-double.c @@ -82,6 +82,6 @@ #define libcolour_convert_en_masse libcolour_convert_en_masse_llf #include "common.h" -#include "convert-template.c" +#include "conversions.h" #include "libcolour-template.c" #include "en_masse-template.c" diff --git a/test.c b/test.c index c5cf8d5..2829f12 100644 --- a/test.c +++ b/test.c @@ -11,6 +11,8 @@ #define libcolour_colour_t libcolour_colour_lf_t #define libcolour_rgb_t libcolour_rgb_lf_t +#define libcolour_srgb_t libcolour_srgb_lf_t +#define libcolour_ciexyy_t libcolour_ciexyy_lf_t #define libcolour_unmarshal libcolour_unmarshal_lf @@ -87,7 +89,7 @@ test_2convert(libcolour_colour_t *c1, libcolour_colour_t *c2, libcolour_colour_t return 0; return 1; } - + static int test_2convert_11(libcolour_colour_t *c1, libcolour_model_t model) @@ -112,7 +114,7 @@ test_2convert_11(libcolour_colour_t *c1, libcolour_model_t model) return r1 & r2; case LIBCOLOUR_CIELCHUV: c2.cielchuv.one_revolution = 360.; - /* fall though */ + /* fall through */ case LIBCOLOUR_CIELUV: c2.cieluv.white.model = LIBCOLOUR_CIEXYZ; c2.cieluv.white.X = 1.0294; @@ -143,7 +145,7 @@ test_2convert_1n(libcolour_model_t model, const char *model_name, double ch1, do case LIBCOLOUR_CIELCHUV: if (ch3 > 0.9999) return 1; - /* fall though */ + /* fall through */ default: c1.srgb.R = ch1, c1.srgb.G = ch2, c1.srgb.B = ch3; break; @@ -182,7 +184,7 @@ test_2convert_1n(libcolour_model_t model, const char *model_name, double ch1, do 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.X = 1.03; c1.cieluv.white.Y = 0.8; c1.cieluv.white.Z = 0.92; } else { @@ -435,6 +437,47 @@ test_en_masse(libcolour_colour_t *c1, libcolour_colour_t *c2, libcolour_colour_t } +static int +test_partitioned_en_masse(void) +{ + libcolour_srgb_t from; + libcolour_ciexyy_t to; + double ch1[32], ch2[32], ch3[32]; + int i; + + from.model = LIBCOLOUR_SRGB; + from.with_transfer = 0; + to.model = LIBCOLOUR_CIEXYY; + + for (i = 0; i < 32; i++) { + ch1[i] = (i + 1.) / 32.; + ch2[i] = (i + 1.) / 32.; + ch3[i] = (i + 1.) / 32.; + } + + for (i = 3; i < 6; i++) ch1[i] = ch2[i] = ch3[i] = 0; + for (i = 20; i < 30; i++) ch1[i] = ch2[i] = ch3[i] = 0; + + if (libcolour_convert_en_masse(&from, &to, LIBCOLOUR_CONVERT_EN_MASSE_SEPARATED, 32, ch1, ch2, ch3)) + return -1; + + for (i = 0; i < 32; i++) { + if ((3 <= i && i < 6) || (20 <= i && i < 30)) + from.R = from.G = from.B = 0; + else + from.R = from.G = from.B = (i + 1.) / 32.; + if (libcolour_convert(&from, &to)) + return -1; + if (ch1[i] != to.x || ch2[i] != to.y || ch3[i] != to.Y) { + printf("test_partitioned_en_masse failed at %i\n", i); + return -1; + } + } + + return 0; +} + + /** * Test libcolour * @@ -467,7 +510,7 @@ main(int argc, char *argv[]) c2.model = LIBCOLOUR_RGB; c2.rgb.with_transfer = 0; if (libcolour_get_rgb_colour_space(&c2.rgb, LIBCOLOUR_RGB_COLOUR_SPACE_SRGB)) { - printf("LIBCOLOUR_RGB_COLOUR_SPACE_SRGB failed\n"), rc = 0; + printf("LIBCOLOUR_RGB_COLOUR_SPACE_SRGB failed\n"), rc = 1; goto colour_spaces_done; } if (c2.rgb.white_r != 1 || c2.rgb.white_g != 1 || c2.rgb.white_b != 1 || @@ -477,7 +520,7 @@ main(int argc, char *argv[]) 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; + printf("LIBCOLOUR_RGB_COLOUR_SPACE_SRGB failed\n"), rc = 1; goto colour_spaces_done; } t1 = c2.rgb.TRANSITION * c2.rgb.SLOPE; @@ -488,21 +531,21 @@ main(int argc, char *argv[]) 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; + printf("LIBCOLOUR_RGB_COLOUR_SPACE_SRGB failed\n"), rc = 1; 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; + printf("LIBCOLOUR_RGB_COLOUR_SPACE_SRGB failed\n"), rc = 1; 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; + printf("LIBCOLOUR_RGB_COLOUR_SPACE_SRGB failed\n"), rc = 1; goto colour_spaces_done; } @@ -511,7 +554,7 @@ main(int argc, char *argv[]) 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; + printf("libcolour_delta_e failed\n"), rc = 1; 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); @@ -609,7 +652,7 @@ main(int argc, char *argv[]) !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; + printf("libcolour_srgb_encode failed\n"), rc = 1; goto colour_spaces_done; } if (libcolour_convert(&c2, &c1)) @@ -622,7 +665,7 @@ main(int argc, char *argv[]) !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; + printf("libcolour_srgb_decode failed\n"), rc = 1; goto colour_spaces_done; } } @@ -645,7 +688,7 @@ main(int argc, char *argv[]) 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; + printf("libcolour_convert failed to convert between two transfer functions\n"), rc = 1; goto colour_spaces_done; } @@ -654,7 +697,7 @@ main(int argc, char *argv[]) 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; + printf("libcolour_convert failed to convert when two different transfer functions are not applied\n"), rc = 1; goto colour_spaces_done; } @@ -710,27 +753,27 @@ colour_spaces_done: 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; + printf("libcolour_marshal failed\n"), rc = 1; goto marshal_done; } n = libcolour_marshal(&c1, buf); if (n > sizeof(buf)) { - printf("libcolour_marshal failed\n"), rc = 0; + printf("libcolour_marshal failed\n"), rc = 1; goto marshal_done; } if (libcolour_unmarshal(NULL, buf) != n) { - printf("libcolour_unmarshal failed\n"), rc = 0; + printf("libcolour_unmarshal failed\n"), rc = 1; goto marshal_done; } if (libcolour_unmarshal(&c2, buf) != n) { - printf("libcolour_unmarshal failed\n"), rc = 0; + printf("libcolour_unmarshal failed\n"), rc = 1; goto marshal_done; } if (memcmp(&c2, &c3, sizeof(c2))) { - printf("libcolour_(un)marshal failed\n"), rc = 0; + printf("libcolour_(un)marshal failed\n"), rc = 1; goto marshal_done; } - marshal_done: +marshal_done: c1.srgb.model = LIBCOLOUR_SRGB; c1.srgb.R = 0.8; @@ -743,13 +786,21 @@ colour_spaces_done: c2.srgb.B = 0.3; c2.srgb.with_transfer = 1; c3.model = LIBCOLOUR_CIEXYZ; - for (i = 0; i < 15; i++) - if (test_en_masse(&c1, &c2, &c3, i)) + for (i = 0; i < 15; i++) { + if (test_en_masse(&c1, &c2, &c3, i)) { + rc = 1; goto en_masse_done; - en_masse_done: + } + } + + if (test_partitioned_en_masse()) { + rc = 1; + goto en_masse_done; + } +en_masse_done: return rc; - fail: +fail: perror(*argv); (void) argc; return 2; -- cgit v1.2.3-70-g09d2