使用Python打开webp等格式图片

2022-08-10,,,,

问题

今天处理图片的时候发现有一张后缀为.jpg的图片在电脑上无法打开,但是使用Chrome浏览器能打开。尝试用OpenCV读取,但是也无法打开。

仔细查看了OpenCV支持的图片格式

Windows bitmaps - *.bmp, *.dib (always supported)
JPEG files - *.jpeg, *.jpg, *.jpe (see the Notes section)
JPEG 2000 files - *.jp2 (see the Notes section)
Portable Network Graphics - *.png (see the Notes section)
Portable image format - *.pbm, *.pgm, *.ppm (always supported)
Sun rasters - *.sr, *.ras (always supported)
TIFF files - *.tiff, *.tif (see the Notes section)

按照后缀判断是jpg格式,仔细想想有可能是图片后缀和实际格式不符合。通过以字节码的形式读取该图片,发现一个问题:

思考

字节码头显示RIFF和WEBPVP8这两个关键信息,根据这判断其不是jpg格式,再搜索发现这是谷歌推出的webp图片格式。
以下是常见的图片格式及判断方法:

格式 描述 判断方式
jpeg 用JFIF或者Exif格式保存的JPEG图片 第7到第10个字节是b’JFIF’或者b’Exif’
png 可移植网络图形格式(Portable Network Graphic Format) 以字节串b’\x89PNG\r\n\x1a\n’开头
gif GIF(Graphics Interchange Format)的87版本和89版本 前6个字节为b’GIF87a’或者b’GIF89a’
tiff TIFF(Tag Image File Format)的两种字节顺序 前两个字节为b’MM’或者b’II’
rgb SGI ImgLib 以字节串b’\x01\xda’开头
pbm Portable Bitmap 第1个字节为b’P’,第2个字节为b’1’或b’4’,第3个字节为b’\t’或b’\n’或b’\r’
pgm Portable Graymap Files 第1个字节为b’P’,第2个字节为b’2’或b’5’,第3个字节为b’\t’或b’\n’或b’\r’
ppm Portable Pixmap Files 第1个字节为b’P’,第2个字节为b’3’或b’6’,第3个字节为b’\t’或b’\n’或b’\r’
rast Sun Raster 以字节串b’\x59\xA6\x6A\x95’开头
xbm X Bitmap Files 以字节串b’#define ‘开头
bmp Bitmap,Windows标准图像文件格式 以字节串b’BM’开头
webp 谷歌的WebP格式,Python3.5加入 以字节串b’RIFF’开头并且第9到第12个字节为b’WEBP’
exr OpenEXR,Python3.5加入 以字节串b’\x76\x2f\x31\x01’开头

解决

既然知道了这个假的“jpg”实际上是“webp”图片。那么如何读取呢?
使用OpenCV读取会报错,使用PIL发现可以读取。

from PIL import Image
import matplotlib.pyplot as plt
img=Image.open('fake.jpg')
plt.imshow(img)
plt.show()

可以直接通过PIL读取后存储为真正的jpg格式图片。

from PIL import Image
img = Image.open('fake.jpg')
img.save('real.jpg')

扩展

图片格式繁多,在处理时很容易出现格式问题。怎么样才能确保出现报错前就能预知问题呢?
经过搜索,发现了一个比较好用的package——imghdr

这个包是python自带,使用方式如下:

import imghdr
imghdr.what('fake.jpg')

处理图片前判断一下格式,就能避免很多格式上的问题。
另外,python下有webp包可以加载和保存webp格式图片。

pip install webp
import webp

# Save an image
webp.save_image(img, 'image.webp', quality=80)

# Load an image
img = webp.load_image('image.webp', 'RGBA')

# Save an animation
webp.save_images(imgs, 'anim.webp', fps=10, lossless=True)

# Load an animation
imgs = webp.load_images('anim.webp', 'RGB', fps=10)

参考资料

[1] RIFF格式图片在ios浏览器中无法显示
[2] OpenCV的imread函数支持的图片格式
[3] imghdr — 推测图像类型
[4] python webp package

本文地址:https://blog.csdn.net/TracelessLe/article/details/107127516

《使用Python打开webp等格式图片.doc》

下载本文的Word格式文档,以方便收藏与打印。