Resize a bitmap in android - OutOfMemoryError exception - android

I try to re-size a bitmap, but sometimes i got an OutOfMemoryError crash.
Think that this line is the problem:
Bitmap.createBitmap(bm, 0, 0, width, height,
matrix, false);
this is the function:
public static Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth) {
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// CREATE A MATRIX FOR THE MANIPULATION
Matrix matrix = new Matrix();
// RESIZE THE BIT MAP
matrix.postScale(scaleWidth, scaleHeight);
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 100 , bos);
byte[] bitmapdata = bos.toByteArray();
ByteArrayInputStream bs = new ByteArrayInputStream(bitmapdata);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, width, height);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
bm = BitmapFactory.decodeStream(bs, null, options);
// "RECREATE" THE NEW BITMAP
return Bitmap.createBitmap(bm, 0, 0, width, height,
matrix, false);
}
this is the exception:
java.lang.OutOfMemoryError: Failed to allocate a 63489036 byte allocation with 16777120 free bytes and 54MB until OOM
at dalvik.system.VMRuntime.newNonMovableArray(VMRuntime.java)
at android.graphics.BitmapFactory.nativeDecodeStream(BitmapFactory.java)
at android.graphics.BitmapFactory.decodeStreamInternal(BitmapFactory.java:863)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:839)
at utils.Utils.getResizedBitmap(Utils.java:573)
at utils.Utils.getScaledBitmap(Utils.java:621)
at com.meucci.IncomingCallActivitym.onActivityResult(IncomingCallActivitym.java:904)
at android.app.Activity.dispatchActivityResult(Activity.java:6758)
at android.app.ActivityThread.deliverResults(ActivityThread.java:4668)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4715)
at android.app.ActivityThread.access$1500(ActivityThread.java:198)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1725)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6837)
at java.lang.reflect.Method.invoke(Method.java)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)

try this,
private Bitmap resizeBitmap(Bitmap image) {
int width = image.getWidth();
int height = image.getHeight();
float ratioBitmap = (float) width / (float) height;
if (width > height) {
ratioBitmap = (float) height / (float) width;
}
int targetHeight = MAX_IMAGE_SIZE;
int targetWidth = (int) ((float) targetHeight * ratioBitmap);
// Log.i(Constants.TAG, "old width = " + width + " new width = " + targetWidth);
// Log.i(Constants.TAG, "old Height = " + height + " new Height = " + targetHeight);
image = Bitmap.createScaledBitmap(image, targetWidth, targetHeight, true);
return image;
}

Related

NullPointerException Cant find bitmap from drawable on oppo device

im trying to get imageview from drawable and resize it my current code is working on all devices except on oppo devices it crash inside crop() method
the crash im getting is on the first line in crop() method you can find below
Caused by: java.lang.NullPointerException:
my current code is:
public Bitmap getTileBitmap(int id, int size) {
String string = tileUrls.get(id);
if (string.contains(Themes.URI_DRAWABLE)) {
String drawableResourceName = string.substring(Themes.URI_DRAWABLE.length());
int drawableResourceId = Shared.context.getResources().getIdentifier(drawableResourceName, "drawable", Shared.context.getPackageName());
Bitmap bitmap = Utils.scaleDown(drawableResourceId, size, size);
return Utils.crop(bitmap, size, size);
}
return null;
}
public static Bitmap crop(Bitmap source, int newHeight, int newWidth) {
int sourceWidth = source.getWidth();
int sourceHeight = source.getHeight();
float xScale = (float) newWidth / sourceWidth;
float yScale = (float) newHeight / sourceHeight;
float scale = Math.max(xScale, yScale);
float scaledWidth = scale * sourceWidth;
float scaledHeight = scale * sourceHeight;
float left = (newWidth - scaledWidth) / 2;
float top = (newHeight - scaledHeight) / 2;
RectF targetRect = new RectF(left, top, left + scaledWidth, top + scaledHeight);
Bitmap dest = Bitmap.createBitmap(newWidth, newHeight, source.getConfig());
Canvas canvas = new Canvas(dest);
canvas.drawBitmap(source, null, targetRect, null);
return dest;
}
EDIT: added scale method which may cause the issue
public static Bitmap scaleDown(int resource, int reqWidth, int reqHeight) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(Shared.context.getResources(), resource);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(Shared.context.getResources(), resource, options);
}
and so far im not sure what is causing the crash only on oppo devices
Try this:
options.inJustDecodeBounds = true;
options.inScaled = false;
options.inDensity = 0;
options.inMutable = true; //API 11. Pass to canvas? Might crash without this.
//Load the image here... BitmapFactory.decodeResource()...
... //Some calculations.
options.inJustDecodeBounds = false;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;

Android, how to reduce the size of a bitmap?

I have an app that allows the user to change their profile image to another one that is stored on their device. For this, the app sends the selected image to a remote server. All this works well, so I do not put the code of that part so as not to complicate the question. My problem is that I want that bitmap sent to the server is reduced in size to prevent, for example, large files of five or six megabytes, which slow down the app. But it does not end well.
This is my code for this:
if (requestCode == 1 && resultCode == RESULT_OK) {
Uri selectedImageUri = data.getData();
imagepath = getPath(selectedImageUri);
Bitmap bitmap=BitmapFactory.decodeFile(imagepath);
ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream();
//Resize the bitmap
Bitmap resizedBitmap = Bitmap.createScaledBitmap(bitmap, 150, 150, false);
resizedBitmap.compress(Bitmap.CompressFormat.JPEG,50,bytearrayoutputstream);
//Round the image
int min = Math.min(resizedBitmap.getWidth(), resizedBitmap.getHeight());
Bitmap bitmapRounded = Bitmap.createBitmap(min, min, resizedBitmap.getConfig());
Canvas canvas = new Canvas(bitmapRounded);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(new BitmapShader(resizedBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
canvas.drawRoundRect((new RectF(0.0f, 0.0f, min, min)), min / 2, min / 2, paint);
//bitmap to imageView
avatar.setImageBitmap(bitmapRounded);
}
I trying to reduce it in size (it does not work) and then round the image (this works fine) before adjusting it to the corresponding ImageView.
The only thing that I can not get it to work properly is to reduce the size of the bitmap.
i am using this to reduce my bitmap size and it is woring fine :-
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 40, baos);
If you want to make your image smaller, you need to first get the height and width of your bitmap, calculate the ratio and then can create a scaled bitmap.
int width = image.getWidth();
int height = image.getHeight();
You have to calculate the image size and return the scaled bitmap.
Find a similar question asked in here: Reduce the size of a bitmap to a specified size in Android
Hope you will get the exact solution.
Try this:
ByteArrayOutputStream ostream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 80, ostream);
I'm using this helper class.
public class ScaleFile {
private Context mContext;
public ScaleFile(Context context) {
this.mContext = context;
}
public Bitmap scaleFile(String imageUri) {
String filePath = getRealPathFromURI(imageUri);
Bitmap scaledBitmap = null;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
Bitmap bmp = BitmapFactory.decodeFile(filePath, options);
int actualHeight = options.outHeight;
int actualWidth = options.outWidth;
//max Height and width values of the compressed image is taken as 816x612
float maxHeight = 816.0f;
float maxWidth = 612.0f;
float imgRatio = actualWidth / actualHeight;
float maxRatio = maxWidth / maxHeight;
//width and height values are set maintaining the aspect ratio of the image
if (actualHeight > maxHeight || actualWidth > maxWidth) {
if (imgRatio < maxRatio) {
imgRatio = maxHeight / actualHeight;
actualWidth = (int) (imgRatio * actualWidth);
actualHeight = (int) maxHeight;
} else if (imgRatio > maxRatio) {
imgRatio = maxWidth / actualWidth;
actualHeight = (int) (imgRatio * actualHeight);
actualWidth = (int) maxWidth;
} else {
actualHeight = (int) maxHeight;
actualWidth = (int) maxWidth;
}
}
//setting inSampleSize value allows to load a scaled down version of the original image
options.inSampleSize = calculateInSampleSize(options, actualWidth, actualHeight);
options.inPurgeable = true;
options.inInputShareable = true;
options.inTempStorage = new byte[16 * 1024];
try {
//load the bitmap from its path
bmp = BitmapFactory.decodeFile(filePath, options);
} catch (OutOfMemoryError exception) {
exception.printStackTrace();
}
try {
scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight, Bitmap.Config.ARGB_8888);
} catch (OutOfMemoryError exception) {
exception.printStackTrace();
}
float ratioX = actualWidth / (float) options.outWidth;
float ratioY = actualHeight / (float) options.outHeight;
float middleX = actualWidth / 2.0f;
float middleY = actualHeight / 2.0f;
Matrix scaleMatrix = new Matrix();
scaleMatrix.setScale(ratioX, ratioY, middleX, middleY);
Canvas canvas = new Canvas(scaledBitmap);
canvas.setMatrix(scaleMatrix);
canvas.drawBitmap(bmp, middleX - bmp.getWidth() / 2, middleY - bmp.getHeight() / 2, new Paint(Paint.FILTER_BITMAP_FLAG));
// check the rotation of the image and display it properly
ExifInterface exif;
try {
exif = new ExifInterface(filePath);
int orientation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION, 0);
Matrix matrix = new Matrix();
if (orientation == 6) {
matrix.postRotate(90);
} else if (orientation == 3) {
matrix.postRotate(180);
} else if (orientation == 8) {
matrix.postRotate(270);
}
scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(),
scaledBitmap.getHeight(), matrix, true);
} catch (IOException e) {
e.printStackTrace();
}
return scaledBitmap;
}
private String getRealPathFromURI(String contentURI) {
Uri contentUri = Uri.parse(contentURI);
Cursor cursor = mContext.getContentResolver().query(contentUri, null, null, null, null);
if (cursor == null) {
return contentUri.getPath();
} else {
cursor.moveToFirst();
int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
return cursor.getString(index);
}
}
public 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 heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
final float totalPixels = width * height;
final float totalReqPixelsCap = reqWidth * reqHeight * 2;
while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) {
inSampleSize++;
}
return inSampleSize;
}
}
This is a useful code for you.
/**
* reduces the size of the image
* #param image
* #param maxSize
* #return
*/
public Bitmap getResizedBitmap(Bitmap image, int maxSize) {
int width = image.getWidth();
int height = image.getHeight();
float bitmapRatio = (float)width / (float) height;
if (bitmapRatio > 1) {
width = maxSize;
height = (int) (width / bitmapRatio);
} else {
height = maxSize;
width = (int) (height * bitmapRatio);
}
return Bitmap.createScaledBitmap(image, width, height, true);
}
Bitmap converetdImage = getResizedBitmap(selectedImageUri, 500);
You can refer to it from the following URL.
Reduce the size of a bitmap to a specified size in Android

low quality when resizing image in Android?

This is my code.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
img = (ImageView)findViewById(R.id.resizedView);
BitmapFactory.Options options = new BitmapFactory.Options ();
options.inScaled = false;
Bitmap largeIcon = BitmapFactory.decodeResource(getResources(), R.drawable.tutimage1, options);
Bitmap bmp = getResizedBitmap(largeIcon, 200);
img.setImageBitmap(bmp);
}
public Bitmap getResizedBitmap(Bitmap image, int maxSize)
{
int width = image.getWidth();
int height = image.getHeight();
float bitmapRatio = (float)width / (float) height;
if (bitmapRatio > 1) {
width = maxSize;
height = (int) (width / bitmapRatio);
} else {
height = maxSize;
width = (int) (height * bitmapRatio);
}
// return getResizedBitmapWithQuality(image, width, height);
return Bitmap.createScaledBitmap(image, width, height, false);
}
So I tried to research and tested but the result is still the same.
Is that because of the size needed is too small?
Original size is 1120 x 2048, the size of the result is 110 x 200.
Use this function to improve the image bitmap quality
public static Bitmap scaleBitmap(Bitmap bitmap, int newWidth, int newHeight) {
Bitmap scaledBitmap = Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888);
float scaleX = newWidth / (float) bitmap.getWidth();
float scaleY = newHeight / (float) bitmap.getHeight();
float pivotX = 0;
float pivotY = 0;
Matrix scaleMatrix = new Matrix();
scaleMatrix.setScale(scaleX, scaleY, pivotX, pivotY);
Canvas canvas = new Canvas(scaledBitmap);
canvas.setMatrix(scaleMatrix);
canvas.drawBitmap(bitmap, 0, 0, new Paint(Paint.FILTER_BITMAP_FLAG));
return scaledBitmap;
}

How to resize Image in Android?

I am creating an application and want to setup a gallery view. I do not want the images in the gallery view to be full size. How do I resize images in Android?
Try:
Bitmap yourBitmap;
Bitmap resized = Bitmap.createScaledBitmap(yourBitmap, newWidth, newHeight, true);
or:
resized = Bitmap.createScaledBitmap(yourBitmap,(int)(yourBitmap.getWidth()*0.8), (int)(yourBitmap.getHeight()*0.8), true);
public Bitmap resizeBitmap(String photoPath, int targetW, int targetH) {
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(photoPath, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
int scaleFactor = 1;
if ((targetW > 0) || (targetH > 0)) {
scaleFactor = Math.min(photoW/targetW, photoH/targetH);
}
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true; //Deprecated API 21
return BitmapFactory.decodeFile(photoPath, bmOptions);
}
Capture the image and resize it.
Bitmap image2 = (Bitmap) data.getExtras().get("data");
img.setImageBitmap(image2);
String incident_ID = IncidentFormActivity.incident_id;
imagepath="/sdcard/RDMS/"+incident_ID+ x + ".PNG";
File file = new File(imagepath);
try {
double xFactor = 0;
double width = Double.valueOf(image2.getWidth());
Log.v("WIDTH", String.valueOf(width));
double height = Double.valueOf(image2.getHeight());
Log.v("height", String.valueOf(height));
if(width>height){
xFactor = 841/width;
}
else{
xFactor = 595/width;
}
Log.v("Nheight", String.valueOf(width*xFactor));
Log.v("Nweight", String.valueOf(height*xFactor));
int Nheight = (int) ((xFactor*height));
int NWidth =(int) (xFactor * width) ;
bm = Bitmap.createScaledBitmap( image2,NWidth, Nheight, true);
file.createNewFile();
FileOutputStream ostream = new FileOutputStream(file);
bm.compress(CompressFormat.PNG, 100, ostream);
ostream.close();
You can use Matrix to resize your camera image ....
BitmapFactory.Options options=new BitmapFactory.Options();
InputStream is = getContentResolver().openInputStream(currImageURI);
bm = BitmapFactory.decodeStream(is,null,options);
int Height = bm.getHeight();
int Width = bm.getWidth();
int newHeight = 300;
int newWidth = 300;
float scaleWidth = ((float) newWidth) / Width;
float scaleHeight = ((float) newHeight) / Height;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0,Width, Height, matrix, true);
BitmapDrawable bmd = new BitmapDrawable(resizedBitmap);
//photo is bitmap image
Bitmap btm00 = Utils.getResizedBitmap(photo, 200, 200);
setimage.setImageBitmap(btm00);
And in Utils class :
public static Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth) {
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
Matrix matrix = new Matrix();
// RESIZE THE BIT MAP
matrix.postScale(scaleWidth, scaleHeight);
// RECREATE THE NEW BITMAP
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height,
matrix, false);
return resizedBitmap;
}
bm = Bitmap.createScaledBitmap(bitmapSource, width, height, true);
:)
BitmapFactory.Options options=new BitmapFactory.Options();
options.inSampleSize=2; //try to decrease decoded image
Bitmap bitmap=BitmapFactory.decodeStream(is, null, options);
bitmap.compress(Bitmap.CompressFormat.JPEG, 70, fos); //compressed bitmap to file
Following is the function to resize bitmap by keeping the same Aspect Ratio. Here I have also written a detailed blog post on the topic to explain this method. Resize a Bitmap by Keeping the Same Aspect Ratio.
public static Bitmap resizeBitmap(Bitmap source, int maxLength) {
try {
if (source.getHeight() >= source.getWidth()) {
int targetHeight = maxLength;
if (source.getHeight() <= targetHeight) { // if image already smaller than the required height
return source;
}
double aspectRatio = (double) source.getWidth() / (double) source.getHeight();
int targetWidth = (int) (targetHeight * aspectRatio);
Bitmap result = Bitmap.createScaledBitmap(source, targetWidth, targetHeight, false);
if (result != source) {
}
return result;
} else {
int targetWidth = maxLength;
if (source.getWidth() <= targetWidth) { // if image already smaller than the required height
return source;
}
double aspectRatio = ((double) source.getHeight()) / ((double) source.getWidth());
int targetHeight = (int) (targetWidth * aspectRatio);
Bitmap result = Bitmap.createScaledBitmap(source, targetWidth, targetHeight, false);
if (result != source) {
}
return result;
}
}
catch (Exception e)
{
return source;
}
}
resized = Bitmap.createScaledBitmap(yourImageBitmap,(int)(yourImageBitmap.getWidth()*0.9), (int)(yourBitmap.getHeight()*0.9), true);
BitmapFactory.Options options=new BitmapFactory.Options();
options.inSampleSize = 10;
FixBitmap = BitmapFactory.decodeFile(ImagePath, options);
//FixBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.gv);
byteArrayOutputStream = new ByteArrayOutputStream();
FixBitmap.compress(Bitmap.CompressFormat.JPEG, 80, byteArrayOutputStream); //compress to 50% of original image quality
byteArray = byteArrayOutputStream.toByteArray();
ConvertImage = Base64.encodeToString(byteArray, Base64.DEFAULT);

How to scale bitmap with high quality and without crash in android

I am downloading image using url, but after scaling it's crashing and scaling is not proper.
This is the code I have used,
//Code to fetch bitmap
Bitmap bmp=HttpFetch.fetchBitmap(imageUrl);
//Scale bitmap
Bitmap myBitmap = getResizedBitmap(bmp, viewWidth, viewHeight);
public static Bitmap getResizedBitmap(Bitmap bm, int newWidth, int newHeight) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
int srcWidth = bm.getWidth();
int srcHeight = bm.getHeight();
int desiredWidth = newWidth;
int desiredHeight = newHeight;
int inSampleSize = 1;
while(srcWidth / 2 > desiredWidth){
srcWidth /= 2;
srcHeight /= 2;
inSampleSize *= 2;
}
float desiredWidthScale = (float) desiredWidth / srcWidth;
float desiredHeightScale = (float) desiredHeight / srcHeight;
// Decode with inSampleSize
options.inJustDecodeBounds = false;
options.inDither = false;
options.inSampleSize = inSampleSize;
options.inScaled = false;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Matrix matrix = new Matrix();
matrix.postScale(desiredWidthScale, desiredHeightScale);
original = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
return original;
}
Could not find code to get BitmapFactory.Option using bitmap and most of the places it is using filename, is it possible to get BitmapFactory.Options using bitmap?
Kindly suggest better solution to scale bitmap when we download from network.
original = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
This line returns an immutable Bitmap, after calling getResizedBitmap(), if you are trying to modify this Bitmap, it might result in a crash.
Android#createBitmap()
Please look up LogCat for details.

Categories

Resources