Skip to content

Commit be2b4e7

Browse files
Kylirocoradarhere
andauthored
Fix qtables and quality scaling (#8879)
Co-authored-by: Andrew Murray <[email protected]>
1 parent a2fbd58 commit be2b4e7

File tree

3 files changed

+36
-4
lines changed

3 files changed

+36
-4
lines changed

Tests/test_file_jpeg.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,24 @@ def _n_qtables_helper(n: int, test_file: str) -> None:
611611
None
612612
)
613613
]
614+
615+
for quality in range(101):
616+
qtable_from_qtable_quality = self.roundtrip(
617+
im,
618+
qtables={0: standard_l_qtable, 1: standard_chrominance_qtable},
619+
quality=quality,
620+
).quantization
621+
622+
qtable_from_quality = self.roundtrip(im, quality=quality).quantization
623+
624+
if features.check_feature("libjpeg_turbo"):
625+
assert qtable_from_qtable_quality == qtable_from_quality
626+
else:
627+
assert qtable_from_qtable_quality[0] == qtable_from_quality[0]
628+
assert (
629+
qtable_from_qtable_quality[1][1:] == qtable_from_quality[1][1:]
630+
)
631+
614632
# list of qtable lists
615633
assert_image_similar(
616634
im,

docs/handbook/image-file-formats.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,8 @@ The :py:meth:`~PIL.Image.Image.save` method supports the following options:
557557
hardly any gain in image quality. The value ``keep`` is only valid for JPEG
558558
files and will retain the original image quality level, subsampling, and
559559
qtables.
560+
For more information on how qtables are modified based on the quality parameter,
561+
see the qtables section.
560562

561563
**optimize**
562564
If present and true, indicates that the encoder should make an extra pass
@@ -622,6 +624,11 @@ The :py:meth:`~PIL.Image.Image.save` method supports the following options:
622624
range(len(keys))) of lists of 64 integers. There must be
623625
between 2 and 4 tables.
624626

627+
If a quality parameter is provided, the qtables will be adjusted accordingly.
628+
By default, the qtables are based on a standard JPEG table with a quality of 50.
629+
The qtable values will be reduced if the quality is higher than 50 and increased
630+
if the quality is lower than 50.
631+
625632
.. versionadded:: 2.5.0
626633

627634
**streamtype**

src/libImaging/JpegEncode.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -175,18 +175,21 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) {
175175
/* Use custom quantization tables */
176176
if (context->qtables) {
177177
int i;
178-
int quality = 100;
178+
int quality = 50;
179179
int last_q = 0;
180+
boolean force_baseline = FALSE;
180181
if (context->quality != -1) {
181182
quality = context->quality;
183+
force_baseline = TRUE;
182184
}
185+
int scale_factor = jpeg_quality_scaling(quality);
183186
for (i = 0; i < context->qtablesLen; i++) {
184187
jpeg_add_quant_table(
185188
&context->cinfo,
186189
i,
187190
&context->qtables[i * DCTSIZE2],
188-
quality,
189-
FALSE
191+
scale_factor,
192+
force_baseline
190193
);
191194
context->cinfo.comp_info[i].quant_tbl_no = i;
192195
last_q = i;
@@ -195,7 +198,11 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) {
195198
// jpeg_set_defaults created two qtables internally, but we only
196199
// wanted one.
197200
jpeg_add_quant_table(
198-
&context->cinfo, 1, &context->qtables[0], quality, FALSE
201+
&context->cinfo,
202+
1,
203+
&context->qtables[0],
204+
scale_factor,
205+
force_baseline
199206
);
200207
}
201208
for (i = last_q; i < context->cinfo.num_components; i++) {

0 commit comments

Comments
 (0)