5

I'm trying to compress an image that I saved in the file. I'm trying to compress the File into 1MB. I try a few way but it usually make an OutofMemoryError. and then i tried to use this solution, but it makes the bitmap blank.

How to compress bitmap from 10mb image from camera to 300kb beforw setting to imageview in android

Here is my code :

    System.gc();
    getActivity().getContentResolver().notifyChange(mImageTempUri, null);
    Bitmap bitmap;
    bitmap = BitmapFactory.decodeFile(mImageDirectory + mImageName, options);
    if(bitmap == null){
    howRequestFailedErrorMessage("Gambar gagal di-upload");
    return;

    ByteArrayOutputStream bytes = new ByteArrayOutputStream();   


    bitmap.compress(Bitmap.CompressFormat.JPEG, 25, bytes);
    File f = new File(mImageDirectory + mImageName);
    if(f.exists()){
        f.delete();
    }
    FileOutputStream fo;

    try {
        fo = new FileOutputStream(f);
        fo.write(bytes.toByteArray());
        fo.flush();
        fo.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    bitmap.recycle();
Community
  • 1
  • 1
stephen1706
  • 1,010
  • 11
  • 22
  • Did you try to put compressed data to fileOutputStream directly? You create two sets of jpeg image data, one is in ByteArrayOutputStream explicitly, and the other is bytes.toBytesArray temporarily. I guess these data may cause 'Out of memory' error. You may be able to avoid these data by the code "bitmap.compress(Bitmap.CompressFormat.JPEG, 25, fo);" – Fumu 7 Feb 27 '15 at 09:15
  • @Fumu7 I don't really get it, can u give the example in code? actually out of memory is not really the issue right now, the main problem is that I can't compress the image dynamically, and I have to adjust the quality staticly (which is 25 now) – stephen1706 Feb 27 '15 at 09:17

2 Answers2

12

okay, I got my own answer

    File f = new File(mImageDirectory + mImageName);
    if(f.exists()){
        f.delete();
    }

    int MAX_IMAGE_SIZE = 1000 * 1024;
    int streamLength = MAX_IMAGE_SIZE;
    int compressQuality = 105;
    ByteArrayOutputStream bmpStream = new ByteArrayOutputStream();
    while (streamLength >= MAX_IMAGE_SIZE && compressQuality > 5) {
        try {
            bmpStream.flush();//to avoid out of memory error
            bmpStream.reset();
        } catch (IOException e) {
            e.printStackTrace();
        }
        compressQuality -= 5;
        bitmap.compress(Bitmap.CompressFormat.JPEG, compressQuality, bmpStream);
        byte[] bmpPicByteArray = bmpStream.toByteArray();
        streamLength = bmpPicByteArray.length;
        if(BuildConfig.DEBUG) {
            Log.d("test upload", "Quality: " + compressQuality);
            Log.d("test upload", "Size: " + streamLength);
        }
    }

    FileOutputStream fo;

    try {
        fo = new FileOutputStream(f);
        fo.write(bmpStream.toByteArray());
        fo.flush();
        fo.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
stephen1706
  • 1,010
  • 11
  • 22
  • you may check size without creating byte[], just get bmpStream.size() `mBitmapImage.compress(Bitmap.CompressFormat.JPEG, percentDecompression, outputStream); actualSize = outputStream.size();` – murt May 24 '16 at 08:32
3

Kotlin Way

        if (file.length() > MAX_IMAGE_SIZE) {
            var streamLength = MAX_IMAGE_SIZE
            var compressQuality = 105
            val bmpStream = ByteArrayOutputStream()
            while (streamLength >= MAX_IMAGE_SIZE && compressQuality > 5) {
                bmpStream.use {
                    it.flush()
                    it.reset()
                }

                compressQuality -= 5
                val bitmap = BitmapFactory.decodeFile(file.absolutePath, BitmapFactory.Options())
                bitmap.compress(Bitmap.CompressFormat.JPEG, compressQuality, bmpStream)
                val bmpPicByteArray = bmpStream.toByteArray()
                streamLength = bmpPicByteArray.size
                if (BuildConfig.DEBUG) {
                    Log.d("test upload", "Quality: $compressQuality")
                    Log.d("test upload", "Size: $streamLength")
                }
            }

            FileOutputStream(file).use {
                it.write(bmpStream.toByteArray())
            }
        }

Constant

companion object {
    //2000 * 1024 = 2 MB
    private const val MAX_IMAGE_SIZE = 2048000
}
LinuxFelipe-COL
  • 381
  • 3
  • 7