android中bitmap压缩的几种方法详解

Android图片压缩(质量压缩和尺寸压缩)

在做项目中遇到一个头疼的问题,读取本地图片时,由于图片太大,奔溃,对于我这种456M内存的破手机哪里受得了几M的照片
我要总结的有这么几点:


1、尺寸压缩和质量压缩
2、处理过的图片存储本地和sqlite数据库

    先看1: 图片有三种存在形式:硬盘上时是file,网络传输时是stream,内存中是stream或bitmap,
                  质量压缩它其实只能实现对file的影响,,你可以把一个file转成bitmap再转成file,或者直接将一个bitmap转成file时,这个最终的file是                                            被压缩过的,但是中间的bitmap并没有被压缩(或者说几乎没有被压缩,我不确定),因为bigmap在内存中的大小是按像素                                            计算的,也就是width * height,对于质量压缩,并不会改变图片的像素,所以就算质量被压缩了,但是bitmap在内存的占有率                                        还是没变小,但你做成file时,它确实变小了。

                     尺寸压缩:
                                   而尺寸压缩由于是减小了图片的像素,所以它直接对bitmap产生了影响,当然最终的file也是相对的变小了;
                                    尺寸压缩对分辨率的处理      接对bitmap产生了影响,当然最终的file也是相对的变小,影响内存。

上诉就是对这两种压缩方式理解, 看看代码怎么实现的吧:


1、首先:点击你某个控件进入相册界面,我用的是一个图片按钮
circleImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                Intent intent = new Intent();// 开启Pictures画面Type设定为image
                intent.setType("image/*");//
                intent.setAction(Intent.ACTION_GET_CONTENT);
                /*
                 * 得到新打开Activity关闭后返回的数据,你需要使用系统提供的
                 * startActivityForResult(Intent intent,int
                 * requestCode)方法打开新的Activity
                 */
                startActivityForResult(intent, 1);// 取得相片后返回本画面
            }
        });  


2、点击图片将会调用 onActivityResult这个方法,尺寸压缩就这个方法里面实现吧!

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == 1) {// 选取图片的返回值
            if (resultCode == RESULT_OK) {
                Uri uri = data.getData();
                Cursor cursor = getContentResolver().query(uri, nullnull,
                        nullnull);
                cursor.moveToFirst();// 指向查询结果的第一个位置
                String imgPath1 = cursor.getString(1); // 图片文件路径
                String imgSize = cursor.getString(2); // 图片大小   
                String imgName = cursor.getString(3); // 图片文件名   
                BitmapFactory.Options options = new BitmapFactory.Options();
        
                // 此时把options.inJustDecodeBounds 设回true,即只读边不读内容
                options.inJustDecodeBounds = true;
                // 默认是Bitmap.Config.ARGB_8888
                options.inPreferredConfig = Bitmap.Config.RGB_565
                try {
                //此时不会把图片读入内存,只会获取图片宽高等信息
                Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver()
                .openInputStream(uri), null, options);
                //上面一句和下面的类似
                //Bitmap bitmap = BitmapFactory.decodeFile(imgPath,options);
                int heitht = options.outHeight;
                // 根据需要设置压缩比例
                int size = heitht / 800;
                if (size <= 0) {
                size = 2;
                }
                   /*inSampleSize表示缩略图大小为原始图片大小的几分之一,
                      即如果这个值为2,则取出的缩略图的宽和高都是原始图片的1/2,
                      图片大小就为原始大小的1/4*/
                options.inSampleSize = size;
                // 设置options.inJustDecodeBounds重新设置为false
                options.inPurgeable = true;// 同时设置才会有效  
                options.inInputShareable = true;//。当系统内存不够时候图片自动被回收  
                options.inJustDecodeBounds = false;
                //此时图片会按比例压缩后被载入内存中
                bitmap = BitmapFactory.decodeStream(getContentResolver()
                .openInputStream(uri), null, options);
                SaveSD.saveBitmap(imgName,bitmap);//saveBitmap这个是我定义保存到SDcard中的方法
                circleImageView.setImageBitmap(bitmap);
                imgPath="/sdcard/"+imgName;
                } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                }
            }
        }
        super.onActivityResult(requestCode, resultCode, data);
    }      
经过以上的压缩,减少了对内存的消耗,可以显示出,你想要的照片高清的照片咯。

上面讲的是尺寸压缩主要是影响内存,现在讲的是质量压缩,我们把这个过程放在保存的方法中吧。

质量压缩1,保存到sd卡。 保存的时候进行质量压缩,将几M的照片,变为几指定大小的图片

public class SaveSD {
    /**
     * 保存图片到指定文件夹,将图片保存到本地时进行压缩, 即将图片从Bitmap形式变为File形式时进行压缩,
     * 
     * @param imgName
     *            图片名称 bitmap 处理图片对象
     * 
     * 
     * */
    public static void saveBitmap(String imgName, Bitmap bitmap) {
        String sdpath = "/sdcard/";
        
        File file = new File(sdpath, imgName);
        if (file.exists()) {
            file.delete();
        }
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        /* options表示 如果不压缩是100,表示压缩率为0。如果是70,就表示压缩率是70,表示压缩30%; */
        int options = 100;
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        while (baos.toByteArray().length / 1024 > 500) {
            // 循环判断如果压缩后图片是否大于500kb继续压缩
            baos.reset();
            options -= 10;
            // 这里压缩options%,把压缩后的数据存放到baos
            bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);
        }
        try {
            FileOutputStream out = new FileOutputStream(file);
            out.write(baos.toByteArray());
            out.flush();
            out.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

质量压缩2,将头像保存到sqlite数据库, 在实例中是是字节,就是将图片转化成字节存入数据库

public class Person implements Serializable{
    private int id;
    private String call;
    private String name;
    private String sexy;
    private String age;
     private byte[] image;  .......

在看看创建数据库时,Image是 BLOB形式:
/**
     * 数据库第一次创建时回调此方法. 初始化一些表
     */
    @Override
    public void onCreate(SQLiteDatabase db) {
        // TODO Auto-generated method stub
        // 操作数据库
        String sql = "create table person(id integer primary key,call varchar(20), " +
                "name varchar(20),sexy varchar(20),age varchar(20),image BLOB);";
        db.execSQL(sql);
    }   

对bitmap进行质量压缩,并将bitmap转化成 字节形式

public class BitmapToByte {
    /**
     * 保存图片到指定文件夹,将图片保存到本地时进行压缩, 即将图片从Bitmap形式变为File形式时进行压缩,
     * 
     * @param imgName
     *            图片名称 bitmap 处理图片对象
     * 
     * 
     * */
    public static byte[] saveBitmap(Bitmap bitmap) {
    
        int size=bitmap.getWidth()*bitmap.getHeight()*4;
        //创建一个字节数组输出流,流的大小为size
        ByteArrayOutputStream baos=new ByteArrayOutputStream(size);
        //设置位图的压缩格式,质量为100%,并放入字节数组输出流中
        int options = 100;
        /* options表示 如果不压缩是100,表示压缩率为0。如果是70,就表示压缩率是70,表示压缩30%; */
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        while (baos.toByteArray().length / 1024 > 500) {
            // 循环判断如果压缩后图片是否大于500kb继续压缩
            baos.reset();
            options -= 10;
            // 这里压缩options%,把压缩后的数据存放到baos
            bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);
        }
        //将字节数组输出流转化为字节数组byte[]
        
        byte[] imagedata=baos.toByteArray();
        return imagedata;
   
    }
}

最后只要得到这个 imagedata执行插入语句即可

    personDao = new PersonDao(NewMemberActivity.this);// 该对象可以调用操作数据库方法
                
                person = new Person(sCall, sName, sexy, age, imagedata);// 初始化对象数据,imagedata
                personDao.insert(person);// 将对象person插入到数据库  

由于时间有限,说得不是很好,见谅啊
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值