This commit is contained in:
@@ -38,6 +38,7 @@ const WEBP_TARGET_MAX_QUALITY: u8 = 100;
|
|||||||
const AVIF_TARGET_MAX_QUALITY: u8 = 100;
|
const AVIF_TARGET_MAX_QUALITY: u8 = 100;
|
||||||
const AVIF_ENCODER_SPEED: u8 = 5;
|
const AVIF_ENCODER_SPEED: u8 = 5;
|
||||||
const WEBP_TARGET_SAFETY_PERCENT: u64 = 97;
|
const WEBP_TARGET_SAFETY_PERCENT: u64 = 97;
|
||||||
|
const WEBP_HIGH_EFFORT_LOSSLESS_MAX_PIXELS: u64 = 2_100_000;
|
||||||
const METADATA_TARGET_OVERHEAD: u64 = 1024;
|
const METADATA_TARGET_OVERHEAD: u64 = 1024;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -1009,7 +1010,7 @@ fn encode_webp_lossless_pixels(pixels: &TargetPixels) -> Result<Vec<u8>, AppErro
|
|||||||
.map_err(|_| AppError::new(ErrorCode::CompressionFailed, "初始化 WebP 无损配置失败"))?;
|
.map_err(|_| AppError::new(ErrorCode::CompressionFailed, "初始化 WebP 无损配置失败"))?;
|
||||||
config.lossless = 1;
|
config.lossless = 1;
|
||||||
config.quality = 100.0;
|
config.quality = 100.0;
|
||||||
config.method = 6;
|
config.method = webp_lossless_method(pixels);
|
||||||
config.alpha_compression = 1;
|
config.alpha_compression = 1;
|
||||||
config.near_lossless = 100;
|
config.near_lossless = 100;
|
||||||
config.exact = 1;
|
config.exact = 1;
|
||||||
@@ -1026,6 +1027,15 @@ fn encode_webp_lossless_pixels(pixels: &TargetPixels) -> Result<Vec<u8>, AppErro
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn webp_lossless_method(pixels: &TargetPixels) -> i32 {
|
||||||
|
let pixel_count = u64::from(pixels.width).saturating_mul(u64::from(pixels.height));
|
||||||
|
if pixel_count <= WEBP_HIGH_EFFORT_LOSSLESS_MAX_PIXELS {
|
||||||
|
6
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn encode_avif_target(
|
fn encode_avif_target(
|
||||||
image: DynamicImage,
|
image: DynamicImage,
|
||||||
target_size: u64,
|
target_size: u64,
|
||||||
@@ -2035,6 +2045,25 @@ mod tests {
|
|||||||
assert_eq!(output, max_lossy);
|
assert_eq!(output, max_lossy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn large_webp_targets_use_the_fast_lossless_probe() {
|
||||||
|
let small = TargetPixels {
|
||||||
|
bytes: Vec::new(),
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
layout: TargetPixelLayout::Rgb,
|
||||||
|
};
|
||||||
|
let large = TargetPixels {
|
||||||
|
bytes: Vec::new(),
|
||||||
|
width: 4096,
|
||||||
|
height: 3072,
|
||||||
|
layout: TargetPixelLayout::Rgb,
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(webp_lossless_method(&small), 6);
|
||||||
|
assert_eq!(webp_lossless_method(&large), 0);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn jpeg_target_encoder_prefers_perceptual_downscaling() {
|
fn jpeg_target_encoder_prefers_perceptual_downscaling() {
|
||||||
let image = DynamicImage::ImageRgb8(RgbImage::from_fn(800, 600, |x, y| {
|
let image = DynamicImage::ImageRgb8(RgbImage::from_fn(800, 600, |x, y| {
|
||||||
|
|||||||
Reference in New Issue
Block a user