mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-11-04 01:47:47 +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
 | 
			
		||||
                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
 | 
			
		||||
| 
						 | 
				
			
			@ -478,7 +478,8 @@ class TestFileJpeg:
 | 
			
		|||
 | 
			
		||||
            # 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 = [
 | 
			
		||||
| 
						 | 
				
			
			@ -589,6 +590,12 @@ class TestFileJpeg:
 | 
			
		|||
            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:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
----------------
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
===========
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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:]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -601,9 +601,11 @@ samplings = {
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -684,7 +686,9 @@ def _save(im, fp, filename):
 | 
			
		|||
                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):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -52,19 +52,11 @@ You can get the quantization tables of a JPEG with::
 | 
			
		|||
 | 
			
		||||
  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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user