mirror of
https://github.com/Cykooz/fast_image_resize.git
synced 2026-10-08 01:11:09 +00:00
Changed example of code in README.md
This commit is contained in:
@@ -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
|
||||
}
|
||||
```
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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,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
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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(),
|
||||
|
||||
Reference in New Issue
Block a user