Zlib.dll? Zlib.NET? DeflateStream?

| トラックバック(0)

ZIP ファイルで馴染みのある「Zlib」。.NET からのアプローチは zlib.dll を直接扱うかマネージコード用の zlib.net を使うか。J# のライブラリという手もあるが今回はパス。もうひとつ気になるクラスが、.NET Framework 2.0 で追加された IO.Compression名前空間にある DeflateStream。はてさて、これらの互換性はあるのかな?

実験してみたところ、Zlib.dll と Zlib.net はさすが本家同士だけあって互換性は大丈夫。

問題の DeflateStream は全く互換性がない。同じ圧縮アルゴリズム (Deflate) を使っているのになぜ互換性がないのだろうか・・・。

 

いろいろ調べてみたら、実装している RFC が違うっぽい。

Zlib.dll と Zlib.net は RFC1950、DeflateStream は RFC 1951 で、バイナリレベルでの互換性はないのだそうな・・・。

 

さて、私は今のところ ZIP ファイルの圧縮と展開には興味ない。むしろ、自作 PNG に興味がある。.NET からでも標準で PNG の出力はサポートされているがすべてのフォーマットがサポートされているわけではない。また、チャンクを自在にいじりながら PNG を作るとなると、 IDATA チャンク(つまり、画像データを圧縮したデータ)は自前で用意しなければならない。DeflateStream が使えればよかったのだがこれが使えない。IDATA チャンクの圧縮は RFC1950 でなければならないから・・・。(´・ω・`) ショボーン

 

と、言うわけで PNG を作るなら Zlib.dll か Zlib.net で、ということになる。マネージコード Only で行くなら Zlib.net で決まり。ただ、本家 DLL のほうがネイティブだから速度は速いだろうなぁ・・・。C みたいに lib ファイルの埋め込みが出来るようになればいいんだけどな・・・。

 

■2009/11/09 加筆

Zlib.dll および Zlib.net で生成した圧縮データには、2バイトの圧縮データのためのヘッダが付加される。DeflateStream で伸張ができなかったのはこのためで、圧縮データからヘッダを取り除けば問題なく伸張できた。しかし、この逆「DeflateStreamで圧縮し、Zlib.dllで伸張」はいまだにうまくいかない。ZlibのヘッダファイルにはRFC1950~1952までの記述があるようなので、たぶんできると思うのだけど・・・。

ということで継続調査中。。。

 

■2013/09/06 加筆

DeflateStreamで圧縮したデータを Zlib.net で伸張することに成功。上記の加筆にあるように、Zlib.net での出力には2バイトのヘッダがあるが DeflateStream にはヘッダがつかない。なので、DeflateStream で圧縮したデータの先頭に Zlib のヘッダを付加してみた。

本来、ヘッダは圧縮の方法によって変化するものだが、現在の仕様ではヘッダが「 0x78 0xDA 」でほとんど固定される。また、このデータは伸張には使われないようなので、付加しても問題ない(はず)。

以前にも、この方法は試してみたのだけれど、うまく読み込みが出来なかった。その後、詳しく調べてみたところ、Zlib.net の読み込み用ストリームにバグ(というかStreamReaderとの相性問題)がありうまく読めなかったようです。また、Zlib のソースコードには、Deflate/Inflateの初期化メソッドで指定するビット数を負数にすると、ヘッダの無いデータを扱うようにコーディングされていたことも分かりました。

と、いうことで最初のエントリーから4年近くが経ちましたが、結論は「DeflateStream と Zlib」にはちゃんと互換性があります。ただし、ヘッダの付加・非付加によって読み込めない場合があるので注意が必要です。

トラックバック(0)

トラックバックURL: http://wiz.came.ac/mt/mt-tb.cgi/12