2012-05-22 12 views
7

trato de girar una imagen en "onPictureTaken"androide: girar una imagen de alta resolución genera un error de falta de memoria

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

Funciona bien si uso una imagen 2MP, pero si uso una imagen de 12Mp I obtener un error de falta de memoria

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) 

he tratado de establecer el "setRotation()" de los parámetros de la cámara, pero no hizo nada.

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

    } 

¿Cómo puedo girar una imagen grande sin tener este error y tener la mejor calidad de imagen posible? ¿Es posible?

Estoy trabajando en un Sony Xperia S con Android 2.3.7.

Gracias.

+0

¿Puedo usar Renderscript para que funcione? – cooler007

Respuesta

1

Al llegar a esta línea

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

ya tiene la imagen en la memoria dos veces, ya que los datos byte [] y, como bitmap1 de mapa de bits. pienso que usted debe encontrar una manera de borrar los datos de byte [] antes de intentar transformar la imagen (por ejemplo, enviando directamente el mapa de bits como parámetro)

+0

Gracias por su respuesta, He intentado trabajar en la imagen después, pero luego ni siquiera puedo cargarla en un mapa de bits. – cooler007

1

reducir el tamaño de la imagen utilizando BitmapFactory.Option

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

Esta es una opción si no puedo encontrar una mejor manera. Necesito la mejor calidad posible y si entiendo esto bien: si reduzco el tamaño de la imagen, también reduzco la calidad. Necesito mantener la resolución de 12Mp. – cooler007

+0

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

-1

¿Qué tal esto:

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

Has memoria para un uso limitado, así que cuando usted tiene que manejar una imagen tan grande, hay que pensar en guardar su memoria.

1

puede usar JNI (utilizando el NDK) para superar la limitación del tamaño máximo de almacenamiento dinámico que Android impone a las aplicaciones.

en este caso, lo que podría hacer es la siguiente:

  1. pasar el mapa de bits a una función JNI.
  2. en la función JNI, lea los bytes del mapa de bits.
  3. recicle el mapa de bits.
  4. crea un nuevo mapa de bits y coloca los píxeles que almacenaste en él.
  5. devuelve el mapa de bits al código java.

si lo desea, he creado un código de muestra que lo hace, here.

Cuestiones relacionadas