web-dev-qa-db-ja.com

Bitmap.Config.HARDWAREとBitmap.Config.RGB_565

API 26 新しいオプションを追加Bitmap.Config.HARDWARE

ビットマップがグラフィックメモリにのみ保存される場合の特別な構成。この構成のビットマップは常に不変です。ビットマップを使用する唯一の操作が画面に描画することである場合に最適です。

ドキュメントで説明されていない質問:

  1. 私たちは常に今すぐに_Bitmap.Config.HARDWARE over Bitmap.Config.RGB_565速度が最優先であり、品質と可変性がそうでない場合(例:サムネイルなど)?
  2. このオプションを使用してデコードした後のピクセルデータは、実際にはヒープメモリを消費せず、GPUメモリのみに存在しますか?もしそうなら、これは最終的に画像を扱う際のOutOfMemoryExceptionの懸念を軽減するようです。
  3. このオプションから、RGB_565、RGBA_F16、またはARGB_8888と比較してどのような品質が期待できますか?
  4. decodingの速度自体は、RGB_565でのデコードと比較して同じ/より良い/価値がありますか?
  5. (コメントで指定してくれた@CommonsWareに感謝します)このオプションを使用して画像をデコードするときにGPUメモリを超えるとどうなりますか?いくつかの例外がスローされますか(おそらく同じOutOfMemoryException :)?
31

ドキュメントと公開ソースコードはまだ Googleのgit にプッシュされていません。したがって、私の研究は、部分的な情報、いくつかの実験、およびJVMをさまざまなデバイスに移植した経験に基づいています。

私のテストでは、大きな可変ビットマップを作成し、ボタンをクリックして新しいハードウェアビットマップにコピーし、ビットマップリストに追加しました。クラッシュする前に、大きなビットマップのインスタンスをいくつか作成できました。

Android-o-preview-4 git Pushでこれを見つけることができました:

+struct AHardwareBuffer;
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLClientBuffer eglGetNativeClientBufferANDROID (const struct AHardwareBuffer *buffer);
+#else
+typedef EGLClientBuffer (EGLAPIENTRYP PFNEGLGETNATIVECLIENTBUFFERANDROID) (const struct AHardwareBuffer *buffer);

そして、A-HardwareBufferの ドキュメントを探して 、内部でAndroid共有メモリ( "ashmem")内の EGLClientBuffer (ネイティブグラフィックバッファー)に裏打ちされたANativeWindowBufferを作成しています。ただし、実際の実装はハードウェアによって異なる場合があります。

質問に関して:

  1. Bitmap.Config.RGB_565よりもBitmap.Config.HARDWAREを常に好むべきでしょうか...?

SDK> = 26の場合、HARDWARE構成により、同じビットマップが画面に戻るたびにピクセルデータをGPUにコピーする必要がなくなるため、低レベルのビットマップ描画が改善されます。ビットマップが画面に追加されたときにいくつかのフレームが失われるのを防ぐことができると思います。

メモリはアプリに対してカウントされず、私のテストではこれが確認されました。

ネイティブライブラリのドキュメントによると、メモリの割り当てが失敗した場合はnullが返されます。この場合、ソースコードがないとJava実装(API実装者)が何を行うかが明確ではありません。異なるタイプの割り当てにOutOfMemoryExceptionまたはフォールバックをスローすることを決定する場合があります。

更新:実験により、OutOfMemoryExceptionがスローされないことが明らかになりました。割り当てが成功している間-すべてが正常に動作します。割り当てに失敗すると-エミュレータがクラッシュしました(消えてしまいました)。他の機会に、アプリのメモリにビットマップを割り当てるときに、奇妙なNullPointerExceptionが発生します。

予測不可能な安定性のため、現在、本番環境でこの新しいAPIを使用することはお勧めしません。少なくとも広範なテストなしではありません。

  1. このオプションを使用してデコードした後のピクセルデータは、実際にはヒープメモリを消費せず、GPUメモリのみに存在しますか?もしそうなら、これは最終的に画像を扱う際のOutOfMemoryExceptionの懸念を軽減するようです。

ピクセルデータは共有メモリ(おそらくテクスチャメモリ)にありますが、それを参照するJavaには小さなBitmapオブジェクトがまだあります(したがって、「ANY」は不正確です)。

すべてのベンダーは、実際の割り当てを異なる方法で実装することを決定できます。これは、バインドされているパブリックAPIではありません。したがって、OutOfMemoryExceptionは依然として問題になる可能性があります。どのように正しく処理できるかわかりません。

  1. RGB_565/ARGB_8888と比較してどのような品質ですか?

HARDWAREフラグは品質に関するものではなく、ピクセルの保存場所に関するものです。構成フラグをOR- edにすることはできないため、デコードにはデフォルト(ARGB_8888)が使用されると思います。

(実際、HARDWARE enumは私にとってはハックのようです)。

  1. デコード自体の速度は同じ/より良い/悪いですか?

HARDWAREフラグはデコードとは無関係であるように見えるため、ARGB_8888と同じです。

  1. GPUメモリを超えるとどうなりますか?

私のテストでは、メモリが不足すると非常に悪い結果になります。エミュレータが時々ひどくクラッシュし、他の機会に予期しない無関係なNPEが発生しました。 OutOfMemoryExceptionは発生せず、GPUメモリが不足していることを通知する方法もなかったため、これを予測する方法はありませんでした。

12
Amir Uval