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