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