« JPEG の赤のブロックノイズとぼやけ | メイン | 本体側の画像キャッシュとの連携を考える »

2008年05月10日

吉里吉里 ムービー拡張日誌2:: 静止画アルファ付きJPEGプラグインが動くように

    

静止画アルファ付きJPEGプラグインが動くようになり、アルファが入ったJPEGを読み込んで綺麗に抜けることが確認できた。
なお、このプラグインではアルファのない通常のJPEGファイルも読み込めるようになっている。
そこで、本体と読込み速度を比較してみた。

比較環境のマシンの CPU は Core2Duo E6750 となっている。
SIMD 拡張版 IJG JPEG library を用いているので、現状本体の読込み速度と最も差が大きくなる環境となる。
もう少し古い CPU では、差は縮まるはず。

まず、通常の JPEG ファイルの読込み。
普通に読み込むとコンソールに読込み時間が何ミリ秒か出るのでそれで比較した。
また、ディスクキャッシュなどの影響も考え、複数回起動し読込み速度が落ち着いた値を元に比較している。
それで、読込み時間は 2倍より少し速い程度になった。

アルファ付きの方は TLG5 と比較した。
すると、ほぼ同等か少し速いぐらいになった。

速い。
これは、SIMD 拡張版 IJG JPEG library によるものと、デコード後の RGB24 から RGB32 への変換を省いていることによる。
たぶん、SIMD 拡張版 IJG JPEG library の影響がかなり大きいと思う。
デコード後の変換は、吉里吉里2本体では一度テンポラリに展開後、変換しつつレイヤーのバッファへ書き込んでいる。
対して、このプラグインでは IJG JPEG library のデバッグオプションによって、最初から RGB32 で出力されるようにし、レイヤーのバッファへ直接デコード結果を書き込むようにしている。
アルファを混ぜるコードは、現状普通に書いているが、ここを SIMD 化すれば更なる高速化が期待できる。

他に画質に関するオプションも本体のものとは異なっている。
本体では以下の3つの内いずれかかを指定可能で、デフォルトでは normal となっている。
1. low はIDCTに固定小数点(整数)ANN、色差拡大補間なし。
2. normal はIDCTに固定小数点(整数)ANN、色差拡大補間あり。
3. high はIDCTに浮動小数点AAN、色差拡大補間あり。

このプラグインでは、IDCTに固定小数点(整数)LLM、色差拡大補間あり としている。
IDCTの固定小数点ANNアルゴリズムは、高速だけど比較的誤差の大きいアルゴリズムだと言われている。
普段吉里吉里2を使用していて特に大きく劣化しているとは感じないが、時々掲示板などで特定の画像でJPEGが汚いと指摘されていることがある。
その場合オプションで high を指定して回避すると良いと言う話だ。
また、過去に ANN は誤差が大きいから使えないというのを見たことがある ( 確か MPEG 関係で調べていた時 ) 。
まあ、普段の感覚からすると大体は問題ないけど、時々汚いと言う感じだろうか。
( JPEG が苦手なものだったり、圧縮率が高い場合に影響が大きい可能性もある )

それと、 IJG JPEG library では、IDCTに固定小数点(整数)LLM、色差拡大補間あり がデフォルトで推奨設定となっている。
そのため、このライブラリを用いて作られているアプリの多くはこの設定になっていると思われる。
このため他で表示したら綺麗なのに吉里吉里2で見たら汚いと言うのは、このプラグインでは回避できるのではないかと思われる。

なお、AAN と LLM の速度差は SIMD 化されているものではそれほどない。
そもそも、SIMD 化されたものでは、IDCT 自体の処理時間が全体的に見て少ないようだ。
これは IDCT の処理時間はほぼ純粋に計算にかかる時間で、最近の CPU では速度が出やすいものだからだと思われる。
対して、ハフマンデコードやビット単位での読込みは遅いと思われる。

以上のような理由から、IDCTに固定小数点(整数)LLM、色差拡大補間あり を使うのが良いと思われ、今回はそうした。

ただ、最近のいくつかのエントリーで書いたように色差拡大補間ありが常に良いかというと、これは検討の余地がある。
色差拡大補間ありでは、鮮やかさが落ちる場合があるからだ。
ただし、なしの場合にはブロックノイズのようなものが見えることもあるので、全体的に綺麗に見えるということであれば、色差拡大補間ありの方が良いと思う。
まあ、鮮やかさが落ちる前の画像を見てなかったらわからないと言えばわからないし。

今回、loadAlphaJpegImage という名前で Layer クラスにメソッドを追加したのだが、この場合ひとつ難点がある。
それは、本体とは別機構で読み込むため、本体のキャッシュ機能が効かないということ。
このためスキップ処理時に少し速度的にペナルティがある。
同じ画像 2 枚を交互に読んでいたりすると速度差はだいぶ大きいと考えられる。
スキップ処理を最速で早送りではなく、本当にジャンプするようなシステムにしているのなら問題はない。
とは言っても、私はそんなことしていないので、キャッシュが効くように出来ればそれに越したことはない。
で、気付いたが、本体のLayer.loadImages をプラグインでオーバーライドしてしまえばいいのではないかと思った。
て、待てよ…… キャッシュのチェックなどは本体の Layer.loadImages 内でやってる気がするから意味なしか?
マスクや領域画像のことを考えて、せっかくだから吉里吉里3のより高速化された TLG の読み込みとかもついでに移植するかーと思ったけど、キャッシュが意味なくなるのはなぁ……

すぐに思いつく方法は以下の3つ
1. 本体にこの機能を入れてしまう
2. 本体に画像読込み専用のプラグイン機構を入れる
3. キャッシュは諦める

3 が楽。1 は bcc でコンパイル出来るようにしないといけないので面倒。
後、遅くなる気がする。
出来るのなら 2 がいいかなぁ。
krmovie.dll のように krimage.dll とかあってそれで拡張とか……
ただまあ、組み込み方は相談しないことには始まらないか。
一度、キャッシュ周りの処理を見てみよう。



投稿者 Takenori : 2008年05月10日 15:26




comments powered by Disqus
Total : Today : Yesterday : なかのひと