Cargar muchas imágenes de mapa de bits grandes como miniaturas – Android

Estoy trabajando en una aplicación de reproductor de medios y deseo cargar imágenes de álbum para mostrar en un ListView. En este momento funciona bien con las imágenes que estoy descargando automáticamente desde last.fm que están bajo 500×500 png. Sin embargo, recientemente he añadido otro panel a mi aplicación que permite ver obras de arte de pantalla completa, así que he reemplazado algunas de mis obras de arte con grandes (1024×1024) png en su lugar.

Ahora, cuando me desplazo varios álbumes con obras de arte de alta resolución, obtengo un java.lang.OutOfMemoryError en mi BitmapFactory.

static public Bitmap getAlbumArtFromCache(String artist, String album, Context c) { Bitmap artwork = null; File dirfile = new File(SourceListOperations.getAlbumArtPath(c)); dirfile.mkdirs(); String artfilepath = SourceListOperations.getAlbumArtPath(c) + File.separator + SourceListOperations.makeFilename(artist) + "_" + SourceListOperations.makeFilename(album) + ".png"; File infile = new File(artfilepath); try { artwork = BitmapFactory.decodeFile(infile.getAbsolutePath()); }catch(Exception e){} if(artwork == null) { try { artwork = BitmapFactory.decodeResource(c.getResources(), R.drawable.icon); }catch(Exception ex){} } return artwork; } 

¿Hay algo que pueda agregar para limitar el tamaño del objeto Bitmap resultante a decir, 256×256? Eso es lo más grande que las miniaturas deben ser y podría hacer una función duplicada o un argumento para obtener las ilustraciones de tamaño completo para mostrar la pantalla completa.

Además, estoy mostrando estos mapas de bits en ImageViews que son pequeños, alrededor de 150×150 a 200×200. Las imágenes más pequeñas bajan más allá de las grandes. ¿Hay alguna manera de aplicar un filtro downscaling para suavizar la imagen (anti-aliasing quizás)? No quiero almacenar en caché un montón de archivos de miniaturas adicionales si no tengo que hacerlo, ya que haría más difícil gestionar las imágenes de las obras de arte (actualmente sólo se pueden descargar nuevas en el directorio y se utilizarán automáticamente la próxima vez Se cargan).

El código completo está en http://github.org/CalcProgrammer1/CalcTunes , en src / com / calcprogrammer1 / calctunes / AlbumArtManager.java, aunque no hay mucho diferente en la otra función (que se remonta a chequear last.fm si el Falta la imagen).

Utilizo esta función privada para configurar el tamaño que quiero para mis miniaturas:

 //decodes image and scales it to reduce memory consumption public static Bitmap getScaledBitmap(String path, int newSize) { File image = new File(path); BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; options.inInputShareable = true; options.inPurgeable = true; BitmapFactory.decodeFile(image.getPath(), options); if ((options.outWidth == -1) || (options.outHeight == -1)) return null; int originalSize = (options.outHeight > options.outWidth) ? options.outHeight : options.outWidth; BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inSampleSize = originalSize / newSize; Bitmap scaledBitmap = BitmapFactory.decodeFile(image.getPath(), opts); return scaledBitmap; } 
  public static Bitmap decodeSampledBitmapFromFile(String path, int reqWidth, int reqHeight) { // First decode with inJustDecodeBounds=true to check dimensions final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(path, options); // Calculate inSampleSize options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; return BitmapFactory.decodeFile(path, 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) { // Calculate ratios of height and width to requested height and width final int heightRatio = Math.round((float) height / (float) reqHeight); final int widthRatio = Math.round((float) width / (float) reqWidth); // Choose the smallest ratio as inSampleSize value, this will guarantee // a final image with both dimensions larger than or equal to the // requested height and width. inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; } return inSampleSize; } 

Adaptado de http://developer.android.com/training/displaying-bitmaps/load-bitmap.html pero para usar cargas de archivos en lugar de recursos. He añadido una opción de miniatura como tal:

  //Checks cache for album art, if it is not found return default icon static public Bitmap getAlbumArtFromCache(String artist, String album, Context c, boolean thumb) { Bitmap artwork = null; File dirfile = new File(SourceListOperations.getAlbumArtPath(c)); dirfile.mkdirs(); String artfilepath = SourceListOperations.getAlbumArtPath(c) + File.separator + SourceListOperations.makeFilename(artist) + "_" + SourceListOperations.makeFilename(album) + ".png"; File infile = new File(artfilepath); try { if(thumb) { artwork = decodeSampledBitmapFromFile(infile.getAbsolutePath(), 256, 256); } else { artwork = BitmapFactory.decodeFile(infile.getAbsolutePath()); } 

La respuesta de Yoann parece bastante similar y es un poco más condensada, podría usar esa solución en su lugar, pero esa página tenía una buena información sobre BitmapFactory.

Una forma de hacerlo sería la biblioteca AQuery .

Esta es una biblioteca que te permite cargar imágenes de forma lenta desde tu almacenamiento local o una url. Con soporte para cosas como almacenamiento en caché y reducción de escala.

Ejemplo de carga perezosa de un recurso sin la reducción de escala:

 AQuery aq = new AQuery(mContext); aq.id(yourImageView).image(R.drawable.myimage); 

Ejemplo de carga perezosa de una imagen en un objeto File con downscaling:

  InputStream ins = getResources().openRawResource(R.drawable.myImage); BufferedReader br = new BufferedReader(new InputStreamReader(ins)); StringBuffer sb; String line; while((line = br.readLine()) != null){ sb.append(line); } File f = new File(sb.toString()); AQuery aq = new AQuery(mContext); aq.id(yourImageView).image(f,350); //Where 350 is the width to downscale to 

Ejemplo de cómo descargar desde una url con caché de memoria local, almacenamiento en caché local y redimensionamiento.

 AQuery aq = new AQuery(mContext); aq.id(yourImageView).image(myImageUrl, true, true, 250, 0, null); 

Esto iniciará una descarga asíncrona de la imagen en myImageUrl , la redimensionará a un ancho de 250 y la almacenará en caché en memoria y almacenamiento. yourImageView mostrará la imagen en yourImageView . Siempre que la imagen de myImageUrl haya sido descargada y almacenada en caché antes, esta línea de código cargará la almacenada en caché en la memoria o almacenamiento en su lugar.

Normalmente estos métodos se llaman en el método getView de un adaptador de lista.

Para obtener una documentación completa sobre las capacidades de carga de imágenes de AQuery, puede consultar la documentación .

Esto se hace fácilmente con droidQuery :

 final ImageView image = (ImageView) findViewById(R.id.myImage); $.ajax(new AjaxOptions(url).type("GET") .dataType("image") .imageHeight(256)//set the output height .imageWidth(256)//set the output width .context(this) .success(new Function() { @Override public void invoke($ droidQuery, Object... params) { $.with(image).val((Bitmap) params[0]); } }) .error(new Function() { @Override public void invoke($ droidQuery, Object... params) { droidQuery.toast("could not set image", Toast.LENGTH_SHORT); } })); 

También puede almacenar en caché las respuestas utilizando los métodos cache y cacheTimeout .

  • Fuera de memoria en una asignación 9830416-byte con mapa de bits
  • Repita la imagen con ImageView en RelativeLayout
  • Encuentra la posición de un mapa de bits en la vista de imagen de Android cuando la vista de contenedor se escala centerInside
  • Cómo cambiar el tamaño de la imagen (mapa de bits) a un tamaño determinado?
  • Retraso en la demostración de uso de la imagen mapa de bits en android
  • Obtención de mapa de bits de vector dibujable
  • Cómo obtener el mapa de bits que proporciona un URI, java.io.FileNotFoundException: No hay proveedor de contenido: /sdcard/Hello/1310610722879.jpg
  • MediaStore.Images.Media.getBitmap y fuera de error de memoria
  • ¿Hay una manera de cargar y dibujar parcialmente un mapa de bits de archivo en Android?
  • Android: cómo convertir matriz de bytes a mapa de bits?
  • Cómo capturar el error 'Bitmap demasiado grande para ser cargado en una textura'
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.