@@ -23,11 +23,19 @@ mod math;
23
23
/// The CIE CAM16 color appearance model.
24
24
///
25
25
/// It's a set of six technically defined attributes that describe the
26
- /// appearance of a color in an environment, and it's a successor of
27
- /// [CIECAM02](https://en.wikipedia.org/wiki/CIECAM02). Not all attributes are
28
- /// needed to be known to convert _from_ CAM16, since they are correlated and
29
- /// derived from each other. This library provides a separate [`PartialCam16`]
30
- /// to make it easier to specify a minimum attribute set.
26
+ /// appearance of a color under certain viewing conditions, and it's a successor
27
+ /// of [CIECAM02](https://en.wikipedia.org/wiki/CIECAM02). The viewing
28
+ /// conditions are defined using [`Parameters`] and two set of `Cam16`
29
+ /// attributes are only really comparable if they were calculated from the same
30
+ /// set of viewing condition parameters. The implementations of
31
+ /// [`FromColor`][crate::FromColor], [`IntoColor`][crate::IntoColor], etc. use
32
+ /// `Parameters::default()` as their viewing conditions. See [`FromCam16`] and
33
+ /// [`IntoCam16`] for options with more control over the parameters.
34
+ ///
35
+ /// Not all attributes are needed to be known to convert _from_ CAM16, since
36
+ /// they are correlated and derived from each other. This library provides a
37
+ /// separate [`PartialCam16`] to make it easier to specify a minimum attribute
38
+ /// set.
31
39
#[ derive( Debug , WithAlpha , FromColorUnclamped ) ]
32
40
#[ palette(
33
41
palette_internal,
@@ -155,14 +163,14 @@ impl<Wp, T> FromColorUnclamped<Cam16<Wp, T>> for Cam16<Wp, T> {
155
163
impl < Wp , T > FromColorUnclamped < Xyz < Wp , T > > for Cam16 < Wp , T >
156
164
where
157
165
Xyz < Wp , T > : IntoCam16 < Wp , T > ,
158
- T : Real ,
166
+ BakedParameters < Wp , T > : Default ,
159
167
{
160
168
fn from_color_unclamped ( val : Xyz < Wp , T > ) -> Self {
161
- val. into_cam16 ( Parameters :: default ( ) )
169
+ val. into_cam16 ( BakedParameters :: default ( ) )
162
170
}
163
171
}
164
172
165
- /// A partial version of [`Cam16`] with only one of each kind of parameter .
173
+ /// A partial version of [`Cam16`] with only one of each kind of attribute .
166
174
///
167
175
/// This is enough information for converting CAM16 to other color spaces.
168
176
#[ derive( Debug ) ]
@@ -335,34 +343,18 @@ pub enum LuminanceType<T> {
335
343
pub trait IntoCam16 < Wp , T > {
336
344
/// Convert `self` into CAM16, with `parameters` that describe the viewing
337
345
/// conditions.
338
- fn into_cam16 ( self , parameters : Parameters < Wp , T > ) -> Cam16 < Wp , T > ;
346
+ fn into_cam16 ( self , parameters : BakedParameters < Wp , T > ) -> Cam16 < Wp , T > ;
339
347
}
340
348
341
349
impl < C , Wp , T > IntoCam16 < Wp , T > for C
342
350
where
343
351
C : IntoColorUnclamped < Xyz < Wp , T > > ,
344
- T : Real
345
- + One
346
- + Zero
347
- + Clamp
348
- + PartialCmp
349
- + Arithmetics
350
- + Powf
351
- + Sqrt
352
- + Exp
353
- + Abs
354
- + Signum
355
- + Trigonometry
356
- + RealAngle
357
- + HasBoolMask
358
- + Clone ,
359
- T :: Mask : LazySelect < T > ,
360
- Wp : WhitePoint < T > ,
352
+ T : Real + Arithmetics + Powf + Sqrt + Abs + Signum + Trigonometry + RealAngle + Clone ,
361
353
{
362
- fn into_cam16 ( self , parameters : Parameters < Wp , T > ) -> Cam16 < Wp , T > {
354
+ fn into_cam16 ( self , parameters : BakedParameters < Wp , T > ) -> Cam16 < Wp , T > {
363
355
math:: xyz_to_cam16 (
364
356
self . into_color_unclamped ( ) . with_white_point ( ) ,
365
- parameters. into_any_white_point ( ) ,
357
+ parameters. inner ,
366
358
)
367
359
. with_white_point ( )
368
360
}
@@ -372,18 +364,16 @@ where
372
364
pub trait FromCam16 < Wp , T > {
373
365
/// Convert `cam16` into `Self`, with `parameters` that describe the viewing
374
366
/// conditions.
375
- fn from_cam16 ( cam16 : PartialCam16 < Wp , T > , parameters : Parameters < Wp , T > ) -> Self ;
367
+ fn from_cam16 ( cam16 : PartialCam16 < Wp , T > , parameters : BakedParameters < Wp , T > ) -> Self ;
376
368
}
377
369
378
370
impl < C , Wp , T > FromCam16 < Wp , T > for C
379
371
where
380
372
T : Real
381
373
+ One
382
374
+ Zero
383
- + Clamp
384
375
+ Sqrt
385
376
+ Powf
386
- + Exp
387
377
+ Abs
388
378
+ Signum
389
379
+ Arithmetics
@@ -392,27 +382,32 @@ where
392
382
+ SignedAngle
393
383
+ PartialCmp
394
384
+ Clone ,
395
- T :: Mask : LazySelect < T > + LazySelect < Xyz < white_point:: Any , T > > ,
385
+ T :: Mask : LazySelect < Xyz < white_point:: Any , T > > ,
396
386
Xyz < Wp , T > : IntoColorUnclamped < C > ,
397
- Wp : WhitePoint < T > ,
398
387
{
399
- fn from_cam16 ( cam16 : PartialCam16 < Wp , T > , parameters : Parameters < Wp , T > ) -> Self {
400
- math:: cam16_to_xyz ( cam16. with_white_point ( ) , parameters. into_any_white_point ( ) )
388
+ fn from_cam16 ( cam16 : PartialCam16 < Wp , T > , parameters : BakedParameters < Wp , T > ) -> Self {
389
+ math:: cam16_to_xyz ( cam16. with_white_point ( ) , parameters. inner )
401
390
. with_white_point ( )
402
391
. into_color_unclamped ( )
403
392
}
404
393
}
405
394
406
- /// Parameters for CAM16.
395
+ /// Parameters for CAM16 that describe the viewing conditions .
407
396
///
408
397
/// These parameters describe the viewing conditions for a more accurate color
409
- /// appearance metric. The default values are used in [`FromColor`],
398
+ /// appearance metric. The CAM16 attributes and derived values are only really
399
+ /// comparable if they were calculated with the same parameters. The parameters
400
+ /// are, however, too dynamic to all be part of the type parameters of
401
+ /// [`Cam16`].
402
+ ///
403
+ /// The default values are used in [`FromColor`][crate::FromColor],
410
404
/// [`IntoColor`][crate::IntoColor], etc.
411
405
///
412
- /// See also Moroney (2000) [Usage Guidelines for CIECAM97s][moroney_2000] for more
413
- /// information and advice on how to customize these parameters.
406
+ /// See also Moroney (2000) [Usage Guidelines for CIECAM97s][moroney_2000] for
407
+ /// more information and advice on how to customize these parameters.
414
408
///
415
- /// [moroney_2000]: https://www.imaging.org/common/uploaded%20files/pdfs/Papers/2000/PICS-0-81/1611.pdf
409
+ /// [moroney_2000]:
410
+ /// https://www.imaging.org/common/uploaded%20files/pdfs/Papers/2000/PICS-0-81/1611.pdf
416
411
#[ non_exhaustive]
417
412
pub struct Parameters < Wp , T > {
418
413
/// The reference white point. Defaults to `Wp` when it implements
@@ -455,6 +450,135 @@ where
455
450
}
456
451
}
457
452
453
+ impl < T > Parameters < white_point:: Any , T > {
454
+ /// Pre-calculate parameters with no statically known reference white point.
455
+ ///
456
+ /// The default white point in this case is [`D65`], unless specified in
457
+ /// `Self::white_point`.
458
+ pub fn any_into ( self ) -> BakedParameters < white_point:: Any , T >
459
+ where
460
+ T : Real
461
+ + One
462
+ + Zero
463
+ + Clamp
464
+ + PartialCmp
465
+ + Arithmetics
466
+ + Powf
467
+ + Sqrt
468
+ + Exp
469
+ + Abs
470
+ + Signum
471
+ + Clone ,
472
+ T :: Mask : LazySelect < T > ,
473
+ {
474
+ BakedParameters :: any_from ( self )
475
+ }
476
+ }
477
+
478
+ impl < Wp , T > Clone for Parameters < Wp , T >
479
+ where
480
+ T : Clone ,
481
+ {
482
+ fn clone ( & self ) -> Self {
483
+ Self {
484
+ white_point : self . white_point . clone ( ) ,
485
+ adapting_luminance : self . adapting_luminance . clone ( ) ,
486
+ background_luminance : self . background_luminance . clone ( ) ,
487
+ surround : self . surround . clone ( ) ,
488
+ discounting : self . discounting . clone ( ) ,
489
+ }
490
+ }
491
+ }
492
+
493
+ impl < Wp , T > Copy for Parameters < Wp , T > where T : Copy { }
494
+
495
+ /// Pre-calculated variables for CAM16, that only depend on the viewing
496
+ /// conditions.
497
+ ///
498
+ /// Derived from [`Parameters`], the `BakedParameters` can be used in
499
+ /// [`FromCam16`] and [`IntoCam16`] to reduce the amount of repeated work
500
+ /// required for converting multiple colors.
501
+ pub struct BakedParameters < Wp , T > {
502
+ inner : math:: DependentParameters < T > ,
503
+ white_point : PhantomData < Wp > ,
504
+ }
505
+
506
+ impl < T > BakedParameters < white_point:: Any , T > {
507
+ /// Pre-calculate parameters with no statically known reference white point.
508
+ ///
509
+ /// The default white point in this case is [`D65`], unless specified in
510
+ /// `Parameters::white_point`.
511
+ pub fn any_from ( parameters : Parameters < white_point:: Any , T > ) -> Self
512
+ where
513
+ T : Real
514
+ + One
515
+ + Zero
516
+ + Clamp
517
+ + PartialCmp
518
+ + Arithmetics
519
+ + Powf
520
+ + Sqrt
521
+ + Exp
522
+ + Abs
523
+ + Signum
524
+ + Clone ,
525
+ T :: Mask : LazySelect < T > ,
526
+ {
527
+ Self {
528
+ inner : math:: prepare_parameters ( parameters) ,
529
+ white_point : PhantomData ,
530
+ }
531
+ }
532
+ }
533
+
534
+ impl < Wp , T > Clone for BakedParameters < Wp , T >
535
+ where
536
+ T : Clone ,
537
+ {
538
+ fn clone ( & self ) -> Self {
539
+ Self {
540
+ inner : self . inner . clone ( ) ,
541
+ white_point : PhantomData ,
542
+ }
543
+ }
544
+ }
545
+
546
+ impl < Wp , T > Copy for BakedParameters < Wp , T > where T : Copy { }
547
+
548
+ impl < Wp , T > From < Parameters < Wp , T > > for BakedParameters < Wp , T >
549
+ where
550
+ Wp : WhitePoint < T > ,
551
+ T : Real
552
+ + One
553
+ + Zero
554
+ + Clamp
555
+ + PartialCmp
556
+ + Arithmetics
557
+ + Powf
558
+ + Sqrt
559
+ + Exp
560
+ + Abs
561
+ + Signum
562
+ + Clone ,
563
+ T :: Mask : LazySelect < T > ,
564
+ {
565
+ fn from ( value : Parameters < Wp , T > ) -> Self {
566
+ Self {
567
+ inner : math:: prepare_parameters ( value. into_any_white_point ( ) ) ,
568
+ white_point : PhantomData ,
569
+ }
570
+ }
571
+ }
572
+
573
+ impl < Wp , T > Default for BakedParameters < Wp , T >
574
+ where
575
+ Parameters < Wp , T > : Default + Into < BakedParameters < Wp , T > > ,
576
+ {
577
+ fn default ( ) -> Self {
578
+ Parameters :: default ( ) . into ( )
579
+ }
580
+ }
581
+
458
582
impl < Wp , T > Parameters < Wp , T >
459
583
where
460
584
T : Real ,
@@ -481,6 +605,7 @@ where
481
605
}
482
606
483
607
/// A description of the peripheral area.
608
+ #[ derive( Clone , Copy ) ]
484
609
#[ non_exhaustive]
485
610
pub enum Surround < T > {
486
611
/// Represents a dark room, such as a movie theatre. Corresponds to a
@@ -550,6 +675,20 @@ where
550
675
}
551
676
}
552
677
678
+ impl < Wp , T > Clone for WhitePointParameter < Wp , T >
679
+ where
680
+ T : Clone ,
681
+ {
682
+ fn clone ( & self ) -> Self {
683
+ match self {
684
+ Self :: Default => Self :: Default ,
685
+ Self :: Custom ( white_point) => Self :: Custom ( white_point. clone ( ) ) ,
686
+ }
687
+ }
688
+ }
689
+
690
+ impl < Wp , T > Copy for WhitePointParameter < Wp , T > where T : Copy { }
691
+
553
692
#[ cfg( test) ]
554
693
mod test {
555
694
use crate :: { convert:: IntoColor , Srgb } ;
0 commit comments