Skip to content

Commit 76590c9

Browse files
committed
fix: propagate per-codec quality to quality_fallback in Format preset
When `format=webp&quality=5` is used, the generic `quality=` param flows through per-codec encoder hints (webp.quality) but never reaches CodecIntent.quality_fallback. This caused effective_quality() to return the default 73.0 instead of 5.0, producing oversized WebP output. Two fixes in preset_map.rs: - Extract per-codec quality from encoder hints into quality_fallback when quality_profile (from qp=) is absent - Map webp.quality to per-codec hints (was only mapping lossless)
1 parent e33b73f commit 76590c9

File tree

2 files changed

+29
-0
lines changed

2 files changed

+29
-0
lines changed

imageflow_core/src/zen/preset_map.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,28 @@ pub fn map_preset(preset: &EncoderPreset) -> Result<PresetMapping, TranslateErro
7878
// lossless hints (webp.lossless=true) are available.
7979
if let Some(hints) = encoder_hints {
8080
intent.hints = map_encoder_hints(hints);
81+
82+
// When no quality profile is set, extract per-codec quality
83+
// from encoder hints as the fallback. This handles the common
84+
// case of `format=webp&quality=5` where the generic `quality=`
85+
// param flows through per-codec hints but not through `qp=`.
86+
if intent.quality_profile.is_none() {
87+
let codec_quality = match zen_format {
88+
zencodecs::ImageFormat::WebP => {
89+
hints.webp.as_ref().and_then(|w| w.quality)
90+
}
91+
zencodecs::ImageFormat::Jpeg => {
92+
hints.jpeg.as_ref().and_then(|j| j.quality)
93+
}
94+
zencodecs::ImageFormat::Png => {
95+
hints.png.as_ref().and_then(|p| p.quality)
96+
}
97+
_ => None,
98+
};
99+
if let Some(q) = codec_quality {
100+
intent.quality_fallback = Some(q);
101+
}
102+
}
81103
}
82104

83105
if let Some(allow) = allow {
@@ -309,6 +331,9 @@ fn map_encoder_hints(hints: &imageflow_types::EncoderHints) -> PerCodecHints {
309331

310332
if let Some(ref webp) = hints.webp {
311333
let mut m = BTreeMap::new();
334+
if let Some(q) = webp.quality {
335+
m.insert("quality".into(), q.to_string());
336+
}
312337
if let Some(ref lossless) = webp.lossless {
313338
m.insert("lossless".into(), format!("{lossless}"));
314339
}

imageflow_core/tests/integration/visuals/codec.checksums

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,3 +167,7 @@ tolerance zensim:95 (dissim 0.05)
167167
## test_transparent_png_to_png shirt_zen
168168
tolerance max-delta:1 zensim:99 (dissim 0.01) pixels-changed:1.0%
169169
~ eager-puma-c6c1b0d4a4:sea x86_64-avx512 @2d81fc05 auto-accepted
170+
171+
## test_webp_to_webp_quality q5_100x100_zen
172+
tolerance zensim:95 (dissim 0.05)
173+
~ draft-curl-48c90c0dcf:sea x86_64-avx512 @e33b73f9 auto-accepted

0 commit comments

Comments
 (0)