1use rayon::prelude::*;
2use std::marker::PhantomData;
3use std::ptr;
4use std::sync::atomic::{AtomicPtr, Ordering};
5use super::{Image, AsBytes};
6
7#[derive(Clone, Debug)]
14pub struct Chunky<T, V = Vec<u8>> {
15 bytes: V,
16 width: usize,
17 height: usize,
18 pixel: PhantomData<T>
19}
20
21impl<T, V> Image for Chunky<T, V>
22where
23 T: AsBytes,
24 V: AsRef<[u8]>
25{
26 type Pixel = T;
27
28 fn width(&self) -> usize { self.width }
29 fn height(&self) -> usize { self.height }
30
31 unsafe fn pixel(&self, x: usize, y: usize) -> Self::Pixel {
32 let off = T::width() * (y * self.width + x);
33 let mut bytes = T::Bytes::default();
34
35 ptr::copy_nonoverlapping(
36 self.bytes.as_ref().as_ptr().offset(off as isize),
37 bytes.as_mut().as_mut_ptr(),
38 T::width()
39 );
40
41 bytes.into()
42 }
43}
44
45impl<T, V> Chunky<T, V> {
46 pub fn from_bytes(width: usize, height: usize, bytes: V) -> Self
53 where
54 T: AsBytes,
55 V: AsRef<[u8]>
56 {
57 assert_eq!(bytes.as_ref().len(), width * height * T::width());
58 Self { bytes, width, height, pixel: PhantomData }
59 }
60
61 pub fn bytes(&self) -> &V {
63 &self.bytes
64 }
65
66 pub fn into_bytes(self) -> V {
68 self.bytes
69 }
70
71 pub fn bytes_mut(&mut self) -> &mut [u8]
73 where
74 V: AsMut<[u8]>
75 {
76 self.bytes.as_mut()
77 }
78
79 pub fn copy_from<U>(&mut self, frame: U)
86 where
87 T: AsBytes,
88 U: Image<Pixel = T> + Sync,
89 V: AsMut<[u8]>
90 {
91 assert_eq!(frame.width(), self.width);
92 assert_eq!(frame.height(), self.height);
93
94 let length = self.width * self.height;
95 let ptr = AtomicPtr::new(self.bytes.as_mut().as_mut_ptr());
96 let width = self.width;
97
98 (0..length).into_par_iter().for_each(|i| unsafe {
99 let ptr = ptr.load(Ordering::Relaxed);
100 let (x, y) = (i % width, i / width);
101 let bytes = T::Bytes::from(frame.pixel(x, y).into());
102
103 ptr::copy_nonoverlapping(
104 bytes.as_ref().as_ptr(),
105 ptr.offset((T::width() * i) as _),
106 T::width()
107 );
108 });
109 }
110}
111
112impl<T> Chunky<T> where T: AsBytes {
113 pub fn new<U>(frame: U) -> Self
117 where
118 U: Image<Pixel = T> + Sync
119 {
120 let (width, height) = (frame.width(), frame.height());
121 let length = width * height;
122 let size = T::width() * length;
123
124 let mut bytes = Vec::with_capacity(size);
125 unsafe { bytes.set_len(size); }
126
127 let mut chunky = Self::from_bytes(width, height, bytes);
128 chunky.copy_from(frame);
129 chunky
130 }
131}
132
133#[test]
134fn black() {
135 use super::{Function, Rgba, iter};
136
137 let (w, h) = (1920, 1080);
138 let frame = Chunky::new(
139 Function::new(w, h, |_, _| Rgba(0, 0, 0, 0))
140 );
141
142 assert_eq!(frame.width(), w);
143 assert_eq!(frame.height(), h);
144 assert_eq!(frame.bytes, vec![0; w * h * 4]);
145 assert_eq!(iter(&frame).count(), w * h);
146 assert!(iter(&frame).all(|(_, _, x)| x == Rgba(0, 0, 0, 0)));
147}