Skip to main content

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