我尝试使用PIL将32位位图转换为32位PNG。
from PIL import Image
im = Image.open('example.bmp')
print im.mode
# it prints 'RGB', but expected was 'RGBA'
im.save('output.png', format='PNG')
预期的图像模式是'RGBA',但实际上我得到'RGB'。
我也尝试了以下代码,但它不起作用。
from PIL import Image
im = Image.open('example.bmp')
im = im.convert('RGBA')
im.save('output.png', format='PNG')
答案 0 :(得分:3)
好的,这是开始的事情。由于我不知道具体是哪种格式是您的BMP文件,我只处理了一个特定的BMP案例,其中包含我碰巧拥有的完整Alpha通道。我在这里处理的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):
# Only accept BMP v3, v4, and v5.
raise IOError("Unsupported BMP header type (%d)" % len(s))
bpp = _i16(s[14:])
if bpp != 32:
# Only accept BMP with alpha.
raise IOError("Unsupported BMP pixel depth (%d)" % bpp)
compression = _i32(s[16:])
if compression == 3:
# BI_BITFIELDS compression
mask = (_i32(self.fp.read(4)), _i32(self.fp.read(4)),
_i32(self.fp.read(4)), _i32(self.fp.read(4)))
# XXX Handle mask.
elif compression != 0:
# Only accept uncompressed BMP.
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':
# upside-down storage
self.size = self.size[0], 2**32 - self.size[1]
direction = 0
self.info["compression"] = compression
# data descriptor
self.tile = [("raw", (0, 0) + self.size, offset,
(rawmode, 0, direction))]
为了正确使用它,应该以规范的方式执行:
from PIL import Image
Image.register_open(BmpAlphaImageFile.format, BmpAlphaImageFile)
# XXX register_save
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
的代码,您会注意到我重复使用了大部分代码。
答案 1 :(得分:0)
PIL是错误的,无法使用透明的BMP文件。
如果我记得很好wxPython似乎与他们正常工作。大约一年前,我在两者之间写了一个小包装器,只有我能找到代码。
答案 2 :(得分:0)
@mmgp的代码非常适合通过Alpha加载BMP文件,但是在Python 3上需要进行两个小更改:
if s[:2] != 'BM':
成为:
if s[:2] != b'BM':
和self.size需要在使用的地方进行更改,因此代码的结尾变为:
self._size = (_i32(s[4:]), _i32(s[8:]))
direction = -1
if s[11] == '\xff':
# upside-down storage
self._size = self._size[0], 2**32 - self._size[1]
direction = 0
self.info["compression"] = compression
# data descriptor
self.tile = [("raw", (0, 0) + self._size, offset,
(rawmode, 0, direction))]
此外,有时它会失败-因为某些BMP格式不正确。您可以预先选择:
if typename != "alpha":
img = Image.open(filename)
else:
img = BmpAlphaImageFile(filename)
或使用try / catch块作为后备:
try:
img = BmpAlphaImageFile(filename)
except IOError:
img = Image.open(filename)