【问题标题】:Image crop and resize in AndroidAndroid中的图像裁剪和调整大小
【发布时间】:2011-08-01 22:16:19
【问题描述】:

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

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)

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

谢谢。

======

更新:我解决了问题。

【问题讨论】:

  • 发布错误,显示一些代码!如果我们不知道问题出在哪里,我们应该如何提供帮助!!!!
  • 错误是应用强制退出。
  • 运行 'adb logcat AndroidRuntime:* *:S' 获取崩溃日志。将其与您的代码一起发布,我们可以提供帮助。

标签: android image


【解决方案1】:

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

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

【讨论】:

【解决方案2】:

我的同事刚刚向我介绍了这个 Android API...请参阅 ThumbnailUtils。

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

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

【讨论】:

  • 正在寻找那个!
【解决方案3】:

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

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

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

您可以通过谷歌搜索日志的其他部分来解决问题,例如“位图大小超出 VM 预算”,并且您会在 stackoverflow 上找到几个有用的线程,例如这个。

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

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

【讨论】:

    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

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

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

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

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

      只要使用canvas.drawBitmap方法就可以裁剪大图!

      也无需触摸 BitmapFactory.Options。

      现在我只是裁剪图像并让 imageview 调整它的大小。不再出现内存不足错误。答对了 !

      【讨论】:

        【解决方案6】:

        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_CROPImageView.setScaleType() 上所需的任何内容。

        您可以在here 中找到Scale Type 选项,在hete 中找到setScaleType 详细信息。

        希望这会有所帮助。

        我还建议不要在资源中包含如此大量的图片。在将它们保存到资源库之前将它们缩小。

        【讨论】:

          【解决方案7】:
          //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);
          

          【讨论】:

            【解决方案8】:
                //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);
            

            希望对你有用

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2011-06-02
              • 1970-01-01
              • 1970-01-01
              • 2011-11-11
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多