图像裁剪并在Android中调整大小

时间:2011-04-09 02:14:31

标签: android image

我按照以下说明裁剪图像。

http://coderzheaven.com/index.php/2011/03/crop-an-image-in-android/

最终裁剪的位图图像的高度和宽度都大于屏幕的高度和宽度。

在调整大小和裁剪过程中,抛出内存不足错误并强制退出应用程序。

错误日志:

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): java.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)

有谁知道如何解决这个问题?

感谢。

==

更新:我解决了这个问题。

8 个答案:

答案 0 :(得分:14)

您可以使用可以解决问题的以下代码来使用裁剪图像。

Matrix matrix = new Matrix();
matrix.postScale(0.5f, 0.5f);
Bitmap croppedBitmap = Bitmap.createBitmap(bitmapOriginal, 100, 100,100, 100, matrix, true);

上面的方法在裁剪之前做postScalling图像,这样你可以获得裁剪图像的最佳效果而不会出现OOM错误。

有关详细信息,请参阅this blog

答案 1 :(得分:8)

我的同事只是让我熟悉这个Android API ...请参阅ThumbnailUtils。

它会为您调整大小和裁剪。

http://developer.android.com/reference/android/media/ThumbnailUtils.html#extractThumbnail(android.graphics.Bitmap,int,int)

答案 2 :(得分:2)

如果您的代码与示例不同,则必须将其发布以获得准确的帮助。否则,仅基于日志 - 这是一个答案:

在您使用的示例中,开发人员正在将应用程序资源文件夹(可能相对较小的图像)裁剪为300x300位图图像。首先,尝试在您自己的应用中裁剪较小尺寸的图像,缩小输出尺寸,以查看代码是否存在问题,或者您使用的图像对于您的代码或设备来说太大了。

由于您说的是裁剪的最终图像比屏幕大,这可能是问题所在,并且您遇到了在Android中使用位图的基本挑战。位图文件大小是像素宽度乘以高度的函数 - 它们变得更快。

您可以通过Google搜索日志的其他部分来解决,例如“位图大小超过VM预算”,您将在stackoverflow上找到几个有用的线程,就像这个一样。

Strange out of memory issue while loading an image to a Bitmap object

您可以使用位图选项和inSampleSize以及其他技术来解决它。

答案 3 :(得分:1)

查看类似的讨论here,它们似乎有同样的byte external allocation too large for this process错误。

答案 4 :(得分:1)

我进一步验证了以下说明。

http://coderzheaven.com/index.php/2011/03/crop-an-image-in-android/

我发现代码不够好,有些代码是多余的。

要裁剪大位图图像,不需要使用矩阵来完成任务。

只需使用canvas.drawBitmap方法即可裁剪大图片!

也无需触摸BitmapFactory.Options。

现在我简单地裁剪图像并让imageview调整大小。没有更多的内存不足错误。答对了 !

答案 5 :(得分:1)

04-09 11:37:28.708:ERROR / AndroidRuntime(4003):at com.test.Test.onCreate(Test.java:57)

如果我没记错的话,

class Test extends Activity ....
第57行

,你有

Bitmap bitmapOrg = BitmapFactory.decodeResource(getResources(),R.drawable.image);

如果是这样,引用的图像是如此之大,以至于当Android尝试将其解码为位图时,它会占用所有空闲的VM堆并抛出错误。您无法使用

解码大位图
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;
}

我从user699618推荐的链接中复制了代码,我之前使用过它,它解决了这个问题。)

之后,您可以在CENTER_CROP上使用ImageView.setScaleType()或其他任何内容。

您可以在here中找到“比例类型”选项,在hete中找到setScaleType详细信息。

希望这有帮助。

我还建议不要在资源上有这么重的照片。在将它们保存在resorce forder中之前,先将它们缩小。

答案 6 :(得分:1)

//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);

答案 7 :(得分:0)

    //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);

我希望有用