web-dev-qa-db-fra.com

Comment travailler avec les types de fichiers image HEIC dans Python

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?

11
j12y

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")

  ...
6
danial

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.

0
Peter Kunszt

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.

0
Tropicalrambler