Android Bitmap处理

几乎所有图片类文件在Android内存中都会以Bitmap位图的形式存在,由于各种奇葩的需求和性能优化的原因,优化Bitmap成为Android性能优化中最常见的手段之一。

其中具体优化步骤这里暂不赘述,有兴趣的可以看我的另外一篇文章
Android Bitmap优化
最常见的Bitmap处理:分辨率处理。解决Bitmap内存占用大的问题,直接修改其分辨率是最有效的方式。常见的修改方式分为以下两种

  • 通过ThumbnailUtils.extractThumbnail()方法,直接生成指定尺寸的Bitmap对象,是比较简单粗暴的一种。
  • 另一种是通过Bitmap.createBitmap()方法,通过传入Matrix对象,并且对Matrix对象进行放大缩小实现图片的编辑。
        Matrix matrix = new Matrix();
        matrix.postScale(scaleWidth, scaleHeight);
        Bitmap targetBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getwidth, bitmap.getheight, matrix, true);

这里有一个坑,就是传入的宽度和高度,理所应当的会想去填入生成之后的宽高,但是一想这个方法本来用处是可以在某个Bitmap上进行裁剪的,传入的值应该是原来的尺寸才对(毕竟Google写的API也不至于这么蠢),所以就试着传入了原尺寸,结果果然证实我的想法是对的,生成出来的图片是传入尺寸经过Matrix转换过得到的。

最后说下之所以写这篇文章的原因,最近在项目中碰到一个特别奇葩的问题,有个需求需要将图片设置到指定的大小,最开始我图简单就使用的第一种方法,在很多手机上也没问题,但是交给客户后反馈说乐视的手机显示出来图片很小,于是就把该Bitmap生成了本地文件进行查看,最后发现分辨率确实是最终需要的分辨率,但这是个图片放大的操作,放大后的图片仅仅是将分辨率放大了,但是图片内容本身没有放大,多余的部分以透明图进行填充,当时就凌乱了,然后各种排除可能的原因,最后换成了第二种方式,正常通过。

之后看了ThumbnailUtils.extractThumbnail()的源码,发现其实其底层也是调用的第二种方式,只是不知为什么多了很多莫名其妙的判断,在得到了需要的尺寸的Bitmap之后又在次基础上进行了二次裁剪,大致是因为图片是按比例缩放,有可能导致生成不是想要的尺寸,需要需要二次裁剪。

总之就是底层实现原理几乎完全一样,但是第一种是错的?反正我也没有真机,不知道是不是客户傻逼了,先写一个在这以防以后碰到同样的奇葩问题。

        Bitmap b1;
        if (scaler != null) {
            // this is used for minithumb and crop, so we want to filter here.
            //这里已经得到了转换之后的bitmap
            b1 = Bitmap.createBitmap(source, 0, 0,
            source.getWidth(), source.getHeight(), scaler, true);
        } else {
            b1 = source;
        }

        if (recycle && b1 != source) {
            source.recycle();
        }

        //计算转换后图片大小是否比需要的尺寸大
        int dx1 = Math.max(0, b1.getWidth() - targetWidth);
        int dy1 = Math.max(0, b1.getHeight() - targetHeight);

        Bitmap b2 = Bitmap.createBitmap(
                b1,
                dx1 / 2,
                dy1 / 2,
                targetWidth,
                targetHeight);

        if (b2 != b1) {
            if (recycle || b1 != source) {
                b1.recycle();
            }
        }

        return b2;

你可能感兴趣的:(Android)