chromashift/
lib.rs

1#![deny(warnings)]
2
3use core::fmt;
4mod a98_rgb;
5mod channels;
6mod conversion;
7mod distance;
8mod hex;
9mod hsb;
10mod hsl;
11mod hwb;
12mod lab;
13mod lch;
14mod linear_rgb;
15mod mix;
16mod named;
17mod oklab;
18mod oklch;
19mod srgb;
20#[cfg(test)]
21mod tests;
22mod wcag;
23mod xyzd50;
24mod xyzd65;
25
26pub use a98_rgb::A98Rgb;
27pub use channels::ToAlpha;
28pub use distance::ColorDistance;
29pub use hex::Hex;
30pub use hsb::Hsv;
31pub use hsl::Hsl;
32pub use hwb::Hwb;
33pub use lab::Lab;
34pub use lch::Lch;
35pub use linear_rgb::LinearRgb;
36pub use mix::{ColorMix, ColorMixPolar, HueInterpolation};
37pub use named::{Named, ToNamedError};
38pub use oklab::Oklab;
39pub use oklch::Oklch;
40pub use srgb::Srgb;
41pub use wcag::{WcagColorContrast, WcagLevel};
42pub use xyzd50::XyzD50;
43pub use xyzd65::XyzD65;
44
45#[derive(Debug, Clone, Copy, PartialEq)]
46pub enum Color {
47	A98Rgb(A98Rgb),
48	Hsv(Hsv),
49	Hsl(Hsl),
50	Hex(Hex),
51	Hwb(Hwb),
52	Lab(Lab),
53	Lch(Lch),
54	LinearRgb(LinearRgb),
55	Named(Named),
56	Oklab(Oklab),
57	Oklch(Oklch),
58	Srgb(Srgb),
59	XyzD50(XyzD50),
60	XyzD65(XyzD65),
61}
62
63impl fmt::Display for Color {
64	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65		match self {
66			Self::A98Rgb(a) => fmt::Display::fmt(a, f),
67			Self::Hex(h) => fmt::Display::fmt(h, f),
68			Self::Hsv(h) => fmt::Display::fmt(h, f),
69			Self::Hsl(h) => fmt::Display::fmt(h, f),
70			Self::Hwb(h) => fmt::Display::fmt(h, f),
71			Self::Lab(l) => fmt::Display::fmt(l, f),
72			Self::Lch(l) => fmt::Display::fmt(l, f),
73			Self::LinearRgb(l) => fmt::Display::fmt(l, f),
74			Self::Named(n) => fmt::Display::fmt(n, f),
75			Self::Oklab(o) => fmt::Display::fmt(o, f),
76			Self::Oklch(o) => fmt::Display::fmt(o, f),
77			Self::Srgb(s) => fmt::Display::fmt(s, f),
78			Self::XyzD50(x) => fmt::Display::fmt(x, f),
79			Self::XyzD65(x) => fmt::Display::fmt(x, f),
80		}
81	}
82}
83
84impl ToAlpha for Color {
85	fn to_alpha(&self) -> f32 {
86		match self {
87			Color::A98Rgb(a) => a.to_alpha(),
88			Color::Hex(h) => h.to_alpha(),
89			Color::Hsv(h) => h.to_alpha(),
90			Color::Hsl(h) => h.to_alpha(),
91			Color::Hwb(h) => h.to_alpha(),
92			Color::Lab(l) => l.to_alpha(),
93			Color::Lch(l) => l.to_alpha(),
94			Color::LinearRgb(l) => l.to_alpha(),
95			Color::Named(n) => n.to_alpha(),
96			Color::Oklab(o) => o.to_alpha(),
97			Color::Oklch(o) => o.to_alpha(),
98			Color::Srgb(s) => s.to_alpha(),
99			Color::XyzD50(x) => x.to_alpha(),
100			Color::XyzD65(x) => x.to_alpha(),
101		}
102	}
103}
104
105impl From<Color> for XyzD65 {
106	fn from(value: Color) -> Self {
107		match value {
108			Color::A98Rgb(a) => a.into(),
109			Color::Hex(h) => h.into(),
110			Color::Hsv(h) => h.into(),
111			Color::Hsl(h) => h.into(),
112			Color::Hwb(h) => h.into(),
113			Color::Lab(l) => l.into(),
114			Color::Lch(l) => l.into(),
115			Color::LinearRgb(l) => l.into(),
116			Color::Named(n) => n.into(),
117			Color::Oklab(o) => o.into(),
118			Color::Oklch(o) => o.into(),
119			Color::Srgb(s) => s.into(),
120			Color::XyzD50(x) => x.into(),
121			Color::XyzD65(x) => x,
122		}
123	}
124}
125
126pub const COLOR_EPSILON: f64 = 0.0072;
127
128pub(crate) fn round_dp(f: f64, d: u32) -> f64 {
129	let factor = 10u32.pow(d) as f64;
130	(f * factor).round() / factor
131}