Android BitmapFactory 解码总结

 使用BitmapFactory解码图片

解码本地图片

final BitmapFactory.Options option = new BitmapFactory.Options();
// inDensity表示当前的Bitmap的像素密度
option.inDensity = DensityUtil.densityDpi;
// 使用inScale=true, 表示解码图片时允许图片缩放
// option.inScaled = true;
// inTargetDensity 表示需要解成Bitmap的像素密度
final Bitmap bitmap = BitmapFactory.decodeFile(path, option);

这样解码仍然会存在问题,假如本地图片是3X图,那么解码完放在2X手机上会造成资源浪费,此时需要根据ImageView的大小动态调整Bitmap的大小,这样可以减少内存占用,同时避免OOM

使用inJustDecodeBounds进行测量Bitmap的宽高

使用inJustDecodeBounds=true, 然后使用BimapFactory.decodeXXX()这样不会造成真正的内存分配,但是此时通过Option可以拿到Bitmap的真实宽高
然后根据View的宽高调整Bitmap的宽高,即计算Bitmap的采样率(inSampleSize)

inSamplleSize的计算

inSampleSize必须是2的n次幂,这个inSampleSize的意思是宽高都缩减为这个值
计算规则如下:
reqWidth, reqHeight为View的需要宽高
option中携带Bitmap的宽高

/**
     * Method allows to find out the scale which can be applied when loading image in order to save memory
     *
     * @param options   preset and preloaded option of an image
     * @param reqWidth  required width of image
     * @param reqHeight required height of image
     * @return scaling of image to be applied while loading the image (as power of 2)
     */
 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;

        // 如果Bitmap的宽高大于View的宽高
        if (height > reqHeight || width > reqWidth) {
            // 均除2
            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
                inSampleSize *= 2;
            }
        }
        return inSampleSize;
    }

使用BitmapFactory进行解码的代码

public void parseDrawable(final List<Pair<View, String>> list, final OnLoadBitmapCallback callback) {
        if (list == null || callback == null || list.isEmpty()) {
            return;
        }
        final List<Pair<View, BitmapDrawable>> drawables = new ArrayList<>();
        for (Pair<View, String> p : list) {
            final BitmapFactory.Options option = new BitmapFactory.Options();
            option.inJustDecodeBounds = true;
            // just decode bound.
            BitmapFactory.decodeFile(p.second, option);
            // 计算真实图片图片比例
            option.inSampleSize = calculateInSampleSize(option, p.first.getWidth(), p.first.getHeight());
            option.inJustDecodeBounds = false;
            // inPrefreredConfig表示优先选用的解码模式
            // 但是RGB_565没有ALPHA通道,且只能表示65525中颜色
            // 如果需要解码的图片含有ALPHA通道那么系统仍然会选用RGB_8888进行解码
            // 忽略InPreferedConfig
            option.inPreferredConfig = Bitmap.Config.RGB_565;
            final Bitmap bitmap = BitmapFactory.decodeFile(p.second, option);
            if (bitmap != null) {
                BitmapDrawable bitmapDrawable = new BitmapDrawable(bitmap);
                bitmapDrawable.setTargetDensity(DensityUtil.DISPLAY_METRICS);
                bitmapDrawable.setTileModeXY(Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
                drawables.add(new Pair<>(p.first, bitmapDrawable));
            }
        }
        callback.onLoadBitmap(drawables);
        });
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值