Python PNG画像を自力で出力する その2



今回は、
・IDAT 画像データ本体 分割することも可能だが、面倒なので1つで。
・IEND ファイルの末端であることを明示
この部分を考えます。

色の指定は、
・左上から右下へ
・グレースケールのピクセルは0が黒、ビット深度の最大値が白
・スキャンライン(列)の始まりにはフィルター情報を1バイト付加する

ここでちょっとはまったのですが・・・

作成したい画像の一番上の列を考えると、
□□□□□□□□

まず、フィルタ情報
0x00


その後、白が8ピクセル続きます。ビットの深さはIHDRで1を指定したので、
1が白となります。
0と1しか情報が無いので、2進数で考えると一列目は
11111111

16進数に変換し
0xFF


あわせて
0x00 0xFF

で表現することができます

同様に
■■■■■■■■

この列は
フィルタ情報
0x00

2進数表記
00000000

16進数表記
0x00


この一列の表現は
0x00 0x00

となります。


□□□□□□□□
□□□□□□□□
□□□□□□□□
□□□□□□□□
■■■■■■■■
■■■■■■■■
■■■■■■■■
■■■■■■■■


こんな画像を作りたいので、全体像は
白列4、黒列4で

0x00 0xFF
0x00 0xFF
0x00 0xFF
0x00 0xFF
0x00 0x00
0x00 0x00
0x00 0x00
0x00 0x00

となることが分かります。


さあ、これでデータが作成できるかというと
そう簡単ではなく、上記データをzip圧縮してやります。

私はこんなコードで作成しました。


import binascii,zlib
import struct

target = (chr(0x00)+chr(0xFF)+chr(0x00)+chr(0xFF)+
chr(0x00)+chr(0xFF)+chr(0x00)+chr(0xFF)+chr(0x00)+
chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+
chr(0x00)+chr(0x00))

lines = zlib.compress(target)
for line in lines:
  print '%x' % ord(line),



結果は
0x78 0x9C 0x63 0xF8 0xCF 0x00 0x81
0x50 0x00 0x00 0x2F 0xE0 0x03 0xFD



その1のロジックを使用してCRCを求めます。
0x66 0xF4 0x5D 0x26



まとめると

【チャンクの長さ】
・長さ
0x00 0x00 0x00 0x0E


【チャンク形式】
・チャンク形式 IDATの文字コードを16進数に変換
0x49 0x44 0x41 0x54


【チャンクデータ本体】
0x78 0x9C 0x63 0xF8 0xCF 0x00 0x81
0x50 0x00 0x00 0x2F 0xE0 0x03 0xFD



【CRC32の結果】
0x66 0xF4 0x5D 0x26




最後に、IENDチャンクです。
これは、IENDというチャンク形式を指定すればよく、
下記の記載で固定です。

【チャンクの長さ】
・長さ
0x00 0x00 0x00 0x00


【チャンク形式】
・チャンク形式 IENDの文字コードを16進数に変換
0x49 0x45 0x4E 0x44


【チャンクデータ本体】
(なし)


【CRC32の結果】
0xAE 0x42 0x60 0x82



次回は、バイナリエディタでファイルを作ってみます。



【参考URL】
PNG (Portable Network Graphics) Specification, Version 1.2
http://www.sutv.zaq.ne.jp/linuz/tks/PngSpec1.2/PNG-Contents.html

PNGについて
http://homepage2.nifty.com/sophia0/png.html


もどる