web-dev-qa-db-ja.com

Android:高速ビットマップぼかし?

過去3日間、Androidでビットマップをぼかすハードウェアアクセラレーションの組み込み方法を探してきました。ビットマップを縮小して再び拡大するなどの特定の回避策に出くわしましたが、この方法では画像認識要件に適さない低品質の結果が生成されました。また、シェーダーまたはJNIで畳み込みを実装するのが良い方法であることも読みましたが、この非常に一般的な目的のためのAndroidフレームワークに組み込みのソリューションがないとは信じられません。 Javaで自己記述された畳み込みの実装になりましたが、それは厄介なほど遅いです。私の質問は:

  • 組み込みソリューションはありません Android framework?
  • 何もない場合:実装と保守の合理的な複雑さで畳み込みを加速する最も効率的な方法は何ですか? JNI、シェーダー、またはまったく異なるものを使用しますか?
32
theV0ID

私は最終的に適切な解決策を見つけました:

  • RenderScript を使用すると、実行中のデバイスで使用可能なすべてのコアに透過的にスケーリングされる重い計算を実装できます。パフォーマンスと実装の複雑さの合理的なバランスに関して、これはJNIやシェーダーよりも優れたアプローチであるという結論に達しました。
  • APIレベル17以降、APIから利用可能な ScriptIntrinsicBlur クラスがあります。これはまさに私が探していたもの、すなわち、高レベルのハードウェアアクセラレーションガウスぼかしの実装です。
  • ScriptIntrinsicBlur は、Froyo以上(API> 8)をサポートするAndroidサポートライブラリ(v8)の一部になりました。Android RenderScriptライブラリのサポートに関する開発者ブログ投稿 には、使用方法に関する基本的なヒントがあります。

ただし、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 );
70
theV0ID

おそらく最も要求の厳しい要件はライブブラーです。つまり、ビューの変化に応じてライブブラーを行います。この状況では、滑らかに見えるためにブラーが10ミリ秒(16ミリ秒/ 60 fpsにプレイルームを持たせるため)より長くかかることはありません。それほど高くないデバイス(galaxy s3およびさらに遅い)でも、適切な設定でこの効果を実現できます。

重要度を下げてパフォーマンスを改善する方法は次のとおりです。

  1. 縮小した画像を使用する:これにより、ピクセルが大幅にぼやけて減少します。また、実際のぼやけた画像が必要な場合にも機能します。また、画像の読み込みとメモリ消費が大幅に削減されます。

  2. Renderscript ScriptIntrinsicBlurを使用します-2014年のAndroidには、おそらくより良い/より速いソリューションはありません。 RenderScript.create(this);はNexus 5で約20ミリ秒かかるため、これを避けたいことに注意してください。

  3. ビットマップの再利用:不要なインスタンスを作成せず、常に同じインスタンスを使用します。非常に高速なぼかしが必要な場合、ガベージコレクションが大きな役割を果たします(一部のビットマップの収集に10〜20ミリ秒かかります)。また、必要なものだけをトリミングしてぼかします。

  4. ライブブラーの場合、おそらくコンテキストスイッチングのため、別のスレッドで(スレッドプールを使用しても)ブラーすることはできません。メインスレッドだけが、ビューをタイムリーに更新するのに十分な速さでした。

その他のヒントについては、こちらの私の他の投稿を参照してください https://stackoverflow.com/a/23119957/774398

ところで。このアプリで簡単なライブブラーを行いました: githubPlaystore

12
patrickf