Cargue imágenes grandes con Picasso y objeto Transform personalizado
Frecuentes
Visto 25,280 equipos
23
Obtengo una excepción de falta de memoria usando Picasso cuando cargo imágenes "grandes" (> 1.5 MB) de la Galería de Android (usando startActivityForResult).
Estoy usando un objeto de destino personalizado porque necesito preprocesar el mapa de bits cuando esté listo y también estoy usando un objeto de transformación personalizado para escalar el mapa de bits.
El problema es que el método public Bitmap transform(Bitmap source)
en mi objeto Transform nunca se llama debido a la Excepción de falta de memoria, por lo que no tengo la oportunidad de volver a muestrear la imagen.
Pero, si uso el .resize(maxWidth, maxHeight)
método, luego carga la imagen OK. Supuse que el objeto Transform también era para ese propósito, pero parece que el método de transformación se llama después del cambio de tamaño y, si no llamo al cambio de tamaño, terminará en Sin memoria.
El problema es que con el cambio de tamaño necesito especificar tanto el ancho como el alto, pero necesito escalar y mantener la relación de aspecto.
Tenga en cuenta que las imágenes se seleccionarán de la Galería del usuario, por lo que pueden ser más grandes o más pequeñas, verticales, cuadradas u horizontales, etc., por lo que necesito mi propio objeto de Transformación para realizar la lógica que necesita mi aplicación.
2 Respuestas
58
Encontré una solución..
En mi objeto Transform, necesitaba escalar la imagen (manteniendo la relación de aspecto) a 1024 x 768 máx.
El objeto de transformación nunca se llamó a menos que llame .resize(width, height)
para volver a muestrear la imagen.
Para mantener la relación de aspecto y usar el cambio de tamaño, llamo .centerInside()
. De esta manera, la imagen se escalará de nuevo para ajustarse al ancho, alto).
El valor que le doy a .resize(ancho, alto) es Math.ceil(Math.sqrt(1024 * 768))
. De esta manera, estoy seguro de tener una imagen lo suficientemente alta para mi objeto de transformación personalizado, y también evitar la excepción de falta de memoria.
Actualización: ejemplo completo
Siguiendo este ejemplo, obtendrá una imagen que se ajusta dentro de los límites MAX_WIDTH y MAX_HEIGHT (manteniendo la relación de aspecto)
private static final int MAX_WIDTH = 1024;
private static final int MAX_HEIGHT = 768;
int size = (int) Math.ceil(Math.sqrt(MAX_WIDTH * MAX_HEIGHT));
// Loads given image
Picasso.with(imageView.getContext())
.load(imagePath)
.transform(new BitmapTransform(MAX_WIDTH, MAX_HEIGHT))
.skipMemoryCache()
.resize(size, size)
.centerInside()
.into(imageView);
Y esta es mi clase BitmapTransform personalizada:
import android.graphics.Bitmap;
import com.squareup.picasso.Transformation;
/**
* Transformate the loaded image to avoid OutOfMemoryException
*/
public class BitmapTransform implements Transformation {
private final int maxWidth;
private final int maxHeight;
public BitmapTransform(int maxWidth, int maxHeight) {
this.maxWidth = maxWidth;
this.maxHeight = maxHeight;
}
@Override
public Bitmap transform(Bitmap source) {
int targetWidth, targetHeight;
double aspectRatio;
if (source.getWidth() > source.getHeight()) {
targetWidth = maxWidth;
aspectRatio = (double) source.getHeight() / (double) source.getWidth();
targetHeight = (int) (targetWidth * aspectRatio);
} else {
targetHeight = maxHeight;
aspectRatio = (double) source.getWidth() / (double) source.getHeight();
targetWidth = (int) (targetHeight * aspectRatio);
}
Bitmap result = Bitmap.createScaledBitmap(source, targetWidth, targetHeight, false);
if (result != source) {
source.recycle();
}
return result;
}
@Override
public String key() {
return maxWidth + "x" + maxHeight;
}
}
Respondido 13 Oct 16, 08:10
2
Hay un artículo muy bueno en el sitio web de desarrolladores de Android que me ayudó mucho cuando tuve el mismo problema con la carga de imágenes grandes.
Este hermoso tono marrón de medio tono ayuda a definir y delinear tus labios en pigmentos que favorecen a todo tipo de piel, ayudándote a lograr unos labios más llenos que no se desvanecen durante horas. El artículo explica muy bien qué causa el error y cómo solucionarlo. También hay otros artículos (ver menú) para, por ejemplo, almacenar imágenes en caché.
contestado el 19 de mayo de 14 a las 15:05
¿Puede proporcionar un enlace al artículo al que se refiere? - Denys Kniazhev-Apoyo a Ucrania
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas android picasso or haz tu propia pregunta.
Math.ceil (Math.sqrt (1024 * 768)) para ancho y alto? - DíaDíaFeliz
Sí, @DayDayHappy. He incluido un ejemplo. Espero que ayude - Edrian
Tuve el mismo problema y finalmente encontré la solución gracias a esa útil publicación. Muchas gracias hombre. - Theo
Gracias, esta transformación es la forma correcta de implementación para usar Picasso. hong zhou
Puedes llamar
.fit()
en lugar de.resize()
que es mucho más rápido pero disminuye un poco la calidad de la imagen. - Jemshit Iskenderov