Skip to content

Commit

Permalink
Merge pull request #4989 from gofr/4962-jpeg-zigzag
Browse files Browse the repository at this point in the history
De-zigzag JPEG's DQT when loading; deprecate convert_dict_qtables
  • Loading branch information
mergify[bot] committed Jun 30, 2021
2 parents 1b74bdd + dfeb49c commit 9149509
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 41 deletions.
11 changes: 9 additions & 2 deletions Tests/test_file_jpeg.py
Expand Up @@ -466,7 +466,7 @@ def _n_qtables_helper(n, test_file):
assert len(im.quantization) == n
reloaded = self.roundtrip(im, qtables="keep")
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:
qtables = im.quantization
Expand All @@ -478,7 +478,8 @@ def _n_qtables_helper(n, test_file):

# valid bounds for baseline qtable
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.
standard_l_qtable = [
Expand Down Expand Up @@ -589,6 +590,12 @@ def test_save_low_quality_baseline_qtables(self):
assert max(im2.quantization[0]) <= 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")
def test_load_djpeg(self):
with Image.open(TEST_FILE) as img:
Expand Down
50 changes: 30 additions & 20 deletions docs/deprecations.rst
Expand Up @@ -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/

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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down Expand Up @@ -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
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
----------------

Expand Down
9 changes: 6 additions & 3 deletions docs/releasenotes/8.3.0.rst
Expand Up @@ -4,10 +4,13 @@
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
===========
Expand Down
14 changes: 9 additions & 5 deletions src/PIL/JpegImagePlugin.py
Expand Up @@ -254,7 +254,7 @@ def DQT(self, marker):
data = array.array("B" if precision == 1 else "H", s[1:qt_length])
if sys.byteorder == "little" and precision > 1:
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:]


Expand Down Expand Up @@ -601,9 +601,11 @@ def _getmp(self):


def convert_dict_qtables(qtables):
qtables = [qtables[key] for key in range(len(qtables)) if key in qtables]
for idx, table in enumerate(qtables):
qtables[idx] = [table[i] for i in zigzag_index]
warnings.warn(
"convert_dict_qtables is deprecated and will be removed in Pillow 10"
"(2023-01-02). Conversion is no longer needed.",
DeprecationWarning,
)
return qtables


Expand Down Expand Up @@ -684,7 +686,9 @@ def validate_qtables(qtables):
qtables = [lines[s : s + 64] for s in range(0, len(lines), 64)]
if isinstance(qtables, (tuple, list, 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):
qtables = list(qtables)
if not (0 < len(qtables) < 5):
Expand Down
14 changes: 3 additions & 11 deletions src/PIL/JpegPresets.py
Expand Up @@ -52,19 +52,11 @@
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.
The tables format between im.quantization and quantization in presets differ in
3 ways:
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.
The quantization table format in presets is a list with sublists. These formats
are interchangeable.
Libjpeg ref.:
https://web.archive.org/web/20120328125543/http://www.jpegcameras.com/libjpeg/libjpeg-3.html
Expand Down

0 comments on commit 9149509

Please sign in to comment.