/src/image/src/io/encoder.rs
Line | Count | Source |
1 | | use crate::error::{ImageFormatHint, ImageResult, UnsupportedError, UnsupportedErrorKind}; |
2 | | use crate::{ColorType, DynamicImage, ExtendedColorType}; |
3 | | |
4 | | /// Nominally public but DO NOT expose this type. |
5 | | /// |
6 | | /// To be somewhat sure here's a compile fail test: |
7 | | /// |
8 | | /// ```compile_fail |
9 | | /// use image::MethodSealedToImage; |
10 | | /// ``` |
11 | | /// |
12 | | /// ```compile_fail |
13 | | /// use image::io::MethodSealedToImage; |
14 | | /// ``` |
15 | | /// |
16 | | /// The same implementation strategy for a partially public trait is used in the standard library, |
17 | | /// for the different effect of forbidding `Error::type_id` overrides thus making them reliable for |
18 | | /// their calls through the `dyn` version of the trait. |
19 | | /// |
20 | | /// Read more: <https://predr.ag/blog/definitive-guide-to-sealed-traits-in-rust/> |
21 | | #[derive(Clone, Copy)] |
22 | | pub struct MethodSealedToImage; |
23 | | |
24 | | /// The trait all encoders implement |
25 | | pub trait ImageEncoder { |
26 | | /// Writes all the bytes in an image to the encoder. |
27 | | /// |
28 | | /// This function takes a slice of bytes of the pixel data of the image and encodes them. Just |
29 | | /// like for [`ImageDecoder::read_image`](crate::ImageDecoder), no particular alignment is |
30 | | /// required and data is expected to be in native endian. The implementation will reorder the |
31 | | /// endianness as necessary for the target encoding format. |
32 | | /// |
33 | | /// # Panics |
34 | | /// |
35 | | /// Panics if `width * height * color_type.bytes_per_pixel() != buf.len()`. |
36 | | fn write_image( |
37 | | self, |
38 | | buf: &[u8], |
39 | | width: u32, |
40 | | height: u32, |
41 | | color_type: ExtendedColorType, |
42 | | ) -> ImageResult<()>; |
43 | | |
44 | | /// Set the ICC profile to use for the image. |
45 | | /// |
46 | | /// This function is a no-op for formats that don't support ICC profiles. |
47 | | /// For formats that do support ICC profiles, the profile will be embedded |
48 | | /// in the image when it is saved. |
49 | | /// |
50 | | /// # Errors |
51 | | /// |
52 | | /// This function returns an error if the format does not support ICC profiles. |
53 | 0 | fn set_icc_profile(&mut self, icc_profile: Vec<u8>) -> Result<(), UnsupportedError> { |
54 | 0 | let _ = icc_profile; |
55 | 0 | Err(UnsupportedError::from_format_and_kind( |
56 | 0 | ImageFormatHint::Unknown, |
57 | 0 | UnsupportedErrorKind::GenericFeature( |
58 | 0 | "ICC profiles are not supported for this format".into(), |
59 | 0 | ), |
60 | 0 | )) |
61 | 0 | } Unexecuted instantiation: <_ as image::io::encoder::ImageEncoder>::set_icc_profile Unexecuted instantiation: <image::codecs::avif::encoder::AvifEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoder>::set_icc_profile Unexecuted instantiation: <image::codecs::farbfeld::FarbfeldEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoder>::set_icc_profile Unexecuted instantiation: <image::codecs::tiff::TiffEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoder>::set_icc_profile Unexecuted instantiation: <image::codecs::qoi::QoiEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoder>::set_icc_profile Unexecuted instantiation: <image::codecs::bmp::encoder::BmpEncoder<std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoder>::set_icc_profile Unexecuted instantiation: <image::codecs::hdr::encoder::HdrEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoder>::set_icc_profile Unexecuted instantiation: <image::codecs::ico::encoder::IcoEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoder>::set_icc_profile Unexecuted instantiation: <image::codecs::gif::GifEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoder>::set_icc_profile Unexecuted instantiation: <image::codecs::openexr::OpenExrEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoder>::set_icc_profile Unexecuted instantiation: <image::codecs::tga::encoder::TgaEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoder>::set_icc_profile Unexecuted instantiation: <image::codecs::pnm::encoder::PnmEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoder>::set_icc_profile |
62 | | |
63 | | /// Set the EXIF metadata to use for the image. |
64 | | /// |
65 | | /// This function is a no-op for formats that don't support EXIF metadata. |
66 | | /// For formats that do support EXIF metadata, the metadata will be embedded |
67 | | /// in the image when it is saved. |
68 | | /// |
69 | | /// # Errors |
70 | | /// |
71 | | /// This function returns an error if the format does not support EXIF metadata or if the |
72 | | /// encoder doesn't implement saving EXIF metadata yet. |
73 | 0 | fn set_exif_metadata(&mut self, exif: Vec<u8>) -> Result<(), UnsupportedError> { |
74 | 0 | let _ = exif; |
75 | 0 | Err(UnsupportedError::from_format_and_kind( |
76 | 0 | ImageFormatHint::Unknown, |
77 | 0 | UnsupportedErrorKind::GenericFeature( |
78 | 0 | "EXIF metadata is not supported for this format".into(), |
79 | 0 | ), |
80 | 0 | )) |
81 | 0 | } Unexecuted instantiation: <_ as image::io::encoder::ImageEncoder>::set_exif_metadata Unexecuted instantiation: <image::codecs::avif::encoder::AvifEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoder>::set_exif_metadata Unexecuted instantiation: <image::codecs::farbfeld::FarbfeldEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoder>::set_exif_metadata Unexecuted instantiation: <image::codecs::tiff::TiffEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoder>::set_exif_metadata Unexecuted instantiation: <image::codecs::qoi::QoiEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoder>::set_exif_metadata Unexecuted instantiation: <image::codecs::bmp::encoder::BmpEncoder<std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoder>::set_exif_metadata Unexecuted instantiation: <image::codecs::hdr::encoder::HdrEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoder>::set_exif_metadata Unexecuted instantiation: <image::codecs::ico::encoder::IcoEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoder>::set_exif_metadata Unexecuted instantiation: <image::codecs::gif::GifEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoder>::set_exif_metadata Unexecuted instantiation: <image::codecs::openexr::OpenExrEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoder>::set_exif_metadata Unexecuted instantiation: <image::codecs::tga::encoder::TgaEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoder>::set_exif_metadata Unexecuted instantiation: <image::codecs::pnm::encoder::PnmEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoder>::set_exif_metadata |
82 | | |
83 | | /// Convert the image to a compatible format for the encoder. This is used by the encoding |
84 | | /// methods on `DynamicImage`. |
85 | | /// |
86 | | /// Note that this is method is sealed to the crate and effectively pub(crate) due to the |
87 | | /// argument type not being nameable. |
88 | | #[doc(hidden)] |
89 | 0 | fn make_compatible_img( |
90 | 0 | &self, |
91 | 0 | _: MethodSealedToImage, |
92 | 0 | _input: &DynamicImage, |
93 | 0 | ) -> Option<DynamicImage> { |
94 | 0 | None |
95 | 0 | } Unexecuted instantiation: <_ as image::io::encoder::ImageEncoder>::make_compatible_img Unexecuted instantiation: <image::codecs::avif::encoder::AvifEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoder>::make_compatible_img Unexecuted instantiation: <image::codecs::farbfeld::FarbfeldEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoder>::make_compatible_img Unexecuted instantiation: <image::codecs::tiff::TiffEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoder>::make_compatible_img Unexecuted instantiation: <image::codecs::qoi::QoiEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoder>::make_compatible_img Unexecuted instantiation: <image::codecs::png::PngEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoder>::make_compatible_img Unexecuted instantiation: <image::codecs::hdr::encoder::HdrEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoder>::make_compatible_img Unexecuted instantiation: <image::codecs::ico::encoder::IcoEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoder>::make_compatible_img Unexecuted instantiation: <image::codecs::gif::GifEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoder>::make_compatible_img Unexecuted instantiation: <image::codecs::openexr::OpenExrEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoder>::make_compatible_img Unexecuted instantiation: <image::codecs::pnm::encoder::PnmEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoder>::make_compatible_img |
96 | | } |
97 | | |
98 | | pub(crate) trait ImageEncoderBoxed: ImageEncoder { |
99 | | fn write_image( |
100 | | self: Box<Self>, |
101 | | buf: &'_ [u8], |
102 | | width: u32, |
103 | | height: u32, |
104 | | color: ExtendedColorType, |
105 | | ) -> ImageResult<()>; |
106 | | } |
107 | | impl<T: ImageEncoder> ImageEncoderBoxed for T { |
108 | 1.83k | fn write_image( |
109 | 1.83k | self: Box<Self>, |
110 | 1.83k | buf: &'_ [u8], |
111 | 1.83k | width: u32, |
112 | 1.83k | height: u32, |
113 | 1.83k | color: ExtendedColorType, |
114 | 1.83k | ) -> ImageResult<()> { |
115 | 1.83k | (*self).write_image(buf, width, height, color) |
116 | 1.83k | } Unexecuted instantiation: <_ as image::io::encoder::ImageEncoderBoxed>::write_image Unexecuted instantiation: <image::codecs::avif::encoder::AvifEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoderBoxed>::write_image Unexecuted instantiation: <image::codecs::farbfeld::FarbfeldEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoderBoxed>::write_image Unexecuted instantiation: <image::codecs::tiff::TiffEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoderBoxed>::write_image Unexecuted instantiation: <image::codecs::qoi::QoiEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoderBoxed>::write_image Unexecuted instantiation: <image::codecs::png::PngEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoderBoxed>::write_image Unexecuted instantiation: <image::codecs::jpeg::encoder::JpegEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoderBoxed>::write_image Unexecuted instantiation: <image::codecs::bmp::encoder::BmpEncoder<std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoderBoxed>::write_image Unexecuted instantiation: <image::codecs::hdr::encoder::HdrEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoderBoxed>::write_image Unexecuted instantiation: <image::codecs::ico::encoder::IcoEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoderBoxed>::write_image Unexecuted instantiation: <image::codecs::gif::GifEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoderBoxed>::write_image Unexecuted instantiation: <image::codecs::openexr::OpenExrEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoderBoxed>::write_image Unexecuted instantiation: <image::codecs::tga::encoder::TgaEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoderBoxed>::write_image <image::codecs::webp::encoder::WebPEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoderBoxed>::write_image Line | Count | Source | 108 | 1.83k | fn write_image( | 109 | 1.83k | self: Box<Self>, | 110 | 1.83k | buf: &'_ [u8], | 111 | 1.83k | width: u32, | 112 | 1.83k | height: u32, | 113 | 1.83k | color: ExtendedColorType, | 114 | 1.83k | ) -> ImageResult<()> { | 115 | 1.83k | (*self).write_image(buf, width, height, color) | 116 | 1.83k | } |
Unexecuted instantiation: <image::codecs::pnm::encoder::PnmEncoder<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>> as image::io::encoder::ImageEncoderBoxed>::write_image |
117 | | } |
118 | | |
119 | | /// Implement `dynimage_conversion_sequence` for the common case of supporting only 8-bit colors |
120 | | /// (with and without alpha). |
121 | | #[allow(unused)] |
122 | 0 | pub(crate) fn dynimage_conversion_8bit(img: &DynamicImage) -> Option<DynamicImage> { |
123 | | use ColorType::*; |
124 | | |
125 | 0 | match img.color() { |
126 | 0 | Rgb8 | Rgba8 | L8 | La8 => None, |
127 | 0 | L16 => Some(img.to_luma8().into()), |
128 | 0 | La16 => Some(img.to_luma_alpha8().into()), |
129 | 0 | Rgb16 | Rgb32F => Some(img.to_rgb8().into()), |
130 | 0 | Rgba16 | Rgba32F => Some(img.to_rgba8().into()), |
131 | | } |
132 | 0 | } |