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
9pub trait AsPixels<PixelType> {
15 fn as_pixels(&self) -> &[PixelType];
26 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
67pub trait FromSlice<T: Copy> {
73 fn as_rgb(&self) -> &[RGB<T>];
75 fn as_rgba(&self) -> &[RGBA<T>];
77 fn as_argb(&self) -> &[ARGB<T>];
79 fn as_rgb_mut(&mut self) -> &mut [RGB<T>];
81 fn as_rgba_mut(&mut self) -> &mut [RGBA<T>];
83 fn as_argb_mut(&mut self) -> &mut [ARGB<T>];
85
86 fn as_gray(&self) -> &[Gray<T>];
88 fn as_gray_alpha(&self) -> &[GrayAlpha<T>];
90 fn as_gray_mut(&mut self) -> &mut [Gray<T>];
92 fn as_gray_alpha_mut(&mut self) -> &mut [GrayAlpha<T>];
94
95 fn as_bgr(&self) -> &[BGR<T>];
97 fn as_bgra(&self) -> &[BGRA<T>];
99 fn as_abgr(&self) -> &[ABGR<T>];
101 fn as_bgr_mut(&mut self) -> &mut [BGR<T>];
103 fn as_bgra_mut(&mut self) -> &mut [BGRA<T>];
105 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 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}