returns outofmemoryerror outofmemory example decodefile decodebytearray bitmaps android bitmap bitmapfactory

outofmemoryerror - bitmaps android



Uso óptimo de BitmapFactory.Options.inSampleSize para la velocidad (3)

Gracias a Schermvlieger por hacer this pregunta en anddev.org ,

Solo copio su pregunta a SO, ya que nadie respondió en el otro sitio y también tengo el mismo problema.

Me preguntaba cuál sería el uso óptimo de BitmapFactory.Options.inSampleSize con respecto a la velocidad de visualización de la imagen.
La documentación menciona el uso de valores que son una potencia de 2, por lo que estoy trabajando con 2, 4, 8, 16, etc.

Las cosas que me pregunto son:

  1. ¿Debo volver a muestrear hasta el tamaño más pequeño que aún sea más grande que la resolución de la pantalla, o debo muestrear hasta el tamaño lo suficiente como para evitar un OutOfMemoryError ?
  2. ¿Cómo se podría calcular el tamaño máximo de una imagen que aún podría visualizarse sin quedarse sin memoria? ¿La profundidad de color de la imagen también juega un papel, y la profundidad de la pantalla?
  3. ¿Es eficiente mostrar imágenes a través de dos mecanismos ( BitmapFactory para archivos grandes, setImageURI() para los más pequeños)? Estoy usando un ImageSwitcher por cierto.
  4. ¿ BitmapFactory.Options crear Bitmap , BitmapFactory.Options e inTempStorage al principio de la aplicación o crearlos solo sobre la marcha, cuando sea necesario?

Aquí puede llamar al método shrinkmehtod definido por el usuario que en realidad envía la ruta del archivo de cadena y la altura y el ancho para reducir la imagen al método.

Bitmap bit=shrinkmethod(arrpath1[position], 100, 100); //iv.setImageURI(Uri.parse(arrpath1[position])); iv.setImageBitmap(bit);

Este es un método definido por el usuario para reducir el tamaño de la imagen mediante programación.

Bitmap shrinkmethod(String file,int width,int height){ BitmapFactory.Options bitopt=new BitmapFactory.Options(); bitopt.inJustDecodeBounds=true; Bitmap bit=BitmapFactory.decodeFile(file, bitopt); int h=(int) Math.ceil(bitopt.outHeight/(float)height); int w=(int) Math.ceil(bitopt.outWidth/(float)width); if(h>1 || w>1){ if(h>w){ bitopt.inSampleSize=h; }else{ bitopt.inSampleSize=w; } } bitopt.inJustDecodeBounds=false; bit=BitmapFactory.decodeFile(file, bitopt); return bit; }

Espero que esto te ayude a reducir el tamaño.


Has hecho buenas preguntas, pero todo depende de tus necesidades y de la cantidad de memoria que utilices. Recomiendo consultar este enlace para obtener muchos consejos sobre mapas de bits: http://developer.android.com/training/displaying-bitmaps/index.html .

En resumen, debe considerar el almacenamiento en caché, la reducción de muestreo y el uso de un formato de mapa de bits lo suficientemente bueno siempre que pueda.

Aquí están mis respuestas a sus preguntas:

  1. ¿Por qué no ambos? Si cree que puede haber OOM, intente reciclar los mapas de bits no utilizados y luego vuelva a verificar.

  2. Puede calcular el tamaño (estimado) del mapa de bits:

    ancho * altura * bytesPerPixel

    donde bytesPerPixel suele ser 4 o 2 (dependiendo del formato de mapa de bits).

  3. Nunca usé setImageURI, así que no puedo ayudarte con eso. Sugiero descargar imágenes en un hilo de fondo (usar asyncTask es una forma de hacerlo) y mostrarlas cuando esté listo.

  4. Si solo hay unos pocos que sabes que no ocuparán gran parte de la memoria, supongo que está bien. Sigo pensando que el caché podría ser mejor.


Siempre debe intentar cargar y realizar una escala previa de las imágenes para que estén lo más cerca posible del tamaño final mostrado. El escalado de imágenes en tiempo de dibujo es extremadamente costoso y debe evitarse a toda costa.

Teniendo en cuenta el costo de memoria de una imagen, sí, el departamento de color juega un papel muy importante. Las imágenes en formato ALPHA_8 utilizan 1 byte por píxel, las imágenes en RGB_565 o ARGB_4444 usan 2 bytes por píxel y las imágenes en ARGB_8888 usan 4 bytes por píxel. La profundidad de la pantalla no importa en absoluto. Siempre debe intentar utilizar ARGB_8888 para obtener la mejor calidad posible, pero 565 puede ser lo suficientemente bueno si su imagen es opaca.