diff --git a/src/buffer.rs b/src/buffer.rs index da4788cdd9..596fe29258 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -948,9 +948,11 @@ where { /// Writes the buffer to a writer in the specified format. /// - /// The image format is derived from the file extension. - /// Currently only jpeg, png, ico, bmp, pnm, - /// gif, tga, farbfeld and avif formats are supported. + /// See [`ImageOutputFormat`](../enum.ImageOutputFormat.html) for + /// supported types. + /// + /// **Note**: TIFF encoding uses buffered writing, + /// which can lead to unexpected use of resources pub fn write_to(&self, writer: &mut W, format: F) -> ImageResult<()> where W: std::io::Write, diff --git a/src/dynimage.rs b/src/dynimage.rs index b55d5d19a6..014f7dcdef 100644 --- a/src/dynimage.rs +++ b/src/dynimage.rs @@ -3,24 +3,12 @@ use std::io::Write; use std::path::Path; use std::u32; -#[cfg(feature = "bmp")] -use crate::codecs::bmp; #[cfg(feature = "gif")] use crate::codecs::gif; -#[cfg(feature = "ico")] -use crate::codecs::ico; -#[cfg(feature = "jpeg")] -use crate::codecs::jpeg; #[cfg(feature = "png")] use crate::codecs::png; #[cfg(feature = "pnm")] use crate::codecs::pnm; -#[cfg(feature = "farbfeld")] -use crate::codecs::farbfeld; -#[cfg(feature = "tga")] -use crate::codecs::tga; -#[cfg(feature = "avif-encoder")] -use crate::codecs::avif; use crate::buffer_::{ BgrImage, BgraImage, ConvertBuffer, GrayAlphaImage, GrayAlpha16Image, @@ -32,7 +20,6 @@ use crate::error::{ImageError, ImageFormatHint, ImageResult, ParameterError, Par use crate::flat::FlatSamples; use crate::image; use crate::image::{GenericImage, GenericImageView, ImageDecoder, ImageFormat, ImageOutputFormat}; -use crate::image::ImageEncoder; use crate::io::free_functions; use crate::imageops; use crate::math::resize_dimensions; @@ -896,6 +883,8 @@ impl DynamicImage { } /// Encode this image and write it to ```w``` + /// **Note**: TIFF encoding uses buffered writing, + /// which can lead to unexpected use of resources pub fn write_to>( &self, w: &mut W, @@ -956,13 +945,6 @@ impl DynamicImage { Ok(()) } - #[cfg(feature = "jpeg")] - image::ImageOutputFormat::Jpeg(quality) => { - let j = jpeg::JpegEncoder::new_with_quality(w, quality); - j.write_image(bytes, width, height, color)?; - Ok(()) - } - #[cfg(feature = "gif")] image::ImageOutputFormat::Gif => { let mut g = gif::GifEncoder::new(w); @@ -970,42 +952,7 @@ impl DynamicImage { Ok(()) } - #[cfg(feature = "ico")] - image::ImageOutputFormat::Ico => { - let i = ico::IcoEncoder::new(w); - i.encode(bytes, width, height, color)?; - Ok(()) - } - - #[cfg(feature = "bmp")] - image::ImageOutputFormat::Bmp => { - let mut b = bmp::BmpEncoder::new(w); - b.encode(bytes, width, height, color)?; - Ok(()) - } - - #[cfg(feature = "farbfeld")] - image::ImageOutputFormat::Farbfeld => { - farbfeld::FarbfeldEncoder::new(w).write_image(bytes, width, height, color) - } - - #[cfg(feature = "tga")] - image::ImageOutputFormat::Tga => { - tga::TgaEncoder::new(w).write_image(bytes, width, height, color) - } - - #[cfg(feature = "avif-encoder")] - image::ImageOutputFormat::Avif => { - avif::AvifEncoder::new(w).write_image(bytes, width, height, color) - } - - image::ImageOutputFormat::Unsupported(msg) => { - Err(ImageError::Unsupported(UnsupportedError::from_format_and_kind( - ImageFormatHint::Unknown, - UnsupportedErrorKind::Format(ImageFormatHint::Name(msg))))) - }, - - image::ImageOutputFormat::__NonExhaustive(marker) => match marker._private {}, + format => write_buffer_with_format(w, bytes, width, height, color, format) } } @@ -1297,8 +1244,13 @@ where /// The buffer is assumed to have the correct format according /// to the specified color type. /// This will lead to corrupted writers if the buffer contains -/// malformed data. Currently only jpeg, png, ico, bmp, -/// pnm, gif, tga, farbfeld and avif formats are supported. +/// malformed data. +/// +/// See [`ImageOutputFormat`](../enum.ImageOutputFormat.html) for +/// supported types. +/// +/// **Note**: TIFF encoding uses buffered writing, +/// which can lead to unexpected use of resources pub fn write_buffer_with_format( writer: &mut W, buf: &[u8], diff --git a/src/image.rs b/src/image.rs index c241d66f5a..5fc96a8009 100644 --- a/src/image.rs +++ b/src/image.rs @@ -243,6 +243,10 @@ pub enum ImageOutputFormat { /// An Image in TGA Format Tga, + #[cfg(feature = "tiff")] + /// An Image in TIFF Format + Tiff, + #[cfg(feature = "avif-encoder")] /// An image in AVIF Format Avif, @@ -275,6 +279,9 @@ impl From for ImageOutputFormat { ImageFormat::Farbfeld => ImageOutputFormat::Farbfeld, #[cfg(feature = "tga")] ImageFormat::Tga => ImageOutputFormat::Tga, + #[cfg(feature = "tiff")] + ImageFormat::Tiff => ImageOutputFormat::Tiff, + #[cfg(feature = "avif-encoder")] ImageFormat::Avif => ImageOutputFormat::Avif, diff --git a/src/io/free_functions.rs b/src/io/free_functions.rs index 9d184ab88a..ea72599424 100644 --- a/src/io/free_functions.rs +++ b/src/io/free_functions.rs @@ -30,7 +30,7 @@ use crate::codecs::farbfeld; #[cfg(any(feature = "avif-encoder", feature = "avif-decoder"))] use crate::codecs::avif; -use crate::{ImageOutputFormat, color}; +use crate::{ImageOutputFormat, color, error::{UnsupportedError, UnsupportedErrorKind}}; use crate::image; use crate::dynimage::DynamicImage; use crate::error::{ImageError, ImageFormatHint, ImageResult}; @@ -218,10 +218,25 @@ pub(crate) fn write_buffer_impl( ImageOutputFormat::Farbfeld => farbfeld::FarbfeldEncoder::new(fout).write_image(buf, width, height, color), #[cfg(feature = "tga")] ImageOutputFormat::Tga => tga::TgaEncoder::new(fout).write_image(buf, width, height, color), + #[cfg(feature = "tiff")] + ImageOutputFormat::Tiff => { + let mut cursor = std::io::Cursor::new(Vec::new()); + tiff::TiffEncoder::new(&mut cursor).write_image(buf, width, height, color)?; + fout.write(&cursor.into_inner()[..]) + .map(|_| ()) + .map_err(ImageError::IoError) + } #[cfg(feature = "avif-encoder")] ImageOutputFormat::Avif => avif::AvifEncoder::new(fout).write_image(buf, width, height, color), - ImageOutputFormat::Unsupported(format) => Err(ImageError::Unsupported(ImageFormatHint::Name(format).into())), - format => Err(ImageError::Unsupported(ImageFormatHint::Name(format!("{:?}", format)).into())) + + image::ImageOutputFormat::Unsupported(msg) => { + Err(ImageError::Unsupported(UnsupportedError::from_format_and_kind( + ImageFormatHint::Unknown, + UnsupportedErrorKind::Format(ImageFormatHint::Name(msg))))) + } + + image::ImageOutputFormat::__NonExhaustive(marker) => match marker._private {}, + } }