日記

日々のことと、Python/Django/PHP/Laravel/nodejs などソフトウェア開発のことを書き綴ります

GIFをSWFのDefineBitsLossless2に変換するコードが無かったから書いたった。

PHPのコードばかりで、あれだったのでPythonで書いたった!

Gitにしようかと思ったけど、Macbook Airmac portsなど入れていなかったから、はてな日記にぺたぺた。

xml2swfで出力したXMLに埋め込む前提なので、SWF内のタグ定義とかヘッダーは、バッファに書き込みしてないので注意。

GIFのカラーパレットは取れたんだけど、PILでrasterbitsのパレットインデックスを取る方法が分からず、Color MapのインデックスをRGBAをキーにしたハッシュでインデックスを持って、rasterbitsはRGBAにしてインデックスを探す変なコードになってます。えろい人がフォローしてくれるかなw

(9/3 透過GIFのときにうまく処理ができていなかったので、カラーマップを抽出してインデックスを作るところを修正してます。)

#vim:fileencoding=utf-8
import Image, zlib, base64

from struct import *
from StringIO import StringIO

source_img = 'source.gif'
output = 'datafile'
output_b64 = 'datafile_b64'
output_ext = 'datafile_ext'

def to_index_rgb(r, g, b, a):
   return str(r).zfill(3) + str(g).zfill(3) + str(b).zfill(3) + str(a).zfill(3)

def main():
   """
   GIF -> DefineBitsLossless2に変換する処理
   カラーマップテーブルを必要な分だけにしているので、
   swftoolsで GIF -> SWFで変換したときよりも、データサイズが減ります。
   """
   img = Image.open(source_img)
   xy = img.size
   width, height = xy

   img = img.convert('RGBA')
   colormap = img.getcolors()
   colormap_num = len(colormap)
   temp_bf = StringIO()
   colormap_index = {}

   for i in range(colormap_num):
       bit_count, rgba = colormap[i]
       red, green, blue, alpha = rgba
       #print red, green, blue, alpha
       if alpha == 0:
           red = 0
           green = 0
           blue = 0
           alpha = 0

       temp_bf.write(chr(red))
       temp_bf.write(chr(green))
       temp_bf.write(chr(blue))
       temp_bf.write(chr(alpha))
       idx_string = to_index_rgb(red, green, blue, alpha)
       colormap_index[idx_string] = i

   indices = StringIO()
   ix = 0
   for y in range(height):
       for x in range(width):
           red, green, blue, alpha = img.getpixel((x,y))
           if alpha == 0:
               red   = 0
               green = 0
               blue  = 0
           idx_string = to_index_rgb(red, green, blue, alpha)
           temp_bf.write(chr(colormap_index.get(idx_string)))
           ix += 1
       while ((ix % 4) != 0):
           temp_bf.write(chr(0))
           ix += 1
   temp_bf.seek(0)

   # 圧縮前のバイナリデータ書き込み
   out_file = open(output_ext, 'wb')
   out_file.write(temp_bf.read())
   out_file.close()
   temp_bf.seek(0)

   # コンテンツ部分をZLIB圧縮
   content_bf = StringIO()
   content_bf.write(zlib.compress(temp_bf.read()))
   content_bf.seek(0)

   # ZLIB圧縮したバイナリデータを書き込み
   out_file = open(output, 'wb')
   out_file.write(content_bf.read())
   out_file.close()
   content_bf.seek(0)

   # ZLIB圧縮したバイナリデータをBase64エンコードして書き込み(swfmillのXMLに埋め込む形式)
   out_file = open(output_b64, 'wb')
   out_file.write(base64.standard_b64encode(content_bf.read()))
   out_file.close()

   # データの他にXMLに埋め込む必要があるのは
   # colormap_num, width, height, content_bf.read()
   print colormap_num, width, height

if __name__ == '__main__':
   main()


参考にしたサイトなど