Android max image size

Android – Уменьшить размер файла изображения

У меня есть файл изображения URI, и я хочу уменьшить его размер, чтобы загрузить его. Начальный размер файла изображения зависит от мобильного телефона (может быть 2 МБ, а может быть 500 КБ), но я хочу, чтобы конечный размер составлял около 200 КБ, чтобы я мог его загрузить.
Из того, что я прочитал, у меня есть (по крайней мере) 2 варианта:

  • Использование BitmapFactory.Options.inSampleSize , чтобы подвыбрать исходное изображение и получить меньшее изображение;
  • Использование Bitmap.compress для сжатия изображения, определяющего качество сжатия.

Какой лучший выбор?

Я думал, что сначала изменит размер / высоту изображения, пока ширина или высота не превысят 1000 пикселей (что-то вроде 1024×768 или других), а затем сжимайте изображение с уменьшением качества, пока размер файла не станет выше 200 КБ. Вот пример:

Есть ли лучший способ сделать это? Должен ли я стараться использовать все 2 метода или только один? благодаря

Используя Bitmap.compress() вы просто указываете алгоритм сжатия и, кстати, операция сжатия занимает довольно большое количество времени. Если вам нужно играть с размерами, чтобы уменьшить выделение памяти для вашего изображения, вам нужно использовать масштабирование изображения с помощью Bitmap.Options , Bitmap.Options вычисляя границы растровых изображений, а затем декодируя его до указанного размера.

Лучшим образцом, который я нашел в StackOverflow, является этот .

Большинство ответов, которые я нашел, были просто частями, которые мне пришлось собрать, чтобы получить рабочий код, который размещен ниже

2 параметра sampleSize и качество играют важную роль

SampleSize используется для подвыборки исходного изображения и возврата меньшего изображения , т.е.
SampleSize == 4 возвращает изображение, которое составляет 1/4 ширины / высоты оригинала.

Качество используется для подсказки компрессора , диапазон ввода составляет от 0 до 100. 0 означает компресс для малого размера, 100 означает компресс для максимального качества

Источник

How to find the max image size supported for contacts images?

background

starting with jelly bean (4.1), android now supports contact images that are 720×720 .

before, starting with ICS (4.0), android has supported contact images that are 256×256.

and before that, contact photos had just a size of a thumbnail — 96×96

the question

is there any function in the API that returns the max size of the contact image?

i also hope that the manufacturers didn’t change the max image sizes, and even if they did and we have such a function, it would return us the correct size.

Answers

according to this link, the correct way to get the max size is:

EDIT: if we use at least API 16 (4.1), it’s possible to use something like:

All you need for gif enc/dec you will find here 3MF Project GIF

GCT

this block is optional and not always present in a GIF file. Size is determined by number of colors and bit wide from GIF header. I decode/load it like this:

  • if _gcolor_table is true then GCT is present
  • GCT size is 3*gcolors [Bytes] stored in order R,G,B

Start of Image

This one is a bit tricky because GIF89a files may contain many optional blocks. You need to do a decoding loop detecting type of block and decoding/skipping it according its purpose. I do it like this:

  • db is BYTE variable
  • dw is WORD variable
  • f is my file cache class the members are self explanatory I hope anyway:
  • f.read(&data,size) read size BYTES into data
  • f.peek(&data,size) do the same but do not update position in file
  • f.eof indicates end of file reached

this has to be done for each frame after all this image header starts.

End of Image

Image block ends with terminator. All the chunks of image start with BYTE count. If it is zero it is a terminator block. Usually after the image there are few BYTES not used by LZW data so after you fill the whole image area skip all blocks until hit the zero sized block and then stop that is image end. If BYTE after this is 0x3B hex you reached the end of GIF file

Читайте также:  Андроид yt9216bj не работает камера заднего вида

[notes]

Do not forget to encapsulate struct by #pragma pack(1) and #pragma pack() or manually set align to 1 BYTE . Beware problems with signed data types (LZW data is unsigned) so overtype where you can to avoid problems or use just unsigned variables (with enough bit-width) for decoding

Источник

Полный список

— читаем и отображаем большие изображения

Когда мы читаем изображение с SD-карты в Bitmap, оно в памяти занимает значительно больше, чем размер файла на SD. Потому что на диске оно хранится в сжатом JPG или PNG формате. А мы при чтении его распаковываем и получаем полновесный Bitmap.

Для примера возьмем изображение размером 5712х2986. Нам необходимо отобразить его в приложении.

Project name: P1601_BitmapLarge
Build Target: Android 4.4
Application name: BitmapLarge
Package name: ru.startandroid.develop.p1601bitmaplarge
Create Activity: MainActivity

На экране только ImageView размером в 300dp

Метод readImage – читает Bitmap из файла и отображает его в ImageView.

Метод logMemory показывает сколько КБ памяти занимает наше приложение. Будем вызывать этот метод до и после отображения, чтобы увидеть сколько памяти заняла картинка.

В папку Download на вашем девайсе или эмуляторе закиньте файл map.jpg.

Total memory = 3184
bitmap size = 5712×2986, byteCount = 66625
Total memory = 69832

Впечатляет! Наше изображение заняло в памяти 66 мегабайт! Т.е. чтобы на экране отобразить изображение размером 300dp, мы держим в памяти изображение размером 5712х2986 и весит оно 66 мегабайт. Крайне неудачная реализация. А уж если придется выводить на экран несколько таких картинок, то OutOfMemory нам не избежать.

Надо картинку срочно уменьшать до необходимых нам размеров. Какие тут есть варианты?

Можно, например, ее читать так же, как мы это делаем сейчас, а перед тем, как помещать ее в ImageView, вызывать метод createScaledBitmap (Урок 158), чтобы привести к нужному размеру. В принципе, конечно, получится то, что надо. Но все равно в какой-то момент приложение займет в памяти эти 66 метров, чтобы получить оригинальную картинку. А значит, мы все равно можем словить OutOfMemory, если у нас с памятью напряги.

Тут нам помогут два параметра BitmapFactory.Options:

inJustDecodeBounds – поможет нам узнать размер изображения, не занимая память

inSampleSize – при чтении изображения уменьшит его размер в требуемое кол-во раз, и на выходе мы получим уже уменьшенную копию, что значительно сэкономит нам память. Этот коэффициент должен быть кратным двум.

Подробнее про эти параметры можно прочесть в Уроке 159.

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

Хелп гугла любезно предоставляет нам готовые методы с реализацией этого алгоритма.

Скопируем их оттуда в MainActivity.java, немного изменив, чтобы они читали файл не из ресурсов, а с SD:

В методе decodeSampledBitmapFromResource мы просто читаем изображение с включенным inJustDecodeBounds. Тем самым, в options помещаются данные о размере изображения, но само изображение не читается. Собственно, тут-то мы и экономим 66 метров. Далее объект options с данными о размере изображения мы передаем в метод calculateInSampleSize. А также передаем туда ширину и высоту изображения, которые нам нужно получить на выходе. Метод calculateInSampleSize вычисляет (и помещает в inSampleSize) коэффициент уменьшения изображения. Далее мы отключаем inJustDecodeBounds и получаем bitmap, который будет уменьшен до необходимых нам размеров.

Метод calculateInSampleSize на вход получает объект options, который содержит данные о реальном размере изображения. Также на вход идут reqWidth и reqHeight, в которые мы передаем желаемые нам размеры изображения.

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

Читайте также:  Скрытые фишки ватсап андроид

Либо можно трактовать логику чуть по-другому. Цикл находит нам коэффициент, использование которого даст нам размер, который вместится в требуемый. А мы потом этот коэффициент откатываем на шаг назад, чтобы получить размер, который будет чуть больше требуемого.

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

Получить точно требуемые нам размеры мы не сможем, т.к. коэффициент должен быть кратным двум.

Перепишем метод readImage с использованием этих методов:

Запускаем, смотрим лог:

Total memory = 3204
Required size = 600, bitmap size = 1428×747, byteCount = 4166
Total memory = 7412

Стало значительно лучше. С учетом density наш ImageView имеет размер 600 px. И при чтении изображения был учтен этот размер. Теперь в памяти изображение размером 1428х747 и весом в 4 мегабайта. Это вполне приемлемый результат.

Кстати, если не очень понятен алгоритм метода calculateInSampleSize, то возьмите реальные цифры и попробуйте сами на бумажке по шагам все посчитать. Исходный размер был 5712х2986, а требуемый размер – 600х600.

Итак, мы получили 4 мегабайта вместо 66. Но этот результат можно еще немного улучшить. Нашему изображению не нужна прозрачность. Поэтому мы можем использовать RGB_565 конфигурацию вместо дефолтовой ARGB_8888. Это уменьшит вес bitmap еще в два раза (Урок 157).

В метод decodeSampledBitmapFromResource добавим перед return следующую строку:

Запускаем, смотрим лог:

Total memory = 3172
Required size = 600, bitmap size = 1428×747, byteCount = 2083
Total memory = 5296

Стало еще лучше, всего 2 мегабайта вместо 66, а результат визуально тот же самый.

В принципе, можно еще и createScaledBitmap применить, чтобы получить уж совсем необходимый вам размер. Это может еще раза в два снизить вес Bitmap.

Если мы теперь, например, уменьшим размер ImageView до 100 dp, то получим такие данные в логе:

Total memory = 3176
Required size = 200, bitmap size = 714×374, byteCount = 521
Total memory = 3740

Изображение весит уже пол-мегабайта всего, а размер = 714х374.

И напоследок пара важных замечаний.

Обратите внимание на разницу во времени логов, которые у нас получались в приложении. Видно, что декодирование изображения может занять от нескольких сотен мсек. до нескольких секунд. Это слишком большая длительность для выполнения операции в основном потоке. Если на экран требуется выводить несколько таких картинок, то задержка UI будет весьма ощутима. Поэтому декодирование рекомендуется проводить в отдельном потоке. AsyncTask (Урок 86) и AsyncTaskLoader (Урок 135) вам в помощь.

На следующем уроке:

— используем memory-кэш
— используем библиотеку Picasso

Присоединяйтесь к нам в Telegram:

— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование

— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня

— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме

Источник

Адаптивные изображения. Что использовать: img или picture?

Теги img и picture предназначены для загрузки изображений. Каждый из них позволяет задать набор правил, согласно которым браузер будет выбирать, какое из изображений загружать. Рассмотрим синтаксис и различия данных тегов. Для начала нужно задать следующий метатег:

Данный метатег указывает браузеру выполнять масштабирование размеров экрана устройства. Так, например, размеры экрана iPhone X составляют 375×812 css-пикселей.

Для тестирования будем использовать следующее изображение:

Медведи

Тег img

Атрибут srcset предназначен для указания всех доступных размеров изображений и URL каждого из них. При этом, тег src указывать нужно. Его значение будет использовано, если все варианты из srcset не подойдут согласно указанным правилам.

Атрибут srcset содержит список из одной или нескольких строк, разделённых запятыми, указывающих набор источников изображения. Каждая строка состоит из:

Читайте также:  Ram or processor android

Рассмотрим на примере:

Ширина всех доступных изображений указывается в пикселях. По историческим причинам для обозначения пикселей используется символ w . В данном примере атрибут srcset содержит три изображения, ширина которых 480, 960 и 1920 пикселей соответственно. Браузер выберет изображение в зависимости от ширины экрана устройтва и его плотности пикселей. Если ширина экрана не превышает 480 css-пикселей, то будет выбрано следующее изображение:

bears-480×270.jpg , если коэфициент плотности пикселей равен 1.

bears-960×540.jpg , если коэфициент плотности пикселей равен 2 (retina display).

bears-1920×1080.jpg , если коэфициент плотности пикселей больше 2.

Аналогично, если ширина экрана больше 480 css-пикселей, но не превышает 960 css-пикселей, то:

bears-960×540.jpg , если коэфициент плотности пикселей равен 1.

bears-1920×1080.jpg , если коэфициент плотности пикселей больше или равен 2.

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

Рассмотрим на примере:

В данном примере браузер будет следовать следующим правилам при выборе источника изображения:

Если ширина экрана устройства составляет не более 600 css-пикселей, то изображение на таком экране занимает максимум 480 css-пикселей в ширину.

Если ширина экрана устройства составляет от 600 до 1200 css-пикселей, то изображение на таком экране занимает максимум 960 css-пикселей в ширину.

В противном случае браузер будет подразумевать, что изображение может занимает всю ширину экрана.

Также нужно учитывать коэфициент плотности пикселей. Например, если ширина экрана устройства составляет 550 css-пикселей, то браузер выберет следующее изображение:

bears-480×270.jpg , если коэфициент плотности пикселей равен 1. Так как ширина экрана устройства не превышает 600 css-пикселей, то изображение на таком экране занимает максимум 480 css-пикселей в ширину.

bears-960×540.jpg , если коэфициент плотности пикселей равен 2.

bears-1920×1080.jpg , если коэфициент плотности пикселей больше 2.

Атрибут sizes нужно указывать, если размеры изображения ограничены css стилями. Если атрибут sizes не указан, то по умолчанию он будет иметь значение 100vw (sizes=»100vw» ), то есть браузер будет подразумевать, что изображение может занимает всю ширину экрана.

Тег picture

Тег picture служит контейнером для одного или более тегов source и одного тега img . Тег source представляет собой источник изображения. Он содержит информацию о формате изображения и его размерах, а также правила, при соблюдении которых браузер должен выбрать этот источник. Если все источники не подходят, то будет выбран файл, указанный в атрибуте src тега img . Если сразу несколько источников подходят, то браузер выберет первый по порядку.

Тег source имеет атрибуты sizes и srcset . Они работают также, как и соотвествующие атрибуты у тега img . Рассмотрим на примере:

Данный пример работает так же, как и второй пример использования тега img .

Разница между img и picture

Тег picture позволяет указать браузеру использовать разные изображения в зависимости от размера экрана. Достигается это за счёт использования атрибута media тега source , который позволяет задать медиа выражение, при котором будет использоваться данный источник. Например, на маленьких экранах мы хотим использовать обрезанное изображение cropped-bears.jpg , которое содержит основную часть изображения:

Медведи

Для этого нужно указать несколько тегов source и задать им атрибуты media :

В данном примере, если ширина экрана устройства не превышает 480 css-пикселей, то будет выбрано обрезанное изображение. Добиться такого результата при помощи тега img не получиться, так как изображения cropped-bears-960×540.jpg и bears-960×540.jpg имеют одинаковый размер, но изображение cropped-bears-960×540.jpg предназначено для использования на устройстве, ширина которого не превышает 480 css-пикселей и коэфициент протности пикселей равен 2, а изображение bears-960×540.jpg — на устройстве, ширина которого от 480 до 960 css-пикселей и коэфициент протности пикселей равен 1.

Также, тег picture позволяет указать различные форматы изображения, например webp и jpeg . Для этого нужно тегу source задать атрибут type:

Источники с наименее поддерживаемыми типами нужно располагать в начале списка, так как браузер выберет первый по порядку подходящий источник. В данном примере браузер выберет тип изображения webp , если он его поддерживает. В противном случае будет выбран тип jpeg .

Источник

Оцените статью