Android 图片压缩

从转行Android这个行业,对图片这一块都是一个模糊区,总是理解不彻底,下午闲来无事,所以就在网上查查资料,总结一下。废话不说,马上开始。

首先,大家都知道图片压缩,大致可以分为2中,质量压缩(不改变图片的尺寸)和尺寸压缩(相当于是像素上的压缩),质量压缩一般可用于上传大图前的处理,这样就可以节省一定的流量

而图片的储存也是三种:硬盘上时是file,网络传输时是stream,内存中是stream或bitmap。

先看第一种:

1. 将图片保存到本地时进行压缩, 即将图片从Bitmap形式变为File形式时进行压缩,

private Bitmap compressImage(Bitmap image){
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    image.compress(Bitmap.CompressFormat.JPEG,100,out);//不压缩是100,表示压缩率为0

    int intoptions = 100;
    while (out.toByteArray().length/1024>100){//循环判断如果压缩后图片是否大于100kb,大于继续压缩

        out.reset();//重置out即清空
        intoptions -=10;

        image.compress(Bitmap.CompressFormat.JPEG,intoptions,out);
    }
 
    //把压缩后的数据baos存放到ByteArrayInputStream中
ByteArrayInputStream input = new ByteArrayInputStream(out.toByteArray()); Bitmap bitmap = BitmapFactory.decodeStream(input,null,null);//把ByteArrayInputStream数据生成图片 return bitmap;}

第二:图片按比例大小压缩方法(根据路径获取图片并压缩):

首先需要了解BitmapFactory相信大家都很熟悉了,这个类里面的所有方法都是用来解码创建一个Bitmap,其中有一个重要的类是Options,此类用于解码Bitmap时的各种参数控制,那这里面的各种参数都是什么含义呢?今天我们就来重点解读几个参数。


1、inJustDecodeBounds :如果我们把它设为true,那么BitmapFactory.decodeFile(String path, Options opt)并不会真的返回一个Bitmap给你,它仅仅会把它的宽,高取回来给你,这样就不会占用太多的内存,也就不会那么频繁的发生OOM了。

2、inJustDecodeBounds:如果将这个值置为true,那么在解码的时候将不会返回bitmap,只会返回这个bitmap的尺寸。这个属性的目的是,如果你只想知道一个bitmap的尺寸,但又不想将其加载到内存时。这是一个非常有用的属性。

3、inSampleSize:
这个值是一个int,当它小于1的时候,将会被当做1处理,如果大于1,那么就会按照比例(1 / inSampleSize)缩小bitmap的宽和高、降低分辨率,大于1时这个值将会被处置为2的倍数。例如,width=100,height=100,inSampleSize=2,那么就会将bitmap处理为,width=50,height=50,宽高降为1 / 2,像素数降为1 / 4。

4、inPreferredConfig:这个值是设置色彩模式,默认值是ARGB_8888,在这个模式下,一个像素点占用4bytes空间
,一般对透明度不做要求的话,一般采用RGB_565模式,这个模式下一个像素点占用2bytes

5、inPremultiplied:这个值和透明度通道有关,默认值是true,如果设置为true,则返回的bitmap的颜色通道上会预先附加上透明度通道。

6、inDither:这个值和抖动解码有关,默认值为false,表示不采用抖动解码。如果想知道什么是抖动解码,请参看另一篇文章:http://blog.csdn.net/haozipi/article/details/47185535

7、inDensity:表示这个bitmap的像素密度(对应的是DisplayMetrics中的densityDpi,不是density)。

8、inTargetDensity:表示要被画出来时的目标像素密度(对应的是DisplayMetrics中的densityDpi,不是density)。

9、inScreenDensity:表示实际设备的像素密度(对应的是DisplayMetrics中的densityDpi,不是density)。

10、inScaled:设置这个Bitmap是否可以被缩放,默认值是true,表示可以被缩放。

11、inDensity,inTargetDensity,inScreenDensity三个值的具体关系请参看另一篇文章:http://blog.csdn.net/haozipi/article/details/47185917


方法2:

private Bitmap getimage(String srcPath){
    /*
    * BitmapFactory相信大家都很熟悉了,这个类里面的所有方法都是用来解码创建
    * 一个Bitmap,其中有一个重要的类是Options,此类用于解码Bitmap时的各种参数控制,
    * */
    BitmapFactory.Options newOpts = new BitmapFactory.Options();
    newOpts.inJustDecodeBounds = true;//图01
    Bitmap bitmap = BitmapFactory.decodeFile(srcPath,newOpts);此时返回bm为空

    newOpts.inJustDecodeBounds =false;//
     int w = newOpts.outWidth;
     int h = newOpts.outHeight;

     float hh = 800f;//这里设置高度为800f
     float ww = 480f;//这里设置高度480分;

    int be = 1;//1表示不缩放

    if(w>h&&w>ww){//如果宽度大的话根据宽度固定大小缩放
        be = (int)(newOpts.outWidth/ww);
    }else if(w < h && h > hh){
        be = (int) (newOpts.outHeight / hh);
    }
    if(be<=0){
        be = 1;
    }
    newOpts.inSampleSize = be;//这里设置比例
    //重新读入图片,注意这里已经把newOpts.inJustDecodeBounds =false,
    bitmap = BitmapFactory.decodeFile(srcPath,newOpts);
    return compressImage(bitmap);
}

方法3:(其实这种是第一种和第二种合起来用)

// 图片按比例大小压缩方法
private Bitmap comp(Bitmap image) {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    image.compress(Bitmap.CompressFormat.JPEG, 100, out);
    if( out.toByteArray().length / 1024>1024) {//判断如果图片大于1M,进行压缩避免在生成图片(BitmapFactory.decodeStream)时溢出
        out.reset();//重置baos即清空baos
        image.compress(Bitmap.CompressFormat.JPEG, 50, out);//这里压缩50%,把压缩后的数据存放到baos中
    }
    ByteArrayInputStream isBm = new ByteArrayInputStream(out.toByteArray());
    BitmapFactory.Options newOpts = new BitmapFactory.Options();
    //开始读入图片,此时把options.inJustDecodeBounds 设回true了
    newOpts.inJustDecodeBounds = true;
    Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);
    newOpts.inJustDecodeBounds = false;
    int w = newOpts.outWidth;
    int h = newOpts.outHeight;
    //现在主流手机比较多是800*480分辨率,所以高和宽我们设置为
    float hh = 800f;//这里设置高度为800f
    float ww = 480f;//这里设置宽度为480f
    //缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
    int be = 1;//be=1表示不缩放
    if (w > h && w > ww) {//如果宽度大的话根据宽度固定大小缩放
        be = (int) (newOpts.outWidth / ww);
    } else if (w < h && h > hh) {//如果高度高的话根据宽度固定大小缩放
        be = (int) (newOpts.outHeight / hh);
    }
    if (be <= 0)
        be = 1;
    newOpts.inSampleSize = be;//设置缩放比例
    //重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了
    isBm = new ByteArrayInputStream(out.toByteArray());
    bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);
    return compressImage(bitmap);//压缩好比例大小后再进行质量压缩
}

其实博客上有很多封装好的类,直接用起来就很好。

推荐:http://blog.csdn.net/jdsjlzx/article/details/44228935(一叶飘舟)大神















































































  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值