rgb/legacy/internal/pixel.rs
1/// Casting the struct to slices of its components
2pub 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")]
38pub 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 = self.as_slice();
44 unsafe {
45 core::slice::from_raw_parts(slice.as_ptr().cast(), 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 = self.as_mut_slice();
54 unsafe {
55 core::slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), 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/// ```
71pub 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).
80pub 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}