Android: BitmapFactory.decodeByteArray — уменьшить качество изображения

Это мой вариант использования:

ByteArray ba; // Some value is assigned here
Bitmap bitmap = BitmapFactory.decodeByteArray(ba, 0, ba.length);

Поскольку объект ByteArray слишком велик, во второй строке возникает исключение OutOfMemoryError при выполнении:

BitmapFactory.decodeByteArray(ba, 0, ba.length);

Уже пробовал:

ByteArray ba; // Some value is assigned here
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4; //or whatever value
Bitmap bitmap = BitmapFactory.decodeByteArray(ba, 0, ba.length, options);

Проблема с этим решением заключается в том, что при использовании атрибута inSampleSize исключается исключение OutOfMemoryError, но размер битовая карта (размеры: ширина x высота) уменьшается.

Вместо этого я ищу что-то похожее на это:

bitmap.compress(Bitmap.CompressFormat.JPEG, 50, stream);

В этом примере качественный растрового изображения уменьшено, НО его размер остается прежним. Когда я показываю это в ImageView:

iv.setImageBitmap(bitmap);

Он занимает то же место, что и оригинал, но с половинным качеством.

Проблема в том, что в моем случае я не могу использовать bitmap.compress, потому что мой битмап нулевой. То есть метод compress можно использовать после у вас есть валидный Bitmap объект, что не мой случай.

Вопрос:

Есть ли решение с использованием BitmapFactory.Options, которое может привести к тому же результату, что и bitmap.compress: меньше quality, то же dimensions?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
713
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Is there any solution using BitmapFactory.Options which can lead to the same result as bitmap.compress: lower quality, same dimensions?

Не совсем. Bitmap несжатый по своей природе.

The problem is, that in my case I cannot use bitmap.compress because my bitmap is null.

Вы путаете закодированное изображение JPEG с Bitmap. Закодированное изображение JPEG сжато. Bitmap нет. Bitmapвсегда потребляет память в зависимости от ширины, высоты и количества битов на пиксель.

Вы можете использовать другое количество бит на пиксель. BitmapFactory использует ARGB_8888 (32 бита на пиксель). Вы можете переключиться на RGB_565 (16 бит/пиксель), если ваше изображение не имеет альфа-канала и вы можете жить с уменьшенным диапазоном цветов.

В противном случае ваш единственный вариант — уменьшить размер (ширину и высоту) изображения.

Это может быть хорошим решением в некоторых случаях. Переключение с ARGB_888 на RGB_565 уменьшает размер более чем вдвое.

Dionis Beqiraj 21.06.2019 09:42

Вы не можете сжимать растровое изображение так, как хотите.

Возможно, вы уже знаете это - Но, да! вы можете найти соответствующий inSampleSize этим методом, чтобы сохранить качество в зависимости от размера.

public static int calculateInSampleSize(
            BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {

        final int halfHeight = height / 2;
        final int halfWidth = width / 2;

        // Calculate the largest inSampleSize value that is a power of 2 and keeps both
        // height and width larger than the requested height and width.
        while ((halfHeight / inSampleSize) >= reqHeight
                && (halfWidth / inSampleSize) >= reqWidth) {
            inSampleSize *= 2;
        }
    }

    return inSampleSize;
}

Этот метод выбран из Android эффективно загружает большие изображения.

Вы можете прочитать больше о передаче Bimaps здесь

Другие вопросы по теме