Python Imaging Library (PIL) で、パレット形式のPNGを扱う
PIL のパレットは色々と問題がある。256色あることしか考えてないとか。
んで、PngImagePlugin も、 PNG の "tRNS" チャンクのうちαが0のところを見つけて、そのインデックスを info['transparency'] に突っ込むだけしかしてくれない。PNGのパレット形式はパレットそれぞれにα値を設定できるのに。
まずは PNG のパレットについて復習。
PNGの中は、チャンクという要素が並んでいる。パレットは 'PLTE' というチャンクに入っている。 "RGBRGBRGB..." という感じで、3バイト×色数(256以下) だけ並んでいる。
パレット形式のPNGでも、α値を利用できる。その場合は、 'tRNS' というチャンクに "AAAA..." という感じでα値が並んでいる。最初のα値は、パレットの最初の色のα値に相当する。 tRNS のサイズは PLTE の色数以下になっていて、 tRNS の足りない部分のα値は 255 で補完される。
ということで、この2種類のチャンクを保存するように PngImagePlugin を改造してみる。
from PIL import PngImagePlugin PngStream = PngImagePlugin.PngStream class PngStreamA(PngStream): def chunk_PLTE(self, pos, len): s = PngStream.chunk_PLTE(self, pos, len) self.im_info["PNG_PLTE"] = s return s def chunk_tRNS(self, pos, len): s = PngStream.chunk_PLTE(self, pos, len) self.im_info["PNG_tRNS"] = s return s PngImagePlugin.PngStream = PngStreamA
これで、 img = Image.open('foobar.png') したあと、 img.info.get('PNG_tRNS') とか img.info.get('PNG_PLTE') とかできるようになる。