rgb/legacy/internal/convert/
mod.rs

1use super::pixel::{ComponentSlice, ComponentMap};
2use crate::alt::{BGR, BGRA, GRB, Gray, GrayAlpha, ARGB, ABGR};
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    #[allow(deprecated)]
287    fn from(other: Gray<T>) -> Self {
288        Self {
289            r: other.0.clone(),
290            g: other.0.clone(),
291            b: other.0,
292        }
293    }
294}
295
296impl<T: Clone> From<Gray<T>> for RGBA<T, u8> {
297    #[inline(always)]
298    #[allow(deprecated)]
299    fn from(other: Gray<T>) -> Self {
300        Self {
301            r: other.0.clone(),
302            g: other.0.clone(),
303            b: other.0,
304            a: 255,
305        }
306    }
307}
308
309impl<T: Clone, A> From<GrayAlpha<T, A>> for RGBA<T, A> {
310    #[inline(always)]
311    #[allow(deprecated)]
312    fn from(other: GrayAlpha<T, A>) -> Self {
313        Self {
314            r: other.0.clone(),
315            g: other.0.clone(),
316            b: other.0,
317            a: other.1,
318        }
319    }
320}
321
322#[cfg(not(feature = "unstable-experimental"))]
323impl<T> AsRef<T> for Gray<T> {
324    #[inline(always)]
325    #[allow(deprecated)]
326    fn as_ref(&self) -> &T {
327        &self.0
328    }
329}
330
331#[cfg(not(feature = "unstable-experimental"))]
332impl<T> AsRef<[T]> for RGB<T> {
333    #[inline(always)]
334    fn as_ref(&self) -> &[T] {
335        self.as_slice()
336    }
337}
338
339#[cfg(feature = "unstable-experimental")]
340impl<T> AsRef<[T; 3]> for RGB<T> {
341    fn as_ref(&self) -> &[T; 3] {
342        unsafe { &*(self as *const Self).cast() }
343    }
344}
345
346#[cfg(not(feature = "unstable-experimental"))]
347impl<T> AsRef<[T]> for RGBA<T> {
348    #[inline(always)]
349    fn as_ref(&self) -> &[T] {
350        self.as_slice()
351    }
352}
353
354#[cfg(feature = "unstable-experimental")]
355impl<T> AsRef<[T; 4]> for RGBA<T> {
356    fn as_ref(&self) -> &[T; 4] {
357        unsafe { &*(self as *const Self).cast() }
358    }
359}
360
361impl<T> AsRef<[T; 4]> for ARGB<T> {
362    fn as_ref(&self) -> &[T; 4] {
363        unsafe { &*(self as *const Self).cast() }
364    }
365}
366
367impl<T> AsRef<[T; 4]> for BGRA<T> {
368    fn as_ref(&self) -> &[T; 4] {
369        unsafe { &*(self as *const Self).cast() }
370    }
371}
372
373impl<T> AsRef<[T; 4]> for ABGR<T> {
374    fn as_ref(&self) -> &[T; 4] {
375        unsafe { &*(self as *const Self).cast() }
376    }
377}
378
379#[cfg(not(feature = "unstable-experimental"))]
380impl<T> AsRef<T> for GrayAlpha<T> {
381    #[inline(always)]
382    #[allow(deprecated)]
383    fn as_ref(&self) -> &T {
384        &self.0
385    }
386}
387
388#[cfg(feature = "unstable-experimental")]
389impl<T> AsRef<[T; 2]> for GrayAlpha<T> {
390    fn as_ref(&self) -> &[T; 2] {
391        unsafe { &*(self as *const Self).cast() }
392    }
393}
394
395#[cfg(not(feature = "unstable-experimental"))]
396impl<T> AsMut<T> for Gray<T> {
397    #[inline(always)]
398    #[allow(deprecated)]
399    fn as_mut(&mut self) -> &mut T {
400        &mut self.0
401    }
402}
403
404#[cfg(not(feature = "unstable-experimental"))]
405impl<T> AsMut<[T]> for RGB<T> {
406    #[inline(always)]
407    fn as_mut(&mut self) -> &mut [T] {
408        self.as_mut_slice()
409    }
410}
411
412#[cfg(feature = "unstable-experimental")]
413impl<T> AsMut<[T; 3]> for RGB<T> {
414    fn as_mut(&mut self) -> &mut [T; 3] {
415        unsafe { &mut *(self as *mut Self).cast() }
416    }
417}
418
419#[cfg(not(feature = "unstable-experimental"))]
420impl<T> AsMut<[T]> for RGBA<T> {
421    #[inline(always)]
422    fn as_mut(&mut self) -> &mut [T] {
423        self.as_mut_slice()
424    }
425}
426
427#[cfg(feature = "unstable-experimental")]
428impl<T> AsMut<[T; 4]> for RGBA<T> {
429    fn as_mut(&mut self) -> &mut [T; 4] {
430        unsafe { &mut *(self as *mut Self).cast() }
431    }
432}
433
434#[cfg(not(feature = "unstable-experimental"))]
435impl<T> AsMut<T> for GrayAlpha<T> {
436    #[inline(always)]
437    #[allow(deprecated)]
438    fn as_mut(&mut self) -> &mut T {
439        &mut self.0
440    }
441}
442
443#[cfg(feature = "unstable-experimental")]
444impl<T> AsMut<[T; 2]> for GrayAlpha<T> {
445    fn as_mut(&mut self) -> &mut [T; 2] {
446        unsafe { &mut *(self as *mut Self).cast() }
447    }
448}
449
450#[test]
451fn argb_converts() {
452    let argb = ARGB { a: 0xffu8, r: 0xfa, g: 0xfb, b: 0xfc };
453    let rgba = RGBA { a: 0xffu8, r: 0xfa, g: 0xfb, b: 0xfc };
454
455    assert_eq!(RGBA::from(argb), rgba);
456    assert_eq!(ARGB::from(rgba), argb);
457    assert_eq!(rgba.rgb(), argb.rgb());
458
459    let bgra = BGRA { a: 0xffu8, r: 0x1f, g: 0x2f, b: 0x3f };
460    let abgr = ABGR { a: 0xffu8, r: 0x1f, g: 0x2f, b: 0x3f };
461
462    assert_eq!(BGRA::from(abgr), bgra);
463    assert_eq!(ABGR::from(bgra), abgr);
464}
465
466#[test]
467fn converts() {
468    assert_eq!([1,2].as_gray(), [Gray::new(1), Gray::new(2)]);
469    assert_eq!([3].as_gray_mut(), [Gray::new(3)]);
470    assert_eq!([1,2].as_gray_alpha(), [GrayAlpha::new(1, 2)]);
471    // excess bytes are ignored
472    assert_eq!([1,2,3].as_gray_alpha_mut(), [GrayAlpha::new(1, 2)]);
473    assert_eq!([1,2,3,4].as_gray_alpha_mut(), [GrayAlpha::new(1, 2), GrayAlpha::new(3, 4)]);
474
475    assert_eq!(RGBA::new(1u8,2,3,255), RGB::new(1u8,2,3).into());
476    assert_eq!(RGBA::new(1u16,2,3,65535), RGB::new(1u16,2,3).into());
477    assert_eq!(BGRA{r:1u8,g:2u8,b:3u8,a:255u8}, BGR{r:1u8,g:2u8,b:3u8}.into());
478    assert_eq!(BGRA{r:1u8,g:2u8,b:3u8,a:255u8}, RGB{r:1u8,g:2u8,b:3u8}.into());
479    assert_eq!(RGBA {r:1u8,g:2,b:3,a:4u8}, BGRA{r:1u8,g:2u8,b:3u8,a:4u8}.into());
480    assert_eq!(BGR {r:1u8,g:2,b:3u8}, RGB {r:1u8,g:2,b:3u8}.into());
481    assert_eq!(RGB {r:1u16,g:0x5678,b:0xABCDu16}, BGR {r:1u16,g:0x5678,b:0xABCDu16}.into());
482    assert_eq!(BGR {r:0x1234567u32,g:2,b:3u32}, RGB {r:0x1234567u32,g:2,b:3u32}.into());
483
484    assert_eq!(&[1u8,2,3,4], RGBA {r:1u8,g:2,b:3,a:4u8}.as_slice());
485    assert_eq!(&[1u8,2,3,4], RGBA {r:1u8,g:2,b:3,a:4u8}.as_ref());
486    assert_eq!(&[1u8,2,3], RGB {r:1u8,g:2,b:3}.as_slice());
487    assert_eq!(&[1u8,2,3], RGB {r:1u8,g:2,b:3}.as_ref());
488
489    assert_eq!(&[1u8,2,3], RGB {r:1u8,g:2,b:3}.as_mut_slice());
490    assert_eq!(&[1u8,2,3], RGB {r:1u8,g:2,b:3}.as_mut());
491}
492
493
494#[test]
495#[cfg(feature = "unstable-experimental")]
496fn as_refs() {
497    let mut r = RGBA::new(1u8,2,3,4u8);
498    assert_eq!(&[1,2,3,4], AsRef::<[u8; 4]>::as_ref(&r));
499    assert_eq!([1,2,3,4], *AsMut::<[u8; 4]>::as_mut(&mut r));
500
501    let mut r = GrayAlpha::new(1u8,4u8);
502    assert_eq!(&[1,4], AsRef::<[u8; 2]>::as_ref(&r));
503    assert_eq!([1,4], *AsMut::<[u8; 2]>::as_mut(&mut r));
504}