pedroooo pedroooo - 5 months ago 58
Java Question

Android image resize error memory

I have a method to rotate images but I always receive an OutMemoryError, but my images in the gallery iare taken from camera and size width is 5000~ from phone

I resized photo to width 1280 and height 960

my first method for show and resize image is

public static Boolean ShowImagesCapture(Context context, Uri PATH_IMAGE, ImageCropView view,int width, int height){

int orientation=0;
Boolean success = true;
try {
Bitmap bitmap =null;

if (Build.VERSION.SDK_INT < 19) {
String selectedImagePath = getPath(PATH_IMAGE,context);
bitmap = BitmapFactory.decodeFile(selectedImagePath);
orientation=GetPhotoOrientation(context,getRealPathFromURI(context,PATH_IMAGE));
}

else {
ParcelFileDescriptor parcelFileDescriptor;

try {
parcelFileDescriptor = context.getContentResolver().openFileDescriptor(PATH_IMAGE, "r");
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor);
parcelFileDescriptor.close();
orientation=GetPhotoOrientation(context,getRealPathFromURI(context,PATH_IMAGE));

} catch (Exception e) {
e.printStackTrace();
}
}
switch (orientation) {

case ExifInterface.ORIENTATION_ROTATE_180:
bitmap=rotateBitmap(bitmap,3,width,height);
view.setImageBitmap(bitmap);

break;
break;
case ExifInterface.ORIENTATION_ROTATE_90:
bitmap=rotateBitmap(bitmap,8,width,height);
view.setImageBitmap(bitmap);
break;

case ExifInterface.ORIENTATION_TRANSVERSE:
break;

case ExifInterface.ORIENTATION_ROTATE_270:
bitmap=rotateBitmap(bitmap,6,width,height);
view.setImageBitmap(bitmap);
break;

default:
view.setImageBitmap(bitmap);

}

bitmap = null;

}
catch (Exception e) {
e.printStackTrace();
success= false;
}
System.gc();
return success;
}


And my method for rotate image is

public static Bitmap rotateBitmap(Bitmap bitmap, int orientation,int width,int height) {

try {
Matrix matrix = new Matrix();
switch (orientation) {
case ExifInterface.ORIENTATION_NORMAL:
return bitmap;
case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
// matrix.setScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
matrix.setRotate(180);
break;
case ExifInterface.ORIENTATION_FLIP_VERTICAL:
matrix.setRotate(180);
// matrix.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_TRANSPOSE:
matrix.setRotate(90);
// matrix.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_90:
matrix.setRotate(90);
break;
case ExifInterface.ORIENTATION_TRANSVERSE:
matrix.setRotate(-90);
// matrix.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
matrix.setRotate(-270);
break;
default:
return bitmap;
}



Bitmap bmRotated = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, false);
bitmap.recycle();
return bmRotated;

}
catch (OutOfMemoryError e) {
Log.e(TAG,"Out memory Error");
return null;
}catch (Exception e){
e.printStackTrace();
return null;
}
}


where is my error?

*-------------------**UPDATE JUN 27 2016 **-------------------*

MY CODE HAVE A BEST VERSION WORK FINE

public static Bitmap rotateBitmap(Bitmap bitmap, int orientation,int width,int height) {

try {
Matrix matrix = new Matrix();
switch (orientation) {
case ExifInterface.ORIENTATION_NORMAL:
return bitmap;
case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
matrix.setScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
matrix.setRotate(180);
break;
case ExifInterface.ORIENTATION_FLIP_VERTICAL:
matrix.setRotate(180);
matrix.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_TRANSPOSE:
matrix.setRotate(90);
matrix.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_90:
matrix.setRotate(90);
break;
case ExifInterface.ORIENTATION_TRANSVERSE:
matrix.setRotate(-90);
matrix.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
matrix.setRotate(-270);
break;
default:
return bitmap;
}
Bitmap bmRotated= null;
try {
Bitmap tmp_bitmap= Bitmap.createScaledBitmap(bitmap,width,height,true);

bmRotated = Bitmap.createBitmap(tmp_bitmap, 0, 0, tmp_bitmap.getWidth(),tmp_bitmap.getHeight(), matrix, true);

bitmap.recycle();
}catch (OutOfMemoryError e){
e.printStackTrace();
}
return bmRotated;

} catch (Exception e){
e.printStackTrace();
return null;
}
}


public static Bitmap decodefilebitmap(String selectedImagePath, int reqWidth, int reqHeight) {

// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(selectedImagePath, options);

// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(selectedImagePath, options);
}

public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
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;

// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}

return inSampleSize;
}

//METODO PARA MOSTRAR LA IMAGEN DESDE LA GALERIA
public static Boolean ShowImagesCapture(Context context, Uri PATH_IMAGE, ImageCropView view,int width, int height){

int orientation=0;
Boolean success = true;
try {
Bitmap bitmap =null;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;

if (Build.VERSION.SDK_INT < 19) {
String selectedImagePath = getPath(PATH_IMAGE,context);
bitmap = decodefilebitmap(selectedImagePath,bitmap.getWidth(),bitmap.getHeight());
orientation=GetPhotoOrientation(context,getRealPathFromURI(context,PATH_IMAGE));
}

else {
ParcelFileDescriptor parcelFileDescriptor;

try {
parcelFileDescriptor = context.getContentResolver().openFileDescriptor(PATH_IMAGE, "r");
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor);
parcelFileDescriptor.close();
orientation=GetPhotoOrientation(context,getRealPathFromURI(context,PATH_IMAGE));

} catch (Exception e) {
e.printStackTrace();
}
}
switch (orientation) {


case ExifInterface.ORIENTATION_ROTATE_180:
bitmap=rotateBitmap(bitmap,3,width,height);
view.setImageBitmap(bitmap);

break;

case ExifInterface.ORIENTATION_ROTATE_90:
bitmap=rotateBitmap(bitmap,8,width,height);
view.setImageBitmap(bitmap);
break;

case ExifInterface.ORIENTATION_TRANSVERSE:
break;

case ExifInterface.ORIENTATION_ROTATE_270:
bitmap=rotateBitmap(bitmap,6,width,height);
view.setImageBitmap(bitmap);
break;

default:
view.setImageBitmap(bitmap);

}

bitmap = null;

}
catch (Exception e) {
e.printStackTrace();
success= false;
}
System.gc();
return success;
}

Answer

That's because you are loading the whole bitmap into memory bitmap = BitmapFactory.decodeFile(selectedImagePath); and then showing a resized version into the ImageView (but wasting memory because you have the full size version in RAM). You need to load a scaled down version. It's not the same to load all the bitmap and then do operations to it (scale, rotate, put it into an image view) than to load an scaled down version of that bitmap into memory. For example, if you have a 5000 by 5000 pixels image, suppose that in JPEG format its size is about 1MB. But when you load it into memory you decompress it and load the whole uncompressed version of that image. Suppose that you load it in 32 bit per pixel, then its size in RAM would be 5000x5000x32 bits, that is about 95MB! So you need to load an scaled down version. Check out this Android Developers document about loading a scaled down bitmap version into memory. That will help you to understand better the problem. You could also use image loading libraries like Glide. Those libraries do all of this and more.