2012-05-22 36 views
7

我尝试在“onPictureTaken”旋转图片安卓:旋转高分辨率图像生成内存不足的错误

public void onPictureTaken(byte[] data, Camera camera) { 
    String fileName = "last"+Calendar.getInstance().getTimeInMillis(); 
    String finalFilePath=null; 
    File temp= Environment.getExternalStorageDirectory(); 
    String destination=temp.getAbsolutePath()+"/pictureTest/"; 
    Bitmap bitmap1 = BitmapFactory.decodeByteArray(data, 0, data.length); 
    Matrix mat = new Matrix(); 
    mat.postRotate(90); // degree j'pense que t'as une methode qui te dit de combien tu veux faire t'as rotation. 
    Bitmap bBitmapRotate = Bitmap.createBitmap(bitmap1, 0, 0, bitmap1.getWidth(), bitmap1.getHeight(), mat, true); 
    try { 
     FileOutputStream fos = null; 
     finalFilePath=destination +"/" + fileName + ".jpg"; 
     fos = new FileOutputStream(finalFilePath); 
     BufferedOutputStream bos = new BufferedOutputStream(fos);     
     bBitmapRotate.compress(CompressFormat.JPEG, 80, bos); 
     bos.flush(); 
     bos.close(); 
    } 
    catch (FileNotFoundException e) { 
     e.printStackTrace(); 
    } 
    catch (IOException e) { 
     e.printStackTrace(); 
    } 

如果我使用一个200万像素的照片,它工作正常,但如果我使用的是1200万像素的图片我出现内存不足错误。

05-22 11:08:41.180: D/dalvikvm(29694): GC_FOR_MALLOC freed 674K, 51% free 3015K/6087K, external 18826K/19988K, paused 33ms 
05-22 11:08:41.190: I/dalvikvm-heap(29694): Grow heap (frag case) to 25.641MB for 2070498-byte allocation 
05-22 11:08:41.230: D/dalvikvm(29694): GC_CONCURRENT freed 133K, 40% free 4903K/8135K, external 17940K/19988K, paused 1ms+2ms 
05-22 11:08:41.700: D/dalvikvm(29694): GC_EXTERNAL_ALLOC freed 19K, 40% free 4884K/8135K, external 33575K/35623K, paused 24ms 
05-22 11:08:41.710: E/dalvikvm-heap(29694): 24000000-byte external allocation too large for this process. 
05-22 11:08:41.710: E/GraphicsJNI(29694): VM won't let us allocate 24000000 bytes 
05-22 11:08:41.720: D/dalvikvm(29694): GC_FOR_MALLOC freed <1K, 40% free 4884K/8135K, external 33575K/35623K, paused 14ms 
05-22 11:08:41.720: D/AndroidRuntime(29694): Shutting down VM 
05-22 11:08:41.720: W/dalvikvm(29694): threadid=1: thread exiting with uncaught exception (group=0x2aac8578) 
05-22 11:08:41.720: E/AndroidRuntime(29694): FATAL EXCEPTION: main 
05-22 11:08:41.720: E/AndroidRuntime(29694): java.lang.OutOfMemoryError: bitmap size exceeds VM budget 
05-22 11:08:41.720: E/AndroidRuntime(29694): at android.graphics.Bitmap.nativeCreate(Native Method) 
05-22 11:08:41.720: E/AndroidRuntime(29694): at android.graphics.Bitmap.createBitmap(Bitmap.java:477) 
05-22 11:08:41.720: E/AndroidRuntime(29694): at android.graphics.Bitmap.createBitmap(Bitmap.java:444) 
05-22 11:08:41.720: E/AndroidRuntime(29694): at com.android.cocoatweet.TestTweetPictureActivity.onPictureTaken(TestTweetPictureActivity.java:143) 
05-22 11:08:41.720: E/AndroidRuntime(29694): at android.hardware.Camera$EventHandler.handleMessage(Camera.java:529) 
05-22 11:08:41.720: E/AndroidRuntime(29694): at android.os.Handler.dispatchMessage(Handler.java:99) 
05-22 11:08:41.720: E/AndroidRuntime(29694): at android.os.Looper.loop(Looper.java:138) 
05-22 11:08:41.720: E/AndroidRuntime(29694): at android.app.ActivityThread.main(ActivityThread.java:3701) 
05-22 11:08:41.720: E/AndroidRuntime(29694): at java.lang.reflect.Method.invokeNative(Native Method) 
05-22 11:08:41.720: E/AndroidRuntime(29694): at java.lang.reflect.Method.invoke(Method.java:507) 
05-22 11:08:41.720: E/AndroidRuntime(29694): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:878) 
05-22 11:08:41.720: E/AndroidRuntime(29694): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:636) 
05-22 11:08:41.720: E/AndroidRuntime(29694): at dalvik.system.NativeStart.main(Native Method) 

我试着从相机参数设置“setRotation()”,但它没有做任何事情。

public void onClick(View v) { 
       sendPicturedTweet(); 
      } 
     }); 
    } 

    protected void sendPicturedTweet() { 
     if(camera!=null){ 
      camera.stopPreview(); 
      Camera.Parameters camParams=this.camera.getParameters();    
      List<Size> sizes=camParams.getSupportedPictureSizes(); 
      SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); 
      int prefSize=Integer.parseInt(preferences.getString(getString(R.string.picture_quality_key), "0")); 
      camParams.setPictureSize(sizes.get(prefSize).width, sizes.get(prefSize).height); 
      camParams.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); 
      camParams.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO); 
      camParams.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_AUTO); 
      camParams.setPictureFormat(ImageFormat.JPEG); 
      camParams.setJpegQuality(100); 
      camParams.setRotation(90); 
      camera.setParameters(camParams); 
      try{ 
       this.camera.setPreviewDisplay(surfaceHolder); 
       this.camera.startPreview(); 
       this.camera.takePicture(null, null, null, this); 
      }catch (Exception e) { 
       Log.e(LOG_TAG_VIDEO_PREVIEW, "ERROR IO on set preview display for camera."); 
      } 
     } 

    } 

如何在不出现此错误的情况下旋转大图片并获得最佳图片质量? 这可能吗?

我正在使用Android 2.3.7在索尼Xperia S上工作。

谢谢。

+0

我可以使用Renderscript使其工作吗? – cooler007

回答

1

当到达该行

Bitmap bBitmapRotate = Bitmap.createBitmap(bitmap1, 0, 0, bitmap1.getWidth(), bitmap1.getHeight(), mat, true); 

你已经在存储器中的图像的两倍,如字节[]数据和为位图bitmap1。 我认为你应该找到一种方法来清除字节[]数据试图转换图像(例如,通过直接发送的位图作为参数)

+0

感谢您的回答, 我试图在之后的图像上工作,但后来我甚至无法将它加载到位图中。 – cooler007

1

使用缩小图像的大小之前BitmapFactory.Option

BitmapFactory.Options option = new BitmapFactory.Options(); 
      option.inSampleSize = 2; 
+0

如果我找不到更好的方法,这是一个选项。我需要尽可能最好的质量,如果我明白这一点:如果我缩小图像的尺寸,我也会降低质量。我需要保持12Mp的分辨率。 – cooler007

+0

http://stackoverflow.com/questions/2997703/android-remote-image-getting-problem –

-1

如何:

bitmap1 = Bitmap.createBitmap(bitmap1, 0, 0, bitmap1.getWidth(), bitmap1.getHeight(), mat, true); 

你只有有限的内存来使用,所以当你要处理这么大的图片,你必须要考虑节省你的记忆。

1

您可以使用JNI(使用NDK)来克服android对应用程序施加的最大堆大小限制。

在这种情况下

,你可以做的是:

  1. 传位给JNI功能。
  2. 在JNI函数中,读取位图的字节。
  3. 回收位图。
  4. 创建一个新的位图并将你存储的像素放入它。
  5. 将位图返回给java代码。

如果你愿意,我已经创建了一个示例代码,它做到了,here