Merge pull request #714 from wiredfool/jpeg_qtables

JPEG qtables
This commit is contained in:
Alex Clark ☺ 2014-06-24 05:48:17 -04:00
commit 88bfd5522d
3 changed files with 74 additions and 1 deletions

View File

@ -498,7 +498,7 @@ def _save(im, fp, filename):
else:
if subsampling in presets:
subsampling = presets[subsampling].get('subsampling', -1)
if qtables in presets:
if isStringType(qtables) and qtables in presets:
qtables = presets[qtables].get('quantization')
if subsampling == "4:4:4":

View File

@ -224,7 +224,57 @@ class TestFileJpeg(PillowTestCase):
filename = "Tests/images/junk_jpeg_header.jpg"
Image.open(filename)
def test_qtables(self):
im = Image.open("Tests/images/lena.jpg")
qtables = im.quantization
reloaded = self.roundtrip(im, qtables=qtables, subsampling=0)
self.assertEqual(im.quantization, reloaded.quantization)
self.assert_image_similar(im, self.roundtrip(im, qtables='web_low'), 30)
self.assert_image_similar(im, self.roundtrip(im, qtables='web_high'), 30)
self.assert_image_similar(im, self.roundtrip(im, qtables='keep'), 30)
#values from wizard.txt in jpeg9-a src package.
standard_l_qtable = [int(s) for s in """
16 11 10 16 24 40 51 61
12 12 14 19 26 58 60 55
14 13 16 24 40 57 69 56
14 17 22 29 51 87 80 62
18 22 37 56 68 109 103 77
24 35 55 64 81 104 113 92
49 64 78 87 103 121 120 101
72 92 95 98 112 100 103 99
""".split(None)]
standard_chrominance_qtable= [int(s) for s in """
17 18 24 47 99 99 99 99
18 21 26 66 99 99 99 99
24 26 56 99 99 99 99 99
47 66 99 99 99 99 99 99
99 99 99 99 99 99 99 99
99 99 99 99 99 99 99 99
99 99 99 99 99 99 99 99
99 99 99 99 99 99 99 99
""".split(None)]
# list of qtable lists
self.assert_image_similar(im,
self.roundtrip(im,
qtables=[standard_l_qtable,
standard_chrominance_qtable]),
30)
# tuple of qtable lists
self.assert_image_similar(im,
self.roundtrip(im,
qtables=(standard_l_qtable,
standard_chrominance_qtable)),
30)
# dict of qtable lists
self.assert_image_similar(im,
self.roundtrip(im,
qtables={0:standard_l_qtable,
1:standard_chrominance_qtable}),
30)
if __name__ == '__main__':
unittest.main()

View File

@ -147,6 +147,29 @@ The :py:meth:`~PIL.Image.Image.save` method supports the following options:
If present, indicates that this image should be stored as a progressive
JPEG file.
**subsampling**
If present, sets the subsampling for the encoder.
* ``keep``: Only valid for JPEG files, will retain the original image setting.
* ``4:4:4``, ``4:2:2``, ``4:1:1``: Specific sampling values
* ``-1``: equivalent to ``keep``
* ``0``: equivalent to ``4:4:4``
* ``1``: equivalent to ``4:2:2``
* ``2``: equivalent to ``4:1:1``
**qtables**
If present, sets the qtables for the encoder. This is listed as an
advanced option for wizards in the JPEG documentation. Use with
caution. ``qtables`` can be one of several types of values:
* a string, naming a preset, e.g. ``keep``, ``web_low``, or ``web_high``
* a list, tuple, or dictionary (with integer keys =
range(len(keys))) of lists of 64 integers. There must be
between 2 and 4 tables.
.. versionadded:: 2.5.0
.. note::
To enable JPEG support, you need to build and install the IJG JPEG library