Skip to content

Commit

Permalink
Rename Reader to ImageReader (#2243)
Browse files Browse the repository at this point in the history
  • Loading branch information
ripytide authored May 27, 2024
1 parent d48c6a6 commit 6d5918f
Show file tree
Hide file tree
Showing 10 changed files with 48 additions and 54 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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()?;
Expand Down
2 changes: 1 addition & 1 deletion fuzz/fuzzers/fuzzer_script_exr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
20 changes: 7 additions & 13 deletions src/dynimage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand All @@ -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);
Expand Down
8 changes: 3 additions & 5 deletions src/io/free_functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -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()
}
Expand Down
26 changes: 13 additions & 13 deletions src/io/reader.rs → src/io/image_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(()) }
/// ```
Expand All @@ -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;
Expand All @@ -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));
Expand All @@ -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.
Expand All @@ -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,
Expand All @@ -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(),
Expand All @@ -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(),
Expand Down Expand Up @@ -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(()) }
Expand Down Expand Up @@ -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.
Expand All @@ -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(),
Expand Down
4 changes: 2 additions & 2 deletions src/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
11 changes: 5 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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];
//!
Expand Down Expand Up @@ -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
//!
Expand Down Expand Up @@ -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;

Expand All @@ -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;

Expand Down Expand Up @@ -290,6 +288,7 @@ mod buffer_par;
mod color;
mod dynimage;
mod image;
mod io;
mod traits;
mod utils;

Expand Down
22 changes: 12 additions & 10 deletions tests/limits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,17 @@
//! 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.
//!
//! These tests also don't cover animation (yet). Adding tests for that would be very welcome too.

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;
Expand Down Expand Up @@ -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()
Expand All @@ -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!

Expand Down Expand Up @@ -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());

Expand All @@ -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());

Expand All @@ -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());

Expand All @@ -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());

Expand All @@ -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());

Expand All @@ -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());

Expand Down
2 changes: 1 addition & 1 deletion tests/limits_anim.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
3 changes: 2 additions & 1 deletion tests/reference_images.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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()
Expand Down

0 comments on commit 6d5918f

Please sign in to comment.