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

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

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

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

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


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

int MAX_IMAGE_SIZE = 200 * 1024; // max final file size
Bitmap bmpPic = BitmapFactory.decodeFile(fileUri.getPath());
if ((bmpPic.getWidth() >= 1024) && (bmpPic.getHeight() >= 1024)) {
    BitmapFactory.Options bmpOptions = new BitmapFactory.Options();
    bmpOptions.inSampleSize = 1;
    while ((bmpPic.getWidth() >= 1024) && (bmpPic.getHeight() >= 1024)) {
        bmpOptions.inSampleSize++;
        bmpPic = BitmapFactory.decodeFile(fileUri.getPath(), bmpOptions);
    }
    Log.d(TAG, "Resize: " + bmpOptions.inSampleSize);
}
int compressQuality = 104; // quality decreasing by 5 every loop. (start from 99)
int streamLength = MAX_IMAGE_SIZE;
while (streamLength >= MAX_IMAGE_SIZE) {
    ByteArrayOutputStream bmpStream = new ByteArrayOutputStream();
    compressQuality -= 5;
    Log.d(TAG, "Quality: " + compressQuality);
    bmpPic.compress(Bitmap.CompressFormat.JPEG, compressQuality, bmpStream);
    byte[] bmpPicByteArray = bmpStream.toByteArray();
    streamLength = bmpPicByteArray.length;
    Log.d(TAG, "Size: " + streamLength);
}
try {
    FileOutputStream bmpFile = new FileOutputStream(finalPath);
    bmpPic.compress(Bitmap.CompressFormat.JPEG, compressQuality, bmpFile);
    bmpFile.flush();
    bmpFile.close();
} catch (Exception e) {
    Log.e(TAG, "Error on saving file");
}

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

 public void compressBitmap(File file, int sampleSize, int quality) {
        try {
           BitmapFactory.Options options = new BitmapFactory.Options();
            options.inSampleSize = sampleSize;
            FileInputStream inputStream = new FileInputStream(file);

            Bitmap selectedBitmap = BitmapFactory.decodeStream(inputStream, null, options);
            inputStream.close();

            FileOutputStream outputStream = new FileOutputStream("location to save");
            selectedBitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream);
            outputStream.close();
            long lengthInKb = photo.length() / 1024; //in kb
            if (lengthInKb > SIZE_LIMIT) {
               compressBitmap(file, (sampleSize*2), (quality/4));
            }

            selectedBitmap.recycle();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

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

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

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

Ответ 3

BitmapFactory.Options - уменьшает размер изображения (в памяти)

Bitmap.compress() - уменьшает размер изображения (на диске)


Обратитесь к этой ссылке для получения дополнительной информации об использовании их обоих:https://android.jlelse.eu/loading-large-bitmaps-efficiently-in-android-66826cd4ad53