OutOfMemory尝试在imageview内旋转图像时出错

时间:2013-08-29 20:20:36

标签: java android bitmap android-imageview out-of-memory

我试图在imageView中旋转图像,并使用相同的图像旋转位图。

(我需要那个位图,因为我稍后将图像发送到服务器)

代码:

image.setOnClickListener(new OnClickListener() {
    public void onClick(View view) {
        mPhoto=rotate(mPhoto,90);
        image.setImageBitmap(mPhoto); 
    }
});

rotate()方法:

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)

希望你能帮助我。

泰!

5 个答案:

答案 0 :(得分:1)

解码文件时尝试此操作

File imgFile = new File("yourPath");
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 10;
Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath(), options);

然后你打电话

rotate(myBitmap,90);

来自BitmapFactory.Options docs:

public int inSampleSize

在API级别1中添加 如果设置为值>如图1所示,请求解码器对原始图像进行二次采样,返回较小的图像以节省存储器。样本大小是任一维度中对应于解码位图中的单个像素的像素数。例如,inSampleSize == 4返回的图像是原始宽度/高度的1/4,像素数量的1/16。任何值< = 1都被视为1.注意:解码器使用基于2的幂的最终值,任何其他值将向下舍入到最接近的2的幂。

希望这有帮助

答案 1 :(得分:1)

考虑您的评论: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

要向用户显示图像,您需要先调整大小。关于如何有效加载和显示位图,请关注the famous developer article

但是在执行此操作时,您需要在计算宽度和高度参数时考虑旋转(我猜您使用的是Exif信息)。

将大图像发送到服务器很棘手。我见过关于如何旋转大图像的this post,但我没有时间试试。想法是在另一个目标位图中旋转位图矩阵。

但是我建议在服务器端轮换图像,或者如果你不能在服务器端进行更改,因为它不属于你,请创建自己的代理服务器,将图像发送到该实例,在那里旋转并从那里将旋转的图像发送到初始服务器(通过转发Android客户端通常发送的任何数据)。

答案 2 :(得分:0)

请查看this related issue,也发布在SO

看起来应该对旋转的位图进行一些recycle()调用,因此在其上分配的内存将被释放,假设将不使用旧的未旋转版本的位图。

另请查看Bitmap class documentation

答案 3 :(得分:0)

为什么不在与android.graphics.Matrix相同的范围内保留对ImageView的引用并使用image.setScaleType(ScaleType.MATRIX); image.setImageMatrix(matrix);,而不是在每次旋转时分配大小为2560 x 1920的新位图?

您的旋转方法可能如下所示:

if (mMatrix == null) {
    mMatrix = new Matrix();
}
mMatrix.postRotate(degrees);
mImageView.setImageMatrix(mMatrix);

答案 4 :(得分:0)

在开始优化之前,我会确保您在实际目标设备上耗尽内存,而不是仅仅在模拟器中。如果它在设备上运行正常,请检查VM方案中的heapSize。您还可以通过Manifest在设备上请求更多内存,方法是在标签中设置android:largeHeap =“true”。如果在执行这些步骤后,您仍然遇到设备限制,那么您需要进行优化。

对于某些设备上的如此大的位图,图像处理可能过于繁琐。我注意到您计划将其发送到服务器。我可以假设您希望图像在显示服务器端正确旋转吗?如果是这种情况,你可以随时在那里进行图像处理,例如使用PIL,如果你使用的是Python。只是一个想法。

祝你好运。