aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Oteiza2017-09-26 17:13:36 -0400
committerMark Oteiza2017-09-30 08:00:53 -0400
commit645ff6c7029daef082b3a558407121207fa64ff5 (patch)
tree2a19d973cdb446169347fb3b7848ce753a8cac51
parent157007b58e41afc848f79c99aced0f09109dfdac (diff)
downloademacs-645ff6c7029daef082b3a558407121207fa64ff5.tar.gz
emacs-645ff6c7029daef082b3a558407121207fa64ff5.zip
Add CAM02 JCh and CAM02-UCS J'a'b' conversions
* src/lcms.c (rad2deg, parse_jch_list, parse_jab_list, xyz_to_jch): (jch_to_xyz, jch_to_jab, jab_to_jch): New functions. (lcms-jch->xyz, lcms-jch->xyz, lcms-jch->jab, lcms-jab->jch): New Lisp functions. (lcms-cam02-ucs): Refactor. (syms_of_lcms2): Declare new functions. * test/src/lcms-tests.el (lcms-roundtrip, lcms-ciecam02-gold): (lcms-jmh->cam02-ucs-silver): New tests. * etc/NEWS: Mention new functions.
-rw-r--r--etc/NEWS3
-rw-r--r--src/lcms.c303
-rw-r--r--test/src/lcms-tests.el44
3 files changed, 315 insertions, 35 deletions
diff --git a/etc/NEWS b/etc/NEWS
index ab9a2a5f32d..adeee9e6ef2 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -76,7 +76,8 @@ If the lcms2 library is installed, Emacs will enable features built on
76top of that library. The new configure option '--without-lcms2' can 76top of that library. The new configure option '--without-lcms2' can
77be used to build without lcms2 support even if it is installed. Emacs 77be used to build without lcms2 support even if it is installed. Emacs
78linked to Little CMS exposes color management functions in Lisp: the 78linked to Little CMS exposes color management functions in Lisp: the
79color metrics 'lcms-cie-de2000' and 'lcms-cam02-ucs'. 79color metrics 'lcms-cie-de2000' and 'lcms-cam02-ucs', as well as
80functions for conversion to and from CIE CAM02 and CAM02-UCS.
80 81
81** The configure option '--with-gameuser' now defaults to 'no', 82** The configure option '--with-gameuser' now defaults to 'no',
82as this appears to be the most common configuration in practice. 83as this appears to be the most common configuration in practice.
diff --git a/src/lcms.c b/src/lcms.c
index a5e527911ef..c7da57658a9 100644
--- a/src/lcms.c
+++ b/src/lcms.c
@@ -25,6 +25,13 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
25 25
26#include "lisp.h" 26#include "lisp.h"
27 27
28typedef struct
29{
30 double J;
31 double a;
32 double b;
33} lcmsJab_t;
34
28#ifdef WINDOWSNT 35#ifdef WINDOWSNT
29# include <windows.h> 36# include <windows.h>
30# include "w32.h" 37# include "w32.h"
@@ -36,6 +43,8 @@ DEF_DLL_FN (cmsHANDLE, cmsCIECAM02Init,
36 (cmsContext ContextID, const cmsViewingConditions* pVC)); 43 (cmsContext ContextID, const cmsViewingConditions* pVC));
37DEF_DLL_FN (void, cmsCIECAM02Forward, 44DEF_DLL_FN (void, cmsCIECAM02Forward,
38 (cmsHANDLE hModel, const cmsCIEXYZ* pIn, cmsJCh* pOut)); 45 (cmsHANDLE hModel, const cmsCIEXYZ* pIn, cmsJCh* pOut));
46DEF_DLL_FN (void, cmsCIECAM02Reverse,
47 (cmsHANDLE hModel, const cmsJCh* pIn, cmsCIEXYZ* pOut));
39DEF_DLL_FN (void, cmsCIECAM02Done, (cmsHANDLE hModel)); 48DEF_DLL_FN (void, cmsCIECAM02Done, (cmsHANDLE hModel));
40DEF_DLL_FN (cmsBool, cmsWhitePointFromTemp, 49DEF_DLL_FN (cmsBool, cmsWhitePointFromTemp,
41 (cmsCIExyY* WhitePoint, cmsFloat64Number TempK)); 50 (cmsCIExyY* WhitePoint, cmsFloat64Number TempK));
@@ -54,6 +63,7 @@ init_lcms_functions (void)
54 LOAD_DLL_FN (library, cmsCIE2000DeltaE); 63 LOAD_DLL_FN (library, cmsCIE2000DeltaE);
55 LOAD_DLL_FN (library, cmsCIECAM02Init); 64 LOAD_DLL_FN (library, cmsCIECAM02Init);
56 LOAD_DLL_FN (library, cmsCIECAM02Forward); 65 LOAD_DLL_FN (library, cmsCIECAM02Forward);
66 LOAD_DLL_FN (library, cmsCIECAM02Reverse);
57 LOAD_DLL_FN (library, cmsCIECAM02Done); 67 LOAD_DLL_FN (library, cmsCIECAM02Done);
58 LOAD_DLL_FN (library, cmsWhitePointFromTemp); 68 LOAD_DLL_FN (library, cmsWhitePointFromTemp);
59 LOAD_DLL_FN (library, cmsxyY2XYZ); 69 LOAD_DLL_FN (library, cmsxyY2XYZ);
@@ -63,6 +73,7 @@ init_lcms_functions (void)
63# undef cmsCIE2000DeltaE 73# undef cmsCIE2000DeltaE
64# undef cmsCIECAM02Init 74# undef cmsCIECAM02Init
65# undef cmsCIECAM02Forward 75# undef cmsCIECAM02Forward
76# undef cmsCIECAM02Reverse
66# undef cmsCIECAM02Done 77# undef cmsCIECAM02Done
67# undef cmsWhitePointFromTemp 78# undef cmsWhitePointFromTemp
68# undef cmsxyY2XYZ 79# undef cmsxyY2XYZ
@@ -70,6 +81,7 @@ init_lcms_functions (void)
70# define cmsCIE2000DeltaE fn_cmsCIE2000DeltaE 81# define cmsCIE2000DeltaE fn_cmsCIE2000DeltaE
71# define cmsCIECAM02Init fn_cmsCIECAM02Init 82# define cmsCIECAM02Init fn_cmsCIECAM02Init
72# define cmsCIECAM02Forward fn_cmsCIECAM02Forward 83# define cmsCIECAM02Forward fn_cmsCIECAM02Forward
84# define cmsCIECAM02Reverse fn_cmsCIECAM02Reverse
73# define cmsCIECAM02Done fn_cmsCIECAM02Done 85# define cmsCIECAM02Done fn_cmsCIECAM02Done
74# define cmsWhitePointFromTemp fn_cmsWhitePointFromTemp 86# define cmsWhitePointFromTemp fn_cmsWhitePointFromTemp
75# define cmsxyY2XYZ fn_cmsxyY2XYZ 87# define cmsxyY2XYZ fn_cmsxyY2XYZ
@@ -145,6 +157,12 @@ deg2rad (double degrees)
145 return M_PI * degrees / 180.0; 157 return M_PI * degrees / 180.0;
146} 158}
147 159
160static double
161rad2deg (double radians)
162{
163 return 180.0 * radians / M_PI;
164}
165
148static cmsCIEXYZ illuminant_d65 = { .X = 95.0455, .Y = 100.0, .Z = 108.8753 }; 166static cmsCIEXYZ illuminant_d65 = { .X = 95.0455, .Y = 100.0, .Z = 108.8753 };
149 167
150static void 168static void
@@ -181,6 +199,46 @@ parse_xyz_list (Lisp_Object xyz_list, cmsCIEXYZ *color)
181} 199}
182 200
183static bool 201static bool
202parse_jch_list (Lisp_Object jch_list, cmsJCh *color)
203{
204#define PARSE_JCH_LIST_FIELD(field) \
205 if (CONSP (jch_list) && NUMBERP (XCAR (jch_list))) \
206 { \
207 color->field = XFLOATINT (XCAR (jch_list)); \
208 jch_list = XCDR (jch_list); \
209 } \
210 else \
211 return false;
212
213 PARSE_JCH_LIST_FIELD (J);
214 PARSE_JCH_LIST_FIELD (C);
215 PARSE_JCH_LIST_FIELD (h);
216
217 if (! NILP (jch_list))
218 return false;
219 return true;
220}
221
222static bool
223parse_jab_list (Lisp_Object jab_list, lcmsJab_t *color)
224{
225#define PARSE_JAB_LIST_FIELD(field) \
226 if (CONSP (jab_list) && NUMBERP (XCAR (jab_list))) \
227 { \
228 color->field = XFLOATINT (XCAR (jab_list)); \
229 jab_list = XCDR (jab_list); \
230 } \
231 else \
232 return false;
233
234 PARSE_JAB_LIST_FIELD (J);
235 PARSE_JAB_LIST_FIELD (a);
236 PARSE_JAB_LIST_FIELD (b);
237
238 return true;
239}
240
241static bool
184parse_viewing_conditions (Lisp_Object view, const cmsCIEXYZ *wp, 242parse_viewing_conditions (Lisp_Object view, const cmsCIEXYZ *wp,
185 cmsViewingConditions *vc) 243 cmsViewingConditions *vc)
186{ 244{
@@ -216,6 +274,204 @@ parse_viewing_conditions (Lisp_Object view, const cmsCIEXYZ *wp,
216 return true; 274 return true;
217} 275}
218 276
277static void
278xyz_to_jch (const cmsCIEXYZ *xyz, cmsJCh *jch, const cmsViewingConditions *vc)
279{
280 cmsHANDLE h;
281
282 h = cmsCIECAM02Init (0, vc);
283 cmsCIECAM02Forward (h, xyz, jch);
284 cmsCIECAM02Done (h);
285}
286
287static void
288jch_to_xyz (const cmsJCh *jch, cmsCIEXYZ *xyz, const cmsViewingConditions *vc)
289{
290 cmsHANDLE h;
291
292 h = cmsCIECAM02Init (0, vc);
293 cmsCIECAM02Reverse (h, jch, xyz);
294 cmsCIECAM02Done (h);
295}
296
297static void
298jch_to_jab (const cmsJCh *jch, lcmsJab_t *jab, double FL, double c1, double c2)
299{
300 double Mp = 43.86 * log (1.0 + c2 * (jch->C * sqrt (sqrt (FL))));
301 jab->J = 1.7 * jch->J / (1.0 + (c1 * jch->J));
302 jab->a = Mp * cos (deg2rad (jch->h));
303 jab->b = Mp * sin (deg2rad (jch->h));
304}
305
306static void
307jab_to_jch (const lcmsJab_t *jab, cmsJCh *jch, double FL, double c1, double c2)
308{
309 jch->J = jab->J / (1.0 + c1 * (100.0 - jab->J));
310 jch->h = atan2 (jab->b, jab->a);
311 double Mp = hypot (jab->a, jab->b);
312 jch->h = rad2deg (jch->h);
313 if (jch->h < 0.0)
314 jch->h += 360.0;
315 jch->C = (exp (c2 * Mp) - 1.0) / (c2 * sqrt (sqrt (FL)));
316}
317
318DEFUN ("lcms-xyz->jch", Flcms_xyz_to_jch, Slcms_xyz_to_jch, 1, 3, 0,
319 doc: /* Convert CIE CAM02 JCh to CIE XYZ.
320COLOR is a list (X Y Z), with Y scaled about unity.
321Optional arguments WHITEPOINT and VIEW are the same as in `lcms-cam02-ucs',
322which see. */)
323 (Lisp_Object color, Lisp_Object whitepoint, Lisp_Object view)
324{
325 cmsViewingConditions vc;
326 cmsJCh jch;
327 cmsCIEXYZ xyz, xyzw;
328
329#ifdef WINDOWSNT
330 if (!lcms_initialized)
331 lcms_initialized = init_lcms_functions ();
332 if (!lcms_initialized)
333 {
334 message1 ("lcms2 library not found");
335 return Qnil;
336 }
337#endif
338
339 if (!(CONSP (color) && parse_xyz_list (color, &xyz)))
340 signal_error ("Invalid color", color);
341 if (NILP (whitepoint))
342 xyzw = illuminant_d65;
343 else if (!(CONSP (whitepoint) && parse_xyz_list (whitepoint, &xyzw)))
344 signal_error ("Invalid white point", whitepoint);
345 if (NILP (view))
346 default_viewing_conditions (&xyzw, &vc);
347 else if (!(CONSP (view) && parse_viewing_conditions (view, &xyzw, &vc)))
348 signal_error ("Invalid viewing conditions", view);
349
350 xyz_to_jch(&xyz, &jch, &vc);
351 return list3 (make_float (jch.J), make_float (jch.C), make_float (jch.h));
352}
353
354DEFUN ("lcms-jch->xyz", Flcms_jch_to_xyz, Slcms_jch_to_xyz, 1, 3, 0,
355 doc: /* Convert CIE XYZ to CIE CAM02 JCh.
356COLOR is a list (J C h), where lightness of white is equal to 100, and hue
357is given in degrees.
358Optional arguments WHITEPOINT and VIEW are the same as in `lcms-cam02-ucs',
359which see. */)
360 (Lisp_Object color, Lisp_Object whitepoint, Lisp_Object view)
361{
362 cmsViewingConditions vc;
363 cmsJCh jch;
364 cmsCIEXYZ xyz, xyzw;
365
366#ifdef WINDOWSNT
367 if (!lcms_initialized)
368 lcms_initialized = init_lcms_functions ();
369 if (!lcms_initialized)
370 {
371 message1 ("lcms2 library not found");
372 return Qnil;
373 }
374#endif
375
376 if (!(CONSP (color) && parse_jch_list (color, &jch)))
377 signal_error ("Invalid color", color);
378 if (NILP (whitepoint))
379 xyzw = illuminant_d65;
380 else if (!(CONSP (whitepoint) && parse_xyz_list (whitepoint, &xyzw)))
381 signal_error ("Invalid white point", whitepoint);
382 if (NILP (view))
383 default_viewing_conditions (&xyzw, &vc);
384 else if (!(CONSP (view) && parse_viewing_conditions (view, &xyzw, &vc)))
385 signal_error ("Invalid viewing conditions", view);
386
387 jch_to_xyz(&jch, &xyz, &vc);
388 return list3 (make_float (xyz.X / 100.0),
389 make_float (xyz.Y / 100.0),
390 make_float (xyz.Z / 100.0));
391}
392
393DEFUN ("lcms-jch->jab", Flcms_jch_to_jab, Slcms_jch_to_jab, 1, 3, 0,
394 doc: /* Convert CIE CAM02 JCh to CAM02-UCS J'a'b'.
395COLOR is a list (J C h) as described in `lcms-jch->xyz', which see.
396Optional arguments WHITEPOINT and VIEW are the same as in `lcms-cam02-ucs',
397which see. */)
398 (Lisp_Object color, Lisp_Object whitepoint, Lisp_Object view)
399{
400 cmsViewingConditions vc;
401 lcmsJab_t jab;
402 cmsJCh jch;
403 cmsCIEXYZ xyzw;
404 double FL, k, k4;
405
406#ifdef WINDOWSNT
407 if (!lcms_initialized)
408 lcms_initialized = init_lcms_functions ();
409 if (!lcms_initialized)
410 {
411 message1 ("lcms2 library not found");
412 return Qnil;
413 }
414#endif
415
416 if (!(CONSP (color) && parse_jch_list (color, &jch)))
417 signal_error ("Invalid color", color);
418 if (NILP (whitepoint))
419 xyzw = illuminant_d65;
420 else if (!(CONSP (whitepoint) && parse_xyz_list (whitepoint, &xyzw)))
421 signal_error ("Invalid white point", whitepoint);
422 if (NILP (view))
423 default_viewing_conditions (&xyzw, &vc);
424 else if (!(CONSP (view) && parse_viewing_conditions (view, &xyzw, &vc)))
425 signal_error ("Invalid viewing conditions", view);
426
427 k = 1.0 / (1.0 + (5.0 * vc.La));
428 k4 = k * k * k * k;
429 FL = vc.La * k4 + 0.1 * (1 - k4) * (1 - k4) * cbrt (5.0 * vc.La);
430 jch_to_jab (&jch, &jab, FL, 0.007, 0.0228);
431 return list3 (make_float (jab.J), make_float (jab.a), make_float (jab.b));
432}
433
434DEFUN ("lcms-jab->jch", Flcms_jab_to_jch, Slcms_jab_to_jch, 1, 3, 0,
435 doc: /* Convert CAM02-UCS J'a'b' to CIE CAM02 JCh.
436COLOR is a list (J' a' b'), where white corresponds to lightness J equal to 100.
437Optional arguments WHITEPOINT and VIEW are the same as in `lcms-cam02-ucs',
438which see. */)
439 (Lisp_Object color, Lisp_Object whitepoint, Lisp_Object view)
440{
441 cmsViewingConditions vc;
442 cmsJCh jch;
443 lcmsJab_t jab;
444 cmsCIEXYZ xyzw;
445 double FL, k, k4;
446
447#ifdef WINDOWSNT
448 if (!lcms_initialized)
449 lcms_initialized = init_lcms_functions ();
450 if (!lcms_initialized)
451 {
452 message1 ("lcms2 library not found");
453 return Qnil;
454 }
455#endif
456
457 if (!(CONSP (color) && parse_jab_list (color, &jab)))
458 signal_error ("Invalid color", color);
459 if (NILP (whitepoint))
460 xyzw = illuminant_d65;
461 else if (!(CONSP (whitepoint) && parse_xyz_list (whitepoint, &xyzw)))
462 signal_error ("Invalid white point", whitepoint);
463 if (NILP (view))
464 default_viewing_conditions (&xyzw, &vc);
465 else if (!(CONSP (view) && parse_viewing_conditions (view, &xyzw, &vc)))
466 signal_error ("Invalid viewing conditions", view);
467
468 k = 1.0 / (1.0 + (5.0 * vc.La));
469 k4 = k * k * k * k;
470 FL = vc.La * k4 + 0.1 * (1 - k4) * (1 - k4) * cbrt (5.0 * vc.La);
471 jab_to_jch (&jab, &jch, FL, 0.007, 0.0228);
472 return list3 (make_float (jch.J), make_float (jch.C), make_float (jch.h));
473}
474
219/* References: 475/* References:
220 Li, Luo et al. "The CRI-CAM02UCS colour rendering index." COLOR research 476 Li, Luo et al. "The CRI-CAM02UCS colour rendering index." COLOR research
221 and application, 37 No.3, 2012. 477 and application, 37 No.3, 2012.
@@ -239,10 +495,9 @@ The default viewing conditions are (20 100 1 1). */)
239{ 495{
240 cmsViewingConditions vc; 496 cmsViewingConditions vc;
241 cmsJCh jch1, jch2; 497 cmsJCh jch1, jch2;
242 cmsHANDLE h1, h2;
243 cmsCIEXYZ xyz1, xyz2, xyzw; 498 cmsCIEXYZ xyz1, xyz2, xyzw;
244 double Jp1, ap1, bp1, Jp2, ap2, bp2; 499 lcmsJab_t jab1, jab2;
245 double Mp1, Mp2, FL, k, k4; 500 double FL, k, k4;
246 501
247#ifdef WINDOWSNT 502#ifdef WINDOWSNT
248 if (!lcms_initialized) 503 if (!lcms_initialized)
@@ -267,41 +522,17 @@ The default viewing conditions are (20 100 1 1). */)
267 else if (!(CONSP (view) && parse_viewing_conditions (view, &xyzw, &vc))) 522 else if (!(CONSP (view) && parse_viewing_conditions (view, &xyzw, &vc)))
268 signal_error ("Invalid view conditions", view); 523 signal_error ("Invalid view conditions", view);
269 524
270 h1 = cmsCIECAM02Init (0, &vc); 525 xyz_to_jch (&xyz1, &jch1, &vc);
271 h2 = cmsCIECAM02Init (0, &vc); 526 xyz_to_jch (&xyz2, &jch2, &vc);
272 cmsCIECAM02Forward (h1, &xyz1, &jch1);
273 cmsCIECAM02Forward (h2, &xyz2, &jch2);
274 cmsCIECAM02Done (h1);
275 cmsCIECAM02Done (h2);
276 527
277 /* Now have colors in JCh, need to calculate J'a'b'
278
279 M = C * F_L^0.25
280 J' = 1.7 J / (1 + 0.007 J)
281 M' = 43.86 ln(1 + 0.0228 M)
282 a' = M' cos(h)
283 b' = M' sin(h)
284
285 where
286
287 F_L = 0.2 k^4 (5 L_A) + 0.1 (1 - k^4)^2 (5 L_A)^(1/3),
288 k = 1/(5 L_A + 1)
289 */
290 k = 1.0 / (1.0 + (5.0 * vc.La)); 528 k = 1.0 / (1.0 + (5.0 * vc.La));
291 k4 = k * k * k * k; 529 k4 = k * k * k * k;
292 FL = vc.La * k4 + 0.1 * (1 - k4) * (1 - k4) * cbrt (5.0 * vc.La); 530 FL = vc.La * k4 + 0.1 * (1 - k4) * (1 - k4) * cbrt (5.0 * vc.La);
293 Mp1 = 43.86 * log (1.0 + 0.0228 * (jch1.C * sqrt (sqrt (FL)))); 531 jch_to_jab (&jch1, &jab1, FL, 0.007, 0.0228);
294 Mp2 = 43.86 * log (1.0 + 0.0228 * (jch2.C * sqrt (sqrt (FL)))); 532 jch_to_jab (&jch2, &jab2, FL, 0.007, 0.0228);
295 Jp1 = 1.7 * jch1.J / (1.0 + (0.007 * jch1.J)); 533
296 Jp2 = 1.7 * jch2.J / (1.0 + (0.007 * jch2.J)); 534 return make_float (hypot (jab2.J - jab1.J,
297 ap1 = Mp1 * cos (deg2rad (jch1.h)); 535 hypot (jab2.a - jab1.a, jab2.b - jab1.b)));
298 ap2 = Mp2 * cos (deg2rad (jch2.h));
299 bp1 = Mp1 * sin (deg2rad (jch1.h));
300 bp2 = Mp2 * sin (deg2rad (jch2.h));
301
302 return make_float (sqrt ((Jp2 - Jp1) * (Jp2 - Jp1) +
303 (ap2 - ap1) * (ap2 - ap1) +
304 (bp2 - bp1) * (bp2 - bp1)));
305} 536}
306 537
307DEFUN ("lcms-temp->white-point", Flcms_temp_to_white_point, Slcms_temp_to_white_point, 1, 1, 0, 538DEFUN ("lcms-temp->white-point", Flcms_temp_to_white_point, Slcms_temp_to_white_point, 1, 1, 0,
@@ -359,6 +590,10 @@ void
359syms_of_lcms2 (void) 590syms_of_lcms2 (void)
360{ 591{
361 defsubr (&Slcms_cie_de2000); 592 defsubr (&Slcms_cie_de2000);
593 defsubr (&Slcms_xyz_to_jch);
594 defsubr (&Slcms_jch_to_xyz);
595 defsubr (&Slcms_jch_to_jab);
596 defsubr (&Slcms_jab_to_jch);
362 defsubr (&Slcms_cam02_ucs); 597 defsubr (&Slcms_cam02_ucs);
363 defsubr (&Slcms2_available_p); 598 defsubr (&Slcms2_available_p);
364 defsubr (&Slcms_temp_to_white_point); 599 defsubr (&Slcms_temp_to_white_point);
diff --git a/test/src/lcms-tests.el b/test/src/lcms-tests.el
index d6d1d16b9ad..cc324af68ba 100644
--- a/test/src/lcms-tests.el
+++ b/test/src/lcms-tests.el
@@ -94,6 +94,38 @@ B is considered the exact value."
94 (apply #'color-xyz-to-xyy (lcms-temp->white-point 7504)) 94 (apply #'color-xyz-to-xyy (lcms-temp->white-point 7504))
95 '(0.29902 0.31485 1.0)))) 95 '(0.29902 0.31485 1.0))))
96 96
97(ert-deftest lcms-roundtrip ()
98 "Test accuracy of converting to and from different color spaces"
99 (skip-unless (featurep 'lcms2))
100 (should
101 (let ((color '(.5 .3 .7)))
102 (lcms-triple-approx-p (lcms-jch->xyz (lcms-xyz->jch color))
103 color
104 0.0001)))
105 (should
106 (let ((color '(.8 -.2 .2)))
107 (lcms-triple-approx-p (lcms-jch->jab (lcms-jab->jch color))
108 color
109 0.0001))))
110
111(ert-deftest lcms-ciecam02-gold ()
112 "Test CIE CAM02 JCh gold values"
113 (skip-unless (featurep 'lcms2))
114 (should
115 (lcms-triple-approx-p
116 (lcms-xyz->jch '(0.1931 0.2393 0.1014)
117 '(0.9888 0.900 0.3203)
118 '(18 200 1 1.0))
119 '(48.0314 38.7789 191.0452)
120 0.02))
121 (should
122 (lcms-triple-approx-p
123 (lcms-xyz->jch '(0.1931 0.2393 0.1014)
124 '(0.9888 0.90 0.3203)
125 '(18 20 1 1.0))
126 '(47.6856 36.0527 185.3445)
127 0.09)))
128
97(ert-deftest lcms-dE-cam02-ucs-silver () 129(ert-deftest lcms-dE-cam02-ucs-silver ()
98 "Test CRI-CAM02-UCS deltaE metric values from colorspacious." 130 "Test CRI-CAM02-UCS deltaE metric values from colorspacious."
99 (skip-unless (featurep 'lcms2)) 131 (skip-unless (featurep 'lcms2))
@@ -114,4 +146,16 @@ B is considered the exact value."
114 8.503323264883667 146 8.503323264883667
115 0.04))) 147 0.04)))
116 148
149(ert-deftest lcms-jmh->cam02-ucs-silver ()
150 "Compare JCh conversion to CAM02-UCS to values from colorspacious."
151 (skip-unless (featurep 'lcms2))
152 (should
153 (lcms-triple-approx-p (lcms-jch->jab '(50 20 10))
154 '(62.96296296 16.22742674 2.86133316)
155 0.05))
156 (should
157 (lcms-triple-approx-p (lcms-jch->jab '(10 60 100))
158 '(15.88785047 -6.56546789 37.23461867)
159 0.04)))
160
117;;; lcms-tests.el ends here 161;;; lcms-tests.el ends here