Changed example of code in README.md

This commit is contained in:
Kirill Kuzminykh
2021-08-01 01:28:24 +03:00
parent 69bef66fa1
commit ef12fe1d76
14 changed files with 119 additions and 168 deletions
+37 -33
View File
@@ -25,8 +25,8 @@ Environment:
- glassbench = "0.3.0"
Other Rust libraries used to compare of resizing speed:
- image = "0.23.14" (https://crates.io/crates/image)
- resize = "0.7.2" (https://crates.io/crates/resize)
- image = "0.23.14" (<https://crates.io/crates/image>)
- resize = "0.7.2" (<https://crates.io/crates/resize>)
Resize algorithms:
- Nearest
@@ -88,52 +88,56 @@ Compiled with `rustflags = ["-C", "target-cpu=native"]`
| fir sse4.1 | 7.865 | 18.407 | 23.586 | 30.649 |
| fir avx2 | 6.882 | 14.847 | 18.026 | 23.450 |
## Examples of code
## Example
```rust
use std::io::BufWriter;
use std::num::NonZeroU32;
use fast_image_resize::{
CropBox, FilterType, ImageData, PixelType, ResizeAlg, Resizer, SrcImageView,
};
use image::codecs::png::PngEncoder;
use image::io::Reader as ImageReader;
use image::{ColorType, GenericImageView};
use fast_image_resize as fr;
#[test]
fn resize_image_example() {
// Read source image from file
let img = ImageReader::open("./data/nasa-4928x3279.png")
.unwrap()
.decode()
.unwrap();
let width = NonZeroU32::new(img.width()).unwrap();
let height = NonZeroU32::new(img.height()).unwrap();
let src_buffer = img.to_rgba8();
fn resize_lanczos3(src_pixels: &[u32], width: NonZeroU32, height: NonZeroU32) -> Vec<u8> {
// Create immutable view of source image data
let src_view = SrcImageView::from_pixels(width, height, src_pixels, PixelType::U8x4).unwrap();
let src_view =
fr::SrcImageView::from_buffer(width, height, src_buffer.as_raw(), fr::PixelType::U8x4)
.unwrap();
// Create wrapper that own data of destination image
let dst_width = NonZeroU32::new(1024).unwrap();
let dst_height = NonZeroU32::new(768).unwrap();
// Create wrapper that own data of destination image
let mut dst_image = ImageData::new_owned(dst_width, dst_height, src_view.pixel_type());
let mut dst_image = fr::ImageData::new(dst_width, dst_height, src_view.pixel_type());
// Get mutable view of destination image data
let mut dst_view = dst_image.dst_view();
// Create Resizer instance and resize source image into buffer of destination image
let mut resizer = Resizer::new(ResizeAlg::Convolution(FilterType::Lanczos3));
let mut resizer = fr::Resizer::new(fr::ResizeAlg::Convolution(fr::FilterType::Lanczos3));
resizer.resize(&src_view, &mut dst_view);
// Return destination buffer as Vec<u8>
dst_image.get_buffer().to_owned()
}
fn crop_and_resize_image(mut src_view: SrcImageView) -> ImageData<Vec<u32>> {
// Set crop-box for view of source image
src_view
.set_crop_box(CropBox {
left: 10,
top: 10,
width: NonZeroU32::new(100).unwrap(),
height: NonZeroU32::new(200).unwrap(),
})
// Write destination image as PNG-file
let mut result_buf = BufWriter::new(Vec::new());
let encoder = PngEncoder::new(&mut result_buf);
encoder
.encode(
dst_image.get_buffer(),
dst_width.get(),
dst_height.get(),
ColorType::Rgba8,
)
.unwrap();
let dst_width = NonZeroU32::new(1024).unwrap();
let dst_height = NonZeroU32::new(768).unwrap();
let mut dst_image = ImageData::new_owned(dst_width, dst_height, src_view.pixel_type());
let mut dst_view = dst_image.dst_view();
let mut resizer = Resizer::new(ResizeAlg::Convolution(FilterType::Lanczos3));
resizer.resize(&src_view, &mut dst_view);
dst_image
}
```
+7 -7
View File
@@ -13,14 +13,14 @@ const fn p(r: u8, g: u8, b: u8, a: u8) -> u32 {
fn get_src_image(width: NonZeroU32, height: NonZeroU32, pixel: u32) -> ImageData<Vec<u32>> {
let buf_size = (width.get() * height.get()) as usize;
let buffer = vec![pixel; buf_size];
ImageData::new(width, height, buffer, PixelType::U8x4).unwrap()
ImageData::from_pixels(width, height, buffer, PixelType::U8x4).unwrap()
}
fn multiplies_alpha_avx2(bench: &mut Bench) {
let width = NonZeroU32::new(4096).unwrap();
let height = NonZeroU32::new(2048).unwrap();
let src_data = get_src_image(width, height, p(255, 128, 0, 128));
let mut dst_data = ImageData::new_owned(width, height, PixelType::U8x4);
let mut dst_data = ImageData::new(width, height, PixelType::U8x4);
let src_view = src_data.src_view();
let mut dst_view = dst_data.dst_view();
let mut alpha_mul_div: MulDiv = Default::default();
@@ -41,7 +41,7 @@ fn multiplies_alpha_sse2(bench: &mut Bench) {
let width = NonZeroU32::new(4096).unwrap();
let height = NonZeroU32::new(2048).unwrap();
let src_data = get_src_image(width, height, p(255, 128, 0, 128));
let mut dst_data = ImageData::new_owned(width, height, PixelType::U8x4);
let mut dst_data = ImageData::new(width, height, PixelType::U8x4);
let src_view = src_data.src_view();
let mut dst_view = dst_data.dst_view();
let mut alpha_mul_div: MulDiv = Default::default();
@@ -62,7 +62,7 @@ fn multiplies_alpha_native(bench: &mut Bench) {
let width = NonZeroU32::new(4096).unwrap();
let height = NonZeroU32::new(2048).unwrap();
let src_data = get_src_image(width, height, p(255, 128, 0, 128));
let mut dst_data = ImageData::new_owned(width, height, PixelType::U8x4);
let mut dst_data = ImageData::new(width, height, PixelType::U8x4);
let src_view = src_data.src_view();
let mut dst_view = dst_data.dst_view();
let mut alpha_mul_div: MulDiv = Default::default();
@@ -83,7 +83,7 @@ fn divides_alpha_avx2(bench: &mut Bench) {
let width = NonZeroU32::new(4096).unwrap();
let height = NonZeroU32::new(2048).unwrap();
let src_data = get_src_image(width, height, p(128, 64, 0, 128));
let mut dst_data = ImageData::new_owned(width, height, PixelType::U8x4);
let mut dst_data = ImageData::new(width, height, PixelType::U8x4);
let src_view = src_data.src_view();
let mut dst_view = dst_data.dst_view();
let mut alpha_mul_div: MulDiv = Default::default();
@@ -104,7 +104,7 @@ fn divides_alpha_sse2(bench: &mut Bench) {
let width = NonZeroU32::new(4096).unwrap();
let height = NonZeroU32::new(2048).unwrap();
let src_data = get_src_image(width, height, p(128, 64, 0, 128));
let mut dst_data = ImageData::new_owned(width, height, PixelType::U8x4);
let mut dst_data = ImageData::new(width, height, PixelType::U8x4);
let src_view = src_data.src_view();
let mut dst_view = dst_data.dst_view();
let mut alpha_mul_div: MulDiv = Default::default();
@@ -125,7 +125,7 @@ fn divides_alpha_native(bench: &mut Bench) {
let width = NonZeroU32::new(4096).unwrap();
let height = NonZeroU32::new(2048).unwrap();
let src_data = get_src_image(width, height, p(128, 64, 0, 128));
let mut dst_data = ImageData::new_owned(width, height, PixelType::U8x4);
let mut dst_data = ImageData::new(width, height, PixelType::U8x4);
let src_view = src_data.src_view();
let mut dst_view = dst_data.dst_view();
let mut alpha_mul_div: MulDiv = Default::default();
+2 -2
View File
@@ -81,7 +81,7 @@ pub fn bench_downscale_rgb(bench: &mut Bench) {
.chunks_exact(4)
.map(|p| u32::from_le_bytes([p[0], p[1], p[2], p[3]]))
.collect();
let src_image_data = ImageData::new(
let src_image_data = ImageData::from_pixels(
NonZeroU32::new(src_image.width()).unwrap(),
NonZeroU32::new(src_image.height()).unwrap(),
buf,
@@ -89,7 +89,7 @@ pub fn bench_downscale_rgb(bench: &mut Bench) {
)
.unwrap();
let src_view = src_image_data.src_view();
let mut dst_image = ImageData::new_owned(new_width, new_height, PixelType::U8x4);
let mut dst_image = ImageData::new(new_width, new_height, PixelType::U8x4);
let mut dst_view = dst_image.dst_view();
let resize_alg = match alg_name {
+3 -3
View File
@@ -88,7 +88,7 @@ pub fn bench_downscale_rgba(bench: &mut Bench) {
.chunks_exact(4)
.map(|p| u32::from_le_bytes([p[0], p[1], p[2], p[3]]))
.collect();
let src_image_data = ImageData::new(
let src_image_data = ImageData::from_pixels(
NonZeroU32::new(src_image.width()).unwrap(),
NonZeroU32::new(src_image.height()).unwrap(),
buf,
@@ -96,12 +96,12 @@ pub fn bench_downscale_rgba(bench: &mut Bench) {
)
.unwrap();
let src_view = src_image_data.src_view();
let mut premultiplied_src_image = ImageData::new_owned(
let mut premultiplied_src_image = ImageData::new(
NonZeroU32::new(src_image.width()).unwrap(),
NonZeroU32::new(src_image.height()).unwrap(),
PixelType::U8x4,
);
let mut dst_image = ImageData::new_owned(new_width, new_height, PixelType::U8x4);
let mut dst_image = ImageData::new(new_width, new_height, PixelType::U8x4);
let mut dst_view = dst_image.dst_view();
let mut mul_div = MulDiv::default();
+8 -8
View File
@@ -22,7 +22,7 @@ fn get_big_source_image() -> ImageData<Vec<u32>> {
.chunks_exact(4)
.map(|p| u32::from_le_bytes([p[0], p[1], p[2], p[3]]))
.collect();
ImageData::new(
ImageData::from_pixels(
NonZeroU32::new(width).unwrap(),
NonZeroU32::new(height).unwrap(),
buf,
@@ -40,7 +40,7 @@ fn get_small_source_image() -> ImageData<Vec<u32>> {
.chunks_exact(4)
.map(|p| u32::from_le_bytes([p[0], p[1], p[2], p[3]]))
.collect();
ImageData::new(
ImageData::from_pixels(
NonZeroU32::new(width).unwrap(),
NonZeroU32::new(height).unwrap(),
buf,
@@ -51,7 +51,7 @@ fn get_small_source_image() -> ImageData<Vec<u32>> {
fn nearest_wo_simd_bench(bench: &mut Bench) {
let image = get_big_source_image();
let mut res_image = ImageData::new_owned(
let mut res_image = ImageData::new(
NonZeroU32::new(NEW_WIDTH).unwrap(),
NonZeroU32::new(NEW_HEIGHT).unwrap(),
image.pixel_type(),
@@ -71,7 +71,7 @@ fn nearest_wo_simd_bench(bench: &mut Bench) {
fn lanczos3_wo_simd_bench(bench: &mut Bench) {
let image = get_big_source_image();
let mut res_image = ImageData::new_owned(
let mut res_image = ImageData::new(
NonZeroU32::new(NEW_WIDTH).unwrap(),
NonZeroU32::new(NEW_HEIGHT).unwrap(),
image.pixel_type(),
@@ -91,7 +91,7 @@ fn lanczos3_wo_simd_bench(bench: &mut Bench) {
fn sse4_lanczos3_bench(bench: &mut Bench) {
let image = get_big_source_image();
let mut res_image = ImageData::new_owned(
let mut res_image = ImageData::new(
NonZeroU32::new(NEW_WIDTH).unwrap(),
NonZeroU32::new(NEW_HEIGHT).unwrap(),
image.pixel_type(),
@@ -111,7 +111,7 @@ fn sse4_lanczos3_bench(bench: &mut Bench) {
fn avx2_lanczos3_bench(bench: &mut Bench) {
let image = get_big_source_image();
let mut res_image = ImageData::new_owned(
let mut res_image = ImageData::new(
NonZeroU32::new(NEW_WIDTH).unwrap(),
NonZeroU32::new(NEW_HEIGHT).unwrap(),
image.pixel_type(),
@@ -131,7 +131,7 @@ fn avx2_lanczos3_bench(bench: &mut Bench) {
fn avx2_supersampling_lanczos3_bench(bench: &mut Bench) {
let image = get_big_source_image();
let mut res_image = ImageData::new_owned(
let mut res_image = ImageData::new(
NonZeroU32::new(NEW_WIDTH).unwrap(),
NonZeroU32::new(NEW_HEIGHT).unwrap(),
image.pixel_type(),
@@ -151,7 +151,7 @@ fn avx2_supersampling_lanczos3_bench(bench: &mut Bench) {
fn avx2_lanczos3_upscale_bench(bench: &mut Bench) {
let image = get_small_source_image();
let mut res_image = ImageData::new_owned(
let mut res_image = ImageData::new(
NonZeroU32::new(NEW_BIG_WIDTH).unwrap(),
NonZeroU32::new(NEW_BIG_HEIGHT).unwrap(),
image.pixel_type(),
+2 -2
View File
@@ -38,8 +38,8 @@ pub enum MulDivImageError {
///
/// let width = NonZeroU32::new(10).unwrap();
/// let height = NonZeroU32::new(7).unwrap();
/// let src_image = ImageData::new_owned(width, height, PixelType::U8x4);
/// let mut dst_image = ImageData::new_owned(width, height, PixelType::U8x4);
/// let src_image = ImageData::new(width, height, PixelType::U8x4);
/// let mut dst_image = ImageData::new(width, height, PixelType::U8x4);
///
/// let mul_div = MulDiv::default();
/// mul_div.multiply_alpha(&src_image.src_view(), &mut dst_image.dst_view()).unwrap();
+27 -35
View File
@@ -13,10 +13,8 @@ impl Avx2U8x4 {
/// For safety, it is necessary to ensure the following conditions:
/// - length of all rows in src_rows must be equal
/// - length of all rows in dst_rows must be equal
/// - bounds.len() == dst_rows.0.len()
/// - coeffs.len() == dst_rows.0.len() * window_size
/// - max(bound.size for bound in bounds) <= window_size
/// - max(bound.start + bound.size for bound in bounds) <= src_row.0.len()
/// - coefficients_chunks.len() == dst_rows.0.len()
/// - max(chunk.start + chunk.values.len() for chunk in coefficients_chunks) <= src_row.0.len()
/// - precision <= MAX_COEFS_PRECISION
#[inline]
#[target_feature(enable = "avx2")]
@@ -58,20 +56,18 @@ impl Avx2U8x4 {
let mmk0 = simd_utils::ptr_i16_to_256set1_epi32(k, 0);
let mmk1 = simd_utils::ptr_i16_to_256set1_epi32(k, 2);
let mut source = _mm256_inserti128_si256(
let mut source = _mm256_inserti128_si256::<1>(
_mm256_castsi128_si256(simd_utils::loadu_si128(s_row0, x + x_start)),
simd_utils::loadu_si128(s_row1, x + x_start),
1,
);
let mut pix = _mm256_shuffle_epi8(source, sh1);
sss0 = _mm256_add_epi32(sss0, _mm256_madd_epi16(pix, mmk0));
pix = _mm256_shuffle_epi8(source, sh2);
sss0 = _mm256_add_epi32(sss0, _mm256_madd_epi16(pix, mmk1));
source = _mm256_inserti128_si256(
source = _mm256_inserti128_si256::<1>(
_mm256_castsi128_si256(simd_utils::loadu_si128(s_row2, x + x_start)),
simd_utils::loadu_si128(s_row3, x + x_start),
1,
);
pix = _mm256_shuffle_epi8(source, sh1);
sss1 = _mm256_add_epi32(sss1, _mm256_madd_epi16(pix, mmk0));
@@ -87,18 +83,16 @@ impl Avx2U8x4 {
for k in coeffs_by_2 {
let mmk = simd_utils::ptr_i16_to_256set1_epi32(k, 0);
let mut pix = _mm256_inserti128_si256(
let mut pix = _mm256_inserti128_si256::<1>(
_mm256_castsi128_si256(simd_utils::loadl_epi64(s_row0, x + x_start)),
simd_utils::loadl_epi64(s_row1, x + x_start),
1,
);
pix = _mm256_shuffle_epi8(pix, sh1);
sss0 = _mm256_add_epi32(sss0, _mm256_madd_epi16(pix, mmk));
pix = _mm256_inserti128_si256(
pix = _mm256_inserti128_si256::<1>(
_mm256_castsi128_si256(simd_utils::loadl_epi64(s_row2, x + x_start)),
simd_utils::loadl_epi64(s_row3, x + x_start),
1,
);
pix = _mm256_shuffle_epi8(pix, sh1);
sss1 = _mm256_add_epi32(sss1, _mm256_madd_epi16(pix, mmk));
@@ -111,17 +105,15 @@ impl Avx2U8x4 {
let mmk = _mm256_set1_epi32(k as i32);
// [16] xx a0 xx b0 xx g0 xx r0 xx a0 xx b0 xx g0 xx r0
let mut pix = _mm256_inserti128_si256(
let mut pix = _mm256_inserti128_si256::<1>(
_mm256_castsi128_si256(simd_utils::mm_cvtepu8_epi32(s_row0, x + x_start)),
simd_utils::mm_cvtepu8_epi32(s_row1, x + x_start),
1,
);
sss0 = _mm256_add_epi32(sss0, _mm256_madd_epi16(pix, mmk));
pix = _mm256_inserti128_si256(
pix = _mm256_inserti128_si256::<1>(
_mm256_castsi128_si256(simd_utils::mm_cvtepu8_epi32(s_row2, x + x_start)),
simd_utils::mm_cvtepu8_epi32(s_row3, x + x_start),
1,
);
sss1 = _mm256_add_epi32(sss1, _mm256_madd_epi16(pix, mmk));
x += 1;
@@ -129,8 +121,8 @@ impl Avx2U8x4 {
macro_rules! call {
($imm8:expr) => {{
sss0 = _mm256_srai_epi32(sss0, $imm8);
sss1 = _mm256_srai_epi32(sss1, $imm8);
sss0 = _mm256_srai_epi32::<$imm8>(sss0);
sss1 = _mm256_srai_epi32::<$imm8>(sss1);
}};
}
constify_imm8!(precision, call);
@@ -140,13 +132,13 @@ impl Avx2U8x4 {
sss0 = _mm256_packus_epi16(sss0, zero);
sss1 = _mm256_packus_epi16(sss1, zero);
*d_row0.get_unchecked_mut(dst_x) =
transmute(_mm_cvtsi128_si32(_mm256_extracti128_si256(sss0, 0)));
transmute(_mm_cvtsi128_si32(_mm256_extracti128_si256::<0>(sss0)));
*d_row1.get_unchecked_mut(dst_x) =
transmute(_mm_cvtsi128_si32(_mm256_extracti128_si256(sss0, 1)));
transmute(_mm_cvtsi128_si32(_mm256_extracti128_si256::<1>(sss0)));
*d_row2.get_unchecked_mut(dst_x) =
transmute(_mm_cvtsi128_si32(_mm256_extracti128_si256(sss1, 0)));
transmute(_mm_cvtsi128_si32(_mm256_extracti128_si256::<0>(sss1)));
*d_row3.get_unchecked_mut(dst_x) =
transmute(_mm_cvtsi128_si32(_mm256_extracti128_si256(sss1, 1)));
transmute(_mm_cvtsi128_si32(_mm256_extracti128_si256::<1>(sss1)));
}
}
@@ -212,7 +204,7 @@ impl Avx2U8x4 {
for k in coeffs_by_8 {
let tmp = simd_utils::loadu_si128(k, 0);
let ksource = _mm256_insertf128_si256(_mm256_castsi128_si256(tmp), tmp, 1);
let ksource = _mm256_insertf128_si256::<1>(_mm256_castsi128_si256(tmp), tmp);
let source = simd_utils::loadu_si256(src_row, x + x_start);
@@ -232,10 +224,10 @@ impl Avx2U8x4 {
for k in coeffs_by_4 {
let tmp = simd_utils::loadl_epi64(k, 0);
let ksource = _mm256_insertf128_si256(_mm256_castsi128_si256(tmp), tmp, 1);
let ksource = _mm256_insertf128_si256::<1>(_mm256_castsi128_si256(tmp), tmp);
let tmp = simd_utils::loadu_si128(src_row, x + x_start);
let source = _mm256_insertf128_si256(_mm256_castsi128_si256(tmp), tmp, 1);
let source = _mm256_insertf128_si256::<1>(_mm256_castsi128_si256(tmp), tmp);
let pix = _mm256_shuffle_epi8(source, sh5);
let mmk = _mm256_shuffle_epi8(ksource, sh6);
@@ -245,8 +237,8 @@ impl Avx2U8x4 {
}
_mm_add_epi32(
_mm256_extracti128_si256(sss256, 0),
_mm256_extracti128_si256(sss256, 1),
_mm256_extracti128_si256::<0>(sss256),
_mm256_extracti128_si256::<1>(sss256),
)
};
@@ -272,7 +264,7 @@ impl Avx2U8x4 {
macro_rules! call {
($imm8:expr) => {{
sss = _mm_srai_epi32(sss, $imm8);
sss = _mm_srai_epi32::<$imm8>(sss);
}};
}
constify_imm8!(precision, call);
@@ -354,10 +346,10 @@ impl Avx2U8x4 {
macro_rules! call {
($imm8:expr) => {{
sss0 = _mm256_srai_epi32(sss0, $imm8);
sss1 = _mm256_srai_epi32(sss1, $imm8);
sss2 = _mm256_srai_epi32(sss2, $imm8);
sss3 = _mm256_srai_epi32(sss3, $imm8);
sss0 = _mm256_srai_epi32::<$imm8>(sss0);
sss1 = _mm256_srai_epi32::<$imm8>(sss1);
sss2 = _mm256_srai_epi32::<$imm8>(sss2);
sss3 = _mm256_srai_epi32::<$imm8>(sss3);
}};
}
constify_imm8!(precision, call);
@@ -409,8 +401,8 @@ impl Avx2U8x4 {
macro_rules! call {
($imm8:expr) => {{
sss0 = _mm_srai_epi32(sss0, $imm8);
sss1 = _mm_srai_epi32(sss1, $imm8);
sss0 = _mm_srai_epi32::<$imm8>(sss0);
sss1 = _mm_srai_epi32::<$imm8>(sss1);
}};
}
constify_imm8!(precision, call);
@@ -450,7 +442,7 @@ impl Avx2U8x4 {
macro_rules! call {
($imm8:expr) => {{
sss = _mm_srai_epi32(sss, $imm8);
sss = _mm_srai_epi32::<$imm8>(sss);
}};
}
constify_imm8!(precision, call);
+20 -22
View File
@@ -13,10 +13,8 @@ impl Sse4U8x4 {
/// For safety, it is necessary to ensure the following conditions:
/// - length of all rows in src_rows must be equal
/// - length of all rows in dst_rows must be equal
/// - bounds.len() == dst_rows.0.len()
/// - coeffs.len() == dst_rows.0.len() * window_size
/// - max(bound.size for bound in bounds) <= window_size
/// - max(bound.start + bound.size for bound in bounds) <= src_row.0.len()
/// - coefficients_chunks.len() == dst_rows.0.len()
/// - max(chunk.start + chunk.values.len() for chunk in coefficients_chunks) <= src_row.0.len()
/// - precision <= MAX_COEFS_PRECISION
#[target_feature(enable = "sse4.1")]
unsafe fn horiz_convolution_8u4x(
@@ -128,10 +126,10 @@ impl Sse4U8x4 {
macro_rules! call {
($imm8:expr) => {{
sss0 = _mm_srai_epi32(sss0, $imm8);
sss1 = _mm_srai_epi32(sss1, $imm8);
sss2 = _mm_srai_epi32(sss2, $imm8);
sss3 = _mm_srai_epi32(sss3, $imm8);
sss0 = _mm_srai_epi32::<$imm8>(sss0);
sss1 = _mm_srai_epi32::<$imm8>(sss1);
sss2 = _mm_srai_epi32::<$imm8>(sss2);
sss3 = _mm_srai_epi32::<$imm8>(sss3);
}};
}
constify_imm8!(precision, call);
@@ -153,8 +151,8 @@ impl Sse4U8x4 {
/// For safety, it is necessary to ensure the following conditions:
/// - bounds.len() == dst_row.len()
/// - coeffs.len() == dst_rows.0.len() * window_size
/// - max(bound.start + bound.size for bound in bounds) <= src_row.len()
/// - coefficients_chunks.len() == dst_row.len()
/// - max(chunk.start + chunk.values.len() for chunk in coefficients_chunks) <= src_row.len()
/// - precision <= MAX_COEFS_PRECISION
#[target_feature(enable = "sse4.1")]
unsafe fn horiz_convolution_8u(
@@ -252,7 +250,7 @@ impl Sse4U8x4 {
macro_rules! call {
($imm8:expr) => {{
sss = _mm_srai_epi32(sss, $imm8);
sss = _mm_srai_epi32::<$imm8>(sss);
}};
}
constify_imm8!(precision, call);
@@ -364,14 +362,14 @@ impl Sse4U8x4 {
macro_rules! call {
($imm8:expr) => {{
sss0 = _mm_srai_epi32(sss0, $imm8);
sss1 = _mm_srai_epi32(sss1, $imm8);
sss2 = _mm_srai_epi32(sss2, $imm8);
sss3 = _mm_srai_epi32(sss3, $imm8);
sss4 = _mm_srai_epi32(sss4, $imm8);
sss5 = _mm_srai_epi32(sss5, $imm8);
sss6 = _mm_srai_epi32(sss6, $imm8);
sss7 = _mm_srai_epi32(sss7, $imm8);
sss0 = _mm_srai_epi32::<$imm8>(sss0);
sss1 = _mm_srai_epi32::<$imm8>(sss1);
sss2 = _mm_srai_epi32::<$imm8>(sss2);
sss3 = _mm_srai_epi32::<$imm8>(sss3);
sss4 = _mm_srai_epi32::<$imm8>(sss4);
sss5 = _mm_srai_epi32::<$imm8>(sss5);
sss6 = _mm_srai_epi32::<$imm8>(sss6);
sss7 = _mm_srai_epi32::<$imm8>(sss7);
}};
}
constify_imm8!(precision, call);
@@ -427,8 +425,8 @@ impl Sse4U8x4 {
macro_rules! call {
($imm8:expr) => {{
sss0 = _mm_srai_epi32(sss0, $imm8);
sss1 = _mm_srai_epi32(sss1, $imm8);
sss0 = _mm_srai_epi32::<$imm8>(sss0);
sss1 = _mm_srai_epi32::<$imm8>(sss1);
}};
}
constify_imm8!(precision, call);
@@ -470,7 +468,7 @@ impl Sse4U8x4 {
macro_rules! call {
($imm8:expr) => {{
sss = _mm_srai_epi32(sss, $imm8);
sss = _mm_srai_epi32::<$imm8>(sss);
}};
}
constify_imm8!(precision, call);
+3 -2
View File
@@ -11,7 +11,7 @@ pub struct ImageData<T: AsRef<[u32]>> {
}
impl<T: AsRef<[u32]>> ImageData<T> {
pub fn new(
pub fn from_pixels(
width: NonZeroU32,
height: NonZeroU32,
pixels: T,
@@ -73,7 +73,7 @@ impl<T: AsRef<[u32]> + AsMut<[u32]>> ImageData<T> {
}
impl ImageData<Vec<u32>> {
pub fn new_owned(width: NonZeroU32, height: NonZeroU32, pixel_type: PixelType) -> Self {
pub fn new(width: NonZeroU32, height: NonZeroU32, pixel_type: PixelType) -> Self {
let size = (width.get() * height.get()) as usize;
let pixels = vec![0; size];
Self {
@@ -84,6 +84,7 @@ impl ImageData<Vec<u32>> {
}
}
/// Copy content of given `buffer` into internal `Vec<u32>`
pub fn from_buffer(
width: NonZeroU32,
height: NonZeroU32,
+1
View File
@@ -1,3 +1,4 @@
#![doc = include_str!("../README.md")]
pub use alpha::{MulDiv, MulDivImageError, MulDivImagesError};
pub use convolution::FilterType;
pub use errors::{CropBoxError, ImageBufferError, ImageRowsError, InvalidBufferSizeError};
+1 -1
View File
@@ -153,7 +153,7 @@ fn get_temp_image_from_buffer(
buffer.resize(buf_size, 0);
}
let pixels = &mut buffer[0..buf_size];
ImageData::new(width, height, pixels, pixel_type).unwrap()
ImageData::from_pixels(width, height, pixels, pixel_type).unwrap()
}
fn resample_nearest(src_image: &SrcImageView, dst_image: &mut DstImageView) {
+2 -2
View File
@@ -29,7 +29,7 @@ fn multiply_alpha_test(cpu_extensions: CpuExtensions) {
)
.unwrap();
let mut dst_image = ImageData::new_owned(
let mut dst_image = ImageData::new(
NonZeroU32::new(width).unwrap(),
NonZeroU32::new(height).unwrap(),
PixelType::U8x4,
@@ -112,7 +112,7 @@ fn divide_alpha_test(cpu_extensions: CpuExtensions) {
)
.unwrap();
let mut dst_image = ImageData::new_owned(
let mut dst_image = ImageData::new(
NonZeroU32::new(width).unwrap(),
NonZeroU32::new(height).unwrap(),
PixelType::U8x4,
-45
View File
@@ -1,45 +0,0 @@
use std::num::NonZeroU32;
use fast_image_resize::{
CropBox, FilterType, ImageData, PixelType, ResizeAlg, Resizer, SrcImageView,
};
fn resize_lanczos3(src_pixels: &[u32], width: NonZeroU32, height: NonZeroU32) -> Vec<u8> {
// Create immutable view of source image data
let src_view = SrcImageView::from_pixels(width, height, src_pixels, PixelType::U8x4).unwrap();
let dst_width = NonZeroU32::new(1024).unwrap();
let dst_height = NonZeroU32::new(768).unwrap();
// Create wrapper that own data of destination image
let mut dst_image = ImageData::new_owned(dst_width, dst_height, src_view.pixel_type());
// Get mutable view of destination image data
let mut dst_view = dst_image.dst_view();
// Create Resizer instance and resize source image into buffer of destination image
let mut resizer = Resizer::new(ResizeAlg::Convolution(FilterType::Lanczos3));
resizer.resize(&src_view, &mut dst_view);
// Return destination buffer as Vec<u8>
dst_image.get_buffer().to_owned()
}
fn crop_and_resize_image(mut src_view: SrcImageView) -> ImageData<Vec<u32>> {
// Set crop-box for view of source image
src_view
.set_crop_box(CropBox {
left: 10,
top: 10,
width: NonZeroU32::new(100).unwrap(),
height: NonZeroU32::new(200).unwrap(),
})
.unwrap();
let dst_width = NonZeroU32::new(1024).unwrap();
let dst_height = NonZeroU32::new(768).unwrap();
let mut dst_image = ImageData::new_owned(dst_width, dst_height, src_view.pixel_type());
let mut dst_view = dst_image.dst_view();
let mut resizer = Resizer::new(ResizeAlg::Convolution(FilterType::Lanczos3));
resizer.resize(&src_view, &mut dst_view);
dst_image
}
+6 -6
View File
@@ -72,7 +72,7 @@ fn resample_wo_simd_lanczos3_test() {
resizer.set_cpu_extensions(CpuExtensions::None);
}
let new_height = get_new_height(&image.src_view(), NEW_WIDTH);
let mut result = ImageData::new_owned(
let mut result = ImageData::new(
NonZeroU32::new(NEW_WIDTH).unwrap(),
NonZeroU32::new(new_height).unwrap(),
image.pixel_type(),
@@ -89,7 +89,7 @@ fn resample_sse4_lanczos3_test() {
resizer.set_cpu_extensions(CpuExtensions::Sse4_1);
}
let new_height = get_new_height(&image.src_view(), NEW_WIDTH);
let mut result = ImageData::new_owned(
let mut result = ImageData::new(
NonZeroU32::new(NEW_WIDTH).unwrap(),
NonZeroU32::new(new_height).unwrap(),
image.pixel_type(),
@@ -106,7 +106,7 @@ fn resample_avx2_lanczos3_test() {
resizer.set_cpu_extensions(CpuExtensions::Avx2);
}
let new_height = get_new_height(&image.src_view(), NEW_WIDTH);
let mut result = ImageData::new_owned(
let mut result = ImageData::new(
NonZeroU32::new(NEW_WIDTH).unwrap(),
NonZeroU32::new(new_height).unwrap(),
image.pixel_type(),
@@ -123,7 +123,7 @@ fn resample_avx2_lanczos3_upscale_test() {
resizer.set_cpu_extensions(CpuExtensions::Avx2);
}
let new_height = get_new_height(&image.src_view(), NEW_BIG_WIDTH);
let mut result = ImageData::new_owned(
let mut result = ImageData::new(
NonZeroU32::new(NEW_BIG_WIDTH).unwrap(),
NonZeroU32::new(new_height).unwrap(),
image.pixel_type(),
@@ -140,7 +140,7 @@ fn resample_nearest_test() {
resizer.set_cpu_extensions(CpuExtensions::None);
}
let new_height = get_new_height(&image.src_view(), NEW_WIDTH);
let mut result = ImageData::new_owned(
let mut result = ImageData::new(
NonZeroU32::new(NEW_WIDTH).unwrap(),
NonZeroU32::new(new_height).unwrap(),
image.pixel_type(),
@@ -157,7 +157,7 @@ fn resample_super_sampling_test() {
resizer.set_cpu_extensions(CpuExtensions::Avx2);
}
let new_height = get_new_height(&image.src_view(), NEW_WIDTH);
let mut result = ImageData::new_owned(
let mut result = ImageData::new(
NonZeroU32::new(NEW_WIDTH).unwrap(),
NonZeroU32::new(new_height).unwrap(),
image.pixel_type(),