From 7594a2099fccf57cef5be9e7abea204cd270e432 Mon Sep 17 00:00:00 2001 From: Jonathan Behrens Date: Sun, 26 May 2024 19:35:15 -0700 Subject: [PATCH] Revert "Rename `Reader` to `ImageReader` (#2243)" This reverts commit 6d5918f48ebce101fa35437e96b38f8424b1da89. --- README.md | 4 ++-- fuzz/fuzzers/fuzzer_script_exr.rs | 2 +- src/dynimage.rs | 20 +++++++++++++------- src/io/free_functions.rs | 8 +++++--- src/io/mod.rs | 4 ++-- src/io/{image_reader.rs => reader.rs} | 26 +++++++++++++------------- src/lib.rs | 11 ++++++----- tests/limits.rs | 22 ++++++++++------------ tests/limits_anim.rs | 2 +- tests/reference_images.rs | 3 +-- 10 files changed, 54 insertions(+), 48 deletions(-) rename src/io/{image_reader.rs => reader.rs} (94%) diff --git a/README.md b/README.md index e3eb168058..ec218fbbe7 100644 --- a/README.md +++ b/README.md @@ -16,11 +16,11 @@ All image processing functions provided operate on types that implement the `Gen ## High level API -Load images using [`ImageReader`]: +Load images using [`io::Reader`]: ```rust,ignore use std::io::Cursor; -use image::ImageReader; +use image::io::Reader as ImageReader; let img = ImageReader::open("myimage.png")?.decode()?; let img2 = ImageReader::new(Cursor::new(bytes)).with_guessed_format()?.decode()?; diff --git a/fuzz/fuzzers/fuzzer_script_exr.rs b/fuzz/fuzzers/fuzzer_script_exr.rs index 75893f3433..f42ffec4d6 100644 --- a/fuzz/fuzzers/fuzzer_script_exr.rs +++ b/fuzz/fuzzers/fuzzer_script_exr.rs @@ -4,7 +4,7 @@ extern crate libfuzzer_sys; extern crate image; use image::codecs::openexr::*; -use image::Limits; +use image::io::Limits; use image::ExtendedColorType; use image::ImageDecoder; use image::ImageEncoder; diff --git a/src/dynimage.rs b/src/dynimage.rs index dcb716f6de..94bfe8f4e8 100644 --- a/src/dynimage.rs +++ b/src/dynimage.rs @@ -17,7 +17,6 @@ use crate::image::{GenericImage, GenericImageView, ImageDecoder, ImageEncoder, I use crate::io::free_functions; use crate::math::resize_dimensions; use crate::traits::Pixel; -use crate::ImageReader; use crate::{image, Luma, LumaA}; use crate::{imageops, ExtendedColorType}; use crate::{Rgb32FImage, Rgba32FImage}; @@ -1098,25 +1097,29 @@ fn decoder_to_image(decoder: I) -> ImageResult { /// Open the image located at the path specified. /// The image's format is determined from the path's file extension. /// -/// Try [`ImageReader`] for more advanced uses, including guessing the format based on the file's +/// Try [`io::Reader`] for more advanced uses, including guessing the format based on the file's /// content before its path. +/// +/// [`io::Reader`]: io/struct.Reader.html pub fn open

(path: P) -> ImageResult where P: AsRef, { - ImageReader::open(path)?.decode() + crate::io::Reader::open(path)?.decode() } /// Read a tuple containing the (width, height) of the image located at the specified path. /// This is faster than fully loading the image and then getting its dimensions. /// -/// Try [`ImageReader`] for more advanced uses, including guessing the format based on the file's +/// Try [`io::Reader`] for more advanced uses, including guessing the format based on the file's /// content before its path or manually supplying the format. +/// +/// [`io::Reader`]: io/struct.Reader.html pub fn image_dimensions

(path: P) -> ImageResult<(u32, u32)> where P: AsRef, { - ImageReader::open(path)?.into_dimensions() + crate::io::Reader::open(path)?.into_dimensions() } /// Saves the supplied buffer to a file at the path specified. @@ -1188,7 +1191,9 @@ pub fn write_buffer_with_format( /// Makes an educated guess about the image format. /// TGA is not supported by this function. /// -/// Try [`ImageReader`] for more advanced uses. +/// Try [`io::Reader`] for more advanced uses. +/// +/// [`io::Reader`]: io/struct.Reader.html pub fn load_from_memory(buffer: &[u8]) -> ImageResult { let format = free_functions::guess_format(buffer)?; load_from_memory_with_format(buffer, format) @@ -1199,9 +1204,10 @@ pub fn load_from_memory(buffer: &[u8]) -> ImageResult { /// This is just a simple wrapper that constructs an `std::io::Cursor` around the buffer and then /// calls `load` with that reader. /// -/// Try [`ImageReader`] for more advanced uses. +/// Try [`io::Reader`] for more advanced uses. /// /// [`load`]: fn.load.html +/// [`io::Reader`]: io/struct.Reader.html #[inline(always)] pub fn load_from_memory_with_format(buf: &[u8], format: ImageFormat) -> ImageResult { let b = io::Cursor::new(buf); diff --git a/src/io/free_functions.rs b/src/io/free_functions.rs index 5cbf8325b2..504efe8017 100644 --- a/src/io/free_functions.rs +++ b/src/io/free_functions.rs @@ -2,7 +2,7 @@ use std::fs::File; use std::io::{BufRead, BufWriter, Seek}; use std::path::Path; -use crate::{codecs::*, ExtendedColorType, ImageReader}; +use crate::{codecs::*, ExtendedColorType}; use crate::dynimage::DynamicImage; use crate::error::{ImageError, ImageFormatHint, ImageResult}; @@ -16,9 +16,11 @@ use crate::image::{ImageDecoder, ImageEncoder}; /// Assumes the reader is already buffered. For optimal performance, /// consider wrapping the reader with a `BufReader::new()`. /// -/// Try [`ImageReader`] for more advanced uses. +/// Try [`io::Reader`] for more advanced uses. +/// +/// [`io::Reader`]: io/struct.Reader.html pub fn load(r: R, format: ImageFormat) -> ImageResult { - let mut reader = ImageReader::new(r); + let mut reader = crate::io::Reader::new(r); reader.set_format(format); reader.decode() } diff --git a/src/io/mod.rs b/src/io/mod.rs index 21ab00d5b9..67db114dc0 100644 --- a/src/io/mod.rs +++ b/src/io/mod.rs @@ -3,9 +3,9 @@ use crate::{error, ColorType, ImageError, ImageResult}; pub(crate) mod free_functions; -mod image_reader; +mod reader; -pub use self::image_reader::ImageReader; +pub use self::reader::Reader; /// Set of supported strict limits for a decoder. #[derive(Clone, Debug, Default, Eq, PartialEq, Hash)] diff --git a/src/io/image_reader.rs b/src/io/reader.rs similarity index 94% rename from src/io/image_reader.rs rename to src/io/reader.rs index 594786bddb..aeb13811f3 100644 --- a/src/io/image_reader.rs +++ b/src/io/reader.rs @@ -21,9 +21,9 @@ use super::free_functions; /// /// ```no_run /// # use image::ImageError; -/// # use image::ImageReader; +/// # use image::io::Reader; /// # fn main() -> Result<(), ImageError> { -/// let image = ImageReader::open("path/to/image.png")? +/// let image = Reader::open("path/to/image.png")? /// .decode()?; /// # Ok(()) } /// ``` @@ -34,7 +34,7 @@ use super::free_functions; /// /// ``` /// # use image::ImageError; -/// # use image::ImageReader; +/// # use image::io::Reader; /// # fn main() -> Result<(), ImageError> { /// use std::io::Cursor; /// use image::ImageFormat; @@ -43,7 +43,7 @@ use super::free_functions; /// 0 1\n\ /// 1 0\n"; /// -/// let mut reader = ImageReader::new(Cursor::new(raw_data)) +/// let mut reader = Reader::new(Cursor::new(raw_data)) /// .with_guessed_format() /// .expect("Cursor io never fails"); /// assert_eq!(reader.format(), Some(ImageFormat::Pnm)); @@ -58,7 +58,7 @@ use super::free_functions; /// /// [`set_format`]: #method.set_format /// [`ImageDecoder`]: ../trait.ImageDecoder.html -pub struct ImageReader { +pub struct Reader { /// The reader. Should be buffered. inner: R, /// The format, if one has been set or deduced. @@ -67,7 +67,7 @@ pub struct ImageReader { limits: super::Limits, } -impl<'a, R: 'a + BufRead + Seek> ImageReader { +impl<'a, R: 'a + BufRead + Seek> Reader { /// Create a new image reader without a preset format. /// /// Assumes the reader is already buffered. For optimal performance, @@ -79,7 +79,7 @@ impl<'a, R: 'a + BufRead + Seek> ImageReader { /// [`with_guessed_format`]: #method.with_guessed_format /// [`set_format`]: method.set_format pub fn new(buffered_reader: R) -> Self { - ImageReader { + Reader { inner: buffered_reader, format: None, limits: super::Limits::default(), @@ -91,7 +91,7 @@ impl<'a, R: 'a + BufRead + Seek> ImageReader { /// Assumes the reader is already buffered. For optimal performance, /// consider wrapping the reader with a `BufReader::new()`. pub fn with_format(buffered_reader: R, format: ImageFormat) -> Self { - ImageReader { + Reader { inner: buffered_reader, format: Some(format), limits: super::Limits::default(), @@ -208,15 +208,15 @@ impl<'a, R: 'a + BufRead + Seek> ImageReader { /// /// ## Usage /// - /// This supplements the path based type deduction from [`ImageReader::open()`] with content based deduction. + /// This supplements the path based type deduction from [`open`](Reader::open) with content based deduction. /// This is more common in Linux and UNIX operating systems and also helpful if the path can /// not be directly controlled. /// /// ```no_run /// # use image::ImageError; - /// # use image::ImageReader; + /// # use image::io::Reader; /// # fn main() -> Result<(), ImageError> { - /// let image = ImageReader::open("image.unknown")? + /// let image = Reader::open("image.unknown")? /// .with_guessed_format()? /// .decode()?; /// # Ok(()) } @@ -281,7 +281,7 @@ impl<'a, R: 'a + BufRead + Seek> ImageReader { } } -impl ImageReader> { +impl Reader> { /// Open a file to read, format will be guessed from path. /// /// This will not attempt any io operation on the opened file. @@ -298,7 +298,7 @@ impl ImageReader> { } fn open_impl(path: &Path) -> io::Result { - Ok(ImageReader { + Ok(Reader { inner: BufReader::new(File::open(path)?), format: ImageFormat::from_path(path).ok(), limits: super::Limits::default(), diff --git a/src/lib.rs b/src/lib.rs index abb45ca0d4..45e09572ec 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,11 +13,11 @@ //! //! # High level API //! -//! Load images using [`ImageReader`]: +//! Load images using [`io::Reader`]: //! //! ```rust,no_run //! use std::io::Cursor; -//! use image::ImageReader; +//! use image::io::Reader as ImageReader; //! # fn main() -> Result<(), image::ImageError> { //! # let bytes = vec![0u8]; //! @@ -49,7 +49,7 @@ //! //! [`save`]: enum.DynamicImage.html#method.save //! [`write_to`]: enum.DynamicImage.html#method.write_to -//! [`ImageReader`]: struct.Reader.html +//! [`io::Reader`]: io/struct.Reader.html //! //! # Image buffers //! @@ -167,7 +167,6 @@ pub use crate::dynimage::{ save_buffer_with_format, write_buffer_with_format, }; pub use crate::io::free_functions::{guess_format, load}; -pub use crate::io::{ImageReader, LimitSupport, Limits}; pub use crate::dynimage::DynamicImage; @@ -194,6 +193,9 @@ pub mod math; // Image processing functions pub mod imageops; +// Io bindings +pub mod io; + // Buffer representations for ffi. pub mod flat; @@ -288,7 +290,6 @@ mod buffer_par; mod color; mod dynimage; mod image; -mod io; mod traits; mod utils; diff --git a/tests/limits.rs b/tests/limits.rs index f858a34ca4..7380deb5c6 100644 --- a/tests/limits.rs +++ b/tests/limits.rs @@ -7,7 +7,7 @@ //! There are several such buggy APIs in the crate. The tests for them are written but commented out. //! Pull requests fixing these APIs are very welcome. //! -//! It is possible that a maliciously crafted file could bypass these checks +//! It is possible that a maliciously crafted file coud bypass these checks //! and cause a large allocation inside the decoder despite these limits. //! These tests cannot catch that, but fuzzing can. //! @@ -15,9 +15,7 @@ use std::io::Cursor; -use image::{ - load_from_memory_with_format, ImageDecoder, ImageFormat, ImageReader, Limits, RgbImage, -}; +use image::{io::Limits, load_from_memory_with_format, ImageDecoder, ImageFormat, RgbImage}; const WIDTH: u32 = 256; const HEIGHT: u32 = 256; @@ -60,7 +58,7 @@ fn load_through_reader( format: ImageFormat, limits: Limits, ) -> Result { - let mut reader = ImageReader::new(Cursor::new(input)); + let mut reader = image::io::Reader::new(Cursor::new(input)); reader.set_format(format); reader.limits(limits); reader.decode() @@ -76,7 +74,7 @@ fn gif() { assert!(load_from_memory_with_format(&image, ImageFormat::Gif).is_ok()); // check that the limits implementation is not overly restrictive assert!(load_through_reader(&image, ImageFormat::Gif, permissive_limits()).is_ok()); - // image::ImageReader + // image::io::Reader assert!(load_through_reader(&image, ImageFormat::Gif, width_height_limits()).is_err()); assert!(load_through_reader(&image, ImageFormat::Gif, allocation_limits()).is_err()); // BROKEN! @@ -106,7 +104,7 @@ fn png() { assert!(load_from_memory_with_format(&image, ImageFormat::Png).is_ok()); // check that the limits implementation is not overly restrictive assert!(load_through_reader(&image, ImageFormat::Png, permissive_limits()).is_ok()); - // image::ImageReader + // image::io::Reader assert!(load_through_reader(&image, ImageFormat::Png, width_height_limits()).is_err()); assert!(load_through_reader(&image, ImageFormat::Png, allocation_limits()).is_err()); @@ -133,7 +131,7 @@ fn jpeg() { assert!(load_from_memory_with_format(&image, ImageFormat::Jpeg).is_ok()); // check that the limits implementation is not overly restrictive assert!(load_through_reader(&image, ImageFormat::Jpeg, permissive_limits()).is_ok()); - // image::ImageReader + // image::io::Reader assert!(load_through_reader(&image, ImageFormat::Jpeg, width_height_limits()).is_err()); assert!(load_through_reader(&image, ImageFormat::Jpeg, allocation_limits()).is_err()); @@ -153,7 +151,7 @@ fn webp() { assert!(load_from_memory_with_format(&image, ImageFormat::WebP).is_ok()); // check that the limits implementation is not overly restrictive assert!(load_through_reader(&image, ImageFormat::WebP, permissive_limits()).is_ok()); - // image::ImageReader + // image::io::Reader assert!(load_through_reader(&image, ImageFormat::WebP, width_height_limits()).is_err()); assert!(load_through_reader(&image, ImageFormat::WebP, allocation_limits()).is_err()); @@ -180,7 +178,7 @@ fn tiff() { tiff_permissive_limits.max_alloc = Some((WIDTH * HEIGHT * 10).into()); // `* 9` would be exactly three output buffers, `* 10`` has some slack space load_through_reader(&image, ImageFormat::Tiff, tiff_permissive_limits).unwrap(); - // image::ImageReader + // image::io::Reader assert!(load_through_reader(&image, ImageFormat::Tiff, width_height_limits()).is_err()); assert!(load_through_reader(&image, ImageFormat::Tiff, allocation_limits()).is_err()); @@ -200,7 +198,7 @@ fn avif() { assert!(load_from_memory_with_format(&image, ImageFormat::Avif).is_ok()); // check that the limits implementation is not overly restrictive assert!(load_through_reader(&image, ImageFormat::Avif, permissive_limits()).is_ok()); - // image::ImageReader + // image::io::Reader assert!(load_through_reader(&image, ImageFormat::Avif, width_height_limits()).is_err()); assert!(load_through_reader(&image, ImageFormat::Avif, allocation_limits()).is_err()); @@ -220,7 +218,7 @@ fn bmp() { assert!(load_from_memory_with_format(&image, ImageFormat::Bmp).is_ok()); // check that the limits implementation is not overly restrictive assert!(load_through_reader(&image, ImageFormat::Bmp, permissive_limits()).is_ok()); - // image::ImageReader + // image::io::Reader assert!(load_through_reader(&image, ImageFormat::Bmp, width_height_limits()).is_err()); assert!(load_through_reader(&image, ImageFormat::Bmp, allocation_limits()).is_err()); diff --git a/tests/limits_anim.rs b/tests/limits_anim.rs index c0983e8c46..d332f81b5c 100644 --- a/tests/limits_anim.rs +++ b/tests/limits_anim.rs @@ -1,6 +1,6 @@ //! Test enforcement of size and memory limits for animation decoding APIs. -use image::{AnimationDecoder, ImageDecoder, ImageResult, Limits}; +use image::{io::Limits, AnimationDecoder, ImageDecoder, ImageResult}; #[cfg(feature = "gif")] use image::codecs::gif::GifDecoder; diff --git a/tests/reference_images.rs b/tests/reference_images.rs index 02ef47d1d5..e695d1844a 100644 --- a/tests/reference_images.rs +++ b/tests/reference_images.rs @@ -5,7 +5,6 @@ use std::path::PathBuf; use crc32fast::Hasher as Crc32; use image::DynamicImage; -use image::ImageReader; const BASE_PATH: [&str; 2] = [".", "tests"]; const IMAGE_DIR: &str = "images"; @@ -186,7 +185,7 @@ fn check_references() { match case.kind { ReferenceTestKind::AnimatedFrame { frame: frame_num } => { - let format = ImageReader::open(&img_path) + let format = image::io::Reader::open(&img_path) .unwrap() .with_guessed_format() .unwrap()