Pillow处理BMP图像抛出ValueError: unknown raw mode错误如何解决
问题现象
使用Pillow库编写图像转base64编码逻辑,用于Flask API调用,该逻辑在多数场景下运行正常,但处理某BMP文件时程序异常崩溃,无明确触发原因。
原有功能实现代码如下:
def get_img_base64(filename): # Open Image image = Image.open(filename) # Saving the format format = image.format buffered = BytesIO() image.save(buffered, format) img_str = base64.b64encode(buffered.getvalue()) return "data:image/" + format + ";base64," + img_str.decode()
报错详情
程序运行时抛出的完整错误栈如下:
Traceback (most recent call last): File "test.py", line XXX, in XXX imgBase64 = get_img_base64(path) File "test.py", line XXX, in get_img_base64 image.save(buffered, format) File "python3.10/site-packages/PIL/Image.py", line 2264, in save self._ensure_mutable() File "python3.10/site-packages/PIL/Image.py", line 626, in _ensure_mutable self._copy() File "python3.10/site-packages/PIL/Image.py", line 619, in _copy self.load() File "python3.10/site-packages/PIL/ImageFile.py", line 234, in load err_code = decoder.decode(b"")[1] File "python3.10/site-packages/PIL/BmpImagePlugin.py", line 326, in decode self.set_as_raw(bytes(data), ("P", 0, self.args[-1])) File "python3.10/site-packages/PIL/ImageFile.py", line 684, in set_as_raw d = Image._getdecoder(self.mode, "raw", (rawmode)) File "python3.10/site-packages/PIL/Image.py", line 435, in _getdecoder return decoder(mode, *args + extra) ValueError: unknown raw mode for given image mode
已尝试参考通用解决方案将图像转换为"P"模式,但转换过程中依然抛出ValueError: unknown raw mode for given image mode错误。
异常文件属性
执行exiftool -v IMG.BMP命令获取的文件元信息如下,确认该文件为8位色深、采用RLE压缩(Compression=1)的BMP格式:
ExifToolVersion = 12.40 FileName = IMG.BMP Directory = . FileSize = 44978 FileModifyDate = 1655391432 FileAccessDate = 1655391514 FileInodeChangeDate = 1655454712 FilePermissions = 33272 FileType = BMP FileTypeExtension = BMP MIMEType = image/bmp + [BinaryData directory, 40 bytes] | BMPVersion = 40 | ImageWidth = 594 | ImageHeight = 163 | Planes = 1 | BitDepth = 8 | Compression = 1 | ImageLength = 43900 | PixelsPerMeterX = 2833 | PixelsPerMeterY = 2833 | NumColors = 256 | NumImportantColors = 256
问题原因
报错根源是旧版本Pillow对采用RLE8压缩的8位BMP存在已知解码兼容bug:该异常文件是BI_RLE8压缩的8位索引色BMP,Pillow自带的BmpImagePlugin解码这类文件时,传给raw解码器的调色板模式参数不匹配,直接触发未知raw mode错误。手动转P模式无法解决问题,因为错误发生在图像加载阶段,还没等执行模式转换,解码流程就已经崩溃。
修复方案
两种方案按需选择即可:
- 方案一:直接升级Pillow到最新版本。目前新版Pillow已经修复了绝大多数RLE8压缩BMP的解码问题,执行命令
pip install --upgrade pillow完成升级后,原有代码无需修改即可正常处理这类文件。 - 方案二:如果受环境限制无法升级Pillow版本,可绕开P模式的解码逻辑,加载图像后先强制转换为RGB模式再做内存存储,转码时优先用PNG格式避免BMP编码的兼容问题,修改后的可直接复用的代码如下:
import base64 from io import BytesIO from PIL import Image def get_img_base64(filename): image = Image.open(filename) save_format = image.format # 针对RLE压缩的8位BMP做兼容处理 if image.format == "BMP" and image.mode == "P": image = image.convert("RGB") save_format = "PNG" buffered = BytesIO() image.save(buffered, save_format) img_str = base64.b64encode(buffered.getvalue()) return f"data:image/{save_format.lower()};base64,{img_str.decode()}"
注意:转RGB后如果强行保存为BMP格式,部分旧版本Pillow仍可能抛出编码错误,内存中转选择PNG格式即可,最终生成的base64不管是用于前端渲染还是接口传参,兼容性和原BMP没有差异。
内容的提问来源于stack exchange,提问作者PythonNewbie
相关产品推荐
相关产品推荐

