image/
image.rs

1#![allow(clippy::too_many_arguments)]
2use std::ffi::OsStr;
3use std::io::{self, Write};
4use std::mem::size_of;
5use std::ops::{Deref, DerefMut};
6use std::path::Path;
7
8use crate::color::{ColorType, ExtendedColorType};
9use crate::error::{
10    ImageError, ImageFormatHint, ImageResult, LimitError, LimitErrorKind, ParameterError,
11    ParameterErrorKind, UnsupportedError, UnsupportedErrorKind,
12};
13use crate::math::Rect;
14use crate::metadata::Orientation;
15use crate::traits::Pixel;
16use crate::ImageBuffer;
17
18use crate::animation::Frames;
19
20/// An enumeration of supported image formats.
21/// Not all formats support both encoding and decoding.
22#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
23#[non_exhaustive]
24pub enum ImageFormat {
25    /// An Image in PNG Format
26    Png,
27
28    /// An Image in JPEG Format
29    Jpeg,
30
31    /// An Image in GIF Format
32    Gif,
33
34    /// An Image in WEBP Format
35    WebP,
36
37    /// An Image in general PNM Format
38    Pnm,
39
40    /// An Image in TIFF Format
41    Tiff,
42
43    /// An Image in TGA Format
44    Tga,
45
46    /// An Image in DDS Format
47    Dds,
48
49    /// An Image in BMP Format
50    Bmp,
51
52    /// An Image in ICO Format
53    Ico,
54
55    /// An Image in Radiance HDR Format
56    Hdr,
57
58    /// An Image in OpenEXR Format
59    OpenExr,
60
61    /// An Image in farbfeld Format
62    Farbfeld,
63
64    /// An Image in AVIF Format
65    Avif,
66
67    /// An Image in QOI Format
68    Qoi,
69}
70
71impl ImageFormat {
72    /// Return the image format specified by a path's file extension.
73    ///
74    /// # Example
75    ///
76    /// ```
77    /// use image::ImageFormat;
78    ///
79    /// let format = ImageFormat::from_extension("jpg");
80    /// assert_eq!(format, Some(ImageFormat::Jpeg));
81    /// ```
82    #[inline]
83    pub fn from_extension<S>(ext: S) -> Option<Self>
84    where
85        S: AsRef<OsStr>,
86    {
87        // thin wrapper function to strip generics
88        fn inner(ext: &OsStr) -> Option<ImageFormat> {
89            let ext = ext.to_str()?.to_ascii_lowercase();
90
91            Some(match ext.as_str() {
92                "avif" => ImageFormat::Avif,
93                "jpg" | "jpeg" => ImageFormat::Jpeg,
94                "png" | "apng" => ImageFormat::Png,
95                "gif" => ImageFormat::Gif,
96                "webp" => ImageFormat::WebP,
97                "tif" | "tiff" => ImageFormat::Tiff,
98                "tga" => ImageFormat::Tga,
99                "dds" => ImageFormat::Dds,
100                "bmp" => ImageFormat::Bmp,
101                "ico" => ImageFormat::Ico,
102                "hdr" => ImageFormat::Hdr,
103                "exr" => ImageFormat::OpenExr,
104                "pbm" | "pam" | "ppm" | "pgm" => ImageFormat::Pnm,
105                "ff" => ImageFormat::Farbfeld,
106                "qoi" => ImageFormat::Qoi,
107                _ => return None,
108            })
109        }
110
111        inner(ext.as_ref())
112    }
113
114    /// Return the image format specified by the path's file extension.
115    ///
116    /// # Example
117    ///
118    /// ```
119    /// use image::ImageFormat;
120    ///
121    /// let format = ImageFormat::from_path("images/ferris.png")?;
122    /// assert_eq!(format, ImageFormat::Png);
123    ///
124    /// # Ok::<(), image::error::ImageError>(())
125    /// ```
126    #[inline]
127    pub fn from_path<P>(path: P) -> ImageResult<Self>
128    where
129        P: AsRef<Path>,
130    {
131        // thin wrapper function to strip generics
132        fn inner(path: &Path) -> ImageResult<ImageFormat> {
133            let exact_ext = path.extension();
134            exact_ext
135                .and_then(ImageFormat::from_extension)
136                .ok_or_else(|| {
137                    let format_hint = match exact_ext {
138                        None => ImageFormatHint::Unknown,
139                        Some(os) => ImageFormatHint::PathExtension(os.into()),
140                    };
141                    ImageError::Unsupported(format_hint.into())
142                })
143        }
144
145        inner(path.as_ref())
146    }
147
148    /// Return the image format specified by a MIME type.
149    ///
150    /// # Example
151    ///
152    /// ```
153    /// use image::ImageFormat;
154    ///
155    /// let format = ImageFormat::from_mime_type("image/png").unwrap();
156    /// assert_eq!(format, ImageFormat::Png);
157    /// ```
158    pub fn from_mime_type<M>(mime_type: M) -> Option<Self>
159    where
160        M: AsRef<str>,
161    {
162        match mime_type.as_ref() {
163            "image/avif" => Some(ImageFormat::Avif),
164            "image/jpeg" => Some(ImageFormat::Jpeg),
165            "image/png" => Some(ImageFormat::Png),
166            "image/gif" => Some(ImageFormat::Gif),
167            "image/webp" => Some(ImageFormat::WebP),
168            "image/tiff" => Some(ImageFormat::Tiff),
169            "image/x-targa" | "image/x-tga" => Some(ImageFormat::Tga),
170            "image/vnd-ms.dds" => Some(ImageFormat::Dds),
171            "image/bmp" => Some(ImageFormat::Bmp),
172            "image/x-icon" => Some(ImageFormat::Ico),
173            "image/vnd.radiance" => Some(ImageFormat::Hdr),
174            "image/x-exr" => Some(ImageFormat::OpenExr),
175            "image/x-portable-bitmap"
176            | "image/x-portable-graymap"
177            | "image/x-portable-pixmap"
178            | "image/x-portable-anymap" => Some(ImageFormat::Pnm),
179            // Qoi's MIME type is being worked on.
180            // See: https://github.com/phoboslab/qoi/issues/167
181            "image/x-qoi" => Some(ImageFormat::Qoi),
182            _ => None,
183        }
184    }
185
186    /// Return the MIME type for this image format or "application/octet-stream" if no MIME type
187    /// exists for the format.
188    ///
189    /// Some notes on a few of the MIME types:
190    ///
191    /// - The portable anymap format has a separate MIME type for the pixmap, graymap and bitmap
192    ///   formats, but this method returns the general "image/x-portable-anymap" MIME type.
193    /// - The Targa format has two common MIME types, "image/x-targa"  and "image/x-tga"; this
194    ///   method returns "image/x-targa" for that format.
195    /// - The QOI MIME type is still a work in progress. This method returns "image/x-qoi" for
196    ///   that format.
197    ///
198    /// # Example
199    ///
200    /// ```
201    /// use image::ImageFormat;
202    ///
203    /// let mime_type = ImageFormat::Png.to_mime_type();
204    /// assert_eq!(mime_type, "image/png");
205    /// ```
206    #[must_use]
207    pub fn to_mime_type(&self) -> &'static str {
208        match self {
209            ImageFormat::Avif => "image/avif",
210            ImageFormat::Jpeg => "image/jpeg",
211            ImageFormat::Png => "image/png",
212            ImageFormat::Gif => "image/gif",
213            ImageFormat::WebP => "image/webp",
214            ImageFormat::Tiff => "image/tiff",
215            // the targa MIME type has two options, but this one seems to be used more
216            ImageFormat::Tga => "image/x-targa",
217            ImageFormat::Dds => "image/vnd-ms.dds",
218            ImageFormat::Bmp => "image/bmp",
219            ImageFormat::Ico => "image/x-icon",
220            ImageFormat::Hdr => "image/vnd.radiance",
221            ImageFormat::OpenExr => "image/x-exr",
222            // return the most general MIME type
223            ImageFormat::Pnm => "image/x-portable-anymap",
224            // Qoi's MIME type is being worked on.
225            // See: https://github.com/phoboslab/qoi/issues/167
226            ImageFormat::Qoi => "image/x-qoi",
227            // farbfeld's MIME type taken from https://www.wikidata.org/wiki/Q28206109
228            ImageFormat::Farbfeld => "application/octet-stream",
229        }
230    }
231
232    /// Return if the `ImageFormat` can be decoded by the lib.
233    #[inline]
234    #[must_use]
235    pub fn can_read(&self) -> bool {
236        // Needs to be updated once a new variant's decoder is added to free_functions.rs::load
237        match self {
238            ImageFormat::Png => true,
239            ImageFormat::Gif => true,
240            ImageFormat::Jpeg => true,
241            ImageFormat::WebP => true,
242            ImageFormat::Tiff => true,
243            ImageFormat::Tga => true,
244            ImageFormat::Dds => false,
245            ImageFormat::Bmp => true,
246            ImageFormat::Ico => true,
247            ImageFormat::Hdr => true,
248            ImageFormat::OpenExr => true,
249            ImageFormat::Pnm => true,
250            ImageFormat::Farbfeld => true,
251            ImageFormat::Avif => true,
252            ImageFormat::Qoi => true,
253        }
254    }
255
256    /// Return if the `ImageFormat` can be encoded by the lib.
257    #[inline]
258    #[must_use]
259    pub fn can_write(&self) -> bool {
260        // Needs to be updated once a new variant's encoder is added to free_functions.rs::save_buffer_with_format_impl
261        match self {
262            ImageFormat::Gif => true,
263            ImageFormat::Ico => true,
264            ImageFormat::Jpeg => true,
265            ImageFormat::Png => true,
266            ImageFormat::Bmp => true,
267            ImageFormat::Tiff => true,
268            ImageFormat::Tga => true,
269            ImageFormat::Pnm => true,
270            ImageFormat::Farbfeld => true,
271            ImageFormat::Avif => true,
272            ImageFormat::WebP => true,
273            ImageFormat::Hdr => true,
274            ImageFormat::OpenExr => true,
275            ImageFormat::Dds => false,
276            ImageFormat::Qoi => true,
277        }
278    }
279
280    /// Return a list of applicable extensions for this format.
281    ///
282    /// All currently recognized image formats specify at least on extension but for future
283    /// compatibility you should not rely on this fact. The list may be empty if the format has no
284    /// recognized file representation, for example in case it is used as a purely transient memory
285    /// format.
286    ///
287    /// The method name `extensions` remains reserved for introducing another method in the future
288    /// that yields a slice of `OsStr` which is blocked by several features of const evaluation.
289    #[must_use]
290    pub fn extensions_str(self) -> &'static [&'static str] {
291        match self {
292            ImageFormat::Png => &["png"],
293            ImageFormat::Jpeg => &["jpg", "jpeg"],
294            ImageFormat::Gif => &["gif"],
295            ImageFormat::WebP => &["webp"],
296            ImageFormat::Pnm => &["pbm", "pam", "ppm", "pgm"],
297            ImageFormat::Tiff => &["tiff", "tif"],
298            ImageFormat::Tga => &["tga"],
299            ImageFormat::Dds => &["dds"],
300            ImageFormat::Bmp => &["bmp"],
301            ImageFormat::Ico => &["ico"],
302            ImageFormat::Hdr => &["hdr"],
303            ImageFormat::OpenExr => &["exr"],
304            ImageFormat::Farbfeld => &["ff"],
305            // According to: https://aomediacodec.github.io/av1-avif/#mime-registration
306            ImageFormat::Avif => &["avif"],
307            ImageFormat::Qoi => &["qoi"],
308        }
309    }
310
311    /// Return the `ImageFormat`s which are enabled for reading.
312    #[inline]
313    #[must_use]
314    pub fn reading_enabled(&self) -> bool {
315        match self {
316            ImageFormat::Png => cfg!(feature = "png"),
317            ImageFormat::Gif => cfg!(feature = "gif"),
318            ImageFormat::Jpeg => cfg!(feature = "jpeg"),
319            ImageFormat::WebP => cfg!(feature = "webp"),
320            ImageFormat::Tiff => cfg!(feature = "tiff"),
321            ImageFormat::Tga => cfg!(feature = "tga"),
322            ImageFormat::Bmp => cfg!(feature = "bmp"),
323            ImageFormat::Ico => cfg!(feature = "ico"),
324            ImageFormat::Hdr => cfg!(feature = "hdr"),
325            ImageFormat::OpenExr => cfg!(feature = "exr"),
326            ImageFormat::Pnm => cfg!(feature = "pnm"),
327            ImageFormat::Farbfeld => cfg!(feature = "ff"),
328            ImageFormat::Avif => cfg!(feature = "avif"),
329            ImageFormat::Qoi => cfg!(feature = "qoi"),
330            ImageFormat::Dds => false,
331        }
332    }
333
334    /// Return the `ImageFormat`s which are enabled for writing.
335    #[inline]
336    #[must_use]
337    pub fn writing_enabled(&self) -> bool {
338        match self {
339            ImageFormat::Gif => cfg!(feature = "gif"),
340            ImageFormat::Ico => cfg!(feature = "ico"),
341            ImageFormat::Jpeg => cfg!(feature = "jpeg"),
342            ImageFormat::Png => cfg!(feature = "png"),
343            ImageFormat::Bmp => cfg!(feature = "bmp"),
344            ImageFormat::Tiff => cfg!(feature = "tiff"),
345            ImageFormat::Tga => cfg!(feature = "tga"),
346            ImageFormat::Pnm => cfg!(feature = "pnm"),
347            ImageFormat::Farbfeld => cfg!(feature = "ff"),
348            ImageFormat::Avif => cfg!(feature = "avif"),
349            ImageFormat::WebP => cfg!(feature = "webp"),
350            ImageFormat::OpenExr => cfg!(feature = "exr"),
351            ImageFormat::Qoi => cfg!(feature = "qoi"),
352            ImageFormat::Hdr => cfg!(feature = "hdr"),
353            ImageFormat::Dds => false,
354        }
355    }
356
357    /// Return all `ImageFormat`s
358    pub fn all() -> impl Iterator<Item = ImageFormat> {
359        [
360            ImageFormat::Gif,
361            ImageFormat::Ico,
362            ImageFormat::Jpeg,
363            ImageFormat::Png,
364            ImageFormat::Bmp,
365            ImageFormat::Tiff,
366            ImageFormat::Tga,
367            ImageFormat::Pnm,
368            ImageFormat::Farbfeld,
369            ImageFormat::Avif,
370            ImageFormat::WebP,
371            ImageFormat::OpenExr,
372            ImageFormat::Qoi,
373            ImageFormat::Dds,
374            ImageFormat::Hdr,
375        ]
376        .iter()
377        .copied()
378    }
379}
380
381// This struct manages buffering associated with implementing `Read` and `Seek` on decoders that can
382// must decode ranges of bytes at a time.
383#[allow(dead_code)]
384// When no image formats that use it are enabled
385pub(crate) struct ImageReadBuffer {
386    scanline_bytes: usize,
387    buffer: Vec<u8>,
388    consumed: usize,
389
390    total_bytes: u64,
391    offset: u64,
392}
393impl ImageReadBuffer {
394    /// Create a new `ImageReadBuffer`.
395    ///
396    /// Panics if `scanline_bytes` doesn't fit into a usize, because that would mean reading anything
397    /// from the image would take more RAM than the entire virtual address space. In other words,
398    /// actually using this struct would instantly OOM so just get it out of the way now.
399    #[allow(dead_code)]
400    // When no image formats that use it are enabled
401    pub(crate) fn new(scanline_bytes: u64, total_bytes: u64) -> Self {
402        Self {
403            scanline_bytes: usize::try_from(scanline_bytes).unwrap(),
404            buffer: Vec::new(),
405            consumed: 0,
406            total_bytes,
407            offset: 0,
408        }
409    }
410
411    #[allow(dead_code)]
412    // When no image formats that use it are enabled
413    pub(crate) fn read<F>(&mut self, buf: &mut [u8], mut read_scanline: F) -> io::Result<usize>
414    where
415        F: FnMut(&mut [u8]) -> io::Result<usize>,
416    {
417        if self.buffer.len() == self.consumed {
418            if self.offset == self.total_bytes {
419                return Ok(0);
420            } else if buf.len() >= self.scanline_bytes {
421                // If there is nothing buffered and the user requested a full scanline worth of
422                // data, skip buffering.
423                let bytes_read = read_scanline(&mut buf[..self.scanline_bytes])?;
424                self.offset += u64::try_from(bytes_read).unwrap();
425                return Ok(bytes_read);
426            } else {
427                // Lazily allocate buffer the first time that read is called with a buffer smaller
428                // than the scanline size.
429                if self.buffer.is_empty() {
430                    self.buffer.resize(self.scanline_bytes, 0);
431                }
432
433                self.consumed = 0;
434                let bytes_read = read_scanline(&mut self.buffer[..])?;
435                self.buffer.resize(bytes_read, 0);
436                self.offset += u64::try_from(bytes_read).unwrap();
437
438                assert!(bytes_read == self.scanline_bytes || self.offset == self.total_bytes);
439            }
440        }
441
442        // Finally, copy bytes into output buffer.
443        let bytes_buffered = self.buffer.len() - self.consumed;
444        if bytes_buffered > buf.len() {
445            buf.copy_from_slice(&self.buffer[self.consumed..][..buf.len()]);
446            self.consumed += buf.len();
447            Ok(buf.len())
448        } else {
449            buf[..bytes_buffered].copy_from_slice(&self.buffer[self.consumed..][..bytes_buffered]);
450            self.consumed = self.buffer.len();
451            Ok(bytes_buffered)
452        }
453    }
454}
455
456/// Decodes a specific region of the image, represented by the rectangle
457/// starting from ```x``` and ```y``` and having ```length``` and ```width```
458#[allow(dead_code)]
459// When no image formats that use it are enabled
460pub(crate) fn load_rect<D, F1, F2, E>(
461    x: u32,
462    y: u32,
463    width: u32,
464    height: u32,
465    buf: &mut [u8],
466    row_pitch: usize,
467    decoder: &mut D,
468    scanline_bytes: usize,
469    mut seek_scanline: F1,
470    mut read_scanline: F2,
471) -> ImageResult<()>
472where
473    D: ImageDecoder,
474    F1: FnMut(&mut D, u64) -> io::Result<()>,
475    F2: FnMut(&mut D, &mut [u8]) -> Result<(), E>,
476    ImageError: From<E>,
477{
478    let scanline_bytes = u64::try_from(scanline_bytes).unwrap();
479    let row_pitch = u64::try_from(row_pitch).unwrap();
480
481    let (x, y, width, height) = (
482        u64::from(x),
483        u64::from(y),
484        u64::from(width),
485        u64::from(height),
486    );
487    let dimensions = decoder.dimensions();
488    let bytes_per_pixel = u64::from(decoder.color_type().bytes_per_pixel());
489    let row_bytes = bytes_per_pixel * u64::from(dimensions.0);
490    let total_bytes = width * height * bytes_per_pixel;
491
492    assert!(
493        buf.len() >= usize::try_from(total_bytes).unwrap_or(usize::MAX),
494        "output buffer too short\n expected `{}`, provided `{}`",
495        total_bytes,
496        buf.len()
497    );
498
499    let mut current_scanline = 0;
500    let mut tmp = Vec::new();
501    let mut tmp_scanline = None;
502
503    {
504        // Read a range of the image starting from byte number `start` and continuing until byte
505        // number `end`. Updates `current_scanline` and `bytes_read` appropriately.
506        let mut read_image_range =
507            |mut start: u64, end: u64, mut output: &mut [u8]| -> ImageResult<()> {
508                // If the first scanline we need is already stored in the temporary buffer, then handle
509                // it first.
510                let target_scanline = start / scanline_bytes;
511                if tmp_scanline == Some(target_scanline) {
512                    let position = target_scanline * scanline_bytes;
513                    let offset = start.saturating_sub(position);
514                    let len = (end - start)
515                        .min(scanline_bytes - offset)
516                        .min(end - position);
517
518                    output
519                        .write_all(&tmp[offset as usize..][..len as usize])
520                        .unwrap();
521                    start += len;
522
523                    if start == end {
524                        return Ok(());
525                    }
526                }
527
528                let target_scanline = start / scanline_bytes;
529                if target_scanline != current_scanline {
530                    seek_scanline(decoder, target_scanline)?;
531                    current_scanline = target_scanline;
532                }
533
534                let mut position = current_scanline * scanline_bytes;
535                while position < end {
536                    if position >= start && end - position >= scanline_bytes {
537                        read_scanline(decoder, &mut output[..(scanline_bytes as usize)])?;
538                        output = &mut output[scanline_bytes as usize..];
539                    } else {
540                        tmp.resize(scanline_bytes as usize, 0u8);
541                        read_scanline(decoder, &mut tmp)?;
542                        tmp_scanline = Some(current_scanline);
543
544                        let offset = start.saturating_sub(position);
545                        let len = (end - start)
546                            .min(scanline_bytes - offset)
547                            .min(end - position);
548
549                        output
550                            .write_all(&tmp[offset as usize..][..len as usize])
551                            .unwrap();
552                    }
553
554                    current_scanline += 1;
555                    position += scanline_bytes;
556                }
557                Ok(())
558            };
559
560        if x + width > u64::from(dimensions.0)
561            || y + height > u64::from(dimensions.1)
562            || width == 0
563            || height == 0
564        {
565            return Err(ImageError::Parameter(ParameterError::from_kind(
566                ParameterErrorKind::DimensionMismatch,
567            )));
568        }
569        if scanline_bytes > usize::MAX as u64 {
570            return Err(ImageError::Limits(LimitError::from_kind(
571                LimitErrorKind::InsufficientMemory,
572            )));
573        }
574
575        if x == 0 && width == u64::from(dimensions.0) && row_pitch == row_bytes {
576            let start = x * bytes_per_pixel + y * row_bytes;
577            let end = (x + width) * bytes_per_pixel + (y + height - 1) * row_bytes;
578            read_image_range(start, end, buf)?;
579        } else {
580            for (output_slice, row) in buf.chunks_mut(row_pitch as usize).zip(y..(y + height)) {
581                let start = x * bytes_per_pixel + row * row_bytes;
582                let end = (x + width) * bytes_per_pixel + row * row_bytes;
583                read_image_range(start, end, output_slice)?;
584            }
585        }
586    }
587
588    // Seek back to the start
589    Ok(seek_scanline(decoder, 0)?)
590}
591
592/// Reads all of the bytes of a decoder into a Vec<T>. No particular alignment
593/// of the output buffer is guaranteed.
594///
595/// Panics if there isn't enough memory to decode the image.
596pub(crate) fn decoder_to_vec<T>(decoder: impl ImageDecoder) -> ImageResult<Vec<T>>
597where
598    T: crate::traits::Primitive + bytemuck::Pod,
599{
600    let total_bytes = usize::try_from(decoder.total_bytes());
601    if total_bytes.is_err() || total_bytes.unwrap() > isize::MAX as usize {
602        return Err(ImageError::Limits(LimitError::from_kind(
603            LimitErrorKind::InsufficientMemory,
604        )));
605    }
606
607    let mut buf = vec![num_traits::Zero::zero(); total_bytes.unwrap() / size_of::<T>()];
608    decoder.read_image(bytemuck::cast_slice_mut(buf.as_mut_slice()))?;
609    Ok(buf)
610}
611
612/// The trait that all decoders implement
613pub trait ImageDecoder {
614    /// Returns a tuple containing the width and height of the image
615    fn dimensions(&self) -> (u32, u32);
616
617    /// Returns the color type of the image data produced by this decoder
618    fn color_type(&self) -> ColorType;
619
620    /// Returns the color type of the image file before decoding
621    fn original_color_type(&self) -> ExtendedColorType {
622        self.color_type().into()
623    }
624
625    /// Returns the ICC color profile embedded in the image, or `Ok(None)` if the image does not have one.
626    ///
627    /// For formats that don't support embedded profiles this function should always return `Ok(None)`.
628    fn icc_profile(&mut self) -> ImageResult<Option<Vec<u8>>> {
629        Ok(None)
630    }
631
632    /// Returns the raw [Exif](https://en.wikipedia.org/wiki/Exif) chunk, if it is present.
633    /// A third-party crate such as [`kamadak-exif`](https://docs.rs/kamadak-exif/) is required to actually parse it.
634    ///
635    /// For formats that don't support embedded profiles this function should always return `Ok(None)`.
636    fn exif_metadata(&mut self) -> ImageResult<Option<Vec<u8>>> {
637        Ok(None)
638    }
639
640    /// Returns the orientation of the image.
641    ///
642    /// This is usually obtained from the Exif metadata, if present. Formats that don't support
643    /// indicating orientation in their image metadata will return `Ok(Orientation::NoTransforms)`.
644    fn orientation(&mut self) -> ImageResult<Orientation> {
645        Ok(self
646            .exif_metadata()?
647            .and_then(|chunk| Orientation::from_exif_chunk(&chunk))
648            .unwrap_or(Orientation::NoTransforms))
649    }
650
651    /// Returns the total number of bytes in the decoded image.
652    ///
653    /// This is the size of the buffer that must be passed to `read_image` or
654    /// `read_image_with_progress`. The returned value may exceed `usize::MAX`, in
655    /// which case it isn't actually possible to construct a buffer to decode all the image data
656    /// into. If, however, the size does not fit in a u64 then `u64::MAX` is returned.
657    fn total_bytes(&self) -> u64 {
658        let dimensions = self.dimensions();
659        let total_pixels = u64::from(dimensions.0) * u64::from(dimensions.1);
660        let bytes_per_pixel = u64::from(self.color_type().bytes_per_pixel());
661        total_pixels.saturating_mul(bytes_per_pixel)
662    }
663
664    /// Returns all the bytes in the image.
665    ///
666    /// This function takes a slice of bytes and writes the pixel data of the image into it.
667    /// Although not required, for certain color types callers may want to pass buffers which are
668    /// aligned to 2 or 4 byte boundaries to the slice can be cast to a [u16] or [u32]. To accommodate
669    /// such casts, the returned contents will always be in native endian.
670    ///
671    /// # Panics
672    ///
673    /// This function panics if `buf.len() != self.total_bytes()`.
674    ///
675    /// # Examples
676    ///
677    /// ```no_build
678    /// use zerocopy::{AsBytes, FromBytes};
679    /// fn read_16bit_image(decoder: impl ImageDecoder) -> Vec<16> {
680    ///     let mut buf: Vec<u16> = vec![0; decoder.total_bytes()/2];
681    ///     decoder.read_image(buf.as_bytes());
682    ///     buf
683    /// }
684    /// ```
685    fn read_image(self, buf: &mut [u8]) -> ImageResult<()>
686    where
687        Self: Sized;
688
689    /// Set the decoder to have the specified limits. See [`Limits`] for the different kinds of
690    /// limits that is possible to set.
691    ///
692    /// Note to implementors: make sure you call [`Limits::check_support`] so that
693    /// decoding fails if any unsupported strict limits are set. Also make sure
694    /// you call [`Limits::check_dimensions`] to check the `max_image_width` and
695    /// `max_image_height` limits.
696    ///
697    /// [`Limits`]: ./io/struct.Limits.html
698    /// [`Limits::check_support`]: ./io/struct.Limits.html#method.check_support
699    /// [`Limits::check_dimensions`]: ./io/struct.Limits.html#method.check_dimensions
700    fn set_limits(&mut self, limits: crate::Limits) -> ImageResult<()> {
701        limits.check_support(&crate::LimitSupport::default())?;
702        let (width, height) = self.dimensions();
703        limits.check_dimensions(width, height)?;
704        Ok(())
705    }
706
707    /// Use `read_image` instead; this method is an implementation detail needed so the trait can
708    /// be object safe.
709    ///
710    /// Note to implementors: This method should be implemented by calling `read_image` on
711    /// the boxed decoder...
712    /// ```no_build
713    ///     fn read_image_boxed(self: Box<Self>, buf: &mut [u8]) -> ImageResult<()> {
714    ///        (*self).read_image(buf)
715    ///    }
716    /// ```
717    fn read_image_boxed(self: Box<Self>, buf: &mut [u8]) -> ImageResult<()>;
718}
719
720impl<T: ?Sized + ImageDecoder> ImageDecoder for Box<T> {
721    fn dimensions(&self) -> (u32, u32) {
722        (**self).dimensions()
723    }
724    fn color_type(&self) -> ColorType {
725        (**self).color_type()
726    }
727    fn original_color_type(&self) -> ExtendedColorType {
728        (**self).original_color_type()
729    }
730    fn icc_profile(&mut self) -> ImageResult<Option<Vec<u8>>> {
731        (**self).icc_profile()
732    }
733    fn exif_metadata(&mut self) -> ImageResult<Option<Vec<u8>>> {
734        (**self).exif_metadata()
735    }
736    fn total_bytes(&self) -> u64 {
737        (**self).total_bytes()
738    }
739    fn read_image(self, buf: &mut [u8]) -> ImageResult<()>
740    where
741        Self: Sized,
742    {
743        T::read_image_boxed(self, buf)
744    }
745    fn read_image_boxed(self: Box<Self>, buf: &mut [u8]) -> ImageResult<()> {
746        T::read_image_boxed(*self, buf)
747    }
748    fn set_limits(&mut self, limits: crate::Limits) -> ImageResult<()> {
749        (**self).set_limits(limits)
750    }
751}
752
753/// Specialized image decoding not be supported by all formats
754pub trait ImageDecoderRect: ImageDecoder {
755    /// Decode a rectangular section of the image.
756    ///
757    /// This function takes a slice of bytes and writes the pixel data of the image into it.
758    /// The rectangle is specified by the x and y coordinates of the top left corner, the width
759    /// and height of the rectangle, and the row pitch of the buffer. The row pitch is the number
760    /// of bytes between the start of one row and the start of the next row. The row pitch must be
761    /// at least as large as the width of the rectangle in bytes.
762    fn read_rect(
763        &mut self,
764        x: u32,
765        y: u32,
766        width: u32,
767        height: u32,
768        buf: &mut [u8],
769        row_pitch: usize,
770    ) -> ImageResult<()>;
771}
772
773/// `AnimationDecoder` trait
774pub trait AnimationDecoder<'a> {
775    /// Consume the decoder producing a series of frames.
776    fn into_frames(self) -> Frames<'a>;
777}
778
779/// The trait all encoders implement
780pub trait ImageEncoder {
781    /// Writes all the bytes in an image to the encoder.
782    ///
783    /// This function takes a slice of bytes of the pixel data of the image
784    /// and encodes them. Unlike particular format encoders inherent impl encode
785    /// methods where endianness is not specified, here image data bytes should
786    /// always be in native endian. The implementor will reorder the endianness
787    /// as necessary for the target encoding format.
788    ///
789    /// See also `ImageDecoder::read_image` which reads byte buffers into
790    /// native endian.
791    ///
792    /// # Panics
793    ///
794    /// Panics if `width * height * color_type.bytes_per_pixel() != buf.len()`.
795    fn write_image(
796        self,
797        buf: &[u8],
798        width: u32,
799        height: u32,
800        color_type: ExtendedColorType,
801    ) -> ImageResult<()>;
802
803    /// Set the ICC profile to use for the image.
804    ///
805    /// This function is a no-op for formats that don't support ICC profiles.
806    /// For formats that do support ICC profiles, the profile will be embedded
807    /// in the image when it is saved.
808    ///
809    /// # Errors
810    ///
811    /// This function returns an error if the format does not support ICC profiles.
812    fn set_icc_profile(&mut self, icc_profile: Vec<u8>) -> Result<(), UnsupportedError> {
813        let _ = icc_profile;
814        Err(UnsupportedError::from_format_and_kind(
815            ImageFormatHint::Unknown,
816            UnsupportedErrorKind::GenericFeature(
817                "ICC profiles are not supported for this format".into(),
818            ),
819        ))
820    }
821}
822
823/// Immutable pixel iterator
824#[derive(Debug)]
825pub struct Pixels<'a, I: ?Sized + 'a> {
826    image: &'a I,
827    x: u32,
828    y: u32,
829    width: u32,
830    height: u32,
831}
832
833impl<I: GenericImageView> Iterator for Pixels<'_, I> {
834    type Item = (u32, u32, I::Pixel);
835
836    fn next(&mut self) -> Option<(u32, u32, I::Pixel)> {
837        if self.x >= self.width {
838            self.x = 0;
839            self.y += 1;
840        }
841
842        if self.y >= self.height {
843            None
844        } else {
845            let pixel = self.image.get_pixel(self.x, self.y);
846            let p = (self.x, self.y, pixel);
847
848            self.x += 1;
849
850            Some(p)
851        }
852    }
853}
854
855impl<I: ?Sized> Clone for Pixels<'_, I> {
856    fn clone(&self) -> Self {
857        Pixels { ..*self }
858    }
859}
860
861/// Trait to inspect an image.
862///
863/// ```
864/// use image::{GenericImageView, Rgb, RgbImage};
865///
866/// let buffer = RgbImage::new(10, 10);
867/// let image: &dyn GenericImageView<Pixel=Rgb<u8>> = &buffer;
868/// ```
869pub trait GenericImageView {
870    /// The type of pixel.
871    type Pixel: Pixel;
872
873    /// The width and height of this image.
874    fn dimensions(&self) -> (u32, u32);
875
876    /// The width of this image.
877    fn width(&self) -> u32 {
878        let (w, _) = self.dimensions();
879        w
880    }
881
882    /// The height of this image.
883    fn height(&self) -> u32 {
884        let (_, h) = self.dimensions();
885        h
886    }
887
888    /// Returns true if this x, y coordinate is contained inside the image.
889    fn in_bounds(&self, x: u32, y: u32) -> bool {
890        let (width, height) = self.dimensions();
891        x < width && y < height
892    }
893
894    /// Returns the pixel located at (x, y). Indexed from top left.
895    ///
896    /// # Panics
897    ///
898    /// Panics if `(x, y)` is out of bounds.
899    fn get_pixel(&self, x: u32, y: u32) -> Self::Pixel;
900
901    /// Returns the pixel located at (x, y). Indexed from top left.
902    ///
903    /// This function can be implemented in a way that ignores bounds checking.
904    /// # Safety
905    ///
906    /// The coordinates must be [`in_bounds`] of the image.
907    ///
908    /// [`in_bounds`]: #method.in_bounds
909    unsafe fn unsafe_get_pixel(&self, x: u32, y: u32) -> Self::Pixel {
910        self.get_pixel(x, y)
911    }
912
913    /// Returns an Iterator over the pixels of this image.
914    /// The iterator yields the coordinates of each pixel
915    /// along with their value
916    fn pixels(&self) -> Pixels<Self>
917    where
918        Self: Sized,
919    {
920        let (width, height) = self.dimensions();
921
922        Pixels {
923            image: self,
924            x: 0,
925            y: 0,
926            width,
927            height,
928        }
929    }
930
931    /// Returns a subimage that is an immutable view into this image.
932    /// You can use [`GenericImage::sub_image`] if you need a mutable view instead.
933    /// The coordinates set the position of the top left corner of the view.
934    fn view(&self, x: u32, y: u32, width: u32, height: u32) -> SubImage<&Self>
935    where
936        Self: Sized,
937    {
938        assert!(u64::from(x) + u64::from(width) <= u64::from(self.width()));
939        assert!(u64::from(y) + u64::from(height) <= u64::from(self.height()));
940        SubImage::new(self, x, y, width, height)
941    }
942}
943
944/// A trait for manipulating images.
945pub trait GenericImage: GenericImageView {
946    /// Gets a reference to the mutable pixel at location `(x, y)`. Indexed from top left.
947    ///
948    /// # Panics
949    ///
950    /// Panics if `(x, y)` is out of bounds.
951    ///
952    /// Panics for dynamic images (this method is deprecated and will be removed).
953    ///
954    /// ## Known issues
955    ///
956    /// This requires the buffer to contain a unique set of continuous channels in the exact order
957    /// and byte representation that the pixel type requires. This is somewhat restrictive.
958    ///
959    /// TODO: Maybe use some kind of entry API? this would allow pixel type conversion on the fly
960    /// while still doing only one array lookup:
961    ///
962    /// ```ignore
963    /// let px = image.pixel_entry_at(x,y);
964    /// px.set_from_rgba(rgba)
965    /// ```
966    #[deprecated(since = "0.24.0", note = "Use `get_pixel` and `put_pixel` instead.")]
967    fn get_pixel_mut(&mut self, x: u32, y: u32) -> &mut Self::Pixel;
968
969    /// Put a pixel at location (x, y). Indexed from top left.
970    ///
971    /// # Panics
972    ///
973    /// Panics if `(x, y)` is out of bounds.
974    fn put_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel);
975
976    /// Puts a pixel at location (x, y). Indexed from top left.
977    ///
978    /// This function can be implemented in a way that ignores bounds checking.
979    /// # Safety
980    ///
981    /// The coordinates must be [`in_bounds`] of the image.
982    ///
983    /// [`in_bounds`]: traits.GenericImageView.html#method.in_bounds
984    unsafe fn unsafe_put_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel) {
985        self.put_pixel(x, y, pixel);
986    }
987
988    /// Put a pixel at location (x, y), taking into account alpha channels
989    #[deprecated(
990        since = "0.24.0",
991        note = "Use iterator `pixels_mut` to blend the pixels directly"
992    )]
993    fn blend_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel);
994
995    /// Copies all of the pixels from another image into this image.
996    ///
997    /// The other image is copied with the top-left corner of the
998    /// other image placed at (x, y).
999    ///
1000    /// In order to copy only a piece of the other image, use [`GenericImageView::view`].
1001    ///
1002    /// You can use [`FlatSamples`] to source pixels from an arbitrary regular raster of channel
1003    /// values, for example from a foreign interface or a fixed image.
1004    ///
1005    /// # Returns
1006    /// Returns an error if the image is too large to be copied at the given position
1007    ///
1008    /// [`GenericImageView::view`]: trait.GenericImageView.html#method.view
1009    /// [`FlatSamples`]: flat/struct.FlatSamples.html
1010    fn copy_from<O>(&mut self, other: &O, x: u32, y: u32) -> ImageResult<()>
1011    where
1012        O: GenericImageView<Pixel = Self::Pixel>,
1013    {
1014        // Do bounds checking here so we can use the non-bounds-checking
1015        // functions to copy pixels.
1016        if self.width() < other.width() + x || self.height() < other.height() + y {
1017            return Err(ImageError::Parameter(ParameterError::from_kind(
1018                ParameterErrorKind::DimensionMismatch,
1019            )));
1020        }
1021
1022        for k in 0..other.height() {
1023            for i in 0..other.width() {
1024                let p = other.get_pixel(i, k);
1025                self.put_pixel(i + x, k + y, p);
1026            }
1027        }
1028        Ok(())
1029    }
1030
1031    /// Copies all of the pixels from one part of this image to another part of this image.
1032    ///
1033    /// The destination rectangle of the copy is specified with the top-left corner placed at (x, y).
1034    ///
1035    /// # Returns
1036    /// `true` if the copy was successful, `false` if the image could not
1037    /// be copied due to size constraints.
1038    fn copy_within(&mut self, source: Rect, x: u32, y: u32) -> bool {
1039        let Rect {
1040            x: sx,
1041            y: sy,
1042            width,
1043            height,
1044        } = source;
1045        let dx = x;
1046        let dy = y;
1047        assert!(sx < self.width() && dx < self.width());
1048        assert!(sy < self.height() && dy < self.height());
1049        if self.width() - dx.max(sx) < width || self.height() - dy.max(sy) < height {
1050            return false;
1051        }
1052        // since `.rev()` creates a new dype we would either have to go with dynamic dispatch for the ranges
1053        // or have quite a lot of code bloat. A macro gives us static dispatch with less visible bloat.
1054        macro_rules! copy_within_impl_ {
1055            ($xiter:expr, $yiter:expr) => {
1056                for y in $yiter {
1057                    let sy = sy + y;
1058                    let dy = dy + y;
1059                    for x in $xiter {
1060                        let sx = sx + x;
1061                        let dx = dx + x;
1062                        let pixel = self.get_pixel(sx, sy);
1063                        self.put_pixel(dx, dy, pixel);
1064                    }
1065                }
1066            };
1067        }
1068        // check how target and source rectangles relate to each other so we dont overwrite data before we copied it.
1069        match (sx < dx, sy < dy) {
1070            (true, true) => copy_within_impl_!((0..width).rev(), (0..height).rev()),
1071            (true, false) => copy_within_impl_!((0..width).rev(), 0..height),
1072            (false, true) => copy_within_impl_!(0..width, (0..height).rev()),
1073            (false, false) => copy_within_impl_!(0..width, 0..height),
1074        }
1075        true
1076    }
1077
1078    /// Returns a mutable subimage that is a view into this image.
1079    /// If you want an immutable subimage instead, use [`GenericImageView::view`]
1080    /// The coordinates set the position of the top left corner of the `SubImage`.
1081    fn sub_image(&mut self, x: u32, y: u32, width: u32, height: u32) -> SubImage<&mut Self>
1082    where
1083        Self: Sized,
1084    {
1085        assert!(u64::from(x) + u64::from(width) <= u64::from(self.width()));
1086        assert!(u64::from(y) + u64::from(height) <= u64::from(self.height()));
1087        SubImage::new(self, x, y, width, height)
1088    }
1089}
1090
1091/// A View into another image
1092///
1093/// Instances of this struct can be created using:
1094///   - [`GenericImage::sub_image`] to create a mutable view,
1095///   - [`GenericImageView::view`] to create an immutable view,
1096///   - [`SubImage::new`] to instantiate the struct directly.
1097///
1098/// Note that this does _not_ implement `GenericImage`, but it dereferences to one which allows you
1099/// to use it as if it did. See [Design Considerations](#Design-Considerations) below for details.
1100///
1101/// # Design Considerations
1102///
1103/// For reasons relating to coherence, this is not itself a `GenericImage` or a `GenericImageView`.
1104/// In short, we want to reserve the ability of adding traits implemented for _all_ generic images
1105/// but in a different manner for `SubImage`. This may be required to ensure that stacking
1106/// sub-images comes at no double indirect cost.
1107///
1108/// If, ultimately, this is not needed then a directly implementation of `GenericImage` can and
1109/// will get added. This inconvenience may alternatively get resolved if Rust allows some forms of
1110/// specialization, which might make this trick unnecessary and thus also allows for a direct
1111/// implementation.
1112#[derive(Copy, Clone)]
1113pub struct SubImage<I> {
1114    inner: SubImageInner<I>,
1115}
1116
1117/// The inner type of `SubImage` that implements `GenericImage{,View}`.
1118///
1119/// This type is _nominally_ `pub` but it is not exported from the crate. It should be regarded as
1120/// an existential type in any case.
1121#[derive(Copy, Clone)]
1122pub struct SubImageInner<I> {
1123    image: I,
1124    xoffset: u32,
1125    yoffset: u32,
1126    xstride: u32,
1127    ystride: u32,
1128}
1129
1130/// Alias to access Pixel behind a reference
1131type DerefPixel<I> = <<I as Deref>::Target as GenericImageView>::Pixel;
1132
1133/// Alias to access Subpixel behind a reference
1134type DerefSubpixel<I> = <DerefPixel<I> as Pixel>::Subpixel;
1135
1136impl<I> SubImage<I> {
1137    /// Construct a new subimage
1138    /// The coordinates set the position of the top left corner of the `SubImage`.
1139    pub fn new(image: I, x: u32, y: u32, width: u32, height: u32) -> SubImage<I> {
1140        SubImage {
1141            inner: SubImageInner {
1142                image,
1143                xoffset: x,
1144                yoffset: y,
1145                xstride: width,
1146                ystride: height,
1147            },
1148        }
1149    }
1150
1151    /// Change the coordinates of this subimage.
1152    pub fn change_bounds(&mut self, x: u32, y: u32, width: u32, height: u32) {
1153        self.inner.xoffset = x;
1154        self.inner.yoffset = y;
1155        self.inner.xstride = width;
1156        self.inner.ystride = height;
1157    }
1158
1159    /// The offsets of this subimage relative to the underlying image.
1160    pub fn offsets(&self) -> (u32, u32) {
1161        (self.inner.xoffset, self.inner.yoffset)
1162    }
1163
1164    /// Convert this subimage to an `ImageBuffer`
1165    pub fn to_image(&self) -> ImageBuffer<DerefPixel<I>, Vec<DerefSubpixel<I>>>
1166    where
1167        I: Deref,
1168        I::Target: GenericImageView + 'static,
1169    {
1170        let mut out = ImageBuffer::new(self.inner.xstride, self.inner.ystride);
1171        let borrowed = &*self.inner.image;
1172
1173        for y in 0..self.inner.ystride {
1174            for x in 0..self.inner.xstride {
1175                let p = borrowed.get_pixel(x + self.inner.xoffset, y + self.inner.yoffset);
1176                out.put_pixel(x, y, p);
1177            }
1178        }
1179
1180        out
1181    }
1182}
1183
1184/// Methods for readable images.
1185impl<I> SubImage<I>
1186where
1187    I: Deref,
1188    I::Target: GenericImageView,
1189{
1190    /// Create a sub-view of the image.
1191    ///
1192    /// The coordinates given are relative to the current view on the underlying image.
1193    ///
1194    /// Note that this method is preferred to the one from `GenericImageView`. This is accessible
1195    /// with the explicit method call syntax but it should rarely be needed due to causing an
1196    /// extra level of indirection.
1197    ///
1198    /// ```
1199    /// use image::{GenericImageView, RgbImage, SubImage};
1200    /// let buffer = RgbImage::new(10, 10);
1201    ///
1202    /// let subimage: SubImage<&RgbImage> = buffer.view(0, 0, 10, 10);
1203    /// let subview: SubImage<&RgbImage> = subimage.view(0, 0, 10, 10);
1204    ///
1205    /// // Less efficient and NOT &RgbImage
1206    /// let _: SubImage<&_> = GenericImageView::view(&*subimage, 0, 0, 10, 10);
1207    /// ```
1208    pub fn view(&self, x: u32, y: u32, width: u32, height: u32) -> SubImage<&I::Target> {
1209        use crate::GenericImageView as _;
1210        assert!(u64::from(x) + u64::from(width) <= u64::from(self.inner.width()));
1211        assert!(u64::from(y) + u64::from(height) <= u64::from(self.inner.height()));
1212        let x = self.inner.xoffset.saturating_add(x);
1213        let y = self.inner.yoffset.saturating_add(y);
1214        SubImage::new(&*self.inner.image, x, y, width, height)
1215    }
1216
1217    /// Get a reference to the underlying image.
1218    pub fn inner(&self) -> &I::Target {
1219        &self.inner.image
1220    }
1221}
1222
1223impl<I> SubImage<I>
1224where
1225    I: DerefMut,
1226    I::Target: GenericImage,
1227{
1228    /// Create a mutable sub-view of the image.
1229    ///
1230    /// The coordinates given are relative to the current view on the underlying image.
1231    pub fn sub_image(
1232        &mut self,
1233        x: u32,
1234        y: u32,
1235        width: u32,
1236        height: u32,
1237    ) -> SubImage<&mut I::Target> {
1238        assert!(u64::from(x) + u64::from(width) <= u64::from(self.inner.width()));
1239        assert!(u64::from(y) + u64::from(height) <= u64::from(self.inner.height()));
1240        let x = self.inner.xoffset.saturating_add(x);
1241        let y = self.inner.yoffset.saturating_add(y);
1242        SubImage::new(&mut *self.inner.image, x, y, width, height)
1243    }
1244
1245    /// Get a mutable reference to the underlying image.
1246    pub fn inner_mut(&mut self) -> &mut I::Target {
1247        &mut self.inner.image
1248    }
1249}
1250
1251impl<I> Deref for SubImage<I>
1252where
1253    I: Deref,
1254{
1255    type Target = SubImageInner<I>;
1256    fn deref(&self) -> &Self::Target {
1257        &self.inner
1258    }
1259}
1260
1261impl<I> DerefMut for SubImage<I>
1262where
1263    I: DerefMut,
1264{
1265    fn deref_mut(&mut self) -> &mut Self::Target {
1266        &mut self.inner
1267    }
1268}
1269
1270#[allow(deprecated)]
1271impl<I> GenericImageView for SubImageInner<I>
1272where
1273    I: Deref,
1274    I::Target: GenericImageView,
1275{
1276    type Pixel = DerefPixel<I>;
1277
1278    fn dimensions(&self) -> (u32, u32) {
1279        (self.xstride, self.ystride)
1280    }
1281
1282    fn get_pixel(&self, x: u32, y: u32) -> Self::Pixel {
1283        self.image.get_pixel(x + self.xoffset, y + self.yoffset)
1284    }
1285}
1286
1287#[allow(deprecated)]
1288impl<I> GenericImage for SubImageInner<I>
1289where
1290    I: DerefMut,
1291    I::Target: GenericImage + Sized,
1292{
1293    fn get_pixel_mut(&mut self, x: u32, y: u32) -> &mut Self::Pixel {
1294        self.image.get_pixel_mut(x + self.xoffset, y + self.yoffset)
1295    }
1296
1297    fn put_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel) {
1298        self.image
1299            .put_pixel(x + self.xoffset, y + self.yoffset, pixel);
1300    }
1301
1302    /// DEPRECATED: This method will be removed. Blend the pixel directly instead.
1303    fn blend_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel) {
1304        self.image
1305            .blend_pixel(x + self.xoffset, y + self.yoffset, pixel);
1306    }
1307}
1308
1309#[cfg(test)]
1310mod tests {
1311    use std::collections::HashSet;
1312    use std::io;
1313    use std::path::Path;
1314
1315    use super::{
1316        load_rect, ColorType, GenericImage, GenericImageView, ImageDecoder, ImageFormat,
1317        ImageResult,
1318    };
1319    use crate::color::Rgba;
1320    use crate::math::Rect;
1321    use crate::{GrayImage, ImageBuffer};
1322
1323    #[test]
1324    #[allow(deprecated)]
1325    /// Test that alpha blending works as expected
1326    fn test_image_alpha_blending() {
1327        let mut target = ImageBuffer::new(1, 1);
1328        target.put_pixel(0, 0, Rgba([255u8, 0, 0, 255]));
1329        assert!(*target.get_pixel(0, 0) == Rgba([255, 0, 0, 255]));
1330        target.blend_pixel(0, 0, Rgba([0, 255, 0, 255]));
1331        assert!(*target.get_pixel(0, 0) == Rgba([0, 255, 0, 255]));
1332
1333        // Blending an alpha channel onto a solid background
1334        target.blend_pixel(0, 0, Rgba([255, 0, 0, 127]));
1335        assert!(*target.get_pixel(0, 0) == Rgba([127, 127, 0, 255]));
1336
1337        // Blending two alpha channels
1338        target.put_pixel(0, 0, Rgba([0, 255, 0, 127]));
1339        target.blend_pixel(0, 0, Rgba([255, 0, 0, 127]));
1340        assert!(*target.get_pixel(0, 0) == Rgba([169, 85, 0, 190]));
1341    }
1342
1343    #[test]
1344    fn test_in_bounds() {
1345        let mut target = ImageBuffer::new(2, 2);
1346        target.put_pixel(0, 0, Rgba([255u8, 0, 0, 255]));
1347
1348        assert!(target.in_bounds(0, 0));
1349        assert!(target.in_bounds(1, 0));
1350        assert!(target.in_bounds(0, 1));
1351        assert!(target.in_bounds(1, 1));
1352
1353        assert!(!target.in_bounds(2, 0));
1354        assert!(!target.in_bounds(0, 2));
1355        assert!(!target.in_bounds(2, 2));
1356    }
1357
1358    #[test]
1359    fn test_can_subimage_clone_nonmut() {
1360        let mut source = ImageBuffer::new(3, 3);
1361        source.put_pixel(1, 1, Rgba([255u8, 0, 0, 255]));
1362
1363        // A non-mutable copy of the source image
1364        let source = source.clone();
1365
1366        // Clone a view into non-mutable to a separate buffer
1367        let cloned = source.view(1, 1, 1, 1).to_image();
1368
1369        assert!(cloned.get_pixel(0, 0) == source.get_pixel(1, 1));
1370    }
1371
1372    #[test]
1373    fn test_can_nest_views() {
1374        let mut source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255]));
1375
1376        {
1377            let mut sub1 = source.sub_image(0, 0, 2, 2);
1378            let mut sub2 = sub1.sub_image(1, 1, 1, 1);
1379            sub2.put_pixel(0, 0, Rgba([0, 0, 0, 0]));
1380        }
1381
1382        assert_eq!(*source.get_pixel(1, 1), Rgba([0, 0, 0, 0]));
1383
1384        let view1 = source.view(0, 0, 2, 2);
1385        assert_eq!(*source.get_pixel(1, 1), view1.get_pixel(1, 1));
1386
1387        let view2 = view1.view(1, 1, 1, 1);
1388        assert_eq!(*source.get_pixel(1, 1), view2.get_pixel(0, 0));
1389    }
1390
1391    #[test]
1392    #[should_panic]
1393    fn test_view_out_of_bounds() {
1394        let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255]));
1395        source.view(1, 1, 3, 3);
1396    }
1397
1398    #[test]
1399    #[should_panic]
1400    fn test_view_coordinates_out_of_bounds() {
1401        let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255]));
1402        source.view(3, 3, 3, 3);
1403    }
1404
1405    #[test]
1406    #[should_panic]
1407    fn test_view_width_out_of_bounds() {
1408        let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255]));
1409        source.view(1, 1, 3, 2);
1410    }
1411
1412    #[test]
1413    #[should_panic]
1414    fn test_view_height_out_of_bounds() {
1415        let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255]));
1416        source.view(1, 1, 2, 3);
1417    }
1418
1419    #[test]
1420    #[should_panic]
1421    fn test_view_x_out_of_bounds() {
1422        let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255]));
1423        source.view(3, 1, 3, 3);
1424    }
1425
1426    #[test]
1427    #[should_panic]
1428    fn test_view_y_out_of_bounds() {
1429        let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255]));
1430        source.view(1, 3, 3, 3);
1431    }
1432
1433    #[test]
1434    fn test_view_in_bounds() {
1435        let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255]));
1436        source.view(0, 0, 3, 3);
1437        source.view(1, 1, 2, 2);
1438        source.view(2, 2, 0, 0);
1439    }
1440
1441    #[test]
1442    fn test_copy_sub_image() {
1443        let source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255]));
1444        let view = source.view(0, 0, 3, 3);
1445        let _view2 = view;
1446        view.to_image();
1447    }
1448
1449    #[test]
1450    fn test_load_rect() {
1451        struct MockDecoder {
1452            scanline_number: u64,
1453            scanline_bytes: u64,
1454        }
1455        impl ImageDecoder for MockDecoder {
1456            fn dimensions(&self) -> (u32, u32) {
1457                (5, 5)
1458            }
1459            fn color_type(&self) -> ColorType {
1460                ColorType::L8
1461            }
1462            fn read_image(self, _buf: &mut [u8]) -> ImageResult<()> {
1463                unimplemented!()
1464            }
1465            fn read_image_boxed(self: Box<Self>, buf: &mut [u8]) -> ImageResult<()> {
1466                (*self).read_image(buf)
1467            }
1468        }
1469
1470        const DATA: [u8; 25] = [
1471            0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
1472            24,
1473        ];
1474
1475        fn seek_scanline(m: &mut MockDecoder, n: u64) -> io::Result<()> {
1476            m.scanline_number = n;
1477            Ok(())
1478        }
1479        fn read_scanline(m: &mut MockDecoder, buf: &mut [u8]) -> io::Result<()> {
1480            let bytes_read = m.scanline_number * m.scanline_bytes;
1481            if bytes_read >= 25 {
1482                return Ok(());
1483            }
1484
1485            let len = m.scanline_bytes.min(25 - bytes_read);
1486            buf[..(len as usize)].copy_from_slice(&DATA[(bytes_read as usize)..][..(len as usize)]);
1487            m.scanline_number += 1;
1488            Ok(())
1489        }
1490
1491        for scanline_bytes in 1..30 {
1492            let mut output = [0u8; 26];
1493
1494            load_rect(
1495                0,
1496                0,
1497                5,
1498                5,
1499                &mut output,
1500                5,
1501                &mut MockDecoder {
1502                    scanline_number: 0,
1503                    scanline_bytes,
1504                },
1505                scanline_bytes as usize,
1506                seek_scanline,
1507                read_scanline,
1508            )
1509            .unwrap();
1510            assert_eq!(output[0..25], DATA);
1511            assert_eq!(output[25], 0);
1512
1513            output = [0u8; 26];
1514            load_rect(
1515                3,
1516                2,
1517                1,
1518                1,
1519                &mut output,
1520                1,
1521                &mut MockDecoder {
1522                    scanline_number: 0,
1523                    scanline_bytes,
1524                },
1525                scanline_bytes as usize,
1526                seek_scanline,
1527                read_scanline,
1528            )
1529            .unwrap();
1530            assert_eq!(output[0..2], [13, 0]);
1531
1532            output = [0u8; 26];
1533            load_rect(
1534                3,
1535                2,
1536                2,
1537                2,
1538                &mut output,
1539                2,
1540                &mut MockDecoder {
1541                    scanline_number: 0,
1542                    scanline_bytes,
1543                },
1544                scanline_bytes as usize,
1545                seek_scanline,
1546                read_scanline,
1547            )
1548            .unwrap();
1549            assert_eq!(output[0..5], [13, 14, 18, 19, 0]);
1550
1551            output = [0u8; 26];
1552            load_rect(
1553                1,
1554                1,
1555                2,
1556                4,
1557                &mut output,
1558                2,
1559                &mut MockDecoder {
1560                    scanline_number: 0,
1561                    scanline_bytes,
1562                },
1563                scanline_bytes as usize,
1564                seek_scanline,
1565                read_scanline,
1566            )
1567            .unwrap();
1568            assert_eq!(output[0..9], [6, 7, 11, 12, 16, 17, 21, 22, 0]);
1569        }
1570    }
1571
1572    #[test]
1573    fn test_load_rect_single_scanline() {
1574        const DATA: [u8; 25] = [
1575            0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
1576            24,
1577        ];
1578
1579        struct MockDecoder;
1580        impl ImageDecoder for MockDecoder {
1581            fn dimensions(&self) -> (u32, u32) {
1582                (5, 5)
1583            }
1584            fn color_type(&self) -> ColorType {
1585                ColorType::L8
1586            }
1587            fn read_image(self, _buf: &mut [u8]) -> ImageResult<()> {
1588                unimplemented!()
1589            }
1590            fn read_image_boxed(self: Box<Self>, buf: &mut [u8]) -> ImageResult<()> {
1591                (*self).read_image(buf)
1592            }
1593        }
1594
1595        // Ensure that seek scanline is called only once.
1596        let mut seeks = 0;
1597        let seek_scanline = |_d: &mut MockDecoder, n: u64| -> io::Result<()> {
1598            seeks += 1;
1599            assert_eq!(n, 0);
1600            assert_eq!(seeks, 1);
1601            Ok(())
1602        };
1603
1604        fn read_scanline(_m: &mut MockDecoder, buf: &mut [u8]) -> io::Result<()> {
1605            buf.copy_from_slice(&DATA);
1606            Ok(())
1607        }
1608
1609        let mut output = [0; 26];
1610        load_rect(
1611            1,
1612            1,
1613            2,
1614            4,
1615            &mut output,
1616            2,
1617            &mut MockDecoder,
1618            DATA.len(),
1619            seek_scanline,
1620            read_scanline,
1621        )
1622        .unwrap();
1623        assert_eq!(output[0..9], [6, 7, 11, 12, 16, 17, 21, 22, 0]);
1624    }
1625
1626    #[test]
1627    fn test_image_format_from_path() {
1628        fn from_path(s: &str) -> ImageResult<ImageFormat> {
1629            ImageFormat::from_path(Path::new(s))
1630        }
1631        assert_eq!(from_path("./a.jpg").unwrap(), ImageFormat::Jpeg);
1632        assert_eq!(from_path("./a.jpeg").unwrap(), ImageFormat::Jpeg);
1633        assert_eq!(from_path("./a.JPEG").unwrap(), ImageFormat::Jpeg);
1634        assert_eq!(from_path("./a.pNg").unwrap(), ImageFormat::Png);
1635        assert_eq!(from_path("./a.gif").unwrap(), ImageFormat::Gif);
1636        assert_eq!(from_path("./a.webp").unwrap(), ImageFormat::WebP);
1637        assert_eq!(from_path("./a.tiFF").unwrap(), ImageFormat::Tiff);
1638        assert_eq!(from_path("./a.tif").unwrap(), ImageFormat::Tiff);
1639        assert_eq!(from_path("./a.tga").unwrap(), ImageFormat::Tga);
1640        assert_eq!(from_path("./a.dds").unwrap(), ImageFormat::Dds);
1641        assert_eq!(from_path("./a.bmp").unwrap(), ImageFormat::Bmp);
1642        assert_eq!(from_path("./a.Ico").unwrap(), ImageFormat::Ico);
1643        assert_eq!(from_path("./a.hdr").unwrap(), ImageFormat::Hdr);
1644        assert_eq!(from_path("./a.exr").unwrap(), ImageFormat::OpenExr);
1645        assert_eq!(from_path("./a.pbm").unwrap(), ImageFormat::Pnm);
1646        assert_eq!(from_path("./a.pAM").unwrap(), ImageFormat::Pnm);
1647        assert_eq!(from_path("./a.Ppm").unwrap(), ImageFormat::Pnm);
1648        assert_eq!(from_path("./a.pgm").unwrap(), ImageFormat::Pnm);
1649        assert_eq!(from_path("./a.AViF").unwrap(), ImageFormat::Avif);
1650        assert!(from_path("./a.txt").is_err());
1651        assert!(from_path("./a").is_err());
1652    }
1653
1654    #[test]
1655    fn test_generic_image_copy_within_oob() {
1656        let mut image: GrayImage = ImageBuffer::from_raw(4, 4, vec![0u8; 16]).unwrap();
1657        assert!(!image.sub_image(0, 0, 4, 4).copy_within(
1658            Rect {
1659                x: 0,
1660                y: 0,
1661                width: 5,
1662                height: 4
1663            },
1664            0,
1665            0
1666        ));
1667        assert!(!image.sub_image(0, 0, 4, 4).copy_within(
1668            Rect {
1669                x: 0,
1670                y: 0,
1671                width: 4,
1672                height: 5
1673            },
1674            0,
1675            0
1676        ));
1677        assert!(!image.sub_image(0, 0, 4, 4).copy_within(
1678            Rect {
1679                x: 1,
1680                y: 0,
1681                width: 4,
1682                height: 4
1683            },
1684            0,
1685            0
1686        ));
1687        assert!(!image.sub_image(0, 0, 4, 4).copy_within(
1688            Rect {
1689                x: 0,
1690                y: 0,
1691                width: 4,
1692                height: 4
1693            },
1694            1,
1695            0
1696        ));
1697        assert!(!image.sub_image(0, 0, 4, 4).copy_within(
1698            Rect {
1699                x: 0,
1700                y: 1,
1701                width: 4,
1702                height: 4
1703            },
1704            0,
1705            0
1706        ));
1707        assert!(!image.sub_image(0, 0, 4, 4).copy_within(
1708            Rect {
1709                x: 0,
1710                y: 0,
1711                width: 4,
1712                height: 4
1713            },
1714            0,
1715            1
1716        ));
1717        assert!(!image.sub_image(0, 0, 4, 4).copy_within(
1718            Rect {
1719                x: 1,
1720                y: 1,
1721                width: 4,
1722                height: 4
1723            },
1724            0,
1725            0
1726        ));
1727    }
1728
1729    #[test]
1730    fn test_generic_image_copy_within_tl() {
1731        let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
1732        let expected = [0, 1, 2, 3, 4, 0, 1, 2, 8, 4, 5, 6, 12, 8, 9, 10];
1733        let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap();
1734        assert!(image.sub_image(0, 0, 4, 4).copy_within(
1735            Rect {
1736                x: 0,
1737                y: 0,
1738                width: 3,
1739                height: 3
1740            },
1741            1,
1742            1
1743        ));
1744        assert_eq!(&image.into_raw(), &expected);
1745    }
1746
1747    #[test]
1748    fn test_generic_image_copy_within_tr() {
1749        let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
1750        let expected = [0, 1, 2, 3, 1, 2, 3, 7, 5, 6, 7, 11, 9, 10, 11, 15];
1751        let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap();
1752        assert!(image.sub_image(0, 0, 4, 4).copy_within(
1753            Rect {
1754                x: 1,
1755                y: 0,
1756                width: 3,
1757                height: 3
1758            },
1759            0,
1760            1
1761        ));
1762        assert_eq!(&image.into_raw(), &expected);
1763    }
1764
1765    #[test]
1766    fn test_generic_image_copy_within_bl() {
1767        let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
1768        let expected = [0, 4, 5, 6, 4, 8, 9, 10, 8, 12, 13, 14, 12, 13, 14, 15];
1769        let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap();
1770        assert!(image.sub_image(0, 0, 4, 4).copy_within(
1771            Rect {
1772                x: 0,
1773                y: 1,
1774                width: 3,
1775                height: 3
1776            },
1777            1,
1778            0
1779        ));
1780        assert_eq!(&image.into_raw(), &expected);
1781    }
1782
1783    #[test]
1784    fn test_generic_image_copy_within_br() {
1785        let data = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
1786        let expected = [5, 6, 7, 3, 9, 10, 11, 7, 13, 14, 15, 11, 12, 13, 14, 15];
1787        let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap();
1788        assert!(image.sub_image(0, 0, 4, 4).copy_within(
1789            Rect {
1790                x: 1,
1791                y: 1,
1792                width: 3,
1793                height: 3
1794            },
1795            0,
1796            0
1797        ));
1798        assert_eq!(&image.into_raw(), &expected);
1799    }
1800
1801    #[test]
1802    fn image_formats_are_recognized() {
1803        use ImageFormat::*;
1804        const ALL_FORMATS: &[ImageFormat] = &[
1805            Avif, Png, Jpeg, Gif, WebP, Pnm, Tiff, Tga, Dds, Bmp, Ico, Hdr, Farbfeld, OpenExr,
1806        ];
1807        for &format in ALL_FORMATS {
1808            let mut file = Path::new("file.nothing").to_owned();
1809            for ext in format.extensions_str() {
1810                assert!(file.set_extension(ext));
1811                match ImageFormat::from_path(&file) {
1812                    Err(_) => panic!("Path {} not recognized as {:?}", file.display(), format),
1813                    Ok(result) => assert_eq!(format, result),
1814                }
1815            }
1816        }
1817    }
1818
1819    #[test]
1820    fn total_bytes_overflow() {
1821        struct D;
1822        impl ImageDecoder for D {
1823            fn color_type(&self) -> ColorType {
1824                ColorType::Rgb8
1825            }
1826            fn dimensions(&self) -> (u32, u32) {
1827                (0xffff_ffff, 0xffff_ffff)
1828            }
1829            fn read_image(self, _buf: &mut [u8]) -> ImageResult<()> {
1830                unimplemented!()
1831            }
1832            fn read_image_boxed(self: Box<Self>, buf: &mut [u8]) -> ImageResult<()> {
1833                (*self).read_image(buf)
1834            }
1835        }
1836        assert_eq!(D.total_bytes(), u64::MAX);
1837
1838        let v: ImageResult<Vec<u8>> = super::decoder_to_vec(D);
1839        assert!(v.is_err());
1840    }
1841
1842    #[test]
1843    fn all() {
1844        let all_formats: HashSet<ImageFormat> = ImageFormat::all().collect();
1845        assert!(all_formats.contains(&ImageFormat::Avif));
1846        assert!(all_formats.contains(&ImageFormat::Gif));
1847        assert!(all_formats.contains(&ImageFormat::Bmp));
1848        assert!(all_formats.contains(&ImageFormat::Farbfeld));
1849        assert!(all_formats.contains(&ImageFormat::Jpeg));
1850    }
1851
1852    #[test]
1853    fn reading_enabled() {
1854        assert_eq!(cfg!(feature = "jpeg"), ImageFormat::Jpeg.reading_enabled());
1855        assert_eq!(
1856            cfg!(feature = "ff"),
1857            ImageFormat::Farbfeld.reading_enabled()
1858        );
1859        assert!(!ImageFormat::Dds.reading_enabled());
1860    }
1861
1862    #[test]
1863    fn writing_enabled() {
1864        assert_eq!(cfg!(feature = "jpeg"), ImageFormat::Jpeg.writing_enabled());
1865        assert_eq!(
1866            cfg!(feature = "ff"),
1867            ImageFormat::Farbfeld.writing_enabled()
1868        );
1869        assert!(!ImageFormat::Dds.writing_enabled());
1870    }
1871}