MGLで画像処理?
注意)主題は、MGL2で画像処理やろうぜ ではなく、
え? MGL2で画像処理やるの? ってことです。そのへん誤解のなきよう...
MGL の 色表現は HSBもどきで しかも 12bit しかない。
- モバギII ぐらいの処理能力のマシンに合わせて なおかつ 2bpp,4bpp なマシン
でも (一応)おなじアプリケーションを動かせる。
という前提なんで こうなっちゃったのだが...
mghana
とか
mglvns
とか
表現力が重要なものでは やっぱり情報量が足りないんだろうか ... なんて
思ってしまう。
- brightness = 15 のときに表現できる全色(左) と brightness = 5 のときに
表現できる全色(右)
..
これみるとなんとなく分かると思うけれども、
色空間は 12bitあるけども 表現できる色はそれ以下。
- 色調(Hue) は 4bit 使っているのに 12 段階しかない。
もとが連続値とは思えないぐらい離れている。
- 色彩(Saturation) は、最大値が 明度(Brightness) なんで、暗くなるほど
解像度がさがる。( ここが モドキという 理由で 本当の HSB は 割合 )
- 計算してみると 4096色の空間に対し 1456 色しか有効でないのだ。
こうなったのは、Hue が 12 の分解能で
しか 作れなかったというのが大きかったりするんで なかなか拡張は難しい
んだけれども、一応 (はるかなる将来の)拡張案。
MGL では 色は 32bit の空間が一応ある。下 15bit 使ってしまっている
ので、拡張は (たぶん) 上 16bit に対し 15bit かなぁ
1 5 5 5 4 4 4 4
|R| H(4-0) | S(4-0) | B(4-0) | OP | H(8-5) | S(8-5) | B(8-5) |
予約 H下位 S下位 B下位 H上位 S上位 B上位
こんな風にしちゃったら どおかなとは思うんだけれども、演算する人におこられて
しまうかなぁ。
そもそも 高速な HSB 変換コードが作れなければ どうにもならないんで
はるかなる将来の拡張案としか 書けない。
まあ 1bitづつ 拡張する場合もこのフォーマットに従えばいいから、
5 + 5 + 5 というパターンもありえるんだけども... それでも 高速な 24 色の
Hue 変換が.. ネック。高速がネックというのもあるけど 24 に場合わけしないと
いけないから コード作るのがとっても面倒。
もしそれができたとしても 32bpp draw engine は
ひどいから たぶん 16bpp native draw engine を作ることになるんだろう。
これ 32K エントリぐらいのテーブル必要になったりもするし、
やっぱり はるかなる将来? 2MB ぐらいのキャッシュが モバギで
あたりまえになったころ... 7-8 年もたてばそうなるかも知れないから
予断は許さない。とはいえそのころの 5bit HSB は いまの 4bit HSB より
価値低いって気もする。
あとは、packRGB とかのマクロも 32bit 版 つくらないといけない.. か。
- くわがたさんからコメント頂きました。はっきり言って 人の顔とかに等高線が入る(= グラデーションがむちゃくちゃ弱い)のは しまった!つう感じ。brightness だけでもあと 1bit あれば
良かったのか...
- MGL の設計しているときに、いろいろチェックしたのだけれども
アニメ風の絵 とか 油絵風の絵とか ばかり 見て 自己満足してしまったというのが
敗因かも。人の顔写真って 全然だめじゃんと気が付いたのがかなり後。
といっても 最初から気が付いていてもうまくやれたかというと疑問。
システム全体のバランスがあるんで うまく直すのはかなり難しく、
作る気をなくすというパターンさえあったかも。
ひとつ思いつきました。下位ドライバ(現在の実装だと fb16.h) で
スムージング処理をするとか...
たとえば、
- MGL の色表現で 明るさが 1 階調の差しかない場合は 中間値 を FB に いれる
とか。これだと あんまりうれしくないかも知れない。もう少し場合わけして、
- ... 1 1 2 2 ... のパターンでは..
- そうではなく ... 1 2 ... となった場合は
とか。
遅くなるのは確実ですが、どれぐらい遅くなるのか見積もってやって 影響が
小さそうなら採用する。ダメなら見送り。
実は本題は 上のような話じゃなくて HSB そのものは 画像処理 したとき
困ったりするんだろうか .. とか そういう話 。私よくわかりませんので
だれか教えて!
- S とか B は 加減乗除 がきくのはわかるけれども H はどうなの ?
とか
- HSB だと嬉しい 処理ってないの? とか。
S とか B は 加減乗除 がきくのはわかるけれども H はどうなの ?
という話。
よくわからんが 自分なりに 考えてみる...
- Hue(H) ってのは、角度だから 2 つの色の 合成は可能
1 と 11 の中間値は 0 なのだが、単純に 足して 1/2 にすると 6 になって
しまう。演算する場合は注意が必要。
あと Saturation(S) を 考慮した合成しないといけない。
Saturation(S) が 0 の場合は、色情報を持っていないわけだから、
Hue(H) がいくつであっても 関係ない。たぶん Saturation(S) でおもみづけして
やれば良いのだろう。ただし、Brightness(B) が 0 のときはやっぱり
色情報を持っていない。
Saturation(S) は % で表示された値でなくて 絶対値? が必要なのだが..
MGL の Saturation(S) は、精度の問題で Brightness(B) をかけてあるので、
絶対値..のはずでそのまま使えばよいはず。
というわけで、独立に合成してもダメで Saturation(S) も考慮しないといけない。
- では色調変換はどうなの。
たとえば 青のフィルターをかけるとか.. これって、青の要素はそのまま通すけども
他の色は 減ってしまうってことだよなぁ。原理的には RGB に変換して
フィルター処理をして 元に戻すってのが正しい?
いやいや... 単に青を足しても同じ効果になるはず。
この場合足す色の Brightness(B)
は もとのいろのBrightness(B) と同じか それに比例した値で、Satiation は、
100 % (MGL では = Brightness(B))
うーん。なんかできそうな気がしてきた。
HSB だと嬉しい 処理ってないの?
上の話を書いてみて思ったけれども、HSB って単に直観的な もので、演算量と
して 嬉しい話はないかも知れない。
だんだん セピア色になっていく エフェクトみたいなのがあったら楽だと
おもっていたんだけれども、上の処理を考えると、別に楽ってわけじゃなさそう。
げ、mghanaで
mglsvrが70%ですか
基本的に mglsvr 側の処理が重いってことですね。
- あ、訂正が.. つうことは エフェクト時 mglsvr が 30% ぐらいか?
このレベルだとしても client/server 合わせて 70% ぐらい 行ってるかも。
- そう言えば... refresh() と get_key()/key_select() の使い分けについて...
MGLAPI.doc には、できるかぎりget_key()/key_select() にして欲しいと書いて
ありますが、これは 長時間 get_key()/key_select() で いろんな裏の
イベント処理をやるためなんで、ある頻度(目安としては、1/3 秒ぐらい?)
以上でget_key()/key_select() を呼んでもらえるならば、
refresh() を その間にいくら いれてもらっても
構わないです。 ちなみに update は 変更があった 点を含む最小の矩形領域
を 再描画するので、どの タイミングで refresh() を呼ぶかで、mglsvr に
描画させる量が変わってきます。
MGLは遅い?で見積もったけれども、かなり速い シグマリオンで
mglsvr 使わなくても 320x240 で 13.4 fps ぐらいしか出ない。
mglsvr 使うとどうかというと もうちょっと落ちる(はず)。
というわけで 15fps とか 20fps 狙うのは 現状ではかなり厳しい..
どころか不可能のような気がします。10 fps 出すのが 精いっぱい?
mghana で実際はどれぐらい出ているんだろうか... かなり気になります。
あと、client 側と server側は非同期で動くので、client 側から見たfps と
実際の fps とは差が出てくるかも。
それはともかく、MGL が 倍速いとできることが違ってくるとかいう感じですね。
いますぐ対処するのは とっても厳しいですが キモに命じておきます。
(ちなみに 倍速くできるとは思っていないです。狙うのは 5割 up ぐらい。
最高にうまくいって 7割 upか)
ディザについて
MGL2でディザがかかっているか確認したい という話が...
- 16bpp なドローエンジンつかっている限り ディザは絶対かからないんですが...
R500 を除くカラーな モバギII は かならず 16bpp かというと
そうとは限らなかったりします。
たしか 256 色にも設定できたはずで、そのときは 256 色にもできたり
します。 この場合は pbsdboot での ブートメニューも 違うエントリを
使ったはずなんで、普通は 16bppのはず。
- では 256 色のモードで どういう風にディザがかかるか...
これは、環境変数 MGL_MAXCOLOR を 192に設定すれば X で ディザがかかった
画像が見れるはず。(ちなみに 4 とか 16 にすると 2bpp 4bpp な画像も確認
できます)
あと、get_pixstream で 16bpp なスクリーンから取ってきた
データには、COLOR_DITHER の bit が立つので、それを put_pixstream すれば
明示的に指定しなくとも ディザが かかかります。
- ディザをかけないようにするには... COLOR_DITHER の bit を落せば良い
わけですが...
それ以外に 16 階調のうち 下位2bit が 0 の 4 つのデータは
ディザと無関係になる(= ベタ塗りになる)ようにしています。
要するに 2bpp 用に 自分でディザかけた場合は、2bpp のデータしか作らない
だろう... そういうときは COLOR_DITHER の bit の有無は関係せず
表示したい画像がちゃんと出るはずだ.. と考えました。
まあ、COLOR_DITHER の bit を落しておく方が性能的に有利なのは確かなんですが
... そういうときは、put_pixstream に渡すデータの先頭 1bit だけ落しておく
という技があったりします。(最適化の都合で 先頭しか見ていない。)
- MGL2 でディザなんてサポートせずにフレームレート上げて欲しいっつう
話も何回か 聞いたんですが...
- 基本的に 性能を上げたいときは put_pixstream を使うはず。
- put_pixstream 使ったときに ディザの有無をチェックするために
1 回 if 文が入るだけなら 性能には影響しない。
...ということで 本質的な 問題ではないと思っています。
なんで頑固に ディザいれているかというと..16bpp 専用のコード 書く人は
たぶん 8bpp(256 色)とか 2bppの見栄えを構うだけの 余裕がないだろうと
いう気がしたから。... 高度なディザを自分でいれるような.. 使わないマシンのため
のコードは なかなか書けないっす。
ところで、くわがたさんの 誤差拡散ディザいいですね。等高線がきれいに消えて
いる。mil に いれたいなぁ ..といってみるテスト。
- おお mgterm壁紙
パッチにディザが入った! 。 あとは mil に組み込むだけ... 折をみて 組み込みます
です。
- そういえば.. mgl X 版だと フィルターかけて 青っぽくしています。
これをはずすには、config.mk の DULL_DISPLAY=y を コメントにします。
あと、実機でも ちょっとだけフィルターが... lib/fb16.h みて頂けるとわかると
思いますが... 色の再現性をみてやるときには これらをいじってやるほうが
良いかも。
---
mc_from_rgb()が少しおかしいのではという話が...
うーん。だいたいは合っていると思うけども..
自信はないっす。いちど確かめないといけないですね。
おお、15度ずれている
ってことですか。確かにそのとおりだなぁ。どうやって直そう...
あと、性能について の 話ですが、いまは、疑似フレームに書いて そこから
本当のフレームバッファにコピーする構造なわけです。で
- 疑似フレームに書くこと自体
- 本当のフレームバッファにコピーすること自体
が ボトルネックになっているはず。結局 frame buffer を アプリに開放
するのがベストとわかっているわけで、それをするのかなぁ なんて思っています。
で、これをするためには、いまの疑似フレームバッファ版 から 共有フレームバッファ
版(shared_fb版) にしないといけない。そうすれば、fb に書けばそれが
他の層で上書きされることがなくなる。
その上で、frame buffer のアクセス方法をアプリに知らせられば 良いのかなぁ
なんて思っています。
(最終更新 Thu Mar 30 18:51:39 2006)