web-dev-qa-db-ja.com

Android-画像ファイルのサイズを小さくする

URIイメージファイルがあり、そのサイズを縮小してアップロードしたい。初期画像ファイルのサイズはモバイルごとに異なります(500KBのように2MBも可能)が、アップロードできるように最終サイズを約200KBにしたいのです。
私が読んだものから、(少なくとも)2つの選択肢があります:

  • BitmapFactory.Options.inSampleSizeを使用して、元の画像をサブサンプリングし、より小さい画像を取得します。
  • Bitmap.compressを使用して、圧縮品質を指定して画像を圧縮します。

最良の選択は何ですか?


私は最初に幅または高さが1000px(1024x768など)を超えるまで画像の幅/高さを変更し、次にファイルサイズが200KBを超えるまで品質を低下させながら画像を圧縮することを考えていました。以下に例を示します。

int MAX_IMAGE_SIZE = 200 * 1024; // max final file size
Bitmap bmpPic = BitmapFactory.decodeFile(fileUri.getPath());
if ((bmpPic.getWidth() >= 1024) && (bmpPic.getHeight() >= 1024)) {
    BitmapFactory.Options bmpOptions = new BitmapFactory.Options();
    bmpOptions.inSampleSize = 1;
    while ((bmpPic.getWidth() >= 1024) && (bmpPic.getHeight() >= 1024)) {
        bmpOptions.inSampleSize++;
        bmpPic = BitmapFactory.decodeFile(fileUri.getPath(), bmpOptions);
    }
    Log.d(TAG, "Resize: " + bmpOptions.inSampleSize);
}
int compressQuality = 104; // quality decreasing by 5 every loop. (start from 99)
int streamLength = MAX_IMAGE_SIZE;
while (streamLength >= MAX_IMAGE_SIZE) {
    ByteArrayOutputStream bmpStream = new ByteArrayOutputStream();
    compressQuality -= 5;
    Log.d(TAG, "Quality: " + compressQuality);
    bmpPic.compress(Bitmap.CompressFormat.JPEG, compressQuality, bmpStream);
    byte[] bmpPicByteArray = bmpStream.toByteArray();
    streamLength = bmpPicByteArray.length;
    Log.d(TAG, "Size: " + streamLength);
}
try {
    FileOutputStream bmpFile = new FileOutputStream(finalPath);
    bmpPic.compress(Bitmap.CompressFormat.JPEG, compressQuality, bmpFile);
    bmpFile.flush();
    bmpFile.close();
} catch (Exception e) {
    Log.e(TAG, "Error on saving file");
}

それを行うためのより良い方法はありますか? 2つすべての方法を使用し続けるべきですか、それとも1つだけを使用すべきですか?ありがとう

54
KitKat

Bitmap.compress()を使用すると、圧縮アルゴリズムを指定するだけで、圧縮操作にはかなり長い時間がかかります。画像のメモリ割り当てを減らすためにサイズを調整する必要がある場合は、Bitmap.Optionsを使用して画像のスケーリングを使用し、最初にビットマップ境界を計算してから指定したサイズにデコードする必要があります。

StackOverflowで見つけた最高のサンプルは this one です。

29
teoREtik

私が見つけた答えのほとんどは、以下に掲載されている作業コード

 public void compressBitmap(File file, int sampleSize, int quality) {
        try {
           BitmapFactory.Options options = new BitmapFactory.Options();
            options.inSampleSize = sampleSize;
            FileInputStream inputStream = new FileInputStream(file);

            Bitmap selectedBitmap = BitmapFactory.decodeStream(inputStream, null, options);
            inputStream.close();

            FileOutputStream outputStream = new FileOutputStream("location to save");
            selectedBitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream);
            outputStream.close();
            long lengthInKb = photo.length() / 1024; //in kb
            if (lengthInKb > SIZE_LIMIT) {
               compressBitmap(file, (sampleSize*2), (quality/4));
            }

            selectedBitmap.recycle();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

2つのパラメーターsampleSizeと品質が重要な役割を果たす

sampleSizeを使用して元の画像をサブサンプリングし、より小さい画像を返します、つまり
SampleSize == 4は、元の幅/高さの1/4の画像を返します。

品質はコンプレッサーのヒントに使用されます、入力範囲は0〜100です。 0は小さなサイズの圧縮を意味し、100は最高の品質の圧縮を意味します

1
war_Hero

BitmapFactory.Options-画像サイズを縮小(メモリ内)

Bitmap.compress()-画像サイズの削減(ディスク内)


両方の使用についての詳細は、このリンクを参照してください:https://Android.jlelse.eu/loading-large-bitmaps-efficiently-in-Android -66826cd4ad5

0
Ziad H.