您的位置:首页 > 其它

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

2016-01-01 15:41 363 查看
文字转载自: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 。抓紧时间一试……正解!

[code]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.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: