Reputation: 734
Im trying to rotate an image inside an imageView and also roate the bitmap with the same image.
(I need that bitmap because Im sending the image to a server later)
The code:
image.setOnClickListener(new OnClickListener() {
public void onClick(View view) {
mPhoto=rotate(mPhoto,90);
image.setImageBitmap(mPhoto);
}
});
rotate() method:
public static Bitmap rotate(Bitmap src, float degree) {
// create new matrix
Matrix matrix = new Matrix();
// setup rotation degree
matrix.postRotate(degree);
// return new bitmap rotated using matrix
return Bitmap.createBitmap(src, 0, 0, src.getWidth(), src.getHeight(), matrix, true);
}
Logcat:
08-29 23:14:34.964: W/dalvikvm(20087): threadid=1: thread exiting with uncaught exception (group=0x41505930)
08-29 23:14:34.968: E/AndroidRuntime(20087): FATAL EXCEPTION: main
08-29 23:14:34.968: E/AndroidRuntime(20087): java.lang.OutOfMemoryError
08-29 23:14:34.968: E/AndroidRuntime(20087): at android.graphics.Bitmap.nativeCreate(Native Method)
08-29 23:14:34.968: E/AndroidRuntime(20087): at android.graphics.Bitmap.createBitmap(Bitmap.java:689)
08-29 23:14:34.968: E/AndroidRuntime(20087): at android.graphics.Bitmap.createBitmap(Bitmap.java:666)
08-29 23:14:34.968: E/AndroidRuntime(20087): at android.graphics.Bitmap.createBitmap(Bitmap.java:599)
08-29 23:14:34.968: E/AndroidRuntime(20087): at com.example.free.Add.rotate(Add.java:356)
08-29 23:14:34.968: E/AndroidRuntime(20087): at com.example.free.Add$5.onClick(Add.java:137)
08-29 23:14:34.968: E/AndroidRuntime(20087): at android.view.View.performClick(View.java:4211)
08-29 23:14:34.968: E/AndroidRuntime(20087): at android.view.View$PerformClick.run(View.java:17362)
08-29 23:14:34.968: E/AndroidRuntime(20087): at android.os.Handler.handleCallback(Handler.java:725)
08-29 23:14:34.968: E/AndroidRuntime(20087): at android.os.Handler.dispatchMessage(Handler.java:92)
08-29 23:14:34.968: E/AndroidRuntime(20087): at android.os.Looper.loop(Looper.java:137)
08-29 23:14:34.968: E/AndroidRuntime(20087): at android.app.ActivityThread.main(ActivityThread.java:5227)
08-29 23:14:34.968: E/AndroidRuntime(20087): at java.lang.reflect.Method.invokeNative(Native Method)
08-29 23:14:34.968: E/AndroidRuntime(20087): at java.lang.reflect.Method.invoke(Method.java:511)
08-29 23:14:34.968: E/AndroidRuntime(20087): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:795)
08-29 23:14:34.968: E/AndroidRuntime(20087): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:562)
08-29 23:14:34.968: E/AndroidRuntime(20087): at dalvik.system.NativeStart.main(Native Method)
Hope you could help me.
Ty!
Upvotes: 4
Views: 1533
Reputation: 14710
Considering your comment: 2560X1920. Its big, but I have to find a way to fit it in.. @gunar - I have to show this image to the user before sending it to the server
.
In order to display the image to the user you'll need to resize it first. Follow the famous developer article on how to load&display bitmaps efficiently.
But when doing this, you'll need to take into account the rotation when computing the parameters for width and height (I guess you're using Exif
info).
Sending the big image to server is tricky. I've seen this post about how to rotate big images but I haven't had time to try that out. The idea is to rotate the bitmap matrix in another target bitmap.
However I would suggest to rotate the image on server side, or if you can't make changes on server side because it doesn't belong to you, create a proxy server of your own, send your image to that instance, rotate it there and from there send the rotated image to initial server (by forwarding any data the Android client usually sends).
Upvotes: 1
Reputation: 4095
Before you start optimising, I would make sure you're running out of memory on the actual target devices, rather than simply in the emulator. If it's running fine on the device itself, check your heapSize in your VM scenario. You can also request more memory on devices, via the Manifest, by setting android:largeHeap="true" in the tag. If, after following these steps, you're still running up against device limitations, yup, you'll need to optimise.
It may be that image manipulation is simply too taxing for such a large bitmap on certain devices. I noted that you're planning on sending this to the server. May I then assume that you want the image to be rotated properly for display server-side? If that's the case, you could always do the image-manipulation there, for example with PIL, if you're using Python. Just a thought.
Best of luck.
Upvotes: 0
Reputation: 1067
Rather than allocating a new Bitmap of size 2560 x 1920 each time you rotate, why not hold a reference to a android.graphics.Matrix in the same scope as your ImageView and use image.setScaleType(ScaleType.MATRIX); image.setImageMatrix(matrix);
?
Your rotate method might look like the following:
if (mMatrix == null) {
mMatrix = new Matrix();
}
mMatrix.postRotate(degrees);
mImageView.setImageMatrix(mMatrix);
Upvotes: 0
Reputation: 4041
Please take a look at this related issue, also posted in SO
Looks like some recycle()
calls should be made over the rotated bitmap, so the memory allocated on it gets freed, assuming that the old unrotated version of the bitmap will not be used.
Also take a look at the Bitmap class documentation
Upvotes: 0
Reputation: 2036
Try this when you decode your file
File imgFile = new File("yourPath");
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 10;
Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath(), options);
then you call
rotate(myBitmap,90);
From BitmapFactory.Options docs:
public int inSampleSize
Added in API level 1 If set to a value > 1, requests the decoder to subsample the original image, returning a smaller image to save memory. The sample size is the number of pixels in either dimension that correspond to a single pixel in the decoded bitmap. For example, inSampleSize == 4 returns an image that is 1/4 the width/height of the original, and 1/16 the number of pixels. Any value <= 1 is treated the same as 1. Note: the decoder uses a final value based on powers of 2, any other value will be rounded down to the nearest power of 2.
Hope this helps
Upvotes: 1