Android 图片压缩方案

       前段时间,项目的一个需求涉及图片压缩之后上传。要求是压缩之后的图片要和原图尺寸一致,压缩后的大小控制在< 600KB,并且重新加载的时候不能卡顿更不能OOM,在此做一下记录。

质量压缩

使用方式:

public String compressAndImage(Bitmap image) throws IOException {
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    //压缩比重,图片存储在磁盘上的大小会根据这个值变化。值越小存储在磁盘的图片文件越小,取值
    //区间为0-100,小于0时会抛异常
    int options = 100;
    image.compress(Bitmap.CompressFormat.JPEG, options, os);
    // Compress by loop
    while (os.toByteArray().length / 1024 > 500) {
        os.reset();
        if (options > 10) {
            options -= 10;
            image.compress(Bitmap.CompressFormat.JPEG, options, os);
        } else {
            options = 1;
            image.compress(Bitmap.CompressFormat.JPEG, options, os);
            break;
        }
    }
    File file = new File("图片路径");
    // Generate compressed image file
    FileOutputStream fos = new FileOutputStream(file);
    fos.write(os.toByteArray());
    fos.flush();
    fos.close();
    return file.getAbsolutePath();
}

       质量压缩图片的宽高不变,质量压缩的原理是通过改变图片的位深和透明度来减小图片占用的磁盘空间大小。但不会改变图片的像素点数,也就是说加载进内存的大小并没有改变,如果是大图加载还是会有OOM的风险。另外,png是无损压缩,所以设置Bitmap.CompressFormat.PNG无效。

采样率压缩

使用方式:

public Bitmap handleImageToBitmap() {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        //此时只是为了获取当inJustDecodeBounds设置为true的时候,
        // BitmapFactory通过decodeResource或者decodeFile解码图片时,
        // 返回的Bitmap对象为null,这样可以避免Bitmap的内存分配,
        // 但是它可以获取Bitmap的宽度、高度
        BitmapFactory.decodeFile("文件路径", options);

        options.inJustDecodeBounds = false;
        //采样率,这个值决定了压缩后的图片大小
        options.inSampleSize = 2;

        return BitmapFactory.decodeFile("文件路径", options);
}

采样率压缩改变了图片的尺寸大小,减少了图片的像素点数,使得加载进内存的对象也变小了,当然对应图片保存到磁盘上所占空间也会变小。这些都取决于采样率的设定。一般这种压缩方式在做缩略图时用的较多。另附上做缩略图时,采样率(options.inSampleSize)的值设置方式:

public static int handleSampleSize(BitmapFactory.Options options, int aimsWidth, int aimsHeight) {
        int height = options.outHeight;//获取原始图片的高度
        int width = options.outWidth;//获取原始图片的宽度
        //inSampleSize小于等于1会按照1处理
        //inSampleSize只能设置为2的平方,不是2的平方则最终会减小到最近的2的平方数,如设置7会按4进行压缩。
        int inSampleSize = 1;//设置初始采样率

        if (height > aimsHeight || width > aimsWidth) {
            final int heightRatio = Math.round((float) height / (float) aimsHeight);
            final int widthRatio = Math.round((float) width / (float) aimsWidth);
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
        }
        return inSampleSize;
    }

尺寸压缩

即通过压缩图片尺寸而改变图片的大小。

public static Bitmap zoomCompress(Bitmap bitmap) {
        Matrix matrix = new Matrix();
        matrix.setScale(0.5f, 0.5f);
        return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
                bitmap.getHeight(), matrix, true);
}

RGB_565压缩

在Android中,图片在内存是以Bitmap对象存在的,Bitmap所占内存计算方式:图片长度 x 图片宽度 x 一个像素点占用的字节数

图片的压缩格式共有以下四种:

ALPHA_8:表示8位Alpha位图,即A=8,一个像素点占用1个字节,它没有颜色,只有透明度
ARGB_4444:表示16位ARGB位图,即A=4,R=4,G=4,B=4,一个像素点占4+4+4+4=16位,2个字节
ARGB_8888:表示32位ARGB位图,即A=8,R=8,G=8,B=8,一个像素点占8+8+8+8=32位,4个字节
RGB_565:表示16位RGB位图,即R=5,G=6,B=5,它没有透明度,一个像素点占5+6+5=16位,2个字节

ARGB_4444压缩出来的画质很差,所以对透明度没有要求的话可以采用RGB_565的方式进行压缩:

public static Bitmap rgbCompress(String imgPath) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inPreferredConfig = Bitmap.Config.RGB_565;
        return BitmapFactory.decodeFile(imgPath, options);
}

也可以采用ARGB_8888,只不过压缩出来大小变化可能会很小。

第三方

鲁班压缩------接近微信朋友圈的压缩方法

放一张作者提供的效果对比图:

具体使用方法上面链接里有,就不多做叙述。这种方案适合那种,要求图片压缩后尺寸不变体积要变小加载进内存的对象也要变小的需求,亲测效果还不错,而且压缩出来的图片也不会模糊,压缩出来的格式是JPEG

总结

使用每种压缩方式都要根据自己的需要来选择,有时候可能需要其中两种方式组合使用。对于第三方的选择上要慎重,毕竟使用第三方会增大apk的体积,能用系统提供的方法解决就尽量不用第三方。

最后如果文章有错误,请大家评论指正。希望我的分享能帮到大家!

参考文章:https://blog.csdn.net/harryweasley/article/details/51955467

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值