rgb/legacy/internal/convert/
mod.rs

1use super::pixel::*;
2use crate::alt::*;
3use crate::{RGB, RGBA};
4use core::{mem, slice};
5
6mod array;
7mod tuple;
8
9/// Use [`::bytemuck::cast_slice()`] instead.
10///
11/// Casts a slice of bytes into a slice of pixels, e.g. `[u8]` to `[RGB8]`.
12///
13/// See also `FromSlice`
14pub trait AsPixels<PixelType> {
15    /// Use [`::bytemuck::cast_slice()`] instead.
16    ///
17    /// Reinterpret the slice as a read-only/shared slice of pixels.
18    /// Multiple consecutive elements in the slice are intepreted as a single pixel
19    /// (depending on format, e.g. 3 for RGB, 4 for RGBA).
20    ///
21    /// Leftover elements are ignored if the slice isn't evenly divisible into pixels.
22    ///
23    /// Use this method only when the type is known from context.
24    /// See also `FromSlice`.
25    fn as_pixels(&self) -> &[PixelType];
26    /// Use [`::bytemuck::cast_slice_mut()`] instead.
27    ///
28    /// Reinterpret the slice as a mutable/exclusive slice of pixels.
29    /// Multiple consecutive elements in the slice are intepreted as a single pixel
30    /// (depending on format, e.g. 3 for RGB, 4 for RGBA).
31    ///
32    /// Leftover elements are ignored if the slice isn't evenly divisible into pixels.
33    ///
34    /// Use this method only when the type is known from context.
35    /// See also `FromSlice`.
36    fn as_pixels_mut(&mut self) -> &mut [PixelType];
37}
38
39macro_rules! as_pixels_impl {
40    ($typ:ident, $elems:expr) => {
41        impl<T> AsPixels<$typ<T>> for [T] {
42            fn as_pixels(&self) -> &[$typ<T>] {
43                unsafe {
44                    slice::from_raw_parts(self.as_ptr() as *const _, self.len() / $elems)
45                }
46            }
47
48            fn as_pixels_mut(&mut self) -> &mut [$typ<T>] {
49                unsafe {
50                    slice::from_raw_parts_mut(self.as_mut_ptr() as *mut _, self.len() / $elems)
51                }
52            }
53        }
54    };
55}
56
57as_pixels_impl! {RGB, 3}
58as_pixels_impl! {RGBA, 4}
59as_pixels_impl! {BGR, 3}
60as_pixels_impl! {BGRA, 4}
61as_pixels_impl! {GRB, 3}
62as_pixels_impl! {Gray, 1}
63as_pixels_impl! {GrayAlpha, 2}
64as_pixels_impl! {ARGB, 4}
65as_pixels_impl! {ABGR, 4}
66
67/// Use [`::bytemuck::cast_slice()`] or [`::bytemuck::from_bytes()`] to convert
68///
69/// Cast a slice of component values (bytes) as a slice of RGB/RGBA pixels
70///
71/// If there's any incomplete pixel at the end of the slice it is ignored.
72pub trait FromSlice<T: Copy> {
73    /// Reinterpert slice as RGB pixels
74    fn as_rgb(&self) -> &[RGB<T>];
75    /// Reinterpert slice as RGBA pixels
76    fn as_rgba(&self) -> &[RGBA<T>];
77    /// Reinterpert slice as alpha-first ARGB pixels
78    fn as_argb(&self) -> &[ARGB<T>];
79    /// Reinterpert mutable slice as RGB pixels
80    fn as_rgb_mut(&mut self) -> &mut [RGB<T>];
81    /// Reinterpert mutable slice as RGBA pixels
82    fn as_rgba_mut(&mut self) -> &mut [RGBA<T>];
83    /// Reinterpert mutable slice as alpha-first ARGB pixels
84    fn as_argb_mut(&mut self) -> &mut [ARGB<T>];
85
86    /// Reinterpert mutable slice as grayscale pixels
87    fn as_gray(&self) -> &[Gray<T>];
88    /// Reinterpert mutable slice as grayscale pixels with alpha
89    fn as_gray_alpha(&self) -> &[GrayAlpha<T>];
90    /// Reinterpert mutable slice as grayscale pixels
91    fn as_gray_mut(&mut self) -> &mut [Gray<T>];
92    /// Reinterpert mutable slice as grayscale pixels with alpha
93    fn as_gray_alpha_mut(&mut self) -> &mut [GrayAlpha<T>];
94
95    /// Reinterpert slice as reverse-order BGR pixels
96    fn as_bgr(&self) -> &[BGR<T>];
97    /// Reinterpert slice as reverse-order BGRA pixels
98    fn as_bgra(&self) -> &[BGRA<T>];
99    /// Reinterpert slice as reverse-order ABGR pixels
100    fn as_abgr(&self) -> &[ABGR<T>];
101    /// Reinterpert ntable slice as reverse-order BGR pixels
102    fn as_bgr_mut(&mut self) -> &mut [BGR<T>];
103    /// Reinterpert mutable slice as reverse-order alpha-last BGRA pixels
104    fn as_bgra_mut(&mut self) -> &mut [BGRA<T>];
105    /// Reinterpert mutable slice as reverse-order alpha-first ABGR pixels
106    fn as_abgr_mut(&mut self) -> &mut [ABGR<T>];
107}
108
109impl<T: Copy> FromSlice<T> for [T] {
110    #[inline]
111    fn as_rgb(&self) -> &[RGB<T>] {
112        unsafe { from_items_to_struct(self) }
113    }
114
115    #[inline]
116    fn as_rgba(&self) -> &[RGBA<T>] {
117        unsafe { from_items_to_struct(self) }
118    }
119
120    #[inline]
121    fn as_argb(&self) -> &[ARGB<T>] {
122        unsafe { from_items_to_struct(self) }
123    }
124
125    #[inline]
126    fn as_rgb_mut(&mut self) -> &mut [RGB<T>] {
127        unsafe { from_items_to_struct_mut(self) }
128    }
129
130    #[inline]
131    fn as_rgba_mut(&mut self) -> &mut [RGBA<T>] {
132        unsafe { from_items_to_struct_mut(self) }
133    }
134
135    #[inline]
136    fn as_argb_mut(&mut self) -> &mut [ARGB<T>] {
137        unsafe { from_items_to_struct_mut(self) }
138    }
139
140    #[inline]
141    fn as_gray(&self) -> &[Gray<T>] {
142        unsafe { from_items_to_struct(self) }
143    }
144
145    #[inline]
146    fn as_gray_alpha(&self) -> &[GrayAlpha<T>] {
147        unsafe { from_items_to_struct(self) }
148    }
149
150    #[inline]
151    fn as_gray_mut(&mut self) -> &mut [Gray<T>] {
152        unsafe { from_items_to_struct_mut(self) }
153    }
154
155    #[inline]
156    fn as_gray_alpha_mut(&mut self) -> &mut [GrayAlpha<T>] {
157        unsafe { from_items_to_struct_mut(self) }
158    }
159
160    #[inline]
161    fn as_bgr(&self) -> &[BGR<T>] {
162        unsafe { from_items_to_struct(self) }
163    }
164
165    #[inline]
166    fn as_abgr(&self) -> &[ABGR<T>] {
167        unsafe { from_items_to_struct(self) }
168    }
169
170    #[inline]
171    fn as_bgra(&self) -> &[BGRA<T>] {
172        unsafe { from_items_to_struct(self) }
173    }
174
175    #[inline]
176    fn as_bgr_mut(&mut self) -> &mut [BGR<T>] {
177        unsafe { from_items_to_struct_mut(self) }
178    }
179
180    #[inline]
181    fn as_bgra_mut(&mut self) -> &mut [BGRA<T>] {
182        unsafe { from_items_to_struct_mut(self) }
183    }
184
185    #[inline]
186    fn as_abgr_mut(&mut self) -> &mut [ABGR<T>] {
187        unsafe { from_items_to_struct_mut(self) }
188    }
189}
190
191#[inline(always)]
192unsafe fn from_items_to_struct<F, T>(from: &[F]) -> &[T] {
193    debug_assert_eq!(0, mem::size_of::<T>() % mem::size_of::<F>());
194    let len = from.len() / (mem::size_of::<T>() / mem::size_of::<F>());
195    slice::from_raw_parts(from.as_ptr().cast::<T>(), len)
196}
197
198#[inline(always)]
199unsafe fn from_items_to_struct_mut<F, T>(from: &mut [F]) -> &mut [T] {
200    debug_assert_eq!(0, mem::size_of::<T>() % mem::size_of::<F>());
201    let len = from.len() / (mem::size_of::<T>() / mem::size_of::<F>());
202    slice::from_raw_parts_mut(from.as_mut_ptr().cast::<T>(), len)
203}
204
205macro_rules! rgb_impl_from {
206    ($typename:ident, $from:ty, $to:ty) => {
207        impl From<$typename<$from>> for $typename<$to> {
208            #[inline(always)]
209            fn from(other: $typename<$from>) -> Self {
210                other.map(core::convert::Into::into)
211            }
212        }
213    };
214}
215
216rgb_impl_from! {RGB, u8,i16}
217rgb_impl_from! {RGB, u8,i32}
218rgb_impl_from! {RGB, u8,u16}
219rgb_impl_from! {RGB, u8,u32}
220rgb_impl_from! {RGB, u16,i32}
221rgb_impl_from! {RGB, u16,u32}
222rgb_impl_from! {RGB, u16,u64}
223
224rgb_impl_from! {RGB, u8,f32}
225rgb_impl_from! {RGB, u8,f64}
226rgb_impl_from! {RGB, u16,f32}
227rgb_impl_from! {RGB, u16,f64}
228
229rgb_impl_from! {RGB, i16,f32}
230rgb_impl_from! {RGB, i16,f64}
231
232rgb_impl_from! {RGB, i32,f64}
233rgb_impl_from! {RGB, f32,f64}
234
235rgb_impl_from! {RGBA, u16,i32}
236rgb_impl_from! {RGBA, u16,u32}
237rgb_impl_from! {RGBA, u16,u64}
238
239rgb_impl_from! {RGBA, u8,i16}
240rgb_impl_from! {RGBA, u8,u16}
241rgb_impl_from! {RGBA, u8,u32}
242rgb_impl_from! {RGBA, u8,f32}
243rgb_impl_from! {RGBA, u8,f64}
244rgb_impl_from! {RGBA, u16,f32}
245rgb_impl_from! {RGBA, u16,f64}
246
247rgb_impl_from! {RGBA, i16,f32}
248rgb_impl_from! {RGBA, i16,f64}
249
250rgb_impl_from! {RGBA, i32,f64}
251rgb_impl_from! {RGBA, f32,f64}
252
253macro_rules! reorder_impl_from {
254    (@rgb $t1:ident, $t2:ident) => {
255        reorder_impl_from!(@once $t1, $t2, r, g, b);
256        reorder_impl_from!(@once $t2, $t1, r, g, b);
257    };
258    (@rgba $t1:ident, $t2:ident) => {
259        reorder_impl_from!(@once $t1, $t2, r, g, b, a);
260        reorder_impl_from!(@once $t2, $t1, r, g, b, a);
261    };
262    (@once $t1:ident, $t2:ident, $($component:ident),+) => {
263        impl<T> From<$t1<T>> for $t2<T> where T: ::core::clone::Clone {
264            fn from(other: $t1<T>) -> Self {
265                let $t1 { $($component),+ } = other;
266                Self {
267                    $($component),+
268                }
269            }
270        }
271    }
272}
273
274reorder_impl_from!(@rgba RGBA, ARGB);
275reorder_impl_from!(@rgba ABGR, ARGB);
276reorder_impl_from!(@rgba BGRA, ARGB);
277reorder_impl_from!(@rgba BGRA, ABGR);
278
279reorder_impl_from!(@rgb RGB, BGR);
280reorder_impl_from!(@rgba BGRA, RGBA);
281reorder_impl_from!(@rgba ABGR, RGBA);
282reorder_impl_from!(@rgb RGB, GRB);
283
284impl<T: Clone> From<Gray<T>> for RGB<T> {
285    #[inline(always)]
286    fn from(other: Gray<T>) -> Self {
287        Self {
288            r: other.0.clone(),
289            g: other.0.clone(),
290            b: other.0,
291        }
292    }
293}
294
295impl<T: Clone> From<Gray<T>> for RGBA<T, u8> {
296    #[inline(always)]
297    fn from(other: Gray<T>) -> Self {
298        Self {
299            r: other.0.clone(),
300            g: other.0.clone(),
301            b: other.0,
302            a: 255,
303        }
304    }
305}
306
307impl<T: Clone, A> From<GrayAlpha<T, A>> for RGBA<T, A> {
308    #[inline(always)]
309    fn from(other: GrayAlpha<T, A>) -> Self {
310        Self {
311            r: other.0.clone(),
312            g: other.0.clone(),
313            b: other.0,
314            a: other.1,
315        }
316    }
317}
318
319#[cfg(not(feature = "unstable-experimental"))]
320impl<T> AsRef<T> for Gray<T> {
321    #[inline(always)]
322    fn as_ref(&self) -> &T {
323        &self.0
324    }
325}
326
327#[cfg(not(feature = "unstable-experimental"))]
328impl<T> AsRef<[T]> for RGB<T> {
329    #[inline(always)]
330    fn as_ref(&self) -> &[T] {
331        self.as_slice()
332    }
333}
334
335#[cfg(feature = "unstable-experimental")]
336impl<T> AsRef<[T; 3]> for RGB<T> {
337    fn as_ref(&self) -> &[T; 3] {
338        unsafe { &*(self as *const Self).cast() }
339    }
340}
341
342#[cfg(not(feature = "unstable-experimental"))]
343impl<T> AsRef<[T]> for RGBA<T> {
344    #[inline(always)]
345    fn as_ref(&self) -> &[T] {
346        self.as_slice()
347    }
348}
349
350#[cfg(feature = "unstable-experimental")]
351impl<T> AsRef<[T; 4]> for RGBA<T> {
352    fn as_ref(&self) -> &[T; 4] {
353        unsafe { &*(self as *const Self).cast() }
354    }
355}
356
357impl<T> AsRef<[T; 4]> for ARGB<T> {
358    fn as_ref(&self) -> &[T; 4] {
359        unsafe { &*(self as *const Self).cast() }
360    }
361}
362
363impl<T> AsRef<[T; 4]> for BGRA<T> {
364    fn as_ref(&self) -> &[T; 4] {
365        unsafe { &*(self as *const Self).cast() }
366    }
367}
368
369impl<T> AsRef<[T; 4]> for ABGR<T> {
370    fn as_ref(&self) -> &[T; 4] {
371        unsafe { &*(self as *const Self).cast() }
372    }
373}
374
375#[cfg(not(feature = "unstable-experimental"))]
376impl<T> AsRef<T> for GrayAlpha<T> {
377    #[inline(always)]
378    fn as_ref(&self) -> &T {
379        &self.0
380    }
381}
382
383#[cfg(feature = "unstable-experimental")]
384impl<T> AsRef<[T; 2]> for GrayAlpha<T> {
385    fn as_ref(&self) -> &[T; 2] {
386        unsafe { &*(self as *const Self).cast() }
387    }
388}
389
390#[cfg(not(feature = "unstable-experimental"))]
391impl<T> AsMut<T> for Gray<T> {
392    #[inline(always)]
393    fn as_mut(&mut self) -> &mut T {
394        &mut self.0
395    }
396}
397
398#[cfg(not(feature = "unstable-experimental"))]
399impl<T> AsMut<[T]> for RGB<T> {
400    #[inline(always)]
401    fn as_mut(&mut self) -> &mut [T] {
402        self.as_mut_slice()
403    }
404}
405
406#[cfg(feature = "unstable-experimental")]
407impl<T> AsMut<[T; 3]> for RGB<T> {
408    fn as_mut(&mut self) -> &mut [T; 3] {
409        unsafe { &mut *(self as *mut Self).cast() }
410    }
411}
412
413#[cfg(not(feature = "unstable-experimental"))]
414impl<T> AsMut<[T]> for RGBA<T> {
415    #[inline(always)]
416    fn as_mut(&mut self) -> &mut [T] {
417        self.as_mut_slice()
418    }
419}
420
421#[cfg(feature = "unstable-experimental")]
422impl<T> AsMut<[T; 4]> for RGBA<T> {
423    fn as_mut(&mut self) -> &mut [T; 4] {
424        unsafe { &mut *(self as *mut Self).cast() }
425    }
426}
427
428#[cfg(not(feature = "unstable-experimental"))]
429impl<T> AsMut<T> for GrayAlpha<T> {
430    #[inline(always)]
431    fn as_mut(&mut self) -> &mut T {
432        &mut self.0
433    }
434}
435
436#[cfg(feature = "unstable-experimental")]
437impl<T> AsMut<[T; 2]> for GrayAlpha<T> {
438    fn as_mut(&mut self) -> &mut [T; 2] {
439        unsafe { &mut *(self as *mut Self).cast() }
440    }
441}
442
443#[test]
444fn argb_converts() {
445    let argb = ARGB { a: 0xffu8, r: 0xfa, g: 0xfb, b: 0xfc };
446    let rgba = RGBA { a: 0xffu8, r: 0xfa, g: 0xfb, b: 0xfc };
447
448    assert_eq!(RGBA::from(argb), rgba);
449    assert_eq!(ARGB::from(rgba), argb);
450    assert_eq!(rgba.rgb(), argb.rgb());
451
452    let bgra = BGRA { a: 0xffu8, r: 0x1f, g: 0x2f, b: 0x3f };
453    let abgr = ABGR { a: 0xffu8, r: 0x1f, g: 0x2f, b: 0x3f };
454
455    assert_eq!(BGRA::from(abgr), bgra);
456    assert_eq!(ABGR::from(bgra), abgr);
457}
458
459#[test]
460fn converts() {
461    assert_eq!([1,2].as_gray(), [Gray::new(1), Gray::new(2)]);
462    assert_eq!([3].as_gray_mut(), [Gray::new(3)]);
463    assert_eq!([1,2].as_gray_alpha(), [GrayAlpha::new(1, 2)]);
464    // excess bytes are ignored
465    assert_eq!([1,2,3].as_gray_alpha_mut(), [GrayAlpha::new(1, 2)]);
466    assert_eq!([1,2,3,4].as_gray_alpha_mut(), [GrayAlpha::new(1, 2), GrayAlpha::new(3, 4)]);
467
468    assert_eq!(RGBA::new(1u8,2,3,255), RGB::new(1u8,2,3).into());
469    assert_eq!(RGBA::new(1u16,2,3,65535), RGB::new(1u16,2,3).into());
470    assert_eq!(BGRA{r:1u8,g:2u8,b:3u8,a:255u8}, BGR{r:1u8,g:2u8,b:3u8}.into());
471    assert_eq!(BGRA{r:1u8,g:2u8,b:3u8,a:255u8}, RGB{r:1u8,g:2u8,b:3u8}.into());
472    assert_eq!(RGBA {r:1u8,g:2,b:3,a:4u8}, BGRA{r:1u8,g:2u8,b:3u8,a:4u8}.into());
473    assert_eq!(BGR {r:1u8,g:2,b:3u8}, RGB {r:1u8,g:2,b:3u8}.into());
474    assert_eq!(RGB {r:1u16,g:0x5678,b:0xABCDu16}, BGR {r:1u16,g:0x5678,b:0xABCDu16}.into());
475    assert_eq!(BGR {r:0x1234567u32,g:2,b:3u32}, RGB {r:0x1234567u32,g:2,b:3u32}.into());
476
477    assert_eq!(&[1u8,2,3,4], RGBA {r:1u8,g:2,b:3,a:4u8}.as_slice());
478    assert_eq!(&[1u8,2,3,4], RGBA {r:1u8,g:2,b:3,a:4u8}.as_ref());
479    assert_eq!(&[1u8,2,3], RGB {r:1u8,g:2,b:3}.as_slice());
480    assert_eq!(&[1u8,2,3], RGB {r:1u8,g:2,b:3}.as_ref());
481
482    assert_eq!(&[1u8,2,3], RGB {r:1u8,g:2,b:3}.as_mut_slice());
483    assert_eq!(&[1u8,2,3], RGB {r:1u8,g:2,b:3}.as_mut());
484}
485
486
487#[test]
488#[cfg(feature = "unstable-experimental")]
489fn as_refs() {
490    let mut r = RGBA::new(1u8,2,3,4u8);
491    assert_eq!(&[1,2,3,4], AsRef::<[u8; 4]>::as_ref(&r));
492    assert_eq!([1,2,3,4], *AsMut::<[u8; 4]>::as_mut(&mut r));
493
494    let mut r = GrayAlpha::new(1u8,4u8);
495    assert_eq!(&[1,4], AsRef::<[u8; 2]>::as_ref(&r));
496    assert_eq!([1,4], *AsMut::<[u8; 2]>::as_mut(&mut r));
497}