2012-05-22 33 views
7

tôi cố gắng xoay một hình ảnh trong "onPictureTaken"android: xoay một hình ảnh độ phân giải cao tạo ra một số lỗi bộ nhớ

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(); 
    } 

Nó hoạt động tốt nếu tôi sử dụng một hình ảnh 2 Mpx nhưng nếu tôi sử dụng một hình ảnh 12MP tôi có được một lỗi bộ nhớ.

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) 

Tôi đã cố gắng đặt "setRotation()" từ thông số máy ảnh nhưng không làm gì cả.

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."); 
      } 
     } 

    } 

Làm cách nào để xoay ảnh lớn mà không gặp phải lỗi này và có chất lượng hình ảnh tốt nhất có thể? Có thể không?

Tôi đang làm việc trên Sony Xperia S với Android 2.3.7.

Cảm ơn.

+0

tôi có thể sử dụng Renderscript để làm cho nó hoạt động không? – cooler007

Trả lời

1

Khi bạn đạt đến dòng này

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

bạn đã có hình ảnh trong bộ nhớ gấp đôi, như byte [] data và như Bitmap bitmap1. Tôi nghĩ rằng bạn nên tìm một cách để xóa byte [] data trước khi bạn cố gắng để thay đổi hình ảnh (ví dụ như bằng cách gửi trực tiếp bitmap như tham số)

+0

Cảm ơn câu trả lời của bạn, Tôi đã cố gắng làm việc trên hình ảnh sau đó nhưng sau đó tôi thậm chí không thể tải nó trong một Bitmap. – cooler007

1

giảm kích thước của hình ảnh sử dụng BitmapFactory.Option

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

Đây là một tùy chọn nếu tôi không thể tìm được cách tốt hơn. Tôi cần chất lượng tốt nhất có thể và nếu tôi hiểu điều này đúng: nếu tôi giảm kích thước của hình ảnh, tôi cũng giảm chất lượng. Tôi cần phải giữ độ phân giải 12Mp. – cooler007

+0

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

-1

Làm thế nào về điều này:

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

bạn đã nhớ để sử dụng hạn chế, vì vậy khi bạn phải xử lý hình ảnh để lớn hơn, bạn phải suy nghĩ tiết kiệm bộ nhớ của bạn.

1

bạn có thể sử dụng JNI (sử dụng NDK) để khắc phục giới hạn kích thước heap tối đa mà android áp đặt trên ứng dụng.

trong trường hợp này, những gì bạn có thể làm như sau:

  1. vượt qua bitmap để một hàm JNI.
  2. trong hàm JNI, đọc các byte của bitmap.
  3. tái chế bitmap.
  4. tạo bitmap mới và đặt các pixel bạn đã lưu vào đó.
  5. trả về bitmap cho mã java.

nếu bạn muốn, tôi đã tạo mã mẫu thực hiện nó, here.

Các vấn đề liên quan