From 40e6ef1f99f78e80af9658b7c600f1f669f6bba3 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Sat, 17 Dec 2016 16:28:23 +0100 Subject: CIELChuv: measure hue in degrees, but add parameter to change this MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- doc/info/chap/colour-spaces.texinfo | 15 ++++++++++----- src/convert.c | 17 ++++++++++++++--- src/libcolour.c | 2 ++ src/libcolour.h | 1 + src/test.c | 23 ++++++++++++++++++++--- 5 files changed, 47 insertions(+), 11 deletions(-) diff --git a/doc/info/chap/colour-spaces.texinfo b/doc/info/chap/colour-spaces.texinfo index a214feb..9455bbc 100644 --- a/doc/info/chap/colour-spaces.texinfo +++ b/doc/info/chap/colour-spaces.texinfo @@ -354,7 +354,7 @@ The wide-gamut RGB colour space, also known as Adobe Wide Gamut RGB. @end table -Call @code{libcolour_proper(&c)} on a +The call @code{libcolour_proper(&c)} on a @code{struct libcolour_rgb_t c} (done automatically for predefined colour spaces) sets @code{c.red.model}, @code{c.green.model}, and @code{c.blue.model} to @@ -521,7 +521,7 @@ The white point. CIE L*u*v* is not additive, since conversion from CIE 1931 XYZ is non-linear. -Call @code{libcolour_proper(&c)} on a +The call @code{libcolour_proper(&c)} on a @code{struct libcolour_cieluv_t c} sets @code{c.white.model} to @code{LIBCOLOUR_CIEXYZ}. Zero is always returned in this case. @@ -555,15 +555,20 @@ The C*@sub{uv} value, the chroma. The h@sub{uv} value, the hue. @item struct libcolour_ciexyz white The white point. +@item double one_revolution +The value lowest positive values of @code{h} that is equivalent to 0. +360 if the hue is measured in degrees, 400 if the hue is measured in +gon, and 2 pi if the hue is measured radian. Any value can be used. @end table 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 +The call @code{libcolour_proper(&c)} on a @code{struct libcolour_cielchuv_t c} sets -@code{c.white.model} to @code{LIBCOLOUR_CIEXYZ}. -Zero is always returned in this case. +@code{c.white.model} to @code{LIBCOLOUR_CIEXYZ}, +and if @code{c.one_revolution} is 0, it is set +to 360. Zero is always returned in this case. @node YIQ diff --git a/src/convert.c b/src/convert.c index 5a358c9..9a2c3d9 100644 --- a/src/convert.c +++ b/src/convert.c @@ -24,6 +24,8 @@ #define WASDIV0(x) (isinf(x) || isnan(x)) +#define PI (3.14159265358979323846) +#define PI2 (2 * PI) @@ -598,11 +600,12 @@ static void cielchuv_to_cieluv(const libcolour_cielchuv_t* restrict from, libcol 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; + L = from->L, C = from->C, h = from->h * PI2 / from->one_revolution; } to->L = L; to->u = C * cos(h); @@ -655,7 +658,7 @@ static void cieluv_to_cielchuv(const libcolour_cieluv_t* restrict from, libcolou } to->L = L; to->C = sqrt(u * u + v * v); - to->h = atan2(v, u); + to->h = atan2(v, u) / PI2 * to->one_revolution; } static void other_to_cielchuv(const libcolour_colour_t* restrict from, libcolour_cielchuv_t* restrict to) @@ -669,6 +672,7 @@ static void other_to_cielchuv(const libcolour_colour_t* restrict from, libcolour 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); @@ -677,7 +681,14 @@ static void to_cielchuv(const libcolour_colour_t* restrict from, libcolour_cielc 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; + 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 */ diff --git a/src/libcolour.c b/src/libcolour.c index 57f1e80..69014d3 100644 --- a/src/libcolour.c +++ b/src/libcolour.c @@ -121,6 +121,8 @@ int libcolour_proper(libcolour_colour_t* colour) 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; diff --git a/src/libcolour.h b/src/libcolour.h index fe53a4e..6387151 100644 --- a/src/libcolour.h +++ b/src/libcolour.h @@ -232,6 +232,7 @@ typedef struct libcolour_cielchuv { double C; double h; struct libcolour_ciexyz white; + double one_revolution; } libcolour_cielchuv_t; typedef struct libcolour_rgb { diff --git a/src/test.c b/src/test.c index 7d5517c..795333f 100644 --- a/src/test.c +++ b/src/test.c @@ -94,8 +94,10 @@ static int test_convert_11(libcolour_colour_t* c1, libcolour_model_t model) if (r2 = test_convert(c1, &c2, &c3), r2 < 0) return -1; return r1 & r2; - case LIBCOLOUR_CIELUV: 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; @@ -119,8 +121,12 @@ static int test_convert_1n(libcolour_model_t model, const char* model_name, doub c1.model = model; switch (model) { case LIBCOLOUR_CIELAB: - c1.srgb.R = ch1 * 100, c1.srgb.G = ch2 * 100, c1.srgb.B = ch3 * 100; + 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; @@ -140,8 +146,11 @@ static int test_convert_1n(libcolour_model_t model, const char* model_name, doub return rc; c1.srgb.with_gamma = run; break; - case LIBCOLOUR_CIELUV: 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; @@ -151,6 +160,14 @@ static int test_convert_1n(libcolour_model_t model, const char* model_name, doub 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; } -- cgit v1.2.3-70-g09d2