Image crop and resize in Android
I followed the instructions below to crop an image.
http://coderzheaven.com/index.php/2011/03/crop-an-image-in-android/
The height and width of the final cropped bitmap image are both larger than those of the screen.
During the resize and crop process, out of memory error was thrown and the app is forced to quit.
The error log:
04-09 11:37:28.658: ERROR/dalvikvm-heap(4003): 435176-byte external allocation too large for this process.
04-09 11:37:28.658: ERROR/GraphicsJNI(4003): VM won't let us allocate 435176 bytes
04-09 11:37:28.668: WARN/dalvikvm(4003): threadid=1: thread exiting with uncaught exception (group=0x4001d800)
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): FATAL EXCEPTION: main
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): ja开发者_高级运维va.lang.OutOfMemoryError: bitmap size exceeds VM budget
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at android.graphics.Bitmap.nativeCreate(Native Method)
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at android.graphics.Bitmap.createBitmap(Bitmap.java:468)
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at android.graphics.Bitmap.createBitmap(Bitmap.java:435)
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at com.test.Test.onCreate(Test.java:57)
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at android.app.ActivityThread.access$2300(ActivityThread.java:125)
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at android.os.Handler.dispatchMessage(Handler.java:99)
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at android.os.Looper.loop(Looper.java:123)
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at android.app.ActivityThread.main(ActivityThread.java:4627)
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at java.lang.reflect.Method.invokeNative(Native Method)
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at java.lang.reflect.Method.invoke(Method.java:521)
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at dalvik.system.NativeStart.main(Native Method)
Does anyone know how to solve the problem ?
Thanks.
======
Update: I solved the problem.
You can used crop image using following code that can solve your problem.
Matrix matrix = new Matrix();
matrix.postScale(0.5f, 0.5f);
Bitmap croppedBitmap = Bitmap.createBitmap(bitmapOriginal, 100, 100,100, 100, matrix, true);
Above method do postScalling of image before cropping, so you can get best result with cropped image without getting OOM error.
For more detail you can refer this blog
My co-worker just hipped me to this Android API... see ThumbnailUtils.
It does resizing and cropping for you.
http://developer.android.com/reference/android/media/ThumbnailUtils.html#extractThumbnail(android.graphics.Bitmap, int, int)
If your code varies from the example, you will have to post it to get precise help. Otherwise, based only on the log - here is an answer:
In the example you are using, the developer is cropping an image in his app's resources folder (which could be relatively small to start) to a 300x300 bitmap image. First, try cropping a smaller size image in your own app, to a smaller output size, to see if there is a problem with the code, or if you are using an image that is too large for your code or device.
Since you are saying the final image you are cropping is larger that the screen, that is probably the issue, and you are encountering a basic challenge of using bitmaps in Android. Bitmap file size is a function of pixel width times height - they get bigger fast.
You can solve by googling other parts of your log, like "bitmap size exceeds VM budget" and you will find several threads on stackoverflow that will help, like this one.
Strange out of memory issue while loading an image to a Bitmap object
You may solve it by using bitmap options and inSampleSize, and other techniques.
Look at the similar discussion here
, they seem to be having the same byte external allocation too large for this process
error.
I further verified the following instructions.
http://coderzheaven.com/index.php/2011/03/crop-an-image-in-android/
I found that the codes are not good enough and some of them are redundant.
To crop a big bitmap image, there is no need to use matrix to do the task.
Just use canvas.drawBitmap method can crop the big image !
Also no need to touch the BitmapFactory.Options.
Now I simply crop the image and let the imageview resize it. No more out-of-memory error. Bingo !
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at com.test.Test.onCreate(Test.java:57)
If I'm not mistaken, in
class Test extends Activity ....
on line 57, you have
Bitmap bitmapOrg = BitmapFactory.decodeResource(getResources(),R.drawable.image);
If so, the referenced image is so big that when Android tries to decode it into a bitmap, it cosumes all the free VM heap and throws theerror. You cant decode big bitmaps with
private Bitmap decodeFile(){
try {
//Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(),R.drawable.image,o);
//The new size we want to scale to
final int REQUIRED_SIZE=100;
//Find the correct scale value. It should be the power of 2.
int width_tmp=o.outWidth, height_tmp=o.outHeight;
int scale=1;
while(true){
if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
break;
width_tmp/=2;
height_tmp/=2;
scale*=2;
}
//Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeResource(getResources(),R.drawable.image, o2);
} catch (FileNotFoundException e) {}
return null;
}
I copied the code from the link that user699618 recommended, i ve used it before and it solves the problem).
After that you can just use CENTER_CROP
or whatever you need on ImageView.setScaleType()
.
You can find the Scale Type options in here and setScaleType details in hete.
Hope this helps.
i'd also recommend not to have such heavy pictures in resources. Make them smaller before saving them in the resorce forder.
//solution for bit map resizing
Bitmap targetBitmap = Bitmap.createBitmap(targetWidth, targetHeight,Bitmap.Config.ARGB_8888);
RectF rectf = new RectF(0, 0, 800, 400);
Canvas canvas = new Canvas(targetBitmap);
Path path = new Path();
path.addRect(rectf, Path.Direction.CW);
canvas.clipPath(path);
int xaxis=bm.getWidth();
int yaxis=bm.getHeight();
canvas.drawBitmap( bm, new Rect(0, 0, bm.getWidth(), bm.getHeight()),
new Rect(0, 0, targetWidth, targetHeight), paint);
Matrix matrix = new Matrix();
matrix.postScale(1f, 1f);
resizedBitmap = Bitmap.createBitmap(targetBitmap, 0, 0, width, height, matrix, true);
BitmapDrawable bd = new BitmapDrawable(resizedBitmap);
//get screen resolution;
WindowManager display = getWindowManager();
Point size = new Point();
display.getDefaultDisplay().getSize(size);
int width = size.x;
int height = size.y;
// scale the bitmap according to the screen resolution .
Bitmap bMap = BitmapFactory.decodeResource(getResources(), .drawable.ima1);
bMap = Bitmap.createScaledBitmap(bMap, width, height, true);
// then crop under value of the screen size and bitmap!
bMap = Bitmap.createBitmap(bMap, 0, 0, width/2, height);
Drawable drawa = new BitmapDrawable(getResources(),bMap);
i hope to be usefull
精彩评论