image/
image.rs

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