Le format fichier image haute efficacité (HEIF) est le format par défaut lors du parachutage d'une image d'un iPhone vers un appareil OSX. Je veux éditer et modifier ces fichiers .HEIC avec Python.
Je pourrais modifier les paramètres du téléphone pour enregistrer au format JPG par défaut, mais cela ne résout pas vraiment le problème de pouvoir travailler avec le type de fichier des autres. Je veux toujours pouvoir traiter les fichiers HEIC pour faire la conversion de fichiers, extraire les métadonnées, etc. ( Exemple d'utilisation - Géocodage )
Oreiller
Voici le résultat du travail avec Python 3.7 et Pillow lorsque vous essayez de lire un fichier de ce type.
$ ipython
Python 3.7.0 (default, Oct 2 2018, 09:20:07)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.2.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: from PIL import Image
In [2]: img = Image.open('IMG_2292.HEIC')
---------------------------------------------------------------------------
OSError Traceback (most recent call last)
<ipython-input-2-fe47106ce80b> in <module>
----> 1 img = Image.open('IMG_2292.HEIC')
~/.env/py3/lib/python3.7/site-packages/PIL/Image.py in open(fp, mode)
2685 warnings.warn(message)
2686 raise IOError("cannot identify image file %r"
-> 2687 % (filename if filename else fp))
2688
2689 #
OSError: cannot identify image file 'IMG_2292.HEIC'
Il semble que la prise en charge de python-pillow ait été demandée ( # 2806 ) mais des problèmes de licence/brevet l'empêchent là-bas.
ImageMagick + baguette
Il semble que ImageMagick peut être une option. Après avoir fait un brew install imagemagick
et pip install wand
mais je n'ai pas réussi.
$ ipython
Python 3.7.0 (default, Oct 2 2018, 09:20:07)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.2.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: from wand.image import Image
In [2]: with Image(filename='img.jpg') as img:
...: print(img.size)
...:
(4032, 3024)
In [3]: with Image(filename='img.HEIC') as img:
...: print(img.size)
...:
---------------------------------------------------------------------------
MissingDelegateError Traceback (most recent call last)
<ipython-input-3-9d6f58c40f95> in <module>
----> 1 with Image(filename='ces2.HEIC') as img:
2 print(img.size)
3
~/.env/py3/lib/python3.7/site-packages/wand/image.py in __init__(self, image, blob, file, filename, format, width, height, depth, background, resolution, pseudo)
4603 self.read(blob=blob, resolution=resolution)
4604 Elif filename is not None:
-> 4605 self.read(filename=filename, resolution=resolution)
4606 # clear the wand format, otherwise any subsequent call to
4607 # MagickGetImageBlob will silently change the image to this
~/.env/py3/lib/python3.7/site-packages/wand/image.py in read(self, file, filename, blob, resolution)
4894 r = library.MagickReadImage(self.wand, filename)
4895 if not r:
-> 4896 self.raise_exception()
4897
4898 def save(self, file=None, filename=None):
~/.env/py3/lib/python3.7/site-packages/wand/resource.py in raise_exception(self, stacklevel)
220 warnings.warn(e, stacklevel=stacklevel + 1)
221 Elif isinstance(e, Exception):
--> 222 raise e
223
224 def __enter__(self):
MissingDelegateError: no decode delegate for this image format `HEIC' @ error/constitute.c/ReadImage/556
Y a-t-il d'autres alternatives disponibles pour effectuer une conversion par programme?
Vous devriez vérifier cette bibliothèque, c'est un wrapper Python 3 pour la bibliothèque libheif , elle devrait servir votre objectif de conversion de fichier, extraire les métadonnées:
https://github.com/david-poirier-csn/pyheif
https://pypi.org/project/pyheif/
Exemple d'utilisation:
import whatimage
import pyheif
from PIL import Image
def decodeImage(bytesIo):
fmt = whatimage.identify_image(bytesIo)
if fmt in ['heic', 'avif']:
i = pyheif.read_heif(bytesIo)
# Extract metadata etc
for metadata in i.metadata or []:
if metadata['type']=='Exif':
# do whatever
# Convert to other file format like jpeg
s = io.BytesIO()
pi = Image.frombytes(
mode=i.mode, size=i.size, data=i.data)
pi.save(s, format="jpeg")
...
Ajoutant à la réponse de danial, j'ai juste eu à modifier légèrement le tableau d'octets pour obtenir un flux de données valide pour un travail ultérieur. Les 6 premiers octets sont "Exif\x00\x00". En les supprimant, vous obtiendrez un format brut que vous pourrez transférer dans n'importe quel outil de traitement d'image.
import pyheif
import PIL
import exifread
def read_heic(path: str):
with open(path, 'rb') as file:
image = pyheif.read_heif(file)
for metadata in image.metadata or []:
if metadata['type'] == 'Exif':
fstream = io.BytesIO(metadata['data'][6:])
# now just convert to jpeg
pi = PIL.Image.open(fstream)
pi.save("file.jpg", "JPEG")
# or do EXIF processing with exifread
tags = exifread.process_file(fstream)
Au moins, cela a fonctionné pour moi.
Je suis confronté exactement au même problème que vous, je veux une solution CLI. En faisant d'autres recherches, il semble que ImageMagick nécessite la bibliothèque de délégués libheif
. La bibliothèque libheif elle-même semble également avoir quelques dépendances.
Je n'ai pas réussi à faire en sorte que ces éléments fonctionnent également, mais je vais continuer d'essayer. Je vous suggère de vérifier si ces dépendances sont disponibles pour votre configuration.