- Класс BitmapFactory
- inJustDecodeBounds
- inSampleSize
- inBitmap
- inPreferredConfig
- inDensity
- inDither
- inPurgeable
- Уменьшение размера файла картинки
- Решение
- Русские Блоги
- Оптимизация растровых изображений Android-сжатие изображений
- Во-первых, причина OOM вызвана растровым изображением
- Введение в растровое изображение
- 2.1 Bitmap.Config
- 2.1.1 Настройка использования памяти разных Bitmap.Config с одинаковым разрешением
- 2.2 Bitmap.CompressFormat
- Как я ускорил обработку изображений на Android в 15 раз
- Задача
- Рисование
- AsyncTask в IntentService
- Обработка изображений
- LruCache
- Корутины
- С 9313 мс обработка уменьшилась до 596 мс
Класс BitmapFactory
Класс BitmapFactory позволяет создать объект Bitmap из файла, потока или байтового массива. Данный класс часто используется в работе с изображениями.
Класс имеет несколько методов decode* (decodeByteArray(), decodeFile(), decodeResource() и др.) для создания растрового изображения из различных источников. Не забывайте, что методы пытаются выделить память под создаваемое изображение и вы можете получить ошибку из-за нехватки памяти на устройстве. Обратите внимание, что каждый метод имеет вторую перегруженную версию с тем же именем и дополнительным параметром типа BitmapFactory.Options.
Мы можем загрузить изображение из каталога assets:
Класс BitmapFactory.Options имеет несколько полезных свойств, которые нужно использовать в своих приложениях.
- inJustDecodeBounds
- inSampleSize
- inBitmap
- inPreferredConfig
- inDensity
- inDither
- inPurgeable
inJustDecodeBounds
Используя свойство inJustDecodeBounds со значением true, вы можете избежать выделения памяти под изображение, при этом вы можете получить значения ширины (outWidth), высоты (outHeight) и MIME-типа (outMimeType). Подобный приём позволяет прочитать размеры картинки и использовать их для своих целей, сведя к минимуму потребление памяти.
Когда размеры изображения известны, вы уже можете решать — загружать ли полное изображение или сделать уменьшенную копию. Тут зависит от логики вашего приложения. Если это просмотр фотографий, то нужно следить за потреблением памяти. Если картинка загружается в маленький ImageView, то нет смысла использовать настоящее большое изображение. Когда вы определились, что делать дальше, то установите снова значение false для данного свойства.
inSampleSize
Чтобы декодер пережал картинку, установите inSampleSize в нужное значение в объекте BitmapFactory.Options. Например, если изображение с размерами 2048×1536 сжать до размеров 512×384 (в 4 раза), то изображение в памяти будет занимать 0.75мб вместо 12мб. Разница ощутима.
Ниже приводится метод для вычисления новых размеров изображения по заданными ширине и высоте, чтобы изменение размера было пропорциональным.
Чтобы использовать этот метод, сначала декодируйте изображение через inJustDecodeBounds = true, затем декодируйте снова, используя новые значения inSampleSize и inJustDecodeBounds = false:
Чтобы загрузить большое изображение в ImageView с размером 100х100 пикселей, используйте наш метод:
По такому же принципу вы можете написать сопутствующие методы для других декодирующих методов класса BitmapFactory.
Сама операция сжатия картинки очень трудоёмка и её не стоит делать в основном потоке приложения. Лучше её вынести в отдельный поток через AsyncTask.
Другие свойства используются реже. Поэтому информация только в ознакомительных целях.
inBitmap
Если передать в этот параметр объект Bitmap, то он и будет использован для получения итогового результата вместо создания нового объекта. В Android 4.4 (API 19) передаваемый Bitmap должен быть не меньше по размеру (в байтах), чем читаемое изображение. В старых версиях объект должен быть строго того же размера (ширина/высота), что и читаемое изображение. Также необходимо использовать свойство inSampleSize = 1.
inPreferredConfig
inDensity
Задаёт плотность для объекта Bitmap.
inDither
Сглаживание цветовой палитры. Где-то валялся пример. Если найду, то добавлю.
inPurgeable
При проблемах с памятью разрешаем системе временно удалить объект Bitmap. Когда потребуется вывести картинку на экран, то объект восстанавливается. Естественно, при этом падает производительность из-за повторной работы по обработке изображения.
Об остальных свойствах читайте в документации.
Источник
Уменьшение размера файла картинки
Как можно уменьшить размер файла (Картинки) ?
Например на входе картинка весит 2мб, а после «манипуляций» должно остаться 100кб..
p.s. есть ли способ при котором максимально сохраняется качество.
Уменьшение размера шрифта Textview, если не влезает по длине или высоте
TextView в режиме width=match_parent, height=match_parent, то есть растянут на весь активити. .
Уменьшение размера картинки в таблице
Меня заинтересовал вопрос —есть таблица —одно из полей картинка —OLE —при клике картинка.
Работа с таймером: уменьшение размера картинки
Картинка высотой 750 пикселей уменьшается каждые 6 секунд на 150 рх до размеров в 150 px. Двойной.
Уменьшение размера картинки под Image
Нужно сделать предпросморт в уменьшеном виде. Любая картинка должна полностью «влезть» в Image1.
Решение
Для уменьшения размера битмапа в BitmapFactory.Options есть поле inSampleSize.Пример «манипуляций» тут.
Добавлено через 4 минуты
Для сохранения сохранения битмапа в FileOutputStream используется метод битмапа compress
Уменьшение размера картинки при открытии (Image)
Приветствую! Нужна ваша помощь! При загрузке картинки использую функцию LoadFromFile. Напишите.
Изменение размера картинки (увеличение, уменьшение) — остаются белые полосы по краям
Доброго времени суток! Есть проект, необходимо открыть картинку, сделать ресайз и сохранить под.
Уменьшение размера файла на php
Для фотогалереи требуется превью картинки, то есть копия загруженного на сервер файла, только.
Уменьшение размера исполняемого файла
обычный printf занимает 30 кб после компиляции, как уменьшить размер? в настройках ничего ненашел.
Источник
Русские Блоги
Оптимизация растровых изображений Android-сжатие изображений
Оригинальный адрес: http://anany.me/2015/10/15/bitmap1/
Растровое изображение всегда было очень сложной проблемой при разработке. Это проблема легендарного OOM (переполнение памяти java.lang.OutofMemoryError). Так почему растровое изображение так теряется и раздражается многими разработчиками Android?
Во-первых, причина OOM вызвана растровым изображением
Поскольку каждая модель компилирует ПЗУ, верхний предел значения виртуальной машины в куче памяти приложения установлен на dalvik.vm.heapgrowthlimit, который используется для ограничения максимального объема памяти, доступной для каждого приложения. Если это максимальное значение будет превышено, будет сообщено о OOM. Этот порог обычно увеличивается в зависимости от размера точек на дюйм экрана мобильного телефона. Чем меньше разрешение, тем меньше максимальный объем памяти, доступный для каждого приложения. Например, в моем Z3c пороговое значение виртуальной машины xhdpi составляет 192M, но только незначительное значение 48M на hdpi для Nexus. Таким образом, когда в мероприятии загружается несколько больших изображений, легко получить OOM. Для справки о порогах памяти приложения смотрите раздел 3.7 здесь:
http://static.googleusercontent.com/media/source.android.com/en//compatibility/android-cdd.pdf
Чем выше разрешение изображения, тем выше потребление памяти.При загрузке изображений с высоким разрешением оно будет занимать много памяти и будет OOM, если с ним не будут обращаться должным образом. Например, разрешение фотографии с разрешением 500 Вт составляет 2592×1936. Если для отображения мозаики в Bitmap используется 32-битный ARGB_8888, занятая память составляет 2592x1936x4 байта, занимая почти 19 Мб памяти. Боже мой, можно загрузить менее 10 таких высококачественных фотографий, приложение будет напрямую зависать и сообщаться в OOM
Введение в растровое изображение
Чтобы работать хорошо, вы должны сначала отточить свои инструменты. Чтобы эффективно загружать Bitmap, необходимо понимать Bitmap. Bitmap имеет несколько важных переменных-членов и методов, которые представлены ниже:
2.1 Bitmap.Config
Растровая память, занятая изображением =Длина изображения x Ширина изображения x Количество байтов, занимаемых одним пикселем
Bitmap.Config — это важный параметр для указания количества байтов, занимаемых единичным пикселем.
где A — прозрачность; R — красный; G — зеленый; B — синий.
- ALPHA_8
означает 8-битное альфа-изображение, то есть A = 8, пиксель занимает 1 байт, у него нет цвета, только прозрачность - ARGB_4444
означает 16-битное растровое изображение ARGB, то есть A = 4, R = 4, G = 4, B = 4, один пиксель занимает 4 + 4 + 4 + 4 = 16 бит, 2 байтов - ARGB_8888
представляет 32-битное растровое изображение ARGB, то есть A = 8, R = 8, G = 8, B = 8, один пиксель занимает 8 + 8 + 8 + 8 = 32 бита, 4 байтов - RGB_565
означает 16-битное растровое изображение RGB, то есть R = 5, G = 6, B = 5, оно не имеет прозрачности, один пиксель занимает 5 + 6 + 5 = 16 бит, 2 слова фестиваль
Основная функция Bitmap.Config: каким образом хранится пиксель.Различные конфигурации будут влиять на качество изображения (глубину цвета) изображения. Чем больше количество бит, тем выше качество изображения. Очевидно, что ARGB_8888 занимает здесь больше всего памяти. Конечно, чем выше качество изображения, тем больше памяти требуется.
Советы: поскольку качество изображения ARGB_4444 ужасно, если для изображения не требуется прозрачность, вы можете изменить его на RGB_565, что сэкономит половину накладных расходов памяти по сравнению с ARGB_8888.
2.1.1 Настройка использования памяти разных Bitmap.Config с одинаковым разрешением
Память, занимаемая изображением Битовая карта = длина изображения x ширина изображения x количество байтов, занимаемых одним пикселем
Bitmap.Config | Объем памяти с разрешением 100×100 |
---|---|
ALPHA_8 | 100x100x1 = 10000 byte = 9.77 KB |
ARGB_4444 | 100x100x2 = 20000 byte = 19.53 kb |
ARGB_8888 | 100x100x4 = 40000 byte = 39.06 KB |
RGB_565 | 100x100x2 = 20000 byte В Android вы можете установить скорость декодирования с помощью следующего кода: 2.2 Bitmap.CompressFormatБуквально это означает:Формат сжатия растрового изображения Источник Как я ускорил обработку изображений на Android в 15 разКак оптимизировать обработку изображений в рантайме, когда необходимо создать 6 изображений, каждое из которых состоит из последовательно наложенных 15-16 PNG, не получив OutOfMemoryException по дороге? При разработке своего pet-приложения столкнулся с проблемой обработки изображений. Гугление хороших юзкейсов предоставить не смогло, поэтому пришлось ходить по своим граблям и изобретать велосипед самостоятельно. ЗадачаПриложение для занятий в тренажерном зале. Необходимо построение карты работы мышц по результатам тренировок в рантайме приложения. Каждое такое изображение состоит из 15 изображений групп мышц для вида спереди и 14 для вида сзади. Плюс по 1 изображению основы (голова, кисти рук и ступни ног). Итого, чтобы собрать вид спереди необходимо наложить 16 изображений, сзади – 15. Всего 23 группы мышц для обеих сторон (для тех, у кого 15+14 != 23, небольшое пояснение – некоторые мышцы «видны» с обеих сторон). Алгоритм наложения в первом приближении:
Для хранения 31 (16+15) изображения размером 1500х1500 px при 24-битном режиме требуется 31х1500х1500х24бит = 199 MB оперативной памяти. Примерно при превышении 30-40 МБ вы получаете OutOfMemoryException. Соотвественно, одновременно загрузить все изображения из ресурсов вы не можете, т. к. необходимо освобождать ресурсы для неполучения эксепшена. Это означает, что необходимо последовательно выполнять наложение изображений. Алгоритм трансформируется в следующий: На основе данных завершенных тренировок строится HashMap , String – мышца, Float – степень нагрузки от 0 до 10. Цикл для каждого из 6 изображений:
Задачу выполняем в отдельном потоке с помощью AsyncTask. В каждом Таске создается последовательно два изображения: вид спереди и сзади. Вспомогательный класс DoubleMusclesBitmaps нужен только для того, чтобы вернуть две переменные Bitmap-а: вид спереди и сзади. Забегая вперед Java-класс DoubleMusclesBitmaps заменяется на Pair в Kotlin-е. РисованиеЦвета colors.xml в ресурсах values. Создание одного вида Наложение одной мышцы Запускаем генерацию 3 пар изображений. Необходимо отметить, что очень много времени занимает чтение ресурсов. Для каждой пары изображений декодируется 29 PNG-файлов из ресурсов. В моем случае из общих затрат на создание изображений функция BitmapFactory.decodeResource() тратит
Плюсы: AsyncTask в IntentServiceДля ухода от AsyncTask решено было перейти на IntentServiсe, в котором выполнялось задание по созданию изображений. После завершения работы сервиса, при наличия запущенного BroadcastReceiver-а получаем Uri всех шести сгенерированных изображений, иначе просто изображения сохранялись, для того, чтобы при следующем открытии пользователем приложения не было необходимости ожидать процесс создания. Время работы при этом никак не изменилось, но с одним минусом – утечками памяти разобрались, осталось еще два минуса. Заставлять пользователей ожидать создание изображений такое количество времени, конечно же, нельзя. Нужно оптимизировать. Намечаю пути оптимизации:
Обработка изображенийВсе исходные PNG-ресурсы имеют размер 1500х1500 пх. Уменьшаем их до 1080х1080. В первом подходе перекрашивались и накладывались все 29 изображений групп мышц на основу. Основа же включала в себя только голову, кисти рук и части ног. Изменяем основу: теперь она включает в себя помимо головы, рук и ног, все остальные группы мышц. Всё красим в серый цвет color_muscle0. Это позволит не перекрашивать и не накладывать те группы мышцы, которые не были задействованы. Теперь все исходники выглядят так: LruCacheПосле дополнительной обработке исходных изображений, некоторые стали занимать немного памяти, что привело к мысли о переиспользовании (не освобождать их после каждого наложения методом .recycle() ) с помощью LruCache. Создаем класс для хранения исходных изображений, который одновременно берет на себя функцию чтения из ресурсов: Изображения подготовлены, декодирование ресурсов оптимизировано. КорутиныКод с использованием IntentService работает, но читаемость кода с колбэками не назовешь приятной. Добавим желание посмотреть на корутины Котлина в работе. Добавим понимание того, что через пару месяцев читать свой синхронный код будет приятнее, чем поиск места возврата Uri файлов сгенерированных изображений. Также ускорение обработки изображений натолкнуло на мысль использовать фичу в нескольких новых местах приложения, в частности в описании упражнений, а не только после тренировки. Стандартная связка errorHandler, job и scope – скоуп корутин с хендлером ошибок, если корутина сломается. uries – HashMap, который хранит в себе 6 изображений для последующего вывода в UI: Замеряем время обработки. С 9313 мс обработка уменьшилась до 596 мсЕсли есть идеи по дополнительной оптимизации – велком в комментарии. Источник |