palette/cam16.rs
1//! Types for the CIE CAM16 color appearance model.
2//!
3//! CIE CAM16 is a color appearance model that tries to predict the appearance
4//! of a color under certain viewing conditions, as specified via the
5//! [`Parameters`] type. The [`Cam16`] type has descriptions for the CAM16
6//! attributes. The [Color appearance model page on Wikipedia][wikipedia_cam]
7//! has some history and background as well.
8//!
9//! # Converting Between XYZ and CAM16
10//!
11//! The CIE CAM16 implementation in Palette has the [`Cam16`] type and its
12//! partial variants on one side of the boundary, and [`Xyz`](crate::Xyz) on the
13//! other. Going between `Xyz` and `Cam16` requires the viewing conditions to be
14//! specified as [`Parameters`].
15//!
16//! ```
17//! use palette::{
18//! Srgb, FromColor, IntoColor,
19//! cam16::{Cam16, Parameters},
20//! };
21//!
22//! // Customize these according to the viewing conditions:
23//! let mut example_parameters = Parameters::default_static_wp(40.0);
24//!
25//! // CAM16 from sRGB, or most other color spaces:
26//! let rgb = Srgb::new(0.3f32, 0.8, 0.1);
27//! let cam16_from_rgb = Cam16::from_xyz(rgb.into_color(), example_parameters);
28//!
29//! // sRGB from CAM16, using lightness, chroma and hue by default:
30//! let rgb_from_cam16 = Srgb::from_color(cam16_from_rgb.into_xyz(example_parameters));
31//! ```
32//!
33//! For more control over the attributes to use when converting from CAM16, one
34//! of the partial CAM16 types can be used:
35//!
36//! * [`Cam16Jch`]: lightness and chroma.
37//! * [`Cam16Jmh`]: lightness and colorfulness.
38//! * [`Cam16Jsh`]: lightness and saturation.
39//! * [`Cam16Qch`]: brightness and chroma.
40//! * [`Cam16Qmh`]: brightness and colorfulness.
41//! * [`Cam16Qsh`]: brightness and saturation.
42//!
43//! Generic traits and functions can make use of the [`IntoCam16Unclamped`],
44//! [`FromCam16Unclamped`], [`Cam16IntoUnclamped`], and [`Cam16FromUnclamped`]
45//! traits. They are similar to the traits from the [`convert`][crate::convert]
46//! module and help abstracting away most of the implementation details.
47//!
48//! # The CAM16-UCS Color Space
49//!
50//! CIE CAM16 specifies a visually uniform color space that can be used for
51//! color manipulation. It's represented by the [`Cam16UcsJmh`] and
52//! [`Cam16UcsJab`] types, similar to [`Lch`][crate::Lch] and
53//! [`Lab`][crate::Lab].
54//!
55//! ```
56//! use palette::{
57//! Srgb, FromColor, IntoColor,
58//! cam16::{Cam16Jmh, Parameters, Cam16UcsJmh},
59//! };
60//!
61//! // Customize these according to the viewing conditions:
62//! let mut example_parameters = Parameters::default_static_wp(40.0);
63//!
64//! // CAM16-UCS from sRGB, or most other color spaces:
65//! let rgb = Srgb::new(0.3f32, 0.8, 0.1);
66//! let cam16 = Cam16Jmh::from_xyz(rgb.into_color(), example_parameters);
67//! let mut ucs_from_rgb = Cam16UcsJmh::from_color(cam16);
68//!
69//! // Shift the hue by 120 degrees in CAM16-UCS:
70//! ucs_from_rgb.hue += 120.0;
71//!
72//! // Convert back to sRGB under the same viewing conditions:
73//! let rgb = Srgb::from_color(Cam16Jmh::from_color(ucs_from_rgb).into_xyz(example_parameters));
74//! ```
75//!
76//! [wikipedia_cam]: https://en.wikipedia.org/wiki/Color_appearance_model
77
78pub use full::*;
79pub use parameters::*;
80pub use partial::*;
81pub use ucs_jab::{Cam16UcsJab, Cam16UcsJaba, Iter as Cam16UcsJabIter};
82pub use ucs_jmh::{Cam16UcsJmh, Cam16UcsJmha, Iter as Cam16UcsJmhIter};
83
84#[cfg(feature = "random")]
85pub use ucs_jab::UniformCam16UcsJab;
86#[cfg(feature = "random")]
87pub use ucs_jmh::UniformCam16UcsJmh;
88
89mod full;
90pub(crate) mod math;
91mod parameters;
92mod partial;
93mod ucs_jab;
94mod ucs_jmh;
95
96/// A trait for converting into a CAM16 color type from `C` without clamping.
97pub trait Cam16FromUnclamped<WpParam, C> {
98 /// The number type that's used in `parameters` when converting.
99 type Scalar;
100
101 /// Converts `color` into `Self`, using the provided parameters.
102 fn cam16_from_unclamped(color: C, parameters: BakedParameters<WpParam, Self::Scalar>) -> Self;
103}
104
105/// A trait for converting into a CAM16 color type `C` without clamping.
106pub trait IntoCam16Unclamped<WpParam, C> {
107 /// The number type that's used in `parameters` when converting.
108 type Scalar;
109
110 /// Converts `self` into `C`, using the provided parameters.
111 fn into_cam16_unclamped(self, parameters: BakedParameters<WpParam, Self::Scalar>) -> C;
112}
113
114impl<WpParam, T, U> IntoCam16Unclamped<WpParam, T> for U
115where
116 T: Cam16FromUnclamped<WpParam, U>,
117{
118 type Scalar = T::Scalar;
119
120 fn into_cam16_unclamped(self, parameters: BakedParameters<WpParam, Self::Scalar>) -> T {
121 T::cam16_from_unclamped(self, parameters)
122 }
123}
124
125/// A trait for converting from a CAM16 color type `C` without clamping.
126pub trait FromCam16Unclamped<WpParam, C> {
127 /// The number type that's used in `parameters` when converting.
128 type Scalar;
129
130 /// Converts `cam16` into `Self`, using the provided parameters.
131 fn from_cam16_unclamped(cam16: C, parameters: BakedParameters<WpParam, Self::Scalar>) -> Self;
132}
133
134/// A trait for converting from a CAM16 color type into `C` without clamping.
135pub trait Cam16IntoUnclamped<WpParam, C> {
136 /// The number type that's used in `parameters` when converting.
137 type Scalar;
138
139 /// Converts `self` into `C`, using the provided parameters.
140 fn cam16_into_unclamped(self, parameters: BakedParameters<WpParam, Self::Scalar>) -> C;
141}
142
143impl<WpParam, T, U> Cam16IntoUnclamped<WpParam, T> for U
144where
145 T: FromCam16Unclamped<WpParam, U>,
146{
147 type Scalar = T::Scalar;
148
149 fn cam16_into_unclamped(self, parameters: BakedParameters<WpParam, Self::Scalar>) -> T {
150 T::from_cam16_unclamped(self, parameters)
151 }
152}