Bitmap二次采样以及压缩另一种方式

文字转载自:http://blog.csdn.net/jian51868/article/details/45225445
感谢原博主无私分享。

最近,做到电子照片上传的功能,要求照片大小不能大于50kb,还有尽量保证质量!心想简单吧……是不是百度一下一箩筐!!!查看了一些发现一箩筐都是一样一样的。简单说一下网上的:
1、bitmap质量压缩。
2、bitmap图片比例缩放。
3、根据path比例缩放图片。最后发现baos.toByteArray().length取到的照片大小与实际保存的大小不符。这是个大问题,得不到真实的图片大小,不能准确的压缩图片。
后来无意想起以前貌似在哪里看到资料说这个 inSampleSize 好像是 2 的 N 次方。看了官方文档,果然这么说的:默认会找一个最接近的 2 的 N 次方的整数。很显然问题就出在这里,它所找的最接近的很可能并不是我们所需要的,可能已经超过了限制。我们需要先对这个压缩比取 2 的对数,然后向上取整,最后再取2的指数得到正确的 inSampleSize 。抓紧时间一试……正解!

public void compress(String srcPath) {
    dm = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(dm);

    float hh = dm.heightPixels;
    float ww = dm.widthPixels;
    BitmapFactory.Options opts = new BitmapFactory.Options();
    opts.inJustDecodeBounds = true;
    Bitmap bitmap = BitmapFactory.decodeFile(srcPath, opts);
    opts.inJustDecodeBounds = false;
    int w = opts.outWidth;
    int h = opts.outHeight;
    int size = 0;
    if (w <= ww && h <= hh) {
        size = 1;
    } else {
        double scale = w >= h ? w / ww : h / hh;
        double log = Math.log(scale) / Math.log(2);//获取对数
        double logCeil = Math.ceil(log); //向上取整
        size = (int) Math.pow(2, logCeil); //再取2的指数
    }
    opts.inSampleSize = size;
    bitmap = BitmapFactory.decodeFile(srcPath, opts);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    int quality = 100;
    bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);
    System.out.println(baos.toByteArray().length);
    while (baos.toByteArray().length > 45 * 1024) {//确保图片小于50k
        baos.reset();
        bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);
        quality -= 20;
        System.out.println(baos.toByteArray().length);
    }
    try {
        baos.writeTo(new FileOutputStream("/mnt/sdcard/Servyou/photo/buffer/22.jpg"));
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            baos.flush();
            baos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

对于bitmap.compress()方法,API的描述为:

public boolean compress(Bitmap.CompressFormat format,
int quality,
OutputStream stream)Write a compressed version of the bitmap to the specified outputstream. If this returns true, the bitmap can be reconstructed by passing a corresponding inputstream to BitmapFactory.decodeStream(). Note: not all Formats support all bitmap configs directly, so it is possible that the returned bitmap from BitmapFactory could be in a different bitdepth, and/or may have lost per-pixel alpha (e.g. JPEG only supports opaque pixels).

参数:
format - The format of the compressed image
quality - Hint to the compressor, 0-100. 0 meaning compress for small size, 100 meaning compress for max quality. Some formats, like PNG which is lossless, will ignore the quality setting //PNG格式无视这个图片质量比,以最优方式保存
stream - The outputstream to write the compressed data.
返回:
true if successfully compressed to the specified stream.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值