1 //! In graphics code it's very common to pass `width` and `height` along with a `Vec` of pixels,
2 //! all as separate arguments. This is tedious, and can lead to errors.
3 //!
4 //! This crate is a simple struct that adds dimensions to the underlying buffer. This makes it easier to correctly keep track
5 //! of the image size and allows passing images with just one function argument instead three or four.
6 //!
7 //! Additionally, it has a concept of a `stride`, which allows defining sub-regions of images without copying,
8 //! as well as handling padding (e.g. buffers for video frames may require to be a multiple of 8, regardless of logical image size).
9 //!
10 //! For convenience, there are iterators over rows or all pixels of a (sub)image and
11 //! pixel-based indexing directly with `img[(x,y)]` (where `x`/`y` can be `u32` as well as `usize`).
12 //!
13 //! `Img<Container>` type has aliases for common uses:
14 //!
15 //! * Owned: `ImgVec<T>` → `Img<Vec<T>>`  (use it in `struct`s and return types)
16 //! * Reference: `ImgRef<T>` → `Img<&[T]>` (use it in function arguments)
17 //! * Mutable reference: `ImgRefMut<T>` → `Img<&mut [T]>`
18 //!
19 //! It is assumed that the container is [one element per pixel](https://crates.io/crates/rgb/), e.g. `Vec<RGBA>`,
20 //! and _not_ a `Vec<u8>` where 4 `u8` elements are interpreted as one pixel.
21 //!
22 use std::slice;
23 
24 mod ops;
25 pub use ops::*;
26 
27 mod iter;
28 pub use iter::*;
29 
30 /// Image owning its pixels.
31 ///
32 /// A 2D array of pixels. The pixels are oriented top-left first and rows are `stride` pixels wide.
33 ///
34 /// If size of the `buf` is larger than `width`*`height`, then any excess space is a padding (see `width_padded()`/`height_padded()`).
35 pub type ImgVec<Pixel> = Img<Vec<Pixel>>;
36 
37 /// Reference to pixels inside another image.
38 /// Pass this structure by value (i.e. `ImgRef`, not `&ImgRef`).
39 ///
40 /// Only `width` of pixels of every `stride` can be modified. The `buf` may be longer than `height`*`stride`, but the extra space should be ignored.
41 pub type ImgRef<'a, Pixel> = Img<&'a [Pixel]>;
42 
43 /// Same as `ImgRef`, but mutable
44 /// Pass this structure by value (i.e. `ImgRef`, not `&ImgRef`).
45 ///
46 pub type ImgRefMut<'a, Pixel> = Img<&'a mut [Pixel]>;
47 
48 /// Additional methods that depend on buffer size
49 ///
50 /// To use these methods you need:
51 ///
52 /// ```rust
53 /// use imgref::*;
54 /// ```
55 pub trait ImgExt<Pixel> {
56     /// Maximum possible width of the data, including the stride.
57     ///
58     /// # Panics
59     ///
60     /// This method may panic if the underlying buffer is not at least `height()*stride()` pixels large.
width_padded(&self) -> usize61     fn width_padded(&self) -> usize;
62 
63     /// Height in number of full strides.
64     /// If the underlying buffer is not an even multiple of strides, the last row is ignored.
65     ///
66     /// # Panics
67     ///
68     /// This method may panic if the underlying buffer is not at least `height()*stride()` pixels large.
height_padded(&self) -> usize69     fn height_padded(&self) -> usize;
70 
71     /// Iterate over the entire buffer as rows, including all padding
72     ///
73     /// Rows will have up to `stride` width, but the last row may be shorter.
rows_padded(&self) -> slice::Chunks<'_, Pixel>74     fn rows_padded(&self) -> slice::Chunks<'_, Pixel>;
75 }
76 
77 /// Additional methods that depend on buffer size
78 ///
79 /// To use these methods you need:
80 ///
81 /// ```rust
82 /// use imgref::*;
83 /// ```
84 pub trait ImgExtMut<Pixel> {
85     /// Iterate over the entire buffer as rows, including all padding
86     ///
87     /// Rows will have up to `stride` width, but the last row may be shorter.
rows_padded_mut(&mut self) -> slice::ChunksMut<'_, Pixel>88     fn rows_padded_mut(&mut self) -> slice::ChunksMut<'_, Pixel>;
89 }
90 
91 /// Basic struct used for both owned (alias `ImgVec`) and borrowed (alias `ImgRef`) image fragments.
92 ///
93 /// Note: the fields are `pub` only because of borrow checker limitations. Please consider them as read-only.
94 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
95 pub struct Img<Container> {
96     /// Storage for the pixels. Usually `Vec<Pixel>` or `&[Pixel]`. See `ImgVec` and `ImgRef`.
97     ///
98     /// Note that future version will make this field private. Use `.rows()` and `.pixels()` iterators where possible, or `buf()`/`buf_mut()`/`into_buf()`.
99     #[deprecated(note = "Don't access struct fields directly. Use buf(), buf_mut() or into_buf()")]
100     pub buf: Container,
101 
102     /// Number of pixels to skip in the container to advance to the next row.
103     ///
104     /// Note: pixels between `width` and `stride` may not be usable, and may not even exist in the last row.
105     #[deprecated(note = "Don't access struct fields directly. Use stride()")]
106     pub stride: usize,
107     /// Width of the image in pixels.
108     ///
109     /// Note that this isn't same as the width of the row in the `buf`, see `stride`
110     #[deprecated(note = "Don't access struct fields directly. Use width()")]
111     pub width: u32,
112     /// Height of the image in pixels.
113     #[deprecated(note = "Don't access struct fields directly. Use height()")]
114     pub height: u32,
115 }
116 
117 impl<Container> Img<Container> {
118     /// Width of the image in pixels.
119     ///
120     /// Note that this isn't same as the width of the row in image data, see `stride()`
121     #[inline(always)]
122     #[allow(deprecated)]
width(&self) -> usize123     pub fn width(&self) -> usize {self.width as usize}
124 
125     /// Height of the image in pixels.
126     #[inline(always)]
127     #[allow(deprecated)]
height(&self) -> usize128     pub fn height(&self) -> usize {self.height as usize}
129 
130     /// Number of _pixels_ to skip in the container to advance to the next row.
131     ///
132     /// Note the last row may have fewer pixels than the stride.
133     /// Some APIs use number of *bytes* for a stride. You may need to multiply this one by number of pixels.
134     #[inline(always)]
135     #[allow(deprecated)]
stride(&self) -> usize136     pub fn stride(&self) -> usize {self.stride}
137 
138     /// Immutable reference to the pixel storage. Warning: exposes stride. Use `pixels()` or `rows()` insetad.
139     ///
140     /// See also `into_contiguous_buf()`.
141     #[inline(always)]
142     #[allow(deprecated)]
buf(&self) -> &Container143     pub fn buf(&self) -> &Container {&self.buf}
144 
145     /// Mutable reference to the pixel storage. Warning: exposes stride. Use `pixels_mut()` or `rows_mut()` insetad.
146     ///
147     /// See also `into_contiguous_buf()`.
148     #[inline(always)]
149     #[allow(deprecated)]
buf_mut(&mut self) -> &mut Container150     pub fn buf_mut(&mut self) -> &mut Container {&mut self.buf}
151 
152     /// Get the pixel storage by consuming the image. Be careful about stride — see `into_contiguous_buf()` for a safe version.
153     #[inline(always)]
154     #[allow(deprecated)]
into_buf(self) -> Container155     pub fn into_buf(self) -> Container {self.buf}
156 
157     #[deprecated(note = "this was meant to be private, use new_buf() and/or rows()")]
rows_buf<'a, T: 'a>(&self, buf: &'a [T]) -> RowsIter<'a, T>158     pub fn rows_buf<'a, T: 'a>(&self, buf: &'a [T]) -> RowsIter<'a, T> {
159         self.rows_buf_internal(buf)
160     }
161 
162     #[inline]
rows_buf_internal<'a, T: 'a>(&self, buf: &'a [T]) -> RowsIter<'a, T>163     fn rows_buf_internal<'a, T: 'a>(&self, buf: &'a [T]) -> RowsIter<'a, T> {
164         let stride = self.stride();
165         debug_assert!(self.width() <= self.stride());
166         debug_assert!(buf.len() >= self.width() * self.height());
167         assert!(stride > 0);
168         let non_padded = &buf[0..stride * self.height() + self.width() - stride];
169         RowsIter {
170             width: self.width(),
171             inner: non_padded.chunks(stride),
172         }
173     }
174 }
175 
176 impl<Pixel,Container> ImgExt<Pixel> for Img<Container> where Container: AsRef<[Pixel]> {
177     #[inline(always)]
width_padded(&self) -> usize178     fn width_padded(&self) -> usize {
179         self.stride()
180     }
181 
182     #[inline(always)]
height_padded(&self) -> usize183     fn height_padded(&self) -> usize {
184         let len = self.buf().as_ref().len();
185         assert_eq!(0, len % self.stride());
186         len / self.stride()
187     }
188 
189     /// Iterate over the entire buffer as rows, including all padding
190     ///
191     /// Rows will have up to `stride` width, but the last row may be shorter.
192     #[inline(always)]
rows_padded(&self) -> slice::Chunks<'_, Pixel>193     fn rows_padded(&self) -> slice::Chunks<'_, Pixel> {
194         self.buf().as_ref().chunks(self.stride())
195     }
196 }
197 
198 impl<Pixel,Container> ImgExtMut<Pixel> for Img<Container> where Container: AsMut<[Pixel]> {
199     /// Iterate over the entire buffer as rows, including all padding
200     ///
201     /// Rows will have up to `stride` width, but the last row may be shorter.
202     ///
203     /// # Panics
204     ///
205     /// If stride is 0
206     #[inline]
207     #[must_use]
rows_padded_mut(&mut self) -> slice::ChunksMut<'_, Pixel>208     fn rows_padded_mut(&mut self) -> slice::ChunksMut<'_, Pixel> {
209         let stride = self.stride();
210         self.buf_mut().as_mut().chunks_mut(stride)
211     }
212 }
213 
214 #[inline]
sub_image(left: usize, top: usize, width: usize, height: usize, stride: usize, buf_len: usize) -> (usize, usize, usize)215 fn sub_image(left: usize, top: usize, width: usize, height: usize, stride: usize, buf_len: usize) -> (usize, usize, usize) {
216     let start = stride * top + left;
217     let full_strides_end = start + stride * height;
218     // when left > 0 and height is full, the last line is shorter than the stride
219     let end = if buf_len >= full_strides_end {
220         full_strides_end
221     } else {
222         debug_assert!(height > 0);
223         let min_strides_len = full_strides_end + width - stride;
224         debug_assert!(buf_len >= min_strides_len, "the buffer is too small to fit the subimage");
225         // if can't use full buffer, then shrink to min required (last line having exact width)
226         min_strides_len
227     };
228     (start, end, stride)
229 }
230 
231 impl<'a, T> ImgRef<'a, T> {
232     /// Make a reference for a part of the image, without copying any pixels.
233     ///
234     /// # Panics
235     ///
236     /// It will panic if sub_image is outside of the image area
237     /// (left + width must be <= container width, etc.)
238     #[inline]
239     #[must_use]
sub_image(&self, left: usize, top: usize, width: usize, height: usize) -> Self240     pub fn sub_image(&self, left: usize, top: usize, width: usize, height: usize) -> Self {
241         assert!(top + height <= self.height());
242         assert!(left + width <= self.width());
243         let (start, end, stride) = sub_image(left, top, width, height, self.stride(), self.buf().len());
244         let buf = &self.buf()[start..end];
245         Self::new_stride(buf, width, height, stride)
246     }
247 
248     #[inline]
249     #[must_use]
250     /// Iterate over whole rows of pixels as slices
251     ///
252     /// # Panics
253     ///
254     /// If stride is 0
255     ///
256     /// See also `pixels()`
rows(&self) -> RowsIter<'_, T>257     pub fn rows(&self) -> RowsIter<'_, T> {
258         self.rows_buf_internal(self.buf())
259     }
260 
261     /// Deprecated
262     ///
263     /// Note: it iterates **all** pixels in the underlying buffer, not just limited by width/height.
264     #[deprecated(note = "Size of this buffer is unpredictable. Use .rows() instead")]
iter(&self) -> std::slice::Iter<'_, T>265     pub fn iter(&self) -> std::slice::Iter<'_, T> {
266         self.buf().iter()
267     }
268 }
269 
270 impl<'a, T> ImgRefMut<'a, T> {
271     /// Turn this into immutable reference, and slice a subregion of it
272     #[inline]
273     #[allow(deprecated)]
274     #[must_use]
sub_image(&'a mut self, left: usize, top: usize, width: usize, height: usize) -> ImgRef<'a, T>275     pub fn sub_image(&'a mut self, left: usize, top: usize, width: usize, height: usize) -> ImgRef<'a, T> {
276         self.as_ref().sub_image(left, top, width, height)
277     }
278 
279     /// Trim this image without copying.
280     /// Note that mutable borrows are exclusive, so it's not possible to have more than
281     /// one mutable subimage at a time.
282     #[inline]
283     #[allow(deprecated)]
284     #[must_use]
sub_image_mut(&mut self, left: usize, top: usize, width: usize, height: usize) -> ImgRefMut<'_, T>285     pub fn sub_image_mut(&mut self, left: usize, top: usize, width: usize, height: usize) -> ImgRefMut<'_, T> {
286         assert!(top+height <= self.height());
287         assert!(left+width <= self.width());
288         let (start, end, stride) = sub_image(left, top, width, height, self.stride(), self.buf.len());
289         let buf = &mut self.buf[start..end];
290         ImgRefMut::new_stride(buf, width, height, stride)
291     }
292 
293     /// Make mutable reference immutable
294     #[inline]
295     #[must_use]
as_ref(&self) -> ImgRef<'_, T>296     pub fn as_ref(&self) -> ImgRef<'_, T> {
297         self.new_buf(self.buf().as_ref())
298     }
299 }
300 
301 impl<'a, T: Copy> ImgRef<'a, T> {
302     /// # Panics
303     ///
304     /// if width is 0
305     #[inline]
306     #[must_use]
pixels(&self) -> PixelsIter<'_, T>307     pub fn pixels(&self) -> PixelsIter<'_, T> {
308         PixelsIter::new(*self)
309     }
310 }
311 
312 impl<'a, T: Copy> ImgRefMut<'a, T> {
313     /// # Panics
314     ///
315     /// if width is 0
316     #[inline]
317     #[must_use]
pixels(&self) -> PixelsIter<'_, T>318     pub fn pixels(&self) -> PixelsIter<'_, T> {
319         PixelsIter::new(self.as_ref())
320     }
321 
322     /// # Panics
323     ///
324     /// if width is 0
325     #[inline]
326     #[must_use]
pixels_mut(&mut self) -> PixelsIterMut<'_, T>327     pub fn pixels_mut(&mut self) -> PixelsIterMut<'_, T> {
328         PixelsIterMut::new(self)
329     }
330 }
331 
332 impl<'a, T: Copy> ImgVec<T> {
333     /// # Panics
334     ///
335     /// if width is 0
336     #[inline]
337     #[must_use]
pixels(&self) -> PixelsIter<'_, T>338     pub fn pixels(&self) -> PixelsIter<'_, T> {
339         PixelsIter::new(self.as_ref())
340     }
341 
342     /// # Panics
343     ///
344     /// if width is 0
345     #[inline]
346     #[must_use]
pixels_mut(&mut self) -> PixelsIterMut<'_, T>347     pub fn pixels_mut(&mut self) -> PixelsIterMut<'_, T> {
348         PixelsIterMut::new(&mut self.as_mut())
349     }
350 }
351 
352 impl<'a, T> ImgRefMut<'a, T> {
353     /// # Panics
354     ///
355     /// if stride is 0
356     #[inline]
357     #[must_use]
rows(&self) -> RowsIter<'_, T>358     pub fn rows(&self) -> RowsIter<'_, T> {
359         self.rows_buf_internal(&self.buf()[..])
360     }
361 
362     /// # Panics
363     ///
364     /// if stride is 0
365     #[inline]
366     #[must_use]
367     #[allow(deprecated)]
rows_mut(&mut self) -> RowsIterMut<'_, T>368     pub fn rows_mut(&mut self) -> RowsIterMut<'_, T> {
369         let stride = self.stride();
370         let width = self.width();
371         let height = self.height();
372         let non_padded = &mut self.buf[0..stride * height + width - stride];
373         RowsIterMut {
374             width,
375             inner: non_padded.chunks_mut(stride),
376         }
377     }
378 }
379 
380 #[deprecated(note = "use .rows() or .pixels() iterators which are more predictable")]
381 impl<Container> IntoIterator for Img<Container> where Container: IntoIterator {
382     type Item = Container::Item;
383     type IntoIter = Container::IntoIter;
into_iter(self) -> Container::IntoIter384     fn into_iter(self) -> Container::IntoIter {
385         self.into_buf().into_iter()
386     }
387 }
388 
389 impl<T> ImgVec<T> {
390     /// Create a mutable view into a region within the image. See `sub_image()` for read-only views.
391     #[allow(deprecated)]
392     #[must_use]
sub_image_mut(&mut self, left: usize, top: usize, width: usize, height: usize) -> ImgRefMut<'_, T>393     pub fn sub_image_mut(&mut self, left: usize, top: usize, width: usize, height: usize) -> ImgRefMut<'_, T> {
394         assert!(top+height <= self.height());
395         assert!(left+width <= self.width());
396         let start = self.stride * top + left;
397         let min_buf_size = if self.height > 0 {self.stride * height + width - self.stride} else {0};
398         let buf = &mut self.buf[start .. start + min_buf_size];
399         Img::new_stride(buf, width, height, self.stride)
400     }
401 
402     #[inline]
403     #[must_use]
404     /// Make a reference for a part of the image, without copying any pixels.
sub_image(&self, left: usize, top: usize, width: usize, height: usize) -> ImgRef<'_, T>405     pub fn sub_image(&self, left: usize, top: usize, width: usize, height: usize) -> ImgRef<'_, T> {
406         self.as_ref().sub_image(left, top, width, height)
407     }
408 
409     /// Make a reference to this image to pass it to functions without giving up ownership
410     ///
411     /// The reference should be passed by value (`ImgRef`, not `&ImgRef`).
412     ///
413     /// If you need a mutable reference, see `as_mut()` and `sub_image_mut()`
414     #[inline]
415     #[must_use]
as_ref(&self) -> ImgRef<'_, T>416     pub fn as_ref(&self) -> ImgRef<'_, T> {
417         self.new_buf(self.buf().as_ref())
418     }
419 
420     /// Make a mutable reference to the entire image
421     ///
422     /// The reference should be passed by value (`ImgRefMut`, not `&mut ImgRefMut`).
423     ///
424     /// See also `sub_image_mut()` and `rows_mut()`
425     #[inline]
as_mut(&mut self) -> ImgRefMut<'_, T>426     pub fn as_mut(&mut self) -> ImgRefMut<'_, T> {
427         let width = self.width();
428         let height = self.height();
429         let stride = self.stride();
430         Img::new_stride(self.buf_mut().as_mut(), width, height, stride)
431     }
432 
433     #[deprecated(note = "Size of this buffer may be unpredictable. Use .rows() instead")]
iter(&self) -> std::slice::Iter<'_, T>434     pub fn iter(&self) -> std::slice::Iter<'_, T> {
435         self.buf().iter()
436     }
437 
438     /// Iterate over rows of the image as slices
439     ///
440     /// Each slice is guaranteed to be exactly `width` pixels wide.
441     #[inline]
442     #[must_use]
rows(&self) -> RowsIter<'_, T>443     pub fn rows(&self) -> RowsIter<'_, T> {
444         self.rows_buf_internal(self.buf())
445     }
446 
447     /// Iterate over rows of the image as mutable slices
448     ///
449     /// Each slice is guaranteed to be exactly `width` pixels wide.
450     #[inline]
451     #[must_use]
452     #[allow(deprecated)]
rows_mut(&mut self) -> RowsIterMut<'_, T>453     pub fn rows_mut(&mut self) -> RowsIterMut<'_, T> {
454         let stride = self.stride();
455         let width = self.width();
456         let height = self.height();
457         let non_padded = &mut self.buf[0..stride * height + width - stride];
458         RowsIterMut {
459             width,
460             inner: non_padded.chunks_mut(stride),
461         }
462     }
463 }
464 
465 impl<Container> Img<Container> {
466     /// Same as `new()`, except each row is located `stride` number of pixels after the previous one.
467     ///
468     /// Stride can be equal to `width` or larger. If it's larger, then pixels between end of previous row and start of the next are considered a padding, and may be ignored.
469     ///
470     /// The `Container` is usually a `Vec` or a slice.
471     #[inline]
472     #[allow(deprecated)]
new_stride(buf: Container, width: usize, height: usize, stride: usize) -> Self473     pub fn new_stride(buf: Container, width: usize, height: usize, stride: usize) -> Self {
474         assert!(stride > 0);
475         assert!(stride >= width as usize);
476         debug_assert!(height < <u32>::max_value() as usize);
477         debug_assert!(width < <u32>::max_value() as usize);
478         Img {
479             buf,
480             width: width as u32,
481             height: height as u32,
482             stride,
483         }
484     }
485 
486     /// Create new image with `Container` (which can be `Vec`, `&[]` or something else) with given `width` and `height` in pixels.
487     ///
488     /// Assumes the pixels in container are contiguous, layed out row by row with `width` pixels per row and at least `height` rows.
489     ///
490     /// If the container is larger than `width`×`height` pixels, the extra rows are a considered a padding and may be ignored.
491     #[inline]
new(buf: Container, width: usize, height: usize) -> Self492     pub fn new(buf: Container, width: usize, height: usize) -> Self {
493         Self::new_stride(buf, width, height, width)
494     }
495 }
496 
497 impl<T: Copy> Img<Vec<T>> {
498     /// Returns buffer, width, height. Guarantees that the buffer is contiguous,
499     /// i.e. it's `width*height` elements long, and `[x + y*width]` addresses each pixel.
500     ///
501     /// Efficiently performs operation in-place. For other containers use `pixels().collect()`.
502     #[allow(deprecated)]
503     #[must_use]
into_contiguous_buf(mut self) -> (Vec<T>, usize, usize)504     pub fn into_contiguous_buf(mut self) -> (Vec<T>, usize, usize) {
505         let width = self.width();
506         let height = self.height();
507         let stride = self.stride();
508         if width != stride {
509             unsafe {
510                 let buf = self.buf.as_mut_ptr();
511                 for row in 1..height {
512                     std::ptr::copy(buf.add(row * stride), buf.add(row * width), width);
513                 }
514             }
515         }
516         self.buf.truncate(width * height);
517         (self.buf, width, height)
518     }
519 }
520 
521 impl<OldContainer> Img<OldContainer> {
522     /// A convenience method for creating an image of the same size and stride, but with a new buffer.
523     #[inline]
new_buf<NewContainer, OldPixel, NewPixel>(&self, new_buf: NewContainer) -> Img<NewContainer> where NewContainer: AsRef<[NewPixel]>, OldContainer: AsRef<[OldPixel]>524     pub fn new_buf<NewContainer, OldPixel, NewPixel>(&self, new_buf: NewContainer) -> Img<NewContainer>
525         where NewContainer: AsRef<[NewPixel]>, OldContainer: AsRef<[OldPixel]> {
526         assert_eq!(self.buf().as_ref().len(), new_buf.as_ref().len());
527         Img::new_stride(new_buf, self.width(), self.height(), self.stride())
528     }
529 }
530 
531 #[cfg(test)]
532 mod tests {
533     use super::*;
534 
535     mod with_opinionated_container {
536         use super::*;
537 
538         struct IDontDeriveAnything;
539 
540         #[test]
compiles()541         fn compiles() {
542             let _ = Img::new(IDontDeriveAnything, 1, 1);
543         }
544     }
545 
546     #[test]
with_vec()547     fn with_vec() {
548         let bytes = vec![0u8;20];
549         let old = Img::new_stride(bytes, 10,2,10);
550         let _ = old.new_buf(vec![6u16;20]);
551     }
552 
553     #[test]
zero()554     fn zero() {
555         let bytes = vec![0u8];
556         let mut img = Img::new_stride(bytes,0,0,1);
557         let _ = img.sub_image(0,0,0,0);
558         let _ = img.sub_image_mut(0,0,0,0);
559         let _ = img.as_ref();
560     }
561 
562     #[test]
zero_width()563     fn zero_width() {
564         let bytes = vec![0u8];
565         let mut img = Img::new_stride(bytes,0,1,1);
566         let _ = img.sub_image(0,1,0,0);
567         let _ = img.sub_image_mut(0,0,0,1);
568     }
569 
570     #[test]
zero_height()571     fn zero_height() {
572         let bytes = vec![0u8];
573         let mut img = Img::new_stride(bytes,1,0,1);
574         assert_eq!(0, img.rows().count());
575         let _ = img.sub_image(1,0,0,0);
576         let _ = img.sub_image_mut(0,0,1,0);
577     }
578 
579     #[test]
580     #[allow(deprecated)]
with_slice()581     fn with_slice() {
582         let bytes = vec![0u8;20];
583         let _ = Img::new_stride(bytes.as_slice(), 10,2,10);
584         let vec = ImgVec::new_stride(bytes, 10,2,10);
585         for _ in vec.iter() {}
586         assert_eq!(2, vec.rows().count());
587         for _ in vec.as_ref().buf().iter() {}
588         for _ in vec {}
589     }
590 
591     #[test]
sub()592     fn sub() {
593         let img = Img::new_stride(vec![1,2,3,4,
594                        5,6,7,8,
595                        9], 3, 2, 4);
596         assert_eq!(img.buf()[img.stride()], 5);
597         assert_eq!(img.buf()[img.stride() + img.width()-1], 7);
598 
599         assert_eq!(img.pixels().count(), img.width() * img.height());
600         assert_eq!(img.pixels().sum::<i32>(), 24);
601 
602         {
603         let refimg = img.as_ref();
604         let refimg2 = refimg; // Test is Copy
605 
606         // sub-image with stride hits end of the buffer
607         let s1 = refimg.sub_image(1, 0, refimg.width()-1, refimg.height());
608         let _ = s1.sub_image(1, 0, s1.width()-1, s1.height());
609 
610         let subimg = refimg.sub_image(1, 1, 2, 1);
611         assert_eq!(subimg.pixels().count(), subimg.width() * subimg.height());
612 
613         assert_eq!(subimg.buf()[0], 6);
614         assert_eq!(subimg.stride(), refimg2.stride());
615         assert!(subimg.stride() * subimg.height() + subimg.width() - subimg.stride() <= subimg.buf().len());
616         assert_eq!(refimg.buf()[0], 1);
617         assert_eq!(1, subimg.rows().count());
618         }
619 
620         let mut img = img;
621         let mut subimg = img.sub_image_mut(1, 1, 2, 1);
622         assert_eq!(1, subimg.rows().count());
623         assert_eq!(1, subimg.rows_mut().count());
624         assert_eq!(1, subimg.rows_mut().rev().count());
625         assert_eq!(1, subimg.rows_mut().fuse().rev().count());
626         assert_eq!(subimg.buf()[0], 6);
627     }
628 
629     #[test]
rows()630     fn rows() {
631         let img = ImgVec::new_stride(vec![0u8; 10000], 10, 15, 100);
632         assert_eq!(img.height(), img.rows().count());
633         assert_eq!(img.height(), img.rows().rev().count());
634         assert_eq!(img.height(), img.rows().fuse().rev().count());
635     }
636 
637     #[test]
mut_pixels()638     fn mut_pixels() {
639         for y in 1..15 {
640             for x in 1..10 {
641                 let mut img = ImgVec::new_stride(vec![0u8; 10000], x, y, 100);
642                 assert_eq!(x*y, img.pixels_mut().count());
643                 assert_eq!(x*y, img.as_mut().pixels().count());
644                 assert_eq!(x*y, img.as_mut().pixels_mut().count());
645                 assert_eq!(x*y, img.as_mut().as_ref().pixels().count());
646             }
647         }
648     }
649 
650     #[test]
into_contiguous_buf()651     fn into_contiguous_buf() {
652         for in_h in [1, 2, 3, 38, 39, 40, 41].iter().copied() {
653             for in_w in [1, 2, 3, 120, 121].iter().copied() {
654                 for stride in [in_w, 121, 122, 166, 242, 243].iter().copied() {
655                     let img = ImgVec::new_stride((0..10000).map(|x| x as u8).collect(), in_w, in_h, stride);
656                     let pixels: Vec<_> = img.pixels().collect();
657                     let (buf, w, h) = img.into_contiguous_buf();
658                     assert_eq!(pixels, buf);
659                     assert_eq!(in_w*in_h, buf.len());
660                     assert_eq!(10000, buf.capacity());
661                     assert_eq!(in_w, w);
662                     assert_eq!(in_h, h);
663                 }
664             }
665         }
666 
667         let img = ImgVec::new((0..55*33).map(|x| x as u8).collect(), 55, 33);
668         let pixels: Vec<_> = img.pixels().collect();
669         let (buf, ..) = img.into_contiguous_buf();
670         assert_eq!(pixels, buf);
671     }
672 }
673