fix: bound large WebP lossless probe cost
Some checks failed
CI / verify (push) Has been cancelled

This commit is contained in:
237899745
2026-07-26 12:22:53 +08:00
parent 66454b6325
commit 03b3a08185

View File

@@ -38,6 +38,7 @@ const WEBP_TARGET_MAX_QUALITY: u8 = 100;
const AVIF_TARGET_MAX_QUALITY: u8 = 100;
const AVIF_ENCODER_SPEED: u8 = 5;
const WEBP_TARGET_SAFETY_PERCENT: u64 = 97;
const WEBP_HIGH_EFFORT_LOSSLESS_MAX_PIXELS: u64 = 2_100_000;
const METADATA_TARGET_OVERHEAD: u64 = 1024;
#[derive(Clone)]
@@ -1009,7 +1010,7 @@ fn encode_webp_lossless_pixels(pixels: &TargetPixels) -> Result<Vec<u8>, AppErro
.map_err(|_| AppError::new(ErrorCode::CompressionFailed, "初始化 WebP 无损配置失败"))?;
config.lossless = 1;
config.quality = 100.0;
config.method = 6;
config.method = webp_lossless_method(pixels);
config.alpha_compression = 1;
config.near_lossless = 100;
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(
image: DynamicImage,
target_size: u64,
@@ -2035,6 +2045,25 @@ mod tests {
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]
fn jpeg_target_encoder_prefers_perceptual_downscaling() {
let image = DynamicImage::ImageRgb8(RgbImage::from_fn(800, 600, |x, y| {