60

我有一个 URI 图像文件,我想减小它的大小来上传它。初始图像文件大小取决于移动设备(可以是 2MB,也可以是 500KB),但我希望最终大小约为 200KB,以便我可以上传它。
从我读到的,我有(至少)2个选择:

  • 使用BitmapFactory.Options.inSampleSize,对原始图像进行二次采样,得到更小的图像;
  • 使用Bitmap.compress压缩指定压缩质量的图像。

最好的选择是什么?


我正在考虑最初调整图像宽度/高度的大小,直到宽度或高度超过 1000 像素(例如 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");
}

有更好的方法吗?我应该尝试继续使用所有两种方法还是只使用一种?谢谢

4

3 回答 3

31

使用Bitmap.compress()您只需指定压缩算法,顺便说一下压缩操作需要相当多的时间。如果您需要使用大小来减少图像的内存分配,您确实需要使用缩放图像Bitmap.Options,首先计算位图边界,然后将其解码为您指定的大小。

我在 StackOverflow 上找到的最好的示例就是这个

于 2012-06-16T06:18:13.850 回答
1

我找到的大多数答案只是我必须拼凑起来才能获得工作代码的部分,发布在下面

 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 和 quality 起重要作用

sampleSize用于对原始图像进行二次采样并返回较小的图像,即
SampleSize == 4 返回的图像是原始图像宽度/高度的 1/4。

质量用于提示压缩器,输入范围在 0-100 之间。0 表示压缩为小尺寸,100 表示压缩为最大质量

于 2016-11-04T09:42:57.593 回答
0

BitmapFactory.Options - 减小图像大小(在内存中)

Bitmap.compress() - 减小图像大小(在磁盘中)


有关使用它们的更多信息,请参阅此链接: https ://android.jlelse.eu/loading-large-bitmaps-efficiently-in-android-66826cd4ad53

于 2019-08-20T19:12:03.340 回答