mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-02-05 06:00:58 +03:00
Merge pull request #4989 from gofr/4962-jpeg-zigzag
De-zigzag JPEG's DQT when loading; deprecate convert_dict_qtables
This commit is contained in:
commit
914950959b
|
@ -466,7 +466,7 @@ class TestFileJpeg:
|
||||||
assert len(im.quantization) == n
|
assert len(im.quantization) == n
|
||||||
reloaded = self.roundtrip(im, qtables="keep")
|
reloaded = self.roundtrip(im, qtables="keep")
|
||||||
assert im.quantization == reloaded.quantization
|
assert im.quantization == reloaded.quantization
|
||||||
assert reloaded.quantization[0].typecode == "B"
|
assert max(reloaded.quantization[0]) <= 255
|
||||||
|
|
||||||
with Image.open("Tests/images/hopper.jpg") as im:
|
with Image.open("Tests/images/hopper.jpg") as im:
|
||||||
qtables = im.quantization
|
qtables = im.quantization
|
||||||
|
@ -478,7 +478,8 @@ class TestFileJpeg:
|
||||||
|
|
||||||
# valid bounds for baseline qtable
|
# valid bounds for baseline qtable
|
||||||
bounds_qtable = [int(s) for s in ("255 1 " * 32).split(None)]
|
bounds_qtable = [int(s) for s in ("255 1 " * 32).split(None)]
|
||||||
self.roundtrip(im, qtables=[bounds_qtable])
|
im2 = self.roundtrip(im, qtables=[bounds_qtable])
|
||||||
|
assert im2.quantization == {0: bounds_qtable}
|
||||||
|
|
||||||
# values from wizard.txt in jpeg9-a src package.
|
# values from wizard.txt in jpeg9-a src package.
|
||||||
standard_l_qtable = [
|
standard_l_qtable = [
|
||||||
|
@ -589,6 +590,12 @@ class TestFileJpeg:
|
||||||
assert max(im2.quantization[0]) <= 255
|
assert max(im2.quantization[0]) <= 255
|
||||||
assert max(im2.quantization[1]) <= 255
|
assert max(im2.quantization[1]) <= 255
|
||||||
|
|
||||||
|
def test_convert_dict_qtables_deprecation(self):
|
||||||
|
with pytest.warns(DeprecationWarning):
|
||||||
|
qtable = {0: [1, 2, 3, 4]}
|
||||||
|
qtable2 = JpegImagePlugin.convert_dict_qtables(qtable)
|
||||||
|
assert qtable == qtable2
|
||||||
|
|
||||||
@pytest.mark.skipif(not djpeg_available(), reason="djpeg not available")
|
@pytest.mark.skipif(not djpeg_available(), reason="djpeg not available")
|
||||||
def test_load_djpeg(self):
|
def test_load_djpeg(self):
|
||||||
with Image.open(TEST_FILE) as img:
|
with Image.open(TEST_FILE) as img:
|
||||||
|
|
|
@ -25,26 +25,6 @@ vulnerability introduced in FreeType 2.6 (:cve:`CVE-2020-15999`).
|
||||||
|
|
||||||
.. _2.10.4: https://sourceforge.net/projects/freetype/files/freetype2/2.10.4/
|
.. _2.10.4: https://sourceforge.net/projects/freetype/files/freetype2/2.10.4/
|
||||||
|
|
||||||
Tk/Tcl 8.4
|
|
||||||
~~~~~~~~~~
|
|
||||||
|
|
||||||
.. deprecated:: 8.2.0
|
|
||||||
|
|
||||||
Support for Tk/Tcl 8.4 is deprecated and will be removed in Pillow 10.0.0 (2023-01-02),
|
|
||||||
when Tk/Tcl 8.5 will be the minimum supported.
|
|
||||||
|
|
||||||
Categories
|
|
||||||
~~~~~~~~~~
|
|
||||||
|
|
||||||
.. deprecated:: 8.2.0
|
|
||||||
|
|
||||||
``im.category`` is deprecated and will be removed in Pillow 10.0.0 (2023-01-02),
|
|
||||||
along with the related ``Image.NORMAL``, ``Image.SEQUENCE`` and
|
|
||||||
``Image.CONTAINER`` attributes.
|
|
||||||
|
|
||||||
To determine if an image has multiple frames or not,
|
|
||||||
``getattr(im, "is_animated", False)`` can be used instead.
|
|
||||||
|
|
||||||
Image.show command parameter
|
Image.show command parameter
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -82,6 +62,36 @@ Use ``__version__`` instead.
|
||||||
It was initially removed in Pillow 7.0.0, but brought back in 7.1.0 to give projects
|
It was initially removed in Pillow 7.0.0, but brought back in 7.1.0 to give projects
|
||||||
more time to upgrade.
|
more time to upgrade.
|
||||||
|
|
||||||
|
Tk/Tcl 8.4
|
||||||
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
.. deprecated:: 8.2.0
|
||||||
|
|
||||||
|
Support for Tk/Tcl 8.4 is deprecated and will be removed in Pillow 10.0.0 (2023-01-02),
|
||||||
|
when Tk/Tcl 8.5 will be the minimum supported.
|
||||||
|
|
||||||
|
Categories
|
||||||
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
.. deprecated:: 8.2.0
|
||||||
|
|
||||||
|
``im.category`` is deprecated and will be removed in Pillow 10.0.0 (2023-01-02),
|
||||||
|
along with the related ``Image.NORMAL``, ``Image.SEQUENCE`` and
|
||||||
|
``Image.CONTAINER`` attributes.
|
||||||
|
|
||||||
|
To determine if an image has multiple frames or not,
|
||||||
|
``getattr(im, "is_animated", False)`` can be used instead.
|
||||||
|
|
||||||
|
JpegImagePlugin.convert_dict_qtables
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. deprecated:: 8.3.0
|
||||||
|
|
||||||
|
JPEG ``quantization`` is now automatically converted, but still returned as a
|
||||||
|
dictionary. The :py:attr:`~PIL.JpegImagePlugin.convert_dict_qtables` method no longer
|
||||||
|
performs any operations on the data given to it, has been deprecated and will be
|
||||||
|
removed in Pillow 10.0.0 (2023-01-02).
|
||||||
|
|
||||||
Removed features
|
Removed features
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,13 @@
|
||||||
Deprecations
|
Deprecations
|
||||||
============
|
============
|
||||||
|
|
||||||
TODO
|
JpegImagePlugin.convert_dict_qtables
|
||||||
^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
TODO
|
JPEG ``quantization`` is now automatically converted, but still returned as a
|
||||||
|
dictionary. The :py:attr:`~PIL.JpegImagePlugin.convert_dict_qtables` method no longer
|
||||||
|
performs any operations on the data given to it, has been deprecated and will be
|
||||||
|
removed in Pillow 10.0.0 (2023-01-02).
|
||||||
|
|
||||||
API Changes
|
API Changes
|
||||||
===========
|
===========
|
||||||
|
|
|
@ -254,7 +254,7 @@ def DQT(self, marker):
|
||||||
data = array.array("B" if precision == 1 else "H", s[1:qt_length])
|
data = array.array("B" if precision == 1 else "H", s[1:qt_length])
|
||||||
if sys.byteorder == "little" and precision > 1:
|
if sys.byteorder == "little" and precision > 1:
|
||||||
data.byteswap() # the values are always big-endian
|
data.byteswap() # the values are always big-endian
|
||||||
self.quantization[v & 15] = data
|
self.quantization[v & 15] = [data[i] for i in zigzag_index]
|
||||||
s = s[qt_length:]
|
s = s[qt_length:]
|
||||||
|
|
||||||
|
|
||||||
|
@ -601,9 +601,11 @@ samplings = {
|
||||||
|
|
||||||
|
|
||||||
def convert_dict_qtables(qtables):
|
def convert_dict_qtables(qtables):
|
||||||
qtables = [qtables[key] for key in range(len(qtables)) if key in qtables]
|
warnings.warn(
|
||||||
for idx, table in enumerate(qtables):
|
"convert_dict_qtables is deprecated and will be removed in Pillow 10"
|
||||||
qtables[idx] = [table[i] for i in zigzag_index]
|
"(2023-01-02). Conversion is no longer needed.",
|
||||||
|
DeprecationWarning,
|
||||||
|
)
|
||||||
return qtables
|
return qtables
|
||||||
|
|
||||||
|
|
||||||
|
@ -684,7 +686,9 @@ def _save(im, fp, filename):
|
||||||
qtables = [lines[s : s + 64] for s in range(0, len(lines), 64)]
|
qtables = [lines[s : s + 64] for s in range(0, len(lines), 64)]
|
||||||
if isinstance(qtables, (tuple, list, dict)):
|
if isinstance(qtables, (tuple, list, dict)):
|
||||||
if isinstance(qtables, dict):
|
if isinstance(qtables, dict):
|
||||||
qtables = convert_dict_qtables(qtables)
|
qtables = [
|
||||||
|
qtables[key] for key in range(len(qtables)) if key in qtables
|
||||||
|
]
|
||||||
elif isinstance(qtables, tuple):
|
elif isinstance(qtables, tuple):
|
||||||
qtables = list(qtables)
|
qtables = list(qtables)
|
||||||
if not (0 < len(qtables) < 5):
|
if not (0 < len(qtables) < 5):
|
||||||
|
|
|
@ -52,19 +52,11 @@ You can get the quantization tables of a JPEG with::
|
||||||
|
|
||||||
im.quantization
|
im.quantization
|
||||||
|
|
||||||
This will return a dict with a number of arrays. You can pass this dict
|
This will return a dict with a number of lists. You can pass this dict
|
||||||
directly as the qtables argument when saving a JPEG.
|
directly as the qtables argument when saving a JPEG.
|
||||||
|
|
||||||
The tables format between im.quantization and quantization in presets differ in
|
The quantization table format in presets is a list with sublists. These formats
|
||||||
3 ways:
|
are interchangeable.
|
||||||
|
|
||||||
1. The base container of the preset is a list with sublists instead of dict.
|
|
||||||
dict[0] -> list[0], dict[1] -> list[1], ...
|
|
||||||
2. Each table in a preset is a list instead of an array.
|
|
||||||
3. The zigzag order is remove in the preset (needed by libjpeg >= 6a).
|
|
||||||
|
|
||||||
You can convert the dict format to the preset format with the
|
|
||||||
:func:`.JpegImagePlugin.convert_dict_qtables()` function.
|
|
||||||
|
|
||||||
Libjpeg ref.:
|
Libjpeg ref.:
|
||||||
https://web.archive.org/web/20120328125543/http://www.jpegcameras.com/libjpeg/libjpeg-3.html
|
https://web.archive.org/web/20120328125543/http://www.jpegcameras.com/libjpeg/libjpeg-3.html
|
||||||
|
|
Loading…
Reference in New Issue
Block a user