diff options
Diffstat (limited to '')
-rw-r--r-- | TODO | 4 | ||||
-rw-r--r-- | doc/info/chap/colour-spaces.texinfo | 20 | ||||
-rw-r--r-- | doc/info/content.texinfo | 2 | ||||
-rw-r--r-- | src/libcolour.c | 76 | ||||
-rw-r--r-- | src/libcolour.h | 9 | ||||
-rw-r--r-- | src/test.c | 20 |
6 files changed, 80 insertions, 51 deletions
@@ -1,4 +1,4 @@ -Colour spaces: +Colour models: LMS L'M'S' ICtCp @@ -6,7 +6,9 @@ Colour spaces: TSL Y'UV Hunter 1948 color space (see Wikipedia article on CIELAB) + Hunter Rdab CIELCh (CIEHLC) (see Wikipedia article on CIELAB) + IPT Support for generic additive colour spaces (3 channels and more) Support for generic subtractive colour spaces (3 channels and more) diff --git a/doc/info/chap/colour-spaces.texinfo b/doc/info/chap/colour-spaces.texinfo index 5c88a88..eb26ba0 100644 --- a/doc/info/chap/colour-spaces.texinfo +++ b/doc/info/chap/colour-spaces.texinfo @@ -8,7 +8,7 @@ * CIEXYZ:: The CIE 1931 XYZ colour model. * CIELAB:: The CIE L*a*b* colour model. * CIELUV:: The CIE 1976 (L*, u*, v*) colour model. -* CIELCh:: The CIE LCh colour model. +* CIELChuv:: The CIE LCh@sub{uv} colour model. * YIQ:: The YIQ colour model. * YDbDr:: The YDbDr colour model. * YUV:: The YUV colour model. @@ -31,7 +31,7 @@ typedef union libcolour_colour @{ struct libcolour_ciexyz ciexyz; struct libcolour_cielab cielab; struct libcolour_cieluv cieluv; - struct libcolour_cielch cielch; + struct libcolour_cielchuv cielchuv; struct libcolour_yiq yiq; struct libcolour_ydbdr ydbdr; struct libcolour_yuv yuv; @@ -297,6 +297,8 @@ The DCI-P3 D65 colour space. The DCI-P3 Theater colour space. @item LIBCOLOUR_RGB_COLOUR_SPACE_DON_RGB_4 The Don RGB 4 colour space. +@item LIBCOLOUR_RGB_COLOUR_SPACE_ECI_RGB +The ECI RGB colour space. @item LIBCOLOUR_RGB_COLOUR_SPACE_ECI_RGB_V2 The ECI RGB v2 colour space. @item LIBCOLOUR_RGB_COLOUR_SPACE_EKTA_SPACE_PS5 @@ -539,20 +541,20 @@ Zero is always returned in this case. -@node CIELCh +@node CIELChuv @section CIE LCh@sub{uv} CIE LCh@sub{uv} (also known as CIE HLC@sub{uv}) colours are presented -with @code{struct libcolour_cielch} (@code{libcolour_cielch_t}), and -the @code{.model} member shall be set to @code{LIBCOLOUR_CIELCH}. In -@code{union libcolour_colour}, @code{.cielch} are used for CIE LCh@sub{uv} +with @code{struct libcolour_cielchuv} (@code{libcolour_cielchuv_t}), and +the @code{.model} member shall be set to @code{LIBCOLOUR_CIELCHUV}. In +@code{union libcolour_colour}, @code{.cielchuv} are used for CIE LCh@sub{uv} colours. CIE LCh@sub{uv} approximates uniform human colour perception using cylindrical representation. -@code{struct libcolour_cielch} has the following members +@code{struct libcolour_cielchuv} has the following members @table @code @item enum libcolour_model model -Shall be set to @code{LIBCOLOUR_CIELCH}. +Shall be set to @code{LIBCOLOUR_CIELCHUV}. @item double L The L* value. 0 is black, 100 is white. @item double C @@ -572,7 +574,7 @@ CIE LCh@sub{uv} is not additive. It is a cylindrical representation of CIE 1976 (L*, u*, v*). Call @code{libcolour_proper(&c)} on a -@code{struct libcolour_cielch_t c} sets +@code{struct libcolour_cielchuv_t c} sets @code{c.white.model} to @code{LIBCOLOUR_CIEXYZ}. Zero is always returned in this case. diff --git a/doc/info/content.texinfo b/doc/info/content.texinfo index 4ad71d5..c8e7811 100644 --- a/doc/info/content.texinfo +++ b/doc/info/content.texinfo @@ -29,7 +29,7 @@ Colour Spaces * CIEXYZ:: The CIE 1931 XYZ colour model. * CIELAB:: The CIE L*a*b* colour model. * CIELUV:: The CIE 1976 (L*, u*, v*) colour model. -* CIELCh:: The CIE LCh colour model. +* CIELChuv:: The CIE LCh@sub{uv} colour model. * YIQ:: The YIQ colour model. * YDbDr:: The YDbDr colour model. * YUV:: The YUV colour model. diff --git a/src/libcolour.c b/src/libcolour.c index dd170af..d2e056b 100644 --- a/src/libcolour.c +++ b/src/libcolour.c @@ -38,7 +38,7 @@ static void to_ciexyy(const libcolour_colour_t* restrict from, libcolour_ciexyy_ 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_cielch(const libcolour_colour_t* restrict from, libcolour_cielch_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); @@ -364,7 +364,7 @@ static void cieluv_to_ciexyz(const libcolour_cieluv_t* restrict from, libcolour_ to->Z = Y * (3 / v - 0.75 * u / v - 5); } -static void cielch_to_ciexyz(const libcolour_cielch_t* restrict from, libcolour_ciexyz_t* restrict to) +static void cielchuv_to_ciexyz(const libcolour_cielchuv_t* restrict from, libcolour_ciexyz_t* restrict to) { libcolour_cieluv_t tmp; tmp.model = LIBCOLOUR_CIELUV; @@ -427,8 +427,8 @@ static void to_ciexyz(const libcolour_colour_t* restrict from, libcolour_ciexyz_ case LIBCOLOUR_CIELUV: cieluv_to_ciexyz(&from->cieluv, to); return; - case LIBCOLOUR_CIELCH: - cielch_to_ciexyz(&from->cielch, to); + case LIBCOLOUR_CIELCHUV: + cielchuv_to_ciexyz(&from->cielchuv, to); return; case LIBCOLOUR_YUV: yuv_to_ciexyz(&from->yuv, to); @@ -504,17 +504,17 @@ static void ciexyz_to_cieluv(const libcolour_ciexyz_t* restrict from, libcolour_ to->v = v * y; } -static void cielch_to_cieluv(const libcolour_cielch_t* restrict from, libcolour_cieluv_t* restrict to) +static void cielchuv_to_cieluv(const libcolour_cielchuv_t* restrict from, libcolour_cieluv_t* restrict to) { libcolour_ciexyz_t tmp; - libcolour_cielch_t tmp2; + 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_CIELCH; + tmp2.model = LIBCOLOUR_CIELCHUV; tmp2.white = to->white; to_ciexyz((const libcolour_colour_t*)from, &tmp); - to_cielch((const libcolour_colour_t*)&tmp, &tmp2); + 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; @@ -538,8 +538,8 @@ static void to_cieluv(const libcolour_colour_t* restrict from, libcolour_cieluv_ case LIBCOLOUR_CIEXYZ: ciexyz_to_cieluv(&from->ciexyz, to); return; - case LIBCOLOUR_CIELCH: - cielch_to_cieluv(&from->cielch, to); + case LIBCOLOUR_CIELCHUV: + cielchuv_to_cieluv(&from->cielchuv, to); return; case LIBCOLOUR_CIELUV: if (to->white.X == from->cieluv.white.X && @@ -556,7 +556,7 @@ static void to_cieluv(const libcolour_colour_t* restrict from, libcolour_cieluv_ } -static void cieluv_to_cielch(const libcolour_cieluv_t* restrict from, libcolour_cielch_t* restrict to) +static void cieluv_to_cielchuv(const libcolour_cieluv_t* restrict from, libcolour_cielchuv_t* restrict to) { libcolour_cieluv_t tmp; double L, u, v; @@ -573,31 +573,31 @@ static void cieluv_to_cielch(const libcolour_cieluv_t* restrict from, libcolour_ to->h = atan2(v, u); } -static void other_to_cielch(const libcolour_colour_t* restrict from, libcolour_cielch_t* restrict to) +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_cielch(&tmp, to); + cieluv_to_cielchuv(&tmp, to); } -static void to_cielch(const libcolour_colour_t* restrict from, libcolour_cielch_t* restrict to) +static void to_cielchuv(const libcolour_colour_t* restrict from, libcolour_cielchuv_t* restrict to) { switch (from->model) { case LIBCOLOUR_CIELUV: - cieluv_to_cielch(&from->cieluv, to); + cieluv_to_cielchuv(&from->cieluv, to); return; - case LIBCOLOUR_CIELCH: - if (to->white.X == from->cielch.white.X && - to->white.Y == from->cielch.white.Y && - to->white.Z == from->cielch.white.Z) { - *to = from->cielch; + 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) { + *to = from->cielchuv; return; } /* fall through */ default: - other_to_cielch(from, to); + other_to_cielchuv(from, to); return; } } @@ -828,8 +828,8 @@ int libcolour_convert(const libcolour_colour_t* restrict from, libcolour_colour_ case LIBCOLOUR_CIELUV: to_cieluv(from, &to->cieluv); break; - case LIBCOLOUR_CIELCH: - to_cielch(from, &to->cielch); + case LIBCOLOUR_CIELCHUV: + to_cielchuv(from, &to->cielchuv); break; case LIBCOLOUR_YIQ: to_yiq(from, &to->yiq); @@ -941,8 +941,8 @@ int libcolour_proper(libcolour_colour_t* colour) case LIBCOLOUR_CIELUV: colour->cieluv.white.model = LIBCOLOUR_CIEXYZ; break; - case LIBCOLOUR_CIELCH: - colour->cielch.white.model = LIBCOLOUR_CIEXYZ; + case LIBCOLOUR_CIELCHUV: + colour->cielchuv.white.model = LIBCOLOUR_CIEXYZ; break; case LIBCOLOUR_RGB: colour->rgb.red.model = LIBCOLOUR_CIEXYY; @@ -1096,11 +1096,26 @@ static int invert_(size_t n, double (*Minvp)[n][n], double (*Mp)[n][n]) } +static double transfer_function_l_star(double t) +{ + t = (t > 216. / 24389.) ? cbrt(t) : t * 841. / 108. + 4. / 29.; + return t * 1.16 - 0.16; +} + +static double invtransfer_function_l_star(double t) +{ + t = (t + 0.16) / 1.16; + return (t > 6. / 29.) ? t * t * t : (t - 4. / 29.) * 108 / 841; +} + + 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: /* TODO L* */ + 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: @@ -1239,6 +1254,15 @@ int libcolour_get_rgb_colour_space(libcolour_rgb_t* cs, libcolour_rgb_colour_spa 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); diff --git a/src/libcolour.h b/src/libcolour.h index 8efe779..c68cf11 100644 --- a/src/libcolour.h +++ b/src/libcolour.h @@ -72,7 +72,7 @@ X(LIBCOLOUR_CIEXYZ, libcolour_ciexyz_t)\ X(LIBCOLOUR_CIELAB, libcolour_cielab_t)\ X(LIBCOLOUR_CIELUV, libcolour_cieluv_t)\ - X(LIBCOLOUR_CIELCH, libcolour_cielch_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)\ @@ -112,6 +112,7 @@ typedef enum libcolour_rgb_colour_space { 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, @@ -223,13 +224,13 @@ typedef struct libcolour_cieluv { struct libcolour_ciexyz white; } libcolour_cieluv_t; -typedef struct libcolour_cielch { +typedef struct libcolour_cielchuv { enum libcolour_model model; double L; double C; double h; struct libcolour_ciexyz white; -} libcolour_cielch_t; +} libcolour_cielchuv_t; typedef struct libcolour_rgb { enum libcolour_model model; @@ -270,7 +271,7 @@ typedef union libcolour_colour { struct libcolour_ciexyz ciexyz; struct libcolour_cielab cielab; struct libcolour_cieluv cieluv; - struct libcolour_cielch cielch; + struct libcolour_cielchuv cielchuv; struct libcolour_yiq yiq; struct libcolour_ydbdr ydbdr; struct libcolour_yuv yuv; @@ -61,11 +61,11 @@ int test_convert(libcolour_colour_t* c1, libcolour_model_t model) return -1; return r1 & r2; case LIBCOLOUR_CIELUV: - case LIBCOLOUR_CIELCH: - c2.cielch.white.model = LIBCOLOUR_CIEXYZ; - c2.cielch.white.X = 1.0294; - c2.cielch.white.Y = 1; - c2.cielch.white.Z = 0.9118; + case LIBCOLOUR_CIELCHUV: + 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_convert_(c1, &c2, &c3); case LIBCOLOUR_CIEUVW: c2.cieuvw.u0 = 0.37; @@ -95,11 +95,11 @@ int test_convert_all(libcolour_model_t model, const char* model_name) c1.srgb.with_gamma = 0; break; case LIBCOLOUR_CIELUV: - case LIBCOLOUR_CIELCH: - c1.cielch.white.model = LIBCOLOUR_CIEXYZ; - c1.cielch.white.X = 1.0294; - c1.cielch.white.Y = 1; - c1.cielch.white.Z = 0.9118; + case LIBCOLOUR_CIELCHUV: + c1.cieluv.white.model = LIBCOLOUR_CIEXYZ; + c1.cieluv.white.X = 1.0294; + c1.cieluv.white.Y = 1; + c1.cieluv.white.Z = 0.9118; break; case LIBCOLOUR_CIEUVW: c1.cieuvw.u0 = 0.37; |