问题描述
1.jpg
使用 Webp 转换器 转换为 1.webp
from docx import Document
document = Document()
document.add_picture('1.webp')
document.save('test.docx')
报错 docx.image.exceptions.UnrecognizedImageError
,发现该图片的 mime_type 为 image/webp
,这是一种浏览器压缩图片的格式
查看源码,image.py 会从 SIGNATURES 读取不同格式的图像文件
安装
pip install python-docx
pip install python-magic
Windows 下还要
pip install python-magic-bin
代码
使用 图像转换器 对 1.jpg 进行不同图像格式转换
mime_type
import magic
files = ['1.jpg', '1.png', '1.jfif', '1.gif', '1.tiff', '1.bmp', '1.eps', '1.hdr', '1.ico', '1.svg', '1.tga', '1.wbmp', '1.webp']
for file in files:
print(file, magic.from_file(file, mime=True))
# 1.jpg image/jpeg
# 1.png image/png
# 1.jfif image/jpeg
# 1.gif image/gif
# 1.tiff image/tiff
# 1.bmp image/x-ms-bmp
# 1.eps application/postscript
# 1.hdr application/octet-stream
# 1.ico image/x-icon
# 1.svg image/svg+xml
# 1.tga image/x-tga
# 1.wbmp application/octet-stream
# 1.webp image/webp
能否插入
from docx import Document
document = Document()
document.add_picture('1.jpg')
document.add_picture('1.png')
document.add_picture('1.jfif')
# document.add_picture('1.exif')
document.add_picture('1.gif')
document.add_picture('1.tiff')
document.add_picture('1.bmp')
document.add_picture('1.eps')
document.add_picture('1.hdr')
document.add_picture('1.ico')
document.add_picture('1.svg')
document.add_picture('1.tga')
document.add_picture('1.wbmp')
document.add_picture('1.webp')
document.save('test.docx')
结论
图片格式 | mime_type | 能否插入 |
---|---|---|
.jpg | image/jpeg | √ |
.png | image/png | √ |
.jfif | image/jpeg | √ |
.exif | √ | |
.gif | image/gif | √ |
.tiff | image/tiff | √ |
.bmp | image/x-ms-bmp | √ |
.eps | application/postscript | × |
.hdr | application/octet-stream | × |
.ico | image/x-icon | × |
.svg | image/svg+xml | × |
.tga | image/x-tga | × |
.wbmp | application/octet-stream | × |
.webp | image/webp | × |
解决方案
方案一、转换格式
将其他格式转换成可插入的类型,如 .jpg
安装
pip install pillow
代码
import io
from pathlib import Path
import magic
from PIL import Image
def image_to_jpg(image_path_or_stream):
"""使用Pillow将不支持的图片文件转换为.jpg文件"""
f = io.BytesIO()
if isinstance(image_path_or_stream, str):
path = Path(image_path_or_stream)
if path.suffix in {'.jpg', '.png', '.jfif', '.exif', '.gif', '.tiff', '.bmp'}:
f = open(image_path_or_stream, mode='rb')
else:
Image.open(image_path_or_stream).convert('RGB').save(f, format='JPEG')
else:
buffer = image_path_or_stream.read()
mime_type = magic.from_buffer(buffer, mime=True)
if mime_type in {'image/jpeg', 'image/png', 'image/gif', 'image/tiff', 'image/x-ms-bmp'}:
f = image_path_or_stream
else:
Image.open(io.BytesIO(buffer)).convert('RGB').save(f, format='JPEG')
return f
if __name__ == '__main__':
from docx import Document
document = Document()
document.add_picture(image_to_jpg('1.jpg'))
document.add_picture(image_to_jpg('1.webp'))
document.add_picture(image_to_jpg(open('1.jpg', mode='rb')))
document.add_picture(image_to_jpg(open('1', mode='rb'))) # 将1.webp拷贝一份并改名为1
document.save('test.docx')
方案二、修改库代码
先尝试能否手动插入到 Word 文档,可以的话证明支持这种格式,再自行修改库,继承 BaseImageHeader
类,实现 from_stream()
方法,并在 SIGNATURES
中加入该图片格式
插入没有后缀的文件提示【当前无法显示此图像。】
将 1.jpg 改名为 1
from docx import Document
document = Document()
document.add_picture('1')
document.save('test.docx')
效果
改成这样即可
from docx import Document
document = Document()
document.add_picture(open('1', mode='rb'))
document.save('test.docx')