diff --git a/picframe/config/configuration_example.yaml b/picframe/config/configuration_example.yaml index effda0a..2daaf6d 100644 --- a/picframe/config/configuration_example.yaml +++ b/picframe/config/configuration_example.yaml @@ -62,6 +62,7 @@ model: "EXIF FocalLength", "EXIF DateTimeOriginal", "Image Model", + "Image Make", "IPTC Caption/Abstract", "IPTC Object Name", "IPTC Keywords"] diff --git a/picframe/get_image_meta.py b/picframe/get_image_meta.py index 0f98b0b..a3d62f8 100644 --- a/picframe/get_image_meta.py +++ b/picframe/get_image_meta.py @@ -1,5 +1,6 @@ import exifread import logging +import os from PIL import Image class GetImageMeta: @@ -102,7 +103,23 @@ def get_orientation(self): def get_exif(self, key): try: - val = self.__get_if_exist(key) + iso_keys = ['EXIF ISOSpeedRatings', 'EXIF PhotographicSensitivity', 'EXIF ISO'] # ISO prior 2.2, ISOSpeedRatings 2.2, PhotographicSensitivity 2.3 + if key in iso_keys: + for iso in iso_keys: + val = self.__get_if_exist(iso) + if val: + break + else: + val = self.__get_if_exist(key) + + if val is None: + grp, tag = key.split(" ", 1) + if grp == "EXIF": + newkey = "Image" + " " + tag + val = self.__get_if_exist(newkey) + elif grp == "Image": + newkey = "EXIF" + " " + tag + val = self.__get_if_exist(newkey) if val is not None: if key == 'EXIF FNumber': val = round(val.values[0].num / val.values[0].den, 1) @@ -117,11 +134,32 @@ def get_exif(self, key): def get_size(self): try: # corrupt image file might crash app - width = self.get_exif('EXIF ExifImageWidth') - height = self.get_exif('EXIF ExifImageLength') - if width and height: - return int(width), int(height) - return Image.open(self.__filename).size + return GetImageMeta.get_image_object(self.__filename).size except Exception as e: self.__logger.warning("get_size failed on %s -> %s", self.__filename, e) - return (0, 0) \ No newline at end of file + return (0, 0) + + @staticmethod + def get_image_object(fname): + ext = os.path.splitext(fname)[1].lower() + if ext in ('.heif','.heic'): + try: + import pyheif + + heif_file = pyheif.read(fname) + image = Image.frombytes(heif_file.mode, heif_file.size, heif_file.data, + "raw", heif_file.mode, heif_file.stride) + if image.mode not in ("RGB", "RGBA"): + image = image.convert("RGB") + return image + except: + logger = logging.getLogger("get_image_meta.GetImageMeta") + logger.warning("Failed attempt to convert %s \n** Have you installed pyheif? **", fname) + else: + try: + image = Image.open(fname) + if image.mode not in ("RGB", "RGBA"): # mat system needs RGB or more + image = image.convert("RGB") + except: # for whatever reason + image = None + return image \ No newline at end of file diff --git a/picframe/image_cache.py b/picframe/image_cache.py index d2ed8bd..c03aa62 100644 --- a/picframe/image_cache.py +++ b/picframe/image_cache.py @@ -9,7 +9,7 @@ class ImageCache: EXTENSIONS = ['.png','.jpg','.jpeg','.heif','.heic'] EXIF_TO_FIELD = {'EXIF FNumber': 'f_number', - 'EXIF Make': 'make', + 'Image Make': 'make', 'Image Model': 'model', 'EXIF ExposureTime': 'exposure_time', 'EXIF ISOSpeedRatings': 'iso', @@ -454,7 +454,8 @@ def __get_exif_info(self, file_path_name): e['orientation'] = exifs.get_orientation() width, height = exifs.get_size() - if e['orientation'] in (5, 6, 7, 8): + ext = os.path.splitext(file_path_name)[1].lower() + if ext not in ('.heif','.heic') and e['orientation'] in (5, 6, 7, 8): width, height = height, width # swap values e['width'] = width e['height'] = height @@ -466,7 +467,7 @@ def __get_exif_info(self, file_path_name): e['exposure_time'] = exifs.get_exif('EXIF ExposureTime') e['iso'] = exifs.get_exif('EXIF ISOSpeedRatings') e['focal_length'] = exifs.get_exif('EXIF FocalLength') - e['rating'] = exifs.get_exif('EXIF Rating') + e['rating'] = exifs.get_exif('Image Rating') e['lens'] = exifs.get_exif('EXIF LensModel') e['exif_datetime'] = None val = exifs.get_exif('EXIF DateTimeOriginal') diff --git a/picframe/viewer_display.py b/picframe/viewer_display.py index f43472a..d200b42 100644 --- a/picframe/viewer_display.py +++ b/picframe/viewer_display.py @@ -8,7 +8,7 @@ import os import numpy as np from PIL import Image, ImageFilter, ImageFile -from picframe import mat_image +from picframe import mat_image, get_image_meta from datetime import datetime # supported display modes for display switch @@ -173,29 +173,6 @@ def clock_is_on(self): def clock_is_on(self, val): self.__show_clock = val - def __check_heif_then_open(self, fname): - ext = os.path.splitext(fname)[1].lower() - if ext in ('.heif','.heic'): - try: - import pyheif - - heif_file = pyheif.read(fname) - image = Image.frombytes(heif_file.mode, heif_file.size, heif_file.data, - "raw", heif_file.mode, heif_file.stride) - if image.mode not in ("RGB", "RGBA"): - image = image.convert("RGB") - return image - except: - self.__logger.warning("Failed attempt to convert %s \n** Have you installed pyheif? **", fname) - else: - try: - image = Image.open(fname) - if image.mode not in ("RGB", "RGBA"): # mat system needs RGB or more - image = image.convert("RGB") - except: # for whatever reason - image = None - return image - # Concatenate the specified images horizontally. Clip the taller # image to the height of the shorter image. def __create_image_pair(self, im1, im2): @@ -210,7 +187,11 @@ def __create_image_pair(self, im1, im2): dst.paste(im2, (im1.width + sep, 0)) return dst - def __orientate_image(self, im, orientation): + def __orientate_image(self, im, pic): + ext = os.path.splitext(pic.fname)[1].lower() + if ext in ('.heif','.heic'): # heif and heic images are converted to PIL.Image obects and are alway in correct orienation + return im + orientation = pic.orientation if orientation == 2: im = im.transpose(Image.FLIP_LEFT_RIGHT) elif orientation == 3: @@ -272,15 +253,18 @@ def __tex_load(self, pics, size=None): # Load the image(s) and correct their orientation as necessary if pics[0]: - im = self.__check_heif_then_open(pics[0].fname) - if pics[0].orientation != 1: - im = self.__orientate_image(im, pics[0].orientation) + im = get_image_meta.GetImageMeta.get_image_object(pics[0].fname) if im is None: return None + if pics[0].orientation != 1: + im = self.__orientate_image(im, pics[0]) + if pics[1]: - im2 = self.__check_heif_then_open(pics[1].fname) + im2 = get_image_meta.GetImageMeta.get_image_object(pics[1].fname) + if im2 is None: + return None if pics[1].orientation != 1: - im2 = self.__orientate_image(im2, pics[1].orientation) + im2 = self.__orientate_image(im2, pics[1]) screen_aspect, image_aspect, diff_aspect = self.__get_aspect_diff(size, im.size) diff --git a/test/test_get_image_meta.py b/test/test_get_image_meta.py index 2b5d6b1..f153ecf 100644 --- a/test/test_get_image_meta.py +++ b/test/test_get_image_meta.py @@ -69,7 +69,9 @@ def test_exifs_jpg(): assert width == 1920 assert height == 1200 val = exifs.get_exif('Image Make') - assert val == "ILCE-7RM3" + assert val == "SONY" + val = exifs.get_exif('EXIF Make') # This should work as well + assert val == "SONY" except: pytest.fail("Unexpected exception") @@ -87,7 +89,7 @@ def test_get_orientation(): exifs = GetImageMeta("test/images/test3.HEIC") orientation = exifs.get_orientation() - assert orientation == 6 + assert orientation == 6 except: pytest.fail("Unexpected exception") @@ -98,8 +100,8 @@ def test_exifs_heic(): assert orientation == 6 width, height = exifs.get_size() - assert width == 4032 - assert height == 3024 + assert height == 4032 + assert width == 3024 f_number = exifs.get_exif('EXIF FNumber')