過去3日間、Androidでビットマップをぼかすハードウェアアクセラレーションの組み込み方法を探してきました。ビットマップを縮小して再び拡大するなどの特定の回避策に出くわしましたが、この方法では画像認識要件に適さない低品質の結果が生成されました。また、シェーダーまたはJNIで畳み込みを実装するのが良い方法であることも読みましたが、この非常に一般的な目的のためのAndroidフレームワークに組み込みのソリューションがないとは信じられません。 Javaで自己記述された畳み込みの実装になりましたが、それは厄介なほど遅いです。私の質問は:
私は最終的に適切な解決策を見つけました:
ただし、ScriptIntrinsicBlur
クラスのドキュメントは非常にまれであり、正しい呼び出し引数を見つけるのにもう少し時間を費やしました。普通のARGB_8888
-photo
という名前のビットマップ。ここにあります:
final RenderScript rs = RenderScript.create( myAndroidContext );
final Allocation input = Allocation.createFromBitmap( rs, photo, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT );
final Allocation output = Allocation.createTyped( rs, input.getType() );
final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create( rs, Element.U8_4( rs ) );
script.setRadius( myBlurRadius /* e.g. 3.f */ );
script.setInput( input );
script.forEach( output );
output.copyTo( photo );
おそらく最も要求の厳しい要件はライブブラーです。つまり、ビューの変化に応じてライブブラーを行います。この状況では、滑らかに見えるためにブラーが10ミリ秒(16ミリ秒/ 60 fpsにプレイルームを持たせるため)より長くかかることはありません。それほど高くないデバイス(galaxy s3およびさらに遅い)でも、適切な設定でこの効果を実現できます。
重要度を下げてパフォーマンスを改善する方法は次のとおりです。
縮小した画像を使用する:これにより、ピクセルが大幅にぼやけて減少します。また、実際のぼやけた画像が必要な場合にも機能します。また、画像の読み込みとメモリ消費が大幅に削減されます。
Renderscript ScriptIntrinsicBlurを使用します-2014年のAndroidには、おそらくより良い/より速いソリューションはありません。 RenderScript.create(this);
はNexus 5で約20ミリ秒かかるため、これを避けたいことに注意してください。
ビットマップの再利用:不要なインスタンスを作成せず、常に同じインスタンスを使用します。非常に高速なぼかしが必要な場合、ガベージコレクションが大きな役割を果たします(一部のビットマップの収集に10〜20ミリ秒かかります)。また、必要なものだけをトリミングしてぼかします。
ライブブラーの場合、おそらくコンテキストスイッチングのため、別のスレッドで(スレッドプールを使用しても)ブラーすることはできません。メインスレッドだけが、ビューをタイムリーに更新するのに十分な速さでした。
その他のヒントについては、こちらの私の他の投稿を参照してください https://stackoverflow.com/a/23119957/774398