2012-05-04 17 views
5

Ho provato a convertire un bitmap a 32 bit in PNG a 32 bit utilizzando PIL.Carica bitmap 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') 

La modalità immagine prevista è 'RGBA', ma in realtà ottengo 'RGB'.

Ho anche provato il seguente codice, ma non funziona.

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

Penso che un file bitmap a 32 bit sia un formato non standard che PIL non supporta. Cercando di scrivere un'immagine RGBA in .bmp si produce l'errore 'impossibile scrivere modalità RGBA come BMP'. –

risposta

3

Ok, ecco qualcosa per iniziare. Dato che non conosco in modo specifico quale formato sia il tuo file BMP, ho gestito solo un caso specifico di BMP con il canale alfa completo che mi capita di avere. Il tipo di BMP che sto gestendo qui può essere ottenuto convertendo, per esempio, PNG con alpha in BMP usando ImageMagick. Questo creerà ciò che viene chiamato "BITMAPV5". Data la tua descrizione, non hai un BitmapV5 (perché PIL non riuscirebbe nemmeno ad aprirlo), quindi avremo bisogno di un'iterazione con discussioni per risolvere il tuo caso specifico.

Quindi, è necessario un nuovo decodificatore di file o un patch BmpImagePlugin.py. Come fare il primo è descritto nel manuale di PIL. Per i successivi dovrai ovviamente inviare una patch e sperare di averla nella prossima versione PIL. Il mio obiettivo è quello di creare un nuovo decoder:

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

Per utilizzare correttamente questo, il modo canonico è presumibilmente da eseguire:

from PIL import Image 
Image.register_open(BmpAlphaImageFile.format, BmpAlphaImageFile) 
# XXX register_save 

Image.register_extension(BmpAlphaImageFile.format, ".bmp") 

Il problema è che c'è già un plugin per la gestione di" .bmp ", e non mi sono preoccupato di scoprire come potrei anteporre questa nuova estensione in modo che venga utilizzata prima che BmpImagePlugin venga utilizzato (non so nemmeno se sia possibile farlo in PIL). Detto questo, Ho utilizzato il codice direttamente, come in:

from BmpAlphaImagePlugin import BmpAlphaImageFile 

x = BmpAlphaImageFile('gearscolor.bmp') 
print x.mode 
x.save('abc1.png') 

Dove gearscolor.bmp è una bitmap campione con canale full alfa come descritto in precedenza. Il png risultante viene salvato con dati alfa. Se si controlla il codice BmpImagePlugin.py, si noterà che ho riutilizzato gran parte del suo codice.

+0

Ho ricevuto un messaggio di errore "Tipo di intestazione BMP non supportato (40)" per il file bitmap – stanleyxu2005

+0

Mi aspettavo che. Puoi caricare il tuo bmp esatto da qualche parte? – mmgp

+0

Vedere il codice aggiornato, ho a malapena bisogno di cambiare nulla per gestire il formato del file. – mmgp

0

PIL è bacato e non funziona correttamente con i file BMP trasparenti.

Se ricordo bene, wxPython sembra funzionare correttamente con loro. Ho scritto un piccolo wrapper tra i due circa un anno fa, solo se riuscivo a trovare il codice.