Android Bitmap压缩图像的正确方法(compress的误区)

原创 2016年08月28日 17:27:07

这两天在做的一个app需要从相册里面载入图片,踩了几个坑,这里Mark一下。

现在的相机基本都是800W+像素,差一点的手机1M多,好点的手机拍出来接近3M,如果直接载入图片,那非常容易造成oom,尤其是在差的手机上面。因此就需要对图像进行压缩处理。

先是在百度上搜了一把,比较多的解决方案都是使用Bitmap.compress()这个方法,那我也就跟着用了咯,使用形式如下:

                    ByteArrayOutputStream out = new ByteArrayOutputStream();
                    bm.compress(Bitmap.CompressFormat.JPEG, 80, out);
                    imageView.setImageBitmap(bm);

其实80的品质,就保留原图像80%的品质,压缩20%,看上去挺正确的,压缩个20%,可以变小一点点。

然后在差的手机上运行,继续会crash。通过Android Monitor查看App的内存状况,发现从相册载入图片时,内存依然会猛的增长2M左右的样子(选取的图片大小在1.5M左右)。就结果而看这个方法并不有用,随即开始打log,看各个变量的详细数据。

然后发现了与理解有偏差的地方!

                    int len = bm.getByteCount(); // 原始图片的byte[]数组大小
                    ByteArrayOutputStream out = new ByteArrayOutputStream();
                    bm.compress(Bitmap.CompressFormat.JPEG, 80, out);
                    int compressedLen = out.toByteArray().length; // 这里out.toByteArray()所返回的byte[]数组大小确实变小了!
                    Bitmap compressedBm = BitmapFactory.decodeByteArray(out.toByteArray(), 0, compressedLen);
                    int newLen = compressedBm.getByteCount(); // 这里decode出来的图片byte[]数组大小和原始图片是一样的!并没有变小

再去google狂搜一发,得到以下一个结论:

Bitmap.compress方法确实可以压缩图片,但压缩的是存储大小,即你放到disk上的大小

我尝试过把品质设置为10,decode出来的Bitmap大小没变,但显示照片的质量非常差

BitmapFactory.decodeByteArray方法对压缩后的byte[]解码后,得到的Bitmap大小依然和未压缩过一样

如果你想要显示的Bitmap占用的内存少一点,还是需要去设置加载的像素长度和宽度(变成缩略图)


下面给出我压缩图片的方法:

                    // 从选取相册的Activity中返回后

                    Uri imageUri = data.getData();
                    String[] filePathColumns = {MediaStore.Images.Media.DATA};
                    Cursor c = getContentResolver().query(imageUri, filePathColumns, null, null, null);
                    c.moveToFirst();
                    int columnIndex = c.getColumnIndex(filePathColumns[0]);
                    String imagePath = c.getString(columnIndex);
                    c.close();
                    
                    // 设置参数
                    BitmapFactory.Options options = new BitmapFactory.Options();
                    options.inJustDecodeBounds = true; // 只获取图片的大小信息,而不是将整张图片载入在内存中,避免内存溢出
                    BitmapFactory.decodeFile(imagePath, options);
                    int height = options.outHeight;
                    int width= options.outWidth;
                    int inSampleSize = 2; // 默认像素压缩比例,压缩为原图的1/2
                    int minLen = Math.min(height, width); // 原图的最小边长
                    if(minLen > 100) { // 如果原始图像的最小边长大于100dp(此处单位我认为是dp,而非px)
                        float ratio = (float)minLen / 100.0f; // 计算像素压缩比例
                        inSampleSize = (int)ratio;
                    }
                    options.inJustDecodeBounds = false; // 计算好压缩比例后,这次可以去加载原图了
                    options.inSampleSize = inSampleSize; // 设置为刚才计算的压缩比例
                    Bitmap bm = BitmapFactory.decodeFile(imagePath, options); // 解码文件
                    Log.w("TAG", "size: " + bm.getByteCount() + " width: " + bm.getWidth() + " heigth:" + bm.getHeight()); // 输出图像数据
                    imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
                    imageView.setImageBitmap(bm);

好,问题解决,一张3MB的照片所生成的bitmap的大小在90KB左右。

另外一点不能漏,bitmap需要显示地调用recycle()方法去回收资源,所以用完的bitmap要及时回收,避免内存异常。


目前我的应用场景比较小,不会有很多图片需要加载。

如果未来应用场景拓展了,我还是会去使用 Universal-Image-Loader, Picasso之类的开源框架。



android bitmap compress(图片压缩)

android bitmap compress android的照相功能随着手机硬件的发展,变得越来越强大,能够找出很高分辨率的图片。 有些场景中,需要照相并且上传到服务,但是由于图片的大小太大,...
  • luhuajcdd
  • luhuajcdd
  • 2013年05月23日 14:41
  • 127342

bitmap compress 图片压缩 图片文件大小处理

android中图片加载到内存中所占空间大小计算:分辨率 height*width*一个像素所占空间大小  解析:decode时指定解码方式为ARGB_8888 代表用8位表示透明度(A),8位表示红...
  • lazyer_dog
  • lazyer_dog
  • 2016年01月27日 17:15
  • 4720

Android Bitmap压缩图像的正确方法(compress的误区)

这两天在做的一个app需要从相册里面载入图片,踩了几个坑,这里Mark一下。 现在的相机基本都是800W+像素,差一点的手机1M多,好点的手机拍出来接近3M,如果直接载入图片,那非常容易造成oom,尤...
  • adam_ling
  • adam_ling
  • 2016年08月28日 17:27
  • 26109

Android Bitmap压缩图像的正确方法(compress的误区)

这两天在做的一个app需要从相册里面载入图片,踩了几个坑,这里Mark一下。 现在的相机基本都是800W+像素,差一点的手机1M多,好点的手机拍出来接近3M,如果直接载入图片,那非常容易造成oo...
  • m0_37402140
  • m0_37402140
  • 2017年08月19日 17:01
  • 865

bitmap.compress(图片压缩的两种方式)(1,质量压缩;2,采样率压缩)

代码如下   ByteArrayOutputStream baos = new ByteArrayOutputStream();   image.compress(Bitmap.Compres...
  • RuingMan
  • RuingMan
  • 2016年06月19日 10:53
  • 3756

bitmap经compress后保存jpg,原透明部分自动填充为黑色,如何让其填充为白色?

泣血以告: bitmap经compress后保存jpg,原透明部分自动填充为黑色,如何让其填充为白色? 答案如下代码: (其中,圆角程序主要部分为百度所得,来源众多,不知出处,故在此感谢大家,如有作者...
  • wangfei0904306
  • wangfei0904306
  • 2015年08月20日 02:32
  • 2516

Android应用开发之图片(Bitmap)压缩(二)---------质量压缩

可以写代码测试一下,在测试之前说说bitmap的占用内存的计算方法,就是像素*像素占用的字节,这里有一篇博客本人觉得写的挺好http://www.2cto.com/kf/201409/338241.h...
  • ls703
  • ls703
  • 2014年10月30日 11:20
  • 4602

Bitmap了解和尝试压缩

图片优化一直以来Bitmap都是开发中很棘手的问题,今天我就遇到了,真的很难解决。处理图片引发这个OOM的原因: 第一,每一个应用都给予了最大可用内存,根据手机屏幕dpi大小递增,dpi越小的手机,...
  • sinat_17314503
  • sinat_17314503
  • 2016年05月15日 20:51
  • 651

传递Bitmap + 图片压缩处理 并保存 + 壁纸设置 总结

基本思路是先把bitmap转化为byte数组,用Intent传递数组,在将数组转化为bitmap bitmap转化为byte数组的方法: private byte[] Bitmap2Bytes(B...
  • moubenmao
  • moubenmao
  • 2014年02月27日 16:38
  • 2842

Bitmap compress

Android 相机像素越来越高,出现了很多高分辨率的图片。在一些Android应用中,需要用户进行图片的上传,这时候就要考虑 清晰度还有流量消耗等问题。 应用中考虑从两个方面进行优化:1.是图片裁剪...
  • ustcchenchuan
  • ustcchenchuan
  • 2014年01月08日 13:51
  • 549
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android Bitmap压缩图像的正确方法(compress的误区)
举报原因:
原因补充:

(最多只允许输入30个字)