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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 05:27:21