You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python HEIC转JPG程序报UnidentifiedImageError求助

问题分析与解决方案

核心原因

  1. PIL原生不支持HEIC格式:直接用Image.open()打开HEIC文件会触发UnidentifiedImageError,必须依赖HEIC解码扩展库。
  2. 代码逻辑错误:
    • 上传文件时调用了uploaded_file.read(),导致文件指针移动到末尾,后续convert_file中再读取文件会失败。
    • 重复调用Image.open(),且保存路径拼接错误,导致文件无法写入。
    • 类初始化时变量类型错误(uploaded_files设为字符串而非列表)。

依赖安装(替代pyheif的更稳定方案)

放弃pyheif,改用pillow-heif(直接作为PIL的插件,无需额外解码逻辑):

pip install pillow-heif

安装后PIL会自动识别HEIC格式,无需额外配置。

修正后的完整代码

import streamlit as st
import os
from PIL import Image
# 导入pillow-heif注册解码器
import pillow_heif

# 注册HEIC解码器
pillow_heif.register_heif_opener()

class HEICToImgConverter():

    def __init__(self) -> None:
        self.uploaded_files = []  # 初始化为列表而非字符串
        self.upload_file()

    def upload_file(self):
        self.uploaded_files = st.file_uploader("选择HEIC文件(支持批量)", accept_multiple_files=True, type=['heic'])
        if self.uploaded_files:
            # 创建输出文件夹
            output_dir = 'converted_images'
            if not os.path.exists(output_dir):
                os.makedirs(output_dir)
            st.write("已选择文件:")
            for uploaded_file in self.uploaded_files:
                st.write(f"文件名:{uploaded_file.name}")
            if st.button("批量转换为JPG"):
                self.convert_files()
        else:
            st.write("请选择HEIC文件")

    def convert_files(self):
        output_dir = 'converted_images'
        success_count = 0
        for uploaded_file in self.uploaded_files:
            file_name = uploaded_file.name.lower()
            if file_name.endswith('.heic'):
                try:
                    # 重置文件指针(避免之前read导致的空文件问题)
                    uploaded_file.seek(0)
                    with Image.open(uploaded_file) as im:
                        new_file_name = os.path.splitext(file_name)[0] + '.jpg'
                        save_path = os.path.join(output_dir, new_file_name)
                        # 保存为JPG,设置质量参数
                        im.save(save_path, 'JPEG', quality=95)
                    success_count += 1
                    st.write(f"✅ {uploaded_file.name} 转换完成")
                except Exception as e:
                    st.write(f"❌ {uploaded_file.name} 转换失败:{str(e)}")
        st.write(f"转换完成!成功转换 {success_count}/{len(self.uploaded_files)} 个文件")
        # 提供下载按钮(可选)
        if success_count > 0:
            st.download_button(
                label="下载全部转换文件(打包)",
                data=self.zip_output_dir(output_dir),
                file_name="converted_jpgs.zip",
                mime="application/zip"
            )

    def zip_output_dir(self, dir_path):
        import zipfile
        from io import BytesIO
        zip_buffer = BytesIO()
        with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zipf:
            for root, _, files in os.walk(dir_path):
                for file in files:
                    file_path = os.path.join(root, file)
                    zipf.write(file_path, os.path.relpath(file_path, dir_path))
        zip_buffer.seek(0)
        return zip_buffer

HEICToImgConverter()

关键修改点说明

  1. 注册HEIC解码器:通过pillow_heif.register_heif_opener()让PIL支持HEIC格式。
  2. 修复文件指针问题:在打开文件前调用uploaded_file.seek(0)重置指针,避免之前读取导致的空文件错误。
  3. 修正路径拼接:直接用os.path.join(output_dir, new_file_name)生成正确的保存路径,避免重复拼接文件名。
  4. 添加错误处理:捕获转换过程中的异常,显示具体错误信息。
  5. 优化用户体验:添加转换状态提示和批量下载功能。
  6. 规范命名:类名改为大驼峰式,符合Python编码规范。

内容的提问来源于stack exchange,提问作者Baris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 22:42:17