Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

External test data #1557

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@ categories = ["multimedia::images", "multimedia::encoding"]
exclude = [
"src/png/testdata/*",
"examples/*",
"tests/*",
"tests/output",
"tests/images",
"tests/reference",
]


[lib]
name = "image"
path = "./src/lib.rs"
Expand All @@ -31,7 +34,7 @@ jpeg = { package = "jpeg-decoder", version = "0.1.22", default-features = false,
png = { version = "0.16.5", optional = true }
scoped_threadpool = { version = "0.1", optional = true }
tiff = { version = "0.6.0", optional = true }
ravif = { version = "0.7.0", optional = true }
ravif = { version = "0.8.7", optional = true }
rgb = { version = "0.8.25", optional = true }
mp4parse = { version = "0.11.5", optional = true }
dav1d = { version = "0.6.0", optional = true }
Expand All @@ -45,6 +48,7 @@ num-complex = "0.3"
glob = "0.3"
quickcheck = "0.9"
criterion = "0.3"
xtest-data = "0.0.4"

[features]
# TODO: Add "avif" to this list while preparing for 0.24.0
Expand Down
4 changes: 3 additions & 1 deletion src/codecs/bmp/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1478,6 +1478,7 @@ impl<'a, R: 'a + Read + Seek> ImageDecoderExt<'a> for BmpDecoder<R> {

#[cfg(test)]
mod test {
use crate::codecs::test_images;
use super::*;

#[test]
Expand All @@ -1497,7 +1498,8 @@ mod test {

#[test]
fn read_rect() {
let f = std::fs::File::open("tests/images/bmp/images/Core_8_Bit.bmp").unwrap();
let images = test_images("bmp/images");
let f = std::fs::File::open(images.join("Core_8_Bit.bmp")).unwrap();
let mut decoder = super::BmpDecoder::new(f).unwrap();

let mut buf: Vec<u8> = vec![0; 8 * 8 * 3];
Expand Down
20 changes: 8 additions & 12 deletions src/codecs/openexr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,11 +339,7 @@ fn to_image_err(exr_error: Error) -> ImageError {
#[cfg(test)]
mod test {
use super::*;
use std::path::PathBuf;

const BASE_PATH: &[&str] = &[".", "tests", "images", "exr"];


use crate::codecs::test_images;

/// Write an `Rgb32FImage`.
/// Assumes the writer is buffered. In most cases,
Expand Down Expand Up @@ -411,9 +407,9 @@ mod test {

#[cfg(feature = "hdr")]
{
let folder = BASE_PATH.iter().collect::<PathBuf>();
let reference_path = folder.clone().join("overexposed gradient.hdr");
let exr_path = folder.clone().join("overexposed gradient - data window equals display window.exr");
let folder = test_images("exr");
let reference_path = folder.join("overexposed gradient.hdr");
let exr_path = folder.join("overexposed gradient - data window equals display window.exr");

let hdr: Vec<Rgb<f32>> = crate::codecs::hdr::HdrDecoder::new(
std::io::BufReader::new(std::fs::File::open(&reference_path).unwrap())
Expand Down Expand Up @@ -466,7 +462,7 @@ mod test {

#[test]
fn compare_rgba_rgb() {
let exr_path = BASE_PATH.iter().collect::<PathBuf>()
let exr_path = test_images("exr")
.join("overexposed gradient - data window equals display window.exr");

let rgb: Rgb32FImage = read_as_rgb_image_from_file(&exr_path).unwrap();
Expand All @@ -490,9 +486,9 @@ mod test {
// in this test we want to make sure that an
// auto-cropped image will be reproduced to the original.

let exr_path = BASE_PATH.iter().collect::<PathBuf>();
let original = exr_path.clone().join("cropping - uncropped original.exr");
let cropped = exr_path.clone().join("cropping - data window differs display window.exr");
let exr_path = test_images("exr");
let original = exr_path.join("cropping - uncropped original.exr");
let cropped = exr_path.join("cropping - data window differs display window.exr");

// smoke-check that the exr files are actually not the same
{
Expand Down
8 changes: 5 additions & 3 deletions src/codecs/png.rs
Original file line number Diff line number Diff line change
Expand Up @@ -649,12 +649,14 @@ impl Default for FilterType {
#[cfg(test)]
mod tests {
use crate::image::ImageDecoder;
use crate::codecs::test_images;
use std::io::Read;
use super::*;

#[test]
fn ensure_no_decoder_off_by_one() {
let dec = PngDecoder::new(std::fs::File::open("tests/images/png/bugfixes/debug_triangle_corners_widescreen.png").unwrap())
let bugfixes = test_images("png/bugfixes");
let dec = PngDecoder::new(std::fs::File::open(bugfixes.join("debug_triangle_corners_widescreen.png")).unwrap())
.expect("Unable to read PNG file (does it exist?)");

assert_eq![(2000, 1000), dec.dimensions()];
Expand All @@ -678,8 +680,8 @@ mod tests {
#[test]
fn underlying_error() {
use std::error::Error;

let mut not_png = std::fs::read("tests/images/png/bugfixes/debug_triangle_corners_widescreen.png").unwrap();
let bugfixes = test_images("png/bugfixes");
let mut not_png = std::fs::read(bugfixes.join("debug_triangle_corners_widescreen.png")).unwrap();
not_png[0] = 0;

let error = PngDecoder::new(&not_png[..]).err().unwrap();
Expand Down
10 changes: 6 additions & 4 deletions src/dynimage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1392,6 +1392,8 @@ mod bench {

#[cfg(test)]
mod test {
use crate::codecs::test_images;

#[test]
fn test_empty_file() {
assert!(super::load_from_memory(b"").is_err());
Expand All @@ -1400,16 +1402,16 @@ mod test {
#[cfg(feature = "jpeg")]
#[test]
fn image_dimensions() {
let im_path = "./tests/images/jpg/progressive/cat.jpg";
let dims = super::image_dimensions(im_path).unwrap();
let im_path = test_images("jpg/progressive");
let dims = super::image_dimensions(im_path.join("cat.jpg")).unwrap();
assert_eq!(dims, (320, 240));
}

#[cfg(feature = "png")]
#[test]
fn open_16bpc_png() {
let im_path = "./tests/images/png/16bpc/basn6a16.png";
let image = super::open(im_path).unwrap();
let im_path = test_images("png/16bpc");
let image = super::open(im_path.join("basn6a16.png")).unwrap();
assert_eq!(image.color(), super::color::ColorType::Rgba16);
}
}
24 changes: 13 additions & 11 deletions src/imageops/sample.rs
Original file line number Diff line number Diff line change
Expand Up @@ -856,15 +856,17 @@ where
#[cfg(test)]
mod tests {
use super::{resize, FilterType};
use crate::{ImageBuffer, RgbImage};
use crate::{ImageBuffer, RgbImage, codecs::test_images};
#[cfg(feature = "benchmarks")]
use test;

#[bench]
#[cfg(all(feature = "benchmarks", feature = "png"))]
fn bench_resize(b: &mut test::Bencher) {
use std::path::Path;
let img = crate::open(&Path::new("./examples/fractal.png")).unwrap();
use std::path::PathBuf;
let mut img = PathBuf::from("examples/fractal.png");
xtest_data::setup!().rewrite([&mut img]).build();
let img = crate::open(img).unwrap();
b.iter(|| {
test::black_box(resize(&img, 200, 200, FilterType::Nearest));
});
Expand All @@ -880,7 +882,8 @@ mod tests {
#[bench]
#[cfg(all(feature = "benchmarks", feature = "tiff"))]
fn bench_thumbnail(b: &mut test::Bencher) {
let path = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/images/tiff/testsuite/mandrill.tiff");
let testsuite = test_images("tiff/testsuite");
let path = testsuite.join("mandrill.tiff");
let image = crate::open(path).unwrap();
b.iter(|| {
test::black_box(image.thumbnail(256, 256));
Expand All @@ -891,7 +894,8 @@ mod tests {
#[bench]
#[cfg(all(feature = "benchmarks", feature = "tiff"))]
fn bench_thumbnail_upsize(b: &mut test::Bencher) {
let path = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/images/tiff/testsuite/mandrill.tiff");
let testsuite = test_images("tiff/testsuite");
let path = testsuite.join("mandrill.tiff");
let image = crate::open(path).unwrap().thumbnail(256, 256);
b.iter(|| {
test::black_box(image.thumbnail(512, 512));
Expand All @@ -902,7 +906,8 @@ mod tests {
#[bench]
#[cfg(all(feature = "benchmarks", feature = "tiff"))]
fn bench_thumbnail_upsize_irregular(b: &mut test::Bencher) {
let path = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/images/tiff/testsuite/mandrill.tiff");
let testsuite = test_images("tiff/testsuite");
let path = testsuite.join("mandrill.tiff");
let image = crate::open(path).unwrap().thumbnail(193, 193);
b.iter(|| {
test::black_box(image.thumbnail(256, 256));
Expand All @@ -929,11 +934,8 @@ mod tests {
}
}

let path = concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/images/png/transparency/tp1n3p08.png"
);
let img = crate::open(path).unwrap();
let images = test_images("png/transparency");
let img = crate::open(images.join("tp1n3p08.png")).unwrap();
let rgba8 = img.as_rgba8().unwrap();
let filters = &[Nearest, Triangle, CatmullRom, Gaussian, Lanczos3];
for filter in filters {
Expand Down
12 changes: 12 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,18 @@ pub mod codecs {
pub mod webp;
#[cfg(feature = "openexr")]
pub mod openexr;

#[cfg(test)]
pub(crate) fn test_images(kind: &str)
-> impl std::ops::Deref<Target=std::path::Path>
{
const BASE_PATH: &[&str] = &["tests", "images"];
let mut path = BASE_PATH.iter().collect::<std::path::PathBuf>();
path = path.join(kind);
xtest_data::setup!().rewrite([&mut path]).build();
path
}

}

#[cfg(feature = "avif-encoder")]
Expand Down
39 changes: 30 additions & 9 deletions tests/reference_images.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,43 @@ extern crate image;

use std::fs;
use std::io;
use std::path::PathBuf;
use std::path::{Path, PathBuf};
use std::u32;

use crc32fast::Hasher as Crc32;

const BASE_PATH: [&str; 2] = [".", "tests"];
const BASE_PATH: [&str; 1] = ["tests"];
const IMAGE_DIR: &str = "images";
const OUTPUT_DIR: &str = "output";
const REFERENCE_DIR: &str = "reference";

fn process_images<F>(dir: &str, input_decoder: Option<&str>, func: F)
where
F: Fn(&PathBuf, PathBuf, &str),
F: Fn(&Path, PathBuf, &str),
{
let base: PathBuf = BASE_PATH.iter().collect();
let decoders = &["tga", "tiff", "png", "gif", "bmp", "ico", "jpg", "hdr", "pbm", "webp"];
for decoder in decoders {
let mut path = base.clone();
path.push(dir);
path.push(decoder);

let mut xsetup = xtest_data::setup!();
// Ensure those are always available.
let _ = xsetup.add(&base.join(IMAGE_DIR));
let _ = xsetup.add(&base.join(REFERENCE_DIR));

let xbase = xsetup.add(&base.join(dir));
let trees = decoders
.iter()
.map(|decoder| {
let mut base = base.to_owned();
base.push(dir);
base.push(decoder);
xsetup.add(&base)
})
.collect::<Vec<_>>();
let xdata = xsetup.build();

for (decoder, base) in decoders.iter().zip(trees) {
let decoder_base = xdata.path(&base);
let mut path = decoder_base.to_owned();
path.push("**");
path.push(
"*.".to_string() + match input_decoder {
Expand All @@ -34,6 +51,10 @@ where
},
);
let pattern = &*format!("{}", path.display());
let base = xdata
.path(&xbase)
.parent()
.unwrap();
for path in glob::glob(pattern).unwrap().filter_map(Result::ok) {
func(&base, path, decoder)
}
Expand Down Expand Up @@ -63,7 +84,7 @@ fn render_images() {
let mut path: Vec<_> = path.components().collect();
(path.pop().unwrap(), path.pop().unwrap())
};
let mut out_path = base.clone();
let mut out_path = base.to_owned();

out_path.push(OUTPUT_DIR);
out_path.push(decoder);
Expand Down Expand Up @@ -173,7 +194,7 @@ fn check_references() {
let filename_str = filename.as_os_str().to_str().unwrap();
let case: ReferenceTestCase = filename_str.parse().unwrap();

let mut img_path = base.clone();
let mut img_path = base.to_owned();
img_path.push(IMAGE_DIR);
img_path.push(decoder);
img_path.push(testsuite.as_os_str());
Expand Down
7 changes: 4 additions & 3 deletions tests/save_jpeg.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
//! Test saving "default" and specific quality jpeg.
#![cfg(all(feature = "jpeg", feature = "tiff"))]
extern crate image;

use std::path::PathBuf;
use image::{ImageOutputFormat, ImageFormat};

#[test]
fn jqeg_qualitys() {
let img = image::open("tests/images/tiff/testsuite/mandrill.tiff").unwrap();
let mut path = PathBuf::from("tests/images/tiff/testsuite/mandrill.tiff");
xtest_data::setup!().rewrite([&mut path]).build();
let img = image::open(path).unwrap();

let mut default = vec![];
img.write_to(&mut default, ImageFormat::Jpeg).unwrap();
Expand Down