Skip to main content

ai_image/images/
buffer.rs

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