xhdpi - Android: ancho y altura máximos permitidos de mapa de bits
medidas diseño app android (5)
Estoy creando una aplicación que necesita decodificar imágenes grandes a mapas de bits para mostrarlas en un ImageView.
Si intento descodificarlos directamente a un mapa de bits, aparece el siguiente error: "Mapa de bits demasiado grande para cargarlo en una textura (1944x2592, máx = 2048x2048)"
Entonces, para poder mostrar imágenes con una resolución demasiado alta, estoy usando:
Bitmap bitmap = BitmapFactory.decodeFile(path);
if(bitmap.getHeight()>=2048||bitmap.getWidth()>=2048){
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int width = metrics.widthPixels;
int height = metrics.heightPixels;
bitmap =Bitmap.createScaledBitmap(bitmap, width, height, true);
}
Esto funciona pero realmente no quiero codificar el valor máximo de 2048 como lo tengo en la sentencia if ahora, pero no puedo averiguar cómo obtener el tamaño máximo permitido del mapa de bits para un dispositivo
¿Algunas ideas?
El límite de 2048 * 2048 es para GN. GN es un dispositivo xhdpi y quizás coloque la imagen en el contenedor de densidad incorrecto. Moví una imagen de 720 * 1280 de drawable a drawable-xhdpi y funcionó.
Gracias por la respuesta de Romain Guy. Aquí está el link de su respuesta.
Este límite debe provenir de la implementación subyacente de OpenGL. Si ya está utilizando OpenGL en su aplicación, puede usar algo como esto para obtener el tamaño máximo:
int[] maxSize = new int[1];
gl.glGetIntegerv(GL10.GL_MAX_TEXTURE_SIZE, maxSize, 0);
// maxSize[0] now contains max size(in both dimensions)
Esto demuestra que tanto mi Galaxy Nexus como mi Galaxy S2 tienen un máximo de 2048x2048.
Desafortunadamente, si aún no lo está utilizando, la única manera de obtener un contexto OpenGL para llamar a esto es crear uno (incluida la vista de la superficie, etc.), que es una gran cantidad de gastos generales para consultar un tamaño máximo.
Otra forma de obtener el tamaño máximo permitido sería recorrer todas las configuraciones de EGL10 y realizar un seguimiento del tamaño más grande.
public static int getMaxTextureSize() {
// Safe minimum default size
final int IMAGE_MAX_BITMAP_DIMENSION = 2048;
// Get EGL Display
EGL10 egl = (EGL10) EGLContext.getEGL();
EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
// Initialise
int[] version = new int[2];
egl.eglInitialize(display, version);
// Query total number of configurations
int[] totalConfigurations = new int[1];
egl.eglGetConfigs(display, null, 0, totalConfigurations);
// Query actual list configurations
EGLConfig[] configurationsList = new EGLConfig[totalConfigurations[0]];
egl.eglGetConfigs(display, configurationsList, totalConfigurations[0], totalConfigurations);
int[] textureSize = new int[1];
int maximumTextureSize = 0;
// Iterate through all the configurations to located the maximum texture size
for (int i = 0; i < totalConfigurations[0]; i++) {
// Only need to check for width since opengl textures are always squared
egl.eglGetConfigAttrib(display, configurationsList[i], EGL10.EGL_MAX_PBUFFER_WIDTH, textureSize);
// Keep track of the maximum texture size
if (maximumTextureSize < textureSize[0])
maximumTextureSize = textureSize[0];
}
// Release
egl.eglTerminate(display);
// Return largest texture size found, or default
return Math.max(maximumTextureSize, IMAGE_MAX_BITMAP_DIMENSION);
}
Desde mis pruebas, esto es bastante confiable y no requiere que crees una instancia. En cuanto al rendimiento, esto tomó 18 milisegundos para ejecutarse en mi Nota 2 y solo 4 milisegundos en mi G3.
Si tiene el nivel API 14+ (ICS), puede usar las funciones getMaximumBitmapWidth
y getMaximumBitmapHeight
en la clase Canvas
. Esto funcionaría tanto en hardware acelerado como en capas de software.
Creo que el hardware de Android debe al menos admitir 2048x2048, por lo que sería un valor más bajo y seguro. En las capas de software, el tamaño máximo es 32766x32766.
esto decodificará y escalará la imagen antes de cargarla en la memoria, solo cambiará el paisaje y el retrato al tamaño que realmente desea
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;
if(imageWidth > imageHeight) {
options.inSampleSize = calculateInSampleSize(options,512,256);//if landscape
} else{
options.inSampleSize = calculateInSampleSize(options,256,512);//if portrait
}
options.inJustDecodeBounds = false;
bitmap = BitmapFactory.decodeFile(path,options);
método para calcular el tamaño
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;
}