Ok, aquí hay algo para empezar. Como no sé específicamente qué formato es su archivo BMP, solo manejé un caso específico de BMP con canal alfa completo que tengo. El tipo de BMP que estoy manejando aquí se puede obtener convirtiendo, por ejemplo, PNG con alfa a BMP usando ImageMagick. Esto creará lo que se llama "BITMAPV5". Dada su descripción, no tiene un BitmapV5 (porque PIL ni siquiera podría abrirlo), por lo que necesitaremos una iteración con discusiones para resolver su caso específico.
Por lo tanto, necesita un nuevo decodificador de archivos o un parche BmpImagePlugin.py
. Cómo hacer lo anterior se describe en el manual de PIL. Para el posterior, obviamente deberá enviar un parche y esperar que llegue a la próxima versión de PIL. Mi atención se centra en la creación de un nuevo descodificador:
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))]
utilizar correctamente esto, la forma canónica es supuestamente para llevar a cabo:
from PIL import Image
Image.register_open(BmpAlphaImageFile.format, BmpAlphaImageFile)
# XXX register_save
Image.register_extension(BmpAlphaImageFile.format, ".bmp")
El problema es que ya es un plugin para el manejo de" .bmp ", y no me molesté en descubrir cómo podía anteponer esta nueva extensión, por lo que se usa antes de usar BmpImagePlugin (tampoco sé si es posible hacer algo así en PIL). Dicho esto, en realidad utilizado el código directamente, como en:
from BmpAlphaImagePlugin import BmpAlphaImageFile
x = BmpAlphaImageFile('gearscolor.bmp')
print x.mode
x.save('abc1.png')
Dónde gearscolor.bmp es un mapa de bits de la muestra con el canal alfa completo como se describió anteriormente. El png resultante se guarda con datos alfa. Si marca el código BmpImagePlugin.py
, notará que he reutilizado la mayor parte de su código.
Creo que un archivo de mapa de bits de 32 bits es un formato no estándar que PIL no admite. Intentar escribir una imagen RGBA en .bmp produce el error 'no se puede escribir el modo RGBA como BMP'. –