Merge pull request #6030 from radarhere/photoshopblocks

Added get_photoshop_blocks() to parse Photoshop TIFF tag
This commit is contained in:
Hugo van Kemenade 2022-02-10 09:40:17 +02:00 committed by GitHub
commit f5fab326fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 108 additions and 1 deletions

View File

@ -26,7 +26,7 @@ Changelog (Pillow)
- Ensure duplicated file pointer is closed #5946 - Ensure duplicated file pointer is closed #5946
[radarhere] [radarhere]
- Added specific error if ImagePath coordinate type is incorrect #5942 - Added specific error if path coordinate type is incorrect #5942
[radarhere] [radarhere]
- Return an empty bytestring from tobytes() for an empty image #5938 - Return an empty bytestring from tobytes() for an empty image #5938

View File

@ -692,6 +692,32 @@ class TestFileTiff:
assert description[0]["format"] == "image/tiff" assert description[0]["format"] == "image/tiff"
assert description[3]["BitsPerSample"]["Seq"]["li"] == ["8", "8", "8"] assert description[3]["BitsPerSample"]["Seq"]["li"] == ["8", "8", "8"]
def test_get_photoshop_blocks(self):
with Image.open("Tests/images/lab.tif") as im:
assert list(im.get_photoshop_blocks().keys()) == [
1061,
1002,
1005,
1062,
1037,
1049,
1011,
1034,
10000,
1013,
1016,
1032,
1054,
1050,
1064,
1041,
1044,
1036,
1057,
4000,
4001,
]
def test_close_on_load_exclusive(self, tmp_path): def test_close_on_load_exclusive(self, tmp_path):
# similar to test_fd_leak, but runs on unixlike os # similar to test_fd_leak, but runs on unixlike os
tmpfile = str(tmp_path / "temp.tif") tmpfile = str(tmp_path / "temp.tif")

View File

@ -0,0 +1,56 @@
9.1.0
-----
API Changes
===========
Raise an error when performing a negative crop
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Performing a negative crop on an image previously just returned a ``(0, 0)`` image. Now
it will raise a ``ValueError``, to help reduce confusion if a user has unintentionally
provided the wrong arguments.
Added specific error if path coordinate type is incorrect
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Rather than returning a ``SystemError``, passing the incorrect types of coordinates into
a path will now raise a more specific ``ValueError``, with the message "incorrect
coordinate type".
Deprecations
^^^^^^^^^^^^
ImageShow.Viewer.show_file file argument
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The ``file`` argument in :py:meth:`~PIL.ImageShow.Viewer.show_file()` has been
deprecated, replaced by ``path``.
In effect, ``viewer.show_file("test.jpg")`` will continue to work unchanged.
``viewer.show_file(file="test.jpg")`` will raise a deprecation warning, and suggest
``viewer.show_file(path="test.jpg")`` instead.
API Additions
=============
Added get_photoshop_blocks() to parse Photoshop TIFF tag
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
:py:meth:`~PIL.TiffImagePlugin.TiffImageFile.get_photoshop_blocks` has been added, to
allow users to determine what Photoshop "Image Resource Blocks" are contained within an
image. The keys of the returned dictionary are the image resource IDs.
At present, the information within each block is merely returned as a dictionary with a
"data" entry. This will allow more useful information to be added in the future without
breaking backwards compatibility.
Other Changes
=============
Image._repr_pretty_
^^^^^^^^^^^^^^^^^^^
``im._repr_pretty_`` has been added to provide a representation of an image without the
identity of the object. This allows Jupyter to describe an image and have that
description stay the same on subsequent executions of the same code.

View File

@ -14,6 +14,7 @@ expected to be backported to earlier versions.
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 2
9.1.0
9.0.1 9.0.1
9.0.0 9.0.0
8.4.0 8.4.0

View File

@ -41,6 +41,7 @@
import io import io
import itertools import itertools
import logging import logging
import math
import os import os
import struct import struct
import warnings import warnings
@ -49,6 +50,8 @@ from fractions import Fraction
from numbers import Number, Rational from numbers import Number, Rational
from . import Image, ImageFile, ImageOps, ImagePalette, TiffTags from . import Image, ImageFile, ImageOps, ImagePalette, TiffTags
from ._binary import i16be as i16
from ._binary import i32be as i32
from ._binary import o8 from ._binary import o8
from .TiffTags import TYPES from .TiffTags import TYPES
@ -1129,6 +1132,27 @@ class TiffImageFile(ImageFile.ImageFile):
""" """
return self._getxmp(self.tag_v2[700]) if 700 in self.tag_v2 else {} return self._getxmp(self.tag_v2[700]) if 700 in self.tag_v2 else {}
def get_photoshop_blocks(self):
"""
Returns a dictionary of Photoshop "Image Resource Blocks".
The keys are the image resource ID. For more information, see
https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_pgfId-1037727
:returns: Photoshop "Image Resource Blocks" in a dictionary.
"""
blocks = {}
val = self.tag_v2.get(0x8649)
if val:
while val[:4] == b"8BIM":
id = i16(val[4:6])
n = math.ceil((val[6] + 1) / 2) * 2
size = i32(val[6 + n : 10 + n])
data = val[10 + n : 10 + n + size]
blocks[id] = {"data": data}
val = val[math.ceil((10 + n + size) / 2) * 2 :]
return blocks
def load(self): def load(self):
if self.tile and self.use_load_libtiff: if self.tile and self.use_load_libtiff:
return self._load_libtiff() return self._load_libtiff()