1#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
10#[non_exhaustive]
11pub enum GrayExpand {
12 Broadcast,
14}
15
16#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
19#[non_exhaustive]
20pub enum AlphaPolicy {
21 DiscardIfOpaque,
23 DiscardUnchecked,
25 CompositeOnto {
27 r: u8,
29 g: u8,
31 b: u8,
33 },
34 Forbid,
36}
37
38#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
40#[non_exhaustive]
41pub enum DepthPolicy {
42 Round,
44 Truncate,
46 Forbid,
48}
49
50#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
52#[non_exhaustive]
53pub enum LumaCoefficients {
54 Bt709,
56 Bt601,
58}
59
60#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
81pub struct ConvertOptions {
82 pub gray_expand: GrayExpand,
84 pub alpha_policy: AlphaPolicy,
86 pub depth_policy: DepthPolicy,
88 pub luma: Option<LumaCoefficients>,
91}
92
93impl ConvertOptions {
94 pub const fn forbid_lossy() -> Self {
104 Self {
105 gray_expand: GrayExpand::Broadcast,
106 alpha_policy: AlphaPolicy::Forbid,
107 depth_policy: DepthPolicy::Forbid,
108 luma: None,
109 }
110 }
111
112 pub const fn permissive() -> Self {
119 Self {
120 gray_expand: GrayExpand::Broadcast,
121 alpha_policy: AlphaPolicy::DiscardIfOpaque,
122 depth_policy: DepthPolicy::Round,
123 luma: Some(LumaCoefficients::Bt709),
124 }
125 }
126
127 pub const fn with_alpha_policy(mut self, policy: AlphaPolicy) -> Self {
129 self.alpha_policy = policy;
130 self
131 }
132
133 pub const fn with_depth_policy(mut self, policy: DepthPolicy) -> Self {
135 self.depth_policy = policy;
136 self
137 }
138
139 pub const fn with_gray_expand(mut self, expand: GrayExpand) -> Self {
141 self.gray_expand = expand;
142 self
143 }
144
145 pub const fn with_luma(mut self, luma: Option<LumaCoefficients>) -> Self {
149 self.luma = luma;
150 self
151 }
152}
153
154#[cfg(test)]
155mod tests {
156 use super::*;
157 use alloc::format;
158
159 #[test]
160 fn gray_expand_derive_traits() {
161 let a = GrayExpand::Broadcast;
162 let b = a;
163 #[allow(clippy::clone_on_copy)]
164 let c = a.clone();
165 assert_eq!(a, b);
166 assert_eq!(a, c);
167 let _ = format!("{a:?}");
168 }
169
170 #[test]
171 fn alpha_policy_variants() {
172 let discard = AlphaPolicy::DiscardIfOpaque;
173 let unchecked = AlphaPolicy::DiscardUnchecked;
174 let composite = AlphaPolicy::CompositeOnto {
175 r: 255,
176 g: 255,
177 b: 255,
178 };
179 let forbid = AlphaPolicy::Forbid;
180
181 assert_ne!(discard, unchecked);
182 assert_ne!(composite, forbid);
183
184 let composite2 = AlphaPolicy::CompositeOnto {
185 r: 255,
186 g: 255,
187 b: 255,
188 };
189 assert_eq!(composite, composite2);
190
191 let composite_diff = AlphaPolicy::CompositeOnto { r: 0, g: 0, b: 0 };
192 assert_ne!(composite, composite_diff);
193 }
194
195 #[test]
196 fn depth_policy_variants() {
197 assert_ne!(DepthPolicy::Round, DepthPolicy::Truncate);
198 assert_ne!(DepthPolicy::Round, DepthPolicy::Forbid);
199 let a = DepthPolicy::Truncate;
200 #[allow(clippy::clone_on_copy)]
201 let b = a.clone();
202 assert_eq!(a, b);
203 }
204
205 #[test]
206 fn luma_coefficients_variants() {
207 assert_ne!(LumaCoefficients::Bt709, LumaCoefficients::Bt601);
208 let a = LumaCoefficients::Bt709;
209 let b = a;
210 assert_eq!(a, b);
211 }
212
213 #[test]
214 fn convert_options_derive_traits() {
215 let opts = ConvertOptions {
216 gray_expand: GrayExpand::Broadcast,
217 alpha_policy: AlphaPolicy::DiscardUnchecked,
218 depth_policy: DepthPolicy::Round,
219 luma: Some(LumaCoefficients::Bt709),
220 };
221 #[allow(clippy::clone_on_copy)]
222 let opts2 = opts.clone();
223 assert_eq!(opts, opts2);
224 let _ = format!("{opts:?}");
225 }
226
227 #[test]
228 #[cfg(feature = "std")]
229 fn alpha_policy_hash() {
230 use core::hash::{Hash, Hasher};
231 let mut h1 = std::hash::DefaultHasher::new();
232 AlphaPolicy::Forbid.hash(&mut h1);
233 let mut h2 = std::hash::DefaultHasher::new();
234 AlphaPolicy::Forbid.hash(&mut h2);
235 assert_eq!(h1.finish(), h2.finish());
236 }
237
238 #[test]
239 #[cfg(feature = "std")]
240 fn convert_options_hash() {
241 use core::hash::{Hash, Hasher};
242 let opts = ConvertOptions {
243 gray_expand: GrayExpand::Broadcast,
244 alpha_policy: AlphaPolicy::Forbid,
245 depth_policy: DepthPolicy::Forbid,
246 luma: None,
247 };
248 let mut h = std::hash::DefaultHasher::new();
249 opts.hash(&mut h);
250 let _ = h.finish();
252 }
253}