写真を加工する 5.6 高度なフィルタの実装と高速化(備忘録)
#wp7dev_jp
これまで、様々な画像フィルタを作ってきて、それを組み合わせてフィルタ効果を実装した。
例えば上記の効果を作るために、フィルタ処理を重ねて実装している。ここでは、レベル補正と→単色乗算→トーンカーブをかけている。
int[] tmp;
uint color = 0xfff6ddad;
float[] tc = ToneCurve.getcurve(0, 39, 75, 70, 167, 203, 255, 255);
tmp = Level.effect(src, w, h, 0, 0, 128);
tmp = SolidColorMix.effect(tmp, color, w, h);
tmp = ToneCurve.effect(tmp, w, h, tc, null, null, null);
return tmp;
ま、Photoshop の処理をプログラムで実現しているわけで、パラメータを変化させればいろいろな効果を生み出せる。
が、気が付いた。実装にはこんなことをやる必要はない。だって、Photoshop を作るわけではないんだから。
高速化
上のフィルタは、所詮完成品。アプリの中でパラメーターを変えることはしない。だったらもっとシンプルになりそう。
色の入力は所詮 RとGとBの3色で、それぞれ 0~255の256段階しかない。 フィルタをかければ、その色が変わっていくだけ。
例 R=30 → レベル補正 → 142 → 乗算 → 96 → トーンカーブ → 80
間はいろいろあるが、結局まとめると、こうなるだけだ。このパターンを 256 色分x3色分用意すればいい。
例 R=30 → 処理 → 80
こうすれば、あとは変換1回で処理が終わる。 ということで上記の処理はこうなってしまった。
int[] tmp;
int[] TR = new int[] { 39, 39, 39, 39, 39, 39, 39, 39, ... 251, 252, 252 };
int[] TG = new int[] { 39, 39, 39, 39, 39, 39, 39, 39, ... 242, 243, 243 };
int[] TB = new int[] { 82, 82, 82, 83, 83, 85, 85, 85, ... 208, 208, 209 };
tmp = Convert.effect(src, TR, TG, TB);
return tmp;
画像処理の高速化のコツ
これはそんなに難しくない。
- 計算を減らす
- 浮動小数点計算よりも整数型の計算にする
- 掛け算よりもビット処理
例えば、30%の濃さにする場合、RGBx0.3 でどうしても浮動小数点演算になりそうになる。
→ 計算時に 1000倍くらいして、整数にして、最後にまた1/1000にする。これで結構十分。
更に、その掛け算割り算もビット処理で行う。
→ 1000倍ではなく1024倍にする。そして終わったら1024で割る。
→ 1024 の割り算掛け算は 10ビットの移動処理でできるので、高速化が見込める。
- (int)((float)a x 0.3) → ((int)a x 307) >> 10 ;
どのくらい高速化するのか?
これまで、全店に対して、フィルタ1回ずつ、場合によっては浮動小数点演算を行ってきた。このフィルタの場合、約0.3-0.4秒かかっていた。
これが高速化処理によって、整数型の変換テーブルで変換するだけなので、結果として処理時間は 約 0.02秒となった。約1/20秒の短縮化である。
デメリットはある。
- あとから処理を微調整できない
- そもそもフィルタ処理から変換テーブルを作るのが面倒
そんなわけで、フィルタ処理から変換テーブルを作るための、別のアプリを作らないとだめそう。ま、仕方がない。
全てにおいて有効か?
単純にこれでできないものもある。1:1の関係にならないもの。
- 例えば、白黒化は RGBの3色を必要とするので、テーブルにすると 256x256x256 のサイズになる。これは計算のほうが早い。
- そしてぼかし処理。これは、1点を決めるのに周りの点の情報が必要となるので、どうにもならない。
特にぼかし処理は時間がかかる(2,3秒)ので、読み込み時に作っちゃいます。ボタンを押してから2,3秒は待てないけどファイル読み込み時のどさくさに紛れて2,3秒は結構許されるんですよね。
関連リンク
- 写真を加工する 5.5 横スクロールするボタンメニュー
- 写真を加工する 5.4 写真を100年前へ
- 写真を加工する 5.3 各種フィルタ2
- 写真を加工する 5.2 各エフェクト
- 写真を加工する 5.1.2 ぼかしクラス追加
- 写真を加工する Part5.1.1 オーバーレイクラス化
- 写真を加工する Part5.1 オーバーレイ
- 写真をぼかす 改め加工する Part 5 レイヤー合成
- 写真をぼかす Part.4.1 マスク画像を使わずに周辺だけをぼかす。
- 写真をぼかす Part.4 マスクを使って周辺だけをぼかす。
- 写真をぼかす Part 3.1 いったん整理
- 写真にぼかしを Part 3 ガウスぼかし
- 写真にぼかしを Part2
- 写真にぼかしを
- 写真をセピアに