mirror of
https://github.com/Cykooz/fast_image_resize.git
synced 2026-10-08 01:11:09 +00:00
Added new resize algorythm ResizeAlg::Interpolation (#32).
This commit is contained in:
@@ -1,3 +1,13 @@
|
||||
## [Unreleased] - ReleaseDate
|
||||
|
||||
### Added
|
||||
|
||||
- Added new resize algorythm `ResizeAlg::Interpolation` (#32).
|
||||
|
||||
It is like `ResizeAlg::Convolution` but with fixed kernel size.
|
||||
This algorithm can be useful if you want to get a result similar
|
||||
to `OpenCV` (except `INTER_AREA` interpolation).
|
||||
|
||||
## [4.1.0] - 2024-07-14
|
||||
|
||||
### Added
|
||||
|
||||
Generated
+48
-48
@@ -113,7 +113,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.68",
|
||||
"syn 2.0.71",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -171,9 +171,9 @@ checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||
|
||||
[[package]]
|
||||
name = "bitstream-io"
|
||||
version = "2.4.2"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "415f8399438eb5e4b2f73ed3152a3448b98149dda642a957ee704e1daa5cf1d8"
|
||||
checksum = "3dcde5f311c85b8ca30c2e4198d4326bc342c76541590106f5fa4a50946ea499"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
@@ -196,9 +196,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "built"
|
||||
version = "0.7.3"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c6a6c0b39c38fd754ac338b00a88066436389c0f029da5d37d1e01091d9b7c17"
|
||||
checksum = "236e6289eda5a812bc6b53c3b024039382a2895fbbeef2d748b2931546d392c4"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
@@ -232,13 +232,12 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.104"
|
||||
version = "1.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74b6a57f98764a267ff415d50a25e6e166f3831a5071af4995296ea97d210490"
|
||||
checksum = "324c74f2155653c90b04f25b2a47a8a631360cb908f92a772695f430c7e31052"
|
||||
dependencies = [
|
||||
"jobserver",
|
||||
"libc",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -326,9 +325,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.8"
|
||||
version = "4.5.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84b3edb18336f4df585bc9aa31dd99c036dfa5dc5e9a2939a722a188f3a8970d"
|
||||
checksum = "64acc1846d54c1fe936a78dc189c34e28d3f5afc348403f28ecf53660b9b8462"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
@@ -346,9 +345,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.8"
|
||||
version = "4.5.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1c09dd5ada6c6c78075d6fd0da3f90d8080651e2d6cc8eb2f1aaa4034ced708"
|
||||
checksum = "6fb8393d67ba2e7bfaf28a23458e4e2b543cc73a99595511eb207fdb8aede942"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
@@ -365,7 +364,7 @@ dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.68",
|
||||
"syn 2.0.71",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -503,9 +502,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "document-features"
|
||||
version = "0.2.8"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef5282ad69563b5fc40319526ba27e0e7363d552a896f0297d54f767717f9b95"
|
||||
checksum = "cb6969eaabd2421f8a2775cfd2471a2b634372b4a25d41e3bd647b79912850a0"
|
||||
dependencies = [
|
||||
"litrs",
|
||||
]
|
||||
@@ -576,6 +575,7 @@ dependencies = [
|
||||
"nix",
|
||||
"num-traits",
|
||||
"png",
|
||||
"rayon",
|
||||
"resize",
|
||||
"rgb",
|
||||
"serde",
|
||||
@@ -776,12 +776,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "image-webp"
|
||||
version = "0.1.2"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d730b085583c4d789dfd07fdcf185be59501666a90c97c40162b37e4fdad272d"
|
||||
checksum = "f79afb8cbee2ef20f59ccd477a218c12a93943d075b492015ecb1bb81f8ee904"
|
||||
dependencies = [
|
||||
"byteorder-lite",
|
||||
"thiserror",
|
||||
"quick-error",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -808,7 +808,7 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.68",
|
||||
"syn 2.0.71",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1056,7 +1056,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.68",
|
||||
"syn 2.0.71",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1096,9 +1096,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||
|
||||
[[package]]
|
||||
name = "oorandom"
|
||||
version = "11.1.3"
|
||||
version = "11.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
|
||||
checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9"
|
||||
|
||||
[[package]]
|
||||
name = "parse-zoneinfo"
|
||||
@@ -1152,7 +1152,7 @@ dependencies = [
|
||||
"pest_meta",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.68",
|
||||
"syn 2.0.71",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1254,7 +1254,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn 2.0.68",
|
||||
"syn 2.0.71",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1348,9 +1348,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ravif"
|
||||
version = "0.11.7"
|
||||
version = "0.11.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67376f469e7e7840d0040bbf4b9b3334005bb167f814621326e4c7ab8cd6e944"
|
||||
checksum = "c6ba61c28ba24c0cf8406e025cb29a742637e3f70776e61c27a8a8b72a042d12"
|
||||
dependencies = [
|
||||
"avif-serialize",
|
||||
"imgref",
|
||||
@@ -1435,9 +1435,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rgb"
|
||||
version = "0.8.40"
|
||||
version = "0.8.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7439be6844e40133eda024efd85bf07f59d0dd2f59b10c00dd6cfb92cc5c741"
|
||||
checksum = "ade4539f42266ded9e755c605bdddf546242b2c961b03b06a7375260788a0523"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
]
|
||||
@@ -1465,22 +1465,22 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.203"
|
||||
version = "1.0.204"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094"
|
||||
checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.203"
|
||||
version = "1.0.204"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
|
||||
checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.68",
|
||||
"syn 2.0.71",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1579,9 +1579,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.68"
|
||||
version = "2.0.71"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9"
|
||||
checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1603,9 +1603,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "target-lexicon"
|
||||
version = "0.12.14"
|
||||
version = "0.12.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f"
|
||||
checksum = "4873307b7c257eddcb50c9bedf158eb669578359fb28428bef438fec8e6ba7c2"
|
||||
|
||||
[[package]]
|
||||
name = "tera"
|
||||
@@ -1639,22 +1639,22 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.61"
|
||||
version = "1.0.63"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709"
|
||||
checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.61"
|
||||
version = "1.0.63"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
|
||||
checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.68",
|
||||
"syn 2.0.71",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1680,9 +1680,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.8.14"
|
||||
version = "0.8.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335"
|
||||
checksum = "ac2caab0bf757388c6c0ae23b3293fdb463fee59434529014f85e3263b995c28"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
@@ -1701,9 +1701,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.22.14"
|
||||
version = "0.22.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38"
|
||||
checksum = "278f3d518e152219c994ce877758516bca5e118eaed6996192a774fb9fbf0788"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde",
|
||||
@@ -1846,7 +1846,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.68",
|
||||
"syn 2.0.71",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
@@ -1868,7 +1868,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.68",
|
||||
"syn 2.0.71",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
+4
-3
@@ -23,7 +23,8 @@ exclude = ["/data"]
|
||||
cfg-if = "1.0"
|
||||
num-traits = "0.2.19"
|
||||
thiserror = "1.0"
|
||||
document-features = "0.2.8"
|
||||
document-features = "0.2.10"
|
||||
rayon = "1.10.0"
|
||||
# Optional dependencies
|
||||
image = { version = "0.25.1", optional = true }
|
||||
bytemuck = { version = "1.16", optional = true }
|
||||
@@ -35,13 +36,13 @@ bytemuck = { version = "1.16", optional = true }
|
||||
## type from the `image` crate.
|
||||
image = ["dep:image", "dep:bytemuck"]
|
||||
for_testing = ["image"]
|
||||
only_u8x4 = [] # This can be used to experiment with the crate's code.
|
||||
only_u8x4 = ["testing/only_u8x4"] # This can be used to experiment with the crate's code.
|
||||
|
||||
|
||||
[dev-dependencies]
|
||||
fast_image_resize = { path = ".", features = ["for_testing"] }
|
||||
resize = { version = "0.8.4", default-features = false, features = ["std"] }
|
||||
rgb = "0.8.37"
|
||||
rgb = "0.8.45"
|
||||
png = "0.17.13"
|
||||
serde = { version = "1.0", features = ["serde_derive"] }
|
||||
serde_json = "1.0"
|
||||
|
||||
@@ -21,7 +21,7 @@ Supported pixel formats and available optimizations:
|
||||
| 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 (e.g. L) | - | - | - | - |
|
||||
| F32 | One `f32` component per pixel (e.g. L) | + | + | - | - |
|
||||
| F32 | One `f32` component per pixel (e.g. L32F) | + | + | - | - |
|
||||
| F32x2 | Two `f32` components per pixel (e.g. LA32F) | + | + | - | - |
|
||||
| F32x3 | Three `f32` components per pixel (e.g. RGB32F) | + | + | - | - |
|
||||
| F32x4 | Four `f32` components per pixel (e.g. RGBA32F) | + | + | - | - |
|
||||
|
||||
@@ -31,6 +31,7 @@ pub fn change_type_of_pixel_components(
|
||||
|
||||
use PixelType as PT;
|
||||
|
||||
#[cfg(not(feature = "only_u8x4"))]
|
||||
match src_pixel_type {
|
||||
PixelType::U8 => map_dst!(
|
||||
U8,
|
||||
@@ -128,6 +129,12 @@ pub fn change_type_of_pixel_components(
|
||||
(PT::F32x4, F32x4)
|
||||
),
|
||||
}
|
||||
|
||||
#[cfg(feature = "only_u8x4")]
|
||||
match src_pixel_type {
|
||||
PixelType::U8x4 => map_dst!(U8x4, dst_pixel_type, (PT::U8x4, U8x4)),
|
||||
_ => Err(MappingError::UnsupportedCombinationOfImageTypes),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
||||
@@ -82,7 +82,7 @@ pub enum FilterType {
|
||||
///
|
||||
/// Minimal kernel size 1x1 px.
|
||||
Box,
|
||||
/// Bilinear filter calculate the output pixel value using linear
|
||||
/// Bilinear filter calculates the output pixel value using linear
|
||||
/// interpolation on all pixels that may contribute to the output value.
|
||||
///
|
||||
/// Minimal kernel size 2x2 px.
|
||||
@@ -91,11 +91,11 @@ pub enum FilterType {
|
||||
/// providing the image downscaling quality comparable to bicubic
|
||||
/// (`CatmulRom` or `Mitchell`). Produces a sharper image than `Bilinear`,
|
||||
/// doesn't have dislocations on local level like with `Box`.
|
||||
/// The filter don’t show good quality for the image upscaling.
|
||||
/// The filter doesn't show good quality for the image upscaling.
|
||||
///
|
||||
/// Minimal kernel size 2x2 px.
|
||||
Hamming,
|
||||
/// Catmull-Rom bicubic filter calculate the output pixel value using
|
||||
/// Catmull-Rom bicubic filter calculates the output pixel value using
|
||||
/// cubic interpolation on all pixels that may contribute to the output
|
||||
/// value.
|
||||
///
|
||||
|
||||
+12
-6
@@ -85,11 +85,12 @@ impl Coefficients {
|
||||
|
||||
pub(crate) fn precompute_coefficients(
|
||||
in_size: u32,
|
||||
in0: f64, // Left border for cropping
|
||||
in1: f64, // Right border for cropping
|
||||
in0: f64, // Left/top border for cropping
|
||||
in1: f64, // Right/bottom border for cropping
|
||||
out_size: u32,
|
||||
filter: fn(f64) -> f64,
|
||||
filter_support: f64,
|
||||
adaptive_kernel_size: bool,
|
||||
) -> Coefficients {
|
||||
if in_size == 0 || out_size == 0 {
|
||||
return Coefficients::default();
|
||||
@@ -98,7 +99,11 @@ pub(crate) fn precompute_coefficients(
|
||||
if scale <= 0. {
|
||||
return Coefficients::default();
|
||||
}
|
||||
let filter_scale = scale.max(1.0);
|
||||
let filter_scale = if adaptive_kernel_size {
|
||||
scale.max(1.0)
|
||||
} else {
|
||||
1.0
|
||||
};
|
||||
|
||||
// Determine filter radius size (length of resampling filter)
|
||||
let filter_radius = filter_support * filter_scale;
|
||||
@@ -113,7 +118,7 @@ pub(crate) fn precompute_coefficients(
|
||||
let mut bounds: Vec<Bound> = Vec::with_capacity(out_size as usize);
|
||||
|
||||
for out_x in 0..out_size {
|
||||
// Find the point in the input image corresponding to the centre
|
||||
// Find the point in the input image corresponding to the center
|
||||
// of the current pixel in the output image.
|
||||
let in_center = in0 + (out_x as f64 + 0.5) * scale;
|
||||
|
||||
@@ -131,14 +136,15 @@ pub(crate) fn precompute_coefficients(
|
||||
// (x + 0.5) - in_center => x - (in_center - 0.5) => x - center
|
||||
let center = in_center - 0.5;
|
||||
|
||||
// Calculate the weight of each input pixel from the given x-range.
|
||||
for x in x_min..x_max {
|
||||
let w: f64 = filter((x as f64 - center) * recip_filter_scale);
|
||||
coeffs.push(w);
|
||||
ww += w;
|
||||
}
|
||||
if ww != 0.0 {
|
||||
// Normalise values of coefficients.
|
||||
// Sum of coefficients must be equal to 1.0.
|
||||
// Normalise values of weights.
|
||||
// The sum of weights must be equal to 1.0.
|
||||
coeffs[cur_index..].iter_mut().for_each(|w| *w /= ww);
|
||||
}
|
||||
// Remaining values should stay empty if they are used despite x_max.
|
||||
|
||||
+60
-25
@@ -12,6 +12,11 @@ use crate::{
|
||||
pub enum ResizeAlg {
|
||||
Nearest,
|
||||
Convolution(FilterType),
|
||||
/// It is like `Convolution` but with fixed kernel size.
|
||||
///
|
||||
/// This algorithm can be useful if you want to get a result
|
||||
/// similar to `OpenCV` (except `INTER_AREA` interpolation).
|
||||
Interpolation(FilterType),
|
||||
SuperSampling(FilterType, u8),
|
||||
}
|
||||
|
||||
@@ -101,6 +106,29 @@ impl ResizeOptions {
|
||||
options.mul_div_alpha = v;
|
||||
options
|
||||
}
|
||||
|
||||
fn get_crop_box<P: PixelTrait>(
|
||||
&self,
|
||||
src_view: &impl ImageView<Pixel = P>,
|
||||
dst_view: &impl ImageView<Pixel = P>,
|
||||
) -> CropBox {
|
||||
match self.cropping {
|
||||
SrcCropping::None => CropBox {
|
||||
left: 0.,
|
||||
top: 0.,
|
||||
width: src_view.width() as _,
|
||||
height: src_view.height() as _,
|
||||
},
|
||||
SrcCropping::Crop(crop_box) => crop_box,
|
||||
SrcCropping::FitIntoDestination(centering) => CropBox::fit_src_into_dst_size(
|
||||
src_view.width(),
|
||||
src_view.height(),
|
||||
dst_view.width(),
|
||||
dst_view.height(),
|
||||
Some(centering),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Methods of this structure used to resize images.
|
||||
@@ -199,24 +227,7 @@ impl Resizer {
|
||||
let default_options = ResizeOptions::default();
|
||||
let options = options.into().unwrap_or(&default_options);
|
||||
|
||||
let crop_box = match options.cropping {
|
||||
SrcCropping::None => CropBox {
|
||||
left: 0.,
|
||||
top: 0.,
|
||||
width: src_view.width() as _,
|
||||
height: src_view.height() as _,
|
||||
},
|
||||
SrcCropping::Crop(crop_box) => crop_box,
|
||||
SrcCropping::FitIntoDestination(centering) => CropBox::fit_src_into_dst_size(
|
||||
src_view.width(),
|
||||
src_view.height(),
|
||||
dst_view.width(),
|
||||
dst_view.height(),
|
||||
Some(centering),
|
||||
),
|
||||
};
|
||||
let cropped_src_view = CroppedSrcImageView::cropped(src_view, crop_box)?;
|
||||
|
||||
let crop_box = options.get_crop_box(src_view, dst_view);
|
||||
if crop_box.width == 0.
|
||||
|| crop_box.height == 0.
|
||||
|| dst_view.width() == 0
|
||||
@@ -226,6 +237,8 @@ impl Resizer {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let cropped_src_view = CroppedSrcImageView::cropped(src_view, crop_box)?;
|
||||
|
||||
if copy_image(&cropped_src_view, dst_view).is_ok() {
|
||||
// If `copy_image()` returns `Ok` it means that
|
||||
// the size of the destination image is equal to
|
||||
@@ -240,6 +253,14 @@ impl Resizer {
|
||||
&cropped_src_view,
|
||||
dst_view,
|
||||
filter_type,
|
||||
true,
|
||||
options.mul_div_alpha,
|
||||
),
|
||||
ResizeAlg::Interpolation(filter_type) => self.resample_convolution(
|
||||
&cropped_src_view,
|
||||
dst_view,
|
||||
filter_type,
|
||||
false,
|
||||
options.mul_div_alpha,
|
||||
),
|
||||
ResizeAlg::SuperSampling(filter_type, multiplicity) => self.resample_super_sampling(
|
||||
@@ -294,6 +315,7 @@ impl Resizer {
|
||||
cropped_src_view: &CroppedSrcImageView<impl ImageView<Pixel = P>>,
|
||||
dst_view: &mut impl ImageViewMut<Pixel = P>,
|
||||
filter_type: FilterType,
|
||||
adaptive_kernel_size: bool,
|
||||
use_alpha: bool,
|
||||
) {
|
||||
if use_alpha && self.mul_div.is_supported(P::pixel_type()) {
|
||||
@@ -315,7 +337,12 @@ impl Resizer {
|
||||
cropped_src_view.crop_box(),
|
||||
)
|
||||
};
|
||||
self.do_convolution(&cropped_premultiplied_src, dst_view, filter_type);
|
||||
self.do_convolution(
|
||||
&cropped_premultiplied_src,
|
||||
dst_view,
|
||||
filter_type,
|
||||
adaptive_kernel_size,
|
||||
);
|
||||
self.mul_div.divide_alpha_inplace_typed(dst_view).unwrap();
|
||||
self.alpha_buffer = alpha_buffer;
|
||||
return;
|
||||
@@ -323,7 +350,12 @@ impl Resizer {
|
||||
self.alpha_buffer = alpha_buffer;
|
||||
}
|
||||
|
||||
self.do_convolution(cropped_src_view, dst_view, filter_type);
|
||||
self.do_convolution(
|
||||
cropped_src_view,
|
||||
dst_view,
|
||||
filter_type,
|
||||
adaptive_kernel_size,
|
||||
);
|
||||
}
|
||||
|
||||
fn do_convolution<P: PixelTrait>(
|
||||
@@ -331,6 +363,7 @@ impl Resizer {
|
||||
cropped_src_view: &CroppedSrcImageView<impl ImageView<Pixel = P>>,
|
||||
dst_view: &mut impl ImageViewMut<Pixel = P>,
|
||||
filter_type: FilterType,
|
||||
adaptive_kernel_size: bool,
|
||||
) {
|
||||
let src_view = cropped_src_view.image_view();
|
||||
let crop_box = cropped_src_view.crop_box();
|
||||
@@ -352,6 +385,7 @@ impl Resizer {
|
||||
dst_width,
|
||||
filter_fn,
|
||||
filter_support,
|
||||
adaptive_kernel_size,
|
||||
)
|
||||
});
|
||||
|
||||
@@ -366,13 +400,14 @@ impl Resizer {
|
||||
dst_height,
|
||||
filter_fn,
|
||||
filter_support,
|
||||
adaptive_kernel_size,
|
||||
)
|
||||
});
|
||||
|
||||
match (horiz_coeffs, vert_coeffs) {
|
||||
(Some(mut horiz_coeffs), Some(mut vert_coeffs)) => {
|
||||
if P::components_is_u8() {
|
||||
// For an u8-based images it is faster to do the vertical pass first
|
||||
// For u8-based images, it is faster to do the vertical pass first
|
||||
// instead of the horizontal.
|
||||
let x_first = horiz_coeffs.bounds[0].start;
|
||||
// Last used col in the source image
|
||||
@@ -475,7 +510,7 @@ impl Resizer {
|
||||
// size is greater than the required size by multiplicity times.
|
||||
let factor = width_scale.min(height_scale) / multiplicity as f64;
|
||||
if factor > 1.2 {
|
||||
// First step is resizing the source image by fastest algorithm.
|
||||
// The first step is resizing the source image by the fastest algorithm.
|
||||
// The temporary image will be about ``multiplicity`` times larger
|
||||
// than required.
|
||||
let tmp_width = (crop_box.width / factor).round() as u32;
|
||||
@@ -485,14 +520,14 @@ impl Resizer {
|
||||
let mut tmp_img =
|
||||
get_temp_image_from_buffer(&mut super_sampling_buffer, tmp_width, tmp_height);
|
||||
resample_nearest(cropped_src_view, &mut tmp_img);
|
||||
// Second step is resizing the temporary image with a convolution.
|
||||
// The second step is resizing the temporary image with a convolution.
|
||||
let cropped_tmp_img = CroppedSrcImageView::new(&tmp_img);
|
||||
self.resample_convolution(&cropped_tmp_img, dst_view, filter_type, use_alpha);
|
||||
self.resample_convolution(&cropped_tmp_img, dst_view, filter_type, true, use_alpha);
|
||||
self.super_sampling_buffer = super_sampling_buffer;
|
||||
} else {
|
||||
// There is no point in doing the resizing in two steps.
|
||||
// We immediately resize the original image with a convolution.
|
||||
self.resample_convolution(cropped_src_view, dst_view, filter_type, use_alpha);
|
||||
self.resample_convolution(cropped_src_view, dst_view, filter_type, true, use_alpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,5 +9,9 @@ fast_image_resize = { path = "..", features = ["for_testing"] }
|
||||
image = "0.25.1"
|
||||
|
||||
|
||||
[features]
|
||||
only_u8x4 = [] # This can be used to experiment with the crate's code.
|
||||
|
||||
|
||||
[package.metadata.release]
|
||||
publish = false
|
||||
|
||||
+193
-188
@@ -163,48 +163,210 @@ pub trait PixelTestingExt: PixelTrait {
|
||||
fn img_into_bytes(img: ImageBuffer<Self::ImagePixel, Self::Container>) -> Vec<u8>;
|
||||
}
|
||||
|
||||
impl PixelTestingExt for U8 {
|
||||
type ImagePixel = image::Luma<u8>;
|
||||
type Container = Vec<u8>;
|
||||
#[cfg(not(feature = "only_u8x4"))]
|
||||
pub mod not_u8x4 {
|
||||
use super::*;
|
||||
|
||||
fn load_image_buffer(
|
||||
img_reader: Reader<BufReader<File>>,
|
||||
) -> ImageBuffer<Self::ImagePixel, Self::Container> {
|
||||
img_reader.decode().unwrap().to_luma8()
|
||||
impl PixelTestingExt for U8 {
|
||||
type ImagePixel = image::Luma<u8>;
|
||||
type Container = Vec<u8>;
|
||||
|
||||
fn load_image_buffer(
|
||||
img_reader: Reader<BufReader<File>>,
|
||||
) -> ImageBuffer<Self::ImagePixel, Self::Container> {
|
||||
img_reader.decode().unwrap().to_luma8()
|
||||
}
|
||||
|
||||
fn img_into_bytes(img: ImageBuffer<Self::ImagePixel, Self::Container>) -> Vec<u8> {
|
||||
img.into_raw()
|
||||
}
|
||||
}
|
||||
|
||||
fn img_into_bytes(img: ImageBuffer<Self::ImagePixel, Self::Container>) -> Vec<u8> {
|
||||
img.into_raw()
|
||||
}
|
||||
}
|
||||
impl PixelTestingExt for U8x2 {
|
||||
type ImagePixel = image::LumaA<u8>;
|
||||
type Container = Vec<u8>;
|
||||
|
||||
impl PixelTestingExt for U8x2 {
|
||||
type ImagePixel = image::LumaA<u8>;
|
||||
type Container = Vec<u8>;
|
||||
fn load_image_buffer(
|
||||
img_reader: Reader<BufReader<File>>,
|
||||
) -> ImageBuffer<Self::ImagePixel, Self::Container> {
|
||||
img_reader.decode().unwrap().to_luma_alpha8()
|
||||
}
|
||||
|
||||
fn load_image_buffer(
|
||||
img_reader: Reader<BufReader<File>>,
|
||||
) -> ImageBuffer<Self::ImagePixel, Self::Container> {
|
||||
img_reader.decode().unwrap().to_luma_alpha8()
|
||||
fn img_into_bytes(img: ImageBuffer<Self::ImagePixel, Self::Container>) -> Vec<u8> {
|
||||
img.into_raw()
|
||||
}
|
||||
}
|
||||
|
||||
fn img_into_bytes(img: ImageBuffer<Self::ImagePixel, Self::Container>) -> Vec<u8> {
|
||||
img.into_raw()
|
||||
}
|
||||
}
|
||||
impl PixelTestingExt for U8x3 {
|
||||
type ImagePixel = image::Rgb<u8>;
|
||||
type Container = Vec<u8>;
|
||||
|
||||
impl PixelTestingExt for U8x3 {
|
||||
type ImagePixel = image::Rgb<u8>;
|
||||
type Container = Vec<u8>;
|
||||
fn load_image_buffer(
|
||||
img_reader: Reader<BufReader<File>>,
|
||||
) -> ImageBuffer<Self::ImagePixel, Self::Container> {
|
||||
img_reader.decode().unwrap().to_rgb8()
|
||||
}
|
||||
|
||||
fn load_image_buffer(
|
||||
img_reader: Reader<BufReader<File>>,
|
||||
) -> ImageBuffer<Self::ImagePixel, Self::Container> {
|
||||
img_reader.decode().unwrap().to_rgb8()
|
||||
fn img_into_bytes(img: ImageBuffer<Self::ImagePixel, Self::Container>) -> Vec<u8> {
|
||||
img.into_raw()
|
||||
}
|
||||
}
|
||||
|
||||
fn img_into_bytes(img: ImageBuffer<Self::ImagePixel, Self::Container>) -> Vec<u8> {
|
||||
img.into_raw()
|
||||
impl PixelTestingExt for U16 {
|
||||
type ImagePixel = image::Luma<u16>;
|
||||
type Container = Vec<u16>;
|
||||
|
||||
fn load_image_buffer(
|
||||
img_reader: Reader<BufReader<File>>,
|
||||
) -> ImageBuffer<Self::ImagePixel, Self::Container> {
|
||||
img_reader.decode().unwrap().to_luma16()
|
||||
}
|
||||
|
||||
fn img_into_bytes(img: ImageBuffer<Self::ImagePixel, Self::Container>) -> Vec<u8> {
|
||||
// img.as_raw()
|
||||
// .iter()
|
||||
// .enumerate()
|
||||
// .flat_map(|(i, &c)| ((i & 0xffff) as u16).to_le_bytes())
|
||||
// .collect()
|
||||
img.as_raw().iter().flat_map(|&c| c.to_le_bytes()).collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl PixelTestingExt for U16x2 {
|
||||
type ImagePixel = image::LumaA<u16>;
|
||||
type Container = Vec<u16>;
|
||||
|
||||
fn load_image_buffer(
|
||||
img_reader: Reader<BufReader<File>>,
|
||||
) -> ImageBuffer<Self::ImagePixel, Self::Container> {
|
||||
img_reader.decode().unwrap().to_luma_alpha16()
|
||||
}
|
||||
|
||||
fn img_into_bytes(img: ImageBuffer<Self::ImagePixel, Self::Container>) -> Vec<u8> {
|
||||
img.as_raw().iter().flat_map(|&c| c.to_le_bytes()).collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl PixelTestingExt for U16x3 {
|
||||
type ImagePixel = image::Rgb<u16>;
|
||||
type Container = Vec<u16>;
|
||||
|
||||
fn load_image_buffer(
|
||||
img_reader: Reader<BufReader<File>>,
|
||||
) -> ImageBuffer<Self::ImagePixel, Self::Container> {
|
||||
img_reader.decode().unwrap().to_rgb16()
|
||||
}
|
||||
|
||||
fn img_into_bytes(img: ImageBuffer<Self::ImagePixel, Self::Container>) -> Vec<u8> {
|
||||
img.as_raw().iter().flat_map(|&c| c.to_le_bytes()).collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl PixelTestingExt for U16x4 {
|
||||
type ImagePixel = image::Rgba<u16>;
|
||||
type Container = Vec<u16>;
|
||||
|
||||
fn load_image_buffer(
|
||||
img_reader: Reader<BufReader<File>>,
|
||||
) -> ImageBuffer<Self::ImagePixel, Self::Container> {
|
||||
img_reader.decode().unwrap().to_rgba16()
|
||||
}
|
||||
|
||||
fn img_into_bytes(img: ImageBuffer<Self::ImagePixel, Self::Container>) -> Vec<u8> {
|
||||
img.as_raw().iter().flat_map(|&c| c.to_le_bytes()).collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl PixelTestingExt for I32 {
|
||||
type ImagePixel = image::Luma<i32>;
|
||||
type Container = Vec<i32>;
|
||||
|
||||
fn cpu_extensions() -> Vec<CpuExtensions> {
|
||||
vec![CpuExtensions::None]
|
||||
}
|
||||
|
||||
fn load_image_buffer(
|
||||
img_reader: Reader<BufReader<File>>,
|
||||
) -> ImageBuffer<Self::ImagePixel, Self::Container> {
|
||||
let image_u16 = img_reader.decode().unwrap().to_luma32f();
|
||||
ImageBuffer::from_fn(image_u16.width(), image_u16.height(), |x, y| {
|
||||
let pixel = image_u16.get_pixel(x, y);
|
||||
image::Luma::from([(pixel.0[0] * i32::MAX as f32).round() as i32])
|
||||
})
|
||||
}
|
||||
|
||||
fn img_into_bytes(img: ImageBuffer<Self::ImagePixel, Self::Container>) -> Vec<u8> {
|
||||
img.as_raw()
|
||||
.iter()
|
||||
.flat_map(|val| val.to_le_bytes())
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl PixelTestingExt for F32 {
|
||||
type ImagePixel = image::Luma<f32>;
|
||||
type Container = Vec<f32>;
|
||||
|
||||
fn load_image_buffer(
|
||||
img_reader: Reader<BufReader<File>>,
|
||||
) -> ImageBuffer<Self::ImagePixel, Self::Container> {
|
||||
img_reader.decode().unwrap().to_luma32f()
|
||||
}
|
||||
|
||||
fn img_into_bytes(img: ImageBuffer<Self::ImagePixel, Self::Container>) -> Vec<u8> {
|
||||
img.as_raw()
|
||||
.iter()
|
||||
.flat_map(|val| val.to_le_bytes())
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl PixelTestingExt for F32x2 {
|
||||
type ImagePixel = image::LumaA<f32>;
|
||||
type Container = Vec<f32>;
|
||||
|
||||
fn load_image_buffer(
|
||||
img_reader: Reader<BufReader<File>>,
|
||||
) -> ImageBuffer<Self::ImagePixel, Self::Container> {
|
||||
img_reader.decode().unwrap().to_luma_alpha32f()
|
||||
}
|
||||
|
||||
fn img_into_bytes(img: ImageBuffer<Self::ImagePixel, Self::Container>) -> Vec<u8> {
|
||||
img.as_raw()
|
||||
.iter()
|
||||
.flat_map(|val| val.to_le_bytes())
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl PixelTestingExt for F32x3 {
|
||||
type ImagePixel = image::Rgb<f32>;
|
||||
type Container = Vec<f32>;
|
||||
|
||||
fn load_image_buffer(
|
||||
img_reader: Reader<BufReader<File>>,
|
||||
) -> ImageBuffer<Self::ImagePixel, Self::Container> {
|
||||
img_reader.decode().unwrap().to_rgb32f()
|
||||
}
|
||||
|
||||
fn img_into_bytes(img: ImageBuffer<Self::ImagePixel, Self::Container>) -> Vec<u8> {
|
||||
img.as_raw().iter().flat_map(|&c| c.to_le_bytes()).collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl PixelTestingExt for F32x4 {
|
||||
type ImagePixel = image::Rgba<f32>;
|
||||
type Container = Vec<f32>;
|
||||
|
||||
fn load_image_buffer(
|
||||
img_reader: Reader<BufReader<File>>,
|
||||
) -> ImageBuffer<Self::ImagePixel, Self::Container> {
|
||||
img_reader.decode().unwrap().to_rgba32f()
|
||||
}
|
||||
|
||||
fn img_into_bytes(img: ImageBuffer<Self::ImagePixel, Self::Container>) -> Vec<u8> {
|
||||
img.as_raw().iter().flat_map(|&c| c.to_le_bytes()).collect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,163 +385,6 @@ impl PixelTestingExt for U8x4 {
|
||||
}
|
||||
}
|
||||
|
||||
impl PixelTestingExt for U16 {
|
||||
type ImagePixel = image::Luma<u16>;
|
||||
type Container = Vec<u16>;
|
||||
|
||||
fn load_image_buffer(
|
||||
img_reader: Reader<BufReader<File>>,
|
||||
) -> ImageBuffer<Self::ImagePixel, Self::Container> {
|
||||
img_reader.decode().unwrap().to_luma16()
|
||||
}
|
||||
|
||||
fn img_into_bytes(img: ImageBuffer<Self::ImagePixel, Self::Container>) -> Vec<u8> {
|
||||
// img.as_raw()
|
||||
// .iter()
|
||||
// .enumerate()
|
||||
// .flat_map(|(i, &c)| ((i & 0xffff) as u16).to_le_bytes())
|
||||
// .collect()
|
||||
img.as_raw().iter().flat_map(|&c| c.to_le_bytes()).collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl PixelTestingExt for U16x2 {
|
||||
type ImagePixel = image::LumaA<u16>;
|
||||
type Container = Vec<u16>;
|
||||
|
||||
fn load_image_buffer(
|
||||
img_reader: Reader<BufReader<File>>,
|
||||
) -> ImageBuffer<Self::ImagePixel, Self::Container> {
|
||||
img_reader.decode().unwrap().to_luma_alpha16()
|
||||
}
|
||||
|
||||
fn img_into_bytes(img: ImageBuffer<Self::ImagePixel, Self::Container>) -> Vec<u8> {
|
||||
img.as_raw().iter().flat_map(|&c| c.to_le_bytes()).collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl PixelTestingExt for U16x3 {
|
||||
type ImagePixel = image::Rgb<u16>;
|
||||
type Container = Vec<u16>;
|
||||
|
||||
fn load_image_buffer(
|
||||
img_reader: Reader<BufReader<File>>,
|
||||
) -> ImageBuffer<Self::ImagePixel, Self::Container> {
|
||||
img_reader.decode().unwrap().to_rgb16()
|
||||
}
|
||||
|
||||
fn img_into_bytes(img: ImageBuffer<Self::ImagePixel, Self::Container>) -> Vec<u8> {
|
||||
img.as_raw().iter().flat_map(|&c| c.to_le_bytes()).collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl PixelTestingExt for U16x4 {
|
||||
type ImagePixel = image::Rgba<u16>;
|
||||
type Container = Vec<u16>;
|
||||
|
||||
fn load_image_buffer(
|
||||
img_reader: Reader<BufReader<File>>,
|
||||
) -> ImageBuffer<Self::ImagePixel, Self::Container> {
|
||||
img_reader.decode().unwrap().to_rgba16()
|
||||
}
|
||||
|
||||
fn img_into_bytes(img: ImageBuffer<Self::ImagePixel, Self::Container>) -> Vec<u8> {
|
||||
img.as_raw().iter().flat_map(|&c| c.to_le_bytes()).collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl PixelTestingExt for I32 {
|
||||
type ImagePixel = image::Luma<i32>;
|
||||
type Container = Vec<i32>;
|
||||
|
||||
fn cpu_extensions() -> Vec<CpuExtensions> {
|
||||
vec![CpuExtensions::None]
|
||||
}
|
||||
|
||||
fn load_image_buffer(
|
||||
img_reader: Reader<BufReader<File>>,
|
||||
) -> ImageBuffer<Self::ImagePixel, Self::Container> {
|
||||
let image_u16 = img_reader.decode().unwrap().to_luma32f();
|
||||
ImageBuffer::from_fn(image_u16.width(), image_u16.height(), |x, y| {
|
||||
let pixel = image_u16.get_pixel(x, y);
|
||||
image::Luma::from([(pixel.0[0] * i32::MAX as f32).round() as i32])
|
||||
})
|
||||
}
|
||||
|
||||
fn img_into_bytes(img: ImageBuffer<Self::ImagePixel, Self::Container>) -> Vec<u8> {
|
||||
img.as_raw()
|
||||
.iter()
|
||||
.flat_map(|val| val.to_le_bytes())
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl PixelTestingExt for F32 {
|
||||
type ImagePixel = image::Luma<f32>;
|
||||
type Container = Vec<f32>;
|
||||
|
||||
fn load_image_buffer(
|
||||
img_reader: Reader<BufReader<File>>,
|
||||
) -> ImageBuffer<Self::ImagePixel, Self::Container> {
|
||||
img_reader.decode().unwrap().to_luma32f()
|
||||
}
|
||||
|
||||
fn img_into_bytes(img: ImageBuffer<Self::ImagePixel, Self::Container>) -> Vec<u8> {
|
||||
img.as_raw()
|
||||
.iter()
|
||||
.flat_map(|val| val.to_le_bytes())
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl PixelTestingExt for F32x2 {
|
||||
type ImagePixel = image::LumaA<f32>;
|
||||
type Container = Vec<f32>;
|
||||
|
||||
fn load_image_buffer(
|
||||
img_reader: Reader<BufReader<File>>,
|
||||
) -> ImageBuffer<Self::ImagePixel, Self::Container> {
|
||||
img_reader.decode().unwrap().to_luma_alpha32f()
|
||||
}
|
||||
|
||||
fn img_into_bytes(img: ImageBuffer<Self::ImagePixel, Self::Container>) -> Vec<u8> {
|
||||
img.as_raw()
|
||||
.iter()
|
||||
.flat_map(|val| val.to_le_bytes())
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl PixelTestingExt for F32x3 {
|
||||
type ImagePixel = image::Rgb<f32>;
|
||||
type Container = Vec<f32>;
|
||||
|
||||
fn load_image_buffer(
|
||||
img_reader: Reader<BufReader<File>>,
|
||||
) -> ImageBuffer<Self::ImagePixel, Self::Container> {
|
||||
img_reader.decode().unwrap().to_rgb32f()
|
||||
}
|
||||
|
||||
fn img_into_bytes(img: ImageBuffer<Self::ImagePixel, Self::Container>) -> Vec<u8> {
|
||||
img.as_raw().iter().flat_map(|&c| c.to_le_bytes()).collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl PixelTestingExt for F32x4 {
|
||||
type ImagePixel = image::Rgba<f32>;
|
||||
type Container = Vec<f32>;
|
||||
|
||||
fn load_image_buffer(
|
||||
img_reader: Reader<BufReader<File>>,
|
||||
) -> ImageBuffer<Self::ImagePixel, Self::Container> {
|
||||
img_reader.decode().unwrap().to_rgba32f()
|
||||
}
|
||||
|
||||
fn img_into_bytes(img: ImageBuffer<Self::ImagePixel, Self::Container>) -> Vec<u8> {
|
||||
img.as_raw().iter().flat_map(|&c| c.to_le_bytes()).collect()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn save_result(image: &Image, name: &str) {
|
||||
if std::env::var("SAVE_RESULT").unwrap_or_else(|_| "".to_owned()) == "" {
|
||||
return;
|
||||
|
||||
@@ -2,6 +2,7 @@ use fast_image_resize as fr;
|
||||
use fast_image_resize::images::Image;
|
||||
use fast_image_resize::pixels::*;
|
||||
|
||||
#[cfg(not(feature = "only_u8x4"))]
|
||||
mod gamma_tests {
|
||||
use super::*;
|
||||
|
||||
@@ -78,6 +79,7 @@ mod gamma_tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "only_u8x4"))]
|
||||
mod srgb_tests {
|
||||
use super::*;
|
||||
|
||||
|
||||
@@ -311,6 +311,16 @@ where
|
||||
FilterType::Lanczos3 => "lanczos3",
|
||||
_ => "unknown",
|
||||
},
|
||||
ResizeAlg::Interpolation(filter) => match filter {
|
||||
FilterType::Box => "inter_box",
|
||||
FilterType::Bilinear => "inter_bilinear",
|
||||
FilterType::Hamming => "inter_hamming",
|
||||
FilterType::Mitchell => "inter_mitchell",
|
||||
FilterType::CatmullRom => "inter_catmullrom",
|
||||
FilterType::Gaussian => "inter_gaussian",
|
||||
FilterType::Lanczos3 => "inter_lanczos3",
|
||||
_ => "inter_unknown",
|
||||
},
|
||||
ResizeAlg::SuperSampling(_, _) => "supersampling",
|
||||
_ => "unknown",
|
||||
};
|
||||
@@ -1026,3 +1036,19 @@ mod u8x4 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "only_u8x4"))]
|
||||
#[test]
|
||||
fn resize_u8x3_interpolation() {
|
||||
U8x3::downscale_test(
|
||||
ResizeAlg::Interpolation(FilterType::Bilinear),
|
||||
CpuExtensions::None,
|
||||
[2938733, 2946338, 2883813],
|
||||
);
|
||||
|
||||
U8x3::upscale_test(
|
||||
ResizeAlg::Interpolation(FilterType::Bilinear),
|
||||
CpuExtensions::None,
|
||||
[1156013474, 1158419787, 1135090328],
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user