/src/image/src/io/decoder.rs
Line | Count | Source |
1 | | use crate::error::ImageResult; |
2 | | use crate::io::DecoderPreparedImage; |
3 | | use crate::metadata::{LoopCount, Orientation}; |
4 | | use crate::Delay; |
5 | | |
6 | | /// The interface for `image` to utilize in reading image files. |
7 | | /// |
8 | | /// Please carefully consider consuming this interface directly and prefer interaction with an |
9 | | /// [`ImageReader`](crate::ImageReader). This is one directional of a protocol between `image` and format decoders. In |
10 | | /// the general case, an implementation can expect calls to be made in the following order: |
11 | | /// |
12 | | /// ```text,bnf |
13 | | /// decoding sequence = configure, { decode image }, "finish", { metadata } |
14 | | /// |
15 | | /// decode image = |
16 | | /// "prepare_image", { metadata | "prepare_image" }, "read_image" |
17 | | /// |
18 | | /// configure = "set_limits" |
19 | | /// |
20 | | /// metadata = "xmp_metadata" | "icc_profile" | "exif_metadata" | "iptc_metadata" |
21 | | /// ``` |
22 | | /// |
23 | | /// Deviation from this order can be treated as an error. Future changes to the protocol may |
24 | | /// introduce additional methods. Decoders will indicate support for sequent variants in their |
25 | | /// [`ImageDecoder::format_attributes`]. |
26 | | /// |
27 | | /// Metadata (`icc_profile`, `exif_metadata`, etc.) is handled different for different image |
28 | | /// containers. The should apply to the previous image. |
29 | | pub trait ImageDecoder { |
30 | | /// Set the decoder to have the specified limits. See [`Limits`] for the different kinds of |
31 | | /// limits that is possible to set. |
32 | | /// |
33 | | /// Note to implementors: make sure you call [`Limits::check_support`] so that |
34 | | /// decoding fails if any unsupported strict limits are set. Also make sure |
35 | | /// you call [`Limits::check_dimensions`] to check the `max_image_width` and |
36 | | /// `max_image_height` limits. |
37 | | /// |
38 | | /// **Note**: By default, _no_ limits are defined. This may be changed in future major version |
39 | | /// increases. |
40 | | /// |
41 | | /// [`Limits`]: crate::Limits |
42 | | /// [`Limits::check_support`]: crate::Limits::check_support |
43 | | /// [`Limits::check_dimensions`]: crate::Limits::check_dimensions |
44 | 17.8k | fn set_limits(&mut self, limits: crate::Limits) -> ImageResult<()> { |
45 | 17.8k | limits.check_support(&crate::LimitSupport::default())?; |
46 | 17.8k | let layout = self.prepare_image()?; |
47 | 17.8k | limits.check_layout_dimensions(&layout)?; |
48 | 17.8k | Ok(()) |
49 | 17.8k | } <image::codecs::qoi::QoiDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::set_limits Line | Count | Source | 44 | 50 | fn set_limits(&mut self, limits: crate::Limits) -> ImageResult<()> { | 45 | 50 | limits.check_support(&crate::LimitSupport::default())?; | 46 | 50 | let layout = self.prepare_image()?; | 47 | 50 | limits.check_layout_dimensions(&layout)?; | 48 | 50 | Ok(()) | 49 | 50 | } |
<image::codecs::webp::decoder::WebPDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::set_limits Line | Count | Source | 44 | 8.83k | fn set_limits(&mut self, limits: crate::Limits) -> ImageResult<()> { | 45 | 8.83k | limits.check_support(&crate::LimitSupport::default())?; | 46 | 8.83k | let layout = self.prepare_image()?; | 47 | 8.83k | limits.check_layout_dimensions(&layout)?; | 48 | 8.83k | Ok(()) | 49 | 8.83k | } |
<image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::set_limits Line | Count | Source | 44 | 1.32k | fn set_limits(&mut self, limits: crate::Limits) -> ImageResult<()> { | 45 | 1.32k | limits.check_support(&crate::LimitSupport::default())?; | 46 | 1.32k | let layout = self.prepare_image()?; | 47 | 1.32k | limits.check_layout_dimensions(&layout)?; | 48 | 1.32k | Ok(()) | 49 | 1.32k | } |
<image::codecs::bmp::decoder::BmpDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::set_limits Line | Count | Source | 44 | 4.64k | fn set_limits(&mut self, limits: crate::Limits) -> ImageResult<()> { | 45 | 4.64k | limits.check_support(&crate::LimitSupport::default())?; | 46 | 4.64k | let layout = self.prepare_image()?; | 47 | 4.64k | limits.check_layout_dimensions(&layout)?; | 48 | 4.64k | Ok(()) | 49 | 4.64k | } |
Unexecuted instantiation: <image::codecs::tga::decoder::TgaDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::set_limits <image::codecs::farbfeld::FarbfeldDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::set_limits Line | Count | Source | 44 | 7 | fn set_limits(&mut self, limits: crate::Limits) -> ImageResult<()> { | 45 | 7 | limits.check_support(&crate::LimitSupport::default())?; | 46 | 7 | let layout = self.prepare_image()?; | 47 | 7 | limits.check_layout_dimensions(&layout)?; | 48 | 7 | Ok(()) | 49 | 7 | } |
<image::codecs::openexr::OpenExrDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::set_limits Line | Count | Source | 44 | 2.86k | fn set_limits(&mut self, limits: crate::Limits) -> ImageResult<()> { | 45 | 2.86k | limits.check_support(&crate::LimitSupport::default())?; | 46 | 2.86k | let layout = self.prepare_image()?; | 47 | 2.86k | limits.check_layout_dimensions(&layout)?; | 48 | 2.86k | Ok(()) | 49 | 2.86k | } |
<image::codecs::openexr::OpenExrDecoder<std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::decoder::ImageDecoder>::set_limits Line | Count | Source | 44 | 98 | fn set_limits(&mut self, limits: crate::Limits) -> ImageResult<()> { | 45 | 98 | limits.check_support(&crate::LimitSupport::default())?; | 46 | 98 | let layout = self.prepare_image()?; | 47 | 98 | limits.check_layout_dimensions(&layout)?; | 48 | 98 | Ok(()) | 49 | 98 | } |
|
50 | | |
51 | | /// Retrieve general information about the decoder / its format itself. |
52 | | /// |
53 | | /// This hints which methods should be called while decoding (a sequence of) images from this |
54 | | /// decoder, e.g. when metadata is available and when it will be overridden. It also provides |
55 | | /// basic capability information about the format. If, in the future, we added different basic |
56 | | /// methods of retrieving color data then the attributes would indicate the preferred and/or |
57 | | /// possible choices. |
58 | 12.6k | fn format_attributes(&self) -> FormatAttributes { |
59 | 12.6k | FormatAttributes::default() |
60 | 12.6k | } <image::codecs::hdr::decoder::HdrDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::format_attributes Line | Count | Source | 58 | 2.21k | fn format_attributes(&self) -> FormatAttributes { | 59 | 2.21k | FormatAttributes::default() | 60 | 2.21k | } |
<image::codecs::qoi::QoiDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::format_attributes Line | Count | Source | 58 | 50 | fn format_attributes(&self) -> FormatAttributes { | 59 | 50 | FormatAttributes::default() | 60 | 50 | } |
<image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::format_attributes Line | Count | Source | 58 | 2.45k | fn format_attributes(&self) -> FormatAttributes { | 59 | 2.45k | FormatAttributes::default() | 60 | 2.45k | } |
<image::codecs::bmp::decoder::BmpDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::format_attributes Line | Count | Source | 58 | 5.94k | fn format_attributes(&self) -> FormatAttributes { | 59 | 5.94k | FormatAttributes::default() | 60 | 5.94k | } |
Unexecuted instantiation: <image::codecs::tga::decoder::TgaDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::format_attributes <image::codecs::farbfeld::FarbfeldDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::format_attributes Line | Count | Source | 58 | 17 | fn format_attributes(&self) -> FormatAttributes { | 59 | 17 | FormatAttributes::default() | 60 | 17 | } |
<image::codecs::openexr::OpenExrDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::format_attributes Line | Count | Source | 58 | 2.01k | fn format_attributes(&self) -> FormatAttributes { | 59 | 2.01k | FormatAttributes::default() | 60 | 2.01k | } |
|
61 | | |
62 | | /// Retrieve animation attributes. |
63 | | /// |
64 | | /// You should check [`FormatAttributes::supports_animation`] before calling this method. A |
65 | | /// value will only be available on animated images. Additionally, most file formats store the |
66 | | /// metadata in the header which might not be read until after calling |
67 | | /// [`ImageDecoder::prepare_image`]. |
68 | | /// |
69 | | /// The value here is expected to remain constant when it is present. |
70 | 0 | fn animation_attributes(&mut self) -> Option<DecodedAnimationAttributes> { |
71 | 0 | None |
72 | 0 | } Unexecuted instantiation: <image::codecs::hdr::decoder::HdrDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::animation_attributes Unexecuted instantiation: <image::codecs::qoi::QoiDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::animation_attributes Unexecuted instantiation: <image::codecs::tiff::TiffDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::animation_attributes Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::animation_attributes Unexecuted instantiation: <image::codecs::bmp::decoder::BmpDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::animation_attributes Unexecuted instantiation: <image::codecs::tga::decoder::TgaDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::animation_attributes Unexecuted instantiation: <image::codecs::farbfeld::FarbfeldDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::animation_attributes Unexecuted instantiation: <image::codecs::jpeg::decoder::JpegDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::animation_attributes Unexecuted instantiation: <image::codecs::openexr::OpenExrDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::animation_attributes |
73 | | |
74 | | /// Consume the header of the image, determining the (next) image's layout. |
75 | | /// |
76 | | /// This shall be called before a call to [`ImageDecoder::read_image`] to ensure that the |
77 | | /// initial metadata has been read. The returned layout indicates the expected buffer of |
78 | | /// [`ImageDecoder::read_image`]. The caller is responsible for passing a buffer of the |
79 | | /// appropriate size. |
80 | | /// |
81 | | /// This method should be idempotent on success, calling it multiple times in a row should |
82 | | /// produce equivalent results. The decoder must _not_ advance to another image descriptor when |
83 | | /// it is called when it has already reached one. |
84 | | /// |
85 | | /// In contrast to a constructor it can be called multiple times, even after reconfiguring |
86 | | /// limits and context which avoids resource issues for formats that buffer metadata. |
87 | | fn prepare_image(&mut self) -> ImageResult<DecoderPreparedImage>; |
88 | | |
89 | | /// Read all the bytes in the image into a buffer. |
90 | | /// |
91 | | /// This function takes a slice of bytes and writes the pixel data of the image into it. |
92 | | /// `buf` must not be assumed to be aligned to any byte boundaries. However, |
93 | | /// alignment to 2 or 4 byte boundaries may result in small performance |
94 | | /// improvements for certain decoder implementations. |
95 | | /// |
96 | | /// The returned pixel data will always be in native endian. This allows |
97 | | /// `[u16]` and `[f32]` slices to be cast to `[u8]` and used for this method. |
98 | | /// |
99 | | /// # Panics |
100 | | /// |
101 | | /// This function should panic if `buf.len() != self.prepare_image().total_bytes()`. |
102 | | /// |
103 | | /// # Examples |
104 | | /// |
105 | | /// ``` |
106 | | /// # use image::ImageDecoder; |
107 | | /// fn read_16bit_image(mut decoder: impl ImageDecoder) -> Vec<u16> { |
108 | | /// let layout = decoder.prepare_image().unwrap(); |
109 | | /// let mut buf: Vec<u16> = vec![0; (layout.total_bytes() / 2) as usize]; |
110 | | /// decoder.read_image(bytemuck::cast_slice_mut(&mut buf)).unwrap(); |
111 | | /// buf |
112 | | /// } |
113 | | /// ``` |
114 | | fn read_image(&mut self, buf: &mut [u8]) -> ImageResult<DecodedImageAttributes>; |
115 | | |
116 | | /// Returns the ICC color profile embedded in the image, or `Ok(None)` if the image does not have one. |
117 | | /// |
118 | | /// For formats that don't support embedded profiles this function should always return |
119 | | /// `Ok(None)`. Decoders for formats with non-standard color profiles may create a synthetic |
120 | | /// profile, see our [`bmp`](`crate::codecs::bmp`) module for an example. |
121 | | /// |
122 | | /// A decoder that encounters tags which contain a color profile whose encoding it does not |
123 | | /// support should return [`UnsupportedError`](`crate::error::UnsupportedError`). This allows a |
124 | | /// reader to continue while differentiating from missing metadata. |
125 | 0 | fn icc_profile(&mut self) -> ImageResult<Option<Vec<u8>>> { |
126 | 0 | Ok(None) |
127 | 0 | } Unexecuted instantiation: <image::codecs::hdr::decoder::HdrDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::icc_profile Unexecuted instantiation: <image::codecs::qoi::QoiDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::icc_profile Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::icc_profile Unexecuted instantiation: <image::codecs::tga::decoder::TgaDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::icc_profile Unexecuted instantiation: <image::codecs::farbfeld::FarbfeldDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::icc_profile Unexecuted instantiation: <image::codecs::openexr::OpenExrDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::icc_profile |
128 | | |
129 | | /// Returns the raw [Exif](https://en.wikipedia.org/wiki/Exif) chunk, if it is present. |
130 | | /// A third-party crate such as [`kamadak-exif`](https://docs.rs/kamadak-exif/) is required to actually parse it. |
131 | | /// |
132 | | /// For formats that don't support embedded profiles this function should always return `Ok(None)`. |
133 | | /// |
134 | | /// A decoder that encounters tags which contain XMP metadata whose encoding it does not |
135 | | /// support should return [`UnsupportedError`](crate::error::UnsupportedError). This allows a |
136 | | /// reader to continue while differentiating from missing metadata. |
137 | 0 | fn exif_metadata(&mut self) -> ImageResult<Option<Vec<u8>>> { |
138 | 0 | Ok(None) |
139 | 0 | } Unexecuted instantiation: <image::codecs::hdr::decoder::HdrDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::exif_metadata Unexecuted instantiation: <image::codecs::qoi::QoiDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::exif_metadata Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::exif_metadata Unexecuted instantiation: <image::codecs::bmp::decoder::BmpDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::exif_metadata Unexecuted instantiation: <image::codecs::tga::decoder::TgaDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::exif_metadata Unexecuted instantiation: <image::codecs::farbfeld::FarbfeldDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::exif_metadata Unexecuted instantiation: <image::codecs::gif::GifDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::exif_metadata Unexecuted instantiation: <image::codecs::openexr::OpenExrDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::exif_metadata |
140 | | |
141 | | /// Returns the raw [XMP](https://en.wikipedia.org/wiki/Extensible_Metadata_Platform) chunk, if it is present. |
142 | | /// A third-party crate such as [`roxmltree`](https://docs.rs/roxmltree/) is required to actually parse it. |
143 | | /// |
144 | | /// For formats that don't support embedded profiles this function should always return `Ok(None)`. |
145 | | /// |
146 | | /// A decoder that encounters tags which contain XMP metadata whose encoding it does not |
147 | | /// support should return [`UnsupportedError`](crate::error::UnsupportedError). This allows a |
148 | | /// reader to continue while differentiating from missing metadata. |
149 | 0 | fn xmp_metadata(&mut self) -> ImageResult<Option<Vec<u8>>> { |
150 | 0 | Ok(None) |
151 | 0 | } Unexecuted instantiation: <image::codecs::hdr::decoder::HdrDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::xmp_metadata Unexecuted instantiation: <image::codecs::qoi::QoiDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::xmp_metadata Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::xmp_metadata Unexecuted instantiation: <image::codecs::bmp::decoder::BmpDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::xmp_metadata Unexecuted instantiation: <image::codecs::tga::decoder::TgaDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::xmp_metadata Unexecuted instantiation: <image::codecs::farbfeld::FarbfeldDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::xmp_metadata Unexecuted instantiation: <image::codecs::openexr::OpenExrDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::xmp_metadata |
152 | | |
153 | | /// Returns the raw [IPTC](https://en.wikipedia.org/wiki/IPTC_Information_Interchange_Model) chunk, if it is present. |
154 | | /// |
155 | | /// For formats that don't support embedded profiles this function should always return `Ok(None)`. |
156 | | /// |
157 | | /// A decoder that encounters tags which contain XMP metadata whose encoding it does not |
158 | | /// support should return [`UnsupportedError`](crate::error::UnsupportedError). This allows a |
159 | | /// reader to continue while differentiating from missing metadata. |
160 | 0 | fn iptc_metadata(&mut self) -> ImageResult<Option<Vec<u8>>> { |
161 | 0 | Ok(None) |
162 | 0 | } Unexecuted instantiation: <image::codecs::hdr::decoder::HdrDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::iptc_metadata Unexecuted instantiation: <image::codecs::qoi::QoiDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::iptc_metadata Unexecuted instantiation: <image::codecs::webp::decoder::WebPDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::iptc_metadata Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::iptc_metadata Unexecuted instantiation: <image::codecs::bmp::decoder::BmpDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::iptc_metadata Unexecuted instantiation: <image::codecs::tga::decoder::TgaDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::iptc_metadata Unexecuted instantiation: <image::codecs::farbfeld::FarbfeldDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::iptc_metadata Unexecuted instantiation: <image::codecs::gif::GifDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::iptc_metadata Unexecuted instantiation: <image::codecs::openexr::OpenExrDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::iptc_metadata |
163 | | |
164 | | /// Called to determine if there may be more images to decode. |
165 | | /// |
166 | | /// This ends the decoding loop early when it indicates `None`. Otherwise, termination can only |
167 | | /// be handled through errors. See also |
168 | | /// [`ImageReader::into_frames`](crate::ImageReader::into_frames). |
169 | 0 | fn more_images(&self) -> SequenceControl { |
170 | 0 | SequenceControl::MaybeMore |
171 | 0 | } Unexecuted instantiation: <image::codecs::hdr::decoder::HdrDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::more_images Unexecuted instantiation: <image::codecs::qoi::QoiDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::more_images Unexecuted instantiation: <image::codecs::png::PngDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::more_images Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::more_images Unexecuted instantiation: <image::codecs::bmp::decoder::BmpDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::more_images Unexecuted instantiation: <image::codecs::tga::decoder::TgaDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::more_images Unexecuted instantiation: <image::codecs::farbfeld::FarbfeldDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::more_images Unexecuted instantiation: <image::codecs::gif::GifDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::more_images Unexecuted instantiation: <image::codecs::jpeg::decoder::JpegDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::more_images Unexecuted instantiation: <image::codecs::openexr::OpenExrDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::more_images |
172 | | |
173 | | /// Consume the rest of the file, including any trailer. |
174 | 0 | fn finish(&mut self) -> ImageResult<()> { |
175 | 0 | Ok(()) |
176 | 0 | } Unexecuted instantiation: <image::codecs::hdr::decoder::HdrDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::finish Unexecuted instantiation: <image::codecs::qoi::QoiDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::finish Unexecuted instantiation: <image::codecs::png::PngDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::finish Unexecuted instantiation: <image::codecs::webp::decoder::WebPDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::finish Unexecuted instantiation: <image::codecs::tiff::TiffDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::finish Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::finish Unexecuted instantiation: <image::codecs::bmp::decoder::BmpDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::finish Unexecuted instantiation: <image::codecs::tga::decoder::TgaDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::finish Unexecuted instantiation: <image::codecs::farbfeld::FarbfeldDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::finish Unexecuted instantiation: <image::codecs::gif::GifDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::finish Unexecuted instantiation: <image::codecs::jpeg::decoder::JpegDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::finish Unexecuted instantiation: <image::codecs::openexr::OpenExrDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::finish |
177 | | } |
178 | | |
179 | | /// Information meant to steer the protocol usage with the decoder. |
180 | | #[derive(Clone, Debug, Default)] |
181 | | #[non_exhaustive] |
182 | | pub struct FormatAttributes { |
183 | | /// Could there be multiple images in this file that form an animation? |
184 | | pub supports_animation: bool, |
185 | | /// Could there be multiple images in this file, as an unrelated sequence? |
186 | | pub supports_sequence: bool, |
187 | | /// When should ICC profiles be retrieved. |
188 | | pub icc: DecodedMetadataHint, |
189 | | /// A hint for polling EXIF metadata. |
190 | | pub exif: DecodedMetadataHint, |
191 | | /// A hint for polling XMP metadata. |
192 | | pub xmp: DecodedMetadataHint, |
193 | | /// A hint for polling IPTC metadata. |
194 | | pub iptc: DecodedMetadataHint, |
195 | | } |
196 | | |
197 | | /// Additional attributes of animated image sequences. |
198 | | #[derive(Clone, Debug)] |
199 | | #[non_exhaustive] |
200 | | pub struct DecodedAnimationAttributes { |
201 | | /// Loop count of the animated image. |
202 | | pub loop_count: LoopCount, |
203 | | } |
204 | | |
205 | | impl Default for DecodedAnimationAttributes { |
206 | 0 | fn default() -> Self { |
207 | 0 | Self { |
208 | 0 | loop_count: LoopCount::Infinite, |
209 | 0 | } |
210 | 0 | } |
211 | | } |
212 | | |
213 | | /// Additional attributes of an image available after decoding. |
214 | | /// |
215 | | /// The [`Default`] is implemented and returns a value suitable for very basic images from formats |
216 | | /// that contain only one raster graphic. |
217 | | #[derive(Clone, Debug, Default)] |
218 | | #[non_exhaustive] |
219 | | pub struct DecodedImageAttributes { |
220 | | /// The x-coordinate of the top-left rectangle of the image relative to canvas indicated by the |
221 | | /// sequence of frames. |
222 | | pub x: u32, |
223 | | /// The y-coordinate of the top-left rectangle of the image relative to canvas indicated by the |
224 | | /// sequence of frames. |
225 | | pub y: u32, |
226 | | /// A suggested presentation offset relative to the previous image. |
227 | | pub delay: Option<Delay>, |
228 | | /// Orientation of the image, not relayed through EXIF metadata. |
229 | | pub orientation: Option<Orientation>, |
230 | | /// Is the underlying data converted into a different pixel format or color model? |
231 | | /// |
232 | | /// This field is currently an optional hint for encoding. The authoritative source for the |
233 | | /// memory size required for [`ImageDecoder::read_image`][`crate::ImageDecoder`] remains the |
234 | | /// [`color`][`crate::ImageLayout::color`] field, you do not need to time travel this |
235 | | /// information. |
236 | | pub original_color_type: Option<crate::ExtendedColorType>, |
237 | | } |
238 | | |
239 | | /// A hint when metadata corresponding to the image is decoded. |
240 | | /// |
241 | | /// Note that while this is a hint, different variants give contradictory indication on when they |
242 | | /// should be polled. When a metadatum is tagged as [`DecodedMetadataHint::PerImage`] it MUST be |
243 | | /// polled after each image to ensure all are retrieved, iterating to the next image without |
244 | | /// polling MAY reset and skip some metadata. |
245 | | /// |
246 | | /// # Design consideration |
247 | | /// |
248 | | /// Each variant describes a way to fetch accurate and complete metadata for an individual image in |
249 | | /// a file. This offloads some responsibility to the decoder, streamed formats that may contain |
250 | | /// parts after the file need to be peek forwards to aggregate all metadata and then seek |
251 | | /// backwards. During design we had a sequence that relied on [`ImageDecoder::finish`] but that did |
252 | | /// not allow the reader to ensure all data was present. This call would also be destructive with |
253 | | /// regards to the other kind of metadata. |
254 | | #[derive(Clone, Debug, Default)] |
255 | | #[non_exhaustive] |
256 | | pub enum DecodedMetadataHint { |
257 | | /// The decoder does not support this datum. It will return `None` but there is no guarantee |
258 | | /// that the datum is truly absent in the file. |
259 | | /// |
260 | | /// This is the default. |
261 | | #[default] |
262 | | Unsupported, |
263 | | /// Metadata is available in the header and will be valid after the first call to |
264 | | /// [`ImageDecoder::prepare_image`] and will remain valid for all subsequent images. |
265 | | InHeader, |
266 | | /// Metadata exists for each image in this file, it must be retrieved between peeking the |
267 | | /// layout and reading the image. |
268 | | PerImage, |
269 | | /// There's no metadata of this type, the decoder would return `None` or an error. |
270 | | None, |
271 | | } |
272 | | |
273 | | /// Indicate if there may be more images to decode. |
274 | | /// |
275 | | /// More concrete indications may be added in the future. |
276 | | #[non_exhaustive] |
277 | | #[derive(Default)] |
278 | | pub enum SequenceControl { |
279 | | /// The format can not certainly say if there are more images. The caller should try to decode |
280 | | /// more images until an error occurs (specifically |
281 | | /// [`ParameterErrorKind::NoMoreData`](crate::error::ParameterErrorKind::NoMoreData)). |
282 | | #[default] |
283 | | MaybeMore, |
284 | | /// The decoder is sure that no more images are present. |
285 | | /// |
286 | | /// Further attempts to decode images should not be made, but no strong guarantee is made about |
287 | | /// returning an error in these cases. In particular, further attempts may further read the |
288 | | /// image file and check for errors in trailing data. |
289 | | None, |
290 | | } |
291 | | |
292 | | #[deny(clippy::missing_trait_methods)] |
293 | | impl<T: ?Sized + ImageDecoder> ImageDecoder for Box<T> { |
294 | 57.0k | fn format_attributes(&self) -> FormatAttributes { |
295 | 57.0k | (**self).format_attributes() |
296 | 57.0k | } <alloc::boxed::Box<dyn image::io::decoder::ImageDecoder> as image::io::decoder::ImageDecoder>::format_attributes Line | Count | Source | 294 | 53.4k | fn format_attributes(&self) -> FormatAttributes { | 295 | 53.4k | (**self).format_attributes() | 296 | 53.4k | } |
<alloc::boxed::Box<image::codecs::png::PngDecoder<std::io::cursor::Cursor<&[u8]>>> as image::io::decoder::ImageDecoder>::format_attributes Line | Count | Source | 294 | 3.61k | fn format_attributes(&self) -> FormatAttributes { | 295 | 3.61k | (**self).format_attributes() | 296 | 3.61k | } |
|
297 | 73.1k | fn prepare_image(&mut self) -> ImageResult<DecoderPreparedImage> { |
298 | 73.1k | (**self).prepare_image() |
299 | 73.1k | } <alloc::boxed::Box<dyn image::io::decoder::ImageDecoder> as image::io::decoder::ImageDecoder>::prepare_image Line | Count | Source | 297 | 60.2k | fn prepare_image(&mut self) -> ImageResult<DecoderPreparedImage> { | 298 | 60.2k | (**self).prepare_image() | 299 | 60.2k | } |
<alloc::boxed::Box<image::codecs::png::PngDecoder<std::io::cursor::Cursor<&[u8]>>> as image::io::decoder::ImageDecoder>::prepare_image Line | Count | Source | 297 | 12.8k | fn prepare_image(&mut self) -> ImageResult<DecoderPreparedImage> { | 298 | 12.8k | (**self).prepare_image() | 299 | 12.8k | } |
|
300 | 0 | fn animation_attributes(&mut self) -> Option<DecodedAnimationAttributes> { |
301 | 0 | (**self).animation_attributes() |
302 | 0 | } Unexecuted instantiation: <alloc::boxed::Box<dyn image::io::decoder::ImageDecoder> as image::io::decoder::ImageDecoder>::animation_attributes Unexecuted instantiation: <alloc::boxed::Box<image::codecs::png::PngDecoder<std::io::cursor::Cursor<&[u8]>>> as image::io::decoder::ImageDecoder>::animation_attributes |
303 | 3.45k | fn icc_profile(&mut self) -> ImageResult<Option<Vec<u8>>> { |
304 | 3.45k | (**self).icc_profile() |
305 | 3.45k | } |
306 | 3.45k | fn exif_metadata(&mut self) -> ImageResult<Option<Vec<u8>>> { |
307 | 3.45k | (**self).exif_metadata() |
308 | 3.45k | } |
309 | 3.45k | fn xmp_metadata(&mut self) -> ImageResult<Option<Vec<u8>>> { |
310 | 3.45k | (**self).xmp_metadata() |
311 | 3.45k | } |
312 | 3.45k | fn iptc_metadata(&mut self) -> ImageResult<Option<Vec<u8>>> { |
313 | 3.45k | (**self).iptc_metadata() |
314 | 3.45k | } |
315 | 3.33k | fn read_image(&mut self, buf: &mut [u8]) -> ImageResult<DecodedImageAttributes> { |
316 | 3.33k | (**self).read_image(buf) |
317 | 3.33k | } Unexecuted instantiation: <alloc::boxed::Box<dyn image::io::decoder::ImageDecoder> as image::io::decoder::ImageDecoder>::read_image <alloc::boxed::Box<image::codecs::png::PngDecoder<std::io::cursor::Cursor<&[u8]>>> as image::io::decoder::ImageDecoder>::read_image Line | Count | Source | 315 | 3.33k | fn read_image(&mut self, buf: &mut [u8]) -> ImageResult<DecodedImageAttributes> { | 316 | 3.33k | (**self).read_image(buf) | 317 | 3.33k | } |
|
318 | 69.9k | fn set_limits(&mut self, limits: crate::Limits) -> ImageResult<()> { |
319 | 69.9k | (**self).set_limits(limits) |
320 | 69.9k | } <alloc::boxed::Box<dyn image::io::decoder::ImageDecoder> as image::io::decoder::ImageDecoder>::set_limits Line | Count | Source | 318 | 63.8k | fn set_limits(&mut self, limits: crate::Limits) -> ImageResult<()> { | 319 | 63.8k | (**self).set_limits(limits) | 320 | 63.8k | } |
<alloc::boxed::Box<image::codecs::png::PngDecoder<std::io::cursor::Cursor<&[u8]>>> as image::io::decoder::ImageDecoder>::set_limits Line | Count | Source | 318 | 6.16k | fn set_limits(&mut self, limits: crate::Limits) -> ImageResult<()> { | 319 | 6.16k | (**self).set_limits(limits) | 320 | 6.16k | } |
|
321 | 0 | fn more_images(&self) -> SequenceControl { |
322 | 0 | (**self).more_images() |
323 | 0 | } Unexecuted instantiation: <alloc::boxed::Box<dyn image::io::decoder::ImageDecoder> as image::io::decoder::ImageDecoder>::more_images Unexecuted instantiation: <alloc::boxed::Box<image::codecs::png::PngDecoder<std::io::cursor::Cursor<&[u8]>>> as image::io::decoder::ImageDecoder>::more_images |
324 | 0 | fn finish(&mut self) -> ImageResult<()> { |
325 | 0 | (**self).finish() |
326 | 0 | } |
327 | | } |
328 | | |
329 | | #[cfg(test)] |
330 | | mod tests { |
331 | | use super::{DecodedImageAttributes, DecoderPreparedImage, ImageDecoder, ImageResult}; |
332 | | use crate::ColorType; |
333 | | |
334 | | #[test] |
335 | | fn total_bytes_overflow() { |
336 | | struct D; |
337 | | |
338 | | impl ImageDecoder for D { |
339 | | fn prepare_image(&mut self) -> ImageResult<DecoderPreparedImage> { |
340 | | Ok(DecoderPreparedImage::new( |
341 | | 0xffff_ffff, |
342 | | 0xffff_ffff, |
343 | | ColorType::Rgb8, |
344 | | )) |
345 | | } |
346 | | |
347 | | fn read_image(&mut self, _buf: &mut [u8]) -> ImageResult<DecodedImageAttributes> { |
348 | | unreachable!("Must not be called in this test") |
349 | | } |
350 | | } |
351 | | |
352 | | assert_eq!(D.prepare_image().unwrap().total_bytes(), u64::MAX); |
353 | | let v = crate::DynamicImage::from_decoder(D); |
354 | | assert!(v.is_err()); |
355 | | } |
356 | | } |