1 | use crate::internal::pixel::*; |
2 | use core::ops; |
3 | use core::slice; |
4 | |
5 | #[repr (C)] |
6 | #[cfg_attr (feature = "serde" , derive(Serialize, Deserialize))] |
7 | #[derive (Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)] |
8 | /// RGB in reverse byte order |
9 | pub struct BGR<ComponentType> { |
10 | /// Blue first |
11 | pub b: ComponentType, |
12 | /// Green |
13 | pub g: ComponentType, |
14 | /// Red last |
15 | pub r: ComponentType, |
16 | } |
17 | |
18 | #[repr (C)] |
19 | #[cfg_attr (feature = "serde" , derive(Serialize, Deserialize))] |
20 | #[derive (Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)] |
21 | /// BGR+A |
22 | pub struct BGRA<ComponentType, AlphaComponentType = ComponentType> { |
23 | /// Blue first |
24 | pub b: ComponentType, |
25 | /// Green |
26 | pub g: ComponentType, |
27 | /// Red |
28 | pub r: ComponentType, |
29 | /// Alpha last |
30 | pub a: AlphaComponentType, |
31 | } |
32 | |
33 | #[cfg (feature = "argb" )] |
34 | #[repr (C)] |
35 | #[cfg_attr (feature = "serde" , derive(Serialize, Deserialize))] |
36 | #[derive (Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)] |
37 | /// A+BGR |
38 | pub struct ABGR<ComponentType, AlphaComponentType = ComponentType> { |
39 | /// Alpha first |
40 | pub a: AlphaComponentType, |
41 | /// Blue |
42 | pub b: ComponentType, |
43 | /// Green |
44 | pub g: ComponentType, |
45 | /// Red last |
46 | pub r: ComponentType, |
47 | } |
48 | |
49 | #[cfg (feature = "argb" )] |
50 | #[repr (C)] |
51 | #[cfg_attr (feature = "serde" , derive(Serialize, Deserialize))] |
52 | #[derive (Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)] |
53 | /// A+RGB |
54 | pub struct ARGB<ComponentType, AlphaComponentType = ComponentType> { |
55 | /// Alpha first |
56 | pub a: AlphaComponentType, |
57 | /// Red |
58 | pub r: ComponentType, |
59 | /// Green |
60 | pub g: ComponentType, |
61 | /// Blue last |
62 | pub b: ComponentType, |
63 | } |
64 | |
65 | /// 8-bit BGR |
66 | pub type BGR8 = BGR<u8>; |
67 | |
68 | /// 16-bit BGR in machine's native endian |
69 | pub type BGR16 = BGR<u16>; |
70 | |
71 | /// 8-bit BGRA |
72 | pub type BGRA8 = BGRA<u8>; |
73 | |
74 | /// 8-bit ABGR, alpha is first. 0 = transparent, 255 = opaque. |
75 | #[cfg (feature = "argb" )] |
76 | pub type ABGR8 = ABGR<u8>; |
77 | |
78 | /// 8-bit ARGB, alpha is first. 0 = transparent, 255 = opaque. |
79 | #[cfg (feature = "argb" )] |
80 | pub type ARGB8 = ARGB<u8>; |
81 | |
82 | /// 16-bit BGR in machine's native endian |
83 | pub type BGRA16 = BGRA<u16>; |
84 | |
85 | /// 16-bit ABGR in machine's native endian. 0 = transparent, 65535 = opaque. |
86 | #[cfg (feature = "argb" )] |
87 | pub type ABGR16 = ABGR<u16>; |
88 | |
89 | /// 16-bit ARGB in machine's native endian. 0 = transparent, 65535 = opaque. |
90 | #[cfg (feature = "argb" )] |
91 | pub type ARGB16 = ARGB<u16>; |
92 | |
93 | #[cfg (feature = "grb" )] |
94 | #[repr (C)] |
95 | #[cfg_attr (feature = "serde" , derive(Serialize, Deserialize))] |
96 | #[derive (Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)] |
97 | /// RGB with red-green swapped (may be useful for LEDs) |
98 | pub struct GRB<ComponentType> { |
99 | /// Green first |
100 | pub g: ComponentType, |
101 | /// Red |
102 | pub r: ComponentType, |
103 | /// Blue last |
104 | pub b: ComponentType, |
105 | } |
106 | |
107 | /// 8-bit GRB |
108 | #[cfg (feature = "grb" )] |
109 | pub type GRB8 = GRB<u8>; |
110 | |
111 | //////////////////////////////////////// |
112 | |
113 | #[repr (C)] |
114 | #[cfg_attr (feature = "serde" , derive(Serialize, Deserialize))] |
115 | #[derive (Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)] |
116 | /// Grayscale. Use `.0` or `*` (deref) to access the value. |
117 | pub struct Gray<ComponentType>( |
118 | /// brightness level |
119 | pub ComponentType, |
120 | ); |
121 | |
122 | #[repr (C)] |
123 | #[cfg_attr (feature = "serde" , derive(Serialize, Deserialize))] |
124 | #[derive (Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)] |
125 | /// Grayscale with alpha. Use `.0`/`.1` to access. |
126 | pub struct GrayAlpha<ComponentType, AlphaComponentType = ComponentType>( |
127 | /// brightness level |
128 | pub ComponentType, |
129 | /// alpha |
130 | pub AlphaComponentType, |
131 | ); |
132 | |
133 | #[cfg (feature = "as-bytes" )] |
134 | unsafe impl<T> crate::Pod for Gray<T> where T: crate::Pod {} |
135 | #[cfg (feature = "as-bytes" )] |
136 | unsafe impl<T, A> crate::Pod for GrayAlpha<T, A> where T: crate::Pod, A: crate::Pod {} |
137 | #[cfg (feature = "as-bytes" )] |
138 | unsafe impl<T> crate::Zeroable for Gray<T> where T: crate::Zeroable {} |
139 | #[cfg (feature = "as-bytes" )] |
140 | unsafe impl<T, A> crate::Zeroable for GrayAlpha<T, A> where T: crate::Zeroable, A: crate::Zeroable {} |
141 | |
142 | /// 8-bit gray |
143 | pub type GRAY8 = Gray<u8>; |
144 | |
145 | /// 16-bit gray in machine's native endian |
146 | pub type GRAY16 = Gray<u16>; |
147 | |
148 | /// 8-bit gray with alpha in machine's native endian |
149 | pub type GRAYA8 = GrayAlpha<u8>; |
150 | |
151 | /// 16-bit gray with alpha in machine's native endian |
152 | pub type GRAYA16 = GrayAlpha<u16>; |
153 | |
154 | impl<T> Gray<T> { |
155 | /// New grayscale pixel |
156 | #[inline (always)] |
157 | pub const fn new(brightness: T) -> Self { |
158 | Self(brightness) |
159 | } |
160 | } |
161 | |
162 | impl<T> ops::Deref for Gray<T> { |
163 | type Target = T; |
164 | #[inline (always)] |
165 | fn deref(&self) -> &T { |
166 | &self.0 |
167 | } |
168 | } |
169 | |
170 | impl<T: Copy> From<T> for Gray<T> { |
171 | #[inline (always)] |
172 | fn from(component: T) -> Self { |
173 | Gray(component) |
174 | } |
175 | } |
176 | |
177 | impl<T: Clone, A> GrayAlpha<T, A> { |
178 | /// Copy `Gray` component out of the `GrayAlpha` struct |
179 | #[inline (always)] |
180 | pub fn gray(&self) -> Gray<T> { |
181 | Gray(self.0.clone()) |
182 | } |
183 | } |
184 | |
185 | impl<T, A> GrayAlpha<T, A> { |
186 | /// New grayscale+alpha pixel |
187 | #[inline (always)] |
188 | pub const fn new(brightness: T, alpha: A) -> Self { |
189 | Self(brightness, alpha) |
190 | } |
191 | |
192 | /// Provide a mutable view of only `Gray` component (leaving out alpha). |
193 | #[inline (always)] |
194 | pub fn gray_mut(&mut self) -> &mut Gray<T> { |
195 | unsafe { |
196 | &mut *(self as *mut _ as *mut _) |
197 | } |
198 | } |
199 | } |
200 | |
201 | impl<T: Copy, A: Clone> GrayAlpha<T, A> { |
202 | /// Create a new `GrayAlpha` with the new alpha value, but same gray value |
203 | #[inline (always)] |
204 | pub fn alpha(&self, a: A) -> Self { |
205 | Self(self.0, a) |
206 | } |
207 | |
208 | /// Create a new `GrayAlpha` with a new alpha value created by the callback. |
209 | #[inline (always)] |
210 | pub fn map_alpha<F, B>(&self, f: F) -> GrayAlpha<T, B> |
211 | where F: FnOnce(A) -> B |
212 | { |
213 | GrayAlpha (self.0, f(self.1.clone())) |
214 | } |
215 | |
216 | /// Create new `GrayAlpha` with the same alpha value, but different `Gray` value |
217 | #[inline (always)] |
218 | pub fn map_gray<F, U, B>(&self, f: F) -> GrayAlpha<U, B> |
219 | where F: FnOnce(T) -> U, U: Clone, B: From<A> + Clone { |
220 | GrayAlpha(f(self.0), self.1.clone().into()) |
221 | } |
222 | } |
223 | |
224 | impl<T: Copy, B> ComponentMap<Gray<B>, T, B> for Gray<T> { |
225 | #[inline (always)] |
226 | fn map<F>(&self, mut f: F) -> Gray<B> where F: FnMut(T) -> B { |
227 | Gray(f(self.0)) |
228 | } |
229 | } |
230 | |
231 | impl<T: Copy, B> ColorComponentMap<Gray<B>, T, B> for Gray<T> { |
232 | #[inline (always)] |
233 | fn map_c<F>(&self, mut f: F) -> Gray<B> where F: FnMut(T) -> B { |
234 | Gray(f(self.0)) |
235 | } |
236 | } |
237 | |
238 | impl<T: Copy, B> ComponentMap<GrayAlpha<B>, T, B> for GrayAlpha<T> { |
239 | #[inline (always)] |
240 | fn map<F>(&self, mut f: F) -> GrayAlpha<B> |
241 | where |
242 | F: FnMut(T) -> B, |
243 | { |
244 | GrayAlpha(f(self.0), f(self.1)) |
245 | } |
246 | } |
247 | |
248 | impl<T: Copy, A: Copy, B> ColorComponentMap<GrayAlpha<B, A>, T, B> for GrayAlpha<T, A> { |
249 | #[inline (always)] |
250 | fn map_c<F>(&self, mut f: F) -> GrayAlpha<B, A> |
251 | where |
252 | F: FnMut(T) -> B, |
253 | { |
254 | GrayAlpha(f(self.0), self.1) |
255 | } |
256 | } |
257 | |
258 | impl<T> ComponentSlice<T> for GrayAlpha<T> { |
259 | #[inline (always)] |
260 | fn as_slice(&self) -> &[T] { |
261 | unsafe { |
262 | slice::from_raw_parts(self as *const Self as *const T, len:2) |
263 | } |
264 | } |
265 | |
266 | #[inline (always)] |
267 | fn as_mut_slice(&mut self) -> &mut [T] { |
268 | unsafe { |
269 | slice::from_raw_parts_mut(self as *mut Self as *mut T, len:2) |
270 | } |
271 | } |
272 | } |
273 | |
274 | impl<T> ComponentSlice<T> for [GrayAlpha<T>] { |
275 | #[inline ] |
276 | fn as_slice(&self) -> &[T] { |
277 | unsafe { |
278 | slice::from_raw_parts(self.as_ptr() as *const _, self.len() * 2) |
279 | } |
280 | } |
281 | |
282 | #[inline ] |
283 | fn as_mut_slice(&mut self) -> &mut [T] { |
284 | unsafe { |
285 | slice::from_raw_parts_mut(self.as_ptr() as *mut _, self.len() * 2) |
286 | } |
287 | } |
288 | } |
289 | |
290 | #[cfg (feature = "as-bytes" )] |
291 | impl<T: crate::Pod> ComponentBytes<T> for [GrayAlpha<T>] {} |
292 | |
293 | impl<T> ComponentSlice<T> for Gray<T> { |
294 | #[inline (always)] |
295 | fn as_slice(&self) -> &[T] { |
296 | slice::from_ref(&self.0) |
297 | } |
298 | |
299 | #[inline (always)] |
300 | fn as_mut_slice(&mut self) -> &mut [T] { |
301 | slice::from_mut(&mut self.0) |
302 | } |
303 | } |
304 | |
305 | impl<T> ComponentSlice<T> for [Gray<T>] { |
306 | #[inline ] |
307 | fn as_slice(&self) -> &[T] { |
308 | unsafe { |
309 | slice::from_raw_parts(self.as_ptr() as *const _, self.len()) |
310 | } |
311 | } |
312 | |
313 | #[inline ] |
314 | fn as_mut_slice(&mut self) -> &mut [T] { |
315 | unsafe { |
316 | slice::from_raw_parts_mut(self.as_ptr() as *mut _, self.len()) |
317 | } |
318 | } |
319 | } |
320 | |
321 | #[cfg (feature = "as-bytes" )] |
322 | impl<T: crate::Pod> ComponentBytes<T> for [Gray<T>] {} |
323 | |
324 | /// Assumes 255 is opaque |
325 | impl<T: Copy> From<Gray<T>> for GrayAlpha<T, u8> { |
326 | #[inline (always)] |
327 | fn from(other: Gray<T>) -> Self { |
328 | GrayAlpha(other.0, 0xFF) |
329 | } |
330 | } |
331 | |
332 | /// Assumes 65535 is opaque |
333 | impl<T: Copy> From<Gray<T>> for GrayAlpha<T, u16> { |
334 | #[inline (always)] |
335 | fn from(other: Gray<T>) -> Self { |
336 | GrayAlpha(other.0, 0xFFFF) |
337 | } |
338 | } |
339 | |
340 | #[test ] |
341 | fn gray() { |
342 | let rgb: crate::RGB<_> = Gray(1).into(); |
343 | assert_eq!(rgb.r, 1); |
344 | assert_eq!(rgb.g, 1); |
345 | assert_eq!(rgb.b, 1); |
346 | |
347 | let rgba: crate::RGBA<_> = Gray(1u8).into(); |
348 | assert_eq!(rgba.r, 1); |
349 | assert_eq!(rgba.g, 1); |
350 | assert_eq!(rgba.b, 1); |
351 | assert_eq!(rgba.a, 255); |
352 | |
353 | let g: GRAY8 = 200.into(); |
354 | let g = g.map(|c| c/2); |
355 | assert_eq!(110, *g + 10); |
356 | assert_eq!(110, 10 + Gray(100).as_ref()); |
357 | |
358 | let ga: GRAYA8 = GrayAlpha(1, 2); |
359 | assert_eq!(ga.gray(), Gray::new(1)); |
360 | let mut g2 = ga.clone(); |
361 | *g2.gray_mut() = Gray(3); |
362 | assert_eq!(g2.map_gray(|g| g+1), GRAYA8::new(4, 2)); |
363 | assert_eq!(g2.map(|g| g+1), GrayAlpha(4, 3)); |
364 | assert_eq!(g2.0, 3); |
365 | assert_eq!(g2.as_slice(), &[3, 2]); |
366 | assert_eq!(g2.as_mut_slice(), &[3, 2]); |
367 | assert_eq!(g2.alpha(13), GrayAlpha(3, 13)); |
368 | assert_eq!(g2.map_alpha(|x| x+3), GrayAlpha(3, 5)); |
369 | |
370 | assert_eq!((&[Gray(1u16), Gray(2)][..]).as_slice(), &[1, 2]); |
371 | assert_eq!((&[GrayAlpha(1u16, 2), GrayAlpha(3, 4)][..]).as_slice(), &[1, 2, 3, 4]); |
372 | |
373 | let rgba: crate::RGBA<_> = ga.into(); |
374 | assert_eq!(rgba.r, 1); |
375 | assert_eq!(rgba.g, 1); |
376 | assert_eq!(rgba.b, 1); |
377 | assert_eq!(rgba.a, 2); |
378 | |
379 | let ga: GRAYA16 = GrayAlpha(1,2); |
380 | let rgba: crate::RGBA<u16, u16> = ga.into(); |
381 | assert_eq!(rgba.r, 1); |
382 | assert_eq!(rgba.g, 1); |
383 | assert_eq!(rgba.b, 1); |
384 | assert_eq!(rgba.a, 2); |
385 | } |
386 | |
387 | |