29

大きな画像をビットマップにデコードして ImageView に表示する必要があるアプリを作成しています。

それらをビットマップに直接デコードしようとすると、「ビットマップが大きすぎてテクスチャにアップロードできません (1944x2592、最大 = 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);             
}

これは機能しますが、現在ifステートメントにあるように2048の最大値をハードコーディングしたくありませんが、デバイスのビットマップの最大許容サイズを取得する方法がわかりません

何か案は?

4

5 に答える 5

13

最大許容サイズを取得する別の方法は、すべての 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 ミリ秒でした。

于 2014-11-08T23:24:45.977 に答える
10

この制限は、基盤となる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)

これは、GalaxyNexusとGalaxyS2の両方が最大2048x2048であることを示しています。

残念ながら、まだ使用していない場合、これを呼び出すOpenGLコンテキストを取得する唯一の方法は、最大サイズを照会するためだけに多くのオーバーヘッドがかかるもの(surfaceviewなどを含む)を作成することです。

于 2013-03-09T19:18:44.313 に答える
2

これにより、メモリにロードされる前に画像がデコードおよびスケーリングされます。横向きと縦向きを実際に必要なサイズに変更するだけです

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;
}
于 2013-03-09T17:56:41.987 に答える
2

API レベル 14+ (ICS) を使用している場合は、クラスでgetMaximumBitmapWidthおよびgetMaximumBitmapHeight関数を使用できます。Canvasこれは、ハードウェア アクセラレーションとソフトウェア レイヤーの両方で機能します。

Android ハードウェアは少なくとも 2048x2048 をサポートする必要があると考えているため、これが安全な最小値になります。ソフトウェア層では、最大サイズは 32766x32766 です。

于 2013-03-09T22:06:22.323 に答える
1

2048*2048 の制限は GN 用です。GN は xhdpi デバイスであり、画像を間違った密度のバケットに入れている可能性があります。720*1280 の画像を drawable から drawable-xhdpi に移動したところ、うまくいきました。

Romain Guy による回答ありがとうございます。これが彼の答えのリンクです。

于 2013-12-27T01:42:39.883 に答える