2012-05-04 21 views
5

Intenté convertir un mapa de bits de 32 bits a PNG de 32 bits utilizando PIL.Cargar mapa de bits RGBA con PIL

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') 

El modo de imagen esperado es 'RGBA', pero en realidad obtengo 'RGB'.

También probé el siguiente código, pero no funciona.

from PIL import Image 
im = Image.open('example.bmp') 
im = im.convert('RGBA') 
im.save('output.png', format='PNG') 
+1

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'. –

Respuesta

3

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.

+0

Recibí un error "Tipo de encabezado BMP no compatible (40)" para mi archivo de mapa de bits – stanleyxu2005

+0

. Lo esperaba. ¿Puedes subir tu bmp exacto en alguna parte? – mmgp

+0

Vea el código actualizado, apenas necesitaba cambiar nada para manejar su formato de archivo. – mmgp

0

PIL tiene errores y no funciona correctamente con archivos BMP transparentes.

Si recuerdo bien, parece que wxPython funciona correctamente con ellos. Escribí un pequeño borrador entre los dos hace un año, solo si podía encontrar el código.

Cuestiones relacionadas