Skip to content

Commit 70b3815

Browse files
authored
Merge pull request #8127 from radarhere/multiple_exif_markers
Fixed processing multiple JPEG EXIF markers
2 parents 41426a6 + 88cd6d4 commit 70b3815

File tree

3 files changed

+32
-33
lines changed

3 files changed

+32
-33
lines changed

Tests/images/multiple_exif.jpg

27 Bytes
Loading

Tests/test_file_jpeg.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -872,7 +872,7 @@ def test_ifd_offset_exif(self) -> None:
872872

873873
def test_multiple_exif(self) -> None:
874874
with Image.open("Tests/images/multiple_exif.jpg") as im:
875-
assert im.info["exif"] == b"Exif\x00\x00firstsecond"
875+
assert im.getexif()[270] == "firstsecond"
876876

877877
@mark_if_feature_version(
878878
pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"

src/PIL/JpegImagePlugin.py

Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -161,38 +161,6 @@ def APP(self, marker):
161161
# plus constant header size
162162
self.info["mpoffset"] = self.fp.tell() - n + 4
163163

164-
# If DPI isn't in JPEG header, fetch from EXIF
165-
if "dpi" not in self.info and "exif" in self.info:
166-
try:
167-
exif = self.getexif()
168-
resolution_unit = exif[0x0128]
169-
x_resolution = exif[0x011A]
170-
try:
171-
dpi = float(x_resolution[0]) / x_resolution[1]
172-
except TypeError:
173-
dpi = x_resolution
174-
if math.isnan(dpi):
175-
msg = "DPI is not a number"
176-
raise ValueError(msg)
177-
if resolution_unit == 3: # cm
178-
# 1 dpcm = 2.54 dpi
179-
dpi *= 2.54
180-
self.info["dpi"] = dpi, dpi
181-
except (
182-
struct.error,
183-
KeyError,
184-
SyntaxError,
185-
TypeError,
186-
ValueError,
187-
ZeroDivisionError,
188-
):
189-
# struct.error for truncated EXIF
190-
# KeyError for dpi not included
191-
# SyntaxError for invalid/unreadable EXIF
192-
# ValueError or TypeError for dpi being an invalid float
193-
# ZeroDivisionError for invalid dpi rational value
194-
self.info["dpi"] = 72, 72
195-
196164

197165
def COM(self: JpegImageFile, marker: int) -> None:
198166
#
@@ -411,6 +379,8 @@ def _open(self):
411379
msg = "no marker found"
412380
raise SyntaxError(msg)
413381

382+
self._read_dpi_from_exif()
383+
414384
def load_read(self, read_bytes: int) -> bytes:
415385
"""
416386
internal: read more image data
@@ -499,6 +469,35 @@ def load_djpeg(self) -> None:
499469
def _getexif(self) -> dict[str, Any] | None:
500470
return _getexif(self)
501471

472+
def _read_dpi_from_exif(self) -> None:
473+
# If DPI isn't in JPEG header, fetch from EXIF
474+
if "dpi" in self.info or "exif" not in self.info:
475+
return
476+
try:
477+
exif = self.getexif()
478+
resolution_unit = exif[0x0128]
479+
x_resolution = exif[0x011A]
480+
try:
481+
dpi = float(x_resolution[0]) / x_resolution[1]
482+
except TypeError:
483+
dpi = x_resolution
484+
if math.isnan(dpi):
485+
msg = "DPI is not a number"
486+
raise ValueError(msg)
487+
if resolution_unit == 3: # cm
488+
# 1 dpcm = 2.54 dpi
489+
dpi *= 2.54
490+
self.info["dpi"] = dpi, dpi
491+
except (
492+
struct.error, # truncated EXIF
493+
KeyError, # dpi not included
494+
SyntaxError, # invalid/unreadable EXIF
495+
TypeError, # dpi is an invalid float
496+
ValueError, # dpi is an invalid float
497+
ZeroDivisionError, # invalid dpi rational value
498+
):
499+
self.info["dpi"] = 72, 72
500+
502501
def _getmp(self):
503502
return _getmp(self)
504503

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy