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 buf = self.buf();
709        #[allow(deprecated)]
710        if stride == 0 || stride < width {
711            imgref_invalid_size(self.width, self.height, stride, 0, buf.len());
712        }
713        #[allow(deprecated)]
714        let min_size = if height == 0 || width == 0 {
715            0
716        } else {
717            stride
718                .checked_mul(height - 1)
719                .and_then(|len| len.checked_add(width))
720                .unwrap_or_else(|| {
721                    imgref_invalid_size(self.width, self.height, stride, usize::MAX, buf.len())
722                })
723        };
724        #[allow(deprecated)]
725        if buf.len() < min_size {
726            imgref_invalid_size(self.width, self.height, stride, min_size, buf.len());
727        }
728        min_size
729    }
730}
731
732impl<T: Copy> Img<Vec<T>> {
733    /// Returns the buffer, width, height. Guarantees that the buffer is contiguous,
734    /// i.e. it's `width*height` elements long, and `[x + y*width]` addresses each pixel.
735    ///
736    /// Efficiently performs operation in-place. For other containers use `pixels().collect()`.
737    #[allow(deprecated)]
738    #[must_use]
739    #[cfg_attr(debug_assertions, track_caller)]
740    pub fn into_contiguous_buf(mut self) -> (Vec<T>, usize, usize) {
741        let (_, w, h) = self.as_contiguous_buf();
742        (self.buf, w, h)
743    }
744
745    /// Returns a reference to the buffer, width, height. Guarantees that the buffer is contiguous,
746    /// i.e. it's `width*height` elements long, and `[x + y*width]` addresses each pixel.
747    ///
748    /// Efficiently performs operation in-place. For other containers use `pixels().collect()`.
749    #[allow(deprecated)]
750    #[must_use]
751    #[cfg_attr(debug_assertions, track_caller)]
752    pub fn as_contiguous_buf(&mut self) -> (&[T], usize, usize) {
753        let width = self.width();
754        let height = self.height();
755        let stride = self.stride();
756        if width != stride {
757            let mut ref_mut = self.as_mut();
758            let buf = ref_mut.valid_buf_mut();
759            for row in 1..height {
760                buf.copy_within(row * stride .. row * stride + width, row * width);
761            }
762        }
763        self.buf.truncate(width * height);
764        (&mut self.buf, width, height)
765    }
766}
767
768impl<OldContainer> Img<OldContainer> {
769    /// A convenience method for creating an image of the same size and stride, but with a new buffer.
770    ///
771    /// # Panics
772    ///
773    /// If the new buffer has a different length
774    #[inline]
775    #[track_caller]
776    pub fn map_buf<NewContainer, OldPixel, NewPixel, F>(self, callback: F) -> Img<NewContainer>
777        where NewContainer: AsRef<[NewPixel]>, OldContainer: AsRef<[OldPixel]>, F: FnOnce(OldContainer) -> NewContainer {
778        let width = self.width();
779        let height = self.height();
780        let stride = self.stride();
781        let old_buf_len = self.buf().as_ref().len();
782        #[allow(deprecated)]
783        let new_buf = callback(self.buf);
784        assert_eq!(old_buf_len, new_buf.as_ref().len());
785        Img::new_stride(new_buf, width, height, stride)
786    }
787
788    /// A convenience method for creating an image of the same size and stride, but with a new buffer.
789    ///
790    /// # Panics
791    ///
792    /// If the new buffer has a different length
793    #[inline]
794    #[track_caller]
795    pub fn new_buf<NewContainer, OldPixel, NewPixel>(&self, new_buf: NewContainer) -> Img<NewContainer>
796        where NewContainer: AsRef<[NewPixel]>, OldContainer: AsRef<[OldPixel]> {
797        assert_eq!(self.buf().as_ref().len(), new_buf.as_ref().len());
798        Img::new_stride(new_buf, self.width(), self.height(), self.stride())
799    }
800}
801
802impl<T: Clone> From<Img<Cow<'_, [T]>>> for Img<Vec<T>> {
803    #[allow(deprecated)]
804    fn from(img: Img<Cow<'_, [T]>>) -> Self {
805        Self {
806            width: img.width,
807            height: img.height,
808            stride: img.stride,
809            buf: img.buf.into_owned(),
810        }
811    }
812}
813
814impl<T: Clone> From<ImgVec<T>> for Img<Cow<'static, [T]>> {
815    #[allow(deprecated)]
816    fn from(img: ImgVec<T>) -> Self {
817        Img {
818            width: img.width,
819            height: img.height,
820            stride: img.stride,
821            buf: img.buf.into(),
822        }
823    }
824}
825
826impl<'a, T: Clone> From<ImgRef<'a, T>> for Img<Cow<'a, [T]>> {
827    #[allow(deprecated)]
828    fn from(img: ImgRef<'a, T>) -> Self {
829        Img {
830            buf: img.buf.into(),
831            width: img.width,
832            height: img.height,
833            stride: img.stride,
834        }
835    }
836}
837
838impl<T: Clone> Img<Cow<'_, [T]>> {
839    /// Convert underlying buffer to owned (e.g. slice to vec)
840    ///
841    /// See also `to_contiguous_buf().0.into_owned()`
842    #[allow(deprecated)]
843    #[must_use]
844    pub fn into_owned(self) -> ImgVec<T> {
845        match self.buf {
846            Cow::Borrowed(_) => {
847                let tmp = self.as_ref();
848                let (buf, w, h) = tmp.to_contiguous_buf();
849                ImgVec::new(buf.into_owned(), w, h)
850            },
851            Cow::Owned(buf) => Img {
852                buf,
853                width: self.width,
854                height: self.height,
855                stride: self.stride,
856            },
857        }
858    }
859}
860
861impl<T> Img<T> where T: ToOwned {
862    /// Convert underlying buffer to owned (e.g. slice to vec)
863    ///
864    /// See also `to_contiguous_buf().0.into_owned()`
865    #[allow(deprecated)]
866    pub fn to_owned(&self) -> Img<T::Owned> {
867        Img {
868            buf: self.buf.to_owned(),
869            width: self.width,
870            height: self.height,
871            stride: self.stride,
872        }
873    }
874}
875
876#[cfg(test)]
877mod tests {
878    use super::*;
879    use alloc::vec;
880
881    mod with_opinionated_container {
882        use super::*;
883
884        struct IDontDeriveAnything;
885
886        #[test]
887        fn compiles() {
888            let _ = Img::new(IDontDeriveAnything, 1, 1);
889        }
890    }
891
892    #[test]
893    fn with_vec() {
894        let bytes = vec![0u8;20];
895        let old = Img::new_stride(bytes, 10,2,10);
896        let _ = old.new_buf(vec![6u16;20]);
897    }
898
899    #[test]
900    fn zero() {
901        let bytes = vec![0u8];
902        let mut img = Img::new_stride(bytes,0,0,1);
903        let _ = img.sub_image(0,0,0,0);
904        let _ = img.sub_image_mut(0,0,0,0);
905        let _ = img.as_ref();
906    }
907
908    #[test]
909    fn zero_width() {
910        let bytes = vec![0u8];
911        let mut img = Img::new_stride(bytes,0,1,1);
912        let _ = img.sub_image(0,1,0,0);
913        let _ = img.sub_image_mut(0,0,0,1);
914    }
915
916    #[test]
917    fn zero_height() {
918        let bytes = vec![0u8];
919        let mut img = Img::new_stride(bytes,1,0,1);
920        assert_eq!(0, img.rows().count());
921        let _ = img.sub_image(1,0,0,0);
922        let _ = img.sub_image_mut(0,0,1,0);
923    }
924
925    #[test]
926    #[allow(deprecated)]
927    fn with_slice() {
928        let bytes = vec![0u8;20];
929        let _ = Img::new_stride(bytes.as_slice(), 10,2,10);
930        let vec = ImgVec::new_stride(bytes, 10,2,10);
931
932        #[cfg(feature = "deprecated")]
933        for _ in vec.iter() {}
934
935        assert_eq!(2, vec.rows().count());
936        for _ in *vec.as_ref().buf() {}
937
938        #[cfg(feature = "deprecated")]
939        for _ in vec {}
940    }
941
942    #[test]
943    fn sub() {
944        let img = Img::new_stride(vec![1,2,3,4,
945                       5,6,7,8,
946                       9], 3, 2, 4);
947        assert_eq!(img.buf()[img.stride()], 5);
948        assert_eq!(img.buf()[img.stride() + img.width()-1], 7);
949
950        assert_eq!(img.pixels().count(), img.width() * img.height());
951        assert_eq!(img.pixels().sum::<i32>(), 24);
952
953        {
954        let refimg = img.as_ref();
955        let refimg2 = refimg; // Test is Copy
956
957        // sub-image with stride hits end of the buffer
958        let s1 = refimg.sub_image(1, 0, refimg.width()-1, refimg.height());
959        let _ = s1.sub_image(1, 0, s1.width()-1, s1.height());
960
961        let subimg = refimg.sub_image(1, 1, 2, 1);
962        assert_eq!(subimg.pixels().count(), subimg.width() * subimg.height());
963
964        assert_eq!(subimg.buf()[0], 6);
965        assert_eq!(subimg.stride(), refimg2.stride());
966        assert!(subimg.stride() * subimg.height() + subimg.width() - subimg.stride() <= subimg.buf().len());
967        assert_eq!(refimg.buf()[0], 1);
968        assert_eq!(1, subimg.rows().count());
969        }
970
971        // 3 different methods for constructing mutable sub-images
972        let mut img_for_mut_1 = img.clone();
973        let mut img_for_mut_2 = img.clone();
974        let mut img_for_mut_3 = img;
975        for mut subimg in [
976            img_for_mut_1.sub_image_mut(1, 1, 2, 1),
977            img_for_mut_2.as_mut().sub_image_mut(1, 1, 2, 1),
978            img_for_mut_3.as_mut().into_sub_image_mut(1, 1, 2, 1),
979        ] {
980            assert_eq!(1, subimg.rows().count());
981            assert_eq!(1, subimg.rows_mut().count());
982            assert_eq!(1, subimg.rows_mut().rev().count());
983            assert_eq!(1, subimg.rows_mut().fuse().rev().count());
984            assert_eq!(subimg.buf()[0], 6);
985        }
986    }
987
988    #[test]
989    fn rows() {
990        let img = ImgVec::new_stride(vec![0u8; 10000], 10, 15, 100);
991        assert_eq!(img.height(), img.rows().count());
992        assert_eq!(img.height(), img.rows().rev().count());
993        assert_eq!(img.height(), img.rows().fuse().rev().count());
994    }
995
996    #[test]
997    fn mut_pixels() {
998        for y in 1..15 {
999            for x in 1..10 {
1000                let mut img = ImgVec::new_stride(vec![0u8; 10000], x, y, 100);
1001                assert_eq!(x*y, img.pixels_mut().count());
1002                assert_eq!(x*y, img.as_mut().pixels().count());
1003                assert_eq!(x*y, img.as_mut().pixels_mut().count());
1004                assert_eq!(x*y, img.as_mut().as_ref().pixels().count());
1005            }
1006        }
1007    }
1008
1009    #[test]
1010    fn into_contiguous_buf() {
1011        for in_h in [1, 2, 3, 38, 39, 40, 41].iter().copied() {
1012            for in_w in [1, 2, 3, 120, 121].iter().copied() {
1013                for stride in [in_w, 121, 122, 166, 242, 243].iter().copied() {
1014                    let img = ImgVec::new_stride((0..10000).map(|x| x as u8).collect(), in_w, in_h, stride)
1015                        .map_buf(|x| x);
1016                    let pixels: Vec<_> = img.pixels().collect();
1017                    let (buf, w, h) = img.into_contiguous_buf();
1018                    assert_eq!(pixels, buf);
1019                    assert_eq!(in_w*in_h, buf.len());
1020                    assert_eq!(10000, buf.capacity());
1021                    assert_eq!(in_w, w);
1022                    assert_eq!(in_h, h);
1023                }
1024            }
1025        }
1026
1027        let img = ImgVec::new((0..55*33).map(|x| x as u8).collect(), 55, 33);
1028        let pixels: Vec<_> = img.pixels().collect();
1029        let tmp = img.as_ref();
1030        let (buf, ..) = tmp.to_contiguous_buf();
1031        assert_eq!(&pixels[..], &buf[..]);
1032        let (buf, ..) = img.into_contiguous_buf();
1033        assert_eq!(pixels, buf);
1034    }
1035}