web-dev-qa-db-ja.com

速度のためのBitmapFactory.Options.inSampleSizeの最適な使用

Schermvliegerに質問してくれてありがとう thisanddev.org

私は彼の質問をSOにコピーしているだけです。他のサイトでは誰も返信しておらず、同じ問題に直面しているからです。

画像の表示速度に関して、_BitmapFactory.Options.inSampleSize_の最適な使用法は何でしょうか。
ドキュメントには2の累乗の値の使用が記載されているため、2、4、8、16などを使用しています。

私が疑問に思っていることは次のとおりです。

  1. 画面の解像度よりもまだ大きい最小サイズにリサンプリングする必要がありますか、それともOutOfMemoryErrorを回避するのに十分なサイズにサンプリングする必要がありますか?
  2. メモリが不足することなく表示できる画像の最大サイズをどのように計算しますか?画像の色深度、およびディスプレイの深度も影響しますか?
  3. 2つのメカニズム(大きなファイルの場合はBitmapFactory、小さなファイルの場合はsetImageURI())を介して画像を表示するのは効率的ですか?ちなみに私はImageSwitcherを使用しています。
  4. アプリケーションの最初にBitmap、_BitmapFactory.Options_、およびinTempStorageを作成するのに役立ちますか、それとも必要に応じてその場でのみ作成するのに役立ちますか?
22

最終的に表示されるサイズにできるだけ近くなるように、画像の読み込みと事前スケーリングを常に試みる必要があります。描画時の画像のスケーリングは非常にコストがかかるため、絶対に避けてください。

画像のメモリコストを考えると、そうです、カラー部門は非常に重要な役割を果たします。 ALPHA_8形式の画像はピクセルあたり1バイトを使用し、RGB_565またはARGB_4444の画像はピクセルあたり2バイトを使用し、ARGB_8888の画像はピクセルあたり4バイトを使用します。ディスプレイの奥行きはまったく関係ありません。最高の品質を得るには、常にARGB_8888を使用するようにしてください。ただし、画像が不透明な場合は565で十分です。

11
Romain Guy

あなたは良い質問をしましたが、それはすべてあなたのニーズとあなたが使うメモリの量に依存します。ビットマップに関する多くのヒントについては、このリンクを確認することをお勧めします: http://developer.Android.com/training/displaying-bitmaps/index.html

つまり、キャッシュ、ダウンサンプリング、および可能な限り十分なビットマップ形式の使用を検討する必要があります。

これがあなたの質問に対する私の答えです:

  1. なぜ両方ではない? OOMがあると思われる場合は、古い未使用のビットマップをリサイクルしてから、もう一度確認してください。

  2. ビットマップの(推定)サイズを計算できます:

    width * height * bytesPerPixel

    ここで、bytesPerPixelは通常4または2です(ビットマップ形式によって異なります)。

  3. SetImageURIを使用したことがないので、それについてはお役に立てません。バックグラウンドスレッドで画像をダウンロードし(asyncTaskを使用するのが1つの方法です)、準備ができたら画像を表示することをお勧めします。

  4. あまりメモリを消費しないことがわかっているものが少ししかない場合は、大丈夫だと思います。私はまだキャッシングがより良いかもしれないと思います。

4

ここでは、文字列ファイルのパスと高さと幅を実際に送信するユーザー定義のメソッドshrinkmehtodを呼び出して、画像をメソッドに縮小できます。

 Bitmap bit=shrinkmethod(arrpath1[position], 100, 100);


            //iv.setImageURI(Uri.parse(arrpath1[position]));
            iv.setImageBitmap(bit);

これは、プログラムで画像のサイズを縮小するためのユーザー定義の方法です。

Bitmap shrinkmethod(String file,int width,int height){
        BitmapFactory.Options bitopt=new BitmapFactory.Options();
        bitopt.inJustDecodeBounds=true;
        Bitmap bit=BitmapFactory.decodeFile(file, bitopt);

        int h=(int) Math.ceil(bitopt.outHeight/(float)height);
        int w=(int) Math.ceil(bitopt.outWidth/(float)width);

        if(h>1 || w>1){
            if(h>w){
                bitopt.inSampleSize=h;

            }else{
                bitopt.inSampleSize=w;
            }
        }
        bitopt.inJustDecodeBounds=false;
        bit=BitmapFactory.decodeFile(file, bitopt);



        return bit;

    }

これがサイズの縮小に役立つことを願っています。

3
Pranav

こんにちは、このロジックを使用してinSampleSizeを計算してみてください

private fun calculateInSampleSize(options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int): Int {
    val (height: Int, width: Int) = options.run { outHeight to outWidth }
    var inSampleSize = 1

    if (height > reqHeight || width > reqWidth) {
        val halfHeight: Int = height / 2
        val halfWidth: Int = width / 2

        // Calculate the largest inSampleSize value that is a power of 2 and keeps both
        // height and width larger than the requested height and width.
        while (halfHeight / inSampleSize >= reqHeight && halfWidth / inSampleSize >= reqWidth) {
            inSampleSize *= 2
        }
    }

    return inSampleSize
}
0
Adarsh Singh