Bitmap fuera de problemas de memoria

Mi problema

Tomo una foto con mi dispositivo Android. Entonces decodifico esa imagen del archivo.

Bitmap photo = BitmapFactory.decodeFile(EXTERNAL_IMAGE_PATH+File.separator+this._currentPhotoName+JPEG_FILE_SUFFIX); if (photo == null && data != null) photo = (Bitmap) data.getExtras().get("data"); else if (data == null && photo == null) Log.e("CCPhotoManager","Can't find image from file or from intent data."); 

A continuación, compruebo que la imagen y ver si es necesario girar a la orientación correcta.

  try { ExifInterface exif = new ExifInterface(EXTERNAL_IMAGE_PATH+File.separator+this._currentPhotoName+JPEG_FILE_SUFFIX); int rotation = CCDataUtils.exifToDegrees(exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,ExifInterface.ORIENTATION_NORMAL)); Log.v("CCPhotoManager", "Rotation:"+rotation); if (rotation > 0) { photo = this.convertSavedImageToCorrectOrientation(EXTERNAL_IMAGE_PATH+File.separator+this._currentPhotoName+JPEG_FILE_SUFFIX, photo, rotation); } } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } 

Si tiene que girar llamo a este método.

 public Bitmap convertSavedImageToCorrectOrientation(String filePath,Bitmap photo,int rotation) { Log.d("CCPhotoManager", "Changing Orientation of photo located at: "+filePath+" Rotating by:"+rotation); int width = photo.getWidth(); int height = photo.getHeight(); Matrix matrix = new Matrix(); matrix.preRotate(rotation); Bitmap adjusted = Bitmap.createBitmap(photo, 0, 0, width, height, matrix, true); try { FileOutputStream out = new FileOutputStream(filePath); adjusted.compress(Bitmap.CompressFormat.JPEG, 100, out); } catch (Exception e) { e.printStackTrace(); } return adjusted; } 

Estoy recibiendo quejas de memoria si se convertSavedImageToCorrectOrientation en la línea Bitmap adjusted = Bitmap.createBitmap(photo,0,0,width,height,matrix,true);

Esto es sólo el caso en el Samsung Galaxy S3 . Funciona bien en el Samsung Galaxy Ace , HTC Hero y el Sony Xperia U

Aquí está el error.

 10-17 14:33:33.950: E/AndroidRuntime(12556): java.lang.OutOfMemoryError 10-17 14:33:33.950: E/AndroidRuntime(12556): at android.graphics.Bitmap.nativeCreate(Native Method) 10-17 14:33:33.950: E/AndroidRuntime(12556): at android.graphics.Bitmap.createBitmap(Bitmap.java:605) 10-17 14:33:33.950: E/AndroidRuntime(12556): at android.graphics.Bitmap.createBitmap(Bitmap.java:551) 

Es una enorme cantidad de memoria también.

 10-17 14:33:33.945: E/dalvikvm-heap(12556): Out of memory on a 31961104-byte allocation. 

Creo que es algo que ver con la cantidad de mapas de bits alrededor, pero no estoy seguro de cómo detener este error de pasar.

Sé que puedes llamar .recycle(); En ellos, pero no parece funcionar.

Mi pregunta

¿Cómo manejo correctamente mis mapas de bits para que no tenga este problema de MOO?

Gracias por adelantado

Para problemas de memoria insuficiente

// decodifica la imagen y la escala para reducir el consumo de memoria

 private Bitmap decodeFile(File f){ try { //Decode image size BitmapFactory.Options o = new BitmapFactory.Options(); o.inJustDecodeBounds = true; BitmapFactory.decodeStream(new FileInputStream(f),null,o); //The new size we want to scale to final int REQUIRED_SIZE=70; //Find the correct scale value. It should be the power of 2. int scale=1; while(o.outWidth/scale/2>=REQUIRED_SIZE && o.outHeight/scale/2>=REQUIRED_SIZE) scale*=2; //Decode with inSampleSize BitmapFactory.Options o2 = new BitmapFactory.Options(); o2.inSampleSize=scale; return BitmapFactory.decodeStream(new FileInputStream(f), null, o2); } catch (FileNotFoundException e) {} return null; } 

Este es un ejemplo más completo de cómo redimensionar / rotar, tomado en parte de la guía de desarrolladores de Android (cambiar REQ_WIDTH y REQ_HEIGHT):

 private static final int REQ_WIDTH = 450; private static final int REQ_HEIGHT = 450; /** * Resize, crop, rotate and Inserts the picture on the layout. * * @param mImageView to insert the bitmap. * @param imageURI from wich to obtain the bitmap. * */ private void setPic(ImageView mImageView, String imageURI) { // Get the original bitmap dimensions BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(imageURI, options); // Calculate inSampleSize options.inSampleSize = calculateInSampleSize(options, REQ_HEIGHT, REQ_WIDTH); // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; Bitmap bitmap = BitmapFactory.decodeFile(imageURI, options); //need rotation? float rotation = rotationForImage(getActivity(), Uri.fromFile(new File(imageURI))); if (rotation != 0) { //rotate Matrix matrix = new Matrix(); matrix.preRotate(rotation); mImageView.setImageBitmap(Bitmap.createBitmap(bitmap, 0, 0, REQ_HEIGHT, REQ_WIDTH, matrix, true)); } else { //use the original mImageView.setImageBitmap(BitmapFactory.decodeFile(imageURI, options)); } } public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { // Raw height and width of image final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { if (width > height) { inSampleSize = Math.round((float) height / (float) reqHeight); } else { inSampleSize = Math.round((float) width / (float) reqWidth); } } return inSampleSize; } public static float rotationForImage(Context context, Uri uri) { try { if (uri.getScheme().equals("content")) { String[] projection = { Images.ImageColumns.ORIENTATION }; Cursor c = context.getContentResolver().query(uri, projection, null, null, null); if (c.moveToFirst()) { return c.getInt(0); } } else if (uri.getScheme().equals("file")) { ExifInterface exif = new ExifInterface(uri.getPath()); int rotation = (int) exifOrientationToDegrees(exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)); return rotation; } return 0; } catch (IOException e) { Log.e(TAG, "Error checking exif", e); return 0; } } private static float exifOrientationToDegrees(int exifOrientation) { if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_90) { return 90; } else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_180) { return 180; } else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_270) { return 270; } return 0; } 

Yo tenía exactamente el mismo problema, haciendo exactamente lo mismo en el mismo dispositivo! Desafortunadamente en mi caso la imagen necesitaba ser enviada a un webservice, usando el tamaño completo, original. Lo que funcionó para mí fue activar largeHeap en el elemento de aplicación del manifiesto.

Esto no solucionará el problema permanentemente – es posible que un dispositivo vaya junto con una cámara aún más grande y las imágenes no encajarán en la memoria incluso con la función grande habilitada. Para capturar este caso extrema borde también puse un try catch alrededor del código que gira la imagen, y acaba de mostrar un error agradable para el usuario.

Una solución más completa sería escribir su propio código de manipulación jpeg que puede rotar un jpeg utilizando un enfoque basado en la secuencia de modo que la imagen nunca necesita ser cargado en la memoria.

  • Cámara en Android
  • Android: camera onPause / onResume issue
  • Compruebe si el dispositivo tiene una cámara?
  • Camera.open () devuelve NULL Android desarrollo
  • Android 2.3.4 se bloquea en Camera.setParameters
  • Opengl fondo transparente y Vista previa de cámara no les gusta texturing
  • ¿No puede acceder a la cámara genymotion?
  • CameraDevice no puede crear sesión
  • La vista previa de la cámara Android es oscura
  • Cámara predeterminada para tomar una foto en android
  • Camera.open () no funciona android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.