android reduce file size for camera captured image

2019-01-18 09:55发布

My requirement is to upload camera captured image to the server, but it should be less than 500 KB. In case, if it is greater than 500 KB, it needs to be reduced to the size less than 500 KB (but somewhat closer to it)

For this, I am using the following code -

@Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        try {
            super.onActivityResult(requestCode, resultCode, data);
            if (resultCode == getActivity().RESULT_OK) {

                    if (requestCode == REQUEST_CODE_CAMERA) {

                        try {

                            photo = MediaStore.Images.Media.getBitmap(
                                    ctx.getContentResolver(), capturedImageUri);
                            String selectedImagePath = getRealPathFromURI(capturedImageUri);

                            img_file = new File(selectedImagePath);

                            Log.d("img_file_size", "file size in KBs (initially): " + (img_file.length()/1000));

                            if(CommonUtilities.isImageFileSizeGreaterThan500KB(img_file)) {
                                photo = CommonUtilities.getResizedBitmapLessThan500KB(photo, 500);
                            }
                            photo = CommonUtilities.getCorrectBitmap(photo, selectedImagePath);


//  // CALL THIS METHOD TO GET THE URI FROM THE BITMAP

                            img_file = new File(ctx.getCacheDir(), "image.jpg");
                            img_file.createNewFile();

//Convert bitmap to byte array
                            ByteArrayOutputStream bytes = new ByteArrayOutputStream();
                            photo.compress(Bitmap.CompressFormat.JPEG, 100, bytes);

//write the bytes in file
                            FileOutputStream fo = new FileOutputStream(img_file);
                            fo.write(bytes.toByteArray());

// remember close de FileOutput
                            fo.close();
                            Log.d("img_file_size", "file size in KBs after image manipulations: " + (img_file.length()/1000));


                        } catch (Exception e) {
                            Logs.setLogException(class_name, "onActivityResult(), when captured from camera", e);
                        }


                    } 

            }
        } catch (Exception e) {
            Logs.setLogException(class_name, "onActivityResult()", e);
        } catch (OutOfMemoryError e) {
            Logs.setLogError(class_name, "onActivityResult()", e);

        }
    }

And

public static Bitmap getResizedBitmapLessThan500KB(Bitmap image, int maxSize) {
        int width = image.getWidth();
        int height = image.getHeight();



        float bitmapRatio = (float)width / (float) height;
        if (bitmapRatio > 0) {
            width = maxSize;
            height = (int) (width / bitmapRatio);
        } else {
            height = maxSize;
            width = (int) (height * bitmapRatio);
        }
        Bitmap reduced_bitmap = Bitmap.createScaledBitmap(image, width, height, true);
        if(sizeOf(reduced_bitmap) > (500 * 1000)) {
            return getResizedBitmap(reduced_bitmap, maxSize);
        } else {
            return reduced_bitmap;
        }
    }

To rotate the image, if needed.

public static Bitmap getCorrectBitmap(Bitmap bitmap, String filePath) {
        ExifInterface ei;
        Bitmap rotatedBitmap = bitmap;
        try {
            ei = new ExifInterface(filePath);

            int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_NORMAL);
            Matrix matrix = new Matrix();
            switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_90:
                    matrix.postRotate(90);
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    matrix.postRotate(180);
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    matrix.postRotate(270);
                    break;
            }

            rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return rotatedBitmap;
    }

Here is the output of the image file size initially and after all the operations to reduce file size.

img_file_size﹕ file size in KBs (initially): 3294

img_file_size﹕ file size in KBs after image manipulations: 235

See the difference above (in the output). The initial file size without those operations, and after those compression and other operations. I need that size to be somewhat closer to 500 kb.

The above code is working somewhat fine for me, as it is reducing the image file size to make it less than 500 KB.

But, the following are the issues with the above code -

  • This code is reducing the file size even if its less than 500 KB

  • In case it is more than 500 KB, the reduced file size becomes too less from 500 KB, , though I need it somewhat closer.

I need to get rid off above 2 issues. So, need to know what should I manipulate in the above code.

As I also want to correct the EXIF-orientation (rotated images), along with my above mentioned requirement.

8条回答
做个烂人
2楼-- · 2019-01-18 10:28

To reduce the size of Image I've used this code.. and its work for me.. Please check it once.. It might be helpful to you..

Bitmap photo1 ;
private byte[] imageByteArray1 ;


BitmapFactory.Options opt1 = new BitmapFactory.Options();
opt1.inJustDecodeBounds=true;
BitmapFactory.decodeFile(imageUrl.get(imgCount).toString(),opt1);

// The new size we want to scale to
final int REQUIRED_SIZE=320;

// Find the correct scale value. It should be the power of 2.
int width_tmp=opt1.outWidth,height_tmp=opt1.outHeight;
int scale=2;
while(true){
    if(width_tmp>REQUIRED_SIZE||height_tmp>REQUIRED_SIZE)
        break;
    width_tmp/=2;
    height_tmp/=2;
    scale*=2;
}
// Decode with inSampleSize
BitmapFactory.Options o2=new BitmapFactory.Options();
o2.inSampleSize=scale;
o2.inJustDecodeBounds=false;
photo1=BitmapFactory.decodeFile(imageUrl.get(imgCount).toString(),o2);

ByteArrayOutputStream baos1=new ByteArrayOutputStream();
photo1.compress(Bitmap.CompressFormat.JPEG,60,baos1);
imageByteArray1=baos1.toByteArray();
查看更多
小情绪 Triste *
3楼-- · 2019-01-18 10:29

Customizing my getResizedBitmapLessThan500KB() to this below, worked for me.

    public static final long CAMERA_IMAGE_MAX_DESIRED_SIZE_IN_BYTES = 2524970;
        public static final double CAMERA_IMAGE_MAX_SIZE_AFTER_COMPRESSSION_IN_BYTES = 1893729.0;

 public static Bitmap getResizedBitmapLessThan500KB(Bitmap image, int maxSize, long file_size_in_bytes) {
                int width = image.getWidth();
                int height = image.getHeight();


                if(file_size_in_bytes <= AppGlobalConstants.CAMERA_IMAGE_MAX_DESIRED_SIZE_IN_BYTES) {
                    if (width > height) {
                        if (width > 500)
                            maxSize = width * 75 / 100;
                    } else {
                        if (height > 500)
                            maxSize = height * 75 / 100;
                    }
                } else {
                    double percentage = ((AppGlobalConstants.CAMERA_IMAGE_MAX_SIZE_AFTER_COMPRESSSION_IN_BYTES/file_size_in_bytes)*100);
                    if (width > height) {
                        if (width > 500)
                            maxSize = width * (int)percentage / 100;
                    } else {
                        if (height > 500)
                            maxSize = height * (int)percentage / 100;
                    }

                    if(maxSize > 600) {
                        maxSize = 600;
                    }

                }

                float bitmapRatio = (float)width / (float) height;
                if (bitmapRatio > 0) {
                    width = maxSize;
                    height = (int) (width / bitmapRatio);
                } else {
                    height = maxSize;
                    width = (int) (height * bitmapRatio);
                }
                Bitmap reduced_bitmap = Bitmap.createScaledBitmap(image, width, height, true);
        //        Log.d("file_size","file_size_during_manipulation: "+String.valueOf(sizeOf(reduced_bitmap)));
                if(sizeOf(reduced_bitmap) > (500 * 1000)) {
                    return getResizedBitmap(reduced_bitmap, maxSize, sizeOf(reduced_bitmap));
                } else {
                    return reduced_bitmap;
                }
            }
查看更多
登录 后发表回答