mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-02-03 21:24:31 +03:00
Merge branch 'master' into rm-3.5
This commit is contained in:
commit
ddc4c64664
|
@ -5,6 +5,9 @@ Changelog (Pillow)
|
|||
8.0.0 (unreleased)
|
||||
------------------
|
||||
|
||||
- Added writing of subIFDs #4862
|
||||
[radarhere]
|
||||
|
||||
- Fix IFDRational __eq__ bug #4888
|
||||
[luphord, radarhere]
|
||||
|
||||
|
|
BIN
Tests/images/empty_gps_ifd.jpg
Normal file
BIN
Tests/images/empty_gps_ifd.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
|
@ -8,6 +8,7 @@ from PIL import (
|
|||
ExifTags,
|
||||
Image,
|
||||
ImageFile,
|
||||
ImageOps,
|
||||
JpegImagePlugin,
|
||||
UnidentifiedImageError,
|
||||
features,
|
||||
|
@ -225,23 +226,48 @@ class TestFileJpeg:
|
|||
# Should not raise a TypeError
|
||||
im._getexif()
|
||||
|
||||
def test_exif_gps(self):
|
||||
# Arrange
|
||||
def test_exif_gps(self, tmp_path):
|
||||
expected_exif_gps = {
|
||||
0: b"\x00\x00\x00\x01",
|
||||
2: 4294967295,
|
||||
5: b"\x01",
|
||||
30: 65535,
|
||||
29: "1999:99:99 99:99:99",
|
||||
}
|
||||
gps_index = 34853
|
||||
|
||||
# Reading
|
||||
with Image.open("Tests/images/exif_gps.jpg") as im:
|
||||
gps_index = 34853
|
||||
expected_exif_gps = {
|
||||
0: b"\x00\x00\x00\x01",
|
||||
2: 4294967295,
|
||||
5: b"\x01",
|
||||
30: 65535,
|
||||
29: "1999:99:99 99:99:99",
|
||||
}
|
||||
|
||||
# Act
|
||||
exif = im._getexif()
|
||||
assert exif[gps_index] == expected_exif_gps
|
||||
|
||||
# Assert
|
||||
assert exif[gps_index] == expected_exif_gps
|
||||
# Writing
|
||||
f = str(tmp_path / "temp.jpg")
|
||||
exif = Image.Exif()
|
||||
exif[gps_index] = expected_exif_gps
|
||||
hopper().save(f, exif=exif)
|
||||
|
||||
with Image.open(f) as reloaded:
|
||||
exif = reloaded._getexif()
|
||||
assert exif[gps_index] == expected_exif_gps
|
||||
|
||||
def test_empty_exif_gps(self):
|
||||
with Image.open("Tests/images/empty_gps_ifd.jpg") as im:
|
||||
exif = im.getexif()
|
||||
del exif[0x8769]
|
||||
|
||||
# Assert that it needs to be transposed
|
||||
assert exif[0x0112] == Image.TRANSVERSE
|
||||
|
||||
# Assert that the GPS IFD is present and empty
|
||||
assert exif[0x8825] == {}
|
||||
|
||||
transposed = ImageOps.exif_transpose(im)
|
||||
exif = transposed.getexif()
|
||||
assert exif[0x8825] == {}
|
||||
|
||||
# Assert that it was transposed
|
||||
assert 0x0112 not in exif
|
||||
|
||||
def test_exif_equality(self):
|
||||
# In 7.2.0, Exif rationals were changed to be read as
|
||||
|
|
|
@ -36,10 +36,4 @@ What about PIL?
|
|||
Prior to Pillow 2.0.0, very few image code changes were made. Pillow 2.0.0
|
||||
added Python 3 support and includes many bug fixes from many contributors.
|
||||
|
||||
As more time passes since the last PIL release (1.1.7 in 2009), the likelihood of a new PIL release decreases. However, we've yet to hear an official "PIL is dead" announcement. So if you still want to support PIL, please `report issues here first`_, then `open corresponding Pillow tickets here`_.
|
||||
|
||||
.. _report issues here first: https://bitbucket.org/effbot/pil-2009-raclette/issues
|
||||
|
||||
.. _open corresponding Pillow tickets here: https://github.com/python-pillow/Pillow/issues
|
||||
|
||||
Please provide a link to the first ticket so we can track the issue(s) upstream.
|
||||
As more time passes since the last PIL release (1.1.7 in 2009), the likelihood of a new PIL release decreases. However, we've yet to hear an official "PIL is dead" announcement.
|
||||
|
|
|
@ -569,7 +569,9 @@ class ImageFileDirectory_v2(MutableMapping):
|
|||
elif self.tagtype[tag] == TiffTags.RATIONAL:
|
||||
values = [float(v) if isinstance(v, int) else v for v in values]
|
||||
|
||||
values = tuple(info.cvt_enum(value) for value in values)
|
||||
is_ifd = self.tagtype[tag] == TiffTags.LONG and isinstance(values, dict)
|
||||
if not is_ifd:
|
||||
values = tuple(info.cvt_enum(value) for value in values)
|
||||
|
||||
dest = self._tags_v1 if legacy_api else self._tags_v2
|
||||
|
||||
|
@ -578,7 +580,7 @@ class ImageFileDirectory_v2(MutableMapping):
|
|||
# Spec'd length == 1, Actual > 1, Warn and truncate. Formerly barfed.
|
||||
# No Spec, Actual length 1, Formerly (<4.2) returned a 1 element tuple.
|
||||
# Don't mess with the legacy api, since it's frozen.
|
||||
if (
|
||||
if not is_ifd and (
|
||||
(info.length == 1)
|
||||
or self.tagtype[tag] == TiffTags.BYTE
|
||||
or (info.length is None and len(values) == 1 and not legacy_api)
|
||||
|
@ -804,11 +806,22 @@ class ImageFileDirectory_v2(MutableMapping):
|
|||
stripoffsets = len(entries)
|
||||
typ = self.tagtype.get(tag)
|
||||
logger.debug(f"Tag {tag}, Type: {typ}, Value: {value}")
|
||||
values = value if isinstance(value, tuple) else (value,)
|
||||
data = self._write_dispatch[typ](self, *values)
|
||||
is_ifd = typ == TiffTags.LONG and isinstance(value, dict)
|
||||
if is_ifd:
|
||||
if self._endian == "<":
|
||||
ifh = b"II\x2A\x00\x08\x00\x00\x00"
|
||||
else:
|
||||
ifh = b"MM\x00\x2A\x00\x00\x00\x08"
|
||||
ifd = ImageFileDirectory_v2(ifh)
|
||||
for ifd_tag, ifd_value in self._tags_v2[tag].items():
|
||||
ifd[ifd_tag] = ifd_value
|
||||
data = ifd.tobytes(offset)
|
||||
else:
|
||||
values = value if isinstance(value, tuple) else (value,)
|
||||
data = self._write_dispatch[typ](self, *values)
|
||||
|
||||
tagname = TiffTags.lookup(tag).name
|
||||
typname = TYPES.get(typ, "unknown")
|
||||
typname = "ifd" if is_ifd else TYPES.get(typ, "unknown")
|
||||
msg = f"save: {tagname} ({tag}) - type: {typname} ({typ})"
|
||||
msg += " - value: " + (
|
||||
"<table: %d bytes>" % len(data) if len(data) >= 16 else str(values)
|
||||
|
@ -816,7 +829,9 @@ class ImageFileDirectory_v2(MutableMapping):
|
|||
logger.debug(msg)
|
||||
|
||||
# count is sum of lengths for string and arbitrary data
|
||||
if typ in [TiffTags.BYTE, TiffTags.ASCII, TiffTags.UNDEFINED]:
|
||||
if is_ifd:
|
||||
count = 1
|
||||
elif typ in [TiffTags.BYTE, TiffTags.ASCII, TiffTags.UNDEFINED]:
|
||||
count = len(data)
|
||||
else:
|
||||
count = len(values)
|
||||
|
|
Loading…
Reference in New Issue
Block a user