Skip to content

Commit

Permalink
- Fixed benchmarks for resizing images with alpha channel using the `…
Browse files Browse the repository at this point in the history
…resizer` crate.

- Removed `image` crate from benchmarks for resizing images with alpha.
- Added method `Image::copy(&self) -> Image<'static>`.
  • Loading branch information
Cykooz committed Jun 28, 2022
1 parent 891312a commit 5b89090
Show file tree
Hide file tree
Showing 10 changed files with 207 additions and 218 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
@@ -1,6 +1,10 @@
## [Unreleased] - ReleaseDate

- Added support of new type of pixels `PixelType::U16x4`.
- Fixed benchmarks for resizing images with alpha channel using
the `resizer` crate.
- Removed `image` crate from benchmarks for resizing images with alpha.
- Added method `Image::copy(&self) -> Image<'static>`.

## [0.9.5] - 2022-06-22

Expand Down
30 changes: 15 additions & 15 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

55 changes: 28 additions & 27 deletions README.md
Expand Up @@ -16,17 +16,18 @@ about resizing with respect to color space._

Supported pixel formats and available optimisations:

| 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) | + | + | + |
| U16x2 | Two `u16` components per pixel (e.g. LA16) | + | + | + |
| U16x3 | Three `u16` components per pixel (e.g. RGB16) | + | + | + |
| I32 | One `i32` component per pixel | + | - | - |
| F32 | One `f32` component per pixel | + | - | - |
| 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) | + | + | + |
| U16x2 | Two `u16` components per pixel (e.g. LA16) | + | + | + |
| U16x3 | Three `u16` components per pixel (e.g. RGB16) | + | + | + |
| U16x4 | Four `u16` components per pixel (e.g. RGBA16, RGBx16, CMYK16) | + | + | + |
| I32 | One `i32` component per pixel | + | - | - |
| F32 | One `f32` component per pixel | + | - | - |

## Some benchmarks

Expand All @@ -48,11 +49,11 @@ Pipeline:

| | Nearest | Bilinear | CatmullRom | Lanczos3 |
|------------|:-------:|:--------:|:----------:|:--------:|
| image | 19.44 | 83.01 | 153.17 | 208.82 |
| resize | - | 52.13 | 103.37 | 154.10 |
| fir rust | 0.28 | 43.00 | 79.52 | 117.41 |
| fir sse4.1 | 0.28 | 27.79 | 42.97 | 58.16 |
| fir avx2 | 0.28 | 7.30 | 9.50 | 13.59 |
| image | 19.24 | 82.52 | 152.17 | 207.63 |
| resize | - | 52.19 | 103.40 | 154.15 |
| fir rust | 0.28 | 40.88 | 69.39 | 101.53 |
| fir sse4.1 | 0.28 | 28.21 | 43.03 | 59.46 |
| fir avx2 | 0.28 | 7.33 | 9.47 | 13.59 |

### Resize RGBA8 image (U8x4) 4928x3279 => 852x567

Expand All @@ -63,16 +64,16 @@ Pipeline:
- Source image
[nasa-4928x3279-rgba.png](https://github.com/Cykooz/fast_image_resize/blob/main/data/nasa-4928x3279-rgba.png)
- Numbers in table is mean duration of image resizing in milliseconds.
- The `image` crate does not support multiplying and dividing by alpha channel.

| | Nearest | Bilinear | CatmullRom | Lanczos3 |
|------------|:-------:|:--------:|:----------:|:--------:|
| image | 19.73 | 82.34 | 141.74 | 198.86 |
| resize | - | 49.91 | 100.27 | 148.99 |
| fir rust | 0.18 | 36.84 | 52.31 | 74.99 |
| fir sse4.1 | 0.18 | 13.21 | 17.26 | 22.42 |
| fir avx2 | 0.18 | 9.47 | 12.03 | 16.08 |
| resize | - | 61.93 | 122.10 | 182.55 |
| fir rust | 0.18 | 36.57 | 52.28 | 74.14 |
| fir sse4.1 | 0.18 | 13.14 | 17.21 | 22.44 |
| fir avx2 | 0.18 | 9.69 | 11.99 | 16.23 |

## Resize L8 (luma) image (U8) 4928x3279 => 852x567
### Resize L8 (luma) image (U8) 4928x3279 => 852x567

Pipeline:

Expand All @@ -84,11 +85,11 @@ Pipeline:

| | Nearest | Bilinear | CatmullRom | Lanczos3 |
|------------|:-------:|:--------:|:----------:|:--------:|
| image | 15.21 | 44.78 | 71.92 | 100.91 |
| resize | - | 17.53 | 36.20 | 61.10 |
| fir rust | 0.15 | 14.08 | 16.38 | 23.73 |
| fir sse4.1 | 0.16 | 11.92 | 12.28 | 17.79 |
| fir avx2 | 0.16 | 6.48 | 4.77 | 7.85 |
| image | 15.86 | 47.17 | 74.46 | 102.53 |
| resize | - | 17.30 | 35.92 | 61.52 |
| fir rust | 0.15 | 14.10 | 16.20 | 24.12 |
| fir sse4.1 | 0.15 | 11.93 | 12.13 | 18.20 |
| fir avx2 | 0.15 | 6.30 | 4.71 | 7.62 |

## Examples

Expand Down
61 changes: 21 additions & 40 deletions benches/bench_compare_la.rs
@@ -1,7 +1,6 @@
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};
Expand All @@ -10,29 +9,11 @@ use testing::PixelExt;
mod utils;

pub fn bench_downscale_la(bench: &mut Bench) {
let src_image = U8x2::load_big_image().to_luma_alpha8();
let new_width = NonZeroU32::new(852).unwrap();
let new_height = NonZeroU32::new(567).unwrap();

let alg_names = ["Nearest", "Bilinear", "CatmullRom", "Lanczos3"];

// image crate
// https://crates.io/crates/image
for alg_name in alg_names {
let filter = match alg_name {
"Nearest" => imageops::Nearest,
"Bilinear" => imageops::Triangle,
"CatmullRom" => imageops::CatmullRom,
"Lanczos3" => imageops::Lanczos3,
_ => continue,
};
bench.task(format!("image - {}", alg_name), |task| {
task.iter(|| {
imageops::resize(&src_image, new_width.get(), new_height.get(), filter);
})
});
}

// fast_image_resize crate;
let mut cpu_ext_and_name = vec![(CpuExtensions::None, "rust")];
#[cfg(target_arch = "x86_64")]
Expand All @@ -49,13 +30,10 @@ pub fn bench_downscale_la(bench: &mut Bench) {
"Lanczos3" => ResizeAlg::Convolution(FilterType::Lanczos3),
_ => return,
};
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(),
src_view.pixel_type(),
);
let src_image = U8x2::load_big_src_image();
let src_view = src_image.view();
let mut premultiplied_src_image =
Image::new(src_image.width(), src_image.height(), src_view.pixel_type());
let mut dst_image = Image::new(new_width, new_height, PixelType::U8x2);
let mut dst_view = dst_image.view_mut();
let mut mul_div = MulDiv::default();
Expand All @@ -68,24 +46,27 @@ pub fn bench_downscale_la(bench: &mut Bench) {
mul_div.set_cpu_extensions(cpu_ext);
}

bench.task(format!("fir {} - {}", ext_name, alg_name), |task| {
task.iter(|| match resize_alg {
bench.task(
format!("fir {} - {}", ext_name, alg_name),
|task| match resize_alg {
ResizeAlg::Nearest => {
fast_resizer
.resize(&premultiplied_src_image.view(), &mut dst_view)
.unwrap();
task.iter(|| {
fast_resizer.resize(&src_view, &mut dst_view).unwrap();
});
}
_ => {
mul_div
.multiply_alpha(&src_view, &mut premultiplied_src_image.view_mut())
.unwrap();
fast_resizer
.resize(&premultiplied_src_image.view(), &mut dst_view)
.unwrap();
mul_div.divide_alpha_inplace(&mut dst_view).unwrap();
task.iter(|| {
mul_div
.multiply_alpha(&src_view, &mut premultiplied_src_image.view_mut())
.unwrap();
fast_resizer
.resize(&premultiplied_src_image.view(), &mut dst_view)
.unwrap();
mul_div.divide_alpha_inplace(&mut dst_view).unwrap();
});
}
})
});
},
);
}
}

Expand Down
33 changes: 6 additions & 27 deletions benches/bench_compare_la16.rs
@@ -1,7 +1,6 @@
use std::num::NonZeroU32;

use glassbench::*;
use image::imageops;

use fast_image_resize::pixels::U16x2;
use fast_image_resize::{CpuExtensions, FilterType, Image, MulDiv, PixelType, ResizeAlg, Resizer};
Expand All @@ -10,29 +9,11 @@ use testing::PixelExt;
mod utils;

pub fn bench_downscale_la16(bench: &mut Bench) {
let src_image = U16x2::load_big_image().to_luma_alpha16();
let new_width = NonZeroU32::new(852).unwrap();
let new_height = NonZeroU32::new(567).unwrap();

let alg_names = ["Nearest", "Bilinear", "CatmullRom", "Lanczos3"];

// image crate
// https://crates.io/crates/image
for alg_name in alg_names {
let filter = match alg_name {
"Nearest" => imageops::Nearest,
"Bilinear" => imageops::Triangle,
"CatmullRom" => imageops::CatmullRom,
"Lanczos3" => imageops::Lanczos3,
_ => continue,
};
bench.task(format!("image - {}", alg_name), |task| {
task.iter(|| {
imageops::resize(&src_image, new_width.get(), new_height.get(), filter);
})
});
}

// fast_image_resize crate;
let mut cpu_ext_and_name = vec![(CpuExtensions::None, "rust")];
#[cfg(target_arch = "x86_64")]
Expand All @@ -49,12 +30,12 @@ pub fn bench_downscale_la16(bench: &mut Bench) {
"Lanczos3" => ResizeAlg::Convolution(FilterType::Lanczos3),
_ => return,
};
let src_image_data = U16x2::load_big_src_image();
let src_view = src_image_data.view();
let src_image = U16x2::load_big_src_image();
let src_view = src_image.view();
let mut premultiplied_src_image = Image::new(
NonZeroU32::new(src_image.width()).unwrap(),
NonZeroU32::new(src_image.height()).unwrap(),
src_view.pixel_type(),
src_image.width(),
src_image.height(),
src_image.pixel_type(),
);
let mut dst_image = Image::new(new_width, new_height, PixelType::U16x2);
let mut dst_view = dst_image.view_mut();
Expand All @@ -71,9 +52,7 @@ pub fn bench_downscale_la16(bench: &mut Bench) {
bench.task(format!("fir {} - {}", ext_name, alg_name), |task| {
task.iter(|| match resize_alg {
ResizeAlg::Nearest => {
fast_resizer
.resize(&premultiplied_src_image.view(), &mut dst_view)
.unwrap();
fast_resizer.resize(&src_view, &mut dst_view).unwrap();
}
_ => {
mul_div
Expand Down

0 comments on commit 5b89090

Please sign in to comment.