Skip to content

Commit

Permalink
Try reopen heif in case when can't be opened without transformations
Browse files Browse the repository at this point in the history
  • Loading branch information
homm committed Aug 19, 2024
1 parent 51f173e commit 3d5dc03
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 9 deletions.
29 changes: 21 additions & 8 deletions HeifImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,20 +99,20 @@ class HeifImageFile(ImageFile.ImageFile):
format = 'HEIF'
format_description = "HEIF/HEIC image"

def _open(self):
def _open_heif_file(self, apply_transformations):
try:
heif_file = pyheif.open(
self.fp, apply_transformations=Transformations is None)
self.fp, apply_transformations=apply_transformations)
except HeifError as e:
raise SyntaxError(str(e))

_extract_heif_exif(heif_file)

if Transformations is not None:
if apply_transformations:
self._size = heif_file.size
else:
heif_file = _rotate_heif_file(heif_file)
self._size = heif_file.transformations.crop[2:4]
else:
self._size = heif_file.size

if hasattr(self, "_mode"):
self._mode = heif_file.mode
Expand All @@ -121,6 +121,9 @@ def _open(self):
# https://pillow.readthedocs.io/en/stable/releasenotes/10.1.0.html#setting-image-mode
self.mode = heif_file.mode

self.info.pop('exif', None)
self.info.pop('icc_profile', None)

if heif_file.exif:
self.info['exif'] = heif_file.exif

Expand All @@ -135,20 +138,30 @@ def _open(self):
# We need to go deeper...
if heif_file.color_profile['type'] in ('rICC', 'prof'):
self.info['icc_profile'] = heif_file.color_profile['data']
return heif_file

def _open(self):
self.tile = []
self.heif_file = heif_file
self.heif_file = self._open_heif_file(Transformations is None)

def load(self):
heif_file, self.heif_file = self.heif_file, None
if heif_file:
try:
heif_file = heif_file.load()
try:
heif_file = heif_file.load()
except HeifError as e:
if not (e.code == 4 and e.subcode == 3003):
raise
# Unsupported feature: Unsupported color conversion
# https://github.com/strukturag/libheif/issues/1273
self.fp.seek(0)
heif_file = self._open_heif_file(True).load()
except HeifError as e:
# Ignore EOF error and return blank image otherwise
cropped_file = e.code == 7 and e.subcode == 100
if not cropped_file or not ImageFile.LOAD_TRUNCATED_IMAGES:
raise
# Ignore EOF error and return blank image otherwise

self.load_prepare()

Expand Down
Binary file added tests/images/unreadable-wo-transf.heic
Binary file not shown.
Binary file added tests/images/unreadable-wo-transf.ref.heic
Binary file not shown.
12 changes: 11 additions & 1 deletion tests/test_transformations.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from HeifImagePlugin import Transformations

from . import respath
from . import avg_diff, respath


skip_if_no_transformations = pytest.mark.skipif(
Expand Down Expand Up @@ -110,3 +110,13 @@ def test_crop_on_load():
image = open_with_custom_meta(respath('test2.heic'), crop=(99, 33, 512, 256))
assert image.size == (512, 256)
assert image.copy() == ref_image.crop((99, 33, 611, 289))


def test_fallback_to_transforms():
# Image with 695x472 color and 696x472 alpha with crop
image = Image.open(respath('unreadable-wo-transf.heic'))
assert image.size == (695, 472)

ref_image = Image.open(respath('unreadable-wo-transf.ref.heic'))
avg_diffs = avg_diff(image, ref_image)
assert max(avg_diffs) <= 0.01

0 comments on commit 3d5dc03

Please sign in to comment.