Rename Reader to ImageReader (#2243)

This commit is contained in:
ripytide 2024-05-27 01:34:15 +01:00 committed by GitHub
parent d48c6a6ff3
commit 6d5918f48e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 48 additions and 54 deletions

View file

@ -16,11 +16,11 @@ All image processing functions provided operate on types that implement the `Gen
## High level API
Load images using [`io::Reader`]:
Load images using [`ImageReader`]:
```rust,ignore
use std::io::Cursor;
use image::io::Reader as ImageReader;
use image::ImageReader;
let img = ImageReader::open("myimage.png")?.decode()?;
let img2 = ImageReader::new(Cursor::new(bytes)).with_guessed_format()?.decode()?;

View file

@ -4,7 +4,7 @@ extern crate libfuzzer_sys;
extern crate image;
use image::codecs::openexr::*;
use image::io::Limits;
use image::Limits;
use image::ExtendedColorType;
use image::ImageDecoder;
use image::ImageEncoder;

View file

@ -17,6 +17,7 @@ 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};
@ -1097,29 +1098,25 @@ fn decoder_to_image<I: ImageDecoder>(decoder: I) -> ImageResult<DynamicImage> {
/// Open the image located at the path specified.
/// The image's format is determined from the path's file extension.
///
/// Try [`io::Reader`] for more advanced uses, including guessing the format based on the file's
/// Try [`ImageReader`] 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<P>(path: P) -> ImageResult<DynamicImage>
where
P: AsRef<Path>,
{
crate::io::Reader::open(path)?.decode()
ImageReader::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 [`io::Reader`] for more advanced uses, including guessing the format based on the file's
/// Try [`ImageReader`] 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<P>(path: P) -> ImageResult<(u32, u32)>
where
P: AsRef<Path>,
{
crate::io::Reader::open(path)?.into_dimensions()
ImageReader::open(path)?.into_dimensions()
}
/// Saves the supplied buffer to a file at the path specified.
@ -1191,9 +1188,7 @@ pub fn write_buffer_with_format<W: Write + Seek>(
/// Makes an educated guess about the image format.
/// TGA is not supported by this function.
///
/// Try [`io::Reader`] for more advanced uses.
///
/// [`io::Reader`]: io/struct.Reader.html
/// Try [`ImageReader`] for more advanced uses.
pub fn load_from_memory(buffer: &[u8]) -> ImageResult<DynamicImage> {
let format = free_functions::guess_format(buffer)?;
load_from_memory_with_format(buffer, format)
@ -1204,10 +1199,9 @@ pub fn load_from_memory(buffer: &[u8]) -> ImageResult<DynamicImage> {
/// This is just a simple wrapper that constructs an `std::io::Cursor` around the buffer and then
/// calls `load` with that reader.
///
/// Try [`io::Reader`] for more advanced uses.
/// Try [`ImageReader`] 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<DynamicImage> {
let b = io::Cursor::new(buf);

View file

@ -2,7 +2,7 @@ use std::fs::File;
use std::io::{BufRead, BufWriter, Seek};
use std::path::Path;
use crate::{codecs::*, ExtendedColorType};
use crate::{codecs::*, ExtendedColorType, ImageReader};
use crate::dynimage::DynamicImage;
use crate::error::{ImageError, ImageFormatHint, ImageResult};
@ -16,11 +16,9 @@ use crate::image::{ImageDecoder, ImageEncoder};
/// Assumes the reader is already buffered. For optimal performance,
/// consider wrapping the reader with a `BufReader::new()`.
///
/// Try [`io::Reader`] for more advanced uses.
///
/// [`io::Reader`]: io/struct.Reader.html
/// Try [`ImageReader`] for more advanced uses.
pub fn load<R: BufRead + Seek>(r: R, format: ImageFormat) -> ImageResult<DynamicImage> {
let mut reader = crate::io::Reader::new(r);
let mut reader = ImageReader::new(r);
reader.set_format(format);
reader.decode()
}

View file

@ -21,9 +21,9 @@ use super::free_functions;
///
/// ```no_run
/// # use image::ImageError;
/// # use image::io::Reader;
/// # use image::ImageReader;
/// # fn main() -> Result<(), ImageError> {
/// let image = Reader::open("path/to/image.png")?
/// let image = ImageReader::open("path/to/image.png")?
/// .decode()?;
/// # Ok(()) }
/// ```
@ -34,7 +34,7 @@ use super::free_functions;
///
/// ```
/// # use image::ImageError;
/// # use image::io::Reader;
/// # use image::ImageReader;
/// # 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 = Reader::new(Cursor::new(raw_data))
/// let mut reader = ImageReader::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 Reader<R: Read + Seek> {
pub struct ImageReader<R: Read + Seek> {
/// The reader. Should be buffered.
inner: R,
/// The format, if one has been set or deduced.
@ -67,7 +67,7 @@ pub struct Reader<R: Read + Seek> {
limits: super::Limits,
}
impl<'a, R: 'a + BufRead + Seek> Reader<R> {
impl<'a, R: 'a + BufRead + Seek> ImageReader<R> {
/// 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> Reader<R> {
/// [`with_guessed_format`]: #method.with_guessed_format
/// [`set_format`]: method.set_format
pub fn new(buffered_reader: R) -> Self {
Reader {
ImageReader {
inner: buffered_reader,
format: None,
limits: super::Limits::default(),
@ -91,7 +91,7 @@ impl<'a, R: 'a + BufRead + Seek> Reader<R> {
/// 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 {
Reader {
ImageReader {
inner: buffered_reader,
format: Some(format),
limits: super::Limits::default(),
@ -208,15 +208,15 @@ impl<'a, R: 'a + BufRead + Seek> Reader<R> {
///
/// ## Usage
///
/// This supplements the path based type deduction from [`open`](Reader::open) with content based deduction.
/// This supplements the path based type deduction from [`ImageReader::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::io::Reader;
/// # use image::ImageReader;
/// # fn main() -> Result<(), ImageError> {
/// let image = Reader::open("image.unknown")?
/// let image = ImageReader::open("image.unknown")?
/// .with_guessed_format()?
/// .decode()?;
/// # Ok(()) }
@ -281,7 +281,7 @@ impl<'a, R: 'a + BufRead + Seek> Reader<R> {
}
}
impl Reader<BufReader<File>> {
impl ImageReader<BufReader<File>> {
/// 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 Reader<BufReader<File>> {
}
fn open_impl(path: &Path) -> io::Result<Self> {
Ok(Reader {
Ok(ImageReader {
inner: BufReader::new(File::open(path)?),
format: ImageFormat::from_path(path).ok(),
limits: super::Limits::default(),

View file

@ -3,9 +3,9 @@
use crate::{error, ColorType, ImageError, ImageResult};
pub(crate) mod free_functions;
mod reader;
mod image_reader;
pub use self::reader::Reader;
pub use self::image_reader::ImageReader;
/// Set of supported strict limits for a decoder.
#[derive(Clone, Debug, Default, Eq, PartialEq, Hash)]

View file

@ -13,11 +13,11 @@
//!
//! # High level API
//!
//! Load images using [`io::Reader`]:
//! Load images using [`ImageReader`]:
//!
//! ```rust,no_run
//! use std::io::Cursor;
//! use image::io::Reader as ImageReader;
//! use image::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
//! [`io::Reader`]: io/struct.Reader.html
//! [`ImageReader`]: struct.Reader.html
//!
//! # Image buffers
//!
@ -167,6 +167,7 @@ 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;
@ -193,9 +194,6 @@ pub mod math;
// Image processing functions
pub mod imageops;
// Io bindings
pub mod io;
// Buffer representations for ffi.
pub mod flat;
@ -290,6 +288,7 @@ mod buffer_par;
mod color;
mod dynimage;
mod image;
mod io;
mod traits;
mod utils;

View file

@ -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 coud bypass these checks
//! It is possible that a maliciously crafted file could bypass these checks
//! and cause a large allocation inside the decoder despite these limits.
//! These tests cannot catch that, but fuzzing can.
//!
@ -15,7 +15,9 @@
use std::io::Cursor;
use image::{io::Limits, load_from_memory_with_format, ImageDecoder, ImageFormat, RgbImage};
use image::{
load_from_memory_with_format, ImageDecoder, ImageFormat, ImageReader, Limits, RgbImage,
};
const WIDTH: u32 = 256;
const HEIGHT: u32 = 256;
@ -58,7 +60,7 @@ fn load_through_reader(
format: ImageFormat,
limits: Limits,
) -> Result<image::DynamicImage, image::ImageError> {
let mut reader = image::io::Reader::new(Cursor::new(input));
let mut reader = ImageReader::new(Cursor::new(input));
reader.set_format(format);
reader.limits(limits);
reader.decode()
@ -74,7 +76,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::io::Reader
// image::ImageReader
assert!(load_through_reader(&image, ImageFormat::Gif, width_height_limits()).is_err());
assert!(load_through_reader(&image, ImageFormat::Gif, allocation_limits()).is_err()); // BROKEN!
@ -104,7 +106,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::io::Reader
// image::ImageReader
assert!(load_through_reader(&image, ImageFormat::Png, width_height_limits()).is_err());
assert!(load_through_reader(&image, ImageFormat::Png, allocation_limits()).is_err());
@ -131,7 +133,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::io::Reader
// image::ImageReader
assert!(load_through_reader(&image, ImageFormat::Jpeg, width_height_limits()).is_err());
assert!(load_through_reader(&image, ImageFormat::Jpeg, allocation_limits()).is_err());
@ -151,7 +153,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::io::Reader
// image::ImageReader
assert!(load_through_reader(&image, ImageFormat::WebP, width_height_limits()).is_err());
assert!(load_through_reader(&image, ImageFormat::WebP, allocation_limits()).is_err());
@ -178,7 +180,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::io::Reader
// image::ImageReader
assert!(load_through_reader(&image, ImageFormat::Tiff, width_height_limits()).is_err());
assert!(load_through_reader(&image, ImageFormat::Tiff, allocation_limits()).is_err());
@ -198,7 +200,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::io::Reader
// image::ImageReader
assert!(load_through_reader(&image, ImageFormat::Avif, width_height_limits()).is_err());
assert!(load_through_reader(&image, ImageFormat::Avif, allocation_limits()).is_err());
@ -218,7 +220,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::io::Reader
// image::ImageReader
assert!(load_through_reader(&image, ImageFormat::Bmp, width_height_limits()).is_err());
assert!(load_through_reader(&image, ImageFormat::Bmp, allocation_limits()).is_err());

View file

@ -1,6 +1,6 @@
//! Test enforcement of size and memory limits for animation decoding APIs.
use image::{io::Limits, AnimationDecoder, ImageDecoder, ImageResult};
use image::{AnimationDecoder, ImageDecoder, ImageResult, Limits};
#[cfg(feature = "gif")]
use image::codecs::gif::GifDecoder;

View file

@ -5,6 +5,7 @@ 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";
@ -185,7 +186,7 @@ fn check_references() {
match case.kind {
ReferenceTestKind::AnimatedFrame { frame: frame_num } => {
let format = image::io::Reader::open(&img_path)
let format = ImageReader::open(&img_path)
.unwrap()
.with_guessed_format()
.unwrap()