primitives/foundation/colorspace/cmyk.rs
1use super::{Color, Float};
2use std::fmt;
3
4/// Cmyk color representation
5#[derive(Clone, Copy, PartialEq, Debug)]
6pub struct CmykColor {
7 /// Cyan component
8 pub cyan: Float,
9 /// Magenta component
10 pub magenta: Float,
11 /// Yellow component
12 pub yellow: Float,
13 /// Key component
14 pub key: Float,
15}
16
17impl CmykColor {
18 /// Create new Cmyk color with parameters
19 pub fn new(cyan: Float, magenta: Float, yellow: Float, key: Float) -> Self {
20 Self {
21 cyan,
22 magenta,
23 yellow,
24 key,
25 }
26 }
27}
28
29impl fmt::Display for CmykColor {
30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31 write!(
32 f,
33 "cmyk({}%, {}%, {}%, {}%)",
34 self.cyan, self.magenta, self.yellow, self.key
35 )
36 }
37}
38
39// CMYK -> RGB
40impl From<CmykColor> for Color {
41 fn from(cmyk: CmykColor) -> Self {
42 let apply = |v| (1.0 as Float - v / 100.0) * (1.0 - cmyk.key / 100.0);
43 Color {
44 red: apply(cmyk.cyan),
45 green: apply(cmyk.magenta),
46 blue: apply(cmyk.yellow),
47 alpha: 1.,
48 }
49 }
50}
51
52// RGB -> CMYK
53impl From<Color> for CmykColor {
54 fn from(rgb: Color) -> Self {
55 let key = 1.
56 - [rgb.red, rgb.green, rgb.blue]
57 .iter()
58 .cloned()
59 .fold(Float::NAN, Float::max);
60
61 let apply = |v: Float| (((1. - v - key) / (1. - key)) * 100.).round();
62 CmykColor {
63 cyan: apply(rgb.red),
64 magenta: apply(rgb.green),
65 yellow: apply(rgb.blue),
66 key: key * 100.,
67 }
68 }
69}
70
71#[cfg(test)]
72mod test {
73 // use super::super::*;
74 // use math::round::stochastic;
75 //
76 // lazy_static! {
77 // static ref TEST_DATA: Vec<(Color, &'static str, CmykColor)> = {
78 // vec!(
79 // (Color::RGB(56, 217, 169), "#38d9a9", CmykColor::new(74.0, 0.0, 22.0, 15.0)),
80 // (Color::RGB(178, 242, 187), "#b2f2bb", CmykColor::new(26.0, 0.0, 23.0, 5.0)),
81 // (Color::RGB(230, 252, 245), "#e6fcf5", CmykColor::new(9.0, 0.0, 3.0, 1.0)),
82 // (Color::RGB(18, 184, 134), "#12b886", CmykColor::new(90.0, 0.0, 27.0, 28.0)),
83 // //(Color::RGB(___), "#______", CmykColor::new(___), HslColor::new(___)),
84 // )
85 // };
86 // }
87 //
88 // #[test]
89 // fn from_rgb() {
90 // for (color, _, expected_cmyk) in TEST_DATA.iter() {
91 // let CmykColor {
92 // cyan: actual_cyan,
93 // magenta: actual_magenta,
94 // yellow: actual_yellow,
95 // key: actual_key,
96 // } = CmykColor::from(*color);
97 //
98 // let CmykColor {
99 // cyan: expected_cyan,
100 // magenta: expected_magenta,
101 // yellow: expected_yellow,
102 // key: expected_key,
103 // } = *expected_cmyk;
104 //
105 // assert_eq!(
106 // stochastic(actual_cyan, 0), expected_cyan,
107 // "wrong cyan in cmyk conversion from {}", color.to_hex_string()
108 // );
109 // assert_eq!(
110 // stochastic(actual_magenta, 0), expected_magenta,
111 // "wrong magenta in cmyk conversion from {}", color.to_hex_string()
112 // );
113 // assert_eq!(
114 // stochastic(actual_yellow, 0), expected_yellow,
115 // "wrong yellow in cmyk conversion from {}", color.to_hex_string()
116 // );
117 // assert_eq!(
118 // stochastic(actual_key, 0), expected_key,
119 // "wrong key in cmyk conversion from {}", color.to_hex_string()
120 // );
121 // }
122 // }
123}