Pregunta Android: reduce el tamaño del archivo de imagen


Tengo un archivo de imagen URI, y quiero reducir su tamaño para subirlo. El tamaño del archivo de imagen inicial depende de un dispositivo móvil a otro (puede ser de 2MB, como puede ser 500KB), pero quiero que el tamaño final sea de aproximadamente 200KB, para que pueda cargarlo.
Por lo que leí, tengo (al menos) 2 opciones:

  • Utilizando BitmapFactory.Options.inSampleSize, para submuestrear la imagen original y obtener una imagen más pequeña;
  • Utilizando Bitmap.compress comprimir la imagen especificando la calidad de compresión.

¿Cuál es la mejor opción?


Estaba pensando en redimensionar inicialmente el ancho / alto de la imagen hasta que el ancho o la altura estén por encima de 1000px (algo así como 1024x768 u otros), luego comprimir la imagen con calidad decreciente hasta que el tamaño del archivo sea superior a 200KB. Aquí hay un ejemplo:

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");
}

Hay una mejor manera de hacerlo? ¿Debo intentar seguir usando los 2 métodos o solo uno? Gracias


50
2018-06-16 06:11


origen


Respuestas:


Utilizando Bitmap.compress() usted solo especifica el algoritmo de compresión y, por cierto, la operación de compresión lleva bastante tiempo. Si necesita jugar con tamaños para reducir la asignación de memoria para su imagen, necesita usar la escala de su imagen usando Bitmap.Options, al principio, calcula los límites del mapa de bits y luego los decodifica con el tamaño especificado.

La mejor muestra que encontré en StackOverflow es éste.


27
2018-06-16 06:18



La mayoría de las respuestas que encontré fueron solo piezas que tuve que juntar para obtener un código de trabajo, que se publica a continuación

 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 parámetros sampleSize y calidad juega un papel importante 

tamaño de la muestra se usa para submuestrear la imagen original y devolver una imagen más pequeña, es decir,
SampleSize == 4 devuelve una imagen que es 1/4 del ancho / alto del original.

la calidad se usa para indicar el compresor, el rango de entrada está entre 0-100. 0 significado comprimir para                       tamaño pequeño, 100 compresor de significado para una calidad máxima


0
2017-11-04 09:42