I'm trying to scale image down before sending them to the back-end in my android app.
Currently I'm doing this with BitmapFactory.decodeFile()
and inJustDecodeBounds
option. but it skips sensor information and as a result I'm getting rotated image. I'm fixing it by setting transformation matrix. Here is my code:
File image = new File(uri.getPath());
int angle = 0;
ExifInterface exif = null;
try {
exif = new ExifInterface(image.getPath());
int orientation = exif.getAttributeInt(TAG_ORIENTATION, ORIENTATION_NORMAL);
switch (orientation) {
case ORIENTATION_ROTATE_90:
angle = 90;
break;
case ORIENTATION_ROTATE_180:
angle = 180;
break;
case ORIENTATION_ROTATE_270:
angle = 270;
break;
}
} catch (IOException e) {
if (DEBUG) e.printStackTrace();
}
Matrix mat = new Matrix();
mat.postRotate(angle);
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(image.getAbsolutePath(), options);
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
options.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeFile(image.getAbsolutePath(), options);
if (angle != 0) {
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), mat, true);
}
if (DEBUG) {
Log.d("COMPRESS", "scaled bitmap size: " + bitmap.getWidth() + "x" + bitmap.getHeight());
}
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 40, buffer);
bitmap.recycle();
return buffer.toByteArray();
But this approach leads to OOM exceptions as it do everything in the memory and each non 0 degree image is loaded to memory twice.
Much better approach could be a direct scaling with saving sensor and other metadata information directly to file. I tried ffmpeg libarary for this but it is hanging.
I tried to google some other library but for all my requests it gives me an answers how to scale image in ImageView
, Canvas
etc.
So is there any other way to scale image on android in efficient way ? Thanks.
I would use Picasso: http://square.github.io/picasso/ as it is able to handle orientation, resizing, and out of memory in one nice fluent API.
Bitmap smaller = Picasso.with(context)
.load(new File(uri.getPath()))
.resize(800, 800) // this is max size
.centerInside()
.get();
... carry on with compress code