关于Bitmap采样的问题

171 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

最近在使用bitmap采样时发现,采样后的大小比采样前还要大。 这是怎么回事呢? 原来是我忽略了一个相关知识点。

代码如下:

BitmapFactory.Options options = new BitmapFactory.Options();
// 设置仅解码宽高。 在options中有in开头的属性,一般是用来设置的。 带out开头的属性一般是输出相关信息的。 
options.inJustDecodeBounds = true;
// 设置后,这次decode会返回null,所以不要使用此时返回的bitmap
BitmapFactory.decodeResource(getResources(), R.drawable.test, options);
Log.i(TAG, "simpleSize before: " + options.outWidth + ", " + options.outHeight);

// 设置采样率。 这里使用的是google推荐的采样方法。 
int sampleSize = calculateInSampleSize(options, Utils.getActivityWidth(this), Utils.getActivityHeight(this));
options.inJustDecodeBounds = false;
options.inSampleSize = sampleSize;
Bitmap originBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.test, options);
Log.i(TAG, "simpleSize after: " + originBitmap.getWidth() + ", " + originBitmap.getHeight());

其中,采样的方法如下:

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;
}

打印的结果如下:

resultofbitmap

通过日志发现,采样后的图片大小反而变大了。 断点调试时,采样率是 1,至少不会变大。 为啥呢?

原来通过 BitmapFactory.Options 设置 inJustDecodeBounds 为 true的方式取出的宽高值是图片原本的值。 打开文件管理器查看图片的宽高为 1200 和 760 像素。

imageInfo

但是通过 设置 inJustDecodeBounds 为 false的方式,则会根据系统屏幕密度对图片进行缩放。 首先,要看图片是放在哪个文件夹下的。假设设备屏幕密度是 m。 如果是drawable文件夹下,那么图片的缩放的比例是 m / 160 , 如果是drawable-mdpi,那么图片的缩放比例是 m / 240 , 同理其他的文件夹。 由此可知,图片的缩放比例是屏幕密度除以图片所在文件夹对应的屏幕密度。

在上例中,图片放在了drawable中,对应的屏幕密度是 160(drawable使用的是基准值 160), 而设备的屏幕密度为 320 。

在这里插入图片描述

故解析出来的bitmap大小是实际图片的 320 / 160 = 2 倍。 如果放在drawable-hdpi中,那么解析出来的图片宽度将是 320 / 240 * 1200 (1200是实际宽度) = 1600, 实际打印也如此:

在这里插入图片描述

总结:

1、通过 BitmapFactory.Options 获取的是图片实际大小,不会随系统改变。 2、通过 BitmapFactory 得到的 Bitmap 大小会根据系统缩放,缩放比例为 屏幕密度 / 图片文件夹对应屏幕密度。 3、当从本地加载图片时不会对图片进行缩放。