imgref/
lib.rs

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//!
23//!  ```rust
24//!  use imgref::*;
25//!  # fn some_image_processing_function(img: ImgRef<u8>) -> ImgVec<u8> { img.new_buf(img.buf().to_vec()) }
26//!
27//!  fn main() {
28//!      let img = Img::new(vec![0; 1000], 50, 20); // 1000 pixels of a 50×20 image
29//!
30//!      let new_image = some_image_processing_function(img.as_ref()); // Use imgvec.as_ref() instead of &imgvec for better efficiency
31//!
32//!      println!("New size is {}×{}", new_image.width(), new_image.height());
33//!      println!("And the top left pixel is {:?}", new_image[(0u32,0u32)]);
34//!
35//!      let first_row_slice = &new_image[0];
36//!
37//!      for row in new_image.rows() {
38//!          // …
39//!      }
40//!      for px in new_image.pixels() {
41//!          // …
42//!      }
43//!
44//!      // slice (x, y, width, height) by reference - no copy!
45//!      let fragment = img.sub_image(5, 5, 15, 15);
46//!
47//!      //
48//!      let (vec, width, height) = fragment.to_contiguous_buf();
49//!  }
50//!  ```
51
52#![no_std]
53
54extern crate alloc;
55#[cfg(test)]
56extern crate std;
57
58use alloc::borrow::{Cow, ToOwned};
59use alloc::vec::Vec;
60use core::slice;
61
62mod traits;
63
64mod iter;
65mod ops;
66pub use iter::*;
67
68/// Image owning its pixels.
69///
70/// A 2D array of pixels. The pixels are oriented top-left first and rows are `stride` pixels wide.
71///
72/// If size of the `buf` is larger than `width`*`height`, then any excess space is a padding (see `width_padded()`/`height_padded()`).
73pub type ImgVec<Pixel> = Img<Vec<Pixel>>;
74
75/// Reference to pixels inside another image.
76/// Pass this structure by value (i.e. `ImgRef`, not `&ImgRef`).
77///
78/// 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.
79pub type ImgRef<'slice, Pixel> = Img<&'slice [Pixel]>;
80
81/// Same as `ImgRef`, but mutable
82/// Pass this structure by value (i.e. `ImgRef`, not `&ImgRef`).
83///
84pub type ImgRefMut<'slice, Pixel> = Img<&'slice mut [Pixel]>;
85
86/// Additional methods that depend on buffer size
87///
88/// To use these methods you need:
89///
90/// ```rust
91/// use imgref::*;
92/// ```
93pub trait ImgExt<Pixel> {
94    /// Maximum possible width of the data, including the stride.
95    ///
96    /// # Panics
97    ///
98    /// This method may panic if the underlying buffer is not at least `height()*stride()` pixels large.
99    #[cfg(feature = "deprecated")]
100    fn width_padded(&self) -> usize;
101
102    /// Height in number of full strides.
103    /// If the underlying buffer is not an even multiple of strides, the last row is ignored.
104    ///
105    /// # Panics
106    ///
107    /// This method may panic if the underlying buffer is not at least `height()*stride()` pixels large.
108    #[cfg(feature = "deprecated")]
109    fn height_padded(&self) -> usize;
110
111    /// Iterate over the entire buffer as rows, including all padding
112    ///
113    /// Rows will have up to `stride` width, but the last row may be shorter.
114    #[cfg(feature = "deprecated")]
115    fn rows_padded(&self) -> slice::Chunks<'_, Pixel>;
116
117    /// Borrow the container
118    fn as_ref(&self) -> ImgRef<Pixel>;
119}
120
121/// Additional methods that depend on buffer size
122///
123/// To use these methods you need:
124///
125/// ```rust
126/// use imgref::*;
127/// ```
128pub trait ImgExtMut<Pixel> {
129    /// Iterate over the entire buffer as rows, including all padding
130    ///
131    /// Rows will have up to `stride` width, but the last row may be shorter.
132    #[cfg(feature = "deprecated")]
133    fn rows_padded_mut(&mut self) -> slice::ChunksMut<'_, Pixel>;
134
135    /// Borrow the container mutably
136    fn as_mut(&mut self) -> ImgRefMut<Pixel>;
137}
138
139/// Basic struct used for both owned (alias `ImgVec`) and borrowed (alias `ImgRef`) image fragments.
140///
141/// Note: the fields are `pub` only because of borrow checker limitations. Please consider them as read-only.
142#[derive(Debug, Copy, Clone)]
143pub struct Img<Container> {
144    /// Storage for the pixels. Usually `Vec<Pixel>` or `&[Pixel]`. See `ImgVec` and `ImgRef`.
145    ///
146    /// Note that future version will make this field private. Use `.rows()` and `.pixels()` iterators where possible, or `buf()`/`buf_mut()`/`into_buf()`.
147    #[deprecated(note = "Don't access struct fields directly. Use buf(), buf_mut() or into_buf()")]
148    #[cfg(feature = "deprecated")]
149    pub buf: Container,
150
151    #[cfg(not(feature = "deprecated"))]
152    buf: Container,
153
154    /// Number of pixels to skip in the container to advance to the next row.
155    ///
156    /// Note: pixels between `width` and `stride` may not be usable, and may not even exist in the last row.
157    #[deprecated(note = "Don't access struct fields directly. Use stride()")]
158    #[cfg(feature = "deprecated")]
159    pub stride: usize,
160
161    #[cfg(not(feature = "deprecated"))]
162    stride: usize,
163
164    /// Width of the image in pixels.
165    ///
166    /// Note that this isn't same as the width of the row in the `buf`, see `stride`
167    #[deprecated(note = "Don't access struct fields directly. Use width()")]
168    #[cfg(feature = "deprecated")]
169    pub width: u32,
170
171    #[cfg(not(feature = "deprecated"))]
172    width: u32,
173
174    /// Height of the image in pixels.
175    #[deprecated(note = "Don't access struct fields directly. Use height()")]
176    #[cfg(feature = "deprecated")]
177    pub height: u32,
178
179    #[cfg(not(feature = "deprecated"))]
180    height: u32,
181}
182
183impl<Container> Img<Container> {
184    /// Width of the image in pixels.
185    ///
186    /// Note that this isn't same as the width of the row in image data, see `stride()`
187    #[inline(always)]
188    #[allow(deprecated)]
189    pub const fn width(&self) -> usize { self.width as usize }
190
191    /// Height of the image in pixels.
192    #[inline(always)]
193    #[allow(deprecated)]
194    pub const fn height(&self) -> usize { self.height as usize }
195
196    /// Number of _pixels_ to skip in the container to advance to the next row.
197    ///
198    /// Note the last row may have fewer pixels than the stride.
199    /// Some APIs use number of *bytes* for a stride. You may need to multiply this one by number of pixels.
200    #[inline(always)]
201    #[allow(deprecated)]
202    pub const fn stride(&self) -> usize { self.stride }
203
204    /// Immutable reference to the pixel storage. Warning: exposes stride. Use `pixels()` or `rows()` instead.
205    ///
206    /// See also `into_contiguous_buf()`.
207    #[inline(always)]
208    #[allow(deprecated)]
209    pub const fn buf(&self) -> &Container { &self.buf }
210
211    /// Mutable reference to the pixel storage. Warning: exposes stride. Use `pixels_mut()` or `rows_mut()` instead.
212    ///
213    /// See also `into_contiguous_buf()`.
214    #[inline(always)]
215    #[allow(deprecated)]
216    pub fn buf_mut(&mut self) -> &mut Container { &mut self.buf }
217
218    /// Get the pixel storage by consuming the image. Be careful about stride — see `into_contiguous_buf()` for a safe version.
219    #[inline(always)]
220    #[allow(deprecated)]
221    pub fn into_buf(self) -> Container { self.buf }
222
223    #[deprecated(note = "this was meant to be private, use new_buf() and/or rows()")]
224    #[cfg(feature = "deprecated")]
225    #[doc(hidden)]
226    pub fn rows_buf<'buf, T: 'buf>(&self, buf: &'buf [T]) -> RowsIter<'buf, T> {
227        self.rows_buf_internal(buf)
228    }
229
230    #[inline]
231    #[track_caller]
232    fn rows_buf_internal<'buf, T: 'buf>(&self, buf: &'buf [T]) -> RowsIter<'buf, T> {
233        let stride = self.stride();
234        debug_assert!(self.width() <= self.stride());
235        debug_assert!(buf.len() >= self.width() * self.height());
236        assert!(stride > 0);
237        let non_padded = &buf[0..stride * self.height() + self.width() - stride];
238        RowsIter {
239            width: self.width(),
240            inner: non_padded.chunks(stride),
241        }
242    }
243}
244
245impl<Pixel,Container> ImgExt<Pixel> for Img<Container> where Container: AsRef<[Pixel]> {
246    #[inline(always)]
247    #[cfg(feature = "deprecated")]
248    fn width_padded(&self) -> usize {
249        self.stride()
250    }
251
252    #[inline(always)]
253    #[cfg(feature = "deprecated")]
254    fn height_padded(&self) -> usize {
255        let len = self.buf().as_ref().len();
256        assert_eq!(0, len % self.stride());
257        len / self.stride()
258    }
259
260    /// Iterate over the entire buffer as rows, including all padding
261    ///
262    /// Rows will have up to `stride` width, but the last row may be shorter.
263    #[inline(always)]
264    #[cfg(feature = "deprecated")]
265    fn rows_padded(&self) -> slice::Chunks<'_, Pixel> {
266        self.buf().as_ref().chunks(self.stride())
267    }
268
269    #[inline(always)]
270    #[allow(deprecated)]
271    fn as_ref(&self) -> ImgRef<Pixel> {
272        Img {
273            buf: self.buf.as_ref(),
274            width: self.width,
275            height: self.height,
276            stride: self.stride,
277        }
278    }
279}
280
281impl<Pixel,Container> ImgExtMut<Pixel> for Img<Container> where Container: AsMut<[Pixel]> {
282    /// Iterate over the entire buffer as rows, including all padding
283    ///
284    /// Rows will have up to `stride` width, but the last row may be shorter.
285    ///
286    /// # Panics
287    ///
288    /// If stride is 0
289    #[inline]
290    #[must_use]
291    #[cfg(feature = "deprecated")]
292    fn rows_padded_mut(&mut self) -> slice::ChunksMut<'_, Pixel> {
293        let stride = self.stride();
294        self.buf_mut().as_mut().chunks_mut(stride)
295    }
296
297    #[inline(always)]
298    #[allow(deprecated)]
299    fn as_mut(&mut self) -> ImgRefMut<Pixel> {
300        Img {
301            buf: self.buf.as_mut(),
302            width: self.width,
303            height: self.height,
304            stride: self.stride,
305        }
306    }
307}
308
309#[inline]
310fn sub_image(left: usize, top: usize, width: usize, height: usize, stride: usize, buf_len: usize) -> (usize, usize, usize) {
311    let start = stride * top + left;
312    let full_strides_end = start + stride * height;
313    // when left > 0 and height is full, the last line is shorter than the stride
314    let end = if buf_len >= full_strides_end {
315        full_strides_end
316    } else {
317        debug_assert!(height > 0);
318        let min_strides_len = full_strides_end + width - stride;
319        debug_assert!(buf_len >= min_strides_len, "the buffer is too small to fit the subimage");
320        // if can't use full buffer, then shrink to min required (last line having exact width)
321        min_strides_len
322    };
323    (start, end, stride)
324}
325
326impl<'slice, T> ImgRef<'slice, T> {
327    /// Make a reference for a part of the image, without copying any pixels.
328    ///
329    /// # Panics
330    ///
331    /// It will panic if sub_image is outside of the image area
332    /// (left + width must be <= container width, etc.)
333    #[inline]
334    #[must_use]
335    #[track_caller]
336    pub fn sub_image(&self, left: usize, top: usize, width: usize, height: usize) -> Self {
337        assert!(top + height <= self.height());
338        assert!(left + width <= self.width());
339        let (start, end, stride) = sub_image(left, top, width, height, self.stride(), self.buf().len());
340        let buf = &self.buf()[start..end];
341        Self::new_stride(buf, width, height, stride)
342    }
343
344    #[inline]
345    /// Iterate over whole rows of pixels as slices
346    ///
347    /// # Panics
348    ///
349    /// If stride is 0
350    ///
351    /// See also `pixels()`
352    pub fn rows(&self) -> RowsIter<'slice, T> {
353        self.rows_buf_internal(self.buf())
354    }
355
356    /// Deprecated
357    ///
358    /// Note: it iterates **all** pixels in the underlying buffer, not just limited by width/height.
359    #[deprecated(note = "Size of this buffer is unpredictable. Use .rows() instead")]
360    #[cfg(feature = "deprecated")]
361    #[doc(hidden)]
362    pub fn iter(&self) -> slice::Iter<'slice, T> {
363        self.buf().iter()
364    }
365}
366
367impl<'a, T: Clone> ImgRef<'a, T> {
368    /// Returns a reference to the buffer, width, height. Guarantees that the buffer is contiguous,
369    /// i.e. it's `width*height` elements long, and `[x + y*width]` addresses each pixel.
370    ///
371    /// It will create a copy if the buffer isn't contiguous (width != stride).
372    /// For a more efficient version, see `into_contiguous_buf()`
373    #[allow(deprecated)]
374    #[must_use]
375    pub fn to_contiguous_buf(&self) -> (Cow<'a, [T]>, usize, usize) {
376        let width = self.width();
377        let height = self.height();
378        let stride = self.stride();
379        if width == stride {
380            return (Cow::Borrowed(self.buf), width, height);
381        }
382        let mut buf = Vec::with_capacity(width * height);
383        for row in self.rows() {
384            buf.extend_from_slice(row);
385        }
386        (Cow::Owned(buf), width, height)
387    }
388}
389
390impl<'slice, T> ImgRefMut<'slice, T> {
391    /// Turn this into immutable reference, and slice a subregion of it
392    #[inline]
393    #[allow(deprecated)]
394    #[must_use]
395    pub fn sub_image(&'slice self, left: usize, top: usize, width: usize, height: usize) -> ImgRef<'slice, T> {
396        self.as_ref().sub_image(left, top, width, height)
397    }
398
399    /// Trim this image without copying.
400    /// Note that mutable borrows are exclusive, so it's not possible to have more than
401    /// one mutable subimage at a time.
402    #[inline]
403    #[allow(deprecated)]
404    #[must_use]
405    #[track_caller]
406    pub fn sub_image_mut(&mut self, left: usize, top: usize, width: usize, height: usize) -> ImgRefMut<'_, T> {
407        assert!(top + height <= self.height());
408        assert!(left + width <= self.width());
409        let (start, end, stride) = sub_image(left, top, width, height, self.stride(), self.buf.len());
410        let buf = &mut self.buf[start..end];
411        ImgRefMut::new_stride(buf, width, height, stride)
412    }
413
414    /// Make mutable reference immutable
415    #[inline]
416    #[must_use]
417    pub fn as_ref(&self) -> ImgRef<'_, T> {
418        self.new_buf(self.buf().as_ref())
419    }
420}
421
422impl<'slice, T: Copy> ImgRef<'slice, T> {
423    /// Iterate `width*height` pixels in the `Img`, ignoring padding area
424    ///
425    /// If you want to iterate in parallel, parallelize `rows()` instead.
426    ///
427    /// # Panics
428    ///
429    /// if width is 0
430    #[inline]
431    #[track_caller]
432    pub fn pixels(&self) -> PixelsIter<'slice, T> {
433        PixelsIter::new(*self)
434    }
435}
436
437impl<'slice, T> ImgRef<'slice, T> {
438    /// Iterate `width*height` pixels in the `Img`, by reference, ignoring padding area
439    ///
440    /// If you want to iterate in parallel, parallelize `rows()` instead.
441    ///
442    /// # Panics
443    ///
444    /// if width is 0
445    #[inline]
446    pub fn pixels_ref(&self) -> PixelsRefIter<'slice, T> {
447        PixelsRefIter::new(*self)
448    }
449}
450
451impl<T: Copy> ImgRefMut<'_, T> {
452    /// # Panics
453    ///
454    /// If you want to iterate in parallel, parallelize `rows()` instead.
455    ///
456    /// if width is 0
457    #[inline]
458    pub fn pixels(&self) -> PixelsIter<'_, T> {
459        PixelsIter::new(self.as_ref())
460    }
461
462    /// If you want to iterate in parallel, parallelize `rows()` instead.
463    /// # Panics
464    ///
465    /// if width is 0
466    #[inline]
467    pub fn pixels_mut(&mut self) -> PixelsIterMut<'_, T> {
468        PixelsIterMut::new(self)
469    }
470}
471
472impl<T: Copy> ImgVec<T> {
473    /// If you want to iterate in parallel, parallelize `rows()` instead.
474    /// # Panics
475    ///
476    /// if width is 0
477    #[inline]
478    pub fn pixels(&self) -> PixelsIter<'_, T> {
479        PixelsIter::new(self.as_ref())
480    }
481
482    /// If you want to iterate in parallel, parallelize `rows()` instead.
483    /// # Panics
484    ///
485    /// if width is 0
486    #[inline]
487    pub fn pixels_mut(&mut self) -> PixelsIterMut<'_, T> {
488        PixelsIterMut::new(&mut self.as_mut())
489    }
490}
491
492impl<T> ImgRefMut<'_, T> {
493    /// Iterate over whole rows as slices
494    ///
495    /// # Panics
496    ///
497    /// if stride is 0
498    #[inline]
499    pub fn rows(&self) -> RowsIter<'_, T> {
500        self.rows_buf_internal(&self.buf()[..])
501    }
502
503    /// Iterate over whole rows as slices
504    ///
505    /// # Panics
506    ///
507    /// if stride is 0
508    #[inline]
509    #[allow(deprecated)]
510    pub fn rows_mut(&mut self) -> RowsIterMut<'_, T> {
511        let stride = self.stride();
512        let width = self.width();
513        let height = self.height();
514        let non_padded = &mut self.buf[0..stride * height + width - stride];
515        RowsIterMut {
516            width,
517            inner: non_padded.chunks_mut(stride),
518        }
519    }
520}
521
522/// Deprecated. Use .`rows()` or .`pixels()` iterators which are more predictable
523#[cfg(feature = "deprecated")]
524impl<Container> IntoIterator for Img<Container> where Container: IntoIterator {
525    type Item = Container::Item;
526    type IntoIter = Container::IntoIter;
527    /// Deprecated. Use .`rows()` or .`pixels()` iterators which are more predictable
528    fn into_iter(self) -> Container::IntoIter {
529        self.into_buf().into_iter()
530    }
531}
532
533impl<T> ImgVec<T> {
534    /// Create a mutable view into a region within the image. See `sub_image()` for read-only views.
535    #[allow(deprecated)]
536    #[must_use]
537    #[track_caller]
538    pub fn sub_image_mut(&mut self, left: usize, top: usize, width: usize, height: usize) -> ImgRefMut<'_, T> {
539        assert!(top + height <= self.height());
540        assert!(left + width <= self.width());
541        let start = self.stride * top + left;
542        let min_buf_size = if self.height > 0 { self.stride * height + width - self.stride } else {0};
543        let buf = &mut self.buf[start .. start + min_buf_size];
544        Img::new_stride(buf, width, height, self.stride)
545    }
546
547    #[inline]
548    #[must_use]
549    /// Make a reference for a part of the image, without copying any pixels.
550    pub fn sub_image(&self, left: usize, top: usize, width: usize, height: usize) -> ImgRef<'_, T> {
551        self.as_ref().sub_image(left, top, width, height)
552    }
553
554    /// Make a reference to this image to pass it to functions without giving up ownership
555    ///
556    /// The reference should be passed by value (`ImgRef`, not `&ImgRef`).
557    ///
558    /// If you need a mutable reference, see `as_mut()` and `sub_image_mut()`
559    #[inline]
560    #[must_use]
561    pub fn as_ref(&self) -> ImgRef<'_, T> {
562        self.new_buf(self.buf().as_ref())
563    }
564
565    /// Make a mutable reference to the entire image
566    ///
567    /// The reference should be passed by value (`ImgRefMut`, not `&mut ImgRefMut`).
568    ///
569    /// See also `sub_image_mut()` and `rows_mut()`
570    #[inline]
571    pub fn as_mut(&mut self) -> ImgRefMut<'_, T> {
572        let width = self.width();
573        let height = self.height();
574        let stride = self.stride();
575        Img::new_stride(self.buf_mut().as_mut(), width, height, stride)
576    }
577
578    #[deprecated(note = "Size of this buffer may be unpredictable. Use .rows() instead")]
579    #[cfg(feature = "deprecated")]
580    #[doc(hidden)]
581    pub fn iter(&self) -> slice::Iter<'_, T> {
582        self.buf().iter()
583    }
584
585    /// Iterate over rows of the image as slices
586    ///
587    /// Each slice is guaranteed to be exactly `width` pixels wide.
588    ///
589    /// This iterator is a good candidate for parallelization (e.g. rayon's `par_bridge()`)
590    #[inline]
591    pub fn rows(&self) -> RowsIter<'_, T> {
592        self.rows_buf_internal(self.buf())
593    }
594
595    /// Iterate over rows of the image as mutable slices
596    ///
597    /// Each slice is guaranteed to be exactly `width` pixels wide.
598    ///
599    /// This iterator is a good candidate for parallelization (e.g. rayon's `par_bridge()`)
600    #[inline]
601    #[allow(deprecated)]
602    pub fn rows_mut(&mut self) -> RowsIterMut<'_, T> {
603        let stride = self.stride();
604        let width = self.width();
605        let height = self.height();
606        let non_padded = &mut self.buf[0..stride * height + width - stride];
607        RowsIterMut {
608            width,
609            inner: non_padded.chunks_mut(stride),
610        }
611    }
612}
613
614impl<Container> Img<Container> {
615    /// Same as `new()`, except each row is located `stride` number of pixels after the previous one.
616    ///
617    /// 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.
618    ///
619    /// The `Container` is usually a `Vec` or a slice.
620    #[inline]
621    #[allow(deprecated)]
622    #[track_caller]
623    pub fn new_stride(buf: Container, width: usize, height: usize, stride: usize) -> Self {
624        assert!(stride > 0);
625        assert!(stride >= width);
626        debug_assert!(height < u32::MAX as usize);
627        debug_assert!(width < u32::MAX as usize);
628        Self {
629            buf,
630            width: width as u32,
631            height: height as u32,
632            stride,
633        }
634    }
635
636    /// Create new image with `Container` (which can be `Vec`, `&[]` or something else) with given `width` and `height` in pixels.
637    ///
638    /// Assumes the pixels in container are contiguous, layed out row by row with `width` pixels per row and at least `height` rows.
639    ///
640    /// If the container is larger than `width`×`height` pixels, the extra rows are a considered a padding and may be ignored.
641    #[inline]
642    pub fn new(buf: Container, width: usize, height: usize) -> Self {
643        Self::new_stride(buf, width, height, width)
644    }
645}
646
647impl<T: Copy> Img<Vec<T>> {
648    /// Returns the buffer, width, height. Guarantees that the buffer is contiguous,
649    /// i.e. it's `width*height` elements long, and `[x + y*width]` addresses each pixel.
650    ///
651    /// Efficiently performs operation in-place. For other containers use `pixels().collect()`.
652    #[allow(deprecated)]
653    #[must_use]
654    pub fn into_contiguous_buf(mut self) -> (Vec<T>, usize, usize) {
655        let (_, w, h) = self.as_contiguous_buf();
656        (self.buf, w, h)
657    }
658
659    /// Returns a reference to the buffer, width, height. Guarantees that the buffer is contiguous,
660    /// i.e. it's `width*height` elements long, and `[x + y*width]` addresses each pixel.
661    ///
662    /// Efficiently performs operation in-place. For other containers use `pixels().collect()`.
663    #[allow(deprecated)]
664    #[must_use]
665    pub fn as_contiguous_buf(&mut self) -> (&[T], usize, usize) {
666        let width = self.width();
667        let height = self.height();
668        let stride = self.stride();
669        if width != stride {
670            for row in 1..height {
671                self.buf.copy_within(row * stride .. row * stride + width, row * width);
672            }
673        }
674        self.buf.truncate(width * height);
675        (&mut self.buf, width, height)
676    }
677}
678
679impl<OldContainer> Img<OldContainer> {
680    /// A convenience method for creating an image of the same size and stride, but with a new buffer.
681    #[inline]
682    #[track_caller]
683    pub fn map_buf<NewContainer, OldPixel, NewPixel, F>(self, callback: F) -> Img<NewContainer>
684        where NewContainer: AsRef<[NewPixel]>, OldContainer: AsRef<[OldPixel]>, F: FnOnce(OldContainer) -> NewContainer {
685        let width = self.width();
686        let height = self.height();
687        let stride = self.stride();
688        let old_buf_len = self.buf().as_ref().len();
689        #[allow(deprecated)]
690        let new_buf = callback(self.buf);
691        assert_eq!(old_buf_len, new_buf.as_ref().len());
692        Img::new_stride(new_buf, width, height, stride)
693    }
694
695    /// A convenience method for creating an image of the same size and stride, but with a new buffer.
696    #[inline]
697    #[track_caller]
698    pub fn new_buf<NewContainer, OldPixel, NewPixel>(&self, new_buf: NewContainer) -> Img<NewContainer>
699        where NewContainer: AsRef<[NewPixel]>, OldContainer: AsRef<[OldPixel]> {
700        assert_eq!(self.buf().as_ref().len(), new_buf.as_ref().len());
701        Img::new_stride(new_buf, self.width(), self.height(), self.stride())
702    }
703}
704
705impl<T: Clone> From<Img<Cow<'_, [T]>>> for Img<Vec<T>> {
706    #[allow(deprecated)]
707    fn from(img: Img<Cow<'_, [T]>>) -> Self {
708        Self {
709            width: img.width,
710            height: img.height,
711            stride: img.stride,
712            buf: img.buf.into_owned(),
713        }
714    }
715}
716
717impl<T: Clone> From<ImgVec<T>> for Img<Cow<'static, [T]>> {
718    #[allow(deprecated)]
719    fn from(img: ImgVec<T>) -> Self {
720        Img {
721            width: img.width,
722            height: img.height,
723            stride: img.stride,
724            buf: img.buf.into(),
725        }
726    }
727}
728
729impl<'a, T: Clone> From<ImgRef<'a, T>> for Img<Cow<'a, [T]>> {
730    #[allow(deprecated)]
731    fn from(img: ImgRef<'a, T>) -> Self {
732        Img {
733            buf: img.buf.into(),
734            width: img.width,
735            height: img.height,
736            stride: img.stride,
737        }
738    }
739}
740
741impl<T: Clone> Img<Cow<'_, [T]>> {
742    /// Convert underlying buffer to owned (e.g. slice to vec)
743    ///
744    /// See also `to_contiguous_buf().0.into_owned()`
745    #[allow(deprecated)]
746    #[must_use]
747    pub fn into_owned(self) -> ImgVec<T> {
748        match self.buf {
749            Cow::Borrowed(_) => {
750                let tmp = self.as_ref();
751                let (buf, w, h) = tmp.to_contiguous_buf();
752                ImgVec::new(buf.into_owned(), w, h)
753            },
754            Cow::Owned(buf) => Img {
755                buf,
756                width: self.width,
757                height: self.height,
758                stride: self.stride,
759            },
760        }
761    }
762}
763
764impl<T> Img<T> where T: ToOwned {
765    /// Convert underlying buffer to owned (e.g. slice to vec)
766    ///
767    /// See also `to_contiguous_buf().0.into_owned()`
768    #[allow(deprecated)]
769    pub fn to_owned(&self) -> Img<T::Owned> {
770        Img {
771            buf: self.buf.to_owned(),
772            width: self.width,
773            height: self.height,
774            stride: self.stride,
775        }
776    }
777}
778
779#[cfg(test)]
780mod tests {
781    use super::*;
782    use alloc::vec;
783
784    mod with_opinionated_container {
785        use super::*;
786
787        struct IDontDeriveAnything;
788
789        #[test]
790        fn compiles() {
791            let _ = Img::new(IDontDeriveAnything, 1, 1);
792        }
793    }
794
795    #[test]
796    fn with_vec() {
797        let bytes = vec![0u8;20];
798        let old = Img::new_stride(bytes, 10,2,10);
799        let _ = old.new_buf(vec![6u16;20]);
800    }
801
802    #[test]
803    fn zero() {
804        let bytes = vec![0u8];
805        let mut img = Img::new_stride(bytes,0,0,1);
806        let _ = img.sub_image(0,0,0,0);
807        let _ = img.sub_image_mut(0,0,0,0);
808        let _ = img.as_ref();
809    }
810
811    #[test]
812    fn zero_width() {
813        let bytes = vec![0u8];
814        let mut img = Img::new_stride(bytes,0,1,1);
815        let _ = img.sub_image(0,1,0,0);
816        let _ = img.sub_image_mut(0,0,0,1);
817    }
818
819    #[test]
820    fn zero_height() {
821        let bytes = vec![0u8];
822        let mut img = Img::new_stride(bytes,1,0,1);
823        assert_eq!(0, img.rows().count());
824        let _ = img.sub_image(1,0,0,0);
825        let _ = img.sub_image_mut(0,0,1,0);
826    }
827
828    #[test]
829    #[allow(deprecated)]
830    fn with_slice() {
831        let bytes = vec![0u8;20];
832        let _ = Img::new_stride(bytes.as_slice(), 10,2,10);
833        let vec = ImgVec::new_stride(bytes, 10,2,10);
834
835        #[cfg(feature = "deprecated")]
836        for _ in vec.iter() {}
837
838        assert_eq!(2, vec.rows().count());
839        for _ in *vec.as_ref().buf() {}
840
841        #[cfg(feature = "deprecated")]
842        for _ in vec {}
843    }
844
845    #[test]
846    fn sub() {
847        let img = Img::new_stride(vec![1,2,3,4,
848                       5,6,7,8,
849                       9], 3, 2, 4);
850        assert_eq!(img.buf()[img.stride()], 5);
851        assert_eq!(img.buf()[img.stride() + img.width()-1], 7);
852
853        assert_eq!(img.pixels().count(), img.width() * img.height());
854        assert_eq!(img.pixels().sum::<i32>(), 24);
855
856        {
857        let refimg = img.as_ref();
858        let refimg2 = refimg; // Test is Copy
859
860        // sub-image with stride hits end of the buffer
861        let s1 = refimg.sub_image(1, 0, refimg.width()-1, refimg.height());
862        let _ = s1.sub_image(1, 0, s1.width()-1, s1.height());
863
864        let subimg = refimg.sub_image(1, 1, 2, 1);
865        assert_eq!(subimg.pixels().count(), subimg.width() * subimg.height());
866
867        assert_eq!(subimg.buf()[0], 6);
868        assert_eq!(subimg.stride(), refimg2.stride());
869        assert!(subimg.stride() * subimg.height() + subimg.width() - subimg.stride() <= subimg.buf().len());
870        assert_eq!(refimg.buf()[0], 1);
871        assert_eq!(1, subimg.rows().count());
872        }
873
874        let mut img = img;
875        let mut subimg = img.sub_image_mut(1, 1, 2, 1);
876        assert_eq!(1, subimg.rows().count());
877        assert_eq!(1, subimg.rows_mut().count());
878        assert_eq!(1, subimg.rows_mut().rev().count());
879        assert_eq!(1, subimg.rows_mut().fuse().rev().count());
880        assert_eq!(subimg.buf()[0], 6);
881    }
882
883    #[test]
884    fn rows() {
885        let img = ImgVec::new_stride(vec![0u8; 10000], 10, 15, 100);
886        assert_eq!(img.height(), img.rows().count());
887        assert_eq!(img.height(), img.rows().rev().count());
888        assert_eq!(img.height(), img.rows().fuse().rev().count());
889    }
890
891    #[test]
892    fn mut_pixels() {
893        for y in 1..15 {
894            for x in 1..10 {
895                let mut img = ImgVec::new_stride(vec![0u8; 10000], x, y, 100);
896                assert_eq!(x*y, img.pixels_mut().count());
897                assert_eq!(x*y, img.as_mut().pixels().count());
898                assert_eq!(x*y, img.as_mut().pixels_mut().count());
899                assert_eq!(x*y, img.as_mut().as_ref().pixels().count());
900            }
901        }
902    }
903
904    #[test]
905    fn into_contiguous_buf() {
906        for in_h in [1, 2, 3, 38, 39, 40, 41].iter().copied() {
907            for in_w in [1, 2, 3, 120, 121].iter().copied() {
908                for stride in [in_w, 121, 122, 166, 242, 243].iter().copied() {
909                    let img = ImgVec::new_stride((0..10000).map(|x| x as u8).collect(), in_w, in_h, stride)
910                        .map_buf(|x| x);
911                    let pixels: Vec<_> = img.pixels().collect();
912                    let (buf, w, h) = img.into_contiguous_buf();
913                    assert_eq!(pixels, buf);
914                    assert_eq!(in_w*in_h, buf.len());
915                    assert_eq!(10000, buf.capacity());
916                    assert_eq!(in_w, w);
917                    assert_eq!(in_h, h);
918                }
919            }
920        }
921
922        let img = ImgVec::new((0..55*33).map(|x| x as u8).collect(), 55, 33);
923        let pixels: Vec<_> = img.pixels().collect();
924        let tmp = img.as_ref();
925        let (buf, ..) = tmp.to_contiguous_buf();
926        assert_eq!(&pixels[..], &buf[..]);
927        let (buf, ..) = img.into_contiguous_buf();
928        assert_eq!(pixels, buf);
929    }
930}