glance_core/img/
iterators.rs1use rayon::{
2 iter::{IndexedParallelIterator, ParallelIterator},
3 slice::{ParallelSlice, ParallelSliceMut},
4};
5
6use super::Image;
7
8pub struct PixelIter<'a> {
9 image: &'a Image,
10 idx: usize,
11}
12
13impl<'a> Iterator for PixelIter<'a> {
14 type Item = (usize, usize, [u8; 4]);
15 fn next(&mut self) -> Option<Self::Item> {
16 if self.idx >= (self.image.width * self.image.height) as usize {
17 return None;
18 }
19 let x = self.idx % self.image.width as usize;
20 let y = self.idx / self.image.width as usize;
21 let base = self.idx * 4;
22 let px = [
23 self.image.data[base],
24 self.image.data[base + 1],
25 self.image.data[base + 2],
26 self.image.data[base + 3],
27 ];
28 self.idx += 1;
29 Some((x, y, px))
30 }
31}
32
33pub struct PixelIterMut<'a> {
34 image: &'a mut Image,
35 idx: usize,
36}
37
38impl<'a> Iterator for PixelIterMut<'a> {
39 type Item = (usize, usize, &'a mut [u8; 4]);
40 fn next(&mut self) -> Option<Self::Item> {
41 let width = self.image.width as usize;
42 let height = self.image.height as usize;
43 if self.idx >= width * height {
44 return None;
45 }
46 let x = self.idx % width;
47 let y = self.idx / width;
48 let base = self.idx * 4;
49
50 let pixel = unsafe {
52 let ptr = self.image.data.as_mut_ptr().add(base) as *mut [u8; 4];
53 &mut *ptr
54 };
55
56 self.idx += 1;
57 Some((x, y, pixel))
58 }
59}
60
61impl Image {
62 pub fn pixels(&self) -> PixelIter<'_> {
63 PixelIter {
64 image: self,
65 idx: 0,
66 }
67 }
68
69 pub fn pixels_mut(&mut self) -> PixelIterMut<'_> {
70 PixelIterMut {
71 image: self,
72 idx: 0,
73 }
74 }
75
76 pub fn par_pixels(&self) -> impl ParallelIterator<Item = (usize, usize, [u8; 4])> {
77 let width = self.width as usize;
78 self.data
79 .par_chunks_exact(4)
80 .enumerate()
81 .map(move |(idx, chunk)| {
82 let x = idx % width;
83 let y = idx / width;
84 let pixel = [chunk[0], chunk[1], chunk[2], chunk[3]];
85 (x, y, pixel)
86 })
87 }
88
89 pub fn par_pixels_mut(&mut self) -> impl ParallelIterator<Item = (usize, usize, &mut [u8; 4])> {
90 let width = self.width as usize;
91
92 self.data
93 .par_chunks_exact_mut(4)
94 .enumerate()
95 .map(move |(idx, chunk)| {
96 let x = idx % width;
97 let y = idx / width;
98
99 let pixel = unsafe { &mut *(chunk.as_mut_ptr() as *mut [u8; 4]) };
102
103 (x, y, pixel)
104 })
105 }
106}