1use core::iter::FusedIterator;
2use core::marker::PhantomData;
3use core::num::NonZeroUsize;
4use core::slice;
5
6#[cfg(test)]
7use alloc::vec;
8
9/// Rows of the image. Call `Img.rows()` to create it.
10///
11/// Each element is a slice `width` pixels wide. Ignores padding, if there's any.
12#[derive(Debug)]
13#[must_use]
14pub struct RowsIter<'a, T> {
15 pub(crate) inner: slice::Chunks<'a, T>,
16 pub(crate) width: usize,
17}
18
19impl<'a, T: 'a> Iterator for RowsIter<'a, T> {
20 type Item = &'a [T];
21
22 #[inline]
23 fn next(&mut self) -> Option<Self::Item> {
24 match self.inner.next() {
25 Some(s) => {
26 // guaranteed during creation of chunks iterator
27 debug_assert!(s.len() >= self.width);
28 unsafe {
29 Some(s.get_unchecked(0..self.width))
30 }
31 },
32 None => None,
33 }
34 }
35
36 #[inline]
37 fn size_hint(&self) -> (usize, Option<usize>) {
38 self.inner.size_hint()
39 }
40
41 #[inline]
42 fn nth(&mut self, n: usize) -> Option<Self::Item> {
43 match self.inner.nth(n) {
44 Some(s) => {
45 // guaranteed during creation of chunks iterator
46 debug_assert!(s.len() >= self.width);
47 unsafe {
48 Some(s.get_unchecked(0..self.width))
49 }
50 },
51 None => None,
52 }
53 }
54
55 #[inline]
56 fn count(self) -> usize {
57 self.inner.count()
58 }
59}
60
61impl<'a, T> ExactSizeIterator for RowsIter<'a, T> {
62 #[inline]
63 fn len(&self) -> usize {
64 self.inner.len()
65 }
66}
67
68impl<'a, T> FusedIterator for RowsIter<'a, T> {}
69
70impl<'a, T: 'a> DoubleEndedIterator for RowsIter<'a, T> {
71 #[inline]
72 fn next_back(&mut self) -> Option<Self::Item> {
73 match self.inner.next_back() {
74 Some(s: &[T]) => {
75 // guaranteed during creation of chunks iterator
76 debug_assert!(s.len() >= self.width);
77 unsafe {
78 Some(s.get_unchecked(index:0..self.width))
79 }
80 },
81 None => None,
82 }
83 }
84}
85
86/// Rows of the image. Call `Img.rows_mut()` to create it.
87///
88/// Each element is a slice `width` pixels wide. Ignores padding, if there's any.
89#[derive(Debug)]
90#[must_use]
91pub struct RowsIterMut<'a, T> {
92 pub(crate) width: usize,
93 pub(crate) inner: slice::ChunksMut<'a, T>,
94}
95
96impl<'a, T: 'a> Iterator for RowsIterMut<'a, T> {
97 type Item = &'a mut [T];
98
99 #[inline]
100 fn next(&mut self) -> Option<Self::Item> {
101 match self.inner.next() {
102 Some(s) => Some(&mut s[0..self.width]),
103 None => None,
104 }
105 }
106
107 #[inline]
108 fn size_hint(&self) -> (usize, Option<usize>) {
109 self.inner.size_hint()
110 }
111
112 #[inline]
113 fn nth(&mut self, n: usize) -> Option<Self::Item> {
114 match self.inner.nth(n) {
115 Some(s) => Some(&mut s[0..self.width]),
116 None => None,
117 }
118 }
119
120 #[inline]
121 fn count(self) -> usize {
122 self.inner.count()
123 }
124}
125
126impl<'a, T> ExactSizeIterator for RowsIterMut<'a, T> {}
127impl<'a, T> FusedIterator for RowsIterMut<'a, T> {}
128
129impl<'a, T: 'a> DoubleEndedIterator for RowsIterMut<'a, T> {
130 #[inline]
131 fn next_back(&mut self) -> Option<Self::Item> {
132 match self.inner.next_back() {
133 Some(s: &mut [T]) => Some(&mut s[0..self.width]),
134 None => None,
135 }
136 }
137}
138
139
140/// Iterates over pixels in the (sub)image. Call `Img.pixels()` to create it.
141///
142/// Ignores padding, if there's any.
143#[must_use]
144pub struct PixelsIter<'a, T: Copy> {
145 inner: PixelsRefIter<'a, T>
146}
147
148impl<'a, T: Copy + 'a> PixelsIter<'a, T> {
149 #[inline(always)]
150 pub(crate) fn new(img: super::ImgRef<'a, T>) -> Self {
151 Self {
152 inner: PixelsRefIter::new(img)
153 }
154 }
155}
156
157impl<'a, T: Copy + 'a> Iterator for PixelsIter<'a, T> {
158 type Item = T;
159
160 #[inline(always)]
161 fn next(&mut self) -> Option<Self::Item> {
162 self.inner.next().copied()
163 }
164}
165
166impl<'a, T: Copy> ExactSizeIterator for PixelsIter<'a, T> {
167 #[inline]
168 fn len(&self) -> usize {
169 self.inner.len()
170 }
171}
172
173/// Iterates over pixels in the (sub)image. Call `Img.pixels_ref()` to create it.
174///
175/// Ignores padding, if there's any.
176#[derive(Debug)]
177#[must_use]
178pub struct PixelsRefIter<'a, T> {
179 current: *const T,
180 current_line_end: *const T,
181 rows_left: usize,
182 width: NonZeroUsize,
183 pad: usize,
184 _dat: PhantomData<&'a [T]>,
185}
186
187unsafe impl<T> Send for PixelsRefIter<'_, T> where T: Send {}
188unsafe impl<T> Sync for PixelsRefIter<'_, T> where T: Sync {}
189
190impl<'a, T: 'a> PixelsRefIter<'a, T> {
191 #[inline]
192 pub(crate) fn new(img: super::ImgRef<'a, T>) -> Self {
193 let width: NonZero = NonZeroUsize::new(img.width()).expect(msg:"width > 0");
194 let height: usize = img.height();
195 let stride: usize = img.stride();
196 assert!(stride >= width.get());
197 let pad: usize = stride - width.get();
198 debug_assert!(img.buf().len() + stride >= stride * height + width.get(),
199 "buffer len {} is less than {} (({}+{})x{})", img.buf().len(),
200 stride * height - pad, width, pad, height);
201 Self {
202 current: img.buf().as_ptr(),
203 current_line_end: img.buf()[width.get()..].as_ptr(),
204 width,
205 rows_left: height,
206 pad,
207 _dat: PhantomData,
208 }
209 }
210}
211
212impl<'a, T: 'a> Iterator for PixelsRefIter<'a, T> {
213 type Item = &'a T;
214
215 #[inline(always)]
216 fn next(&mut self) -> Option<Self::Item> {
217 unsafe {
218 if self.current >= self.current_line_end {
219 if self.rows_left <= 1 {
220 return None;
221 }
222 self.rows_left -= 1;
223 self.current = self.current_line_end.add(self.pad);
224 self.current_line_end = self.current.add(self.width.get());
225 }
226 let px = &*self.current;
227 self.current = self.current.add(1);
228 Some(px)
229 }
230 }
231
232 #[inline]
233 fn size_hint(&self) -> (usize, Option<usize>) {
234 let this_line = unsafe {
235 self.current_line_end.offset_from(self.current)
236 };
237 debug_assert!(this_line >= 0);
238 let len = this_line as usize + (self.rows_left - 1) * self.width.get();
239 (len, Some(len))
240 }
241}
242
243impl<'a, T: Copy> ExactSizeIterator for PixelsRefIter<'a, T> {
244}
245
246/// Iterates over pixels in the (sub)image. Call `Img.pixels_mut()` to create it.
247///
248/// Ignores padding, if there's any.
249#[derive(Debug)]
250#[must_use]
251pub struct PixelsIterMut<'a, T> {
252 current: *mut T,
253 current_line_end: *mut T,
254 y: usize,
255 width: NonZeroUsize,
256 pad: usize,
257 _dat: PhantomData<&'a mut [T]>,
258}
259
260unsafe impl<T> Send for PixelsIterMut<'_, T> where T: Send {}
261unsafe impl<T> Sync for PixelsIterMut<'_, T> where T: Sync {}
262
263impl<'a, T: 'a> PixelsIterMut<'a, T> {
264 #[inline]
265 pub(crate) fn new(img: &mut super::ImgRefMut<'a, T>) -> Self {
266 let width: NonZero = NonZeroUsize::new(img.width()).expect(msg:"width > 0");
267 let stride: usize = img.stride();
268 debug_assert!(!img.buf().is_empty() && img.buf().len() + stride >= stride * img.height() + width.get());
269 Self {
270 current: img.buf_mut().as_mut_ptr(),
271 current_line_end: img.buf_mut()[width.get()..].as_mut_ptr(),
272 width,
273 y: img.height(),
274 pad: stride - width.get(),
275 _dat: PhantomData,
276 }
277 }
278}
279
280impl<'a, T: 'a> Iterator for PixelsIterMut<'a, T> {
281 type Item = &'a mut T;
282
283 #[inline(always)]
284 fn next(&mut self) -> Option<Self::Item> {
285 unsafe {
286 if self.current >= self.current_line_end {
287 self.y -= 1;
288 if self.y == 0 {
289 return None;
290 }
291 self.current = self.current_line_end.add(self.pad);
292 self.current_line_end = self.current.add(self.width.get());
293 }
294 let px: &mut T = &mut *self.current;
295 self.current = self.current.add(count:1);
296 Some(px)
297 }
298 }
299}
300
301#[test]
302fn iter() {
303 let img = super::Img::new(vec![1u8, 2], 1, 2);
304 let mut it = img.pixels();
305 assert_eq!(Some(1), it.next());
306 assert_eq!(Some(2), it.next());
307 assert_eq!(None, it.next());
308
309 let buf = vec![1u8; (16 + 3) * (8 + 1)];
310 for width in 1..16 {
311 for height in 1..8 {
312 for pad in 0..3 {
313 let stride = width + pad;
314 let img = super::Img::new_stride(&buf[..stride * height + stride - width], width, height, stride);
315 assert_eq!(width * height, img.pixels().map(|a| a as usize).sum(), "{}x{}", width, height);
316 assert_eq!(width * height, img.pixels().count(), "{}x{}", width, height);
317 assert_eq!(height, img.rows().count());
318
319 let mut iter1 = img.pixels();
320 let mut left = width * height;
321 while let Some(_px) = iter1.next() {
322 left -= 1;
323 assert_eq!(left, iter1.len());
324 }
325 assert_eq!(0, iter1.len()); iter1.next();
326 assert_eq!(0, iter1.len());
327
328 let mut iter2 = img.rows();
329 match iter2.next() {
330 Some(_) => {
331 assert_eq!(height - 1, iter2.size_hint().0);
332 assert_eq!(height - 1, iter2.filter(|_| true).count());
333 },
334 None => {
335 assert_eq!(height, 0);
336 },
337 };
338 }
339 }
340 }
341}
342