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