好的,让我们开始吧。由于我不知道你的BMP文件的具体格式是什么,所以我只处理了一个我恰巧拥有的带有完整Alpha通道的BMP特定情况。我在这里处理的BMP类型可以通过使用ImageMagick将具有Alpha通道的PNG转换为BMP而获得。这将创建所谓的“BITMAPV5”。根据您的描述,您没有BitmapV5(因为PIL甚至无法打开它),因此我们需要进行讨论的迭代来解决您的特定情况。
因此,您需要一个新的文件解码器或已修补的BmpImagePlugin.py
。如何执行前者在PIL的手册中有描述。对于后者,您显然需要发送一个补丁,并希望将其纳入下一个PIL版本。我专注于创建一个新的解码器:
from PIL import ImageFile, BmpImagePlugin
_i16, _i32 = BmpImagePlugin.i16, BmpImagePlugin.i32
class BmpAlphaImageFile(ImageFile.ImageFile):
format = "BMP+Alpha"
format_description = "BMP with full alpha channel"
def _open(self):
s = self.fp.read(14)
if s[:2] != 'BM':
raise SyntaxError("Not a BMP file")
offset = _i32(s[10:])
self._read_bitmap(offset)
def _read_bitmap(self, offset):
s = self.fp.read(4)
s += ImageFile._safe_read(self.fp, _i32(s) - 4)
if len(s) not in (40, 108, 124):
raise IOError("Unsupported BMP header type (%d)" % len(s))
bpp = _i16(s[14:])
if bpp != 32:
raise IOError("Unsupported BMP pixel depth (%d)" % bpp)
compression = _i32(s[16:])
if compression == 3:
mask = (_i32(self.fp.read(4)), _i32(self.fp.read(4)),
_i32(self.fp.read(4)), _i32(self.fp.read(4)))
elif compression != 0:
raise IOError("Unsupported BMP compression (%d)" % compression)
self.mode, rawmode = 'RGBA', 'BGRA'
self.size = (_i32(s[4:]), _i32(s[8:]))
direction = -1
if s[11] == '\xff':
self.size = self.size[0], 2**32 - self.size[1]
direction = 0
self.info["compression"] = compression
self.tile = [("raw", (0, 0) + self.size, offset,
(rawmode, 0, direction))]
要正确使用它,据说规范的方法是执行以下操作:
from PIL import Image
Image.register_open(BmpAlphaImageFile.format, BmpAlphaImageFile)
Image.register_extension(BmpAlphaImageFile.format, ".bmp")
问题在于已经有一个处理".bmp"的插件了,而我没有找到如何在BmpImagePlugin被使用之前将这个新扩展名添加到插件中(我也不知道在PIL中是否可能这样做)。话虽如此,我实际上直接使用了以下代码:
from BmpAlphaImagePlugin import BmpAlphaImageFile
x = BmpAlphaImageFile('gearscolor.bmp')
print x.mode
x.save('abc1.png')
其中 gearscolor.bmp 是一个具有完整 alpha 通道的示例位图,如前所述。生成的 png 文件将保存 alpha 数据。如果您检查 BmpImagePlugin.py
的代码,您会注意到我重用了它的大部分代码。