web-dev-qa-db-de.com

Android: Maximal zulässige Breite und Höhe der Bitmap

Im Erstellen einer App, die große Bilder zu Bitmaps decodieren muss, um in einer ImageView angezeigt zu werden.

Wenn ich gerade versuche, sie direkt in eine Bitmap zu decodieren, erhalte ich die folgende Fehlermeldung: "Bitmap zu groß, um in eine Textur hochgeladen zu werden (1944x2592, max = 2048x2048)"

Um also Bilder mit zu hoher Auflösung anzeigen zu können, verwenden Sie: 

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

Das funktioniert zwar, aber ich möchte nicht wirklich den Maximalwert von 2048 hartcodieren, wie ich es in der if-Anweisung jetzt habe, aber ich kann nicht herausfinden, wie man die maximal zulässige Größe der Bitmap für ein Gerät erhält

Irgendwelche Ideen? 

28
Fredkr

Dieses Limit sollte von der zugrunde liegenden OpenGL-Implementierung stammen. Wenn Sie OpenGL bereits in Ihrer App verwenden, können Sie so etwas verwenden, um die maximale Größe zu erhalten:

int[] maxSize = new int[1];
gl.glGetIntegerv(GL10.GL_MAX_TEXTURE_SIZE, maxSize, 0);
// maxSize[0] now contains max size(in both dimensions)

Dies zeigt, dass meine beiden Galaxy Nexus und Galaxy S2 maximal 2048x2048 haben.

Wenn Sie es nicht bereits verwenden, können Sie einen OpenGL-Kontext nur aufrufen, indem Sie einen erstellen (einschließlich der Oberflächenansicht usw.).

9
Geobits

Eine andere Möglichkeit, die maximal zulässige Größe zu erhalten, besteht darin, alle EGL10-Konfigurationen zu durchlaufen und die größte Größe zu verfolgen.

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

Nach meinen Tests ist dies ziemlich zuverlässig und es ist nicht erforderlich, dass Sie eine Instanz erstellen. Die Performance hat 18 Millisekunden für meine Note 2 und nur 4 Millisekunden für mein G3 gedauert.

13
Pkmmte

dadurch wird das Bild dekodiert und skaliert, bevor es in den Speicher geladen wird. Ändern Sie einfach Querformat und Hochformat auf die gewünschte Größe

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

methode zur Berechnung der Größe

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

Wenn Sie sich auf API Level 14 (ICS) befinden, können Sie die Funktionen getMaximumBitmapWidth und getMaximumBitmapHeight für die Klasse Canvas verwenden. Dies würde sowohl auf hardwarebeschleunigten als auch auf Softwareschichten funktionieren.

Ich glaube, die Android-Hardware muss mindestens 2048x2048 unterstützen, damit wäre dies ein sicherer niedrigster Wert. Auf Software-Layern beträgt die maximale Größe 32766 x 32766.

1

Die Grenze von 2048 * 2048 gilt für GN. GN ist ein xhdpi-Gerät, und vielleicht legen Sie das Bild in den falschen Dichteimer. Ich habe ein 720 * 1280-Bild von drawable nach drawable-xhdpi verschoben und es hat funktioniert. 

Danke für die Antwort von Romain Guy. Hier ist der Link seiner Antwort. 

0
jedichen