libjpegによるJPEG圧縮の画像データをRGB無圧縮データに展開する方法の概要について述べる。なお、実際のコード詳細については、利用しているプログラムを参照されたい。
一般にJPEG形式と呼ばれる圧縮方法は離散コサイン変換(DCT)を基本とした非可逆圧縮である。ロスレスJPEGもあるがここでは考えない。
離散コサイン変換とは、元のデータ列を関数とみなし、それを複数のcos波の合成波と考えて個々の周波数成分に変換することを示す。 この周波数成分の個々のパラメータを記録しておき、後程再度合成することによって、元の波形に近い波形を求めることができる。
元のデータ列そのものは記録しないので、圧縮→展開後は元のデータに「なんとなく特徴が似ている」ということになる。これが「自然画像に向いている」という理由となる。
JPEGではこのDCT変換だけでなく、ハフマン符号化圧縮等も利用している。
JPEGのデータ形式は公開されているが、全て最初から自力で作るのは大変。そこでIJG注1 libjpegを使う。
NetBSDやFreeBSDのpkgsrc/ports注2にも当然あり、画像を扱う非常にたくさん(ほとんどの?)プログラムが利用している。
ファイルから読み込むだけなら簡単。libjpeg.docにある通り。
標準のファイルから読み出す手段は汎用性に欠ける。
そこでjpeg_stdio_src()相当のものを作る。これはj_decompress_struct という構造体に必要な関数を登録してやればよい。
jpeg_mem_src()
マネージャ本体(入口)。関数の登録他。
init_mem_source()
初期化ルーチン(特に何もしない)
fill_input_mem_buffer()
データポインタの設定。ファイルのように途中で充填はできない。
skip_input_mem_data()
データのスキップ。ファイルでのseek相当。
term_mem_source()
終了処理。特に何もせず。
標準のエラーハンドラが用意されており、そのまま使用すれば展開中にデータ不正等を検出した場合に終了(exit)する。
しかしデータの連続展開時等にはexitして欲しくなく、呼び出し元に戻りたいこともある。そのために独自のハンドラを追加することも可能である。
cpia2viewのjpeg_decode.cを見よ
これも読みにくくてスイマセン。
注1 Independent JPEG Group
注2 graphics/jpeg
注3 コンパイルフラグで変わる。とはいえ、PPMやBMPのいわゆるベタフォーマット