为什么需要压缩?
android中的图片是以Bitmap形式存在的,bitmap的大小和数量会直接影响到手机内存情况。不同大小的手机显示的图片也会不一样,跟分辨率、手机内存、显示的大小都有关系,所以很多时候我们需要对位图进行一些压缩的操作。
质量压缩不会减少图片的像素,它是在保持像素的前提下改变图片的位深及透明度,来达到压缩图片的目的,图片的长,宽,像素都不会改变,那么bitmap所占内存大小是不会变的。
计算bitmap大小
宽 * 高 * 一个像素点占用字节
四种压缩格式
[图片上传失败...(image-e55c37-1535879147605)]
ARGB代表的意思是
A(透明度)
R(red红色)
G(green绿色)
B(blue蓝色)
- ALPHA_8
8位Alpha位图一个像素占用一个字节,只有透明度。A=8 - ARGB_4444
16位的ARGB位图,ARGB各占用4位总共16位,2个字节。 - ARGB_8888
16位的ARGB位图,ARGB各占用8位总共36位,4个字节。 - RGB_565
16位RGB位图没有透明度,2个字节。
1. 质量压缩方式
质量压缩是在不改变图片大小的前提下,改变图片的位深以透明度,来达到压缩的目的。所以通过这种方式压缩的话,实际上我们内存加载进来的bitmap大小也是不会改变的。
但是这种方式会改变图片的文件大小,代码中可以看到通过了byteArray来判断大小,所以适合去传递二进制的图片数据,比如微信分享图片,要传入二进制数据过去,限制32kb之内。
public static Bitmap compressByQuality(Bitmap src, long maxByteSize, boolean recycle) {
if (isEmptyBitmap(src) || maxByteSize <= 0) {
return null;
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int quality = 100;
src.compress(CompressFormat.JPEG, quality, baos);
while (baos.toByteArray().length > maxByteSize && quality > 0) {
baos.reset();
src.compress(CompressFormat.JPEG, quality -= 5, baos);
}
if (quality < 0) {
return null;
}
byte[] bytes = baos.toByteArray();
if (recycle && !src.isRecycled()) {
src.recycle();
}
return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
}
2. 采样率压缩
采样率压缩主要是通过BitmapFactory.Options类的inJustDecodeBunds标识为true,然后返回的bitmap就是一个Null对象,这样可以节约内存空间的开销。
但是这个bitmap的options是包含bitmap的宽高、MimeType参数。我们可以根据这些图片参数去设置options的 inSampleSize参数,通过这个参数我们可以实现图片大小的压缩。
主要压缩步骤
-
BitmapFactory.Options的 inJustDecodeBunds为true并加载图片
-
从BitmapFactory.Options 中取出图片的原始宽高信息,对应outWidth和outHeight
-
根据采样率的规格并结合目标计算出View的所需大小计算出inSampleSize
-
BitmapFactory.Options 的 inJustDecodeBunds 参数设置为false,然后重新加载图片
private Bitmap decodeSampleBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
options.inJustDecodeBounds = false;
Bitmap bm = BitmapFactory.decodeFile(imagePath, options);
return bm;
}
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = height / 2;
while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
** 3. 缩放法压缩(martix)**
/**
* 缩放图片
*
* @param src 源图片
* @param scaleWidth 缩放宽度倍数
* @param scaleHeight 缩放高度倍数
* @param recycle 是否回收
* @return 缩放后的图片
*/
public static Bitmap scale(Bitmap src, float scaleWidth, float scaleHeight, boolean recycle) {
if (isEmptyBitmap(src)) {
return null;
}
Matrix matrix = new Matrix();
matrix.setScale(scaleWidth, scaleHeight);
Bitmap ret = Bitmap.createBitmap(src, 0, 0, src.getWidth(), src
.getHeight(), matrix, true);
if (recycle && !src.isRecycled()) {
src.recycle();
}
return ret;
}
4. RGB_565压缩法
/**
* rgb 565压缩
* @param bm
* @param path
* @return
*/
private Bitmap rgb565(Bitmap bm, String path) {
BitmapFactory.Options options2 = new BitmapFactory.Options();
options2.inPreferredConfig = Bitmap.Config.RGB_565;
bm = BitmapFactory.decodeFile(path, options2);
return bm;
}
5 . createScaledBitmap方式压缩
/**
* 缩放图片
*
* @param src 源图片
* @param newWidth 新宽度
* @param newHeight 新高度
* @param recycle 是否回收
* @return 缩放后的图片
*/
public static Bitmap scale(Bitmap src, int newWidth, int newHeight, boolean recycle) {
if (isEmptyBitmap(src)) {
return null;
}
Bitmap ret = Bitmap.createScaledBitmap(src, newWidth, newHeight, true);
if (recycle && !src.isRecycled()) {
src.recycle();
}
return ret;
}
网友评论