简体   繁体   English

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

[英]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/ 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): 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)

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. 上面的方法在裁剪之前做postScalling图像,这样你可以获得裁剪图像的最佳效果而不会出现OOM错误。

For more detail you can refer this blog 有关更多详细信息,请参阅此博客

My co-worker just hipped me to this Android API... see ThumbnailUtils. 我的同事让我熟悉这个Android API ...请参阅ThumbnailUtils。

It does resizing and cropping for you. 它会为您调整大小和裁剪。

http://developer.android.com/reference/android/media/ThumbnailUtils.html#extractThumbnail(android.graphics.Bitmap , int, int) 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. 在您使用的示例中,开发人员正在将应用程序资源文件夹(可能相对较小的图像)中的图像裁剪为300x300位图图像。 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. 因为你说最后的图像你正在裁剪比屏幕更大,这可能是问题,你遇到了在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. 您可以通过Google搜索日志的其他部分来解决,例如“位图大小超过VM预算”,您将在stackoverflow上找到几个有用的线程,就像这个一样。

Strange out of memory issue while loading an image to a Bitmap object 将图像加载到Bitmap对象时出现奇怪的内存不足问题

You may solve it by using bitmap options and inSampleSize, and other techniques. 您可以使用位图选项和inSampleSize以及其他技术来解决它。

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

看看here类似的讨论,他们似乎有相同的byte external allocation too large for this process错误byte external allocation too large for this process

I further verified the following instructions. 我进一步验证了以下说明。

http://coderzheaven.com/index.php/2011/03/crop-an-image-in-android/ 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 ! 只需使用canvas.drawBitmap方法即可裁剪大图!

Also no need to touch the BitmapFactory.Options. 也无需触摸BitmapFactory.Options。

Now I simply crop the image and let the imageview resize it. 现在我简单地裁剪图像并让imageview调整大小。 No more out-of-memory error. 没有更多的内存不足错误。 Bingo ! 答对了 !

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 com.test.Test.onCreate(Test.java:57)

If I'm not mistaken, in 如果我没有记错的话

class Test extends Activity ....

on line 57, you have 在第57行,你有

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. 如果是这样,引用的图像是如此之大,以至于当Android尝试将其解码为位图时,它会占用所有空闲的VM堆并抛出错误。 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). 我从user699618推荐的链接中复制了代码,我之前使用过它,它解决了问题)。

After that you can just use CENTER_CROP or whatever you need on ImageView.setScaleType() . 之后,您可以在ImageView.setScaleType()上使用CENTER_CROP或任何您需要的东西。

You can find the Scale Type options in here and setScaleType details in hete . 您可以在此处找到“缩放类型”选项,并在hete找到 setScaleType详细信息。

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. 在将它们保存在resorce forder中之前,将它们缩小。

    //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 我希望有用

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM