Reputation: 1370
I am trying to reduce the size of the bitmap after taking the picture. I am able to reduce the size to max 900kb but I wan to reduce it further as much as possible
First I do this:
public static Bitmap decodeSampledBitmapFromResource(byte[] data,
int reqWidth, int reqHeight) {
//reqWidth is 320
//reqHeight is 480
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(data, 0, data.length, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeByteArray(data, 0, data.length, options);
}
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
then this
bitmap.compress(Bitmap.CompressFormat.PNG, 10, fos);
How do i compress the bitmap further ? or Should I compress the byte[] instead? I just want to send documents, black and white.
Upvotes: 0
Views: 6389
Reputation: 1022
I know that the question has some time, but I think this answer could help someone.
There are three methods to compress your picture (the "byte[] data" you have recieved from the Camera):
1) PNG format -> It's the worst choice when the image has a lot of different colors, and in general, this is the case when you take a photo. The PNG format is more useful in images like logotypes and stuff like this.
The code:
String filename = "" //THE PATH WHERE YOU WANT TO PUT YOUR IMAGE
File pictureFile = new File(filename);
try{ //"data" is your "byte[] data"
FileOutputStream fos = new FileOutputStream(pictureFile);
Bitmap bmp = BitmapFactory.decodeByteArray(data, 0, data.length);
bmp.compress(Bitmap.CompressFormat.PNG, 100, fos); //100-best quality
fos.write(data);
fos.close();
} catch (Exception e){
Log.d("Error", "Image "+filename+" not saved: " + e.getMessage());
}
2) JPG format -> It's a better option with an image with a lot of colors (the algoritm to compress is very different than PNG), but it does not have the 'alpha channel' that could be necesary in some scenarios.
There is only one change from the previous code:
bmp.compress(Bitmap.CompressFormat.JPEG, 100, fos); //100-best quality
3) WebP format -> It's the best format by far. An image of 1.0 MB in PNG could be compress to 100-200KB in JPG, and only to 30-50 KB in WebP. This format has also the 'alpha channel'. But it's not perfect: some browsers are not compatible with it. So you have to be careful about this in your project.
There is only one change from the previous code:
bmp.compress(Bitmap.CompressFormat.WEBP, 100, fos); //100-best quality
NOTES:
1) If this level of compress is not enought, you can play with the quality of the compress (the '100' that you can see in the bmp.compress() method). Be careful with the quality in the JPEG, because in some cases with a quality of 80%, you can see the impact in the image easyly. In PNG and WebP formats the loss percentage has less impact.
2) The other way to reduce the size is to resize the image. The easiest way I found is to simply create a smaller bitmap through Bitmap.createScaledBitmap method (more info).
3) And the last one method is to put the image in black and white. You can do this with this method:
Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
PS 1 - If someone wants to have a deeper knowledge about the image compress methods in Android, I recommend this talk by Colt McAnlis in the Google I/O 2016 (link).
Upvotes: 2
Reputation: 4007
You should use jpg instead of png if the alpha channel is not needed. Also you can change the color config of your output bitmap:
// Decode bitmap with inSampleSize set
options.inPreferredConfig= Bitmap.Config.RGB_565;
options.inJustDecodeBounds = false;
return BitmapFactory.decodeByteArray(data, 0, data.length, options);
Upvotes: 1