Android Bitmap загружает ошибку памяти Galaxy S3 WXGA

Я был бы очень признателен, если бы кто-нибудь мог подтвердить, что я правильно решил проблему ниже или если есть альтернативное решение?

У меня есть приложение, которое загружает большое изображение (например, 800 * 1720 пикселей) в память и отображает его в scrollview. Изображение представляет собой план этажей для музея, и мне нужна простая карта, например, опыт прокрутки и масштабирования. Изображение загружено на старых устройствах, но вызвало ошибку памяти на Samsung Galaxy S3.

Глядя на сообщения LogCat, выяснилось, что при создании растрового изображения 22MB выделялось для растрового изображения вместо 800 * 1720 * 4 = 5,5 МБ. По существу, в 4 раза больше памяти выделялось по требованию других устройств и нажимало использование памяти на размер кучи размером 50 МБ.

Рекомендуемое решение этой проблемы – использовать параметр BitmapFactory.Options.inSampleSize чтобы уменьшить разрешение загруженного изображения и потребовать меньше памяти. Однако это снижает качество изображения, и я действительно хочу отобразить его в полном размере в оригинальном качестве, так как отлично работает на старых устройствах.

После большой царапины головы я пришел к выводу, что проблема заключается в том, что плотность пикселей на экранах WXGA S3 составляет 2,0 и, следовательно, для каждого пикселя на изображении, битмап фактически выделяет 4 пикселя. С небольшим количеством проб и ошибок я обнаружил, что могу предотвратить это, установив options.inScaled = false;

http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html#inScaled

По пути я также понял, что я мог бы сократить использование памяти в два раза до 2,7 МБ, используя более низкую глубину цвета в 2 пикселя вместо 4 пикселей, установив параметры. options.inPreferredConfig = Bitmap.Config.RGB_565; , Для моих напольных покрытий это не повлияло на качество видимого изображения.

Окончательный код был таким образом:

 String uri = "drawable/floorplan"; int imageResource = getResources().getIdentifier(uri, null, getPackageName()); BitmapFactory.Options options = new BitmapFactory.Options(); options.inPreferredConfig = Bitmap.Config.RGB_565; options.inScaled = false; Bitmap bm = BitmapFactory.decodeResource(getResources(), imageResource, options); IVfloorplan.setImageBitmap(bm); 

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

 float density = getResources().getDisplayMetrics().density; 

Я уменьшил использование памяти для растрового изображения с 22 МБ до 2,7 МБ, что в куче 50 МБ значительно.

Экран S3 имеет действительно высокое разрешение, так что это вполне понятно. Кроме того, если изображение находится в папке с возможностью переноса, оно может автоматически масштабироваться. Могут быть способы отключить это. Даже если ваш размер изображения не является случайным, ОС должна выделять буфер для размещения изображения, а также, возможно, один для размещения его на экране.

Альтернативой является использование черепицы, которая используется в играх типа игр SNES. Это также то, как они обрабатывали множество графических элементов без исчерпания ОЗУ. Доказательства показывают, что именно так Google Maps имеет карту планеты Земля. Вы в основном раскалываете большое изображение на плитки и показываете плитки на экране, когда вы их подвешиваете (конечно, возможно, по 1 дополнительной плитки с каждой стороны).

Несмотря на то, что это post-Honeycomb, где Google вводит код для лучшего управления распределениями Bitmap, будьте осторожны с распределением Bitmap. Это больше похоже на программу на C, чем на Java-программу, и это хорошая идея, чтобы управлять ею, как одна. При использовании объектов Bitmap в Android очень легко выходить из области кучи

Intereting Posts
Layer Layout не закрывается при нажатии (в зависимости от версии v4 lib) Как сделать мой ImageView фиксированным, независимо от размера растрового изображения Таблица с переменной шириной столбца для строки (аналогично UICollectionView для iOS) Разработка клиентских приложений REST для Android PictureCallback.onPictureTaken никогда не вызывал Как добавить строку 1dp в нижней части моей ячейки textview (а не таблицы) Android SIP с CSipSimple и pjsip Определите, будет ли просмотр списка останавливать прокрутку? Использование библиотеки picasso с изображением окружности Как использовать опцию –core-library в eclipse / Android Загружайте и запускайте apk по телефону без проводов с рабочего стола для разработки EventBus и Proguard: не удалось отправить событие Как просматривать файлы Android / data / your.package.name на внешнем хранилище в Android 4.2 с помощью многопользовательской среды? Сделайте резервную копию всего файла apk install в sdcard программно в android Диалоговое окно выбора намерений показывает имя пакета, кроме метки активности