Search code examples
androidandroid-asynctaskphotoimage-compression

Multiple photo compression


I need decrease photo size while photo size is not under 1MB. So how I do this. I have activity where I can take photo when is photo taken then in activity result I start AsyncTask which do compression of my photo. Compression works good and photo is saved OK if compression is done only once but if I try multiple photo compression I get infinity loop and is interesting photo size is increasing after every compression but why? Anyone have idea what I do bad? I find some samples with change photo resolution but I dont want change photo resolution I want apply only multiple photo compression.

    public class PhotoSaverAsyncTask extends AsyncTask<Void, Void, Void> {
    private int compressionLevel = 99; //if not set then default 99
    private Bitmap bitmap = null;
    private final int MAX_PHOTO_SIZE_IN_KILO_BYTES = 1024; // 1MB
    private PhotoSavedNotify photoSavedNotify = null;
    private ProgressDialog mProgressDialog = null;

    public PhotoSaverAsyncTask(int compressionLevel, PhotoSavedNotify photoSavedNotify) {
        super();
        this.compressionLevel = compressionLevel;
        this.photoSavedNotify = photoSavedNotify;
    }

    protected void onPreExecute() {
        mProgressDialog = new ProgressDialog(activity);
        mProgressDialog.setTitle("Kompresia fotografie...");
        mProgressDialog.setMessage("Čakajťe prosím...");
        mProgressDialog.setIndeterminate(true);
        mProgressDialog.show();
    }

    protected Void doInBackground(Void... params) {
        try {
            Log.d(this.toString(), "Original size: " + (getMediaFile().length() / 1024) + "Kb");
            compressionMethod();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    protected void onPostExecute(Void unused) {
        mProgressDialog.dismiss();
        if ((getMediaFile().length() / 1024) > MAX_PHOTO_SIZE_IN_KILO_BYTES) //1MB
        {
            new PhotoSaverAsyncTask(compressionLevel, photoSavedNotify).execute(); 
            //compressionMethod(); I also try while cycle without start another tak but the same result
        } else {
            photoSavedNotify.taskCompletionResult(getMediaFileName());
        }
    }

    private void compressionMethod() {
        try {
            BitmapFactory.Options options = new BitmapFactory.Options();
            bitmap = BitmapFactory.decodeFile(getMediaFileUri().getPath(), options);
            FileOutputStream out = new FileOutputStream(getMediaFile());
            bitmap.compress(Bitmap.CompressFormat.JPEG, compressionLevel, out);
            out.flush();
            out.close();
            Log.d(this.toString(), "After compression size: " + (getMediaFile().length() / 1024) + "Kb");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Solution

  • If after compression the size is still too large you should not compress the compressed photo. Instead you should compress the original photo with a different value of compressionLevel.

    If you compress a compressed photo it can get LARGER because the compression artifacts from the previous round of compression don't have the same smooth transitions as an uncompressed photo.