34个版本
新 0.2.8 | 2024年8月23日 |
---|---|
0.2.7 | 2024年8月20日 |
0.2.0 | 2024年7月29日 |
0.1.24 | 2024年7月23日 |
0.1.16 | 2024年6月21日 |
#58 in 图像
1,197 每月下载量
1MB
25K SLoC
Rust图像缩放库
使用SIMD和多线程在Rust中对不同色彩空间进行图像缩放。
支持NEON、SSE、AVX-2、RISC-V(向量扩展)。
色彩空间
此库为您提供在不同色彩空间中缩放的便利。
预构建选项包括CIE L*a*b、CIE L*u*v、CIE L*c*h、线性、Sigmoidal、Oklab、Jzazbz。
这些转换也非常高效。建议在线性色彩空间或XYZ中进行降级。
升级可能通过LAB/LUB和模拟化组件进行,在sRGB中也同样高效。
具有良好的f16(二进制浮点16)支持。
使用image
crate的示例集成
let img = ImageReader::open("./assets/asset.png")
.unwrap()
.decode()
.unwrap();
let dimensions = img.dimensions();
let mut bytes = Vec::from(img.as_bytes());
let mut scaler = LinearScaler::new(ResamplingFunction::Lanczos3);
scaler.set_threading_policy(ThreadingPolicy::Adaptive);
// ImageStore::<u8, 4> - (u8, 4) represents RGBA, (u8, 3) - RGB etc
let store =
ImageStore::<u8, 4>::from_slice(&mut bytes, dimensions.0 as usize, dimensions.1 as usize).unwrap();
let resized = scaler.resize_rgba(
ImageSize::new(dimensions.0 as usize / 2, dimensions.1 as usize / 2),
store,
true
);
let resized_image = resized.as_bytes();
使用SIMD的最快路径
尽管所有实现都很快,但并非所有路径都使用SIMD实现,因此某些路径较慢
~
- 部分实现
NEON | SSE | AVX | RISC-V | WASM | |
---|---|---|---|---|---|
RGBA (8位) | x | x | ~ | x | x |
RGB (8位) | x | x | ~ | ~ | x |
平面 (8位) | x | x | ~ | ~ | ~ |
RGBA (8+位) | x | x | ~ | - | - |
RGB (8+位) | x | x | ~ | - | - |
平面 (8+位) | ~ | ~ | ~ | - | - |
RGBA (f32) | x | x | x | x | - |
RGB (f32) | x | x | ~ | ~ | - |
平面 (f32) | x | x | ~ | ~ | - |
RGBA (f16) | x | x | x | x | - |
RGB (f16) | x | ~ | ~ | ~ | - |
平面 (f16) | ~ | ~ | ~ | ~ | - |
特性
对于RISC-V riscv
特性应隐式启用,需要夜间编译器通道。
要启用对f16
的支持,应激活half
特性。
目标特性
neon
可选目标特性可用,在支持的平台上进行编译时启用它以获取完整特性
avx2
、fma
、sse4.1
、f16c
将在可用时自动检测,并调用最佳路径
fullfp16
NEON目标检测在运行时执行,当可用时,在ARM上提供最佳路径以处理f16图像。
如果启用特性 riscv
并且可用,则在运行时将检测到 RISC-V V (向量扩展)
。需要使用 Nightly rust 频道。
在构建标志中强制激活 WASM simd128
目标特性。
关于 f16
要启用对 f16 的全面支持,应使用 half
特性,并在针对 x86 平台时启用 f16c》。对于 NEON
f16
特性,使用运行时检测,如果 CPU 支持此特性,则可使用非常快速的路径。
即使激活了 half
特性,但平台不支持或未启用 f16
特性,速度将较慢。
对于 RISC-V V
和 zfh
,以及 zvfh
,需要 CPU 支持,以使用最快的路径。
性能
以下是使用 fast-image-resize
时间比较,将 RGB 4928x3279 图像缩小两倍。
Lanczos3 | SSE | AVX | NEON |
---|---|---|---|
pic-scale | 43.84 | 33.98 | 23.48 |
fir sse | 45.36 | 36.05 | 36.69 |
使用预乘 alpha 的 RGBA 4928x3279 图像在两倍缩小时的比较示例时间。
Lanczos3 | SSE | AVX | NEON |
---|---|---|---|
pic-scale | 68.51 | 47.33 | 35.67 |
fir sse | 73.28 | 54.66 | 54.66 |
不使用预乘 alpha 的 RGBA 4928x3279 图像在两倍缩小时的比较示例时间。
Lanczos3 | SSE | AVX | NEON |
---|---|---|---|
pic-scale | 52.42 | 38.37 | 28.75 |
fir sse | 51.89 | 39.82 | 44.54 |
使用预乘 alpha 的 RGBA 4928x3279 10 位图像在两倍缩小时的比较示例时间。
Lanczos3 | SSE | NEON |
---|---|---|
pic-scale | 156.90 | 62.44 |
fir sse | 150.65 | 91.08 |
不使用预乘 alpha 的 RGBA 4928x3279 10 位图像在两倍缩小。
Lanczos3 | SSE | NEON |
---|---|---|
pic-scale | 156.90 | 45.09 |
fir sse | 150.65 | 73.82 |
使用 NEON 将 RGB 4000x6000 10 位图像缩小两倍的比较示例时间。
Lanczos3 | SSE | NEON |
---|---|---|
pic-scale | 138.75 | 56.89 |
fir sse | 125.85 | 100.36 |
在 sRGB 中的示例
通常,您不应在 sRGB 颜色空间中缩小图像,但如果速度比更合适的缩放更重要,则可以省略线性化。
let mut scaler = Scaler::new(ResamplingFunction::Hermite);
scaler.set_threading_policy(ThreadingPolicy::Single);
let store =
ImageStore::<u8, 4>::from_slice(&mut bytes, width, height).unwrap();
let resized = scaler.resize_rgba(
ImageSize::new(new_width, new_height),
store,
true
);
在线性中的示例
目前仅支持 sRGB 转换函数。这也是一个很好的优化路径,因此速度相当快。
let mut scaler = LinearScaler::new(ResamplingFunction::Lanczos3);
scaler.set_threading_policy(ThreadingPolicy::Single);
let store =
ImageStore::<u8, 4>::from_slice(&mut bytes, width, height).unwrap();
let resized = scaler.resize_rgba(
ImageSize::new(new_width, new_height),
store,
true
);
CIE L*a*b 中的示例
let mut scaler = LabScaler::new(ResamplingFunction::Hermite);
scaler.set_threading_policy(ThreadingPolicy::Single);
let store =
ImageStore::<u8, 4>::from_slice(&mut bytes, width, height).unwrap();
let resized = scaler.resize_rgba(
ImageSize::new(new_width, new_height),
store,
true
);
CIE L*u*v 中的示例
let mut scaler = LuvScaler::new(ResamplingFunction::Hermite);
scaler.set_threading_policy(ThreadingPolicy::Single);
let store =
ImageStore::<u8, 4>::from_slice(&mut bytes, width, height).unwrap();
let resized = scaler.resize_rgba(
ImageSize::new(new_width, new_height),
store,
true
);
CIE XYZ 颜色空间中的示例
let mut scaler = XYZScale::new(ResamplingFunction::Hermite);
scaler.set_threading_policy(ThreadingPolicy::Single);
let store =
ImageStore::<u8, 4>::from_slice(&mut bytes, width, height).unwrap();
let resized = scaler.resize_rgba(
ImageSize::new(new_width, new_height),
store,
true
);
sigmoidal 颜色空间中的示例
let mut scaler = SigmoidalScaler::new(ResamplingFunction::Hermite);
scaler.set_threading_policy(ThreadingPolicy::Single);
let store =
ImageStore::<u8, 4>::from_slice(&mut bytes, width, height).unwrap();
let resized = scaler.resize_rgba(
ImageSize::new(new_width, new_height),
store,
true
);
LCh 颜色空间中的示例
let mut scaler = LChScaler::new(ResamplingFunction::Hermite);
scaler.set_threading_policy(ThreadingPolicy::Single);
let store =
ImageStore::<u8, 4>::from_slice(&mut bytes, width, height).unwrap();
let resized = scaler.resize_rgba(
ImageSize::new(new_width, new_height),
store,
true
);
Oklab 颜色空间中的示例
let mut scaler = OklabScaler::new(ResamplingFunction::Hermite);
scaler.set_threading_policy(ThreadingPolicy::Single);
let store =
ImageStore::<u8, 4>::from_slice(&mut bytes, width, height).unwrap();
let resized = scaler.resize_rgba(
ImageSize::new(new_width, new_height),
store,
true
);
重采样滤波器
支持超过 30 种重采样滤波器。
Bilinear
Nearest
Cubic
MitchellNetravalli
CatmullRom
Hermite
BSpline
Hann
Bicubic
Hamming
Hanning
Blackman
以及其他
依赖项
~3MB
~68K SLoC