How to work with HEIC image file types in Python
Solution 1
You guys should check out this library, it's a Python 3 wrapper to the libheif library, it should serve your purpose of file conversion, extracting metadata:
https://github.com/david-poirier-csn/pyheif
https://pypi.org/project/pyheif/
Example usage:
import io
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")
...
Solution 2
I was quite successful with Wand package : Install Wand: https://docs.wand-py.org/en/0.6.4/ Code for conversion:
from wand.image import Image
import os
SourceFolder="K:/HeicFolder"
TargetFolder="K:/JpgFolder"
for file in os.listdir(SourceFolder):
SourceFile=SourceFolder + "/" + file
TargetFile=TargetFolder + "/" + file.replace(".HEIC",".JPG")
img=Image(filename=SourceFile)
img.format='jpg'
img.save(filename=TargetFile)
img.close()
Solution 3
Adding to the answer by danial, i just had to modify the byte array slighly to get a valid datastream for further work. The first 6 bytes are 'Exif\x00\x00' .. dropping these will give you a raw format that you can pipe into any image processing tool.
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)
At least this worked for me.
Solution 4
You can use the pillow_heif
library to read HEIF images in a way compatible with PIL.
The example below will import a HEIF picture and save it in png
format.
from PIL import Image
import pillow_heif
heif_file = pillow_heif.read_heif("HEIC_file.HEIC")
image = Image.frombytes(
heif_file.mode,
heif_file.size,
heif_file.data,
"raw",
)
image.save("./picture_name.png", format="png")
Solution 5
This will do go get the exif data from the heic file
import pyheif
import exifread
import io
heif_file = pyheif.read_heif("file.heic")
for metadata in heif_file.metadata:
if metadata['type'] == 'Exif':
fstream = io.BytesIO(metadata['data'][6:])
exifdata = exifread.process_file(fstream,details=False)
# example to get device model from heic file
model = str(exifdata.get("Image Model"))
print(model)
j12y
**Sr. Manager, Developer Relations, Dolby Laboratories Robot Garden, Maker Previously HERE, GE, Rackspace, DreamWorks Animation, MathWorks, Carnegie Mellon
Updated on July 09, 2022Comments
-
j12y almost 2 years
The High Efficiency Image File (HEIF) format is the default when airdropping an image from an iPhone to a OSX device. I want to edit and modify these .HEIC files with Python.
I could modify phone settings to save as JPG by default but that doesn't really solve the problem of being able to work with the filetype from others. I still want to be able to process HEIC files for doing file conversion, extracting metadata, etc. (Example Use Case -- Geocoding)
Pillow
Here is the result of working with Python 3.7 and Pillow when trying to read a file of this 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'
It looks like support in python-pillow was requested (#2806) but there are licensing / patent issues preventing it there.
ImageMagick + Wand
It appears that ImageMagick may be an option. After doing a
brew install imagemagick
andpip install wand
however I was unsuccessful.$ 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
Any other alternatives available to do a conversion programmatically?
-
j12y over 5 yearsSimilarly Sindre Sorhus has an excellent HEIC Converter to generate JPEG or PNG images but not the flexibility I'm looking for. sindresorhus.com/heic-converter
-
buzjwa about 5 yearsExifTool provides a CLI for working with image metadata and supports HEIF. Should be easy to wrap in Python.
-
Mark Setchell over 4 yearsThis may help... stackoverflow.com/a/54558699/2836621
-
-
Norm over 4 yearsMy experience with
pyheif
is that it successfully reads HEIC files, but I don't understand how or whyImage.frombytes()
is supposed to work in the code above. Wouldn't that require PIL to understand HEIF? In any event, what I get is a badly corrupted JPG file when I run it. -
Cigogne Eveillée over 4 years
read_heif
required actual data, so the line should actually be:pyheif.read_heif(bytesIo.read())
-
user9074332 over 4 yearscan you give some examples of the
do whatever
?metadata['data']
here appears to be of typebytes
. But when I attempt to:metadata['data'].decode('utf-8'))
, I see:UnicodeDecodeError: 'utf-8' codec can't decode byte 0x86 in position 27: invalid start byte
-
Tropicalrambler over 4 yearsThank you for this Mark, it will prove useful.
-
Zhang18 about 4 yearsfwiw, I tried to install
pyheif
on windows and ran into this issue. Turns outpyheif
is not compatible with Windows. -
Josh Clark over 3 yearsUsing your code, when I pass an HEIC file path I get
PIL.UnidentifiedImageError: cannot identify image file <_io.BytesIO object at 0x109aefef0>
. -
M-Chen-3 over 3 yearsPlease explain what your code does and how it does it.
-
d1p3 over 3 yearsThis is a simple solution using multiple libraries. It basically opens each .heic file inside the same folder as the ".py" file and converts to jpg. Did you mean code explanation?
-
M-Chen-3 over 3 yearsYes, every answer should explain how the code works.
-
Rodriguez over 3 yearsIt seems ImageMagick (low level lib used by Wand) does not support heic delegate in some distro's package manager out of the box (eg: Centos 8).
-
pedroprates almost 3 yearsHad the same problem as Josh, PIL is unable to identify the HEIC image with this code
-
AlvaroFG almost 3 yearsThanks!, this worked for me as I couldn't get pyheif to work in windows 10.
-
mara004 over 2 yearsYour code has invalid indentation. Please correct your example so that it is actually testable.
-
Gerald Zehetner over 2 yearsThis does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From Review
-
Alexander Piskun about 2 yearsI know that it is not an answer, but here are examples and documentation: pillow-heif-docs From now work with heif,heic and hif files in python as simple as with all other images using Pillow, i done my best.