inSampleSize Matrix 组合缩放图片(bitmap size exceeds 32 bits???)

为什么要将inSampleSize Matrix组合使用?

1.inSampleSize(采样率)

优点:效率较高,解析速度快

缺点:采样率inSampleSize的取值只能是2的次方数(例如:inSampleSize=15,实际取值为8;inSampleSize=17,实际取值为16;实际取值会往2的次方结算),因此该方法不能精确的指定图片的大小

2.Matrix

优点:可以精确地指定图片的缩放大小

缺点:是在原bitmap的基础之上生成的,占内存,效率低.

  • 可以从1、2看到,单独使用inSampleSize的话,无法将图片进行精确的压缩,因为inSampleSize实际取值会往2的次方结算。例如:当inSampleSize = 3时实际为inSampleSize = 2
  • 单独使用Matrix呢又因为占内存,效率低.常常会出现bitmap size exceeds 32bits

所以要将inSampleSize Matrix进行组合使用

public CompressModel compressImage(final String filePath) {
    int i = readPictureDegree(filePath);
    TLog.e(TAG,"filePath : " + i);
    final CompressModel compressModel = new CompressModel();
    try {
        BitmapFactory.Options newOpts = new BitmapFactory.Options();
        //开始读入图片,此时把options.inJustDecodeBounds 设回true了
        newOpts.inJustDecodeBounds = true;
        Bitmap bitmap = BitmapFactory.decodeFile(filePath, newOpts);//此时返回bm为空

        newOpts.inJustDecodeBounds = false;
        int w = newOpts.outWidth;
        int h = newOpts.outHeight;
        TLog.d(TAG,"w : " + w);
        TLog.d(TAG,"h : " + h);
        float standardLength = compressLength;
        //scale = 1 表示不需要缩放
        int scale = 1;
        **1**
        if (w > standardLength || h > standardLength) {
            //需要压缩
            int maxL = Math.max(w, h);
            TLog.d(TAG,"maxL : " + maxL);
            float scaleF = (float) (maxL / standardLength);
            TLog.d(TAG,"will scaleF : " + scaleF);
            scale = (int) Math.floor(scaleF);
            TLog.d(TAG,"will scale : " + scale);
        }else {
            compressModel.setFilePath(filePath);
            return compressModel;
        }
        if (scale <= 0) {
            scale = 1;
        }
        newOpts.inSampleSize = scale;//设置缩放比例
        TLog.d(TAG,"newOpts.inSampleSize : " + newOpts.inSampleSize);
        //重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了
        bitmap = BitmapFactory.decodeFile(filePath, newOpts);
        int ow = newOpts.outWidth;
        int oh = newOpts.outHeight;
        TLog.d(TAG,"ow : " + ow);
        TLog.d(TAG,"oh : " + oh);
        **2**
        if (ow > standardLength || oh > standardLength) {
            int maxL = Math.max(ow, oh);
            TLog.d(TAG,"maxL : " + maxL);
            float scaleF = (float) (maxL / standardLength);
            TLog.d(TAG,"will scaleF : " + scaleF);
            Matrix matrix = new Matrix();
            /*int scaleW = (int) Math.floor(ow / scaleF);
            int scaleH = (int) Math.floor(oh / scaleF);
            TLog.d(TAG,"scaleW : " + scaleW);
            TLog.d(TAG,"scaleH : " + scaleH);
            float matrixScaleW = (float) (scaleW / ow);
            float matrixScaleH = (float) (scaleH / oh);
            TLog.d(TAG,"matrixScaleW : " + matrixScaleW);
            TLog.d(TAG,"matrixScaleH : " + matrixScaleH);*/
            TLog.d(TAG,"1/scaleF : " + 1/scaleF);
            matrix.postScale(1/scaleF,1/scaleF);
            Bitmap resizeBitmap = Bitmap.createBitmap(bitmap, 0, 0, ow, oh, matrix, true);
            int rbWidth = resizeBitmap.getWidth();
            int rbHeight = resizeBitmap.getHeight();
            TLog.d(TAG,"rbWidth : " + rbWidth);
            TLog.d(TAG,"rbHeight : " + rbHeight);
            bitmap = resizeBitmap;
        }

            // 图片尺寸大小方面压缩完毕
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
          //bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
        bitmap.compress(Bitmap.CompressFormat.JPEG, 80, baos);//质量压缩方法,压缩至80%
        int options = 80;
        while (baos.toByteArray().length / 1024 > compressKB) {  //循环判断如果压缩后图片是否大于300kb,大于继续压缩
            baos.reset();//重置baos即清空baos
            bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos中
            options -= 10;//每次都减少10
            if (options < 70) { //若质量系数小于0.7则不再压缩
                break;
            }
        }
        BitmapFactory.Options option = new BitmapFactory.Options();
        option.inPreferredConfig = Bitmap.Config.RGB_565;
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中
        Bitmap bit = BitmapFactory.decodeStream(isBm, null, option);//把ByteArrayInputStream数据生成图片
        String fileName = ImageUtils.saveToFile(Constants.APP_IMAGE, true, bit);
        compressModel.setFilePath(fileName);
        baos.close();
        bit.recycle();
        isBm.close();
        bitmap.recycle();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return compressModel;
}

- 标记1处使用inSampleSize最大限度缩放至理想尺寸
- 标签2,如果经过inSampleSize缩放的尺寸大于理想尺寸,那么需要使用Matrix进行精确缩放。

易错点:为什么会出现bitmap size exceeds 32 bits??

我正经缩放图片,为什么要这样对我?
我正经缩放图片,为什么要这样对我?

matrix.postScale(1/scaleF,1/scaleF);

这两个参数为需要缩放的倍数,大部分同学将参数理解为理想尺寸,图片一下扩大了几百上千倍,结果一下就BOOM了。
注释很详细,大家仔细看看就好。
代码用代码片括起来变得乱七八糟,完全不能格式化啊,有高手懂请告诉我下~~

standardLength = 1280
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值