mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-25 17:36:18 +03:00
Read Photoshop resolution data
This commit is contained in:
parent
975fccafc7
commit
636ad68f5e
|
@ -590,6 +590,15 @@ class TestFileJpeg(PillowTestCase):
|
||||||
# Act / Assert
|
# Act / Assert
|
||||||
self.assertEqual(im._getexif()[306], '2017:03:13 23:03:09')
|
self.assertEqual(im._getexif()[306], '2017:03:13 23:03:09')
|
||||||
|
|
||||||
|
def test_photoshop(self):
|
||||||
|
im = Image.open("Tests/images/photoshop-200dpi.jpg")
|
||||||
|
self.assertEqual(im.info["photoshop"][0x03ed], {
|
||||||
|
'XResolution': 200.0,
|
||||||
|
'DisplayedUnitsX': 1,
|
||||||
|
'YResolution': 200.0,
|
||||||
|
'DisplayedUnitsY': 1,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipUnless(sys.platform.startswith('win32'), "Windows only")
|
@unittest.skipUnless(sys.platform.startswith('win32'), "Windows only")
|
||||||
class TestFileCloseW32(PillowTestCase):
|
class TestFileCloseW32(PillowTestCase):
|
||||||
|
|
|
@ -198,35 +198,9 @@ def getiptcinfo(im):
|
||||||
|
|
||||||
elif isinstance(im, JpegImagePlugin.JpegImageFile):
|
elif isinstance(im, JpegImagePlugin.JpegImageFile):
|
||||||
# extract the IPTC/NAA resource
|
# extract the IPTC/NAA resource
|
||||||
try:
|
photoshop = im.info.get("photoshop")
|
||||||
app = im.app["APP13"]
|
if photoshop:
|
||||||
if app[:14] == b"Photoshop 3.0\x00":
|
data = photoshop.get(0x0404)
|
||||||
app = app[14:]
|
|
||||||
# parse the image resource block
|
|
||||||
offset = 0
|
|
||||||
while app[offset:offset+4] == b"8BIM":
|
|
||||||
offset += 4
|
|
||||||
# resource code
|
|
||||||
code = i16(app, offset)
|
|
||||||
offset += 2
|
|
||||||
# resource name (usually empty)
|
|
||||||
name_len = i8(app[offset])
|
|
||||||
# name = app[offset+1:offset+1+name_len]
|
|
||||||
offset = 1 + offset + name_len
|
|
||||||
if offset & 1:
|
|
||||||
offset += 1
|
|
||||||
# resource data block
|
|
||||||
size = i32(app, offset)
|
|
||||||
offset += 4
|
|
||||||
if code == 0x0404:
|
|
||||||
# 0x0404 contains IPTC/NAA data
|
|
||||||
data = app[offset:offset+size]
|
|
||||||
break
|
|
||||||
offset = offset + size
|
|
||||||
if offset & 1:
|
|
||||||
offset += 1
|
|
||||||
except (AttributeError, KeyError):
|
|
||||||
pass
|
|
||||||
|
|
||||||
elif isinstance(im, TiffImagePlugin.TiffImageFile):
|
elif isinstance(im, TiffImagePlugin.TiffImageFile):
|
||||||
# get raw data from the IPTC/NAA tag (PhotoShop tags the data
|
# get raw data from the IPTC/NAA tag (PhotoShop tags the data
|
||||||
|
|
|
@ -39,7 +39,7 @@ import struct
|
||||||
import io
|
import io
|
||||||
import warnings
|
import warnings
|
||||||
from . import Image, ImageFile, TiffImagePlugin
|
from . import Image, ImageFile, TiffImagePlugin
|
||||||
from ._binary import i8, o8, i16be as i16
|
from ._binary import i8, o8, i16be as i16, i32be as i32
|
||||||
from .JpegPresets import presets
|
from .JpegPresets import presets
|
||||||
from ._util import isStringType
|
from ._util import isStringType
|
||||||
|
|
||||||
|
@ -104,6 +104,39 @@ def APP(self, marker):
|
||||||
# reassemble the profile, rather than assuming that the APP2
|
# reassemble the profile, rather than assuming that the APP2
|
||||||
# markers appear in the correct sequence.
|
# markers appear in the correct sequence.
|
||||||
self.icclist.append(s)
|
self.icclist.append(s)
|
||||||
|
elif marker == 0xFFED:
|
||||||
|
if s[:14] == b"Photoshop 3.0\x00":
|
||||||
|
blocks = s[14:]
|
||||||
|
# parse the image resource block
|
||||||
|
offset = 0
|
||||||
|
photoshop = {}
|
||||||
|
while blocks[offset:offset+4] == b"8BIM":
|
||||||
|
offset += 4
|
||||||
|
# resource code
|
||||||
|
code = i16(blocks, offset)
|
||||||
|
offset += 2
|
||||||
|
# resource name (usually empty)
|
||||||
|
name_len = i8(blocks[offset])
|
||||||
|
# name = blocks[offset+1:offset+1+name_len]
|
||||||
|
offset = 1 + offset + name_len
|
||||||
|
if offset & 1:
|
||||||
|
offset += 1
|
||||||
|
# resource data block
|
||||||
|
size = i32(blocks, offset)
|
||||||
|
offset += 4
|
||||||
|
data = blocks[offset:offset+size]
|
||||||
|
if code == 0x03ED: # ResolutionInfo
|
||||||
|
data = {
|
||||||
|
'XResolution': i32(data[:4]) / 65536,
|
||||||
|
'DisplayedUnitsX': i16(data[4:8]),
|
||||||
|
'YResolution': i32(data[8:12]) / 65536,
|
||||||
|
'DisplayedUnitsY': i16(data[12:]),
|
||||||
|
}
|
||||||
|
photoshop[code] = data
|
||||||
|
offset = offset + size
|
||||||
|
if offset & 1:
|
||||||
|
offset += 1
|
||||||
|
self.info["photoshop"] = photoshop
|
||||||
elif marker == 0xFFEE and s[:5] == b"Adobe":
|
elif marker == 0xFFEE and s[:5] == b"Adobe":
|
||||||
self.info["adobe"] = i16(s, 5)
|
self.info["adobe"] = i16(s, 5)
|
||||||
# extract Adobe custom properties
|
# extract Adobe custom properties
|
||||||
|
|
Loading…
Reference in New Issue
Block a user