Coverage Report

Created: 2026-05-16 07:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/imgref-1.12.1/src/lib.rs
Line
Count
Source
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
51
extern crate alloc;
52
#[cfg(test)]
53
extern crate std;
54
55
use alloc::borrow::{Cow, ToOwned};
56
use alloc::vec::Vec;
57
use core::slice;
58
59
mod traits;
60
61
mod iter;
62
mod ops;
63
pub 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()`).
70
pub 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.
76
pub 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
///
81
pub 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
/// ```
90
pub 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
/// ```
125
pub 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)]
140
pub 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
180
impl<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
0
    pub const fn width(&self) -> usize { self.width as usize }
Unexecuted instantiation: <imgref::Img<alloc::vec::Vec<rgb::formats::rgba::Rgba<u8>>>>::width
Unexecuted instantiation: <imgref::Img<&[rgb::formats::rgba::Rgba<u8>]>>::width
Unexecuted instantiation: <imgref::Img<_>>::width
Unexecuted instantiation: <imgref::Img<&[rgb::formats::rgb::Rgb<u8>]>>::width
187
188
    /// Height of the image in pixels.
189
    #[inline(always)]
190
    #[allow(deprecated)]
191
0
    pub const fn height(&self) -> usize { self.height as usize }
Unexecuted instantiation: <imgref::Img<alloc::vec::Vec<rgb::formats::rgba::Rgba<u8>>>>::height
Unexecuted instantiation: <imgref::Img<&[rgb::formats::rgba::Rgba<u8>]>>::height
Unexecuted instantiation: <imgref::Img<_>>::height
Unexecuted instantiation: <imgref::Img<&[rgb::formats::rgb::Rgb<u8>]>>::height
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
0
    pub const fn stride(&self) -> usize { self.stride }
Unexecuted instantiation: <imgref::Img<alloc::vec::Vec<rgb::formats::rgba::Rgba<u8>>>>::stride
Unexecuted instantiation: <imgref::Img<&[rgb::formats::rgba::Rgba<u8>]>>::stride
Unexecuted instantiation: <imgref::Img<_>>::stride
Unexecuted instantiation: <imgref::Img<&[rgb::formats::rgb::Rgb<u8>]>>::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
0
    pub const fn buf(&self) -> &Container { &self.buf }
Unexecuted instantiation: <imgref::Img<alloc::vec::Vec<rgb::formats::rgba::Rgba<u8>>>>::buf
Unexecuted instantiation: <imgref::Img<&[rgb::formats::rgba::Rgba<u8>]>>::buf
Unexecuted instantiation: <imgref::Img<_>>::buf
Unexecuted instantiation: <imgref::Img<&[rgb::formats::rgb::Rgb<u8>]>>::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
0
    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
0
    pub fn into_buf(self) -> Container { self.buf }
222
}
223
224
impl<Pixel,Container> ImgExt<Pixel> for Img<Container> where Container: AsRef<[Pixel]> {
225
    #[inline(always)]
226
    #[cfg(feature = "deprecated")]
227
0
    fn width_padded(&self) -> usize {
228
0
        self.stride()
229
0
    }
230
231
    #[inline(always)]
232
    #[cfg(feature = "deprecated")]
233
0
    fn height_padded(&self) -> usize {
234
0
        let len = self.buf().as_ref().len();
235
0
        assert_eq!(0, len % self.stride());
236
0
        len / self.stride()
237
0
    }
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
0
    fn rows_padded(&self) -> slice::Chunks<'_, Pixel> {
245
0
        self.buf().as_ref().chunks(self.stride())
246
0
    }
247
248
    #[inline(always)]
249
    #[allow(deprecated)]
250
0
    fn as_ref(&self) -> ImgRef<'_, Pixel> {
251
0
        Img {
252
0
            buf: self.buf.as_ref(),
253
0
            width: self.width,
254
0
            height: self.height,
255
0
            stride: self.stride,
256
0
        }
257
0
    }
258
}
259
260
impl<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
0
    fn rows_padded_mut(&mut self) -> slice::ChunksMut<'_, Pixel> {
270
0
        let stride = self.stride();
271
0
        self.buf_mut().as_mut().chunks_mut(stride)
272
0
    }
273
274
    #[inline(always)]
275
    #[allow(deprecated)]
276
0
    fn as_mut(&mut self) -> ImgRefMut<'_, Pixel> {
277
0
        Img {
278
0
            buf: self.buf.as_mut(),
279
0
            width: self.width,
280
0
            height: self.height,
281
0
            stride: self.stride,
282
0
        }
283
0
    }
284
}
285
286
#[inline]
287
0
fn sub_image(left: usize, top: usize, width: usize, height: usize, stride: usize, buf_len: usize) -> (usize, usize, usize) {
288
0
    let start = stride * top + left;
289
0
    let full_strides_end = start + stride * height;
290
    // when left > 0 and height is full, the last line is shorter than the stride
291
0
    let end = if buf_len >= full_strides_end {
292
0
        full_strides_end
293
    } else {
294
0
        debug_assert!(height > 0);
295
0
        let min_strides_len = full_strides_end + width - stride;
296
0
        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
0
        min_strides_len
299
    };
300
0
    (start, end, stride)
301
0
}
302
303
impl<'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
0
    pub fn sub_image(&self, left: usize, top: usize, width: usize, height: usize) -> Self {
314
0
        assert!(top + height <= self.height());
315
0
        assert!(left + width <= self.width());
316
0
        let (start, end, stride) = sub_image(left, top, width, height, self.stride(), self.buf().len());
317
0
        let buf = &self.buf()[start..end];
318
0
        Self::new_stride(buf, width, height, stride)
319
0
    }
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
0
    pub fn rows(&self) -> RowsIter<'slice, T> {
331
0
        RowsIter {
332
0
            inner: self.valid_buf().chunks(self.stride()),
333
0
            width: self.width(),
334
0
        }
335
0
    }
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
0
    pub fn iter(&self) -> slice::Iter<'slice, T> {
344
0
        self.buf().iter()
345
0
    }
346
}
347
348
impl<'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
0
    pub fn to_contiguous_buf(&self) -> (Cow<'a, [T]>, usize, usize) {
357
0
        let width = self.width();
358
0
        let height = self.height();
359
0
        let stride = self.stride();
360
0
        if width == stride {
361
0
            return (Cow::Borrowed(self.buf), width, height);
362
0
        }
363
0
        let mut buf = Vec::with_capacity(width * height);
364
0
        for row in self.rows() {
365
0
            buf.extend_from_slice(row);
366
0
        }
367
0
        (Cow::Owned(buf), width, height)
368
0
    }
369
}
370
371
impl<'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
0
    pub fn sub_image(&'slice self, left: usize, top: usize, width: usize, height: usize) -> ImgRef<'slice, T> {
377
0
        self.as_ref().sub_image(left, top, width, height)
378
0
    }
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
0
    pub fn sub_image_mut(&mut self, left: usize, top: usize, width: usize, height: usize) -> ImgRefMut<'_, T> {
393
0
        assert!(top + height <= self.height());
394
0
        assert!(left + width <= self.width());
395
0
        let (start, end, stride) = sub_image(left, top, width, height, self.stride(), self.buf.len());
396
0
        let buf = &mut self.buf[start..end];
397
0
        ImgRefMut::new_stride(buf, width, height, stride)
398
0
    }
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
0
    pub fn into_sub_image_mut(self, left: usize, top: usize, width: usize, height: usize) -> Self {
412
0
        assert!(top + height <= self.height());
413
0
        assert!(left + width <= self.width());
414
0
        let (start, end, stride) = sub_image(left, top, width, height, self.stride(), self.buf.len());
415
0
        let buf = &mut self.buf[start..end];
416
0
        ImgRefMut::new_stride(buf, width, height, stride)
417
0
    }
418
419
    /// Make mutable reference immutable
420
    #[inline]
421
    #[must_use]
422
0
    pub fn as_ref(&self) -> ImgRef<'_, T> {
423
0
        self.new_buf(self.buf().as_ref())
424
0
    }
425
}
426
427
impl<'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
0
    pub fn pixels(&self) -> PixelsIter<'slice, T> {
438
0
        PixelsIter::new(*self)
439
0
    }
Unexecuted instantiation: <imgref::Img<&[rgb::formats::rgba::Rgba<u8>]>>::pixels
Unexecuted instantiation: <imgref::Img<&[_]>>::pixels
Unexecuted instantiation: <imgref::Img<&[rgb::formats::rgb::Rgb<u8>]>>::pixels
440
}
441
442
impl<'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
0
    pub fn pixels_ref(&self) -> PixelsRefIter<'slice, T> {
452
0
        PixelsRefIter::new(*self)
453
0
    }
454
}
455
456
impl<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
0
    pub fn pixels(&self) -> PixelsIter<'_, T> {
464
0
        PixelsIter::new(self.as_ref())
465
0
    }
466
}
467
468
impl<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
0
    pub fn pixels_mut(&mut self) -> PixelsIterMut<'_, T> {
475
0
        PixelsIterMut::new(self.as_mut())
476
0
    }
477
}
478
479
impl<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
0
    pub fn pixels(&self) -> PixelsIter<'_, T> {
487
0
        PixelsIter::new(self.as_ref())
488
0
    }
489
}
490
491
impl<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
0
    pub fn pixels_mut(&mut self) -> PixelsIterMut<'_, T> {
499
0
        PixelsIterMut::new(self.as_mut())
500
0
    }
501
}
502
503
impl<T> ImgRefMut<'_, T> {
504
    /// Iterate over whole rows as slices
505
    ///
506
    /// # Panics
507
    ///
508
    /// if stride is 0
509
    #[inline]
510
0
    pub fn rows(&self) -> RowsIter<'_, T> {
511
0
        self.as_ref().rows()
512
0
    }
513
514
    /// Iterate over whole rows as slices
515
    ///
516
    /// # Panics
517
    ///
518
    /// if stride is 0
519
    #[inline]
520
    #[allow(deprecated)]
521
0
    pub fn rows_mut(&mut self) -> RowsIterMut<'_, T> {
522
0
        let stride = self.stride();
523
0
        let width = self.width();
524
0
        let height = self.height();
525
0
        let non_padded = &mut self.buf[0..stride * height + width - stride];
526
0
        RowsIterMut {
527
0
            width,
528
0
            inner: non_padded.chunks_mut(stride),
529
0
        }
530
0
    }
531
}
532
533
/// Deprecated. Use .`rows()` or .`pixels()` iterators which are more predictable
534
#[cfg(feature = "deprecated")]
535
impl<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
0
    fn into_iter(self) -> Container::IntoIter {
540
0
        self.into_buf().into_iter()
541
0
    }
542
}
543
544
impl<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
0
    pub fn sub_image_mut(&mut self, left: usize, top: usize, width: usize, height: usize) -> ImgRefMut<'_, T> {
554
0
        assert!(top + height <= self.height());
555
0
        assert!(left + width <= self.width());
556
0
        let start = self.stride * top + left;
557
0
        let min_buf_size = if self.height > 0 { self.stride * height + width - self.stride } else {0};
558
0
        let buf = &mut self.buf[start .. start + min_buf_size];
559
0
        Img::new_stride(buf, width, height, self.stride)
560
0
    }
561
562
    #[inline]
563
    #[must_use]
564
    /// Make a reference for a part of the image, without copying any pixels.
565
0
    pub fn sub_image(&self, left: usize, top: usize, width: usize, height: usize) -> ImgRef<'_, T> {
566
0
        self.as_ref().sub_image(left, top, width, height)
567
0
    }
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
0
    pub fn as_ref(&self) -> ImgRef<'_, T> {
577
0
        self.new_buf(self.buf().as_ref())
578
0
    }
Unexecuted instantiation: <imgref::Img<alloc::vec::Vec<rgb::formats::rgba::Rgba<u8>>>>::as_ref
Unexecuted instantiation: <imgref::Img<alloc::vec::Vec<_>>>::as_ref
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
0
    pub fn as_mut(&mut self) -> ImgRefMut<'_, T> {
587
0
        let width = self.width();
588
0
        let height = self.height();
589
0
        let stride = self.stride();
590
0
        Img::new_stride(self.buf_mut().as_mut(), width, height, stride)
591
0
    }
592
593
    #[deprecated(note = "Size of this buffer may be unpredictable. Use .rows() instead")]
594
    #[cfg(feature = "deprecated")]
595
    #[doc(hidden)]
596
0
    pub fn iter(&self) -> slice::Iter<'_, T> {
597
0
        self.buf().iter()
598
0
    }
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
0
    pub fn rows(&self) -> RowsIter<'_, T> {
608
0
        self.as_ref().rows()
609
0
    }
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
0
    pub fn rows_mut(&mut self) -> RowsIterMut<'_, T> {
619
0
        let stride = self.stride();
620
0
        let width = self.width();
621
0
        let height = self.height();
622
0
        let non_padded = &mut self.buf[0..stride * height + width - stride];
623
0
        RowsIterMut {
624
0
            width,
625
0
            inner: non_padded.chunks_mut(stride),
626
0
        }
627
0
    }
628
}
629
630
impl<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
0
    pub fn new_stride(buf: Container, width: usize, height: usize, stride: usize) -> Self {
650
0
        assert!(stride > 0);
651
0
        assert!(stride >= width);
652
0
        debug_assert!(height < u32::MAX as usize);
653
0
        debug_assert!(width < u32::MAX as usize);
654
0
        Self {
655
0
            buf,
656
0
            width: width as u32,
657
0
            height: height as u32,
658
0
            stride,
659
0
        }
660
0
    }
Unexecuted instantiation: <imgref::Img<alloc::vec::Vec<rgb::formats::rgba::Rgba<u8>>>>::new_stride
Unexecuted instantiation: <imgref::Img<&[rgb::formats::rgba::Rgba<u8>]>>::new_stride
Unexecuted instantiation: <imgref::Img<_>>::new_stride
Unexecuted instantiation: <imgref::Img<&[rgb::formats::rgb::Rgb<u8>]>>::new_stride
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
0
    pub fn new(buf: Container, width: usize, height: usize) -> Self {
677
0
        Self::new_stride(buf, width, height, width)
678
0
    }
Unexecuted instantiation: <imgref::Img<alloc::vec::Vec<rgb::formats::rgba::Rgba<u8>>>>::new
Unexecuted instantiation: <imgref::Img<_>>::new
Unexecuted instantiation: <imgref::Img<&[rgb::formats::rgb::Rgb<u8>]>>::new
Unexecuted instantiation: <imgref::Img<&[rgb::formats::rgba::Rgba<u8>]>>::new
679
}
680
681
#[cold]
682
#[inline(never)]
683
#[cfg_attr(debug_assertions, track_caller)]
684
0
fn imgref_invalid_size(width: u32, height: u32, stride: usize, min_size: usize, len: usize) {
685
0
    panic!("Invalid ImgRef params. Got stride={stride} for {width}×{height}; len={len} (needed {min_size})");
686
}
687
688
impl<T> ImgRefMut<'_, T> {
689
    #[cfg_attr(debug_assertions, track_caller)]
690
0
    fn valid_buf_mut(&mut self) -> &mut [T] {
691
0
        let len = self.as_ref().valid_min_len();
692
0
        &mut self.buf_mut()[..len]
693
0
    }
694
}
695
696
impl<'buf, T> ImgRef<'buf, T> {
697
    #[cfg_attr(debug_assertions, track_caller)]
698
0
    fn valid_buf(&self) -> &'buf [T] {
699
0
        &self.buf()[..self.valid_min_len()]
700
0
    }
Unexecuted instantiation: <imgref::Img<&[rgb::formats::rgba::Rgba<u8>]>>::valid_buf
Unexecuted instantiation: <imgref::Img<&[_]>>::valid_buf
Unexecuted instantiation: <imgref::Img<&[rgb::formats::rgb::Rgb<u8>]>>::valid_buf
701
702
    #[cfg_attr(debug_assertions, track_caller)]
703
    #[inline(always)]
704
0
    fn valid_min_len(&self) -> usize {
705
0
        let stride = self.stride();
706
0
        let width = self.width();
707
0
        let height = self.height();
708
0
        let min_size = if height == 0 || width == 0 { 0 } else { stride * height + width - stride };
709
0
        let buf = self.buf();
710
        #[allow(deprecated)]
711
0
        if stride == 0 || stride < width || buf.len() < min_size {
712
0
            imgref_invalid_size(self.width, self.height, stride, min_size, buf.len());
713
0
        }
714
0
        min_size
715
0
    }
Unexecuted instantiation: <imgref::Img<&[rgb::formats::rgba::Rgba<u8>]>>::valid_min_len
Unexecuted instantiation: <imgref::Img<&[_]>>::valid_min_len
Unexecuted instantiation: <imgref::Img<&[rgb::formats::rgb::Rgb<u8>]>>::valid_min_len
716
}
717
718
impl<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
0
    pub fn into_contiguous_buf(mut self) -> (Vec<T>, usize, usize) {
727
0
        let (_, w, h) = self.as_contiguous_buf();
728
0
        (self.buf, w, h)
729
0
    }
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
0
    pub fn as_contiguous_buf(&mut self) -> (&[T], usize, usize) {
739
0
        let width = self.width();
740
0
        let height = self.height();
741
0
        let stride = self.stride();
742
0
        if width != stride {
743
0
            let mut ref_mut = self.as_mut();
744
0
            let buf = ref_mut.valid_buf_mut();
745
0
            for row in 1..height {
746
0
                buf.copy_within(row * stride .. row * stride + width, row * width);
747
0
            }
748
0
        }
749
0
        self.buf.truncate(width * height);
750
0
        (&mut self.buf, width, height)
751
0
    }
752
}
753
754
impl<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
0
    pub fn map_buf<NewContainer, OldPixel, NewPixel, F>(self, callback: F) -> Img<NewContainer>
763
0
        where NewContainer: AsRef<[NewPixel]>, OldContainer: AsRef<[OldPixel]>, F: FnOnce(OldContainer) -> NewContainer {
764
0
        let width = self.width();
765
0
        let height = self.height();
766
0
        let stride = self.stride();
767
0
        let old_buf_len = self.buf().as_ref().len();
768
        #[allow(deprecated)]
769
0
        let new_buf = callback(self.buf);
770
0
        assert_eq!(old_buf_len, new_buf.as_ref().len());
771
0
        Img::new_stride(new_buf, width, height, stride)
772
0
    }
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
0
    pub fn new_buf<NewContainer, OldPixel, NewPixel>(&self, new_buf: NewContainer) -> Img<NewContainer>
782
0
        where NewContainer: AsRef<[NewPixel]>, OldContainer: AsRef<[OldPixel]> {
783
0
        assert_eq!(self.buf().as_ref().len(), new_buf.as_ref().len());
784
0
        Img::new_stride(new_buf, self.width(), self.height(), self.stride())
785
0
    }
Unexecuted instantiation: <imgref::Img<alloc::vec::Vec<rgb::formats::rgba::Rgba<u8>>>>::new_buf::<&[rgb::formats::rgba::Rgba<u8>], rgb::formats::rgba::Rgba<u8>, rgb::formats::rgba::Rgba<u8>>
Unexecuted instantiation: <imgref::Img<_>>::new_buf::<_, _, _>
786
}
787
788
impl<T: Clone> From<Img<Cow<'_, [T]>>> for Img<Vec<T>> {
789
    #[allow(deprecated)]
790
0
    fn from(img: Img<Cow<'_, [T]>>) -> Self {
791
0
        Self {
792
0
            width: img.width,
793
0
            height: img.height,
794
0
            stride: img.stride,
795
0
            buf: img.buf.into_owned(),
796
0
        }
797
0
    }
798
}
799
800
impl<T: Clone> From<ImgVec<T>> for Img<Cow<'static, [T]>> {
801
    #[allow(deprecated)]
802
0
    fn from(img: ImgVec<T>) -> Self {
803
0
        Img {
804
0
            width: img.width,
805
0
            height: img.height,
806
0
            stride: img.stride,
807
0
            buf: img.buf.into(),
808
0
        }
809
0
    }
810
}
811
812
impl<'a, T: Clone> From<ImgRef<'a, T>> for Img<Cow<'a, [T]>> {
813
    #[allow(deprecated)]
814
0
    fn from(img: ImgRef<'a, T>) -> Self {
815
0
        Img {
816
0
            buf: img.buf.into(),
817
0
            width: img.width,
818
0
            height: img.height,
819
0
            stride: img.stride,
820
0
        }
821
0
    }
822
}
823
824
impl<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
0
    pub fn into_owned(self) -> ImgVec<T> {
831
0
        match self.buf {
832
            Cow::Borrowed(_) => {
833
0
                let tmp = self.as_ref();
834
0
                let (buf, w, h) = tmp.to_contiguous_buf();
835
0
                ImgVec::new(buf.into_owned(), w, h)
836
            },
837
0
            Cow::Owned(buf) => Img {
838
0
                buf,
839
0
                width: self.width,
840
0
                height: self.height,
841
0
                stride: self.stride,
842
0
            },
843
        }
844
0
    }
845
}
846
847
impl<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
0
    pub fn to_owned(&self) -> Img<T::Owned> {
853
0
        Img {
854
0
            buf: self.buf.to_owned(),
855
0
            width: self.width,
856
0
            height: self.height,
857
0
            stride: self.stride,
858
0
        }
859
0
    }
860
}
861
862
#[cfg(test)]
863
mod 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
}