概述
在个人中心得图片选择上传功能的时候,一般为了节省流量和保证上传的成功率,都会选择压缩上传.其中涉及到了如下一些注意事项.
一. 图片压缩
android 系统的图片压缩大体上有三种方式,质量压缩,比例压缩,采样率压缩
质量压缩
在保持像素的前提下改变图片的位深及透明度,其有如下的缺陷:
- 压缩后的图片文件大小会有改变,但是导入成bitmap后占得内存是不变的
- 因为要保持像素不变,所以它就无法无限压缩
- 不适用于缩略图,也不适用于想减少内存的占用.仅使用于想在保证图片质量的同时减少文件大小的情况
质量压缩的模板代码
public Bitmap compressImage(Bitmap image,int imageSize) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
int options = 100;
while ( baos.toByteArray().length / 1024>imageSize) { //循环判断压缩后图片是否大于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;
}
比例压缩
通过改变bitmap的宽高,可以显著改变图片大小,但是如果缩放过度了,图片也会变得模糊
比例压缩的模板代码
public static Bitmap getCompressBitmapByScale(Bitmap bitmap, int maxW, int maxH) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
float sx = (float) maxW / (float) w;
float sy = (float) maxH / (float) h;
Matrix matrix = new Matrix();
matrix.setScale(sx, sy);
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
采样率压缩
主要是利用BitmapFactory.Options.inSampleSize来实现图片的压缩,
比例压缩的模板代码:
public void scalePic(int reqWidth,int reqHeight) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;//只解码图片解码边界信息
BitmapFactory.decodeResource(getResources(), R.mipmap.demo, options);
options.inSampleSize = calculateInSampleSize(options, reqWidth,reqHeight);
options.inJustDecodeBounds = false;//根据已经得到的缩放比例得到自己想要的图片缩放图
bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.demo, options);
postInvalidate();
}
//计算inSampleSize
public 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 heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
采样率为1的时候为原始大小,为2的时候,宽高为原来的1/2,像素数和占用内存数为原来1/4,采样率是2的指数。
二. 图片旋转
在开发过程中,经常会出现图片在裁剪的时候会出现转屏.
这里需要借助ExifInterface
接口,关于其介绍可以参见: Android ExifInterface 学习笔记,图片旋转的操作。
ExifInterface
类主要描述多媒体文件比如JPG格式图片的一些附加信息.通过ExifInterface
获取图片旋转角度后再用Matrix
对图片进行旋转即可
模板代码:
public void setImageBitmap(Bitmap bitmap, ExifInterface exif) {
if (bitmap == null) {
return;
}
if (exif == null) {
setImageBitmap(bitmap);
return;
}
final Matrix matrix = new Matrix();
final int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
int rotate = -1;
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_270:
rotate = 270;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotate = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_90:
rotate = 90;
break;
}
if (rotate == -1) {
setImageBitmap(bitmap);
} else {
matrix.postRotate(rotate);
final Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap,
0,
0,
bitmap.getWidth(),
bitmap.getHeight(),
matrix,
true);
setImageBitmap(rotatedBitmap);
bitmap.recycle();
}
}