高効率画像ファイル (HEIF)形式は、iPhoneからOSXデバイスに画像をエアドロップするときのデフォルトです。これらの.HEICファイルをPythonで編集および変更したい。
デフォルトでJPGとして保存するように電話の設定を変更することもできますが、他のユーザーのファイルタイプを使用できるという問題は実際には解決しません。ファイル変換やメタデータの抽出などを行うためにHEICファイルを処理できるようにしたい( 使用例の例-ジオコーディング )
枕
このタイプのファイルを読み込もうとしたときにPython 3.7およびPillowを操作した結果がここにあります。
$ 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'
Python-pillowでのサポートがリクエストされたようです( #2806 )が、ライセンス/特許の問題により、サポートされていません。
ImageMagick +ワンド
ImageMagick はオプションのようです。 brew install imagemagick
とpip install wand
を実行した後、失敗しました。
$ 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
プログラムで変換を行うために利用できる他の選択肢はありますか?
あなたはこのライブラリをチェックアウトするべきです、それは libheif ライブラリへのPython 3ラッパーです)、それはファイル変換の目的に役立ち、メタデータを抽出します:
https://github.com/david-poirier-csn/pyheif
https://pypi.org/project/pyheif/
使用例:
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バイトは 'Exif\x00\x00'です。これらを削除すると、任意の画像処理ツールにパイプできる生の形式になります。
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)
少なくともこれでうまくいきました。