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