Подтвердить что ты не робот

Android: максимальная разрешенная ширина и высота растрового изображения

Im создает приложение, которое должно декодировать большие изображения в растровые изображения, которые будут отображаться в ImageView.

Если я просто попытаюсь их декодировать прямо в растровое изображение, я получаю следующую ошибку "Растровое изображение слишком велико, чтобы быть загруженным в текстуру (1944x2592, max = 2048x2048)"

Таким образом, чтобы показывать изображения с высоким разрешением im, используя:

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);             
}

Это работает, но я действительно не хочу, чтобы hardcode максимальное значение 2048, как и в if-statement, но я не могу узнать, как получить максимально допустимый размер растрового изображения для устройства

Любые идеи?

4b9b3361

Ответ 1

Этот предел должен исходить из базовой реализации 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, чтобы вызвать это, - это создать его (включая viewview и т.д.), что является большим количеством накладных расходов, чтобы запросить максимальный размер.

Ответ 2

Другим способом получения максимального разрешенного размера будет цикл всех конфигураций 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);
}

Из моего тестирования это довольно надёжно и не требует создания экземпляра. По производительности, это заняло 18 миллисекунд, чтобы выполнить на моей заметке 2 и только 4 миллисекунды на моем G3.

Ответ 3

это будет декодировать и масштабировать изображение перед загрузкой в ​​память, просто измените пейзаж и портрет на желаемый размер.

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;
}

Ответ 4

Если вы используете API уровня 14+ (ICS), вы можете использовать функции getMaximumBitmapWidth и getMaximumBitmapHeight в классе Canvas. Это будет работать как на аппаратном, так и на программном уровнях.

Я считаю, что аппаратное обеспечение Android должно по крайней мере поддерживать 2048x2048, так что это будет безопасное минимальное значение. На программных уровнях максимальный размер составляет 32766x32766.

Ответ 5

Предел 2048 * 2048 для GN. GN является устройством xhdpi и, возможно, вы помещаете изображение в неправильный ковш плотности. Я переместил изображение 720 * 1280 от drawable to drawable-xhdpi, и оно сработало.

Спасибо за ответ Ромен Гай. Здесь ссылка его ответа.