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};
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    where
867        Container: AsRef<[P::Subpixel]>,
868    {
869        let layout = self.sample_layout();
870        FlatSamples {
871            samples: self.data.as_ref(),
872            layout,
873            color_hint: None, // TODO: the pixel type might contain P::COLOR_TYPE if it satisfies PixelWithColorType
874        }
875    }
876
877    /// Return a mutable view on the raw sample buffer.
878    ///
879    /// See [`into_flat_samples`](#method.into_flat_samples) for more details.
880    pub fn as_flat_samples_mut(&mut self) -> FlatSamples<&mut [P::Subpixel]>
881    where
882        Container: AsMut<[P::Subpixel]>,
883    {
884        let layout = self.sample_layout();
885        FlatSamples {
886            samples: self.data.as_mut(),
887            layout,
888            color_hint: None, // TODO: the pixel type might contain P::COLOR_TYPE if it satisfies PixelWithColorType
889        }
890    }
891}
892
893impl<P, Container> ImageBuffer<P, Container>
894where
895    P: Pixel,
896    Container: Deref<Target = [P::Subpixel]> + DerefMut,
897{
898    // TODO: choose name under which to expose.
899    pub(crate) fn inner_pixels_mut(&mut self) -> &mut [P::Subpixel] {
900        let len = Self::image_buffer_len(self.width, self.height).unwrap();
901        &mut self.data[..len]
902    }
903
904    /// Returns an iterator over the mutable pixels of this image.
905    pub fn pixels_mut(&mut self) -> PixelsMut<'_, P> {
906        PixelsMut {
907            chunks: self
908                .inner_pixels_mut()
909                .chunks_exact_mut(<P as Pixel>::CHANNEL_COUNT as usize),
910        }
911    }
912
913    /// Returns an iterator over the mutable rows of this image.
914    ///
915    /// Only non-empty rows can be iterated in this manner. In particular the iterator will not
916    /// yield any item when the width of the image is `0` or a pixel type without any channels is
917    /// used. This ensures that its length can always be represented by `usize`.
918    pub fn rows_mut(&mut self) -> RowsMut<'_, P> {
919        RowsMut::with_image(&mut self.data, self.width, self.height)
920    }
921
922    /// Enumerates over the pixels of the image.
923    /// The iterator yields the coordinates of each pixel
924    /// along with a mutable reference to them.
925    pub fn enumerate_pixels_mut(&mut self) -> EnumeratePixelsMut<'_, P> {
926        let width = self.width;
927        EnumeratePixelsMut {
928            pixels: self.pixels_mut(),
929            x: 0,
930            y: 0,
931            width,
932        }
933    }
934
935    /// Enumerates over the rows of the image.
936    /// The iterator yields the y-coordinate of each row
937    /// along with a mutable reference to them.
938    pub fn enumerate_rows_mut(&mut self) -> EnumerateRowsMut<'_, P> {
939        let width = self.width;
940        EnumerateRowsMut {
941            rows: self.rows_mut(),
942            y: 0,
943            width,
944        }
945    }
946
947    /// Gets a reference to the mutable pixel at location `(x, y)`
948    ///
949    /// # Panics
950    ///
951    /// Panics if `(x, y)` is out of the bounds `(width, height)`.
952    #[inline]
953    #[track_caller]
954    pub fn get_pixel_mut(&mut self, x: u32, y: u32) -> &mut P {
955        match self.pixel_indices(x, y) {
956            None => panic!(
957                "Image index {:?} out of bounds {:?}",
958                (x, y),
959                (self.width, self.height)
960            ),
961            Some(pixel_indices) => <P as Pixel>::from_slice_mut(&mut self.data[pixel_indices]),
962        }
963    }
964
965    /// Gets a reference to the mutable pixel at location `(x, y)` or returns
966    /// `None` if the index is out of the bounds `(width, height)`.
967    pub fn get_pixel_mut_checked(&mut self, x: u32, y: u32) -> Option<&mut P> {
968        if x >= self.width {
969            return None;
970        }
971        let num_channels = <P as Pixel>::CHANNEL_COUNT as usize;
972        let i = (y as usize)
973            .saturating_mul(self.width as usize)
974            .saturating_add(x as usize)
975            .saturating_mul(num_channels);
976
977        self.data
978            .get_mut(i..i.checked_add(num_channels)?)
979            .map(|pixel_indices| <P as Pixel>::from_slice_mut(pixel_indices))
980    }
981
982    /// Puts a pixel at location `(x, y)`
983    ///
984    /// # Panics
985    ///
986    /// Panics if `(x, y)` is out of the bounds `(width, height)`.
987    #[inline]
988    #[track_caller]
989    pub fn put_pixel(&mut self, x: u32, y: u32, pixel: P) {
990        *self.get_pixel_mut(x, y) = pixel;
991    }
992}
993
994impl<P: Pixel, Container> ImageBuffer<P, Container> {
995    /// Define the color space for the image.
996    ///
997    /// The color data is unchanged. Reinterprets the existing red, blue, green channels as points
998    /// in the new set of primary colors, changing the apparent shade of pixels.
999    ///
1000    /// Note that the primaries also define a reference whitepoint When this buffer contains Luma
1001    /// data, the luminance channel is interpreted as the `Y` channel of a related `YCbCr` color
1002    /// space as if by a non-constant chromaticity derived matrix. That is, coefficients are *not*
1003    /// applied in the linear RGB space but use encoded channel values. (In a color space with the
1004    /// linear transfer function there is no difference).
1005    ///
1006    /// The default color space is [`Cicp::SRGB`].
1007    pub fn set_rgb_primaries(&mut self, color: CicpColorPrimaries) {
1008        self.color.primaries = color;
1009    }
1010
1011    /// Define the transfer function for the image.
1012    ///
1013    /// The color data is unchanged. Reinterprets all (non-alpha) components in the image,
1014    /// potentially changing the apparent shade of pixels. Individual components are always
1015    /// interpreted as encoded numbers. To denote numbers in a linear RGB space, use
1016    /// [`CicpTransferCharacteristics::Linear`].
1017    ///
1018    /// The default color space is [`Cicp::SRGB`].
1019    pub fn set_transfer_function(&mut self, tf: CicpTransferCharacteristics) {
1020        self.color.transfer = tf;
1021    }
1022
1023    /// Get the Cicp encoding of this buffer's color data.
1024    pub fn color_space(&self) -> Cicp {
1025        self.color.into()
1026    }
1027
1028    /// Set primaries and transfer characteristics from a Cicp color space.
1029    ///
1030    /// Returns an error if `cicp` uses features that are not support with an RGB color space, e.g.
1031    /// a matrix or narrow range (studio encoding) channels.
1032    pub fn set_color_space(&mut self, cicp: Cicp) -> ImageResult<()> {
1033        self.color = cicp.try_into_rgb()?;
1034        Ok(())
1035    }
1036
1037    pub(crate) fn set_rgb_color_space(&mut self, color: CicpRgb) {
1038        self.color = color;
1039    }
1040}
1041
1042impl<P, Container> ImageBuffer<P, Container>
1043where
1044    P: Pixel,
1045    [P::Subpixel]: EncodableLayout,
1046    Container: Deref<Target = [P::Subpixel]>,
1047{
1048    /// Saves the buffer to a file at the path specified.
1049    ///
1050    /// The image format is derived from the file extension.
1051    pub fn save<Q>(&self, path: Q) -> ImageResult<()>
1052    where
1053        Q: AsRef<Path>,
1054        P: PixelWithColorType,
1055    {
1056        save_buffer(
1057            path,
1058            self.inner_pixels().as_bytes(),
1059            self.width(),
1060            self.height(),
1061            <P as PixelWithColorType>::COLOR_TYPE,
1062        )
1063    }
1064}
1065
1066impl<P, Container> ImageBuffer<P, Container>
1067where
1068    P: Pixel,
1069    [P::Subpixel]: EncodableLayout,
1070    Container: Deref<Target = [P::Subpixel]>,
1071{
1072    /// Saves the buffer to a file at the specified path in
1073    /// the specified format.
1074    ///
1075    /// See [`save_buffer_with_format`](fn.save_buffer_with_format.html) for
1076    /// supported types.
1077    pub fn save_with_format<Q>(&self, path: Q, format: ImageFormat) -> ImageResult<()>
1078    where
1079        Q: AsRef<Path>,
1080        P: PixelWithColorType,
1081    {
1082        // This is valid as the subpixel is u8.
1083        save_buffer_with_format(
1084            path,
1085            self.inner_pixels().as_bytes(),
1086            self.width(),
1087            self.height(),
1088            <P as PixelWithColorType>::COLOR_TYPE,
1089            format,
1090        )
1091    }
1092}
1093
1094impl<P, Container> ImageBuffer<P, Container>
1095where
1096    P: Pixel,
1097    [P::Subpixel]: EncodableLayout,
1098    Container: Deref<Target = [P::Subpixel]>,
1099{
1100    /// Writes the buffer to a writer in the specified format.
1101    ///
1102    /// Assumes the writer is buffered. In most cases, you should wrap your writer in a `BufWriter`
1103    /// for best performance.
1104    pub fn write_to<W>(&self, writer: &mut W, format: ImageFormat) -> ImageResult<()>
1105    where
1106        W: std::io::Write + std::io::Seek,
1107        P: PixelWithColorType,
1108    {
1109        // This is valid as the subpixel is u8.
1110        write_buffer_with_format(
1111            writer,
1112            self.inner_pixels().as_bytes(),
1113            self.width(),
1114            self.height(),
1115            <P as PixelWithColorType>::COLOR_TYPE,
1116            format,
1117        )
1118    }
1119}
1120
1121impl<P, Container> ImageBuffer<P, Container>
1122where
1123    P: Pixel,
1124    [P::Subpixel]: EncodableLayout,
1125    Container: Deref<Target = [P::Subpixel]>,
1126{
1127    /// Writes the buffer with the given encoder.
1128    pub fn write_with_encoder<E>(&self, encoder: E) -> ImageResult<()>
1129    where
1130        E: ImageEncoder,
1131        P: PixelWithColorType,
1132    {
1133        // This is valid as the subpixel is u8.
1134        encoder.write_image(
1135            self.inner_pixels().as_bytes(),
1136            self.width(),
1137            self.height(),
1138            <P as PixelWithColorType>::COLOR_TYPE,
1139        )
1140    }
1141}
1142
1143impl<P, Container> Default for ImageBuffer<P, Container>
1144where
1145    P: Pixel,
1146    Container: Default,
1147{
1148    fn default() -> Self {
1149        Self {
1150            width: 0,
1151            height: 0,
1152            _phantom: PhantomData,
1153            color: Cicp::SRGB_LINEAR.into_rgb(),
1154            data: Default::default(),
1155        }
1156    }
1157}
1158
1159impl<P, Container> Deref for ImageBuffer<P, Container>
1160where
1161    P: Pixel,
1162    Container: Deref<Target = [P::Subpixel]>,
1163{
1164    type Target = [P::Subpixel];
1165
1166    fn deref(&self) -> &<Self as Deref>::Target {
1167        &self.data
1168    }
1169}
1170
1171impl<P, Container> DerefMut for ImageBuffer<P, Container>
1172where
1173    P: Pixel,
1174    Container: Deref<Target = [P::Subpixel]> + DerefMut,
1175{
1176    fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {
1177        &mut self.data
1178    }
1179}
1180
1181impl<P, Container> Index<(u32, u32)> for ImageBuffer<P, Container>
1182where
1183    P: Pixel,
1184    Container: Deref<Target = [P::Subpixel]>,
1185{
1186    type Output = P;
1187
1188    fn index(&self, (x, y): (u32, u32)) -> &P {
1189        self.get_pixel(x, y)
1190    }
1191}
1192
1193impl<P, Container> IndexMut<(u32, u32)> for ImageBuffer<P, Container>
1194where
1195    P: Pixel,
1196    Container: Deref<Target = [P::Subpixel]> + DerefMut,
1197{
1198    fn index_mut(&mut self, (x, y): (u32, u32)) -> &mut P {
1199        self.get_pixel_mut(x, y)
1200    }
1201}
1202
1203impl<P, Container> Clone for ImageBuffer<P, Container>
1204where
1205    P: Pixel,
1206    Container: Deref<Target = [P::Subpixel]> + Clone,
1207{
1208    fn clone(&self) -> ImageBuffer<P, Container> {
1209        ImageBuffer {
1210            data: self.data.clone(),
1211            width: self.width,
1212            height: self.height,
1213            color: self.color,
1214            _phantom: PhantomData,
1215        }
1216    }
1217
1218    fn clone_from(&mut self, source: &Self) {
1219        self.data.clone_from(&source.data);
1220        self.width = source.width;
1221        self.height = source.height;
1222        self.color = source.color;
1223    }
1224}
1225
1226impl<P, Container> GenericImageView for ImageBuffer<P, Container>
1227where
1228    P: Pixel,
1229    Container: Deref<Target = [P::Subpixel]> + Deref,
1230{
1231    type Pixel = P;
1232
1233    fn dimensions(&self) -> (u32, u32) {
1234        self.dimensions()
1235    }
1236
1237    fn get_pixel(&self, x: u32, y: u32) -> P {
1238        *self.get_pixel(x, y)
1239    }
1240
1241    /// Returns the pixel located at (x, y), ignoring bounds checking.
1242    #[inline(always)]
1243    unsafe fn unsafe_get_pixel(&self, x: u32, y: u32) -> P {
1244        let indices = self.pixel_indices_unchecked(x, y);
1245        *<P as Pixel>::from_slice(self.data.get_unchecked(indices))
1246    }
1247
1248    fn buffer_with_dimensions(&self, width: u32, height: u32) -> ImageBuffer<P, Vec<P::Subpixel>> {
1249        let mut buffer = ImageBuffer::new(width, height);
1250        buffer.copy_color_space_from(self);
1251        buffer
1252    }
1253}
1254
1255impl<P, Container> GenericImage for ImageBuffer<P, Container>
1256where
1257    P: Pixel,
1258    Container: Deref<Target = [P::Subpixel]> + DerefMut,
1259{
1260    fn get_pixel_mut(&mut self, x: u32, y: u32) -> &mut P {
1261        self.get_pixel_mut(x, y)
1262    }
1263
1264    fn put_pixel(&mut self, x: u32, y: u32, pixel: P) {
1265        *self.get_pixel_mut(x, y) = pixel;
1266    }
1267
1268    /// Puts a pixel at location (x, y), ignoring bounds checking.
1269    #[inline(always)]
1270    unsafe fn unsafe_put_pixel(&mut self, x: u32, y: u32, pixel: P) {
1271        let indices = self.pixel_indices_unchecked(x, y);
1272        let p = <P as Pixel>::from_slice_mut(self.data.get_unchecked_mut(indices));
1273        *p = pixel;
1274    }
1275
1276    /// Put a pixel at location (x, y), taking into account alpha channels
1277    ///
1278    /// DEPRECATED: This method will be removed. Blend the pixel directly instead.
1279    fn blend_pixel(&mut self, x: u32, y: u32, p: P) {
1280        self.get_pixel_mut(x, y).blend(&p);
1281    }
1282
1283    fn copy_within(&mut self, source: Rect, x: u32, y: u32) -> bool {
1284        let Rect {
1285            x: sx,
1286            y: sy,
1287            width,
1288            height,
1289        } = source;
1290        let dx = x;
1291        let dy = y;
1292        assert!(sx < self.width() && dx < self.width());
1293        assert!(sy < self.height() && dy < self.height());
1294        if self.width() - dx.max(sx) < width || self.height() - dy.max(sy) < height {
1295            return false;
1296        }
1297
1298        if sy < dy {
1299            for y in (0..height).rev() {
1300                let sy = sy + y;
1301                let dy = dy + y;
1302                let Range { start, .. } = self.pixel_indices_unchecked(sx, sy);
1303                let Range { end, .. } = self.pixel_indices_unchecked(sx + width - 1, sy);
1304                let dst = self.pixel_indices_unchecked(dx, dy).start;
1305                self.data.copy_within(start..end, dst);
1306            }
1307        } else {
1308            for y in 0..height {
1309                let sy = sy + y;
1310                let dy = dy + y;
1311                let Range { start, .. } = self.pixel_indices_unchecked(sx, sy);
1312                let Range { end, .. } = self.pixel_indices_unchecked(sx + width - 1, sy);
1313                let dst = self.pixel_indices_unchecked(dx, dy).start;
1314                self.data.copy_within(start..end, dst);
1315            }
1316        }
1317        true
1318    }
1319}
1320
1321// concrete implementation for `Vec`-backed buffers
1322// TODO: I think that rustc does not "see" this impl any more: the impl with
1323// Container meets the same requirements. At least, I got compile errors that
1324// there is no such function as `into_vec`, whereas `into_raw` did work, and
1325// `into_vec` is redundant anyway, because `into_raw` will give you the vector,
1326// and it is more generic.
1327impl<P: Pixel> ImageBuffer<P, Vec<P::Subpixel>> {
1328    /// Creates a new image buffer based on a `Vec<P::Subpixel>`.
1329    ///
1330    /// all the pixels of this image have a value of zero, regardless of the data type or number of channels.
1331    ///
1332    /// The color space is initially set to [`sRGB`][`Cicp::SRGB`].
1333    ///
1334    /// # Panics
1335    ///
1336    /// Panics when the resulting image is larger than the maximum size of a vector.
1337    #[must_use]
1338    pub fn new(width: u32, height: u32) -> ImageBuffer<P, Vec<P::Subpixel>> {
1339        let size = Self::image_buffer_len(width, height)
1340            .expect("Buffer length in `ImageBuffer::new` overflows usize");
1341        ImageBuffer {
1342            data: vec![Zero::zero(); size],
1343            width,
1344            height,
1345            color: Cicp::SRGB.into_rgb(),
1346            _phantom: PhantomData,
1347        }
1348    }
1349
1350    /// Constructs a new `ImageBuffer` by copying a pixel
1351    ///
1352    /// # Panics
1353    ///
1354    /// Panics when the resulting image is larger than the maximum size of a vector.
1355    pub fn from_pixel(width: u32, height: u32, pixel: P) -> ImageBuffer<P, Vec<P::Subpixel>> {
1356        let mut buf = ImageBuffer::new(width, height);
1357        for p in buf.pixels_mut() {
1358            *p = pixel;
1359        }
1360        buf
1361    }
1362
1363    /// Constructs a new `ImageBuffer` by repeated application of the supplied function.
1364    ///
1365    /// The arguments to the function are the pixel's x and y coordinates.
1366    ///
1367    /// # Panics
1368    ///
1369    /// Panics when the resulting image is larger than the maximum size of a vector.
1370    pub fn from_fn<F>(width: u32, height: u32, mut f: F) -> ImageBuffer<P, Vec<P::Subpixel>>
1371    where
1372        F: FnMut(u32, u32) -> P,
1373    {
1374        let mut buf = ImageBuffer::new(width, height);
1375        for (x, y, p) in buf.enumerate_pixels_mut() {
1376            *p = f(x, y);
1377        }
1378        buf
1379    }
1380
1381    /// Creates an image buffer out of an existing buffer.
1382    /// Returns None if the buffer is not big enough.
1383    #[must_use]
1384    pub fn from_vec(
1385        width: u32,
1386        height: u32,
1387        buf: Vec<P::Subpixel>,
1388    ) -> Option<ImageBuffer<P, Vec<P::Subpixel>>> {
1389        ImageBuffer::from_raw(width, height, buf)
1390    }
1391
1392    /// Consumes the image buffer and returns the underlying data
1393    /// as an owned buffer
1394    #[must_use]
1395    pub fn into_vec(self) -> Vec<P::Subpixel> {
1396        self.into_raw()
1397    }
1398
1399    /// Transfer the meta data, not the pixel values.
1400    ///
1401    /// This will reinterpret all the pixels.
1402    ///
1403    /// We may want to export this but under what name?
1404    pub(crate) fn copy_color_space_from<O: Pixel, C>(&mut self, other: &ImageBuffer<O, C>) {
1405        self.color = other.color;
1406    }
1407}
1408
1409/// Provides color conversions for whole image buffers.
1410pub trait ConvertBuffer<T> {
1411    /// Converts `self` to a buffer of type T
1412    ///
1413    /// A generic implementation is provided to convert any image buffer to a image buffer
1414    /// based on a `Vec<T>`.
1415    fn convert(&self) -> T;
1416}
1417
1418// concrete implementation Luma -> Rgba
1419impl GrayImage {
1420    /// Expands a color palette by re-using the existing buffer.
1421    /// Assumes 8 bit per pixel. Uses an optionally transparent index to
1422    /// adjust it's alpha value accordingly.
1423    #[must_use]
1424    pub fn expand_palette(
1425        self,
1426        palette: &[(u8, u8, u8)],
1427        transparent_idx: Option<u8>,
1428    ) -> RgbaImage {
1429        let (width, height) = self.dimensions();
1430        let mut data = self.into_raw();
1431        let entries = data.len();
1432        data.resize(entries.checked_mul(4).unwrap(), 0);
1433        let mut buffer = ImageBuffer::from_vec(width, height, data).unwrap();
1434        expand_packed(&mut buffer, 4, 8, |idx, pixel| {
1435            let (r, g, b) = palette[idx as usize];
1436            let a = if let Some(t_idx) = transparent_idx {
1437                if t_idx == idx {
1438                    0
1439                } else {
1440                    255
1441                }
1442            } else {
1443                255
1444            };
1445            pixel[0] = r;
1446            pixel[1] = g;
1447            pixel[2] = b;
1448            pixel[3] = a;
1449        });
1450        buffer
1451    }
1452}
1453
1454/// This copies the color space information but is somewhat wrong, in numeric terms this conversion
1455/// fails to actually convert rgb/luma with consistent treatment. But this trait impl is too
1456/// generic to handle it correctly (missing any CICP related parameter for the coefficients) so the
1457/// best effort here is to copy the metadata and have slighly incorrect color. May you've only been
1458/// adding an alpha channel or converting sample types, which is fine.
1459///
1460/// It will very likely be deprecated in a future release.
1461impl<Container, FromType: Pixel, ToType: Pixel>
1462    ConvertBuffer<ImageBuffer<ToType, Vec<ToType::Subpixel>>> for ImageBuffer<FromType, Container>
1463where
1464    Container: Deref<Target = [FromType::Subpixel]>,
1465    ToType: FromColor<FromType>,
1466{
1467    /// # Examples
1468    /// Convert RGB image to gray image.
1469    /// ```no_run
1470    /// use image::buffer::ConvertBuffer;
1471    /// use image::GrayImage;
1472    ///
1473    /// let image_path = "examples/fractal.png";
1474    /// let image = image::open(&image_path)
1475    ///     .expect("Open file failed")
1476    ///     .to_rgba8();
1477    ///
1478    /// let gray_image: GrayImage = image.convert();
1479    /// ```
1480    fn convert(&self) -> ImageBuffer<ToType, Vec<ToType::Subpixel>> {
1481        let mut buffer: ImageBuffer<ToType, Vec<ToType::Subpixel>> =
1482            ImageBuffer::new(self.width, self.height);
1483        buffer.copy_color_space_from(self);
1484        for (to, from) in buffer.pixels_mut().zip(self.pixels()) {
1485            to.from_color(from);
1486        }
1487        buffer
1488    }
1489}
1490
1491/// Inputs to [`ImageBuffer::copy_from_color_space`].
1492#[non_exhaustive]
1493#[derive(Default)]
1494pub struct ConvertColorOptions {
1495    /// A pre-calculated transform. This is only used when the actual colors of the input and
1496    /// output image match the color spaces with which the was constructed.
1497    ///
1498    /// FIXME: Clarify that the transform is cheap to clone, i.e. internally an Arc of precomputed
1499    /// tables and not expensive despite having `Clone`.
1500    pub(crate) transform: Option<CicpTransform>,
1501    /// Make sure we can later add options that are bound to the thread. That does not mean that
1502    /// all attributes will be bound to the thread, only that we can add `!Sync` options later. You
1503    /// should be constructing the options at the call site with each attribute being cheap to move
1504    /// into here.
1505    pub(crate) _auto_traits: PhantomData<std::rc::Rc<()>>,
1506}
1507
1508impl ConvertColorOptions {
1509    pub(crate) fn as_transform(
1510        &mut self,
1511        from_color: Cicp,
1512        into_color: Cicp,
1513    ) -> Result<&CicpTransform, ImageError> {
1514        if let Some(tr) = &self.transform {
1515            tr.check_applicable(from_color, into_color)?;
1516        }
1517
1518        if self.transform.is_none() {
1519            self.transform = CicpTransform::new(from_color, into_color);
1520        }
1521
1522        self.transform.as_ref().ok_or_else(|| {
1523            ImageError::Unsupported(UnsupportedError::from_format_and_kind(
1524                crate::error::ImageFormatHint::Unknown,
1525                // One of them is responsible.
1526                UnsupportedErrorKind::ColorspaceCicp(if from_color.qualify_stability() {
1527                    into_color
1528                } else {
1529                    from_color
1530                }),
1531            ))
1532        })
1533    }
1534
1535    pub(crate) fn as_transform_fn<FromType, IntoType>(
1536        &mut self,
1537        from_color: Cicp,
1538        into_color: Cicp,
1539    ) -> Result<&'_ CicpApplicable<'_, FromType::Subpixel>, ImageError>
1540    where
1541        FromType: PixelWithColorType,
1542        IntoType: PixelWithColorType,
1543    {
1544        Ok(self
1545            .as_transform(from_color, into_color)?
1546            .supported_transform_fn::<FromType, IntoType>())
1547    }
1548}
1549
1550impl<C, SelfPixel: Pixel> ImageBuffer<SelfPixel, C>
1551where
1552    SelfPixel: PixelWithColorType,
1553    C: Deref<Target = [SelfPixel::Subpixel]> + DerefMut,
1554{
1555    /// Convert the color data to another pixel type, the color space.
1556    ///
1557    /// This method is supposed to be called by exposed monomorphized methods, not directly by
1558    /// users. In particular it serves to implement `DynamicImage`'s casts that go beyond those
1559    /// offered by `PixelWithColorType` and include, e.g., `LumaAlpha<f32>`.
1560    ///
1561    /// Before exposing this method, decide if we want a design like [`DynamicImage::to`] (many
1562    /// trait parameters) with color space aware `FromColor` or if we want a design that takes a
1563    /// `ColorType` parameter / `PixelWithColorType`. The latter is not quite as flexible but
1564    /// allows much greater internal changes that do not tie in with the _external_ stable API.
1565    pub(crate) fn cast_in_color_space<IntoPixel>(
1566        &self,
1567    ) -> ImageBuffer<IntoPixel, Vec<IntoPixel::Subpixel>>
1568    where
1569        SelfPixel: Pixel,
1570        IntoPixel: Pixel,
1571        IntoPixel: CicpPixelCast<SelfPixel>,
1572        SelfPixel::Subpixel: ColorComponentForCicp,
1573        IntoPixel::Subpixel: ColorComponentForCicp + FromPrimitive<SelfPixel::Subpixel>,
1574    {
1575        let vec = self
1576            .color
1577            .cast_pixels::<SelfPixel, IntoPixel>(self.inner_pixels(), &|| [0.2126, 0.7152, 0.0722]);
1578        let mut buffer = ImageBuffer::from_vec(self.width, self.height, vec)
1579            .expect("cast_pixels returned the right number of pixels");
1580        buffer.copy_color_space_from(self);
1581        buffer
1582    }
1583
1584    /// Copy pixel data from one buffer to another, calculating equivalent color representations
1585    /// for the target's color space.
1586    ///
1587    /// Returns `Ok` if:
1588    /// - Both images to have the same dimensions, otherwise returns a [`ImageError::Parameter`].
1589    /// - The primaries and transfer functions of both image's color spaces must be supported,
1590    ///   otherwise returns a [`ImageError::Unsupported`].
1591    /// - The pixel's channel layout must be supported for conversion, otherwise returns a
1592    ///   [`ImageError::Unsupported`]. You can rely on RGB and RGBA always being supported. If a
1593    ///   layout is supported for one color space it is supported for all of them.
1594    ///
1595    /// To copy color data of arbitrary channel layouts use `DynamicImage` with the overhead of
1596    /// having data converted into and from RGB representation.
1597    pub fn copy_from_color_space<FromType, D>(
1598        &mut self,
1599        from: &ImageBuffer<FromType, D>,
1600        mut options: ConvertColorOptions,
1601    ) -> ImageResult<()>
1602    where
1603        FromType: Pixel<Subpixel = SelfPixel::Subpixel> + PixelWithColorType,
1604        D: Deref<Target = [SelfPixel::Subpixel]>,
1605    {
1606        if self.dimensions() != from.dimensions() {
1607            return Err(ImageError::Parameter(ParameterError::from_kind(
1608                ParameterErrorKind::DimensionMismatch,
1609            )));
1610        }
1611
1612        let transform = options
1613            .as_transform_fn::<FromType, SelfPixel>(from.color_space(), self.color_space())?;
1614
1615        let from = from.inner_pixels();
1616        let into = self.inner_pixels_mut();
1617
1618        debug_assert_eq!(
1619            from.len() / usize::from(FromType::CHANNEL_COUNT),
1620            into.len() / usize::from(SelfPixel::CHANNEL_COUNT),
1621            "Diverging pixel count despite same size",
1622        );
1623
1624        transform(from, into);
1625
1626        Ok(())
1627    }
1628
1629    /// Convert this buffer into a newly allocated buffer, changing the color representation.
1630    ///
1631    /// This will avoid an allocation if the target layout or the color conversion is not supported
1632    /// (yet).
1633    ///
1634    /// See [`ImageBuffer::copy_from_color_space`] if you intend to assign to an existing buffer,
1635    /// swapping the argument with `self`.
1636    pub fn to_color_space<IntoType>(
1637        &self,
1638        color: Cicp,
1639        mut options: ConvertColorOptions,
1640    ) -> Result<ImageBuffer<IntoType, Vec<SelfPixel::Subpixel>>, ImageError>
1641    where
1642        IntoType: Pixel<Subpixel = SelfPixel::Subpixel> + PixelWithColorType,
1643    {
1644        let transform =
1645            options.as_transform_fn::<SelfPixel, IntoType>(self.color_space(), color)?;
1646
1647        let (width, height) = self.dimensions();
1648        let mut target = ImageBuffer::new(width, height);
1649
1650        let from = self.inner_pixels();
1651        let into = target.inner_pixels_mut();
1652
1653        transform(from, into);
1654
1655        Ok(target)
1656    }
1657
1658    /// Apply a color space to an image, transforming the pixel representation.
1659    pub fn apply_color_space(
1660        &mut self,
1661        color: Cicp,
1662        mut options: ConvertColorOptions,
1663    ) -> ImageResult<()> {
1664        if self.color_space() == color {
1665            return Ok(());
1666        }
1667
1668        let transform =
1669            options.as_transform_fn::<SelfPixel, SelfPixel>(self.color_space(), color)?;
1670
1671        let mut scratch = [<SelfPixel::Subpixel as crate::Primitive>::DEFAULT_MIN_VALUE; 1200];
1672        let chunk_len = scratch.len() / usize::from(<SelfPixel as Pixel>::CHANNEL_COUNT)
1673            * usize::from(<SelfPixel as Pixel>::CHANNEL_COUNT);
1674
1675        for chunk in self.data.chunks_mut(chunk_len) {
1676            let scratch = &mut scratch[..chunk.len()];
1677            scratch.copy_from_slice(chunk);
1678            transform(scratch, chunk);
1679        }
1680
1681        self.color = color.into_rgb();
1682
1683        Ok(())
1684    }
1685}
1686
1687/// Sendable Rgb image buffer
1688pub type RgbImage = ImageBuffer<Rgb<u8>, Vec<u8>>;
1689/// Sendable Rgb + alpha channel image buffer
1690pub type RgbaImage = ImageBuffer<Rgba<u8>, Vec<u8>>;
1691/// Sendable grayscale image buffer
1692pub type GrayImage = ImageBuffer<Luma<u8>, Vec<u8>>;
1693/// Sendable grayscale + alpha channel image buffer
1694pub type GrayAlphaImage = ImageBuffer<LumaA<u8>, Vec<u8>>;
1695/// Sendable 16-bit Rgb image buffer
1696pub(crate) type Rgb16Image = ImageBuffer<Rgb<u16>, Vec<u16>>;
1697/// Sendable 16-bit Rgb + alpha channel image buffer
1698pub(crate) type Rgba16Image = ImageBuffer<Rgba<u16>, Vec<u16>>;
1699/// Sendable 16-bit grayscale image buffer
1700pub(crate) type Gray16Image = ImageBuffer<Luma<u16>, Vec<u16>>;
1701/// Sendable 16-bit grayscale + alpha channel image buffer
1702pub(crate) type GrayAlpha16Image = ImageBuffer<LumaA<u16>, Vec<u16>>;
1703
1704/// An image buffer for 32-bit float RGB pixels,
1705/// where the backing container is a flattened vector of floats.
1706pub type Rgb32FImage = ImageBuffer<Rgb<f32>, Vec<f32>>;
1707
1708/// An image buffer for 32-bit float RGBA pixels,
1709/// where the backing container is a flattened vector of floats.
1710pub type Rgba32FImage = ImageBuffer<Rgba<f32>, Vec<f32>>;
1711
1712impl From<DynamicImage> for RgbImage {
1713    fn from(value: DynamicImage) -> Self {
1714        value.into_rgb8()
1715    }
1716}
1717
1718impl From<DynamicImage> for RgbaImage {
1719    fn from(value: DynamicImage) -> Self {
1720        value.into_rgba8()
1721    }
1722}
1723
1724impl From<DynamicImage> for GrayImage {
1725    fn from(value: DynamicImage) -> Self {
1726        value.into_luma8()
1727    }
1728}
1729
1730impl From<DynamicImage> for GrayAlphaImage {
1731    fn from(value: DynamicImage) -> Self {
1732        value.into_luma_alpha8()
1733    }
1734}
1735
1736impl From<DynamicImage> for Rgb16Image {
1737    fn from(value: DynamicImage) -> Self {
1738        value.into_rgb16()
1739    }
1740}
1741
1742impl From<DynamicImage> for Rgba16Image {
1743    fn from(value: DynamicImage) -> Self {
1744        value.into_rgba16()
1745    }
1746}
1747
1748impl From<DynamicImage> for Gray16Image {
1749    fn from(value: DynamicImage) -> Self {
1750        value.into_luma16()
1751    }
1752}
1753
1754impl From<DynamicImage> for GrayAlpha16Image {
1755    fn from(value: DynamicImage) -> Self {
1756        value.into_luma_alpha16()
1757    }
1758}
1759
1760impl From<DynamicImage> for Rgba32FImage {
1761    fn from(value: DynamicImage) -> Self {
1762        value.into_rgba32f()
1763    }
1764}
1765
1766#[cfg(test)]
1767mod test {
1768    use super::{GrayImage, ImageBuffer, RgbImage};
1769    use crate::math::Rect;
1770    use crate::metadata::Cicp;
1771    use crate::metadata::CicpTransform;
1772    use crate::GenericImage as _;
1773    use crate::ImageFormat;
1774    use crate::{Luma, LumaA, Pixel, Rgb, Rgba};
1775    use num_traits::Zero;
1776
1777    #[test]
1778    /// Tests if image buffers from slices work
1779    fn slice_buffer() {
1780        let data = [0; 9];
1781        let buf: ImageBuffer<Luma<u8>, _> = ImageBuffer::from_raw(3, 3, &data[..]).unwrap();
1782        assert_eq!(&*buf, &data[..]);
1783    }
1784
1785    macro_rules! new_buffer_zero_test {
1786        ($test_name:ident, $pxt:ty) => {
1787            #[test]
1788            fn $test_name() {
1789                let buffer = ImageBuffer::<$pxt, Vec<<$pxt as Pixel>::Subpixel>>::new(2, 2);
1790                assert!(buffer
1791                    .iter()
1792                    .all(|p| *p == <$pxt as Pixel>::Subpixel::zero()));
1793            }
1794        };
1795    }
1796
1797    new_buffer_zero_test!(luma_u8_zero_test, Luma<u8>);
1798    new_buffer_zero_test!(luma_u16_zero_test, Luma<u16>);
1799    new_buffer_zero_test!(luma_f32_zero_test, Luma<f32>);
1800    new_buffer_zero_test!(luma_a_u8_zero_test, LumaA<u8>);
1801    new_buffer_zero_test!(luma_a_u16_zero_test, LumaA<u16>);
1802    new_buffer_zero_test!(luma_a_f32_zero_test, LumaA<f32>);
1803    new_buffer_zero_test!(rgb_u8_zero_test, Rgb<u8>);
1804    new_buffer_zero_test!(rgb_u16_zero_test, Rgb<u16>);
1805    new_buffer_zero_test!(rgb_f32_zero_test, Rgb<f32>);
1806    new_buffer_zero_test!(rgb_a_u8_zero_test, Rgba<u8>);
1807    new_buffer_zero_test!(rgb_a_u16_zero_test, Rgba<u16>);
1808    new_buffer_zero_test!(rgb_a_f32_zero_test, Rgba<f32>);
1809
1810    #[test]
1811    fn get_pixel() {
1812        let mut a: RgbImage = ImageBuffer::new(10, 10);
1813        {
1814            let b = a.get_mut(3 * 10).unwrap();
1815            *b = 255;
1816        }
1817        assert_eq!(a.get_pixel(0, 1)[0], 255);
1818    }
1819
1820    #[test]
1821    fn get_pixel_checked() {
1822        let mut a: RgbImage = ImageBuffer::new(10, 10);
1823        a.get_pixel_mut_checked(0, 1).unwrap()[0] = 255;
1824
1825        assert_eq!(a.get_pixel_checked(0, 1), Some(&Rgb([255, 0, 0])));
1826        assert_eq!(a.get_pixel_checked(0, 1).unwrap(), a.get_pixel(0, 1));
1827        assert_eq!(a.get_pixel_checked(10, 0), None);
1828        assert_eq!(a.get_pixel_checked(0, 10), None);
1829        assert_eq!(a.get_pixel_mut_checked(10, 0), None);
1830        assert_eq!(a.get_pixel_mut_checked(0, 10), None);
1831
1832        // From image/issues/1672
1833        const WHITE: Rgb<u8> = Rgb([255_u8, 255, 255]);
1834        let mut a = RgbImage::new(2, 1);
1835        a.put_pixel(1, 0, WHITE);
1836
1837        assert_eq!(a.get_pixel_checked(1, 0), Some(&WHITE));
1838        assert_eq!(a.get_pixel_checked(1, 0).unwrap(), a.get_pixel(1, 0));
1839    }
1840
1841    #[test]
1842    fn mut_iter() {
1843        let mut a: RgbImage = ImageBuffer::new(10, 10);
1844        {
1845            let val = a.pixels_mut().next().unwrap();
1846            *val = Rgb([42, 0, 0]);
1847        }
1848        assert_eq!(a.data[0], 42);
1849    }
1850
1851    #[test]
1852    fn zero_width_zero_height() {
1853        let mut image = RgbImage::new(0, 0);
1854
1855        assert_eq!(image.rows_mut().count(), 0);
1856        assert_eq!(image.pixels_mut().count(), 0);
1857        assert_eq!(image.rows().count(), 0);
1858        assert_eq!(image.pixels().count(), 0);
1859    }
1860
1861    #[test]
1862    fn zero_width_nonzero_height() {
1863        let mut image = RgbImage::new(0, 2);
1864
1865        assert_eq!(image.rows_mut().count(), 0);
1866        assert_eq!(image.pixels_mut().count(), 0);
1867        assert_eq!(image.rows().count(), 0);
1868        assert_eq!(image.pixels().count(), 0);
1869    }
1870
1871    #[test]
1872    fn nonzero_width_zero_height() {
1873        let mut image = RgbImage::new(2, 0);
1874
1875        assert_eq!(image.rows_mut().count(), 0);
1876        assert_eq!(image.pixels_mut().count(), 0);
1877        assert_eq!(image.rows().count(), 0);
1878        assert_eq!(image.pixels().count(), 0);
1879    }
1880
1881    #[test]
1882    fn pixels_on_large_buffer() {
1883        let mut image = RgbImage::from_raw(1, 1, vec![0; 6]).unwrap();
1884
1885        assert_eq!(image.pixels().count(), 1);
1886        assert_eq!(image.enumerate_pixels().count(), 1);
1887        assert_eq!(image.pixels_mut().count(), 1);
1888        assert_eq!(image.enumerate_pixels_mut().count(), 1);
1889
1890        assert_eq!(image.rows().count(), 1);
1891        assert_eq!(image.rows_mut().count(), 1);
1892    }
1893
1894    #[test]
1895    fn default() {
1896        let image = ImageBuffer::<Rgb<u8>, Vec<u8>>::default();
1897        assert_eq!(image.dimensions(), (0, 0));
1898    }
1899
1900    #[test]
1901    #[rustfmt::skip]
1902    fn test_image_buffer_copy_within_oob() {
1903        let mut image: GrayImage = ImageBuffer::from_raw(4, 4, vec![0u8; 16]).unwrap();
1904        assert!(!image.copy_within(Rect { x: 0, y: 0, width: 5, height: 4 }, 0, 0));
1905        assert!(!image.copy_within(Rect { x: 0, y: 0, width: 4, height: 5 }, 0, 0));
1906        assert!(!image.copy_within(Rect { x: 1, y: 0, width: 4, height: 4 }, 0, 0));
1907        assert!(!image.copy_within(Rect { x: 0, y: 0, width: 4, height: 4 }, 1, 0));
1908        assert!(!image.copy_within(Rect { x: 0, y: 1, width: 4, height: 4 }, 0, 0));
1909        assert!(!image.copy_within(Rect { x: 0, y: 0, width: 4, height: 4 }, 0, 1));
1910        assert!(!image.copy_within(Rect { x: 1, y: 1, width: 4, height: 4 }, 0, 0));
1911    }
1912
1913    #[test]
1914    fn test_image_buffer_copy_within_tl() {
1915        let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
1916        let expected = [0, 1, 2, 3, 4, 0, 1, 2, 8, 4, 5, 6, 12, 8, 9, 10];
1917        let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap();
1918        assert!(image.copy_within(
1919            Rect {
1920                x: 0,
1921                y: 0,
1922                width: 3,
1923                height: 3
1924            },
1925            1,
1926            1
1927        ));
1928        assert_eq!(&image.into_raw(), &expected);
1929    }
1930
1931    #[test]
1932    fn test_image_buffer_copy_within_tr() {
1933        let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
1934        let expected = [0, 1, 2, 3, 1, 2, 3, 7, 5, 6, 7, 11, 9, 10, 11, 15];
1935        let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap();
1936        assert!(image.copy_within(
1937            Rect {
1938                x: 1,
1939                y: 0,
1940                width: 3,
1941                height: 3
1942            },
1943            0,
1944            1
1945        ));
1946        assert_eq!(&image.into_raw(), &expected);
1947    }
1948
1949    #[test]
1950    fn test_image_buffer_copy_within_bl() {
1951        let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
1952        let expected = [0, 4, 5, 6, 4, 8, 9, 10, 8, 12, 13, 14, 12, 13, 14, 15];
1953        let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap();
1954        assert!(image.copy_within(
1955            Rect {
1956                x: 0,
1957                y: 1,
1958                width: 3,
1959                height: 3
1960            },
1961            1,
1962            0
1963        ));
1964        assert_eq!(&image.into_raw(), &expected);
1965    }
1966
1967    #[test]
1968    fn test_image_buffer_copy_within_br() {
1969        let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
1970        let expected = [5, 6, 7, 3, 9, 10, 11, 7, 13, 14, 15, 11, 12, 13, 14, 15];
1971        let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap();
1972        assert!(image.copy_within(
1973            Rect {
1974                x: 1,
1975                y: 1,
1976                width: 3,
1977                height: 3
1978            },
1979            0,
1980            0
1981        ));
1982        assert_eq!(&image.into_raw(), &expected);
1983    }
1984
1985    #[test]
1986    #[cfg(feature = "png")]
1987    fn write_to_with_large_buffer() {
1988        // A buffer of 1 pixel, padded to 4 bytes as would be common in, e.g. BMP.
1989
1990        let img: GrayImage = ImageBuffer::from_raw(1, 1, vec![0u8; 4]).unwrap();
1991        let mut buffer = std::io::Cursor::new(vec![]);
1992        assert!(img.write_to(&mut buffer, ImageFormat::Png).is_ok());
1993    }
1994
1995    #[test]
1996    fn exact_size_iter_size_hint() {
1997        // The docs for `std::iter::ExactSizeIterator` requires that the implementation of
1998        // `size_hint` on the iterator returns the same value as the `len` implementation.
1999
2000        // This test should work for any size image.
2001        const N: u32 = 10;
2002
2003        let mut image = RgbImage::from_raw(N, N, vec![0; (N * N * 3) as usize]).unwrap();
2004
2005        let iter = image.pixels();
2006        let exact_len = ExactSizeIterator::len(&iter);
2007        assert_eq!(iter.size_hint(), (exact_len, Some(exact_len)));
2008
2009        let iter = image.pixels_mut();
2010        let exact_len = ExactSizeIterator::len(&iter);
2011        assert_eq!(iter.size_hint(), (exact_len, Some(exact_len)));
2012
2013        let iter = image.rows();
2014        let exact_len = ExactSizeIterator::len(&iter);
2015        assert_eq!(iter.size_hint(), (exact_len, Some(exact_len)));
2016
2017        let iter = image.rows_mut();
2018        let exact_len = ExactSizeIterator::len(&iter);
2019        assert_eq!(iter.size_hint(), (exact_len, Some(exact_len)));
2020
2021        let iter = image.enumerate_pixels();
2022        let exact_len = ExactSizeIterator::len(&iter);
2023        assert_eq!(iter.size_hint(), (exact_len, Some(exact_len)));
2024
2025        let iter = image.enumerate_rows();
2026        let exact_len = ExactSizeIterator::len(&iter);
2027        assert_eq!(iter.size_hint(), (exact_len, Some(exact_len)));
2028
2029        let iter = image.enumerate_pixels_mut();
2030        let exact_len = ExactSizeIterator::len(&iter);
2031        assert_eq!(iter.size_hint(), (exact_len, Some(exact_len)));
2032
2033        let iter = image.enumerate_rows_mut();
2034        let exact_len = ExactSizeIterator::len(&iter);
2035        assert_eq!(iter.size_hint(), (exact_len, Some(exact_len)));
2036    }
2037
2038    #[test]
2039    fn color_conversion() {
2040        let mut source = ImageBuffer::from_fn(128, 128, |_, _| Rgb([255, 0, 0]));
2041        let mut target = ImageBuffer::from_fn(128, 128, |_, _| Rgba(Default::default()));
2042
2043        source.set_rgb_primaries(Cicp::SRGB.primaries);
2044        source.set_transfer_function(Cicp::SRGB.transfer);
2045
2046        target.set_rgb_primaries(Cicp::DISPLAY_P3.primaries);
2047        target.set_transfer_function(Cicp::DISPLAY_P3.transfer);
2048
2049        let result = target.copy_from_color_space(&source, Default::default());
2050
2051        assert!(result.is_ok(), "{result:?}");
2052        assert_eq!(target[(0, 0)], Rgba([234u8, 51, 35, 255]));
2053    }
2054
2055    #[test]
2056    fn gray_conversions() {
2057        let mut source = ImageBuffer::from_fn(128, 128, |_, _| Luma([255u8]));
2058        let mut target = ImageBuffer::from_fn(128, 128, |_, _| Rgba(Default::default()));
2059
2060        source.set_rgb_primaries(Cicp::SRGB.primaries);
2061        source.set_transfer_function(Cicp::SRGB.transfer);
2062
2063        target.set_rgb_primaries(Cicp::SRGB.primaries);
2064        target.set_transfer_function(Cicp::SRGB.transfer);
2065
2066        let result = target.copy_from_color_space(&source, Default::default());
2067
2068        assert!(result.is_ok(), "{result:?}");
2069        assert_eq!(target[(0, 0)], Rgba([u8::MAX; 4]));
2070    }
2071
2072    #[test]
2073    fn rgb_to_gray_conversion() {
2074        let mut source = ImageBuffer::from_fn(128, 128, |_, _| Rgb([128u8; 3]));
2075        let mut target = ImageBuffer::from_fn(128, 128, |_, _| Luma(Default::default()));
2076
2077        source.set_rgb_primaries(Cicp::SRGB.primaries);
2078        source.set_transfer_function(Cicp::SRGB.transfer);
2079
2080        target.set_rgb_primaries(Cicp::SRGB.primaries);
2081        target.set_transfer_function(Cicp::SRGB.transfer);
2082
2083        let result = target.copy_from_color_space(&source, Default::default());
2084
2085        assert!(result.is_ok(), "{result:?}");
2086        assert_eq!(target[(0, 0)], Luma([128u8]));
2087    }
2088
2089    #[test]
2090    fn apply_color() {
2091        let mut buffer = ImageBuffer::from_fn(128, 128, |_, _| Rgb([255u8, 0, 0]));
2092
2093        buffer.set_rgb_primaries(Cicp::SRGB.primaries);
2094        buffer.set_transfer_function(Cicp::SRGB.transfer);
2095
2096        buffer
2097            .apply_color_space(Cicp::DISPLAY_P3, Default::default())
2098            .expect("supported transform");
2099
2100        buffer.pixels().for_each(|&p| {
2101            assert_eq!(p, Rgb([234u8, 51, 35]));
2102        });
2103    }
2104
2105    #[test]
2106    fn to_color() {
2107        let mut source = ImageBuffer::from_fn(128, 128, |_, _| Rgba([255u8, 0, 0, 255]));
2108        source.set_rgb_primaries(Cicp::SRGB.primaries);
2109        source.set_transfer_function(Cicp::SRGB.transfer);
2110
2111        let target = source
2112            .to_color_space::<Rgb<u8>>(Cicp::DISPLAY_P3, Default::default())
2113            .expect("supported transform");
2114
2115        assert_eq!(target[(0, 0)], Rgb([234u8, 51, 35]));
2116    }
2117
2118    #[test]
2119    fn transformation_mismatch() {
2120        let mut source = ImageBuffer::from_fn(128, 128, |_, _| Luma([255u8]));
2121        let mut target = ImageBuffer::from_fn(128, 128, |_, _| Rgba(Default::default()));
2122
2123        source.set_color_space(Cicp::SRGB).unwrap();
2124        target.set_color_space(Cicp::DISPLAY_P3).unwrap();
2125
2126        let options = super::ConvertColorOptions {
2127            transform: CicpTransform::new(Cicp::SRGB, Cicp::SRGB),
2128            ..super::ConvertColorOptions::default()
2129        };
2130
2131        let result = target.copy_from_color_space(&source, options);
2132        assert!(matches!(result, Err(crate::ImageError::Parameter(_))));
2133    }
2134}
2135
2136#[cfg(test)]
2137#[cfg(feature = "benchmarks")]
2138mod benchmarks {
2139    use super::{ConvertBuffer, GrayImage, ImageBuffer, Pixel, RgbImage};
2140
2141    #[bench]
2142    fn conversion(b: &mut test::Bencher) {
2143        let mut a: RgbImage = ImageBuffer::new(1000, 1000);
2144        for p in a.pixels_mut() {
2145            let rgb = p.channels_mut();
2146            rgb[0] = 255;
2147            rgb[1] = 23;
2148            rgb[2] = 42;
2149        }
2150
2151        assert!(a.data[0] != 0);
2152        b.iter(|| {
2153            let b: GrayImage = a.convert();
2154            assert!(0 != b.data[0]);
2155            assert!(a.data[0] != b.data[0]);
2156            test::black_box(b);
2157        });
2158        b.bytes = 1000 * 1000 * 3;
2159    }
2160
2161    #[bench]
2162    fn image_access_row_by_row(b: &mut test::Bencher) {
2163        let mut a: RgbImage = ImageBuffer::new(1000, 1000);
2164        for p in a.pixels_mut() {
2165            let rgb = p.channels_mut();
2166            rgb[0] = 255;
2167            rgb[1] = 23;
2168            rgb[2] = 42;
2169        }
2170
2171        b.iter(move || {
2172            let image: &RgbImage = test::black_box(&a);
2173            let mut sum: usize = 0;
2174            for y in 0..1000 {
2175                for x in 0..1000 {
2176                    let pixel = image.get_pixel(x, y);
2177                    sum = sum.wrapping_add(pixel[0] as usize);
2178                    sum = sum.wrapping_add(pixel[1] as usize);
2179                    sum = sum.wrapping_add(pixel[2] as usize);
2180                }
2181            }
2182            test::black_box(sum)
2183        });
2184
2185        b.bytes = 1000 * 1000 * 3;
2186    }
2187
2188    #[bench]
2189    fn image_access_col_by_col(b: &mut test::Bencher) {
2190        let mut a: RgbImage = ImageBuffer::new(1000, 1000);
2191        for p in a.pixels_mut() {
2192            let rgb = p.channels_mut();
2193            rgb[0] = 255;
2194            rgb[1] = 23;
2195            rgb[2] = 42;
2196        }
2197
2198        b.iter(move || {
2199            let image: &RgbImage = test::black_box(&a);
2200            let mut sum: usize = 0;
2201            for x in 0..1000 {
2202                for y in 0..1000 {
2203                    let pixel = image.get_pixel(x, y);
2204                    sum = sum.wrapping_add(pixel[0] as usize);
2205                    sum = sum.wrapping_add(pixel[1] as usize);
2206                    sum = sum.wrapping_add(pixel[2] as usize);
2207                }
2208            }
2209            test::black_box(sum)
2210        });
2211
2212        b.bytes = 1000 * 1000 * 3;
2213    }
2214}