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