Fix incorrect quality scaling when using qtables in JPEG encoder

When both `qtables` and `quality` are provided, Pillow previously passed
the raw `quality` value directly to `jpeg_add_quant_table()` as the scale
factor, which caused incorrect quantization.

This commit corrects the behavior by using `jpeg_quality_scaling(quality)`
to compute the proper JPEG quantization scaling factor, consistent with
`jpeg_set_quality()`.

This ensures expected compression behavior when custom qtables are used
alongside a specified quality level.
This commit is contained in:
Kylian Ronfleux--Corail 2025-04-10 07:31:05 +00:00
parent c8d98d56a0
commit e3c0ee6ae2

View File

@ -178,12 +178,13 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) {
if (context->quality != -1) { if (context->quality != -1) {
quality = context->quality; quality = context->quality;
} }
int scale_factor = jpeg_quality_scaling(quality);
for (i = 0; i < context->qtablesLen; i++) { for (i = 0; i < context->qtablesLen; i++) {
jpeg_add_quant_table( jpeg_add_quant_table(
&context->cinfo, &context->cinfo,
i, i,
&context->qtables[i * DCTSIZE2], &context->qtables[i * DCTSIZE2],
quality, scale_factor,
FALSE FALSE
); );
context->cinfo.comp_info[i].quant_tbl_no = i; context->cinfo.comp_info[i].quant_tbl_no = i;
@ -193,7 +194,7 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) {
// jpeg_set_defaults created two qtables internally, but we only // jpeg_set_defaults created two qtables internally, but we only
// wanted one. // wanted one.
jpeg_add_quant_table( jpeg_add_quant_table(
&context->cinfo, 1, &context->qtables[0], quality, FALSE &context->cinfo, 1, &context->qtables[0], scale_factor, FALSE
); );
} }
for (i = last_q; i < context->cinfo.num_components; i++) { for (i = last_q; i < context->cinfo.num_components; i++) {