Android: максимально допустимая ширина и высота растрового изображения
Я создаю приложение, которое должно декодировать большие изображения в растровые изображения для отображения в ImageView.
Если я просто пытаюсь декодировать их прямо в растровое изображение, я получаю следующую ошибку "Растровое изображение слишком велико для загрузки в текстуру (1944x2592, max=2048x2048)"
Поэтому, чтобы иметь возможность показывать изображения со слишком высоким разрешением, я использую:
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);
}
Это работает, но я на самом деле не хочу жестко задавать максимальное значение 2048, как сейчас в выражении if, но я не могу узнать, как получить максимально допустимый размер растрового изображения для устройства
Есть идеи?
5 ответов
Этот предел должен исходить из базовой реализации OpenGL. Если вы уже используете OpenGL в своем приложении, вы можете использовать что-то вроде этого, чтобы получить максимальный размер:
int[] maxSize = new int[1];
gl.glGetIntegerv(GL10.GL_MAX_TEXTURE_SIZE, maxSize, 0);
// maxSize[0] now contains max size(in both dimensions)
Это показывает, что мои и Galaxy Nexus, и Galaxy S2 имеют максимум 2048x2048.
К сожалению, если вы еще не используете его, единственный способ получить контекст OpenGL для его вызова - это создать его (включая представление поверхности и т. Д.), Что потребует больших затрат только для запроса максимального размера.
Другим способом получения максимально допустимого размера было бы перебирать все конфигурации EGL10 и отслеживать самый большой размер.
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);
}
Из моего тестирования это довольно надежно и не требует от вас создания экземпляра. Что касается производительности, на моем Note 2 потребовалось 18 миллисекунд, а на моем G3 - всего 4 миллисекунды.
Если вы на уровне API 14+ (ICS), вы можете использовать getMaximumBitmapWidth
а также getMaximumBitmapHeight
функции на Canvas
учебный класс. Это будет работать как на аппаратном, так и на программном уровнях.
Я считаю, что аппаратное обеспечение Android должно по крайней мере поддерживать 2048x2048, так что это будет безопасное минимальное значение. На программных слоях максимальный размер составляет 32766x32766.
Это будет декодировать и масштабировать изображение перед загрузкой в память, просто измените альбомную и книжную ориентацию на нужный вам размер
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);
метод расчета размера
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;
}
Ограничение 2048*2048 для GN. GN - это устройство xhdpi, и, возможно, вы поместили изображение в неправильную область плотности. Я переместил изображение 720*1280 из drawable в drawable-xhdpi, и это сработало.
Спасибо за ответ Ромена Гая. Вот ссылка на его ответ.