how - Android Bitmap cargando de memoria error Galaxy S3 WXGA
bitmaps android (1)
Estaría muy agradecido si alguien pudiera confirmar que he resuelto el problema de abajo correctamente o si hay una solución alternativa.
Tengo una aplicación que carga una imagen grande (por ejemplo, 800 * 1720 píxeles) en la memoria y la muestra en una vista de desplazamiento. La imagen es un plano de planta para un museo y quería un mapa simple como la experiencia de desplazamiento y zoom. La imagen se cargó correctamente en dispositivos antiguos, pero causó un error de falta de memoria en un Samsung Galaxy S3.
Al observar los mensajes de LogCat, resultó que al crear el mapa de bits se asignaron 22 MB para el mapa de bits en lugar de 800 * 1720 * 4 = 5,5 MB. Esencialmente, se asignó 4 veces la cantidad de memoria que requerían otros dispositivos y el uso de la memoria sobre el tamaño del montón de 50 MB.
La solución recomendada para este problema es usar la opción BitmapFactory.Options.inSampleSize
para reducir la resolución de la imagen cargada y hacer que requiera menos memoria. Sin embargo, esto reduce la calidad de la imagen, y realmente quiero mostrarla en su tamaño completo en la calidad original, ya que funciona bien en dispositivos más antiguos.
Después de rascarse mucho la cabeza, llegué a la conclusión de que el problema era que la densidad de píxeles en las pantallas WXGA del S3 es de 2.0 y, por lo tanto, para cada píxel de la imagen, el mapa de bits estaba asignando 4 píxeles. Con un poco de prueba y error descubrí que podía evitar que esto sucediera configurando options.inScaled = false;
http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html#inScaled
En el camino, también me di cuenta de que podía reducir mi uso de memoria a la mitad a 2,7 MB usando una profundidad de color de fidelidad inferior de 2 píxeles en lugar de 4 píxeles configurando options.inPreferredConfig = Bitmap.Config.RGB_565;
. Para mis cubiertas de piso esto no afectó la calidad de imagen visible.
El código final fue así:
String uri = "drawable/floorplan";
int imageResource = getResources().getIdentifier(uri, null, getPackageName());
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
options.inScaled = false;
Bitmap bm = BitmapFactory.decodeResource(getResources(), imageResource, options);
IVfloorplan.setImageBitmap(bm);
Cuando se muestra este mapa de bits, es necesario escalarlo de nuevo. Para calcular la escala, puede obtener la densidad de píxeles de:
float density = getResources().getDisplayMetrics().density;
Reduje el uso de memoria para el mapa de bits de 22 MB a 2,7 MB, lo que en un montón de 50 MB es significativo.
La pantalla del S3 tiene una resolución realmente alta, por lo que es bastante comprensible. Además, si la imagen está en la carpeta que se puede dibujar, es posible que se la actualice automáticamente. Puede haber maneras de apagar eso. Incluso si el tamaño de su imagen no es casual, el sistema operativo tiene que asignar un búfer para acomodar la imagen, posiblemente también uno para que se muestre en la pantalla.
Una alternativa es usar mosaico, que se usa en juegos como los juegos de SNES. También es así como manejaron muchos gráficos sin quedarse sin RAM. La evidencia muestra que así es como Google Maps tiene un mapa del planeta Tierra. Básicamente, se corta la imagen grande en mosaicos y se muestran los mosaicos en la pantalla a medida que se realiza una panorámica (por supuesto, tal vez 1 mosaico adicional en cada lado).
Aunque esto es posterior a Honeycomb, donde Google ingresa un código para administrar mejor las asignaciones de mapas de bits, tenga cuidado con la asignación de mapas de bits. Es más parecido a un programa C que a un programa Java, y es una buena idea gestionarlo como tal. Es muy fácil quedarse sin espacio de almacenamiento cuando se utilizan objetos de mapa de bits en Android