image/images/
buffer.rs

1//! Contains the generic `ImageBuffer` struct.
2use num_traits::Zero;
3use std::fmt;
4use std::marker::PhantomData;
5use std::ops::{Deref, DerefMut, Index, IndexMut, Range};
6use std::path::Path;
7use std::slice::{ChunksExact, ChunksExactMut};
8
9use crate::color::{FromColor, FromPrimitive, Luma, LumaA, Rgb, Rgba};
10use crate::error::{
11    ImageResult, ParameterError, ParameterErrorKind, UnsupportedError, UnsupportedErrorKind,
12};
13use crate::flat::{FlatSamples, SampleLayout, ViewOfPixel};
14use crate::math::Rect;
15use crate::metadata::cicp::{CicpApplicable, CicpPixelCast, CicpRgb, ColorComponentForCicp};
16use crate::traits::{EncodableLayout, Pixel, PixelWithColorType};
17use crate::utils::expand_packed;
18use crate::{
19    metadata::{Cicp, CicpColorPrimaries, CicpTransferCharacteristics, CicpTransform},
20    save_buffer, save_buffer_with_format, write_buffer_with_format, ImageError,
21};
22use crate::{DynamicImage, GenericImage, GenericImageView, ImageEncoder, ImageFormat};
23
24/// Iterate over pixel refs.
25pub struct Pixels<'a, P: Pixel + 'a>
26where
27    P::Subpixel: 'a,
28{
29    chunks: ChunksExact<'a, P::Subpixel>,
30}
31
32impl<'a, P: Pixel + 'a> Iterator for Pixels<'a, P>
33where
34    P::Subpixel: 'a,
35{
36    type Item = &'a P;
37
38    #[inline(always)]
39    fn next(&mut self) -> Option<&'a P> {
40        self.chunks.next().map(|v| <P as Pixel>::from_slice(v))
41    }
42
43    #[inline(always)]
44    fn size_hint(&self) -> (usize, Option<usize>) {
45        let len = self.len();
46        (len, Some(len))
47    }
48}
49
50impl<'a, P: Pixel + 'a> ExactSizeIterator for Pixels<'a, P>
51where
52    P::Subpixel: 'a,
53{
54    fn len(&self) -> usize {
55        self.chunks.len()
56    }
57}
58
59impl<'a, P: Pixel + 'a> DoubleEndedIterator for Pixels<'a, P>
60where
61    P::Subpixel: 'a,
62{
63    #[inline(always)]
64    fn next_back(&mut self) -> Option<&'a P> {
65        self.chunks.next_back().map(|v| <P as Pixel>::from_slice(v))
66    }
67}
68
69impl<P: Pixel> Clone for Pixels<'_, P> {
70    fn clone(&self) -> Self {
71        Pixels {
72            chunks: self.chunks.clone(),
73        }
74    }
75}
76
77impl<P: Pixel> fmt::Debug for Pixels<'_, P>
78where
79    P::Subpixel: fmt::Debug,
80{
81    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
82        f.debug_struct("Pixels")
83            .field("chunks", &self.chunks)
84            .finish()
85    }
86}
87
88/// Iterate over mutable pixel refs.
89pub struct PixelsMut<'a, P: Pixel + 'a>
90where
91    P::Subpixel: 'a,
92{
93    chunks: ChunksExactMut<'a, P::Subpixel>,
94}
95
96impl<'a, P: Pixel + 'a> Iterator for PixelsMut<'a, P>
97where
98    P::Subpixel: 'a,
99{
100    type Item = &'a mut P;
101
102    #[inline(always)]
103    fn next(&mut self) -> Option<&'a mut P> {
104        self.chunks.next().map(|v| <P as Pixel>::from_slice_mut(v))
105    }
106
107    #[inline(always)]
108    fn size_hint(&self) -> (usize, Option<usize>) {
109        let len = self.len();
110        (len, Some(len))
111    }
112}
113
114impl<'a, P: Pixel + 'a> ExactSizeIterator for PixelsMut<'a, P>
115where
116    P::Subpixel: 'a,
117{
118    fn len(&self) -> usize {
119        self.chunks.len()
120    }
121}
122
123impl<'a, P: Pixel + 'a> DoubleEndedIterator for PixelsMut<'a, P>
124where
125    P::Subpixel: 'a,
126{
127    #[inline(always)]
128    fn next_back(&mut self) -> Option<&'a mut P> {
129        self.chunks
130            .next_back()
131            .map(|v| <P as Pixel>::from_slice_mut(v))
132    }
133}
134
135impl<P: Pixel> fmt::Debug for PixelsMut<'_, P>
136where
137    P::Subpixel: fmt::Debug,
138{
139    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
140        f.debug_struct("PixelsMut")
141            .field("chunks", &self.chunks)
142            .finish()
143    }
144}
145
146/// Iterate over rows of an image
147///
148/// This iterator is created with [`ImageBuffer::rows`]. See its document for details.
149///
150/// [`ImageBuffer::rows`]: ../struct.ImageBuffer.html#method.rows
151pub struct Rows<'a, P: Pixel + 'a>
152where
153    <P as Pixel>::Subpixel: 'a,
154{
155    pixels: ChunksExact<'a, P::Subpixel>,
156}
157
158impl<'a, P: Pixel + 'a> Rows<'a, P> {
159    /// Construct the iterator from image pixels. This is not public since it has a (hidden) panic
160    /// condition. The `pixels` slice must be large enough so that all pixels are addressable.
161    fn with_image(pixels: &'a [P::Subpixel], width: u32, height: u32) -> Self {
162        let row_len = (width as usize) * usize::from(<P as Pixel>::CHANNEL_COUNT);
163        if row_len == 0 {
164            Rows {
165                pixels: [].chunks_exact(1),
166            }
167        } else {
168            let pixels = pixels
169                .get(..row_len * height as usize)
170                .expect("Pixel buffer has too few subpixels");
171            // Rows are physically present. In particular, height is smaller than `usize::MAX` as
172            // all subpixels can be indexed.
173            Rows {
174                pixels: pixels.chunks_exact(row_len),
175            }
176        }
177    }
178}
179
180impl<'a, P: Pixel + 'a> Iterator for Rows<'a, P>
181where
182    P::Subpixel: 'a,
183{
184    type Item = Pixels<'a, P>;
185
186    #[inline(always)]
187    fn next(&mut self) -> Option<Pixels<'a, P>> {
188        let row = self.pixels.next()?;
189        Some(Pixels {
190            // Note: this is not reached when CHANNEL_COUNT is 0.
191            chunks: row.chunks_exact(<P as Pixel>::CHANNEL_COUNT as usize),
192        })
193    }
194
195    #[inline(always)]
196    fn size_hint(&self) -> (usize, Option<usize>) {
197        let len = self.len();
198        (len, Some(len))
199    }
200}
201
202impl<'a, P: Pixel + 'a> ExactSizeIterator for Rows<'a, P>
203where
204    P::Subpixel: 'a,
205{
206    fn len(&self) -> usize {
207        self.pixels.len()
208    }
209}
210
211impl<'a, P: Pixel + 'a> DoubleEndedIterator for Rows<'a, P>
212where
213    P::Subpixel: 'a,
214{
215    #[inline(always)]
216    fn next_back(&mut self) -> Option<Pixels<'a, P>> {
217        let row = self.pixels.next_back()?;
218        Some(Pixels {
219            // Note: this is not reached when CHANNEL_COUNT is 0.
220            chunks: row.chunks_exact(<P as Pixel>::CHANNEL_COUNT as usize),
221        })
222    }
223}
224
225impl<P: Pixel> Clone for Rows<'_, P> {
226    fn clone(&self) -> Self {
227        Rows {
228            pixels: self.pixels.clone(),
229        }
230    }
231}
232
233impl<P: Pixel> fmt::Debug for Rows<'_, P>
234where
235    P::Subpixel: fmt::Debug,
236{
237    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
238        f.debug_struct("Rows")
239            .field("pixels", &self.pixels)
240            .finish()
241    }
242}
243
244/// Iterate over mutable rows of an image
245///
246/// This iterator is created with [`ImageBuffer::rows_mut`]. See its document for details.
247///
248/// [`ImageBuffer::rows_mut`]: ../struct.ImageBuffer.html#method.rows_mut
249pub struct RowsMut<'a, P: Pixel + 'a>
250where
251    <P as Pixel>::Subpixel: 'a,
252{
253    pixels: ChunksExactMut<'a, P::Subpixel>,
254}
255
256impl<'a, P: Pixel + 'a> RowsMut<'a, P> {
257    /// Construct the iterator from image pixels. This is not public since it has a (hidden) panic
258    /// condition. The `pixels` slice must be large enough so that all pixels are addressable.
259    fn with_image(pixels: &'a mut [P::Subpixel], width: u32, height: u32) -> Self {
260        let row_len = (width as usize) * usize::from(<P as Pixel>::CHANNEL_COUNT);
261        if row_len == 0 {
262            RowsMut {
263                pixels: [].chunks_exact_mut(1),
264            }
265        } else {
266            let pixels = pixels
267                .get_mut(..row_len * height as usize)
268                .expect("Pixel buffer has too few subpixels");
269            // Rows are physically present. In particular, height is smaller than `usize::MAX` as
270            // all subpixels can be indexed.
271            RowsMut {
272                pixels: pixels.chunks_exact_mut(row_len),
273            }
274        }
275    }
276}
277
278impl<'a, P: Pixel + 'a> Iterator for RowsMut<'a, P>
279where
280    P::Subpixel: 'a,
281{
282    type Item = PixelsMut<'a, P>;
283
284    #[inline(always)]
285    fn next(&mut self) -> Option<PixelsMut<'a, P>> {
286        let row = self.pixels.next()?;
287        Some(PixelsMut {
288            // Note: this is not reached when CHANNEL_COUNT is 0.
289            chunks: row.chunks_exact_mut(<P as Pixel>::CHANNEL_COUNT as usize),
290        })
291    }
292
293    #[inline(always)]
294    fn size_hint(&self) -> (usize, Option<usize>) {
295        let len = self.len();
296        (len, Some(len))
297    }
298}
299
300impl<'a, P: Pixel + 'a> ExactSizeIterator for RowsMut<'a, P>
301where
302    P::Subpixel: 'a,
303{
304    fn len(&self) -> usize {
305        self.pixels.len()
306    }
307}
308
309impl<'a, P: Pixel + 'a> DoubleEndedIterator for RowsMut<'a, P>
310where
311    P::Subpixel: 'a,
312{
313    #[inline(always)]
314    fn next_back(&mut self) -> Option<PixelsMut<'a, P>> {
315        let row = self.pixels.next_back()?;
316        Some(PixelsMut {
317            // Note: this is not reached when CHANNEL_COUNT is 0.
318            chunks: row.chunks_exact_mut(<P as Pixel>::CHANNEL_COUNT as usize),
319        })
320    }
321}
322
323impl<P: Pixel> fmt::Debug for RowsMut<'_, P>
324where
325    P::Subpixel: fmt::Debug,
326{
327    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
328        f.debug_struct("RowsMut")
329            .field("pixels", &self.pixels)
330            .finish()
331    }
332}
333
334/// Enumerate the pixels of an image.
335pub struct EnumeratePixels<'a, P: Pixel + 'a>
336where
337    <P as Pixel>::Subpixel: 'a,
338{
339    pixels: Pixels<'a, P>,
340    x: u32,
341    y: u32,
342    width: u32,
343}
344
345impl<'a, P: Pixel + 'a> Iterator for EnumeratePixels<'a, P>
346where
347    P::Subpixel: 'a,
348{
349    type Item = (u32, u32, &'a P);
350
351    #[inline(always)]
352    fn next(&mut self) -> Option<(u32, u32, &'a P)> {
353        if self.x >= self.width {
354            self.x = 0;
355            self.y += 1;
356        }
357        let (x, y) = (self.x, self.y);
358        self.x += 1;
359        self.pixels.next().map(|p| (x, y, p))
360    }
361
362    #[inline(always)]
363    fn size_hint(&self) -> (usize, Option<usize>) {
364        let len = self.len();
365        (len, Some(len))
366    }
367}
368
369impl<'a, P: Pixel + 'a> ExactSizeIterator for EnumeratePixels<'a, P>
370where
371    P::Subpixel: 'a,
372{
373    fn len(&self) -> usize {
374        self.pixels.len()
375    }
376}
377
378impl<P: Pixel> Clone for EnumeratePixels<'_, P> {
379    fn clone(&self) -> Self {
380        EnumeratePixels {
381            pixels: self.pixels.clone(),
382            ..*self
383        }
384    }
385}
386
387impl<P: Pixel> fmt::Debug for EnumeratePixels<'_, P>
388where
389    P::Subpixel: fmt::Debug,
390{
391    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
392        f.debug_struct("EnumeratePixels")
393            .field("pixels", &self.pixels)
394            .field("x", &self.x)
395            .field("y", &self.y)
396            .field("width", &self.width)
397            .finish()
398    }
399}
400
401/// Enumerate the rows of an image.
402pub struct EnumerateRows<'a, P: Pixel + 'a>
403where
404    <P as Pixel>::Subpixel: 'a,
405{
406    rows: Rows<'a, P>,
407    y: u32,
408    width: u32,
409}
410
411impl<'a, P: Pixel + 'a> Iterator for EnumerateRows<'a, P>
412where
413    P::Subpixel: 'a,
414{
415    type Item = (u32, EnumeratePixels<'a, P>);
416
417    #[inline(always)]
418    fn next(&mut self) -> Option<(u32, EnumeratePixels<'a, P>)> {
419        let y = self.y;
420        self.y += 1;
421        self.rows.next().map(|r| {
422            (
423                y,
424                EnumeratePixels {
425                    x: 0,
426                    y,
427                    width: self.width,
428                    pixels: r,
429                },
430            )
431        })
432    }
433
434    #[inline(always)]
435    fn size_hint(&self) -> (usize, Option<usize>) {
436        let len = self.len();
437        (len, Some(len))
438    }
439}
440
441impl<'a, P: Pixel + 'a> ExactSizeIterator for EnumerateRows<'a, P>
442where
443    P::Subpixel: 'a,
444{
445    fn len(&self) -> usize {
446        self.rows.len()
447    }
448}
449
450impl<P: Pixel> Clone for EnumerateRows<'_, P> {
451    fn clone(&self) -> Self {
452        EnumerateRows {
453            rows: self.rows.clone(),
454            ..*self
455        }
456    }
457}
458
459impl<P: Pixel> fmt::Debug for EnumerateRows<'_, P>
460where
461    P::Subpixel: fmt::Debug,
462{
463    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
464        f.debug_struct("EnumerateRows")
465            .field("rows", &self.rows)
466            .field("y", &self.y)
467            .field("width", &self.width)
468            .finish()
469    }
470}
471
472/// Enumerate the pixels of an image.
473pub struct EnumeratePixelsMut<'a, P: Pixel + 'a>
474where
475    <P as Pixel>::Subpixel: 'a,
476{
477    pixels: PixelsMut<'a, P>,
478    x: u32,
479    y: u32,
480    width: u32,
481}
482
483impl<'a, P: Pixel + 'a> Iterator for EnumeratePixelsMut<'a, P>
484where
485    P::Subpixel: 'a,
486{
487    type Item = (u32, u32, &'a mut P);
488
489    #[inline(always)]
490    fn next(&mut self) -> Option<(u32, u32, &'a mut P)> {
491        if self.x >= self.width {
492            self.x = 0;
493            self.y += 1;
494        }
495        let (x, y) = (self.x, self.y);
496        self.x += 1;
497        self.pixels.next().map(|p| (x, y, p))
498    }
499
500    #[inline(always)]
501    fn size_hint(&self) -> (usize, Option<usize>) {
502        let len = self.len();
503        (len, Some(len))
504    }
505}
506
507impl<'a, P: Pixel + 'a> ExactSizeIterator for EnumeratePixelsMut<'a, P>
508where
509    P::Subpixel: 'a,
510{
511    fn len(&self) -> usize {
512        self.pixels.len()
513    }
514}
515
516impl<P: Pixel> fmt::Debug for EnumeratePixelsMut<'_, P>
517where
518    P::Subpixel: fmt::Debug,
519{
520    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
521        f.debug_struct("EnumeratePixelsMut")
522            .field("pixels", &self.pixels)
523            .field("x", &self.x)
524            .field("y", &self.y)
525            .field("width", &self.width)
526            .finish()
527    }
528}
529
530/// Enumerate the rows of an image.
531pub struct EnumerateRowsMut<'a, P: Pixel + 'a>
532where
533    <P as Pixel>::Subpixel: 'a,
534{
535    rows: RowsMut<'a, P>,
536    y: u32,
537    width: u32,
538}
539
540impl<'a, P: Pixel + 'a> Iterator for EnumerateRowsMut<'a, P>
541where
542    P::Subpixel: 'a,
543{
544    type Item = (u32, EnumeratePixelsMut<'a, P>);
545
546    #[inline(always)]
547    fn next(&mut self) -> Option<(u32, EnumeratePixelsMut<'a, P>)> {
548        let y = self.y;
549        self.y += 1;
550        self.rows.next().map(|r| {
551            (
552                y,
553                EnumeratePixelsMut {
554                    x: 0,
555                    y,
556                    width: self.width,
557                    pixels: r,
558                },
559            )
560        })
561    }
562
563    #[inline(always)]
564    fn size_hint(&self) -> (usize, Option<usize>) {
565        let len = self.len();
566        (len, Some(len))
567    }
568}
569
570impl<'a, P: Pixel + 'a> ExactSizeIterator for EnumerateRowsMut<'a, P>
571where
572    P::Subpixel: 'a,
573{
574    fn len(&self) -> usize {
575        self.rows.len()
576    }
577}
578
579impl<P: Pixel> fmt::Debug for EnumerateRowsMut<'_, P>
580where
581    P::Subpixel: fmt::Debug,
582{
583    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
584        f.debug_struct("EnumerateRowsMut")
585            .field("rows", &self.rows)
586            .field("y", &self.y)
587            .field("width", &self.width)
588            .finish()
589    }
590}
591
592/// Generic image buffer
593///
594/// This is an image parameterised by its Pixel types, represented by a width and height and a
595/// container of channel data. It provides direct access to its pixels and implements the
596/// [`GenericImageView`] and [`GenericImage`] traits. In many ways, this is the standard buffer
597/// implementing those traits. Using this concrete type instead of a generic type parameter has
598/// been shown to improve performance.
599///
600/// The crate defines a few type aliases with regularly used pixel types for your convenience, such
601/// as [`RgbImage`], [`GrayImage`] etc.
602///
603/// [`GenericImage`]: trait.GenericImage.html
604/// [`GenericImageView`]: trait.GenericImageView.html
605/// [`RgbImage`]: type.RgbImage.html
606/// [`GrayImage`]: type.GrayImage.html
607///
608/// To convert between images of different Pixel types use [`DynamicImage`].
609///
610/// You can retrieve a complete description of the buffer's layout and contents through
611/// [`as_flat_samples`] and [`as_flat_samples_mut`]. This can be handy to also use the contents in
612/// a foreign language, map it as a GPU host buffer or other similar tasks.
613///
614/// [`DynamicImage`]: enum.DynamicImage.html
615/// [`as_flat_samples`]: #method.as_flat_samples
616/// [`as_flat_samples_mut`]: #method.as_flat_samples_mut
617///
618/// ## Examples
619///
620/// Create a simple canvas and paint a small cross.
621///
622/// ```
623/// use image::{RgbImage, Rgb};
624///
625/// let mut img = RgbImage::new(32, 32);
626///
627/// for x in 15..=17 {
628///     for y in 8..24 {
629///         img.put_pixel(x, y, Rgb([255, 0, 0]));
630///         img.put_pixel(y, x, Rgb([255, 0, 0]));
631///     }
632/// }
633/// ```
634///
635/// Overlays an image on top of a larger background raster.
636///
637/// ```no_run
638/// use image::{GenericImage, GenericImageView, ImageBuffer, open};
639///
640/// let on_top = open("path/to/some.png").unwrap().into_rgb8();
641/// let mut img = ImageBuffer::from_fn(512, 512, |x, y| {
642///     if (x + y) % 2 == 0 {
643///         image::Rgb([0, 0, 0])
644///     } else {
645///         image::Rgb([255, 255, 255])
646///     }
647/// });
648///
649/// image::imageops::overlay(&mut img, &on_top, 128, 128);
650/// ```
651///
652/// Convert an `RgbaImage` to a `GrayImage`.
653///
654/// ```no_run
655/// use image::{open, DynamicImage};
656///
657/// let rgba = open("path/to/some.png").unwrap().into_rgba8();
658/// let gray = DynamicImage::ImageRgba8(rgba).into_luma8();
659/// ```
660#[derive(Debug, Hash, PartialEq, Eq)]
661pub struct ImageBuffer<P: Pixel, Container> {
662    width: u32,
663    height: u32,
664    _phantom: PhantomData<P>,
665    color: CicpRgb,
666    data: Container,
667}
668
669// generic implementation, shared along all image buffers
670impl<P, Container> ImageBuffer<P, Container>
671where
672    P: Pixel,
673    Container: Deref<Target = [P::Subpixel]>,
674{
675    /// Constructs a buffer from a generic container
676    /// (for example a `Vec` or a slice)
677    ///
678    /// Returns `None` if the container is not big enough (including when the image dimensions
679    /// necessitate an allocation of more bytes than supported by the container).
680    pub fn from_raw(width: u32, height: u32, buf: Container) -> Option<ImageBuffer<P, Container>> {
681        if Self::check_image_fits(width, height, buf.len()) {
682            Some(ImageBuffer {
683                data: buf,
684                width,
685                height,
686                color: Cicp::SRGB.into_rgb(),
687                _phantom: PhantomData,
688            })
689        } else {
690            None
691        }
692    }
693
694    /// Returns the underlying raw buffer
695    pub fn into_raw(self) -> Container {
696        self.data
697    }
698
699    /// Returns the underlying raw buffer
700    pub fn as_raw(&self) -> &Container {
701        &self.data
702    }
703
704    /// The width and height of this image.
705    pub fn dimensions(&self) -> (u32, u32) {
706        (self.width, self.height)
707    }
708
709    /// The width of this image.
710    pub fn width(&self) -> u32 {
711        self.width
712    }
713
714    /// The height of this image.
715    pub fn height(&self) -> u32 {
716        self.height
717    }
718
719    // TODO: choose name under which to expose.
720    pub(crate) fn inner_pixels(&self) -> &[P::Subpixel] {
721        let len = Self::image_buffer_len(self.width, self.height).unwrap();
722        &self.data[..len]
723    }
724
725    /// Returns an iterator over the pixels of this image.
726    /// The iteration order is x = 0 to width then y = 0 to height
727    pub fn pixels(&self) -> Pixels<'_, P> {
728        Pixels {
729            chunks: self
730                .inner_pixels()
731                .chunks_exact(<P as Pixel>::CHANNEL_COUNT as usize),
732        }
733    }
734
735    /// Returns an iterator over the rows of this image.
736    ///
737    /// Only non-empty rows can be iterated in this manner. In particular the iterator will not
738    /// yield any item when the width of the image is `0` or a pixel type without any channels is
739    /// used. This ensures that its length can always be represented by `usize`.
740    pub fn rows(&self) -> Rows<'_, P> {
741        Rows::with_image(&self.data, self.width, self.height)
742    }
743
744    /// Enumerates over the pixels of the image.
745    /// The iterator yields the coordinates of each pixel
746    /// along with a reference to them.
747    /// The iteration order is x = 0 to width then y = 0 to height
748    /// Starting from the top left.
749    pub fn enumerate_pixels(&self) -> EnumeratePixels<'_, P> {
750        EnumeratePixels {
751            pixels: self.pixels(),
752            x: 0,
753            y: 0,
754            width: self.width,
755        }
756    }
757
758    /// Enumerates over the rows of the image.
759    /// The iterator yields the y-coordinate of each row
760    /// along with a reference to them.
761    pub fn enumerate_rows(&self) -> EnumerateRows<'_, P> {
762        EnumerateRows {
763            rows: self.rows(),
764            y: 0,
765            width: self.width,
766        }
767    }
768
769    /// Gets a reference to the pixel at location `(x, y)`
770    ///
771    /// # Panics
772    ///
773    /// Panics if `(x, y)` is out of the bounds `(width, height)`.
774    #[inline]
775    #[track_caller]
776    pub fn get_pixel(&self, x: u32, y: u32) -> &P {
777        match self.pixel_indices(x, y) {
778            None => panic!(
779                "Image index {:?} out of bounds {:?}",
780                (x, y),
781                (self.width, self.height)
782            ),
783            Some(pixel_indices) => <P as Pixel>::from_slice(&self.data[pixel_indices]),
784        }
785    }
786
787    /// Gets a reference to the pixel at location `(x, y)` or returns `None` if
788    /// the index is out of the bounds `(width, height)`.
789    pub fn get_pixel_checked(&self, x: u32, y: u32) -> Option<&P> {
790        if x >= self.width {
791            return None;
792        }
793        let num_channels = <P as Pixel>::CHANNEL_COUNT as usize;
794        let i = (y as usize)
795            .saturating_mul(self.width as usize)
796            .saturating_add(x as usize)
797            .saturating_mul(num_channels);
798
799        self.data
800            .get(i..i.checked_add(num_channels)?)
801            .map(|pixel_indices| <P as Pixel>::from_slice(pixel_indices))
802    }
803
804    /// Test that the image fits inside the buffer.
805    ///
806    /// Verifies that the maximum image of pixels inside the bounds is smaller than the provided
807    /// length. Note that as a corrolary we also have that the index calculation of pixels inside
808    /// the bounds will not overflow.
809    fn check_image_fits(width: u32, height: u32, len: usize) -> bool {
810        let checked_len = Self::image_buffer_len(width, height);
811        checked_len.is_some_and(|min_len| min_len <= len)
812    }
813
814    fn image_buffer_len(width: u32, height: u32) -> Option<usize> {
815        Some(<P as Pixel>::CHANNEL_COUNT as usize)
816            .and_then(|size| size.checked_mul(width as usize))
817            .and_then(|size| size.checked_mul(height as usize))
818    }
819
820    #[inline(always)]
821    fn pixel_indices(&self, x: u32, y: u32) -> Option<Range<usize>> {
822        if x >= self.width || y >= self.height {
823            return None;
824        }
825
826        Some(self.pixel_indices_unchecked(x, y))
827    }
828
829    #[inline(always)]
830    fn pixel_indices_unchecked(&self, x: u32, y: u32) -> Range<usize> {
831        let no_channels = <P as Pixel>::CHANNEL_COUNT as usize;
832        // If in bounds, this can't overflow as we have tested that at construction!
833        let min_index = (y as usize * self.width as usize + x as usize) * no_channels;
834        min_index..min_index + no_channels
835    }
836
837    /// Get the format of the buffer when viewed as a matrix of samples.
838    pub fn sample_layout(&self) -> SampleLayout {
839        // None of these can overflow, as all our memory is addressable.
840        SampleLayout::row_major_packed(<P as Pixel>::CHANNEL_COUNT, self.width, self.height)
841    }
842
843    /// Return the raw sample buffer with its stride an dimension information.
844    ///
845    /// The returned buffer is guaranteed to be well formed in all cases. It is laid out by
846    /// colors, width then height, meaning `channel_stride <= width_stride <= height_stride`. All
847    /// strides are in numbers of elements but those are mostly `u8` in which case the strides are
848    /// also byte strides.
849    pub fn into_flat_samples(self) -> FlatSamples<Container>
850    where
851        Container: AsRef<[P::Subpixel]>,
852    {
853        // None of these can overflow, as all our memory is addressable.
854        let layout = self.sample_layout();
855        FlatSamples {
856            samples: self.data,
857            layout,
858            color_hint: None, // TODO: the pixel type might contain P::COLOR_TYPE if it satisfies PixelWithColorType
859        }
860    }
861
862    /// Return a view on the raw sample buffer.
863    ///
864    /// See [`into_flat_samples`](#method.into_flat_samples) for more details.
865    pub fn as_flat_samples(&self) -> FlatSamples<&[P::Subpixel]> {
866        let layout = self.sample_layout();
867        FlatSamples {
868            samples: self.data.as_ref(),
869            layout,
870            color_hint: None, // TODO: the pixel type might contain P::COLOR_TYPE if it satisfies PixelWithColorType
871        }
872    }
873
874    /// Return a mutable view on the raw sample buffer.
875    ///
876    /// See [`into_flat_samples`](#method.into_flat_samples) for more details.
877    pub fn as_flat_samples_mut(&mut self) -> FlatSamples<&mut [P::Subpixel]>
878    where
879        Container: AsMut<[P::Subpixel]>,
880    {
881        let layout = self.sample_layout();
882        FlatSamples {
883            samples: self.data.as_mut(),
884            layout,
885            color_hint: None, // TODO: the pixel type might contain P::COLOR_TYPE if it satisfies PixelWithColorType
886        }
887    }
888}
889
890impl<P, Container> ImageBuffer<P, Container>
891where
892    P: Pixel,
893    Container: Deref<Target = [P::Subpixel]> + DerefMut,
894{
895    // TODO: choose name under which to expose.
896    pub(crate) fn inner_pixels_mut(&mut self) -> &mut [P::Subpixel] {
897        let len = Self::image_buffer_len(self.width, self.height).unwrap();
898        &mut self.data[..len]
899    }
900
901    /// Returns an iterator over the mutable pixels of this image.
902    pub fn pixels_mut(&mut self) -> PixelsMut<'_, P> {
903        PixelsMut {
904            chunks: self
905                .inner_pixels_mut()
906                .chunks_exact_mut(<P as Pixel>::CHANNEL_COUNT as usize),
907        }
908    }
909
910    /// Returns an iterator over the mutable rows of this image.
911    ///
912    /// Only non-empty rows can be iterated in this manner. In particular the iterator will not
913    /// yield any item when the width of the image is `0` or a pixel type without any channels is
914    /// used. This ensures that its length can always be represented by `usize`.
915    pub fn rows_mut(&mut self) -> RowsMut<'_, P> {
916        RowsMut::with_image(&mut self.data, self.width, self.height)
917    }
918
919    /// Enumerates over the pixels of the image.
920    /// The iterator yields the coordinates of each pixel
921    /// along with a mutable reference to them.
922    pub fn enumerate_pixels_mut(&mut self) -> EnumeratePixelsMut<'_, P> {
923        let width = self.width;
924        EnumeratePixelsMut {
925            pixels: self.pixels_mut(),
926            x: 0,
927            y: 0,
928            width,
929        }
930    }
931
932    /// Enumerates over the rows of the image.
933    /// The iterator yields the y-coordinate of each row
934    /// along with a mutable reference to them.
935    pub fn enumerate_rows_mut(&mut self) -> EnumerateRowsMut<'_, P> {
936        let width = self.width;
937        EnumerateRowsMut {
938            rows: self.rows_mut(),
939            y: 0,
940            width,
941        }
942    }
943
944    /// Gets a reference to the mutable pixel at location `(x, y)`
945    ///
946    /// # Panics
947    ///
948    /// Panics if `(x, y)` is out of the bounds `(width, height)`.
949    #[inline]
950    #[track_caller]
951    pub fn get_pixel_mut(&mut self, x: u32, y: u32) -> &mut P {
952        match self.pixel_indices(x, y) {
953            None => panic!(
954                "Image index {:?} out of bounds {:?}",
955                (x, y),
956                (self.width, self.height)
957            ),
958            Some(pixel_indices) => <P as Pixel>::from_slice_mut(&mut self.data[pixel_indices]),
959        }
960    }
961
962    /// Gets a reference to the mutable pixel at location `(x, y)` or returns
963    /// `None` if the index is out of the bounds `(width, height)`.
964    pub fn get_pixel_mut_checked(&mut self, x: u32, y: u32) -> Option<&mut P> {
965        if x >= self.width {
966            return None;
967        }
968        let num_channels = <P as Pixel>::CHANNEL_COUNT as usize;
969        let i = (y as usize)
970            .saturating_mul(self.width as usize)
971            .saturating_add(x as usize)
972            .saturating_mul(num_channels);
973
974        self.data
975            .get_mut(i..i.checked_add(num_channels)?)
976            .map(|pixel_indices| <P as Pixel>::from_slice_mut(pixel_indices))
977    }
978
979    /// Puts a pixel at location `(x, y)`
980    ///
981    /// # Panics
982    ///
983    /// Panics if `(x, y)` is out of the bounds `(width, height)`.
984    #[inline]
985    #[track_caller]
986    pub fn put_pixel(&mut self, x: u32, y: u32, pixel: P) {
987        *self.get_pixel_mut(x, y) = pixel;
988    }
989}
990
991impl<P: Pixel, Container> ImageBuffer<P, Container> {
992    /// Define the color space for the image.
993    ///
994    /// The color data is unchanged. Reinterprets the existing red, blue, green channels as points
995    /// in the new set of primary colors, changing the apparent shade of pixels.
996    ///
997    /// Note that the primaries also define a reference whitepoint When this buffer contains Luma
998    /// data, the luminance channel is interpreted as the `Y` channel of a related `YCbCr` color
999    /// space as if by a non-constant chromaticity derived matrix. That is, coefficients are *not*
1000    /// applied in the linear RGB space but use encoded channel values. (In a color space with the
1001    /// linear transfer function there is no difference).
1002    ///
1003    /// The default color space is [`Cicp::SRGB`].
1004    pub fn set_rgb_primaries(&mut self, color: CicpColorPrimaries) {
1005        self.color.primaries = color;
1006    }
1007
1008    /// Define the transfer function for the image.
1009    ///
1010    /// The color data is unchanged. Reinterprets all (non-alpha) components in the image,
1011    /// potentially changing the apparent shade of pixels. Individual components are always
1012    /// interpreted as encoded numbers. To denote numbers in a linear RGB space, use
1013    /// [`CicpTransferCharacteristics::Linear`].
1014    ///
1015    /// The default color space is [`Cicp::SRGB`].
1016    pub fn set_transfer_function(&mut self, tf: CicpTransferCharacteristics) {
1017        self.color.transfer = tf;
1018    }
1019
1020    /// Get the Cicp encoding of this buffer's color data.
1021    pub fn color_space(&self) -> Cicp {
1022        self.color.into()
1023    }
1024
1025    /// Set primaries and transfer characteristics from a Cicp color space.
1026    ///
1027    /// Returns an error if `cicp` uses features that are not support with an RGB color space, e.g.
1028    /// a matrix or narrow range (studio encoding) channels.
1029    pub fn set_color_space(&mut self, cicp: Cicp) -> ImageResult<()> {
1030        self.color = cicp.try_into_rgb()?;
1031        Ok(())
1032    }
1033
1034    pub(crate) fn set_rgb_color_space(&mut self, color: CicpRgb) {
1035        self.color = color;
1036    }
1037}
1038
1039impl<P, Container> ImageBuffer<P, Container>
1040where
1041    P: Pixel,
1042    [P::Subpixel]: EncodableLayout,
1043    Container: Deref<Target = [P::Subpixel]>,
1044{
1045    /// Saves the buffer to a file at the path specified.
1046    ///
1047    /// The image format is derived from the file extension.
1048    pub fn save<Q>(&self, path: Q) -> ImageResult<()>
1049    where
1050        Q: AsRef<Path>,
1051        P: PixelWithColorType,
1052    {
1053        save_buffer(
1054            path,
1055            self.inner_pixels().as_bytes(),
1056            self.width(),
1057            self.height(),
1058            <P as PixelWithColorType>::COLOR_TYPE,
1059        )
1060    }
1061}
1062
1063impl<P, Container> ImageBuffer<P, Container>
1064where
1065    P: Pixel,
1066    [P::Subpixel]: EncodableLayout,
1067    Container: Deref<Target = [P::Subpixel]>,
1068{
1069    /// Saves the buffer to a file at the specified path in
1070    /// the specified format.
1071    ///
1072    /// See [`save_buffer_with_format`](fn.save_buffer_with_format.html) for
1073    /// supported types.
1074    pub fn save_with_format<Q>(&self, path: Q, format: ImageFormat) -> ImageResult<()>
1075    where
1076        Q: AsRef<Path>,
1077        P: PixelWithColorType,
1078    {
1079        // This is valid as the subpixel is u8.
1080        save_buffer_with_format(
1081            path,
1082            self.inner_pixels().as_bytes(),
1083            self.width(),
1084            self.height(),
1085            <P as PixelWithColorType>::COLOR_TYPE,
1086            format,
1087        )
1088    }
1089}
1090
1091impl<P, Container> ImageBuffer<P, Container>
1092where
1093    P: Pixel,
1094    [P::Subpixel]: EncodableLayout,
1095    Container: Deref<Target = [P::Subpixel]>,
1096{
1097    /// Writes the buffer to a writer in the specified format.
1098    ///
1099    /// Assumes the writer is buffered. In most cases, you should wrap your writer in a `BufWriter`
1100    /// for best performance.
1101    pub fn write_to<W>(&self, writer: &mut W, format: ImageFormat) -> ImageResult<()>
1102    where
1103        W: std::io::Write + std::io::Seek,
1104        P: PixelWithColorType,
1105    {
1106        // This is valid as the subpixel is u8.
1107        write_buffer_with_format(
1108            writer,
1109            self.inner_pixels().as_bytes(),
1110            self.width(),
1111            self.height(),
1112            <P as PixelWithColorType>::COLOR_TYPE,
1113            format,
1114        )
1115    }
1116}
1117
1118impl<P, Container> ImageBuffer<P, Container>
1119where
1120    P: Pixel,
1121    [P::Subpixel]: EncodableLayout,
1122    Container: Deref<Target = [P::Subpixel]>,
1123{
1124    /// Writes the buffer with the given encoder.
1125    pub fn write_with_encoder<E>(&self, encoder: E) -> ImageResult<()>
1126    where
1127        E: ImageEncoder,
1128        P: PixelWithColorType,
1129    {
1130        // This is valid as the subpixel is u8.
1131        encoder.write_image(
1132            self.inner_pixels().as_bytes(),
1133            self.width(),
1134            self.height(),
1135            <P as PixelWithColorType>::COLOR_TYPE,
1136        )
1137    }
1138}
1139
1140impl<P, Container> Default for ImageBuffer<P, Container>
1141where
1142    P: Pixel,
1143    Container: Default,
1144{
1145    fn default() -> Self {
1146        Self {
1147            width: 0,
1148            height: 0,
1149            _phantom: PhantomData,
1150            color: Cicp::SRGB_LINEAR.into_rgb(),
1151            data: Default::default(),
1152        }
1153    }
1154}
1155
1156impl<P, Container> Deref for ImageBuffer<P, Container>
1157where
1158    P: Pixel,
1159    Container: Deref<Target = [P::Subpixel]>,
1160{
1161    type Target = [P::Subpixel];
1162
1163    fn deref(&self) -> &<Self as Deref>::Target {
1164        &self.data
1165    }
1166}
1167
1168impl<P, Container> DerefMut for ImageBuffer<P, Container>
1169where
1170    P: Pixel,
1171    Container: Deref<Target = [P::Subpixel]> + DerefMut,
1172{
1173    fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {
1174        &mut self.data
1175    }
1176}
1177
1178impl<P, Container> Index<(u32, u32)> for ImageBuffer<P, Container>
1179where
1180    P: Pixel,
1181    Container: Deref<Target = [P::Subpixel]>,
1182{
1183    type Output = P;
1184
1185    fn index(&self, (x, y): (u32, u32)) -> &P {
1186        self.get_pixel(x, y)
1187    }
1188}
1189
1190impl<P, Container> IndexMut<(u32, u32)> for ImageBuffer<P, Container>
1191where
1192    P: Pixel,
1193    Container: Deref<Target = [P::Subpixel]> + DerefMut,
1194{
1195    fn index_mut(&mut self, (x, y): (u32, u32)) -> &mut P {
1196        self.get_pixel_mut(x, y)
1197    }
1198}
1199
1200impl<P, Container> Clone for ImageBuffer<P, Container>
1201where
1202    P: Pixel,
1203    Container: Deref<Target = [P::Subpixel]> + Clone,
1204{
1205    fn clone(&self) -> ImageBuffer<P, Container> {
1206        ImageBuffer {
1207            data: self.data.clone(),
1208            width: self.width,
1209            height: self.height,
1210            color: self.color,
1211            _phantom: PhantomData,
1212        }
1213    }
1214
1215    fn clone_from(&mut self, source: &Self) {
1216        self.data.clone_from(&source.data);
1217        self.width = source.width;
1218        self.height = source.height;
1219        self.color = source.color;
1220    }
1221}
1222
1223impl<P, Container> GenericImageView for ImageBuffer<P, Container>
1224where
1225    P: Pixel,
1226    Container: Deref<Target = [P::Subpixel]> + Deref,
1227{
1228    type Pixel = P;
1229
1230    fn dimensions(&self) -> (u32, u32) {
1231        self.dimensions()
1232    }
1233
1234    fn get_pixel(&self, x: u32, y: u32) -> P {
1235        *self.get_pixel(x, y)
1236    }
1237
1238    fn to_pixel_view(&self) -> Option<ViewOfPixel<'_, Self::Pixel>> {
1239        self.as_flat_samples().into_view().ok()
1240    }
1241
1242    /// Returns the pixel located at (x, y), ignoring bounds checking.
1243    #[inline(always)]
1244    unsafe fn unsafe_get_pixel(&self, x: u32, y: u32) -> P {
1245        let indices = self.pixel_indices_unchecked(x, y);
1246        *<P as Pixel>::from_slice(self.data.get_unchecked(indices))
1247    }
1248
1249    fn buffer_with_dimensions(&self, width: u32, height: u32) -> ImageBuffer<P, Vec<P::Subpixel>> {
1250        let mut buffer = ImageBuffer::new(width, height);
1251        buffer.copy_color_space_from(self);
1252        buffer
1253    }
1254}
1255
1256impl<P, Container> GenericImage for ImageBuffer<P, Container>
1257where
1258    P: Pixel,
1259    Container: Deref<Target = [P::Subpixel]> + DerefMut,
1260{
1261    fn get_pixel_mut(&mut self, x: u32, y: u32) -> &mut P {
1262        self.get_pixel_mut(x, y)
1263    }
1264
1265    fn put_pixel(&mut self, x: u32, y: u32, pixel: P) {
1266        *self.get_pixel_mut(x, y) = pixel;
1267    }
1268
1269    /// Puts a pixel at location (x, y), ignoring bounds checking.
1270    #[inline(always)]
1271    unsafe fn unsafe_put_pixel(&mut self, x: u32, y: u32, pixel: P) {
1272        let indices = self.pixel_indices_unchecked(x, y);
1273        let p = <P as Pixel>::from_slice_mut(self.data.get_unchecked_mut(indices));
1274        *p = pixel;
1275    }
1276
1277    /// Put a pixel at location (x, y), taking into account alpha channels
1278    ///
1279    /// DEPRECATED: This method will be removed. Blend the pixel directly instead.
1280    fn blend_pixel(&mut self, x: u32, y: u32, p: P) {
1281        self.get_pixel_mut(x, y).blend(&p);
1282    }
1283
1284    fn copy_from_samples(
1285        &mut self,
1286        view: ViewOfPixel<'_, Self::Pixel>,
1287        x: u32,
1288        y: u32,
1289    ) -> ImageResult<()> {
1290        let (width, height) = view.dimensions();
1291        let pix_stride = usize::from(<Self::Pixel as Pixel>::CHANNEL_COUNT);
1292        Rect::from_image_at(&view, x, y).test_in_bounds(self)?;
1293
1294        if width == 0 || height == 0 || pix_stride == 0 {
1295            return Ok(());
1296        }
1297
1298        // Since this image is not empty, all its indices fit into `usize` as they address the
1299        // memory resident buffer of `self`.
1300        let row_len = width as usize * pix_stride;
1301        let img_sh = self.width as usize;
1302
1303        let (sw, sh) = view.strides_wh();
1304        let view_samples: &[_] = view.samples();
1305        let inner = self.inner_pixels_mut();
1306
1307        let img_pixel_indices_unchecked =
1308            |x: u32, y: u32| (y as usize * img_sh + x as usize) * pix_stride;
1309
1310        // Can we use row-by-row byte copy?
1311        if sw == pix_stride {
1312            for j in 0..height {
1313                let start = img_pixel_indices_unchecked(x, j + y);
1314                let img_row = &mut inner[start..][..row_len];
1315                let view_row = &view_samples[j as usize * sh..][..row_len];
1316                img_row.copy_from_slice(view_row);
1317            }
1318
1319            return Ok(());
1320        }
1321
1322        // Fallback behavior.
1323        for j in 0..height {
1324            let img_start = img_pixel_indices_unchecked(x, j + y);
1325            let img_row = &mut inner[img_start..][..row_len];
1326            let pixels = img_row.chunks_exact_mut(pix_stride);
1327
1328            let view_start = j as usize * sh;
1329
1330            for (i, sp) in pixels.enumerate() {
1331                let view_pixel = &view_samples[i * sw + view_start..][..pix_stride];
1332                sp.copy_from_slice(view_pixel);
1333            }
1334        }
1335
1336        Ok(())
1337    }
1338
1339    fn copy_within(&mut self, source: Rect, x: u32, y: u32) -> bool {
1340        let Rect {
1341            x: sx,
1342            y: sy,
1343            width,
1344            height,
1345        } = source;
1346        let dx = x;
1347        let dy = y;
1348        assert!(sx < self.width() && dx < self.width());
1349        assert!(sy < self.height() && dy < self.height());
1350        if self.width() - dx.max(sx) < width || self.height() - dy.max(sy) < height {
1351            return false;
1352        }
1353
1354        if sy < dy {
1355            for y in (0..height).rev() {
1356                let sy = sy + y;
1357                let dy = dy + y;
1358                let Range { start, .. } = self.pixel_indices_unchecked(sx, sy);
1359                let Range { end, .. } = self.pixel_indices_unchecked(sx + width - 1, sy);
1360                let dst = self.pixel_indices_unchecked(dx, dy).start;
1361                self.data.copy_within(start..end, dst);
1362            }
1363        } else {
1364            for y in 0..height {
1365                let sy = sy + y;
1366                let dy = dy + y;
1367                let Range { start, .. } = self.pixel_indices_unchecked(sx, sy);
1368                let Range { end, .. } = self.pixel_indices_unchecked(sx + width - 1, sy);
1369                let dst = self.pixel_indices_unchecked(dx, dy).start;
1370                self.data.copy_within(start..end, dst);
1371            }
1372        }
1373        true
1374    }
1375}
1376
1377// concrete implementation for `Vec`-backed buffers
1378// TODO: I think that rustc does not "see" this impl any more: the impl with
1379// Container meets the same requirements. At least, I got compile errors that
1380// there is no such function as `into_vec`, whereas `into_raw` did work, and
1381// `into_vec` is redundant anyway, because `into_raw` will give you the vector,
1382// and it is more generic.
1383impl<P: Pixel> ImageBuffer<P, Vec<P::Subpixel>> {
1384    /// Creates a new image buffer based on a `Vec<P::Subpixel>`.
1385    ///
1386    /// all the pixels of this image have a value of zero, regardless of the data type or number of channels.
1387    ///
1388    /// The color space is initially set to [`sRGB`][`Cicp::SRGB`].
1389    ///
1390    /// # Panics
1391    ///
1392    /// Panics when the resulting image is larger than the maximum size of a vector.
1393    #[must_use]
1394    pub fn new(width: u32, height: u32) -> ImageBuffer<P, Vec<P::Subpixel>> {
1395        let size = Self::image_buffer_len(width, height)
1396            .expect("Buffer length in `ImageBuffer::new` overflows usize");
1397        ImageBuffer {
1398            data: vec![Zero::zero(); size],
1399            width,
1400            height,
1401            color: Cicp::SRGB.into_rgb(),
1402            _phantom: PhantomData,
1403        }
1404    }
1405
1406    /// Constructs a new `ImageBuffer` by copying a pixel
1407    ///
1408    /// # Panics
1409    ///
1410    /// Panics when the resulting image is larger than the maximum size of a vector.
1411    pub fn from_pixel(width: u32, height: u32, pixel: P) -> ImageBuffer<P, Vec<P::Subpixel>> {
1412        let mut buf = ImageBuffer::new(width, height);
1413        for p in buf.pixels_mut() {
1414            *p = pixel;
1415        }
1416        buf
1417    }
1418
1419    /// Constructs a new `ImageBuffer` by repeated application of the supplied function.
1420    ///
1421    /// The arguments to the function are the pixel's x and y coordinates.
1422    ///
1423    /// # Panics
1424    ///
1425    /// Panics when the resulting image is larger than the maximum size of a vector.
1426    pub fn from_fn<F>(width: u32, height: u32, mut f: F) -> ImageBuffer<P, Vec<P::Subpixel>>
1427    where
1428        F: FnMut(u32, u32) -> P,
1429    {
1430        let mut buf = ImageBuffer::new(width, height);
1431        for (x, y, p) in buf.enumerate_pixels_mut() {
1432            *p = f(x, y);
1433        }
1434        buf
1435    }
1436
1437    /// Creates an image buffer out of an existing buffer.
1438    /// Returns None if the buffer is not big enough.
1439    #[must_use]
1440    pub fn from_vec(
1441        width: u32,
1442        height: u32,
1443        buf: Vec<P::Subpixel>,
1444    ) -> Option<ImageBuffer<P, Vec<P::Subpixel>>> {
1445        ImageBuffer::from_raw(width, height, buf)
1446    }
1447
1448    /// Consumes the image buffer and returns the underlying data
1449    /// as an owned buffer
1450    #[must_use]
1451    pub fn into_vec(self) -> Vec<P::Subpixel> {
1452        self.into_raw()
1453    }
1454
1455    /// Transfer the meta data, not the pixel values.
1456    ///
1457    /// This will reinterpret all the pixels.
1458    ///
1459    /// We may want to export this but under what name?
1460    pub(crate) fn copy_color_space_from<O: Pixel, C>(&mut self, other: &ImageBuffer<O, C>) {
1461        self.color = other.color;
1462    }
1463}
1464
1465impl<S, Container> ImageBuffer<Rgb<S>, Container>
1466where
1467    Rgb<S>: PixelWithColorType<Subpixel = S>,
1468    Container: DerefMut<Target = [S]>,
1469{
1470    /// Construct an image by swapping `Bgr` channels into an `Rgb` order.
1471    pub fn from_raw_bgr(width: u32, height: u32, container: Container) -> Option<Self> {
1472        let mut img = Self::from_raw(width, height, container)?;
1473
1474        for pix in img.pixels_mut() {
1475            pix.0.reverse();
1476        }
1477
1478        Some(img)
1479    }
1480
1481    /// Return the underlying raw buffer after converting it into `Bgr` channel order.
1482    pub fn into_raw_bgr(mut self) -> Container {
1483        for pix in self.pixels_mut() {
1484            pix.0.reverse();
1485        }
1486
1487        self.into_raw()
1488    }
1489}
1490
1491impl<S, Container> ImageBuffer<Rgba<S>, Container>
1492where
1493    Rgba<S>: PixelWithColorType<Subpixel = S>,
1494    Container: DerefMut<Target = [S]>,
1495{
1496    /// Construct an image by swapping `BgrA` channels into an `RgbA` order.
1497    pub fn from_raw_bgra(width: u32, height: u32, container: Container) -> Option<Self> {
1498        let mut img = Self::from_raw(width, height, container)?;
1499
1500        for pix in img.pixels_mut() {
1501            pix.0[..3].reverse();
1502        }
1503
1504        Some(img)
1505    }
1506
1507    /// Return the underlying raw buffer after converting it into `BgrA` channel order.
1508    pub fn into_raw_bgra(mut self) -> Container {
1509        for pix in self.pixels_mut() {
1510            pix.0[..3].reverse();
1511        }
1512
1513        self.into_raw()
1514    }
1515}
1516
1517/// Provides color conversions for whole image buffers.
1518pub trait ConvertBuffer<T> {
1519    /// Converts `self` to a buffer of type T
1520    ///
1521    /// A generic implementation is provided to convert any image buffer to a image buffer
1522    /// based on a `Vec<T>`.
1523    fn convert(&self) -> T;
1524}
1525
1526// concrete implementation Luma -> Rgba
1527impl GrayImage {
1528    /// Expands a color palette by re-using the existing buffer.
1529    /// Assumes 8 bit per pixel. Uses an optionally transparent index to
1530    /// adjust it's alpha value accordingly.
1531    #[must_use]
1532    pub fn expand_palette(
1533        self,
1534        palette: &[(u8, u8, u8)],
1535        transparent_idx: Option<u8>,
1536    ) -> RgbaImage {
1537        let (width, height) = self.dimensions();
1538        let mut data = self.into_raw();
1539        let entries = data.len();
1540        data.resize(entries.checked_mul(4).unwrap(), 0);
1541        let mut buffer = ImageBuffer::from_vec(width, height, data).unwrap();
1542        expand_packed(&mut buffer, 4, 8, |idx, pixel| {
1543            let (r, g, b) = palette[idx as usize];
1544            let a = if let Some(t_idx) = transparent_idx {
1545                if t_idx == idx {
1546                    0
1547                } else {
1548                    255
1549                }
1550            } else {
1551                255
1552            };
1553            pixel[0] = r;
1554            pixel[1] = g;
1555            pixel[2] = b;
1556            pixel[3] = a;
1557        });
1558        buffer
1559    }
1560}
1561
1562/// This copies the color space information but is somewhat wrong, in numeric terms this conversion
1563/// fails to actually convert rgb/luma with consistent treatment. But this trait impl is too
1564/// generic to handle it correctly (missing any CICP related parameter for the coefficients) so the
1565/// best effort here is to copy the metadata and have slighly incorrect color. May you've only been
1566/// adding an alpha channel or converting sample types, which is fine.
1567///
1568/// It will very likely be deprecated in a future release.
1569impl<Container, FromType: Pixel, ToType: Pixel>
1570    ConvertBuffer<ImageBuffer<ToType, Vec<ToType::Subpixel>>> for ImageBuffer<FromType, Container>
1571where
1572    Container: Deref<Target = [FromType::Subpixel]>,
1573    ToType: FromColor<FromType>,
1574{
1575    /// # Examples
1576    /// Convert RGB image to gray image.
1577    /// ```no_run
1578    /// use image::buffer::ConvertBuffer;
1579    /// use image::GrayImage;
1580    ///
1581    /// let image_path = "examples/fractal.png";
1582    /// let image = image::open(&image_path)
1583    ///     .expect("Open file failed")
1584    ///     .to_rgba8();
1585    ///
1586    /// let gray_image: GrayImage = image.convert();
1587    /// ```
1588    fn convert(&self) -> ImageBuffer<ToType, Vec<ToType::Subpixel>> {
1589        let mut buffer: ImageBuffer<ToType, Vec<ToType::Subpixel>> =
1590            ImageBuffer::new(self.width, self.height);
1591        buffer.copy_color_space_from(self);
1592        for (to, from) in buffer.pixels_mut().zip(self.pixels()) {
1593            to.from_color(from);
1594        }
1595        buffer
1596    }
1597}
1598
1599/// Inputs to [`ImageBuffer::copy_from_color_space`].
1600#[non_exhaustive]
1601#[derive(Default)]
1602pub struct ConvertColorOptions {
1603    /// A pre-calculated transform. This is only used when the actual colors of the input and
1604    /// output image match the color spaces with which the was constructed.
1605    ///
1606    /// FIXME: Clarify that the transform is cheap to clone, i.e. internally an Arc of precomputed
1607    /// tables and not expensive despite having `Clone`.
1608    pub(crate) transform: Option<CicpTransform>,
1609    /// Make sure we can later add options that are bound to the thread. That does not mean that
1610    /// all attributes will be bound to the thread, only that we can add `!Sync` options later. You
1611    /// should be constructing the options at the call site with each attribute being cheap to move
1612    /// into here.
1613    pub(crate) _auto_traits: PhantomData<std::rc::Rc<()>>,
1614}
1615
1616impl ConvertColorOptions {
1617    pub(crate) fn as_transform(
1618        &mut self,
1619        from_color: Cicp,
1620        into_color: Cicp,
1621    ) -> Result<&CicpTransform, ImageError> {
1622        if let Some(tr) = &self.transform {
1623            tr.check_applicable(from_color, into_color)?;
1624        }
1625
1626        if self.transform.is_none() {
1627            self.transform = CicpTransform::new(from_color, into_color);
1628        }
1629
1630        self.transform.as_ref().ok_or_else(|| {
1631            ImageError::Unsupported(UnsupportedError::from_format_and_kind(
1632                crate::error::ImageFormatHint::Unknown,
1633                // One of them is responsible.
1634                UnsupportedErrorKind::ColorspaceCicp(if from_color.qualify_stability() {
1635                    into_color
1636                } else {
1637                    from_color
1638                }),
1639            ))
1640        })
1641    }
1642
1643    pub(crate) fn as_transform_fn<FromType, IntoType>(
1644        &mut self,
1645        from_color: Cicp,
1646        into_color: Cicp,
1647    ) -> Result<&'_ CicpApplicable<'_, FromType::Subpixel>, ImageError>
1648    where
1649        FromType: PixelWithColorType,
1650        IntoType: PixelWithColorType,
1651    {
1652        Ok(self
1653            .as_transform(from_color, into_color)?
1654            .supported_transform_fn::<FromType, IntoType>())
1655    }
1656}
1657
1658impl<C, SelfPixel: Pixel> ImageBuffer<SelfPixel, C>
1659where
1660    SelfPixel: PixelWithColorType,
1661    C: Deref<Target = [SelfPixel::Subpixel]> + DerefMut,
1662{
1663    /// Convert the color data to another pixel type, the color space.
1664    ///
1665    /// This method is supposed to be called by exposed monomorphized methods, not directly by
1666    /// users. In particular it serves to implement `DynamicImage`'s casts that go beyond those
1667    /// offered by `PixelWithColorType` and include, e.g., `LumaAlpha<f32>`.
1668    ///
1669    /// Before exposing this method, decide if we want a design like [`DynamicImage::to`] (many
1670    /// trait parameters) with color space aware `FromColor` or if we want a design that takes a
1671    /// `ColorType` parameter / `PixelWithColorType`. The latter is not quite as flexible but
1672    /// allows much greater internal changes that do not tie in with the _external_ stable API.
1673    pub(crate) fn cast_in_color_space<IntoPixel>(
1674        &self,
1675    ) -> ImageBuffer<IntoPixel, Vec<IntoPixel::Subpixel>>
1676    where
1677        SelfPixel: Pixel,
1678        IntoPixel: Pixel,
1679        IntoPixel: CicpPixelCast<SelfPixel>,
1680        SelfPixel::Subpixel: ColorComponentForCicp,
1681        IntoPixel::Subpixel: ColorComponentForCicp + FromPrimitive<SelfPixel::Subpixel>,
1682    {
1683        let vec = self
1684            .color
1685            .cast_pixels::<SelfPixel, IntoPixel>(self.inner_pixels(), &|| [0.2126, 0.7152, 0.0722]);
1686        let mut buffer = ImageBuffer::from_vec(self.width, self.height, vec)
1687            .expect("cast_pixels returned the right number of pixels");
1688        buffer.copy_color_space_from(self);
1689        buffer
1690    }
1691
1692    /// Copy pixel data from one buffer to another, calculating equivalent color representations
1693    /// for the target's color space.
1694    ///
1695    /// Returns `Ok` if:
1696    /// - Both images to have the same dimensions, otherwise returns a [`ImageError::Parameter`].
1697    /// - The primaries and transfer functions of both image's color spaces must be supported,
1698    ///   otherwise returns a [`ImageError::Unsupported`].
1699    /// - The pixel's channel layout must be supported for conversion, otherwise returns a
1700    ///   [`ImageError::Unsupported`]. You can rely on RGB and RGBA always being supported. If a
1701    ///   layout is supported for one color space it is supported for all of them.
1702    ///
1703    /// To copy color data of arbitrary channel layouts use `DynamicImage` with the overhead of
1704    /// having data converted into and from RGB representation.
1705    pub fn copy_from_color_space<FromType, D>(
1706        &mut self,
1707        from: &ImageBuffer<FromType, D>,
1708        mut options: ConvertColorOptions,
1709    ) -> ImageResult<()>
1710    where
1711        FromType: Pixel<Subpixel = SelfPixel::Subpixel> + PixelWithColorType,
1712        D: Deref<Target = [SelfPixel::Subpixel]>,
1713    {
1714        if self.dimensions() != from.dimensions() {
1715            return Err(ImageError::Parameter(ParameterError::from_kind(
1716                ParameterErrorKind::DimensionMismatch,
1717            )));
1718        }
1719
1720        let transform = options
1721            .as_transform_fn::<FromType, SelfPixel>(from.color_space(), self.color_space())?;
1722
1723        let from = from.inner_pixels();
1724        let into = self.inner_pixels_mut();
1725
1726        debug_assert_eq!(
1727            from.len() / usize::from(FromType::CHANNEL_COUNT),
1728            into.len() / usize::from(SelfPixel::CHANNEL_COUNT),
1729            "Diverging pixel count despite same size",
1730        );
1731
1732        transform(from, into);
1733
1734        Ok(())
1735    }
1736
1737    /// Convert this buffer into a newly allocated buffer, changing the color representation.
1738    ///
1739    /// This will avoid an allocation if the target layout or the color conversion is not supported
1740    /// (yet).
1741    ///
1742    /// See [`ImageBuffer::copy_from_color_space`] if you intend to assign to an existing buffer,
1743    /// swapping the argument with `self`.
1744    pub fn to_color_space<IntoType>(
1745        &self,
1746        color: Cicp,
1747        mut options: ConvertColorOptions,
1748    ) -> Result<ImageBuffer<IntoType, Vec<SelfPixel::Subpixel>>, ImageError>
1749    where
1750        IntoType: Pixel<Subpixel = SelfPixel::Subpixel> + PixelWithColorType,
1751    {
1752        let transform =
1753            options.as_transform_fn::<SelfPixel, IntoType>(self.color_space(), color)?;
1754
1755        let (width, height) = self.dimensions();
1756        let mut target = ImageBuffer::new(width, height);
1757
1758        let from = self.inner_pixels();
1759        let into = target.inner_pixels_mut();
1760
1761        transform(from, into);
1762
1763        Ok(target)
1764    }
1765
1766    /// Apply a color space to an image, transforming the pixel representation.
1767    pub fn apply_color_space(
1768        &mut self,
1769        color: Cicp,
1770        mut options: ConvertColorOptions,
1771    ) -> ImageResult<()> {
1772        if self.color_space() == color {
1773            return Ok(());
1774        }
1775
1776        let transform =
1777            options.as_transform_fn::<SelfPixel, SelfPixel>(self.color_space(), color)?;
1778
1779        let mut scratch = [<SelfPixel::Subpixel as crate::Primitive>::DEFAULT_MIN_VALUE; 1200];
1780        let chunk_len = scratch.len() / usize::from(<SelfPixel as Pixel>::CHANNEL_COUNT)
1781            * usize::from(<SelfPixel as Pixel>::CHANNEL_COUNT);
1782
1783        for chunk in self.data.chunks_mut(chunk_len) {
1784            let scratch = &mut scratch[..chunk.len()];
1785            scratch.copy_from_slice(chunk);
1786            transform(scratch, chunk);
1787        }
1788
1789        self.color = color.into_rgb();
1790
1791        Ok(())
1792    }
1793}
1794
1795/// Sendable Rgb image buffer
1796pub type RgbImage = ImageBuffer<Rgb<u8>, Vec<u8>>;
1797/// Sendable Rgb + alpha channel image buffer
1798pub type RgbaImage = ImageBuffer<Rgba<u8>, Vec<u8>>;
1799/// Sendable grayscale image buffer
1800pub type GrayImage = ImageBuffer<Luma<u8>, Vec<u8>>;
1801/// Sendable grayscale + alpha channel image buffer
1802pub type GrayAlphaImage = ImageBuffer<LumaA<u8>, Vec<u8>>;
1803/// Sendable 16-bit Rgb image buffer
1804pub(crate) type Rgb16Image = ImageBuffer<Rgb<u16>, Vec<u16>>;
1805/// Sendable 16-bit Rgb + alpha channel image buffer
1806pub(crate) type Rgba16Image = ImageBuffer<Rgba<u16>, Vec<u16>>;
1807/// Sendable 16-bit grayscale image buffer
1808pub(crate) type Gray16Image = ImageBuffer<Luma<u16>, Vec<u16>>;
1809/// Sendable 16-bit grayscale + alpha channel image buffer
1810pub(crate) type GrayAlpha16Image = ImageBuffer<LumaA<u16>, Vec<u16>>;
1811
1812/// An image buffer for 32-bit float RGB pixels,
1813/// where the backing container is a flattened vector of floats.
1814pub type Rgb32FImage = ImageBuffer<Rgb<f32>, Vec<f32>>;
1815
1816/// An image buffer for 32-bit float RGBA pixels,
1817/// where the backing container is a flattened vector of floats.
1818pub type Rgba32FImage = ImageBuffer<Rgba<f32>, Vec<f32>>;
1819
1820impl From<DynamicImage> for RgbImage {
1821    fn from(value: DynamicImage) -> Self {
1822        value.into_rgb8()
1823    }
1824}
1825
1826impl From<DynamicImage> for RgbaImage {
1827    fn from(value: DynamicImage) -> Self {
1828        value.into_rgba8()
1829    }
1830}
1831
1832impl From<DynamicImage> for GrayImage {
1833    fn from(value: DynamicImage) -> Self {
1834        value.into_luma8()
1835    }
1836}
1837
1838impl From<DynamicImage> for GrayAlphaImage {
1839    fn from(value: DynamicImage) -> Self {
1840        value.into_luma_alpha8()
1841    }
1842}
1843
1844impl From<DynamicImage> for Rgb16Image {
1845    fn from(value: DynamicImage) -> Self {
1846        value.into_rgb16()
1847    }
1848}
1849
1850impl From<DynamicImage> for Rgba16Image {
1851    fn from(value: DynamicImage) -> Self {
1852        value.into_rgba16()
1853    }
1854}
1855
1856impl From<DynamicImage> for Gray16Image {
1857    fn from(value: DynamicImage) -> Self {
1858        value.into_luma16()
1859    }
1860}
1861
1862impl From<DynamicImage> for GrayAlpha16Image {
1863    fn from(value: DynamicImage) -> Self {
1864        value.into_luma_alpha16()
1865    }
1866}
1867
1868impl From<DynamicImage> for Rgba32FImage {
1869    fn from(value: DynamicImage) -> Self {
1870        value.into_rgba32f()
1871    }
1872}
1873
1874#[cfg(test)]
1875mod test {
1876    use super::{GrayImage, ImageBuffer, RgbImage};
1877    use crate::math::Rect;
1878    use crate::metadata::Cicp;
1879    use crate::metadata::CicpTransform;
1880    use crate::ImageFormat;
1881    use crate::{GenericImage as _, GenericImageView as _};
1882    use crate::{Luma, LumaA, Pixel, Rgb, Rgba};
1883    use num_traits::Zero;
1884
1885    #[test]
1886    /// Tests if image buffers from slices work
1887    fn slice_buffer() {
1888        let data = [0; 9];
1889        let buf: ImageBuffer<Luma<u8>, _> = ImageBuffer::from_raw(3, 3, &data[..]).unwrap();
1890        assert_eq!(&*buf, &data[..]);
1891    }
1892
1893    macro_rules! new_buffer_zero_test {
1894        ($test_name:ident, $pxt:ty) => {
1895            #[test]
1896            fn $test_name() {
1897                let buffer = ImageBuffer::<$pxt, Vec<<$pxt as Pixel>::Subpixel>>::new(2, 2);
1898                assert!(buffer
1899                    .iter()
1900                    .all(|p| *p == <$pxt as Pixel>::Subpixel::zero()));
1901            }
1902        };
1903    }
1904
1905    new_buffer_zero_test!(luma_u8_zero_test, Luma<u8>);
1906    new_buffer_zero_test!(luma_u16_zero_test, Luma<u16>);
1907    new_buffer_zero_test!(luma_f32_zero_test, Luma<f32>);
1908    new_buffer_zero_test!(luma_a_u8_zero_test, LumaA<u8>);
1909    new_buffer_zero_test!(luma_a_u16_zero_test, LumaA<u16>);
1910    new_buffer_zero_test!(luma_a_f32_zero_test, LumaA<f32>);
1911    new_buffer_zero_test!(rgb_u8_zero_test, Rgb<u8>);
1912    new_buffer_zero_test!(rgb_u16_zero_test, Rgb<u16>);
1913    new_buffer_zero_test!(rgb_f32_zero_test, Rgb<f32>);
1914    new_buffer_zero_test!(rgb_a_u8_zero_test, Rgba<u8>);
1915    new_buffer_zero_test!(rgb_a_u16_zero_test, Rgba<u16>);
1916    new_buffer_zero_test!(rgb_a_f32_zero_test, Rgba<f32>);
1917
1918    #[test]
1919    fn get_pixel() {
1920        let mut a: RgbImage = ImageBuffer::new(10, 10);
1921        {
1922            let b = a.get_mut(3 * 10).unwrap();
1923            *b = 255;
1924        }
1925        assert_eq!(a.get_pixel(0, 1)[0], 255);
1926    }
1927
1928    #[test]
1929    fn get_pixel_checked() {
1930        let mut a: RgbImage = ImageBuffer::new(10, 10);
1931        a.get_pixel_mut_checked(0, 1).unwrap()[0] = 255;
1932
1933        assert_eq!(a.get_pixel_checked(0, 1), Some(&Rgb([255, 0, 0])));
1934        assert_eq!(a.get_pixel_checked(0, 1).unwrap(), a.get_pixel(0, 1));
1935        assert_eq!(a.get_pixel_checked(10, 0), None);
1936        assert_eq!(a.get_pixel_checked(0, 10), None);
1937        assert_eq!(a.get_pixel_mut_checked(10, 0), None);
1938        assert_eq!(a.get_pixel_mut_checked(0, 10), None);
1939
1940        // From image/issues/1672
1941        const WHITE: Rgb<u8> = Rgb([255_u8, 255, 255]);
1942        let mut a = RgbImage::new(2, 1);
1943        a.put_pixel(1, 0, WHITE);
1944
1945        assert_eq!(a.get_pixel_checked(1, 0), Some(&WHITE));
1946        assert_eq!(a.get_pixel_checked(1, 0).unwrap(), a.get_pixel(1, 0));
1947    }
1948
1949    #[test]
1950    fn mut_iter() {
1951        let mut a: RgbImage = ImageBuffer::new(10, 10);
1952        {
1953            let val = a.pixels_mut().next().unwrap();
1954            *val = Rgb([42, 0, 0]);
1955        }
1956        assert_eq!(a.data[0], 42);
1957    }
1958
1959    #[test]
1960    fn zero_width_zero_height() {
1961        let mut image = RgbImage::new(0, 0);
1962
1963        assert_eq!(image.rows_mut().count(), 0);
1964        assert_eq!(image.pixels_mut().count(), 0);
1965        assert_eq!(image.rows().count(), 0);
1966        assert_eq!(image.pixels().count(), 0);
1967    }
1968
1969    #[test]
1970    fn zero_width_nonzero_height() {
1971        let mut image = RgbImage::new(0, 2);
1972
1973        assert_eq!(image.rows_mut().count(), 0);
1974        assert_eq!(image.pixels_mut().count(), 0);
1975        assert_eq!(image.rows().count(), 0);
1976        assert_eq!(image.pixels().count(), 0);
1977    }
1978
1979    #[test]
1980    fn nonzero_width_zero_height() {
1981        let mut image = RgbImage::new(2, 0);
1982
1983        assert_eq!(image.rows_mut().count(), 0);
1984        assert_eq!(image.pixels_mut().count(), 0);
1985        assert_eq!(image.rows().count(), 0);
1986        assert_eq!(image.pixels().count(), 0);
1987    }
1988
1989    #[test]
1990    fn pixels_on_large_buffer() {
1991        let mut image = RgbImage::from_raw(1, 1, vec![0; 6]).unwrap();
1992
1993        assert_eq!(image.pixels().count(), 1);
1994        assert_eq!(image.enumerate_pixels().count(), 1);
1995        assert_eq!(image.pixels_mut().count(), 1);
1996        assert_eq!(image.enumerate_pixels_mut().count(), 1);
1997
1998        assert_eq!(image.rows().count(), 1);
1999        assert_eq!(image.rows_mut().count(), 1);
2000    }
2001
2002    #[test]
2003    fn default() {
2004        let image = ImageBuffer::<Rgb<u8>, Vec<u8>>::default();
2005        assert_eq!(image.dimensions(), (0, 0));
2006    }
2007
2008    #[test]
2009    #[rustfmt::skip]
2010    fn test_image_buffer_copy_within_oob() {
2011        let mut image: GrayImage = ImageBuffer::from_raw(4, 4, vec![0u8; 16]).unwrap();
2012        assert!(!image.copy_within(Rect { x: 0, y: 0, width: 5, height: 4 }, 0, 0));
2013        assert!(!image.copy_within(Rect { x: 0, y: 0, width: 4, height: 5 }, 0, 0));
2014        assert!(!image.copy_within(Rect { x: 1, y: 0, width: 4, height: 4 }, 0, 0));
2015        assert!(!image.copy_within(Rect { x: 0, y: 0, width: 4, height: 4 }, 1, 0));
2016        assert!(!image.copy_within(Rect { x: 0, y: 1, width: 4, height: 4 }, 0, 0));
2017        assert!(!image.copy_within(Rect { x: 0, y: 0, width: 4, height: 4 }, 0, 1));
2018        assert!(!image.copy_within(Rect { x: 1, y: 1, width: 4, height: 4 }, 0, 0));
2019    }
2020
2021    #[test]
2022    fn test_image_buffer_copy_within_tl() {
2023        let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
2024        let expected = [0, 1, 2, 3, 4, 0, 1, 2, 8, 4, 5, 6, 12, 8, 9, 10];
2025        let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap();
2026        assert!(image.copy_within(
2027            Rect {
2028                x: 0,
2029                y: 0,
2030                width: 3,
2031                height: 3
2032            },
2033            1,
2034            1
2035        ));
2036        assert_eq!(&image.into_raw(), &expected);
2037    }
2038
2039    #[test]
2040    fn test_image_buffer_copy_within_tr() {
2041        let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
2042        let expected = [0, 1, 2, 3, 1, 2, 3, 7, 5, 6, 7, 11, 9, 10, 11, 15];
2043        let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap();
2044        assert!(image.copy_within(
2045            Rect {
2046                x: 1,
2047                y: 0,
2048                width: 3,
2049                height: 3
2050            },
2051            0,
2052            1
2053        ));
2054        assert_eq!(&image.into_raw(), &expected);
2055    }
2056
2057    #[test]
2058    fn test_image_buffer_copy_within_bl() {
2059        let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
2060        let expected = [0, 4, 5, 6, 4, 8, 9, 10, 8, 12, 13, 14, 12, 13, 14, 15];
2061        let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap();
2062        assert!(image.copy_within(
2063            Rect {
2064                x: 0,
2065                y: 1,
2066                width: 3,
2067                height: 3
2068            },
2069            1,
2070            0
2071        ));
2072        assert_eq!(&image.into_raw(), &expected);
2073    }
2074
2075    #[test]
2076    fn test_image_buffer_copy_within_br() {
2077        let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
2078        let expected = [5, 6, 7, 3, 9, 10, 11, 7, 13, 14, 15, 11, 12, 13, 14, 15];
2079        let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap();
2080        assert!(image.copy_within(
2081            Rect {
2082                x: 1,
2083                y: 1,
2084                width: 3,
2085                height: 3
2086            },
2087            0,
2088            0
2089        ));
2090        assert_eq!(&image.into_raw(), &expected);
2091    }
2092
2093    #[test]
2094    #[cfg(feature = "png")]
2095    fn write_to_with_large_buffer() {
2096        // A buffer of 1 pixel, padded to 4 bytes as would be common in, e.g. BMP.
2097
2098        let img: GrayImage = ImageBuffer::from_raw(1, 1, vec![0u8; 4]).unwrap();
2099        let mut buffer = std::io::Cursor::new(vec![]);
2100        assert!(img.write_to(&mut buffer, ImageFormat::Png).is_ok());
2101    }
2102
2103    #[test]
2104    fn exact_size_iter_size_hint() {
2105        // The docs for `std::iter::ExactSizeIterator` requires that the implementation of
2106        // `size_hint` on the iterator returns the same value as the `len` implementation.
2107
2108        // This test should work for any size image.
2109        const N: u32 = 10;
2110
2111        let mut image = RgbImage::from_raw(N, N, vec![0; (N * N * 3) as usize]).unwrap();
2112
2113        let iter = image.pixels();
2114        let exact_len = ExactSizeIterator::len(&iter);
2115        assert_eq!(iter.size_hint(), (exact_len, Some(exact_len)));
2116
2117        let iter = image.pixels_mut();
2118        let exact_len = ExactSizeIterator::len(&iter);
2119        assert_eq!(iter.size_hint(), (exact_len, Some(exact_len)));
2120
2121        let iter = image.rows();
2122        let exact_len = ExactSizeIterator::len(&iter);
2123        assert_eq!(iter.size_hint(), (exact_len, Some(exact_len)));
2124
2125        let iter = image.rows_mut();
2126        let exact_len = ExactSizeIterator::len(&iter);
2127        assert_eq!(iter.size_hint(), (exact_len, Some(exact_len)));
2128
2129        let iter = image.enumerate_pixels();
2130        let exact_len = ExactSizeIterator::len(&iter);
2131        assert_eq!(iter.size_hint(), (exact_len, Some(exact_len)));
2132
2133        let iter = image.enumerate_rows();
2134        let exact_len = ExactSizeIterator::len(&iter);
2135        assert_eq!(iter.size_hint(), (exact_len, Some(exact_len)));
2136
2137        let iter = image.enumerate_pixels_mut();
2138        let exact_len = ExactSizeIterator::len(&iter);
2139        assert_eq!(iter.size_hint(), (exact_len, Some(exact_len)));
2140
2141        let iter = image.enumerate_rows_mut();
2142        let exact_len = ExactSizeIterator::len(&iter);
2143        assert_eq!(iter.size_hint(), (exact_len, Some(exact_len)));
2144    }
2145
2146    #[test]
2147    fn color_conversion() {
2148        let mut source = ImageBuffer::from_fn(128, 128, |_, _| Rgb([255, 0, 0]));
2149        let mut target = ImageBuffer::from_fn(128, 128, |_, _| Rgba(Default::default()));
2150
2151        source.set_rgb_primaries(Cicp::SRGB.primaries);
2152        source.set_transfer_function(Cicp::SRGB.transfer);
2153
2154        target.set_rgb_primaries(Cicp::DISPLAY_P3.primaries);
2155        target.set_transfer_function(Cicp::DISPLAY_P3.transfer);
2156
2157        let result = target.copy_from_color_space(&source, Default::default());
2158
2159        assert!(result.is_ok(), "{result:?}");
2160        assert_eq!(target[(0, 0)], Rgba([234u8, 51, 35, 255]));
2161    }
2162
2163    #[test]
2164    fn gray_conversions() {
2165        let mut source = ImageBuffer::from_fn(128, 128, |_, _| Luma([255u8]));
2166        let mut target = ImageBuffer::from_fn(128, 128, |_, _| Rgba(Default::default()));
2167
2168        source.set_rgb_primaries(Cicp::SRGB.primaries);
2169        source.set_transfer_function(Cicp::SRGB.transfer);
2170
2171        target.set_rgb_primaries(Cicp::SRGB.primaries);
2172        target.set_transfer_function(Cicp::SRGB.transfer);
2173
2174        let result = target.copy_from_color_space(&source, Default::default());
2175
2176        assert!(result.is_ok(), "{result:?}");
2177        assert_eq!(target[(0, 0)], Rgba([u8::MAX; 4]));
2178    }
2179
2180    #[test]
2181    fn rgb_to_gray_conversion() {
2182        let mut source = ImageBuffer::from_fn(128, 128, |_, _| Rgb([128u8; 3]));
2183        let mut target = ImageBuffer::from_fn(128, 128, |_, _| Luma(Default::default()));
2184
2185        source.set_rgb_primaries(Cicp::SRGB.primaries);
2186        source.set_transfer_function(Cicp::SRGB.transfer);
2187
2188        target.set_rgb_primaries(Cicp::SRGB.primaries);
2189        target.set_transfer_function(Cicp::SRGB.transfer);
2190
2191        let result = target.copy_from_color_space(&source, Default::default());
2192
2193        assert!(result.is_ok(), "{result:?}");
2194        assert_eq!(target[(0, 0)], Luma([128u8]));
2195    }
2196
2197    #[test]
2198    fn apply_color() {
2199        let mut buffer = ImageBuffer::from_fn(128, 128, |_, _| Rgb([255u8, 0, 0]));
2200
2201        buffer.set_rgb_primaries(Cicp::SRGB.primaries);
2202        buffer.set_transfer_function(Cicp::SRGB.transfer);
2203
2204        buffer
2205            .apply_color_space(Cicp::DISPLAY_P3, Default::default())
2206            .expect("supported transform");
2207
2208        buffer.pixels().for_each(|&p| {
2209            assert_eq!(p, Rgb([234u8, 51, 35]));
2210        });
2211    }
2212
2213    #[test]
2214    fn to_color() {
2215        let mut source = ImageBuffer::from_fn(128, 128, |_, _| Rgba([255u8, 0, 0, 255]));
2216        source.set_rgb_primaries(Cicp::SRGB.primaries);
2217        source.set_transfer_function(Cicp::SRGB.transfer);
2218
2219        let target = source
2220            .to_color_space::<Rgb<u8>>(Cicp::DISPLAY_P3, Default::default())
2221            .expect("supported transform");
2222
2223        assert_eq!(target[(0, 0)], Rgb([234u8, 51, 35]));
2224    }
2225
2226    #[test]
2227    fn transformation_mismatch() {
2228        let mut source = ImageBuffer::from_fn(128, 128, |_, _| Luma([255u8]));
2229        let mut target = ImageBuffer::from_fn(128, 128, |_, _| Rgba(Default::default()));
2230
2231        source.set_color_space(Cicp::SRGB).unwrap();
2232        target.set_color_space(Cicp::DISPLAY_P3).unwrap();
2233
2234        let options = super::ConvertColorOptions {
2235            transform: CicpTransform::new(Cicp::SRGB, Cicp::SRGB),
2236            ..super::ConvertColorOptions::default()
2237        };
2238
2239        let result = target.copy_from_color_space(&source, options);
2240        assert!(matches!(result, Err(crate::ImageError::Parameter(_))));
2241    }
2242
2243    /// We specialize copy_from on types that provide `as_samples` so test that.
2244    #[test]
2245    fn copy_from_subimage_to_middle() {
2246        let mut source = RgbImage::new(16, 16);
2247        let mut target = RgbImage::new(16, 16);
2248
2249        source.put_pixel(8, 8, Rgb([255, 8, 8]));
2250        source.put_pixel(9, 8, Rgb([255, 9, 8]));
2251        source.put_pixel(9, 9, Rgb([255, 9, 9]));
2252
2253        let view = source.view(8, 8, 2, 2);
2254        assert!(target.copy_from(&*view, 4, 4).is_ok());
2255
2256        // Check the pixel was copied.
2257        assert_eq!(*target.get_pixel(4, 4), Rgb([255, 8, 8]));
2258        assert_eq!(*target.get_pixel(5, 4), Rgb([255, 9, 8]));
2259        assert_eq!(*target.get_pixel(5, 5), Rgb([255, 9, 9]));
2260
2261        // Check that were the only copied pixel.
2262        assert_eq!(
2263            target.iter().copied().map(usize::from).sum::<usize>(),
2264            3 * (255 + 8 + 9)
2265        );
2266    }
2267
2268    #[test]
2269    fn copy_from_band() {
2270        let source = RgbImage::from_fn(16, 8, |x, y| Rgb([x as u8, y as u8, 0]));
2271        let mut target = RgbImage::new(16, 16);
2272
2273        assert!(target.copy_from(&source, 0, 4).is_ok());
2274
2275        let lhs = source.chunks_exact(48);
2276        let rhs = target.chunks_exact(48).skip(4).take(8);
2277
2278        assert!(lhs.eq(rhs));
2279    }
2280
2281    #[test]
2282    fn copy_from_pixel() {
2283        let bg = Rgb([255, 0, 128]);
2284        let samples = crate::flat::FlatSamples::with_monocolor(&bg, 4, 4);
2285        let source = samples.as_view().unwrap();
2286
2287        let mut target = RgbImage::new(16, 16);
2288        assert!(target.copy_from(&source, 4, 4).is_ok());
2289
2290        for i in 4..8 {
2291            for j in 4..8 {
2292                assert_eq!(*target.get_pixel(i, j), bg);
2293            }
2294        }
2295
2296        assert_eq!(
2297            target.iter().copied().map(usize::from).sum::<usize>(),
2298            16 * (255 + 128)
2299        );
2300    }
2301
2302    #[test]
2303    fn copy_from_strided() {
2304        #[rustfmt::skip]
2305        let sample_data = [
2306            1, 0xff, 0, 0, 2, 0xff,
2307            3, 0xff, 0, 0, 4, 0xff
2308        ];
2309
2310        let samples = crate::flat::FlatSamples {
2311            samples: &sample_data,
2312            layout: crate::flat::SampleLayout {
2313                channels: 2,
2314                channel_stride: 1,
2315                width: 2,
2316                width_stride: 4,
2317                height: 2,
2318                height_stride: 6,
2319            },
2320            color_hint: None,
2321        };
2322
2323        let source = samples.as_view::<LumaA<u8>>().unwrap();
2324        let mut target = crate::GrayAlphaImage::new(16, 16);
2325        assert!(target.copy_from(&source, 4, 4).is_ok());
2326
2327        assert_eq!(*target.get_pixel(4, 4), LumaA([1, 0xff]));
2328        assert_eq!(*target.get_pixel(5, 4), LumaA([2, 0xff]));
2329        assert_eq!(*target.get_pixel(4, 5), LumaA([3, 0xff]));
2330        assert_eq!(*target.get_pixel(5, 5), LumaA([4, 0xff]));
2331
2332        assert_eq!(
2333            target.iter().copied().map(usize::from).sum::<usize>(),
2334            sample_data.iter().copied().map(usize::from).sum::<usize>(),
2335        );
2336    }
2337
2338    #[test]
2339    fn copy_from_strided_subimage() {
2340        #[rustfmt::skip]
2341        let sample_data = [
2342            1, 0xff, 0, 0, 2, 0xff,
2343            3, 0xff, 0, 0, 4, 0xff
2344        ];
2345
2346        let samples = crate::flat::FlatSamples {
2347            samples: &sample_data,
2348            layout: crate::flat::SampleLayout {
2349                channels: 2,
2350                channel_stride: 1,
2351                width: 2,
2352                width_stride: 4,
2353                height: 2,
2354                height_stride: 6,
2355            },
2356            color_hint: None,
2357        };
2358
2359        let view = samples.as_view::<LumaA<u8>>().unwrap();
2360        let source = view.view(1, 0, 1, 2);
2361
2362        let mut target = crate::GrayAlphaImage::new(16, 16);
2363        assert!(target.copy_from(&*source, 4, 4).is_ok());
2364
2365        assert_eq!(*target.get_pixel(4, 4), LumaA([2, 0xff]));
2366        assert_eq!(*target.get_pixel(4, 5), LumaA([4, 0xff]));
2367
2368        assert_eq!(
2369            target.iter().copied().map(usize::from).sum::<usize>(),
2370            2usize + 0xff + 4 + 0xff
2371        );
2372    }
2373
2374    #[test]
2375    fn copy_from_subimage_subimage() {
2376        let mut source = RgbImage::new(16, 16);
2377        let mut target = RgbImage::new(16, 16);
2378
2379        source.put_pixel(8, 8, Rgb([255, 8, 8]));
2380        source.put_pixel(9, 8, Rgb([255, 9, 8]));
2381        source.put_pixel(9, 9, Rgb([255, 9, 9]));
2382
2383        let view = source.view(8, 8, 2, 2);
2384        let view = view.view(1, 0, 1, 1);
2385        assert!(target.copy_from(&*view, 4, 4).is_ok());
2386
2387        // Check the pixel was copied.
2388        assert_eq!(*target.get_pixel(4, 4), Rgb([255, 9, 8]));
2389
2390        // Check that was the only copied pixel.
2391        assert_eq!(
2392            target.iter().copied().map(usize::from).sum::<usize>(),
2393            255 + 9 + 8
2394        );
2395    }
2396}
2397
2398#[cfg(test)]
2399#[cfg(feature = "benchmarks")]
2400mod benchmarks {
2401    use super::{ConvertBuffer, GrayImage, ImageBuffer, Pixel, RgbImage};
2402
2403    #[bench]
2404    fn conversion(b: &mut test::Bencher) {
2405        let mut a: RgbImage = ImageBuffer::new(1000, 1000);
2406        for p in a.pixels_mut() {
2407            let rgb = p.channels_mut();
2408            rgb[0] = 255;
2409            rgb[1] = 23;
2410            rgb[2] = 42;
2411        }
2412
2413        assert!(a.data[0] != 0);
2414        b.iter(|| {
2415            let b: GrayImage = a.convert();
2416            assert!(0 != b.data[0]);
2417            assert!(a.data[0] != b.data[0]);
2418            test::black_box(b);
2419        });
2420        b.bytes = 1000 * 1000 * 3;
2421    }
2422
2423    #[bench]
2424    fn image_access_row_by_row(b: &mut test::Bencher) {
2425        let mut a: RgbImage = ImageBuffer::new(1000, 1000);
2426        for p in a.pixels_mut() {
2427            let rgb = p.channels_mut();
2428            rgb[0] = 255;
2429            rgb[1] = 23;
2430            rgb[2] = 42;
2431        }
2432
2433        b.iter(move || {
2434            let image: &RgbImage = test::black_box(&a);
2435            let mut sum: usize = 0;
2436            for y in 0..1000 {
2437                for x in 0..1000 {
2438                    let pixel = image.get_pixel(x, y);
2439                    sum = sum.wrapping_add(pixel[0] as usize);
2440                    sum = sum.wrapping_add(pixel[1] as usize);
2441                    sum = sum.wrapping_add(pixel[2] as usize);
2442                }
2443            }
2444            test::black_box(sum)
2445        });
2446
2447        b.bytes = 1000 * 1000 * 3;
2448    }
2449
2450    #[bench]
2451    fn image_access_col_by_col(b: &mut test::Bencher) {
2452        let mut a: RgbImage = ImageBuffer::new(1000, 1000);
2453        for p in a.pixels_mut() {
2454            let rgb = p.channels_mut();
2455            rgb[0] = 255;
2456            rgb[1] = 23;
2457            rgb[2] = 42;
2458        }
2459
2460        b.iter(move || {
2461            let image: &RgbImage = test::black_box(&a);
2462            let mut sum: usize = 0;
2463            for x in 0..1000 {
2464                for y in 0..1000 {
2465                    let pixel = image.get_pixel(x, y);
2466                    sum = sum.wrapping_add(pixel[0] as usize);
2467                    sum = sum.wrapping_add(pixel[1] as usize);
2468                    sum = sum.wrapping_add(pixel[2] as usize);
2469                }
2470            }
2471            test::black_box(sum)
2472        });
2473
2474        b.bytes = 1000 * 1000 * 3;
2475    }
2476}