mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-11-01 00:17:27 +03:00 
			
		
		
		
	Merge pull request #6030 from radarhere/photoshopblocks
Added get_photoshop_blocks() to parse Photoshop TIFF tag
This commit is contained in:
		
						commit
						f5fab326fa
					
				|  | @ -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 | ||||||
|  |  | ||||||
|  | @ -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") | ||||||
|  |  | ||||||
							
								
								
									
										56
									
								
								docs/releasenotes/9.1.0.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								docs/releasenotes/9.1.0.rst
									
									
									
									
									
										Normal 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. | ||||||
|  | @ -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 | ||||||
|  |  | ||||||
|  | @ -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() | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user