Подтвердить что ты не робот

Bitmap.Config.HARDWARE vs Bitmap.Config.RGB_565

API 26 добавляет новую опцию Bitmap.Config.HARDWARE:

Специальная конфигурация, когда растровое изображение сохраняется только в графической памяти. Растровые изображения в этой конфигурации всегда неизменны. Это оптимально для случаях, когда единственной операцией с растровым изображением является рисование на экран.

Вопросы, которые не описаны в документах:

  • Если мы ВСЕГДА предпочитаем сейчас Bitmap.Config.HARDWARE over Bitmap.Config.RGB_565, когда скорость имеет первостепенное значение и качество и изменчивость не являются (например, для эскизов и т.д.)?
  • Имеются ли пиксельные данные после декодирования с использованием этой опции на самом деле НЕ потребляют ЛЮБАЯ кучную память и находятся только в памяти GPU? Если это так, это кажется для окончательного облегчения для OutOfMemoryException, когда работа с изображениями.
  • Какое качество по сравнению с RGB_565, RGBA_F16 или ARGB_8888 следует ожидать из этой опции?
  • Является ли скорость декодирования тем же/лучше/стоит по сравнению с декодирование с помощью RGB_565?
  • (Спасибо @CommonsWare за указание на него в комментариях) Что бы произойдет, если мы превысим память GPU при декодировании изображения, используя это вариант? Будет ли исключено какое-то исключение (может быть, такое же OutOfMemoryException:)?
4b9b3361

Ответ 1

Документация и открытый исходный код еще не нажаты Google git. Поэтому мои исследования основаны только на частичной информации, некоторых экспериментах и ​​на собственном опыте переноса JVM на различные устройства.

Мой тест создал большой измененный битмап и скопировал его в новый растровый рисунок HARDWARE одним нажатием кнопки, добавив его в список растровых изображений. Мне удалось создать несколько экземпляров больших растровых изображений, прежде чем он разбился.

Я смог найти это в 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);

И ища документацию AHardwareBuffer, под капотом создается EGLClientBuffer под ANativeWindowBuffer (собственный графический буфер) в общей памяти Android ( "ashmem" ). Но фактическая реализация может различаться в зависимости от оборудования.

Что касается вопросов:

  • Должны ли мы ВСЕГДА выбрать сейчас Bitmap.Config.HARDWARE через Bitmap.Config.RGB_565...?

Для конфигурации SDK >= 26, HARDWARE можно улучшить рисунок растрового изображения низкого уровня, предотвращая необходимость копирования пиксельных данных на GPU каждый раз, когда одна и та же растровая карта возвращается к экрану. Я думаю, это может предотвратить потерю некоторых кадров, когда растровое изображение добавляется на экран.

Память не учитывается в вашем приложении, и мой тест подтвердил это.

Собственная библиотека docs говорит, что она вернет null, если распределение памяти не увенчалось успехом. Без исходного кода неясно, что будет делать реализация Java (разработчики API) в этом случае - она ​​может решить бросить OutOfMemoryException или вернуться к другому типу распределения.

Обновление: Эксперимент показывает, что не выбрано исключение OutOfMemoryException. Хотя распределение успешно - все работает нормально. После неудачного выделения - эмулятор разбился (просто исчез). В других случаях у меня есть странный NullPointerException при распределении Bitmap в памяти приложения.

Из-за непредсказуемой стабильности я бы не рекомендовал использовать этот новый API в настоящее время. По крайней мере, не без тщательного тестирования.

  1. Получают ли пиксельные данные после декодирования с использованием этой опции, фактически НЕ потребляют ЛЮБАЯ кучную память и находятся только в памяти GPU? Если это так, представляется, наконец, облегчением для беспокойства OutOfMemoryException, когда работа с изображениями.

Пиксельные данные будут находиться в общей памяти (возможно, в памяти текстур), но все еще есть небольшой объект Bitmap в Java, ссылающийся на него (так что "ЛЮБОЙ" является неточным).

Каждый поставщик может решить реализовать фактическое распределение по-разному, это не публичный API, к которому они привязаны. Так что OutOfMemoryException все еще может быть проблемой. Я не уверен, как можно корректно обрабатывать.

  1. Какое качество по сравнению с RGB_565/ARGB_8888?

Флаг HARDWARE не относится к качеству, а относится к местоположению хранения пикселей. Поскольку флаги конфигурации не могут быть OR -ed, я полагаю, что для декодирования используется значение по умолчанию (ARGB_8888).

(На самом деле, перечисление HARDWARE кажется мне взломанным).

  1. Является ли скорость декодирования тем же/лучше/хуже...?
Флаг

HARDWARE кажется не связанным с декодированием, так же, как ARGB_8888.

  1. Что произойдет, если мы превысим память GPU?

Мой результат теста очень плох, когда память заканчивается. Иногда эмулятор разбивался ужасно, и в других случаях у меня был неожиданный несвязанный NPE. Отсутствие OutOfMemoryException произошло, и также не было возможности сказать, когда заканчивается память GPU, поэтому невозможно предвидеть это.