API 26 新しいオプションを追加Bitmap.Config.HARDWARE
:
ビットマップがグラフィックメモリにのみ保存される場合の特別な構成。この構成のビットマップは常に不変です。ビットマップを使用する唯一の操作が画面に描画することである場合に最適です。
ドキュメントで説明されていない質問:
Bitmap.Config.HARDWARE
over Bitmap.Config.RGB_565
速度が最優先であり、品質と可変性がそうでない場合(例:サムネイルなど)?OutOfMemoryException
の懸念を軽減するようです。OutOfMemoryException
:)?ドキュメントと公開ソースコードはまだ 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
を作成しています。ただし、実際の実装はハードウェアによって異なる場合があります。
質問に関して:
- Bitmap.Config.RGB_565よりもBitmap.Config.HARDWAREを常に好むべきでしょうか...?
SDK> = 26の場合、HARDWARE
構成により、同じビットマップが画面に戻るたびにピクセルデータをGPUにコピーする必要がなくなるため、低レベルのビットマップ描画が改善されます。ビットマップが画面に追加されたときにいくつかのフレームが失われるのを防ぐことができると思います。
メモリはアプリに対してカウントされず、私のテストではこれが確認されました。
ネイティブライブラリのドキュメントによると、メモリの割り当てが失敗した場合はnull
が返されます。この場合、ソースコードがないとJava実装(API実装者)が何を行うかが明確ではありません。異なるタイプの割り当てにOutOfMemoryException
またはフォールバックをスローすることを決定する場合があります。
更新:実験により、OutOfMemoryExceptionがスローされないことが明らかになりました。割り当てが成功している間-すべてが正常に動作します。割り当てに失敗すると-エミュレータがクラッシュしました(消えてしまいました)。他の機会に、アプリのメモリにビットマップを割り当てるときに、奇妙なNullPointerException
が発生します。
予測不可能な安定性のため、現在、本番環境でこの新しいAPIを使用することはお勧めしません。少なくとも広範なテストなしではありません。
- このオプションを使用してデコードした後のピクセルデータは、実際にはヒープメモリを消費せず、GPUメモリのみに存在しますか?もしそうなら、これは最終的に画像を扱う際の
OutOfMemoryException
の懸念を軽減するようです。
ピクセルデータは共有メモリ(おそらくテクスチャメモリ)にありますが、それを参照するJavaには小さなBitmap
オブジェクトがまだあります(したがって、「ANY」は不正確です)。
すべてのベンダーは、実際の割り当てを異なる方法で実装することを決定できます。これは、バインドされているパブリックAPIではありません。したがって、OutOfMemoryException
は依然として問題になる可能性があります。どのように正しく処理できるかわかりません。
- RGB_565/ARGB_8888と比較してどのような品質ですか?
HARDWARE
フラグは品質に関するものではなく、ピクセルの保存場所に関するものです。構成フラグをOR
- edにすることはできないため、デコードにはデフォルト(ARGB_8888
)が使用されると思います。
(実際、HARDWARE
enumは私にとってはハックのようです)。
- デコード自体の速度は同じ/より良い/悪いですか?
HARDWARE
フラグはデコードとは無関係であるように見えるため、ARGB_8888
と同じです。
- GPUメモリを超えるとどうなりますか?
私のテストでは、メモリが不足すると非常に悪い結果になります。エミュレータが時々ひどくクラッシュし、他の機会に予期しない無関係なNPEが発生しました。 OutOfMemoryExceptionは発生せず、GPUメモリが不足していることを通知する方法もなかったため、これを予測する方法はありませんでした。