1 | |
2 | /// Casting the struct to slices of its components |
3 | pub trait ComponentSlice<T> { |
4 | /// The components interpreted as an array, e.g. one `RGB` expands to 3 elements. |
5 | /// |
6 | /// It's implemented for individual pixels as well as slices of pixels. |
7 | fn as_slice(&self) -> &[T]; |
8 | |
9 | /// The components interpreted as a mutable array, e.g. one `RGB` expands to 3 elements. |
10 | /// |
11 | /// It's implemented for individual pixels as well as slices of pixels. |
12 | /// |
13 | /// If you get an error when calling this on an array, add `[..]` |
14 | /// |
15 | /// > use of unstable library feature 'array_methods' |
16 | /// |
17 | /// ```rust,ignore |
18 | /// arr[..].as_mut_slice() |
19 | /// ``` |
20 | fn as_mut_slice(&mut self) -> &mut [T]; |
21 | } |
22 | |
23 | /// Casting a slice of `RGB/A` values to a slice of `u8` |
24 | /// |
25 | /// If instead of `RGB8` you use `RGB<MyCustomType>`, and you want to cast from/to that custom type, |
26 | /// implement the `Plain` trait for it: |
27 | /// |
28 | /// ```rust |
29 | /// # #[derive(Copy, Clone)] |
30 | /// # struct MyCustomType; |
31 | /// unsafe impl rgb::Pod for MyCustomType {} |
32 | /// unsafe impl rgb::Zeroable for MyCustomType {} |
33 | /// ``` |
34 | /// |
35 | /// Plain types are not allowed to contain struct padding, booleans, chars, enums, references or pointers. |
36 | #[cfg (feature = "as-bytes" )] |
37 | pub trait ComponentBytes<T: crate::Pod> where Self: ComponentSlice<T> { |
38 | /// The components interpreted as raw bytes, in machine's native endian. In `RGB` bytes of the red component are first. |
39 | #[inline ] |
40 | fn as_bytes(&self) -> &[u8] { |
41 | assert_ne!(0, core::mem::size_of::<T>()); |
42 | let slice: &[T] = self.as_slice(); |
43 | unsafe { |
44 | core::slice::from_raw_parts(data:slice.as_ptr() as *const _, len:slice.len() * core::mem::size_of::<T>()) |
45 | } |
46 | } |
47 | |
48 | /// The components interpreted as raw bytes, in machine's native endian. In `RGB` bytes of the red component are first. |
49 | #[inline ] |
50 | fn as_bytes_mut(&mut self) -> &mut [u8] { |
51 | assert_ne!(0, core::mem::size_of::<T>()); |
52 | let slice: &mut [T] = self.as_mut_slice(); |
53 | unsafe { |
54 | core::slice::from_raw_parts_mut(data:slice.as_mut_ptr() as *mut _, len:slice.len() * core::mem::size_of::<T>()) |
55 | } |
56 | } |
57 | } |
58 | |
59 | /// Applying operation to every component |
60 | /// |
61 | /// ```rust |
62 | /// use rgb::ComponentMap; |
63 | /// # let pixel = rgb::RGB::new(0u8,0,0); |
64 | /// let inverted = pixel.map(|c| 255 - c); |
65 | /// |
66 | /// // For simple math there are Add/Sub/Mul implementations: |
67 | /// let halved = pixel.map(|c| c / 2); |
68 | /// let doubled = pixel * 2; |
69 | /// ``` |
70 | pub trait ComponentMap<DestPixel, SrcComponent, DestComponent> { |
71 | /// Convenience function (equivalent of `self.iter().map().collect()`) for applying the same formula to every component. |
72 | /// |
73 | /// Note that it returns the pixel directly, not an Interator. |
74 | fn map<Callback>(&self, f: Callback) -> DestPixel |
75 | where Callback: FnMut(SrcComponent) -> DestComponent; |
76 | } |
77 | |
78 | /// Same as `ComponentMap`, but doesn't change the alpha channel (if there's any alpha). |
79 | pub trait ColorComponentMap<DestPixel, SrcComponent, DestComponent> { |
80 | /// Convenience function for applying the same formula to every rgb/gray component, but skipping the alpha component. |
81 | /// |
82 | /// Note that it returns the pixel directly, not an Interator. |
83 | fn map_c<Callback>(&self, f: Callback) -> DestPixel |
84 | where Callback: FnMut(SrcComponent) -> DestComponent; |
85 | } |
86 | |