2012-05-04 14 views
5

32ビットのビットマップをPILを使用して32ビットのPNGに変換しようとしました。RGBAビットマップを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') 

予想される画像モードは「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

[OK]をここに始めることです。あなたのBMPファイルがどのフォーマットであるか分かりませんので、完全なアルファチャンネルを持ったBMPの特定のケースしか扱っていませんでした。私がここで扱っているBMPの種類は、例えばImageMagickを使って、アルファ付き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でこのようなことができるかどうかわかりません)。

前述のようgearscolor.bmpは、完全なアルファチャネルを有するサンプルのビットマップである
from BmpAlphaImagePlugin import BmpAlphaImageFile 

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

:私は実際のように、コードを直接使用する、と述べました。結果のPNGはアルファデータと共に保存されます。 BmpImagePlugin.pyのコードをチェックすると、ほとんどのコードを再利用していることに気付くでしょう。

+0

ビットマップファイルに「サポートされていないBMPヘッダータイプ(40)」というエラーが発生しました – stanleyxu2005

+0

私はそれを期待していました。正確なbmpをどこかにアップロードできますか? – mmgp

+0

更新されたコードを参照してください。ファイル形式を処理するために何かを変更する必要はほとんどありませんでした。 – mmgp

0

PILはバグで、透過的なBMPファイルでは正しく動作しません。

私がよく覚えているのであれば、wxPythonは正しく動作するようです。私はコードを見つけることができる場合に限り、約1年前に2つの小さなラッパーを書いた。

関連する問題