Determine size from markers, not EXIF data

This commit is contained in:
Andrew Murray 2024-03-16 18:40:16 +11:00
parent 794a7d691f
commit a78ed9595f
3 changed files with 10 additions and 21 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

After

Width:  |  Height:  |  Size: 117 KiB

View File

@ -93,7 +93,7 @@ def test_exif(test_file: str) -> None:
def test_frame_size() -> None: def test_frame_size() -> None:
# This image has been hexedited to contain a different size # This image has been hexedited to contain a different size
# in the EXIF data of the second frame # in the SOF marker of the second frame
with Image.open("Tests/images/sugarshack_frame_size.mpo") as im: with Image.open("Tests/images/sugarshack_frame_size.mpo") as im:
assert im.size == (640, 480) assert im.size == (640, 480)

View File

@ -24,14 +24,11 @@ import os
import struct import struct
from . import ( from . import (
ExifTags,
Image, Image,
ImageFile,
ImageSequence, ImageSequence,
JpegImagePlugin, JpegImagePlugin,
TiffImagePlugin, TiffImagePlugin,
) )
from ._binary import i16be as i16
from ._binary import o32le from ._binary import o32le
@ -109,7 +106,6 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile):
self._after_jpeg_open() self._after_jpeg_open()
def _after_jpeg_open(self, mpheader=None): def _after_jpeg_open(self, mpheader=None):
self._initial_size = self.size
self.mpinfo = mpheader if mpheader is not None else self._getmp() self.mpinfo = mpheader if mpheader is not None else self._getmp()
self.n_frames = self.mpinfo[0xB001] self.n_frames = self.mpinfo[0xB001]
self.__mpoffsets = [ self.__mpoffsets = [
@ -137,27 +133,20 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile):
self.fp = self._fp self.fp = self._fp
self.offset = self.__mpoffsets[frame] self.offset = self.__mpoffsets[frame]
original_exif = self.info.get("exif")
if "exif" in self.info:
del self.info["exif"]
self.fp.seek(self.offset + 2) # skip SOI marker self.fp.seek(self.offset + 2) # skip SOI marker
segment = self.fp.read(2) if not self.fp.read(2):
if not segment:
msg = "No data found for frame" msg = "No data found for frame"
raise ValueError(msg) raise ValueError(msg)
self._size = self._initial_size self.fp.seek(self.offset)
if i16(segment) == 0xFFE1: # APP1 JpegImagePlugin.JpegImageFile._open(self)
n = i16(self.fp.read(2)) - 2 if self.info.get("exif") != original_exif:
self.info["exif"] = ImageFile._safe_read(self.fp, n)
self._reload_exif() self._reload_exif()
mptype = self.mpinfo[0xB002][frame]["Attribute"]["MPType"] self.tile = [("jpeg", (0, 0) + self.size, self.offset, self.tile[0][-1])]
if mptype.startswith("Large Thumbnail"):
exif = self.getexif().get_ifd(ExifTags.IFD.Exif)
if 40962 in exif and 40963 in exif:
self._size = (exif[40962], exif[40963])
elif "exif" in self.info:
del self.info["exif"]
self._reload_exif()
self.tile = [("jpeg", (0, 0) + self.size, self.offset, (self.mode, ""))]
self.__frame = frame self.__frame = frame
def tell(self): def tell(self):