在我们Android的实际开发中,显示很多图片,总会出现内存溢出的问题。为了避免出现OOM,我们总会使用到图片压缩,LruCache技术。今天,我这里说说图片的压缩技术,尺度压缩和质量压缩。
首先我们了解基本的概念,尺度压缩是指:设置采样率,减少像素点,达到图片的压缩;
/**
* 对图片进行尺度压缩
* */
public static Bitmap zoomBitmap(String path){
BitmapFactory.Options newOpts = new BitmapFactory.Options();
// 开始读入图片,此时把options.inJustDecodeBounds 设回true了
newOpts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, newOpts);
int w = newOpts.outWidth;
int h = newOpts.outHeight;
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了
newOpts.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(path, newOpts);
}
图片压缩关键点是:设置边界属性为true,然后设置采样比,最后设置边界属性,读取图片。边界数据设置为true,Google这样解释的:
/**
* If set to true, the decoder will return null (no bitmap), but
* the out... fields will still be set, allowing the caller to query
* the bitmap without having to allocate the memory for its pixels.
*/
public boolean inJustDecodeBounds;
就是不会图片分配内存,但是我们可以获取图片的属性,高和宽。采样比的计算:原图片的图片的高和宽和我们想要显示的图片高宽大小的比值最小。计算如下:
public static int computeImageSampleSize(int srcWidth, int srcHeight, int targetWidth,
int targetHeight) {
int widthScale = (int) Math.ceil((float) srcWidth / targetWidth);
int heightScale = (int) Math.ceil((float) srcHeight / targetHeight);
return Math.min(widthScale, heightScale);
}
质量压缩:减少图片的透明度,和饱和度,而Bitmap内存大小不会变,就是图片的高度和宽度不会变;
/**
* 对bitmap进行质量压缩
* */
private static Bitmap compressImage(Bitmap image) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);// 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
int options = 100;
while (baos.toByteArray().length / 1024 > 100) { // 循环判断如果压缩后图片是否大于100kb,大于继续压缩
baos.reset();// 重置baos即清空baos
image.compress(Bitmap.CompressFormat.JPEG, options, baos);// 这里压缩options%,把压缩后的数据存放到baos中
options -= 10;// 每次都减少10
}
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中
Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);// 把ByteArrayInputStream数据生成图片
return bitmap;
}
质量压缩,只要设置压缩率:上面的代码是把图片质量压缩到100Kb以内,最后返回bitmap。
好了,今天就说到这了,希望对大家有所帮助。