您的位置:首页 > 移动开发 > Android开发

Android图片压缩(质量压缩和尺寸压缩)、图片保存(本地和sqlite数据库)

2015-09-21 14:58 519 查看


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, null, null,
null, null);
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插入到数据库

由于时间有限,说得不是很好,见谅啊

本人项目中的效果图:

点击完成后
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: