2012-05-04 56 views
5

我試圖使用PIL將32位位圖轉換爲32位PNG。用PIL加載RGBA位圖

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

我認爲32位位圖文件是PIL不支持的非標準格式。嘗試將RGBA圖像寫入.bmp會產生錯誤「無法將模式RGBA寫入BMP」。 –

回答

3

好的,這裏有一些開始。由於我不知道具體是哪種格式的BMP文件,因此我只處理了具有完整Alpha通道的特定情況的BMP,而我恰好擁有這些通道。我在這裏處理的BMP的類型可以通過使用ImageMagick將alpha轉換爲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的代碼,你會注意到我重用了它的大部分代碼。

+0

我得到了一個錯誤「Unsupported BMP header type(40)」for my bitmap file – stanleyxu2005

+0

我期待着這一點。你能上傳你的精確bmp的地方嗎? – mmgp

+0

查看更新的代碼,我幾乎不需要改變任何東西來處理您的文件格式。 – mmgp

0

PIL有問題,無法正常使用透明BMP文件。

如果我記得不錯,wxPython似乎可以正常使用它們。一年前,我在兩者之間寫了一個小包裝,但前提是我能找到代碼。