如何在Python中处理HEIC图像文件类型

74

高效图像文件(HEIF)格式是从iPhone向OSX设备空投图像时的默认格式。我想使用Python编辑和修改这些.HEIC文件。

我可以修改手机设置,将默认保存为JPG,但这并不能真正解决与他人共享文件类型问题。我仍然希望能够处理HEIC文件,以进行文件转换、提取元数据等操作(示例用例--地理编码

Pillow

这是在使用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 + Wand
看起来ImageMagick可能是一个选项。然而,在执行brew install imagemagickpip 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

有没有其他可用的方法来进行程序转换?

1
同样地,Sindre Sorhus有一个出色的HEIC转换器,可以生成JPEG或PNG图像,但不是我正在寻找的灵活性。https://sindresorhus.com/heic-converter - j12y
1
ExifTool 提供了一个命令行界面,用于处理图像元数据并支持 HEIF 格式。在 Python 中使用应该很容易。 - buzjwa
这可能会有所帮助... https://stackoverflow.com/a/54558699/2836621 - Mark Setchell
1
仅供参考: 今天发布了pillow-heif的第一个版本,支持64位Windows。现在它几乎支持所有平台,除了Windows ARM和32位系统。在这个话题中,两个人展示了它的基本用法。 - Alexander Piskun
14个回答

0

我和你一样面临着同样的问题,需要一个CLI解决方案。经过进一步的研究,似乎ImageMagick 需要 libheif 委托库。libheif库本身似乎也有一些依赖关系。

我还没有成功地让它们中的任何一个工作,但会继续尝试。建议您检查这些依赖项是否可用于您的配置。


2
谢谢你的分享,Mark。这将会非常有用。 - Tropicalrambler

0
从多个人的回复中得出的简单解决方案。
在运行此代码之前,请安装whatimagepyheifPIL库。

[注意]:我使用了这个命令进行安装。

python3 -m pip install Pillow

同时,在Linux上安装所有这些库要容易得多。我建议Windows用户使用WSL


  • 代码
import whatimage
import pyheif
from PIL import Image
import os

def decodeImage(bytesIo, index):
    with open(bytesIo, 'rb') as f:
    data = f.read()
    fmt = whatimage.identify_image(data)
    if fmt in ['heic', 'avif']:
    i = pyheif.read_heif(data)
    pi = Image.frombytes(mode=i.mode, size=i.size, data=i.data)
    pi.save("new" + str(index) + ".jpg", format="jpeg")

# For my use I had my python file inside the same folder as the heic files
source = "./"

for index,file in enumerate(os.listdir(source)):
    decodeImage(file, index)

请解释您的代码是做什么的以及它如何实现。 - M-Chen-3
1
这是一个使用多个库的简单解决方案。它基本上打开与“.py”文件在同一文件夹中的每个.heic文件并将其转换为jpg。您是指代码说明吗? - d1p3
是的,每个答案都应该解释代码的工作原理。 - M-Chen-3
你的代码缩进无效,请更正你的示例,以便实际测试。 - mara004

0

看起来好像有一个名为 heic-to-jpg 的解决方案,但我不太确定它在 colab 中如何工作。


0

我使用pillow_heif库。例如,当我有一个包含heif文件的文件夹需要转换为png时,我会使用这个脚本。

from PIL import Image
import pillow_heif
import os 
from tqdm import tqdm 
import argparse

def get_images(heic_folder):

    # Get all the heic images in the folder
    imgs = [os.path.join(heic_folder, f) for f in os.listdir(heic_folder) if f.endswith('.HEIC')]

    # Name of the folder where the png files will be stored
    png_folder = heic_folder + "_png"

    # If it doesn't exist, create the folder
    if not os.path.exists(png_folder):
        os.mkdir(png_folder)
    
    for img in tqdm(imgs):
        heif_file = pillow_heif.read_heif(img)
        image = Image.frombytes(
            heif_file.mode,
            heif_file.size,
            heif_file.data,
            "raw",

        )

        image.save(os.path.join(png_folder,os.path.basename(img).split('.')[0])+'.png', format("png"))


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='Convert heic images to png')
    parser.add_argument('heic_folder', type=str, help='Folder with heic images')
    args = parser.parse_args()

    get_images(args.heic_folder)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接