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