diff --git a/.github/workflows/Check.yml b/.github/workflows/Check.yml index 79dd49e..53f88d0 100644 --- a/.github/workflows/Check.yml +++ b/.github/workflows/Check.yml @@ -10,12 +10,12 @@ jobs: python: ['3.8', '3.11'] pillow: [prod, latest] libheif: ['1.16.2-6ee6762-3f6b709', '1.18.2-bf35e9e-47f4fc0'] - pyheif: ['', '0.7.1'] + pyheif: ['', '0.8.0'] exclude: - python: '3.11' - pyheif: '0.7.1' + pyheif: '0.8.0' - libheif: '1.18.2-bf35e9e-47f4fc0' - pyheif: '0.7.1' + pyheif: '0.8.0' steps: - uses: actions/checkout@v2 diff --git a/HeifImagePlugin.py b/HeifImagePlugin.py index 9d84369..200c093 100644 --- a/HeifImagePlugin.py +++ b/HeifImagePlugin.py @@ -11,12 +11,6 @@ from pyheif.error import HeifError -try: - from pyheif.transformations import Transformations -except ImportError: - Transformations = None - - @dataclass class LibheifError: code: int @@ -159,7 +153,7 @@ def _open_heif_file(self, apply_transformations): def _open(self): self.tile = [] - self.heif_file = self._open_heif_file(Transformations is None) + self.heif_file = self._open_heif_file(False) def load(self): heif_file, self.heif_file = self.heif_file, None @@ -183,8 +177,7 @@ def load(self): self.load_prepare() if heif_file.data: - if Transformations is not None: - heif_file = _crop_heif_file(heif_file) + heif_file = _crop_heif_file(heif_file) self.frombytes(heif_file.data, "raw", (self.mode, heif_file.stride)) heif_file.data = None diff --git a/README.md b/README.md index d3c7603..283430e 100644 --- a/README.md +++ b/README.md @@ -50,9 +50,9 @@ This is not a big library but if you want to contribute is very easy! ## Changelog -### 0.6.3 +### 0.7.0 -* Depends on pyheif>=0.8.0 +* Depends on pyheif>=0.8.0, drop older versions support ### 0.6.2 diff --git a/setup.py b/setup.py index 08afc46..4bef201 100755 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ from setuptools import setup -__version__ = '0.6.3' +__version__ = '0.7.0' github_url = 'https://github.com/uploadcare' package_name = 'heif-image-plugin' diff --git a/tests/__init__.py b/tests/__init__.py index 61e8e9f..8674715 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -14,7 +14,8 @@ def avg_diff(im1, im2, *, threshold=0): size = im1.width * im1.height histos = [ - ImageMath.eval("abs(ch1 - ch2)", ch1=ch1, ch2=ch2).convert('L').histogram() + ImageMath.unsafe_eval( + "abs(ch1 - ch2)", ch1=ch1, ch2=ch2).convert('L').histogram() for ch1, ch2 in zip(im1.split(), im2.split()) ] return [ diff --git a/tests/test_reading.py b/tests/test_reading.py index 64131c1..31adbcc 100644 --- a/tests/test_reading.py +++ b/tests/test_reading.py @@ -5,8 +5,9 @@ import pytest from PIL import Image, ImageCms, ImageOps from pyheif.error import HeifError +from pyheif.transformations import Transformations -from HeifImagePlugin import Transformations, check_heif_magic +from HeifImagePlugin import check_heif_magic from . import avg_diff, respath @@ -69,8 +70,7 @@ def test_open_image_metadata(open_mock): m.size = (10, 20) m.mode = 'RGB' m.data = b'rgb' * 10 * 20 - if Transformations is not None: - m.transformations = Transformations(10, 20) + m.transformations = Transformations(10, 20) m.metadata = [ {'type': 'foo', 'data': 'bar'}, {'type': 'bar', 'data': 'foo'}, @@ -102,25 +102,23 @@ def test_check_heif_magic_wrong(): def test_orientation(orientation, orientation_ref_image): image = Image.open(respath('orientation', f'Landscape_{orientation}.heic')) - if Transformations is not None: - # There should be exif in each image, even if Orientation is 0 - assert 'exif' in image.info + # There should be exif in each image, even if Orientation is 0 + assert 'exif' in image.info - # There should be Orientation tag for each image - exif = image.getexif() - assert 0x0112 in exif + # There should be Orientation tag for each image + exif = image.getexif() + assert 0x0112 in exif - # And this orientation should be the same as in filename - assert exif[0x0112] == orientation + # And this orientation should be the same as in filename + assert exif[0x0112] == orientation # Transposed image shoud be Landscape transposed = ImageOps.exif_transpose(image) assert transposed.size == (600, 450) - if Transformations is not None: - # Image should change after transposition - if orientation != 1: - assert image != transposed + # Image should change after transposition + if orientation != 1: + assert image != transposed # The average diff between transposed and original image should be small avg_diffs = avg_diff(transposed, orientation_ref_image, threshold=20) diff --git a/tests/test_transformations.py b/tests/test_transformations.py index d066a3f..ad9e140 100644 --- a/tests/test_transformations.py +++ b/tests/test_transformations.py @@ -1,24 +1,12 @@ from unittest import mock -import pyheif -import pytest from PIL import Image from pyheif import open as pyheif_open - -from HeifImagePlugin import Transformations +from pyheif.transformations import Transformations from . import avg_diff, respath -skip_no_transformations = pytest.mark.skipif( - Transformations is None, - reason="pyheif doesn't support transformations") - -skip_libheif_not_16 = pytest.mark.skipif( - pyheif.libheif_version() < '1.16.0', - reason="libheif < 1.16.0 can't decode odd sizes") - - def open_with_custom_meta(path, *, exif_data=None, exif=None, crop=None, orientation=0): def my_pyheif_open(*args, **kwargs): nonlocal exif_data @@ -32,11 +20,10 @@ def my_pyheif_open(*args, **kwargs): heif.metadata = [{'type': 'Exif', 'data': exif_data}] else: heif.metadata = None - if Transformations is not None: - heif.transformations = Transformations(*heif.size) - heif.transformations.orientation_tag = orientation - if crop: - heif.transformations.crop = crop + heif.transformations = Transformations(*heif.size) + heif.transformations.orientation_tag = orientation + if crop: + heif.transformations.crop = crop return heif with mock.patch('pyheif.open') as open_mock: @@ -52,14 +39,12 @@ def test_no_orientation_and_no_exif(): assert 'exif' not in image.info -@skip_no_transformations def test_empty_exif(): image = open_with_custom_meta(respath('test2.heic'), exif_data=b'', orientation=1) assert 'exif' in image.info assert image.getexif()[274] == 1 -@skip_no_transformations def test_broken_exif(): broken = b'Exif\x00\x00II*\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00' image = open_with_custom_meta(respath('test2.heic'), @@ -68,7 +53,6 @@ def test_broken_exif(): assert image.getexif()[274] == 1 -@skip_no_transformations def test_orientation_and_no_exif(): image = open_with_custom_meta(respath('test2.heic'), orientation=7) @@ -84,7 +68,6 @@ def test_no_orientation_and_exif_with_rotation(): assert image.getexif()[274] == 7 -@skip_no_transformations def test_orientation_and_exif_with_rotation(): # Orientation tag from file should suppress Exif value image = open_with_custom_meta( @@ -94,7 +77,6 @@ def test_orientation_and_exif_with_rotation(): assert image.getexif()[274] == 1 -@skip_no_transformations def test_orientation_and_exif_without_rotation(): image = open_with_custom_meta( respath('test2.heic'), orientation=1, exif={270: "Sample image"}) @@ -103,7 +85,6 @@ def test_orientation_and_exif_without_rotation(): assert image.getexif()[274] == 1 -@skip_no_transformations def test_crop_on_load(): ref_image = Image.open(respath('test2.heic')) assert ref_image.size == (1280, 720) @@ -117,7 +98,6 @@ def test_crop_on_load(): assert image.copy() == ref_image.crop((99, 33, 611, 289)) -@skip_libheif_not_16 def test_fallback_to_transforms(): # Image with 695x472 color and 696x472 alpha with crop image = Image.open(respath('unreadable-wo-transf.heic'))