Android: BitmapFactory.decodeByteArray - 降低图像质量

Android: BitmapFactory.decodeByteArray - reduce image quality

这是我的用例:

ByteArray ba; // Some value is assigned here
Bitmap bitmap = BitmapFactory.decodeByteArray(ba, 0, ba.length);

因为ByteArray对象太大,在第二行抛出OutOfMemoryError异常,当做:

BitmapFactory.decodeByteArray(ba, 0, ba.length);

已经尝试过:

ByteArray ba; // Some value is assigned here
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4; //or whatever value
Bitmap bitmap = BitmapFactory.decodeByteArray(ba, 0, ba.length, options);

这个解决方案的问题是,使用 inSampleSize 属性,它避免了 OutOfMemoryError 异常,但是 bitmap 大小(尺寸:宽度 x高度)减少。

相反,我正在寻找与此类似的内容:

bitmap.compress(Bitmap.CompressFormat.JPEG, 50, stream);

在此示例中,位图的 质量 降低了,但其大小 仍然相同。当我在 ImageView:

中显示它时

iv.setImageBitmap(bitmap);

与原版占space,质量减半

问题是,在我的情况下我不能使用 bitmap.compress,因为我的位图是 null。也就是说,compress 方法可以在 之后使用 你有一个有效的 Bitmap 对象,这不是我的情况。

问题:

是否有任何使用 BitmapFactory.Options 的解决方案可以导致与 bitmap.compress 相同的结果:较低的 quality,相同的 dimensions

Is there any solution using BitmapFactory.Options which can lead to the same result as bitmap.compress: lower quality, same dimensions?

不是真的。 Bitmap 本质上是未压缩的。

The problem is, that in my case I cannot use bitmap.compress because my bitmap is null.

您将编码的 JPEG 图像与 Bitmap 混淆了。编码的 JPEG 图像被压缩。 Bitmap 不是。 Bitmap 总是 根据宽度、高度和每个像素的位数消耗内存。

您可以使用不同的每像素位数。 BitmapFactory 使用 ARGB_8888 (32 bits/pixel)。如果您的图像没有 Alpha 通道并且您可以接受缩小的颜色范围,您可以切换到 RGB_565 (16 bits/pixel)。

否则,您唯一的选择就是缩小图像的尺寸(宽度和高度)。

您不能随意压缩位图。

您可能已经知道了 - 但是,是的!你可以通过这个方法找到合适的inSampleSize来保持基于大小的质量。

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

        final int halfHeight = height / 2;
        final int halfWidth = 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;
}

此方法选自 Android Loading Large images efficiently

您可以阅读有关处理 Bimap 的更多信息here