6.3 【JPEG6】 QT-Qではもちろん、JPEGの圧縮にQuickTimeを使っているのだが、世の中で一般的に使われているのはJPEG6(って呼んでいいのかどうかよく知らないが)という方式だ。圧縮率を同じにしても、両者の間では画像もファイルサイズも異なる。100%の場合には、単純な図形ではJPEG6の方がきれいになるが(もちろんファイルサイズは大きい)、普通の写真ではほとんど変わらない。0%では、JPEG6の方がファイルサイズはかなり小さくなるが、その分画質はかなり悪い。それから、JPEG6はプログレッシブJPEGに対応している。使う側からすると大きな違いはここくらいか。 とりあえずはQuickTimeで圧縮できるから実用上は問題ないのだけど、せっかくだからJPEG6にも対応できたらいいなと思い、info-macからコードを探してきた。IJG JPEG LIBRARYとかいうもの。IJGってのはIndependent JPEG Groupの略らしいんだけど、まだREADMEをちゃんと読んでいないのでどういう団体なのかはよく知らない(苦笑)。まずは使い方を読んで使えそうだと思ったら調べようかなと(汗)。 libjpeg.docというファイルがライブラリの実際の使い方を説明したドキュメントで、細かな使い方がいろいろと書かれている。とりあえずMacから使えるようにするには、エラー処理ルーチン、メモリ関連ルーチン、ファイル読み書きルーチンを書き換えればいいらしい。あ、あと、jconfig.hというファイルをコンパイラの設定などによって作成すると。 エラー処理は、ライブラリのデフォルトではstderrにfprintf()で書き出されるようになっているからこれを書き換える。まずは動けばいいということで、エラーの画面への出力は一切行わないことにする。また、exit()をExitToShell()に変更。 メモリ関連ルーチンは、mallocをNewPtrに、freeをDisposePtrなどに置き換えていく。実際にはテンポラリメモリを使うほうがいいので、あとで書き換えることも一応検討。 ファイル読み書きは、stdioストリームを使っていた部分をファイルリファレンスナンバで管理するようにし、読み書きのルーチンをFSWrite、FSReadに変更。だいたいこんなもんかな(ファイルを開くほうはQuickTimeにやってもらえばいいから、まずは圧縮のほうだけやってみた。よって、FSWriteしか使わなかった)。 なかなかすんなりとは動いてくれなかったが、なんとかイメージをJPEG圧縮してファイルに保存させるところまでは到達できた。ライブラリのなかの細かいことはさっぱりわからないが、外側をいじるだけならなんとかできそうな気がしてきた。 次は、ファイルに書き出さずにメモリ内で処理することを考えてみる。ドキュメントを読むと、I/O suspensionモードというのを使うとそういうことができるらしい。suspensionってのは、延期だとか停止だとかいう意味で、おそらくはファイルの読み書きをしないということだろう(そのままやん)。このモードを使うためには、さっきいじったファイル書き出しルーチンを変更してやる。 empty_output_buffer()をなにもしないでFALSEを返すだけのルーチンに書き換えるというのはすぐにわかったが、そこからが問題。要は、empty_output_buffer()が呼ばれるタイミング(バッファが一杯になったタイミング。おそらくはjpeg_write_scanlines()を呼んだあとであろう)に呼びだし元のアプリケーションに処理が戻されるから、そこでバッファに入っているデータを取り出してバッファをクリアしてやればいいのだが、いつ取り出したらいいのかがよくわからない。1ライン書き出すごとでもいいのかもしれないが、試しに書き出しに失敗した場合(書き出したライン数が1ラインでなかった場合)だけチェックするようにしてみた。と、あとはjpeg_finish_compress()のあとにも残っている分を書き出すことにして、おそらくこれで大丈夫なはず。 圧縮率の設定はjpeg_set_quality()でする。最後の引数がなんなのかよくわからないが、とりあえずTRUEにしておく。プログレッシブにするには、jpeg_simple_progression()を呼ぶと、、とやってみたが、なぜかうまく書き出せていない。なにがまずいのかよくわからないが、適当に作ったバッファチェックルーチンがいけないような気がする。あるいは他になにかを忘れているのかもしれないが、、、ファイル出力ができた段階でチェックしておくべきだったなぁ。。。 |