Merge pull request #4440 from radarhere/jpeg_quality

Allow saving of zero quality JPEG images
This commit is contained in:
Hugo van Kemenade 2020-02-25 12:02:53 +02:00 committed by GitHub
commit 3c995fd173
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 29 additions and 9 deletions

View File

@ -299,6 +299,10 @@ class TestFileJpeg(PillowTestCase):
assert_image(im1, im2.mode, im2.size)
assert im1.bytes >= im2.bytes
im3 = self.roundtrip(hopper(), quality=0)
assert_image(im1, im3.mode, im3.size)
self.assertGreater(im2.bytes, im3.bytes)
def test_smooth(self):
im1 = self.roundtrip(hopper())
im2 = self.roundtrip(hopper(), smooth=100)

View File

@ -302,7 +302,7 @@ The :py:meth:`~PIL.Image.Image.open` method may set the following
The :py:meth:`~PIL.Image.Image.save` method supports the following options:
**quality**
The image quality, on a scale from 1 (worst) to 95 (best). The default is
The image quality, on a scale from 0 (worst) to 95 (best). The default is
75. Values above 95 should be avoided; 100 disables portions of the JPEG
compression algorithm, and results in large files with hardly any gain in
image quality.

View File

@ -0,0 +1,16 @@
7.0.0
-----
Allow saving of zero quality JPEG images
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If no quality was specified when saving a JPEG, Pillow internally used a value
of zero to indicate that the default quality should be used. However, this
removed the ability to actually save a JPEG with zero quality. This has now
been resolved.
.. code-block:: python
from PIL import Image
im = Image.open("hopper.jpg")
im.save("out.jpg", quality=0)

View File

@ -616,17 +616,17 @@ def _save(im, fp, filename):
dpi = [round(x) for x in info.get("dpi", (0, 0))]
quality = info.get("quality", 0)
quality = info.get("quality", -1)
subsampling = info.get("subsampling", -1)
qtables = info.get("qtables")
if quality == "keep":
quality = 0
quality = -1
subsampling = "keep"
qtables = "keep"
elif quality in presets:
preset = presets[quality]
quality = 0
quality = -1
subsampling = preset.get("subsampling", -1)
qtables = preset.get("quantization")
elif not isinstance(quality, int):
@ -749,8 +749,8 @@ def _save(im, fp, filename):
# CMYK can be bigger
if im.mode == "CMYK":
bufsize = 4 * im.size[0] * im.size[1]
# keep sets quality to 0, but the actual value may be high.
elif quality >= 95 or quality == 0:
# keep sets quality to -1, but the actual value may be high.
elif quality >= 95 or quality == -1:
bufsize = 2 * im.size[0] * im.size[1]
else:
bufsize = im.size[0] * im.size[1]

View File

@ -67,7 +67,7 @@ typedef struct {
/* CONFIGURATION */
/* Quality (1-100, 0 means default) */
/* Quality (0-100, -1 means default) */
int quality;
/* Progressive mode */

View File

@ -153,7 +153,7 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
int i;
int quality = 100;
int last_q = 0;
if (context->quality > 0) {
if (context->quality != -1) {
quality = context->quality;
}
for (i = 0; i < context->qtablesLen; i++) {
@ -171,7 +171,7 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
for (i = last_q; i < context->cinfo.num_components; i++) {
context->cinfo.comp_info[i].quant_tbl_no = last_q;
}
} else if (context->quality > 0) {
} else if (context->quality != -1) {
jpeg_set_quality(&context->cinfo, context->quality, 1);
}