とりあえずminizip入れてみたけど、minizipのソース見たらわざわざライブラリとしてリンクするまでも無いほど、zipアーカイブのフォーマットって意外に単純なのね...
というわけで、minizipは止めて0から起こすことにした。(もちろん参考にはするけど)
zipファイルフォーマット超簡略版
local file header | 4 | シグニチャ | 0x04034b50 |
2 | バージョン | ||
2 | フラグ | ||
2 | 圧縮方式 | ※非圧縮の場合は0 | |
2 | 最終更新時刻 | ||
2 | 最終更新日付 | ||
4 | CRC32 | ||
4 | 圧縮サイズ | (a) | |
4 | 元サイズ | ※非圧縮の場合は(a)と同じ | |
2 | ファイル名長 | (b) | |
2 | 追加領域長 | (c) | |
任意(b) | ファイル名 | (b)で指定されたバイト数 | |
任意(c) | 追加領域 | (c)で指定されたバイト数 | |
file data | 任意(a) | 圧縮データ | ※非圧縮の場合は生データ |
data descriptor | 4 | シグニチャ | 0x08074b50 |
4 | CRC32 | ||
4 | 圧縮サイズ | ||
4 | 元サイズ |
data descriptorは、フラグのbit3が1の時のみ存在する(通常は存在しない)。
圧縮環境がシーク不可能なデバイス(標準出力など)の場合に、local file header内のCRC32、圧縮サイズ、元サイズを書き換えられないのでこの情報を出力する。
zipファイルは、上記構造を1ファイル単位として、これがファイル先頭から順番に連なった構造をしている。ファイルの最後にディレクトリ情報などが保存されるが、カタログブラウザでは無視して差し支えなかろう。0x04034b50以外のシグニチャをリードしたらそこで処理を打ち止めにすればよい。
非圧縮であることを前提にすれば(CD-ROMデータ仕様ではそうなっているから前提にして問題ないはずだが)、file data部分には生データがそのままごっそり入っている。カタログブラウザの用途では処理を簡略化するとしたら、ファイル名と、file data部分へのファイルポインタ、圧縮サイズ(非圧縮なので元サイズに等しいはず)だけ取り出してデータベース化しておけば、毎回zipフォーマットを解析しないで直ファイルポインタに飛んで、直データを取出すだけで済む。
libpngの場合はPNGを展開する際にデータフィード関数を自分で与える必要があるので、libpngから渡されたバッファに直接この直データをReadFileするようバイパス処理をするだけだ。
あとはCDATAのページ番号、カット番号からページ画像を構成するだけ…のはずだが、細かい点では考えることが多い。というか与えられてない変数が多すぎ。
・ページ余白情報がないので、自分でサイズを決めないといけない。
・ページ上部のテキストの表示位置、フォント、サイズ等。
・従来と画像の解像度が異なる。(従来: 178x255、新(低): 105x150、新(高): 210x300)
・ブロックヘッダの扱い(01スペースの直前2カット分の位置に配置すればいい?)
・事故SPの扱い(事故SPってカット画像は存在するけど情報あるの?)
とりあえず、*.cczを走査してサークルID、ファイルポインタ、ファイルサイズをデータベースに突っ込むコードを書いてみたが…超遅い。3万件超のサイズをシークしてるわけだからある程度がまんするしかないかもだけど…。一回メモリに全部落としてからまとめてDB書込みした方がいいのかもしれない。