mirror of
https://github.com/Cykooz/fast_image_resize.git
synced 2026-10-08 01:11:09 +00:00
- Extracted helping code for testing into separate crate.
- Optimized convolution of U16 images with help of AVX2.
This commit is contained in:
Generated
+13
-4
@@ -395,6 +395,7 @@ dependencies = [
|
||||
"png",
|
||||
"resize",
|
||||
"rgb",
|
||||
"testing",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
@@ -695,9 +696,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libz-sys"
|
||||
version = "1.1.6"
|
||||
version = "1.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92e7e15d7610cce1d9752e137625f14e61a28cd45929b6e12e47b50fe154ee2e"
|
||||
checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
@@ -867,9 +868,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.11.0"
|
||||
version = "1.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b10983b38c53aebdf33f542c6275b0f58a238129d00c4ae0e6fb59738d783ca"
|
||||
checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225"
|
||||
|
||||
[[package]]
|
||||
name = "open"
|
||||
@@ -1196,6 +1197,14 @@ dependencies = [
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "testing"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"fast_image_resize",
|
||||
"image",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.31"
|
||||
|
||||
+7
-5
@@ -1,3 +1,9 @@
|
||||
[workspace]
|
||||
members = [
|
||||
"testing",
|
||||
]
|
||||
|
||||
|
||||
[package]
|
||||
name = "fast_image_resize"
|
||||
version = "0.9.2"
|
||||
@@ -25,6 +31,7 @@ resize = "0.7.2"
|
||||
rgb = "0.8.32"
|
||||
png = "0.17.5"
|
||||
nix = { version = "0.24.1", default-features = false, features = ["sched"] }
|
||||
testing = {path= "testing" }
|
||||
|
||||
|
||||
[[bench]]
|
||||
@@ -47,11 +54,6 @@ name = "bench_compare_rgb16"
|
||||
harness = false
|
||||
|
||||
|
||||
[[bench]]
|
||||
name = "bench_compare_rgbx"
|
||||
harness = false
|
||||
|
||||
|
||||
[[bench]]
|
||||
name = "bench_compare_rgba"
|
||||
harness = false
|
||||
|
||||
@@ -12,34 +12,16 @@ about resizing with respect to color space._
|
||||
|
||||
Supported pixel formats and available optimisations:
|
||||
|
||||
- `U8` - one `u8` component per pixel:
|
||||
- native Rust-code without forced SIMD
|
||||
- SSE4.1 (partial)
|
||||
- AVX2
|
||||
- `U8x2` - two `u8` components per pixel (e.g. LA):
|
||||
- native Rust-code without forced SIMD
|
||||
- SSE4.1
|
||||
- AVX2
|
||||
- `U8x3` - three `u8` components per pixel (e.g. RGB):
|
||||
- native Rust-code without forced SIMD
|
||||
- SSE4.1 (partial)
|
||||
- AVX2
|
||||
- `U8x4` - four `u8` components per pixel (RGBA, RGBx, CMYK and other):
|
||||
- native Rust-code without forced SIMD
|
||||
- SSE4.1
|
||||
- AVX2
|
||||
- `U16` - one `u16` components per pixel (e.g. L16):
|
||||
- native Rust-code without forced SIMD
|
||||
- SSE4.1
|
||||
- AVX2
|
||||
- `U16x3` - three `u16` components per pixel (e.g. RGB):
|
||||
- native Rust-code without forced SIMD
|
||||
- SSE4.1
|
||||
- AVX2
|
||||
- `I32` - one `i32` component per pixel:
|
||||
- native Rust-code without forced SIMD
|
||||
- `F32` - one `f32` component per pixel:
|
||||
- native Rust-code without forced SIMD
|
||||
| Format | Description | Native Rust | SSE4.1 | AVX2 |
|
||||
|:------:|:-----------------------------------------------------------|:-----------:|:-------:|:----:|
|
||||
| U8 | One `u8` component per pixel (e.g. L) | + | partial | + |
|
||||
| U8x2 | Two `u8` components per pixel (e.g. LA) | + | + | + |
|
||||
| U8x3 | Three `u8` components per pixel (e.g. RGB) | + | partial | + |
|
||||
| U8x4 | Four `u8` components per pixel (e.g. RGBA, RGBx, CMYK) | + | + | + |
|
||||
| U16 | One `u16` components per pixel (e.g. L16) | + | + | + |
|
||||
| U16x3 | Three `u16` components per pixel (e.g. RGB16) | + | + | + |
|
||||
| I32 | One `i32` component per pixel | + | - | - |
|
||||
| F32 | One `f32` component per pixel | + | - | - |
|
||||
|
||||
## Benchmarks
|
||||
|
||||
@@ -49,13 +31,13 @@ Environment:
|
||||
- RAM: DDR4 3800 MHz
|
||||
- Ubuntu 22.04 (linux 5.15.0)
|
||||
- Rust 1.61.0
|
||||
- fast_image_resize = "0.10.0"
|
||||
- fast_image_resize = "0.9.3"
|
||||
- glassbench = "0.3.1"
|
||||
- `rustflags = ["-C", "llvm-args=-x86-branches-within-32B-boundaries"]`
|
||||
|
||||
Other Rust libraries used to compare of resizing speed:
|
||||
|
||||
- image = "0.24.1" (<https://crates.io/crates/image>)
|
||||
- image = "0.24.2" (<https://crates.io/crates/image>)
|
||||
- resize = "0.7.2" (<https://crates.io/crates/resize>)
|
||||
|
||||
Resize algorithms:
|
||||
|
||||
@@ -6,13 +6,15 @@ use resize::Pixel::Gray8;
|
||||
use rgb::alt::Gray;
|
||||
use rgb::FromSlice;
|
||||
|
||||
use fast_image_resize::pixels::U8;
|
||||
use fast_image_resize::Image;
|
||||
use fast_image_resize::{CpuExtensions, FilterType, PixelType, ResizeAlg, Resizer};
|
||||
use fast_image_resize::{CpuExtensions, FilterType, ResizeAlg, Resizer};
|
||||
use testing::PixelExt;
|
||||
|
||||
mod utils;
|
||||
|
||||
pub fn bench_downscale_l(bench: &mut Bench) {
|
||||
let src_image = utils::get_big_luma8_image();
|
||||
let src_image = U8::load_big_image().to_luma8();
|
||||
let new_width = NonZeroU32::new(852).unwrap();
|
||||
let new_height = NonZeroU32::new(567).unwrap();
|
||||
|
||||
@@ -76,16 +78,9 @@ pub fn bench_downscale_l(bench: &mut Bench) {
|
||||
}
|
||||
for (cpu_ext, ext_name) in cpu_ext_and_name {
|
||||
for alg_name in alg_names {
|
||||
let src_rgba_image = utils::get_big_luma8_image();
|
||||
let src_image_data = Image::from_vec_u8(
|
||||
NonZeroU32::new(src_image.width()).unwrap(),
|
||||
NonZeroU32::new(src_image.height()).unwrap(),
|
||||
src_rgba_image.into_raw(),
|
||||
PixelType::U8,
|
||||
)
|
||||
.unwrap();
|
||||
let src_image_data = U8::load_big_src_image();
|
||||
let src_view = src_image_data.view();
|
||||
let mut dst_image = Image::new(new_width, new_height, PixelType::U8);
|
||||
let mut dst_image = Image::new(new_width, new_height, src_view.pixel_type());
|
||||
let mut dst_view = dst_image.view_mut();
|
||||
|
||||
let resize_alg = match alg_name {
|
||||
|
||||
@@ -6,13 +6,15 @@ use resize::Pixel::Gray16;
|
||||
use rgb::alt::Gray;
|
||||
use rgb::FromSlice;
|
||||
|
||||
use fast_image_resize::pixels::U16;
|
||||
use fast_image_resize::Image;
|
||||
use fast_image_resize::{CpuExtensions, FilterType, PixelType, ResizeAlg, Resizer};
|
||||
use fast_image_resize::{CpuExtensions, FilterType, ResizeAlg, Resizer};
|
||||
use testing::PixelExt;
|
||||
|
||||
mod utils;
|
||||
|
||||
pub fn bench_downscale_l16(bench: &mut Bench) {
|
||||
let src_image = utils::get_big_luma16_image();
|
||||
let src_image = U16::load_big_image().to_luma16();
|
||||
let new_width = NonZeroU32::new(852).unwrap();
|
||||
let new_height = NonZeroU32::new(567).unwrap();
|
||||
|
||||
@@ -76,19 +78,9 @@ pub fn bench_downscale_l16(bench: &mut Bench) {
|
||||
}
|
||||
for (cpu_ext, ext_name) in cpu_ext_and_name {
|
||||
for alg_name in alg_names {
|
||||
let src_image_data = Image::from_vec_u8(
|
||||
NonZeroU32::new(src_image.width()).unwrap(),
|
||||
NonZeroU32::new(src_image.height()).unwrap(),
|
||||
src_image
|
||||
.as_raw()
|
||||
.iter()
|
||||
.flat_map(|&c| c.to_le_bytes())
|
||||
.collect(),
|
||||
PixelType::U16,
|
||||
)
|
||||
.unwrap();
|
||||
let src_image_data = U16::load_big_src_image();
|
||||
let src_view = src_image_data.view();
|
||||
let mut dst_image = Image::new(new_width, new_height, src_image_data.pixel_type());
|
||||
let mut dst_image = Image::new(new_width, new_height, src_view.pixel_type());
|
||||
let mut dst_view = dst_image.view_mut();
|
||||
|
||||
let resize_alg = match alg_name {
|
||||
|
||||
@@ -3,12 +3,14 @@ use std::num::NonZeroU32;
|
||||
use glassbench::*;
|
||||
use image::imageops;
|
||||
|
||||
use fast_image_resize::pixels::U8x2;
|
||||
use fast_image_resize::{CpuExtensions, FilterType, Image, MulDiv, PixelType, ResizeAlg, Resizer};
|
||||
use testing::PixelExt;
|
||||
|
||||
mod utils;
|
||||
|
||||
pub fn bench_downscale_la(bench: &mut Bench) {
|
||||
let src_image = &utils::get_big_la_image();
|
||||
let src_image = U8x2::load_big_image().to_luma_alpha8();
|
||||
let new_width = NonZeroU32::new(852).unwrap();
|
||||
let new_height = NonZeroU32::new(567).unwrap();
|
||||
|
||||
@@ -26,7 +28,7 @@ pub fn bench_downscale_la(bench: &mut Bench) {
|
||||
};
|
||||
bench.task(format!("image - {}", alg_name), |task| {
|
||||
task.iter(|| {
|
||||
imageops::resize(src_image, new_width.get(), new_height.get(), filter);
|
||||
imageops::resize(&src_image, new_width.get(), new_height.get(), filter);
|
||||
})
|
||||
});
|
||||
}
|
||||
@@ -47,18 +49,12 @@ pub fn bench_downscale_la(bench: &mut Bench) {
|
||||
"Lanczos3" => ResizeAlg::Convolution(FilterType::Lanczos3),
|
||||
_ => return,
|
||||
};
|
||||
let src_image_data = Image::from_vec_u8(
|
||||
NonZeroU32::new(src_image.width()).unwrap(),
|
||||
NonZeroU32::new(src_image.height()).unwrap(),
|
||||
src_image.as_raw().clone(),
|
||||
PixelType::U8x2,
|
||||
)
|
||||
.unwrap();
|
||||
let src_image_data = U8x2::load_big_src_image();
|
||||
let src_view = src_image_data.view();
|
||||
let mut premultiplied_src_image = Image::new(
|
||||
NonZeroU32::new(src_image.width()).unwrap(),
|
||||
NonZeroU32::new(src_image.height()).unwrap(),
|
||||
PixelType::U8x2,
|
||||
src_view.pixel_type(),
|
||||
);
|
||||
let mut dst_image = Image::new(new_width, new_height, PixelType::U8x2);
|
||||
let mut dst_view = dst_image.view_mut();
|
||||
|
||||
@@ -5,13 +5,15 @@ use image::imageops;
|
||||
use resize::Pixel::RGB8;
|
||||
use rgb::{FromSlice, RGB};
|
||||
|
||||
use fast_image_resize::pixels::U8x3;
|
||||
use fast_image_resize::Image;
|
||||
use fast_image_resize::{CpuExtensions, FilterType, PixelType, ResizeAlg, Resizer};
|
||||
use fast_image_resize::{CpuExtensions, FilterType, ResizeAlg, Resizer};
|
||||
use testing::PixelExt;
|
||||
|
||||
mod utils;
|
||||
|
||||
pub fn bench_downscale_rgb(bench: &mut Bench) {
|
||||
let src_image = utils::get_big_rgb_image();
|
||||
let src_image = U8x3::load_big_image().to_rgb8();
|
||||
let new_width = NonZeroU32::new(852).unwrap();
|
||||
let new_height = NonZeroU32::new(567).unwrap();
|
||||
|
||||
@@ -75,16 +77,9 @@ pub fn bench_downscale_rgb(bench: &mut Bench) {
|
||||
}
|
||||
for (cpu_ext, ext_name) in cpu_ext_and_name {
|
||||
for alg_name in alg_names {
|
||||
let src_buffer = src_image.as_raw();
|
||||
let src_image_data = Image::from_vec_u8(
|
||||
NonZeroU32::new(src_image.width()).unwrap(),
|
||||
NonZeroU32::new(src_image.height()).unwrap(),
|
||||
src_buffer.clone(),
|
||||
PixelType::U8x3,
|
||||
)
|
||||
.unwrap();
|
||||
let src_image_data = U8x3::load_big_src_image();
|
||||
let src_view = src_image_data.view();
|
||||
let mut dst_image = Image::new(new_width, new_height, PixelType::U8x3);
|
||||
let mut dst_image = Image::new(new_width, new_height, src_view.pixel_type());
|
||||
let mut dst_view = dst_image.view_mut();
|
||||
|
||||
let resize_alg = match alg_name {
|
||||
|
||||
@@ -2,16 +2,18 @@ use std::num::NonZeroU32;
|
||||
|
||||
use glassbench::*;
|
||||
use image::imageops;
|
||||
use resize::Pixel::{RGB16, RGB8};
|
||||
use resize::Pixel::RGB16;
|
||||
use rgb::{FromSlice, RGB};
|
||||
|
||||
use fast_image_resize::pixels::U16x3;
|
||||
use fast_image_resize::Image;
|
||||
use fast_image_resize::{CpuExtensions, FilterType, PixelType, ResizeAlg, Resizer};
|
||||
use fast_image_resize::{CpuExtensions, FilterType, ResizeAlg, Resizer};
|
||||
use testing::PixelExt;
|
||||
|
||||
mod utils;
|
||||
|
||||
pub fn bench_downscale_rgb16(bench: &mut Bench) {
|
||||
let src_image = utils::get_big_rgb16_image();
|
||||
let src_image = U16x3::load_big_image().to_rgb16();
|
||||
let new_width = NonZeroU32::new(852).unwrap();
|
||||
let new_height = NonZeroU32::new(567).unwrap();
|
||||
|
||||
@@ -68,11 +70,7 @@ pub fn bench_downscale_rgb16(bench: &mut Bench) {
|
||||
}
|
||||
|
||||
// fast_image_resize crate;
|
||||
let src_buffer: Vec<u8> = src_image
|
||||
.as_raw()
|
||||
.iter()
|
||||
.flat_map(|&c| c.to_le_bytes())
|
||||
.collect();
|
||||
let src_image_data = U16x3::load_big_src_image();
|
||||
let mut cpu_ext_and_name = vec![(CpuExtensions::None, "rust")];
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
{
|
||||
@@ -81,15 +79,8 @@ pub fn bench_downscale_rgb16(bench: &mut Bench) {
|
||||
}
|
||||
for (cpu_ext, ext_name) in cpu_ext_and_name {
|
||||
for alg_name in alg_names {
|
||||
let src_image_data = Image::from_vec_u8(
|
||||
NonZeroU32::new(src_image.width()).unwrap(),
|
||||
NonZeroU32::new(src_image.height()).unwrap(),
|
||||
src_buffer.clone(),
|
||||
PixelType::U16x3,
|
||||
)
|
||||
.unwrap();
|
||||
let src_view = src_image_data.view();
|
||||
let mut dst_image = Image::new(new_width, new_height, src_image_data.pixel_type());
|
||||
let mut dst_image = Image::new(new_width, new_height, src_view.pixel_type());
|
||||
let mut dst_view = dst_image.view_mut();
|
||||
|
||||
let resize_alg = match alg_name {
|
||||
|
||||
@@ -6,12 +6,14 @@ use resize::px::RGBA;
|
||||
use resize::Pixel::RGBA8;
|
||||
use rgb::FromSlice;
|
||||
|
||||
use fast_image_resize::{CpuExtensions, FilterType, Image, MulDiv, PixelType, ResizeAlg, Resizer};
|
||||
use fast_image_resize::pixels::U8x4;
|
||||
use fast_image_resize::{CpuExtensions, FilterType, Image, MulDiv, ResizeAlg, Resizer};
|
||||
use testing::PixelExt;
|
||||
|
||||
mod utils;
|
||||
|
||||
pub fn bench_downscale_rgba(bench: &mut Bench) {
|
||||
let src_image = &utils::get_big_rgba_image();
|
||||
let src_image = U8x4::load_big_image().to_rgba8();
|
||||
let new_width = NonZeroU32::new(852).unwrap();
|
||||
let new_height = NonZeroU32::new(567).unwrap();
|
||||
|
||||
@@ -29,7 +31,7 @@ pub fn bench_downscale_rgba(bench: &mut Bench) {
|
||||
};
|
||||
bench.task(format!("image - {}", alg_name), |task| {
|
||||
task.iter(|| {
|
||||
imageops::resize(src_image, new_width.get(), new_height.get(), filter);
|
||||
imageops::resize(&src_image, new_width.get(), new_height.get(), filter);
|
||||
})
|
||||
});
|
||||
}
|
||||
@@ -67,6 +69,7 @@ pub fn bench_downscale_rgba(bench: &mut Bench) {
|
||||
}
|
||||
|
||||
// fast_image_resize crate;
|
||||
let src_image_data = U8x4::load_big_src_image();
|
||||
let mut cpu_ext_and_name = vec![(CpuExtensions::None, "rust")];
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
{
|
||||
@@ -82,20 +85,13 @@ pub fn bench_downscale_rgba(bench: &mut Bench) {
|
||||
"Lanczos3" => ResizeAlg::Convolution(FilterType::Lanczos3),
|
||||
_ => return,
|
||||
};
|
||||
let src_image_data = Image::from_vec_u8(
|
||||
NonZeroU32::new(src_image.width()).unwrap(),
|
||||
NonZeroU32::new(src_image.height()).unwrap(),
|
||||
src_image.as_raw().clone(),
|
||||
PixelType::U8x4,
|
||||
)
|
||||
.unwrap();
|
||||
let src_view = src_image_data.view();
|
||||
let mut premultiplied_src_image = Image::new(
|
||||
NonZeroU32::new(src_image.width()).unwrap(),
|
||||
NonZeroU32::new(src_image.height()).unwrap(),
|
||||
PixelType::U8x4,
|
||||
src_view.pixel_type(),
|
||||
);
|
||||
let mut dst_image = Image::new(new_width, new_height, PixelType::U8x4);
|
||||
let mut dst_image = Image::new(new_width, new_height, src_view.pixel_type());
|
||||
let mut dst_view = dst_image.view_mut();
|
||||
let mut mul_div = MulDiv::default();
|
||||
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use glassbench::*;
|
||||
|
||||
use fast_image_resize::Image;
|
||||
use fast_image_resize::{CpuExtensions, FilterType, PixelType, ResizeAlg, Resizer};
|
||||
|
||||
mod utils;
|
||||
|
||||
pub fn bench_downscale_rgbx(bench: &mut Bench) {
|
||||
let src_image = utils::get_big_rgb_image();
|
||||
let new_width = NonZeroU32::new(852).unwrap();
|
||||
let new_height = NonZeroU32::new(567).unwrap();
|
||||
|
||||
let alg_names = ["Nearest", "Bilinear", "CatmullRom", "Lanczos3"];
|
||||
|
||||
// fast_image_resize crate;
|
||||
let mut cpu_ext_and_name = vec![(CpuExtensions::None, "rust")];
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
{
|
||||
cpu_ext_and_name.push((CpuExtensions::Sse4_1, "sse4.1"));
|
||||
cpu_ext_and_name.push((CpuExtensions::Avx2, "avx2"));
|
||||
}
|
||||
for (cpu_ext, ext_name) in cpu_ext_and_name {
|
||||
for alg_name in alg_names {
|
||||
let src_rgba_image = utils::get_big_rgba_image();
|
||||
let src_image_data = Image::from_vec_u8(
|
||||
NonZeroU32::new(src_image.width()).unwrap(),
|
||||
NonZeroU32::new(src_image.height()).unwrap(),
|
||||
src_rgba_image.into_raw(),
|
||||
PixelType::U8x4,
|
||||
)
|
||||
.unwrap();
|
||||
let src_view = src_image_data.view();
|
||||
let mut dst_image = Image::new(new_width, new_height, PixelType::U8x4);
|
||||
let mut dst_view = dst_image.view_mut();
|
||||
|
||||
let resize_alg = match alg_name {
|
||||
"Nearest" => ResizeAlg::Nearest,
|
||||
"Bilinear" => ResizeAlg::Convolution(FilterType::Bilinear),
|
||||
"CatmullRom" => ResizeAlg::Convolution(FilterType::CatmullRom),
|
||||
"Lanczos3" => ResizeAlg::Convolution(FilterType::Lanczos3),
|
||||
_ => return,
|
||||
};
|
||||
let mut fast_resizer = Resizer::new(resize_alg);
|
||||
|
||||
unsafe {
|
||||
fast_resizer.reset_internal_buffers();
|
||||
fast_resizer.set_cpu_extensions(cpu_ext);
|
||||
}
|
||||
|
||||
bench.task(format!("fir {} - {}", ext_name, alg_name), |task| {
|
||||
task.iter(|| {
|
||||
fast_resizer.resize(&src_view, &mut dst_view).unwrap();
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
utils::print_md_table(bench);
|
||||
}
|
||||
|
||||
bench_main!("Compare resize of RGBx image", bench_downscale_rgbx,);
|
||||
+48
-268
@@ -2,115 +2,18 @@ use std::num::NonZeroU32;
|
||||
|
||||
use glassbench::*;
|
||||
|
||||
use fast_image_resize::pixels::*;
|
||||
use fast_image_resize::Image;
|
||||
use fast_image_resize::{CpuExtensions, FilterType, PixelType, ResizeAlg, Resizer};
|
||||
use testing::{cpu_ext_into_str, PixelExt};
|
||||
|
||||
mod utils;
|
||||
|
||||
const NEW_WIDTH: u32 = 852;
|
||||
const NEW_HEIGHT: u32 = 567;
|
||||
|
||||
const NEW_BIG_WIDTH: u32 = 4928;
|
||||
const NEW_BIG_HEIGHT: u32 = 3279;
|
||||
|
||||
fn get_big_source_image() -> Image<'static> {
|
||||
let img = utils::get_big_rgba_image();
|
||||
let width = img.width();
|
||||
let height = img.height();
|
||||
Image::from_vec_u8(
|
||||
NonZeroU32::new(width).unwrap(),
|
||||
NonZeroU32::new(height).unwrap(),
|
||||
img.into_raw(),
|
||||
PixelType::U8x4,
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn get_big_u8x2_source_image() -> Image<'static> {
|
||||
let img = utils::get_big_luma_alpha8_image();
|
||||
let width = img.width();
|
||||
let height = img.height();
|
||||
Image::from_vec_u8(
|
||||
NonZeroU32::new(width).unwrap(),
|
||||
NonZeroU32::new(height).unwrap(),
|
||||
img.into_raw(),
|
||||
PixelType::U8x2,
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn get_big_u8x3_source_image() -> Image<'static> {
|
||||
let img = utils::get_big_rgb_image();
|
||||
let width = img.width();
|
||||
let height = img.height();
|
||||
Image::from_vec_u8(
|
||||
NonZeroU32::new(width).unwrap(),
|
||||
NonZeroU32::new(height).unwrap(),
|
||||
img.into_raw(),
|
||||
PixelType::U8x3,
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn get_big_u16x3_source_image() -> Image<'static> {
|
||||
let img = utils::get_big_rgb16_image();
|
||||
let width = img.width();
|
||||
let height = img.height();
|
||||
Image::from_vec_u8(
|
||||
NonZeroU32::new(width).unwrap(),
|
||||
NonZeroU32::new(height).unwrap(),
|
||||
img.as_raw().iter().flat_map(|&c| c.to_le_bytes()).collect(),
|
||||
PixelType::U16x3,
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn get_big_i32_image() -> Image<'static> {
|
||||
let img = utils::get_big_luma16_image();
|
||||
let img_data: Vec<u8> = img
|
||||
.as_raw()
|
||||
.iter()
|
||||
.flat_map(|&p| (p as u32 * (i16::MAX as u32 + 1)).to_le_bytes())
|
||||
.collect();
|
||||
let width = img.width();
|
||||
let height = img.height();
|
||||
Image::from_vec_u8(
|
||||
NonZeroU32::new(width).unwrap(),
|
||||
NonZeroU32::new(height).unwrap(),
|
||||
img_data,
|
||||
PixelType::I32,
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn get_big_u8_image() -> Image<'static> {
|
||||
let img = utils::get_big_luma8_image();
|
||||
let width = img.width();
|
||||
let height = img.height();
|
||||
Image::from_vec_u8(
|
||||
NonZeroU32::new(width).unwrap(),
|
||||
NonZeroU32::new(height).unwrap(),
|
||||
img.into_raw(),
|
||||
PixelType::U8,
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn get_small_source_image() -> Image<'static> {
|
||||
let img = utils::get_small_rgba_image();
|
||||
let width = img.width();
|
||||
let height = img.height();
|
||||
Image::from_vec_u8(
|
||||
NonZeroU32::new(width).unwrap(),
|
||||
NonZeroU32::new(height).unwrap(),
|
||||
img.into_raw(),
|
||||
PixelType::U8x4,
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn native_nearest_u8x4_bench(bench: &mut Bench) {
|
||||
let image = get_big_source_image();
|
||||
let image = U8x4::load_big_src_image();
|
||||
let mut res_image = Image::new(
|
||||
NonZeroU32::new(NEW_WIDTH).unwrap(),
|
||||
NonZeroU32::new(NEW_HEIGHT).unwrap(),
|
||||
@@ -129,8 +32,12 @@ fn native_nearest_u8x4_bench(bench: &mut Bench) {
|
||||
});
|
||||
}
|
||||
|
||||
fn u8x4_lanczos3_bench(bench: &mut Bench, cpu_extensions: CpuExtensions, name: &str) {
|
||||
let image = get_big_source_image();
|
||||
fn downscale_bench(
|
||||
bench: &mut Bench,
|
||||
image: &Image<'static>,
|
||||
cpu_extensions: CpuExtensions,
|
||||
filter_type: FilterType,
|
||||
) {
|
||||
let mut res_image = Image::new(
|
||||
NonZeroU32::new(NEW_WIDTH).unwrap(),
|
||||
NonZeroU32::new(NEW_HEIGHT).unwrap(),
|
||||
@@ -138,93 +45,17 @@ fn u8x4_lanczos3_bench(bench: &mut Bench, cpu_extensions: CpuExtensions, name: &
|
||||
);
|
||||
let src_image = image.view();
|
||||
let mut dst_image = res_image.view_mut();
|
||||
let mut resizer = Resizer::new(ResizeAlg::Convolution(FilterType::Lanczos3));
|
||||
let mut resizer = Resizer::new(ResizeAlg::Convolution(filter_type));
|
||||
unsafe {
|
||||
resizer.set_cpu_extensions(cpu_extensions);
|
||||
}
|
||||
bench.task(name, |task| {
|
||||
task.iter(|| {
|
||||
resizer.resize(&src_image, &mut dst_image).unwrap();
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
fn avx2_supersampling_lanczos3_bench(bench: &mut Bench) {
|
||||
let image = get_big_source_image();
|
||||
let mut res_image = Image::new(
|
||||
NonZeroU32::new(NEW_WIDTH).unwrap(),
|
||||
NonZeroU32::new(NEW_HEIGHT).unwrap(),
|
||||
let bench_name = &format!(
|
||||
"{:?}-{:?}-{}",
|
||||
image.pixel_type(),
|
||||
filter_type,
|
||||
cpu_ext_into_str(cpu_extensions),
|
||||
);
|
||||
let src_image = image.view();
|
||||
let mut dst_image = res_image.view_mut();
|
||||
let mut resizer = Resizer::new(ResizeAlg::SuperSampling(FilterType::Lanczos3, 2));
|
||||
unsafe {
|
||||
resizer.set_cpu_extensions(CpuExtensions::Avx2);
|
||||
}
|
||||
bench.task("supersampling lanczos3 avx2", |task| {
|
||||
task.iter(|| {
|
||||
resizer.resize(&src_image, &mut dst_image).unwrap();
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
fn avx2_lanczos3_upscale_bench(bench: &mut Bench) {
|
||||
let image = get_small_source_image();
|
||||
let mut res_image = Image::new(
|
||||
NonZeroU32::new(NEW_BIG_WIDTH).unwrap(),
|
||||
NonZeroU32::new(NEW_BIG_HEIGHT).unwrap(),
|
||||
image.pixel_type(),
|
||||
);
|
||||
let src_image = image.view();
|
||||
let mut dst_image = res_image.view_mut();
|
||||
let mut resizer = Resizer::new(ResizeAlg::Convolution(FilterType::Lanczos3));
|
||||
unsafe {
|
||||
resizer.set_cpu_extensions(CpuExtensions::Avx2);
|
||||
}
|
||||
bench.task("lanczos3 upscale avx2", |task| {
|
||||
task.iter(|| {
|
||||
resizer.resize(&src_image, &mut dst_image).unwrap();
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn native_lanczos3_i32_bench(bench: &mut Bench) {
|
||||
let image = get_big_i32_image();
|
||||
let mut res_image = Image::new(
|
||||
NonZeroU32::new(NEW_WIDTH).unwrap(),
|
||||
NonZeroU32::new(NEW_HEIGHT).unwrap(),
|
||||
image.pixel_type(),
|
||||
);
|
||||
let src_image = image.view();
|
||||
let mut dst_image = res_image.view_mut();
|
||||
let mut resizer = Resizer::new(ResizeAlg::Convolution(FilterType::Lanczos3));
|
||||
unsafe {
|
||||
resizer.set_cpu_extensions(CpuExtensions::None);
|
||||
}
|
||||
bench.task("i32 lanczos3 wo SIMD", |task| {
|
||||
task.iter(|| {
|
||||
resizer.resize(&src_image, &mut dst_image).unwrap();
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn u8_lanczos3_bench(bench: &mut Bench, cpu_extensions: CpuExtensions, name: &str) {
|
||||
let image = get_big_u8_image();
|
||||
let mut res_image = Image::new(
|
||||
NonZeroU32::new(NEW_WIDTH).unwrap(),
|
||||
NonZeroU32::new(NEW_HEIGHT).unwrap(),
|
||||
image.pixel_type(),
|
||||
);
|
||||
let src_image = image.view();
|
||||
let mut dst_image = res_image.view_mut();
|
||||
let mut resizer = Resizer::new(ResizeAlg::Convolution(FilterType::Lanczos3));
|
||||
unsafe {
|
||||
resizer.set_cpu_extensions(cpu_extensions);
|
||||
}
|
||||
bench.task(name, |task| {
|
||||
bench.task(bench_name, |task| {
|
||||
task.iter(|| {
|
||||
resizer.resize(&src_image, &mut dst_image).unwrap();
|
||||
})
|
||||
@@ -232,7 +63,7 @@ fn u8_lanczos3_bench(bench: &mut Bench, cpu_extensions: CpuExtensions, name: &st
|
||||
}
|
||||
|
||||
fn native_nearest_u8_bench(bench: &mut Bench) {
|
||||
let image = get_big_u8_image();
|
||||
let image = U8::load_big_src_image();
|
||||
let mut res_image = Image::new(
|
||||
NonZeroU32::new(NEW_WIDTH).unwrap(),
|
||||
NonZeroU32::new(NEW_HEIGHT).unwrap(),
|
||||
@@ -251,66 +82,6 @@ fn native_nearest_u8_bench(bench: &mut Bench) {
|
||||
});
|
||||
}
|
||||
|
||||
fn u8x3_lanczos3_bench(bench: &mut Bench, cpu_extensions: CpuExtensions, name: &str) {
|
||||
let image = get_big_u8x3_source_image();
|
||||
let mut res_image = Image::new(
|
||||
NonZeroU32::new(NEW_WIDTH).unwrap(),
|
||||
NonZeroU32::new(NEW_HEIGHT).unwrap(),
|
||||
image.pixel_type(),
|
||||
);
|
||||
let src_image = image.view();
|
||||
let mut dst_image = res_image.view_mut();
|
||||
let mut resizer = Resizer::new(ResizeAlg::Convolution(FilterType::Lanczos3));
|
||||
unsafe {
|
||||
resizer.set_cpu_extensions(cpu_extensions);
|
||||
}
|
||||
bench.task(name, |task| {
|
||||
task.iter(|| {
|
||||
resizer.resize(&src_image, &mut dst_image).unwrap();
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn u16x3_lanczos3_bench(bench: &mut Bench, cpu_extensions: CpuExtensions, name: &str) {
|
||||
let image = get_big_u16x3_source_image();
|
||||
let mut res_image = Image::new(
|
||||
NonZeroU32::new(NEW_WIDTH).unwrap(),
|
||||
NonZeroU32::new(NEW_HEIGHT).unwrap(),
|
||||
image.pixel_type(),
|
||||
);
|
||||
let src_image = image.view();
|
||||
let mut dst_image = res_image.view_mut();
|
||||
let mut resizer = Resizer::new(ResizeAlg::Convolution(FilterType::Lanczos3));
|
||||
unsafe {
|
||||
resizer.set_cpu_extensions(cpu_extensions);
|
||||
}
|
||||
bench.task(name, |task| {
|
||||
task.iter(|| {
|
||||
resizer.resize(&src_image, &mut dst_image).unwrap();
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn u8x2_lanczos3_bench(bench: &mut Bench, cpu_extensions: CpuExtensions, name: &str) {
|
||||
let image = get_big_u8x2_source_image();
|
||||
let mut res_image = Image::new(
|
||||
NonZeroU32::new(NEW_WIDTH).unwrap(),
|
||||
NonZeroU32::new(NEW_HEIGHT).unwrap(),
|
||||
image.pixel_type(),
|
||||
);
|
||||
let src_image = image.view();
|
||||
let mut dst_image = res_image.view_mut();
|
||||
let mut resizer = Resizer::new(ResizeAlg::Convolution(FilterType::Lanczos3));
|
||||
unsafe {
|
||||
resizer.set_cpu_extensions(cpu_extensions);
|
||||
}
|
||||
bench.task(name, |task| {
|
||||
task.iter(|| {
|
||||
resizer.resize(&src_image, &mut dst_image).unwrap();
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
// Pin process to #0 CPU core
|
||||
let mut cpu_set = nix::sched::CpuSet::new();
|
||||
@@ -322,32 +93,41 @@ pub fn main() {
|
||||
let cmd = Command::read();
|
||||
if cmd.include_bench(name) {
|
||||
let mut bench = create_bench(name, "Resize", &cmd);
|
||||
|
||||
let pixel_types = [
|
||||
PixelType::U8,
|
||||
PixelType::U8x2,
|
||||
PixelType::U8x3,
|
||||
PixelType::U8x4,
|
||||
PixelType::U16,
|
||||
PixelType::U16x3,
|
||||
PixelType::I32,
|
||||
];
|
||||
let mut cpu_extensions = vec![CpuExtensions::None];
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
{
|
||||
cpu_extensions.push(CpuExtensions::Sse4_1);
|
||||
cpu_extensions.push(CpuExtensions::Avx2);
|
||||
}
|
||||
for pixel_type in pixel_types {
|
||||
for &cpu_extension in cpu_extensions.iter() {
|
||||
let image = match pixel_type {
|
||||
PixelType::U8 => U8::load_big_src_image(),
|
||||
PixelType::U8x2 => U8x2::load_big_src_image(),
|
||||
PixelType::U8x3 => U8x3::load_big_src_image(),
|
||||
PixelType::U8x4 => U8x4::load_big_src_image(),
|
||||
PixelType::U16 => U16::load_big_src_image(),
|
||||
PixelType::U16x3 => U16x3::load_big_src_image(),
|
||||
PixelType::I32 => I32::load_big_src_image(),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
downscale_bench(&mut bench, &image, cpu_extension, FilterType::Lanczos3);
|
||||
}
|
||||
}
|
||||
|
||||
native_nearest_u8x4_bench(&mut bench);
|
||||
native_nearest_u8_bench(&mut bench);
|
||||
|
||||
u8_lanczos3_bench(&mut bench, CpuExtensions::None, "u8 lanczos3 wo SIMD");
|
||||
u8x3_lanczos3_bench(&mut bench, CpuExtensions::None, "u8x3 lanczos3 wo SIMD");
|
||||
u8x4_lanczos3_bench(&mut bench, CpuExtensions::None, "u8x4 lanczos3 wo SIMD");
|
||||
u16x3_lanczos3_bench(&mut bench, CpuExtensions::None, "u16x3 lanczos3 wo SIMD");
|
||||
native_lanczos3_i32_bench(&mut bench);
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
{
|
||||
u8_lanczos3_bench(&mut bench, CpuExtensions::Sse4_1, "u8 lanczos3 sse4.1");
|
||||
u8_lanczos3_bench(&mut bench, CpuExtensions::Avx2, "u8 lanczos3 avx2");
|
||||
|
||||
u8x2_lanczos3_bench(&mut bench, CpuExtensions::Avx2, "u8x2 lanczos3 avx2");
|
||||
|
||||
u8x3_lanczos3_bench(&mut bench, CpuExtensions::Sse4_1, "u8x3 lanczos3 sse4.1");
|
||||
u8x3_lanczos3_bench(&mut bench, CpuExtensions::Avx2, "u8x3 lanczos3 avx2");
|
||||
u16x3_lanczos3_bench(&mut bench, CpuExtensions::Sse4_1, "u16x3 lanczos3 sse4.1");
|
||||
u16x3_lanczos3_bench(&mut bench, CpuExtensions::Avx2, "u16x3 lanczos3 avx2");
|
||||
|
||||
u8x4_lanczos3_bench(&mut bench, CpuExtensions::Sse4_1, "u8x4 lanczos3 sse4.1");
|
||||
u8x4_lanczos3_bench(&mut bench, CpuExtensions::Avx2, "u8x4 lanczos3 avx2");
|
||||
|
||||
avx2_supersampling_lanczos3_bench(&mut bench);
|
||||
avx2_lanczos3_upscale_bench(&mut bench);
|
||||
}
|
||||
if let Err(e) = after_bench(&mut bench, &cmd) {
|
||||
eprintln!("{:?}", e);
|
||||
}
|
||||
|
||||
@@ -1,83 +1,6 @@
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
|
||||
use glassbench::*;
|
||||
use image::io::Reader;
|
||||
use image::{GrayAlphaImage, GrayImage, ImageBuffer, Luma, Rgb, RgbImage, RgbaImage};
|
||||
|
||||
pub type Rgb16Image = ImageBuffer<Rgb<u16>, Vec<u16>>;
|
||||
|
||||
pub fn get_big_rgb_image() -> RgbImage {
|
||||
let cur_dir = env::current_dir().unwrap();
|
||||
let img = Reader::open(cur_dir.join("data/nasa-4928x3279.png"))
|
||||
.unwrap()
|
||||
.decode()
|
||||
.unwrap();
|
||||
img.to_rgb8()
|
||||
}
|
||||
|
||||
pub fn get_big_rgb16_image() -> Rgb16Image {
|
||||
let cur_dir = env::current_dir().unwrap();
|
||||
let img = Reader::open(cur_dir.join("data/nasa-4928x3279.png"))
|
||||
.unwrap()
|
||||
.decode()
|
||||
.unwrap();
|
||||
img.to_rgb16()
|
||||
}
|
||||
|
||||
pub fn get_big_rgba_image() -> RgbaImage {
|
||||
let cur_dir = env::current_dir().unwrap();
|
||||
let img = Reader::open(cur_dir.join("data/nasa-4928x3279-rgba.png"))
|
||||
.unwrap()
|
||||
.decode()
|
||||
.unwrap();
|
||||
img.to_rgba8()
|
||||
}
|
||||
|
||||
pub fn get_big_luma_alpha8_image() -> GrayAlphaImage {
|
||||
let cur_dir = env::current_dir().unwrap();
|
||||
let img = Reader::open(cur_dir.join("data/nasa-4928x3279-rgba.png"))
|
||||
.unwrap()
|
||||
.decode()
|
||||
.unwrap();
|
||||
img.to_luma_alpha8()
|
||||
}
|
||||
|
||||
pub fn get_big_luma16_image() -> ImageBuffer<Luma<u16>, Vec<u16>> {
|
||||
let cur_dir = env::current_dir().unwrap();
|
||||
let img = Reader::open(cur_dir.join("data/nasa-4928x3279.png"))
|
||||
.unwrap()
|
||||
.decode()
|
||||
.unwrap();
|
||||
img.to_luma16()
|
||||
}
|
||||
|
||||
pub fn get_big_luma8_image() -> GrayImage {
|
||||
let cur_dir = env::current_dir().unwrap();
|
||||
let img = Reader::open(cur_dir.join("data/nasa-4928x3279.png"))
|
||||
.unwrap()
|
||||
.decode()
|
||||
.unwrap();
|
||||
img.to_luma8()
|
||||
}
|
||||
|
||||
pub fn get_big_la_image() -> GrayAlphaImage {
|
||||
let cur_dir = env::current_dir().unwrap();
|
||||
let img = Reader::open(cur_dir.join("data/nasa-4928x3279-rgba.png"))
|
||||
.unwrap()
|
||||
.decode()
|
||||
.unwrap();
|
||||
img.to_luma_alpha8()
|
||||
}
|
||||
|
||||
pub fn get_small_rgba_image() -> RgbaImage {
|
||||
let cur_dir = env::current_dir().unwrap();
|
||||
let img = Reader::open(cur_dir.join("data/nasa-852x567.png"))
|
||||
.unwrap()
|
||||
.decode()
|
||||
.unwrap();
|
||||
img.to_rgba8()
|
||||
}
|
||||
|
||||
pub fn print_md_table(bench: &Bench) {
|
||||
let mut res_map: HashMap<String, Vec<String>> = HashMap::new();
|
||||
|
||||
@@ -106,113 +106,106 @@ unsafe fn horiz_convolution_four_rows(
|
||||
|
||||
for (dst_x, coeffs_chunk) in coefficients_chunks.iter().enumerate() {
|
||||
let mut x: usize = coeffs_chunk.start as usize;
|
||||
let mut ll_sum = [_mm256_set1_epi64x(0); 4];
|
||||
let mut ll_sum = [_mm256_set1_epi64x(0); 2];
|
||||
|
||||
let mut coeffs = coeffs_chunk.values;
|
||||
|
||||
let coeffs_by_16 = coeffs.chunks_exact(16);
|
||||
coeffs = coeffs_by_16.remainder();
|
||||
|
||||
for k in coeffs_by_16 {
|
||||
let coeff0189_i64x4 =
|
||||
_mm256_set_epi64x(k[9] as i64, k[8] as i64, k[1] as i64, k[0] as i64);
|
||||
let coeff23ab_i64x2 =
|
||||
_mm256_set_epi64x(k[11] as i64, k[10] as i64, k[3] as i64, k[2] as i64);
|
||||
let coeff45cd_i64x2 =
|
||||
_mm256_set_epi64x(k[13] as i64, k[12] as i64, k[5] as i64, k[4] as i64);
|
||||
let coeff67ef_i64x2 =
|
||||
_mm256_set_epi64x(k[15] as i64, k[14] as i64, k[7] as i64, k[6] as i64);
|
||||
|
||||
for i in 0..4 {
|
||||
let mut sum = ll_sum[i];
|
||||
let source = simd_utils::loadu_si256(s_rows[i], x);
|
||||
|
||||
let l0l1_i64x4 = _mm256_shuffle_epi8(source, l0l1_shuffle);
|
||||
sum = _mm256_add_epi64(sum, _mm256_mul_epi32(l0l1_i64x4, coeff0189_i64x4));
|
||||
|
||||
let l2l3_i64x4 = _mm256_shuffle_epi8(source, l2l3_shuffle);
|
||||
sum = _mm256_add_epi64(sum, _mm256_mul_epi32(l2l3_i64x4, coeff23ab_i64x2));
|
||||
|
||||
let l4l5_i64x4 = _mm256_shuffle_epi8(source, l4l5_shuffle);
|
||||
sum = _mm256_add_epi64(sum, _mm256_mul_epi32(l4l5_i64x4, coeff45cd_i64x2));
|
||||
|
||||
let l6l7_i64x4 = _mm256_shuffle_epi8(source, l6l7_shuffle);
|
||||
sum = _mm256_add_epi64(sum, _mm256_mul_epi32(l6l7_i64x4, coeff67ef_i64x2));
|
||||
|
||||
ll_sum[i] = sum;
|
||||
}
|
||||
x += 16;
|
||||
}
|
||||
|
||||
let coeffs_by_8 = coeffs.chunks_exact(8);
|
||||
coeffs = coeffs_by_8.remainder();
|
||||
|
||||
for k in coeffs_by_8 {
|
||||
let coeff0145_i64x4 =
|
||||
_mm256_set_epi64x(k[5] as i64, k[4] as i64, k[1] as i64, k[0] as i64);
|
||||
let coeff2367_i64x2 =
|
||||
_mm256_set_epi64x(k[7] as i64, k[6] as i64, k[3] as i64, k[2] as i64);
|
||||
let coeff01_i64x4 =
|
||||
_mm256_set_epi64x(k[1] as i64, k[0] as i64, k[1] as i64, k[0] as i64);
|
||||
let coeff23_i64x4 =
|
||||
_mm256_set_epi64x(k[3] as i64, k[2] as i64, k[3] as i64, k[2] as i64);
|
||||
let coeff45_i64x4 =
|
||||
_mm256_set_epi64x(k[5] as i64, k[4] as i64, k[5] as i64, k[4] as i64);
|
||||
let coeff67_i64x4 =
|
||||
_mm256_set_epi64x(k[7] as i64, k[6] as i64, k[7] as i64, k[6] as i64);
|
||||
|
||||
for i in 0..4 {
|
||||
let mut sum = ll_sum[i];
|
||||
for (i, sum) in ll_sum.iter_mut().enumerate() {
|
||||
let source = _mm256_set_m128i(
|
||||
simd_utils::loadl_epi64(s_rows[i], x + 4),
|
||||
simd_utils::loadl_epi64(s_rows[i], x),
|
||||
simd_utils::loadu_si128(s_rows[i * 2 + 1], x),
|
||||
simd_utils::loadu_si128(s_rows[i * 2], x),
|
||||
);
|
||||
|
||||
let l0l1_i64x4 = _mm256_shuffle_epi8(source, l0l1_shuffle);
|
||||
sum = _mm256_add_epi64(sum, _mm256_mul_epi32(l0l1_i64x4, coeff0145_i64x4));
|
||||
*sum = _mm256_add_epi64(*sum, _mm256_mul_epi32(l0l1_i64x4, coeff01_i64x4));
|
||||
|
||||
let l2l3_i64x4 = _mm256_shuffle_epi8(source, l2l3_shuffle);
|
||||
sum = _mm256_add_epi64(sum, _mm256_mul_epi32(l2l3_i64x4, coeff2367_i64x2));
|
||||
*sum = _mm256_add_epi64(*sum, _mm256_mul_epi32(l2l3_i64x4, coeff23_i64x4));
|
||||
|
||||
ll_sum[i] = sum;
|
||||
let l4l5_i64x4 = _mm256_shuffle_epi8(source, l4l5_shuffle);
|
||||
*sum = _mm256_add_epi64(*sum, _mm256_mul_epi32(l4l5_i64x4, coeff45_i64x4));
|
||||
|
||||
let l6l7_i64x4 = _mm256_shuffle_epi8(source, l6l7_shuffle);
|
||||
*sum = _mm256_add_epi64(*sum, _mm256_mul_epi32(l6l7_i64x4, coeff67_i64x4));
|
||||
}
|
||||
x += 8;
|
||||
}
|
||||
|
||||
let coeffs_by_4 = coeffs.chunks_exact(4);
|
||||
coeffs = coeffs_by_4.remainder();
|
||||
|
||||
for k in coeffs_by_4 {
|
||||
let coeff0123_i64x4 =
|
||||
_mm256_set_epi64x(k[3] as i64, k[2] as i64, k[1] as i64, k[0] as i64);
|
||||
let coeff01_i64x4 =
|
||||
_mm256_set_epi64x(k[1] as i64, k[0] as i64, k[1] as i64, k[0] as i64);
|
||||
let coeff23_i64x4 =
|
||||
_mm256_set_epi64x(k[3] as i64, k[2] as i64, k[3] as i64, k[2] as i64);
|
||||
|
||||
for i in 0..4 {
|
||||
for (i, sum) in ll_sum.iter_mut().enumerate() {
|
||||
let source = _mm256_set_m128i(
|
||||
simd_utils::loadl_epi32(s_rows[i], x + 2),
|
||||
simd_utils::loadl_epi32(s_rows[i], x),
|
||||
simd_utils::loadl_epi64(s_rows[i * 2 + 1], x),
|
||||
simd_utils::loadl_epi64(s_rows[i * 2], x),
|
||||
);
|
||||
|
||||
let l0l1_i64x4 = _mm256_shuffle_epi8(source, l0l1_shuffle);
|
||||
ll_sum[i] =
|
||||
_mm256_add_epi64(ll_sum[i], _mm256_mul_epi32(l0l1_i64x4, coeff0123_i64x4));
|
||||
*sum = _mm256_add_epi64(*sum, _mm256_mul_epi32(l0l1_i64x4, coeff01_i64x4));
|
||||
|
||||
let l2l3_i64x4 = _mm256_shuffle_epi8(source, l2l3_shuffle);
|
||||
*sum = _mm256_add_epi64(*sum, _mm256_mul_epi32(l2l3_i64x4, coeff23_i64x4));
|
||||
}
|
||||
x += 4;
|
||||
}
|
||||
|
||||
if !coeffs.is_empty() {
|
||||
let mut coeffs_x3: [i64; 4] = [0; 4];
|
||||
for (d_coeff, &s_coeff) in coeffs_x3.iter_mut().zip(coeffs) {
|
||||
*d_coeff = s_coeff as i64;
|
||||
}
|
||||
let coeff0123_i64x4 = simd_utils::loadu_si256(&coeffs_x3, 0);
|
||||
let coeffs_by_2 = coeffs.chunks_exact(2);
|
||||
coeffs = coeffs_by_2.remainder();
|
||||
for k in coeffs_by_2 {
|
||||
let coeff01_i64x4 =
|
||||
_mm256_set_epi64x(k[1] as i64, k[0] as i64, k[1] as i64, k[0] as i64);
|
||||
|
||||
for i in 0..4 {
|
||||
let mut pixels: [i64; 4] = [0; 4];
|
||||
let src_row = s_rows[i];
|
||||
for (i, pixel) in pixels.iter_mut().take(coeffs.len()).enumerate() {
|
||||
*pixel = (*src_row.get_unchecked(x + i)).0 as i64;
|
||||
}
|
||||
let source = simd_utils::loadu_si256(&pixels, 0);
|
||||
ll_sum[i] = _mm256_add_epi64(ll_sum[i], _mm256_mul_epi32(source, coeff0123_i64x4));
|
||||
for (i, sum) in ll_sum.iter_mut().enumerate() {
|
||||
let source = _mm256_set_m128i(
|
||||
simd_utils::loadl_epi32(s_rows[i * 2 + 1], x),
|
||||
simd_utils::loadl_epi32(s_rows[i * 2], x),
|
||||
);
|
||||
|
||||
let l0l1_i64x4 = _mm256_shuffle_epi8(source, l0l1_shuffle);
|
||||
*sum = _mm256_add_epi64(*sum, _mm256_mul_epi32(l0l1_i64x4, coeff01_i64x4));
|
||||
}
|
||||
x += 2;
|
||||
}
|
||||
|
||||
for &k in coeffs {
|
||||
let coeff0_i64x4 = _mm256_set1_epi64x(k as i64);
|
||||
|
||||
for (i, sum) in ll_sum.iter_mut().enumerate() {
|
||||
let source = _mm256_set_epi64x(
|
||||
0,
|
||||
s_rows[i * 2 + 1].get_unchecked(x).0 as i64,
|
||||
0,
|
||||
s_rows[i * 2].get_unchecked(x).0 as i64,
|
||||
);
|
||||
*sum = _mm256_add_epi64(*sum, _mm256_mul_epi32(source, coeff0_i64x4));
|
||||
}
|
||||
}
|
||||
|
||||
for i in 0..4 {
|
||||
_mm256_storeu_si256((&mut ll_buf).as_mut_ptr() as *mut __m256i, ll_sum[i]);
|
||||
let dst_pixel = d_rows[i].get_unchecked_mut(dst_x);
|
||||
dst_pixel.0 = normalizer_guard.clip(ll_buf.iter().sum::<i64>() + half_error);
|
||||
// ll_sum.into_iter().enumerate() executes slowly than ll_sum.iter().enumerate()
|
||||
for (i, &ll) in ll_sum.iter().enumerate() {
|
||||
_mm256_storeu_si256((&mut ll_buf).as_mut_ptr() as *mut __m256i, ll);
|
||||
let dst_pixel = d_rows[i * 2].get_unchecked_mut(dst_x);
|
||||
dst_pixel.0 = normalizer_guard.clip(ll_buf[0] + ll_buf[1] + half_error);
|
||||
|
||||
let dst_pixel = d_rows[i * 2 + 1].get_unchecked_mut(dst_x);
|
||||
dst_pixel.0 = normalizer_guard.clip(ll_buf[2] + ll_buf[3] + half_error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -277,15 +270,14 @@ unsafe fn horiz_convolution_one_row(
|
||||
|
||||
let coeffs_by_16 = coeffs.chunks_exact(16);
|
||||
coeffs = coeffs_by_16.remainder();
|
||||
|
||||
for k in coeffs_by_16 {
|
||||
let coeff0189_i64x4 =
|
||||
_mm256_set_epi64x(k[9] as i64, k[8] as i64, k[1] as i64, k[0] as i64);
|
||||
let coeff23ab_i64x2 =
|
||||
let coeff23ab_i64x4 =
|
||||
_mm256_set_epi64x(k[11] as i64, k[10] as i64, k[3] as i64, k[2] as i64);
|
||||
let coeff45cd_i64x2 =
|
||||
let coeff45cd_i64x4 =
|
||||
_mm256_set_epi64x(k[13] as i64, k[12] as i64, k[5] as i64, k[4] as i64);
|
||||
let coeff67ef_i64x2 =
|
||||
let coeff67ef_i64x4 =
|
||||
_mm256_set_epi64x(k[15] as i64, k[14] as i64, k[7] as i64, k[6] as i64);
|
||||
|
||||
let source = simd_utils::loadu_si256(src_row, x);
|
||||
@@ -294,24 +286,23 @@ unsafe fn horiz_convolution_one_row(
|
||||
ll_sum = _mm256_add_epi64(ll_sum, _mm256_mul_epi32(l0l1_i64x4, coeff0189_i64x4));
|
||||
|
||||
let l2l3_i64x4 = _mm256_shuffle_epi8(source, l2l3_shuffle);
|
||||
ll_sum = _mm256_add_epi64(ll_sum, _mm256_mul_epi32(l2l3_i64x4, coeff23ab_i64x2));
|
||||
ll_sum = _mm256_add_epi64(ll_sum, _mm256_mul_epi32(l2l3_i64x4, coeff23ab_i64x4));
|
||||
|
||||
let l4l5_i64x4 = _mm256_shuffle_epi8(source, l4l5_shuffle);
|
||||
ll_sum = _mm256_add_epi64(ll_sum, _mm256_mul_epi32(l4l5_i64x4, coeff45cd_i64x2));
|
||||
ll_sum = _mm256_add_epi64(ll_sum, _mm256_mul_epi32(l4l5_i64x4, coeff45cd_i64x4));
|
||||
|
||||
let l6l7_i64x4 = _mm256_shuffle_epi8(source, l6l7_shuffle);
|
||||
ll_sum = _mm256_add_epi64(ll_sum, _mm256_mul_epi32(l6l7_i64x4, coeff67ef_i64x2));
|
||||
ll_sum = _mm256_add_epi64(ll_sum, _mm256_mul_epi32(l6l7_i64x4, coeff67ef_i64x4));
|
||||
|
||||
x += 16;
|
||||
}
|
||||
|
||||
let coeffs_by_8 = coeffs.chunks_exact(8);
|
||||
coeffs = coeffs_by_8.remainder();
|
||||
|
||||
for k in coeffs_by_8 {
|
||||
let coeff0145_i64x4 =
|
||||
_mm256_set_epi64x(k[5] as i64, k[4] as i64, k[1] as i64, k[0] as i64);
|
||||
let coeff2367_i64x2 =
|
||||
let coeff2367_i64x4 =
|
||||
_mm256_set_epi64x(k[7] as i64, k[6] as i64, k[3] as i64, k[2] as i64);
|
||||
|
||||
let source = _mm256_set_m128i(
|
||||
@@ -323,14 +314,13 @@ unsafe fn horiz_convolution_one_row(
|
||||
ll_sum = _mm256_add_epi64(ll_sum, _mm256_mul_epi32(l0l1_i64x4, coeff0145_i64x4));
|
||||
|
||||
let l2l3_i64x4 = _mm256_shuffle_epi8(source, l2l3_shuffle);
|
||||
ll_sum = _mm256_add_epi64(ll_sum, _mm256_mul_epi32(l2l3_i64x4, coeff2367_i64x2));
|
||||
ll_sum = _mm256_add_epi64(ll_sum, _mm256_mul_epi32(l2l3_i64x4, coeff2367_i64x4));
|
||||
|
||||
x += 8;
|
||||
}
|
||||
|
||||
let coeffs_by_4 = coeffs.chunks_exact(4);
|
||||
coeffs = coeffs_by_4.remainder();
|
||||
|
||||
for k in coeffs_by_4 {
|
||||
let coeff0123_i64x4 =
|
||||
_mm256_set_epi64x(k[3] as i64, k[2] as i64, k[1] as i64, k[0] as i64);
|
||||
@@ -346,20 +336,20 @@ unsafe fn horiz_convolution_one_row(
|
||||
x += 4;
|
||||
}
|
||||
|
||||
if !coeffs.is_empty() {
|
||||
let mut coeffs_x4: [i64; 4] = [0; 4];
|
||||
for (d_coeff, &s_coeff) in coeffs_x4.iter_mut().zip(coeffs) {
|
||||
*d_coeff = s_coeff as i64;
|
||||
}
|
||||
let coeff0123_i64x4 = simd_utils::loadu_si256(&coeffs_x4, 0);
|
||||
let coeffs_by_2 = coeffs.chunks_exact(2);
|
||||
coeffs = coeffs_by_2.remainder();
|
||||
for k in coeffs_by_2 {
|
||||
let coeff01_i64x4 = _mm256_set_epi64x(0, 0, k[1] as i64, k[0] as i64);
|
||||
let source = _mm256_set_m128i(_mm_setzero_si128(), simd_utils::loadl_epi32(src_row, x));
|
||||
let l0l1_i64x4 = _mm256_shuffle_epi8(source, l0l1_shuffle);
|
||||
ll_sum = _mm256_add_epi64(ll_sum, _mm256_mul_epi32(l0l1_i64x4, coeff01_i64x4));
|
||||
x += 2;
|
||||
}
|
||||
|
||||
let mut pixels: [i64; 4] = [0; 4];
|
||||
for pixel in pixels.iter_mut().take(coeffs.len()) {
|
||||
*pixel = (*src_row.get_unchecked(x)).0 as i64;
|
||||
x += 1;
|
||||
}
|
||||
let source = simd_utils::loadu_si256(&pixels, 0);
|
||||
ll_sum = _mm256_add_epi64(ll_sum, _mm256_mul_epi32(source, coeff0123_i64x4));
|
||||
for &k in coeffs {
|
||||
let coeff0_i64x4 = _mm256_set1_epi64x(k as i64);
|
||||
let source = _mm256_set_epi64x(0, 0, 0, src_row.get_unchecked(x).0 as i64);
|
||||
ll_sum = _mm256_add_epi64(ll_sum, _mm256_mul_epi32(source, coeff0_i64x4));
|
||||
}
|
||||
|
||||
_mm256_storeu_si256((&mut ll_buf).as_mut_ptr() as *mut __m256i, ll_sum);
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "testing"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
fast_image_resize = {path=".."}
|
||||
image = "0.24.2"
|
||||
@@ -38,11 +38,15 @@ pub trait PixelExt: Pixel {
|
||||
}
|
||||
}
|
||||
|
||||
fn load_big_src_image() -> Image<'static> {
|
||||
let img = ImageReader::open("./data/nasa-4928x3279.png")
|
||||
fn load_big_image() -> DynamicImage {
|
||||
ImageReader::open("./data/nasa-4928x3279.png")
|
||||
.unwrap()
|
||||
.decode()
|
||||
.unwrap();
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn load_big_src_image() -> Image<'static> {
|
||||
let img = Self::load_big_image();
|
||||
Image::from_vec_u8(
|
||||
NonZeroU32::new(img.width()).unwrap(),
|
||||
NonZeroU32::new(img.height()).unwrap(),
|
||||
@@ -52,25 +56,15 @@ pub trait PixelExt: Pixel {
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn load_small_image() -> DynamicImage {
|
||||
ImageReader::open("./data/nasa-852x567.png")
|
||||
.unwrap()
|
||||
.decode()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn load_small_src_image() -> Image<'static> {
|
||||
let img = ImageReader::open("./data/nasa-852x567.png")
|
||||
.unwrap()
|
||||
.decode()
|
||||
.unwrap();
|
||||
Image::from_vec_u8(
|
||||
NonZeroU32::new(img.width()).unwrap(),
|
||||
NonZeroU32::new(img.height()).unwrap(),
|
||||
Self::img_into_bytes(img),
|
||||
Self::pixel_type(),
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn load_small_rgba_image() -> Image<'static> {
|
||||
let img = ImageReader::open("./data/nasa-852x567-rgba.png")
|
||||
.unwrap()
|
||||
.decode()
|
||||
.unwrap();
|
||||
let img = Self::load_small_image();
|
||||
Image::from_vec_u8(
|
||||
NonZeroU32::new(img.width()).unwrap(),
|
||||
NonZeroU32::new(img.height()).unwrap(),
|
||||
@@ -102,6 +96,20 @@ impl PixelExt for U8x3 {
|
||||
}
|
||||
|
||||
impl PixelExt for U8x4 {
|
||||
fn load_big_image() -> DynamicImage {
|
||||
ImageReader::open("./data/nasa-4928x3279-rgba.png")
|
||||
.unwrap()
|
||||
.decode()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn load_small_image() -> DynamicImage {
|
||||
ImageReader::open("./data/nasa-852x567-rgba.png")
|
||||
.unwrap()
|
||||
.decode()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn img_into_bytes(img: DynamicImage) -> Vec<u8> {
|
||||
img.to_rgba8().into_raw()
|
||||
}
|
||||
@@ -163,12 +171,12 @@ pub fn save_result(image: &Image, name: &str) {
|
||||
std::fs::create_dir_all("./data/result").unwrap();
|
||||
let path = format!("./data/result/{}.png", name);
|
||||
let color_type = match image.pixel_type() {
|
||||
PixelType::U8 => ColorType::L8,
|
||||
PixelType::U8x2 => ColorType::La8,
|
||||
PixelType::U8x3 => ColorType::Rgb8,
|
||||
PixelType::U8x4 => ColorType::Rgba8,
|
||||
PixelType::U16 => ColorType::L16,
|
||||
PixelType::U16x3 => ColorType::Rgb16,
|
||||
PixelType::U8 => ColorType::L8,
|
||||
_ => panic!("Unsupported type of pixels"),
|
||||
};
|
||||
image::save_buffer(
|
||||
@@ -4,9 +4,6 @@ use fast_image_resize::pixels::{Pixel, U8x2, U8x4};
|
||||
use fast_image_resize::{
|
||||
CpuExtensions, Image, ImageRows, ImageRowsMut, ImageView, ImageViewMut, MulDiv, PixelType,
|
||||
};
|
||||
use utils::{cpu_ext_into_str, image_checksum};
|
||||
|
||||
mod utils;
|
||||
|
||||
trait IntoImageRows
|
||||
where
|
||||
@@ -339,10 +336,13 @@ fn multiply_alpha_real_image_test() {
|
||||
.multiply_alpha(&src_image.view(), &mut dst_image.view_mut())
|
||||
.unwrap();
|
||||
|
||||
let name = format!("multiple_alpha-{}", cpu_ext_into_str(cpu_extensions));
|
||||
utils::save_result(&dst_image, &name);
|
||||
let name = format!(
|
||||
"multiple_alpha-{}",
|
||||
testing::cpu_ext_into_str(cpu_extensions)
|
||||
);
|
||||
testing::save_result(&dst_image, &name);
|
||||
|
||||
let checksum = image_checksum::<4>(dst_image.buffer());
|
||||
let checksum = testing::image_checksum::<4>(dst_image.buffer());
|
||||
assert_eq!(checksum, [4177920, 4177920, 4177920, 8355840]);
|
||||
}
|
||||
}
|
||||
@@ -379,10 +379,10 @@ fn divide_alpha_real_image_test() {
|
||||
.divide_alpha(&src_image.view(), &mut dst_image.view_mut())
|
||||
.unwrap();
|
||||
|
||||
let name = format!("divide_alpha-{}", cpu_ext_into_str(cpu_extensions));
|
||||
utils::save_result(&dst_image, &name);
|
||||
let name = format!("divide_alpha-{}", testing::cpu_ext_into_str(cpu_extensions));
|
||||
testing::save_result(&dst_image, &name);
|
||||
|
||||
let checksum = image_checksum::<4>(dst_image.buffer());
|
||||
let checksum = testing::image_checksum::<4>(dst_image.buffer());
|
||||
assert_eq!(checksum, [8292504, 8292504, 8292504, 8355840]);
|
||||
}
|
||||
}
|
||||
|
||||
+33
-44
@@ -5,9 +5,7 @@ use fast_image_resize::{
|
||||
CpuExtensions, DifferentTypesOfPixelsError, FilterType, Image, ImageView, PixelType, ResizeAlg,
|
||||
Resizer,
|
||||
};
|
||||
use utils::{cpu_ext_into_str, PixelExt};
|
||||
|
||||
mod utils;
|
||||
use testing::PixelExt;
|
||||
|
||||
fn get_new_height(src_image: &ImageView, new_width: u32) -> u32 {
|
||||
let scale = new_width as f32 / src_image.width().get() as f32;
|
||||
@@ -69,9 +67,9 @@ fn downscale_test<P: PixelExt>(resize_alg: ResizeAlg, cpu_extensions: CpuExtensi
|
||||
"downscale-{}-{}-{}",
|
||||
P::pixel_type_str(),
|
||||
alg_name,
|
||||
cpu_ext_into_str(cpu_extensions),
|
||||
testing::cpu_ext_into_str(cpu_extensions),
|
||||
);
|
||||
utils::save_result(&result, &name);
|
||||
testing::save_result(&result, &name);
|
||||
result.buffer().to_owned()
|
||||
}
|
||||
|
||||
@@ -112,9 +110,9 @@ fn upscale_test<P: PixelExt>(resize_alg: ResizeAlg, cpu_extensions: CpuExtension
|
||||
"upscale-{}-{}-{}",
|
||||
P::pixel_type_str(),
|
||||
alg_name,
|
||||
cpu_ext_into_str(cpu_extensions),
|
||||
testing::cpu_ext_into_str(cpu_extensions),
|
||||
);
|
||||
utils::save_result(&result, &name);
|
||||
testing::save_result(&result, &name);
|
||||
result.buffer().to_owned()
|
||||
}
|
||||
|
||||
@@ -122,7 +120,7 @@ fn upscale_test<P: PixelExt>(resize_alg: ResizeAlg, cpu_extensions: CpuExtension
|
||||
fn downscale_u8() {
|
||||
type P = U8;
|
||||
let buffer = downscale_test::<P>(ResizeAlg::Nearest, CpuExtensions::None);
|
||||
assert_eq!(utils::image_checksum::<1>(&buffer), [2920348]);
|
||||
assert_eq!(testing::image_checksum::<1>(&buffer), [2920348]);
|
||||
|
||||
let mut cpu_extensions_vec = vec![CpuExtensions::None];
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
@@ -133,7 +131,7 @@ fn downscale_u8() {
|
||||
for cpu_extensions in cpu_extensions_vec {
|
||||
let buffer =
|
||||
downscale_test::<P>(ResizeAlg::Convolution(FilterType::Lanczos3), cpu_extensions);
|
||||
assert_eq!(utils::image_checksum::<1>(&buffer), [2923557]);
|
||||
assert_eq!(testing::image_checksum::<1>(&buffer), [2923557]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,7 +139,7 @@ fn downscale_u8() {
|
||||
fn upscale_u8() {
|
||||
type P = U8;
|
||||
let buffer = upscale_test::<P>(ResizeAlg::Nearest, CpuExtensions::None);
|
||||
assert_eq!(utils::image_checksum::<1>(&buffer), [1148754010]);
|
||||
assert_eq!(testing::image_checksum::<1>(&buffer), [1148754010]);
|
||||
|
||||
let mut cpu_extensions_vec = vec![CpuExtensions::None];
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
@@ -151,7 +149,7 @@ fn upscale_u8() {
|
||||
for cpu_extensions in cpu_extensions_vec {
|
||||
let buffer =
|
||||
upscale_test::<P>(ResizeAlg::Convolution(FilterType::Lanczos3), cpu_extensions);
|
||||
assert_eq!(utils::image_checksum::<1>(&buffer), [1148811406]);
|
||||
assert_eq!(testing::image_checksum::<1>(&buffer), [1148811406]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,7 +157,7 @@ fn upscale_u8() {
|
||||
fn downscale_u8x2() {
|
||||
type P = U8x2;
|
||||
let buffer = downscale_test::<P>(ResizeAlg::Nearest, CpuExtensions::None);
|
||||
assert_eq!(utils::image_checksum::<2>(&buffer), [2920348, 11054250]);
|
||||
assert_eq!(testing::image_checksum::<2>(&buffer), [2920348, 11054250]);
|
||||
|
||||
let mut cpu_extensions_vec = vec![CpuExtensions::None];
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
@@ -170,7 +168,7 @@ fn downscale_u8x2() {
|
||||
for cpu_extensions in cpu_extensions_vec {
|
||||
let buffer =
|
||||
downscale_test::<P>(ResizeAlg::Convolution(FilterType::Lanczos3), cpu_extensions);
|
||||
assert_eq!(utils::image_checksum::<2>(&buffer), [2923557, 11054250]);
|
||||
assert_eq!(testing::image_checksum::<2>(&buffer), [2923557, 11054250]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,7 +177,7 @@ fn upscale_u8x2() {
|
||||
type P = U8x2;
|
||||
let buffer = upscale_test::<P>(ResizeAlg::Nearest, CpuExtensions::None);
|
||||
assert_eq!(
|
||||
utils::image_checksum::<2>(&buffer),
|
||||
testing::image_checksum::<2>(&buffer),
|
||||
[1148754010, 4269569040]
|
||||
);
|
||||
|
||||
@@ -193,7 +191,7 @@ fn upscale_u8x2() {
|
||||
let buffer =
|
||||
upscale_test::<P>(ResizeAlg::Convolution(FilterType::Lanczos3), cpu_extensions);
|
||||
assert_eq!(
|
||||
utils::image_checksum::<2>(&buffer),
|
||||
testing::image_checksum::<2>(&buffer),
|
||||
[1148811406, 4269569040]
|
||||
);
|
||||
}
|
||||
@@ -204,7 +202,7 @@ fn downscale_u8x3() {
|
||||
type P = U8x3;
|
||||
let buffer = downscale_test::<P>(ResizeAlg::Nearest, CpuExtensions::None);
|
||||
assert_eq!(
|
||||
utils::image_checksum::<3>(&buffer),
|
||||
testing::image_checksum::<3>(&buffer),
|
||||
[2937940, 2945380, 2882679]
|
||||
);
|
||||
|
||||
@@ -218,7 +216,7 @@ fn downscale_u8x3() {
|
||||
let buffer =
|
||||
downscale_test::<P>(ResizeAlg::Convolution(FilterType::Lanczos3), cpu_extensions);
|
||||
assert_eq!(
|
||||
utils::image_checksum::<3>(&buffer),
|
||||
testing::image_checksum::<3>(&buffer),
|
||||
[2942479, 2947850, 2885072]
|
||||
);
|
||||
}
|
||||
@@ -229,7 +227,7 @@ fn upscale_u8x3() {
|
||||
type P = U8x3;
|
||||
let buffer = upscale_test::<P>(ResizeAlg::Nearest, CpuExtensions::None);
|
||||
assert_eq!(
|
||||
utils::image_checksum::<3>(&buffer),
|
||||
testing::image_checksum::<3>(&buffer),
|
||||
[1156008260, 1158417906, 1135087540]
|
||||
);
|
||||
|
||||
@@ -243,7 +241,7 @@ fn upscale_u8x3() {
|
||||
let buffer =
|
||||
upscale_test::<P>(ResizeAlg::Convolution(FilterType::Lanczos3), cpu_extensions);
|
||||
assert_eq!(
|
||||
utils::image_checksum::<3>(&buffer),
|
||||
testing::image_checksum::<3>(&buffer),
|
||||
[1156107005, 1158443335, 1135101759]
|
||||
);
|
||||
}
|
||||
@@ -254,8 +252,8 @@ fn downscale_u8x4() {
|
||||
type P = U8x4;
|
||||
let buffer = downscale_test::<P>(ResizeAlg::Nearest, CpuExtensions::None);
|
||||
assert_eq!(
|
||||
utils::image_checksum::<4>(&buffer),
|
||||
[2937940, 2945380, 2882679, 11054250]
|
||||
testing::image_checksum::<4>(&buffer),
|
||||
[2937940, 2945380, 2882679, 6121802]
|
||||
);
|
||||
|
||||
let mut cpu_extensions_vec = vec![CpuExtensions::None];
|
||||
@@ -268,8 +266,8 @@ fn downscale_u8x4() {
|
||||
let buffer =
|
||||
downscale_test::<P>(ResizeAlg::Convolution(FilterType::Lanczos3), cpu_extensions);
|
||||
assert_eq!(
|
||||
utils::image_checksum::<4>(&buffer),
|
||||
[2942479, 2947850, 2885072, 11054250]
|
||||
testing::image_checksum::<4>(&buffer),
|
||||
[2942479, 2947850, 2885072, 6122818]
|
||||
);
|
||||
|
||||
downscale_test::<P>(
|
||||
@@ -284,8 +282,8 @@ fn upscale_u8x4() {
|
||||
type P = U8x4;
|
||||
let buffer = upscale_test::<P>(ResizeAlg::Nearest, CpuExtensions::None);
|
||||
assert_eq!(
|
||||
utils::image_checksum::<4>(&buffer),
|
||||
[1156008260, 1158417906, 1135087540, 4269569040]
|
||||
testing::image_checksum::<4>(&buffer),
|
||||
[1155096957, 1152644783, 1123285879, 2364895380]
|
||||
);
|
||||
|
||||
let mut cpu_extensions_vec = vec![CpuExtensions::None];
|
||||
@@ -298,8 +296,8 @@ fn upscale_u8x4() {
|
||||
let buffer =
|
||||
upscale_test::<P>(ResizeAlg::Convolution(FilterType::Lanczos3), cpu_extensions);
|
||||
assert_eq!(
|
||||
utils::image_checksum::<4>(&buffer),
|
||||
[1156107005, 1158443335, 1135101759, 4269569040]
|
||||
testing::image_checksum::<4>(&buffer),
|
||||
[1155201788, 1152688479, 1123328716, 2364890194]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -308,7 +306,7 @@ fn upscale_u8x4() {
|
||||
fn downscale_u16() {
|
||||
type P = U16;
|
||||
let buffer = downscale_test::<P>(ResizeAlg::Nearest, CpuExtensions::None);
|
||||
assert_eq!(utils::image_u16_checksum::<1>(&buffer), [750529436]);
|
||||
assert_eq!(testing::image_u16_checksum::<1>(&buffer), [750529436]);
|
||||
|
||||
let mut cpu_extensions_vec = vec![CpuExtensions::None];
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
@@ -320,7 +318,7 @@ fn downscale_u16() {
|
||||
let buffer =
|
||||
downscale_test::<P>(ResizeAlg::Convolution(FilterType::Lanczos3), cpu_extensions);
|
||||
assert_eq!(
|
||||
utils::image_u16_checksum::<1>(&buffer),
|
||||
testing::image_u16_checksum::<1>(&buffer),
|
||||
[751401243],
|
||||
"Error in checksum for {:?}",
|
||||
cpu_extensions
|
||||
@@ -332,7 +330,7 @@ fn downscale_u16() {
|
||||
fn upscale_u16() {
|
||||
type P = U16;
|
||||
let buffer = upscale_test::<P>(ResizeAlg::Nearest, CpuExtensions::None);
|
||||
assert_eq!(utils::image_u16_checksum::<1>(&buffer), [295229780570]);
|
||||
assert_eq!(testing::image_u16_checksum::<1>(&buffer), [295229780570]);
|
||||
|
||||
let mut cpu_extensions_vec = vec![CpuExtensions::None];
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
@@ -344,7 +342,7 @@ fn upscale_u16() {
|
||||
let buffer =
|
||||
upscale_test::<P>(ResizeAlg::Convolution(FilterType::Lanczos3), cpu_extensions);
|
||||
assert_eq!(
|
||||
utils::image_u16_checksum::<1>(&buffer),
|
||||
testing::image_u16_checksum::<1>(&buffer),
|
||||
[295246940755],
|
||||
"Error in checksum for {:?}",
|
||||
cpu_extensions
|
||||
@@ -357,7 +355,7 @@ fn downscale_u16x3() {
|
||||
type P = U16x3;
|
||||
let buffer = downscale_test::<P>(ResizeAlg::Nearest, CpuExtensions::None);
|
||||
assert_eq!(
|
||||
utils::image_u16_checksum::<3>(&buffer),
|
||||
testing::image_u16_checksum::<3>(&buffer),
|
||||
[755050580, 756962660, 740848503]
|
||||
);
|
||||
|
||||
@@ -371,7 +369,7 @@ fn downscale_u16x3() {
|
||||
let buffer =
|
||||
downscale_test::<P>(ResizeAlg::Convolution(FilterType::Lanczos3), cpu_extensions);
|
||||
assert_eq!(
|
||||
utils::image_u16_checksum::<3>(&buffer),
|
||||
testing::image_u16_checksum::<3>(&buffer),
|
||||
[756269847, 757632467, 741478612]
|
||||
);
|
||||
}
|
||||
@@ -382,7 +380,7 @@ fn upscale_u16x3() {
|
||||
type P = U16x3;
|
||||
let buffer = upscale_test::<P>(ResizeAlg::Nearest, CpuExtensions::None);
|
||||
assert_eq!(
|
||||
utils::image_u16_checksum::<3>(&buffer),
|
||||
testing::image_u16_checksum::<3>(&buffer),
|
||||
[297094122820, 297713401842, 291717497780]
|
||||
);
|
||||
|
||||
@@ -396,17 +394,8 @@ fn upscale_u16x3() {
|
||||
let buffer =
|
||||
upscale_test::<P>(ResizeAlg::Convolution(FilterType::Lanczos3), cpu_extensions);
|
||||
assert_eq!(
|
||||
utils::image_u16_checksum::<3>(&buffer),
|
||||
testing::image_u16_checksum::<3>(&buffer),
|
||||
[297122154090, 297723994984, 291725294637]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// #[test]
|
||||
fn _resize_i32() {
|
||||
type P = I32;
|
||||
downscale_test::<P>(ResizeAlg::Nearest, CpuExtensions::None);
|
||||
for cpu_extensions in [CpuExtensions::None] {
|
||||
downscale_test::<P>(ResizeAlg::Convolution(FilterType::Lanczos3), cpu_extensions);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user