Android-压缩大图到容量超小的图片
2018-05-16 本文已影响15人
Merbng
- 压缩图片的宽高
/**
* 计算图片的压缩比
*
* @param options
* @param reqWidth
* @param reqHeight
* @return
*/
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 = width / 2;
while ((halfHeight / inSampleSize) >= reqHeight &&
(halfWidth / inSampleSize) >= reqWidth) {
inSampleSize*=2;
}
}
return inSampleSize;
}
调用calculateInSampleSize计算压缩比。并解码原图为Bitmap:
/**
* @param imagePath
* @param displayWidth
* @param displayHeight
* @return
*/
private Bitmap compress(String imagePath, int displayWidth, int displayHeight) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;//只测量image 不加载到内存。
BitmapFactory.decodeFile(imagePath, options);//测量image
options.inPreferredConfig = Bitmap.Config.RGB_565;//设置565编码格式,省内存,
options.inSampleSize = calculateInSampleSize(options, displayWidth, displayHeight);
options.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeFile(imagePath, options);//按照Options配置去加载图片到内存
return bitmap;
}
这里比较重要的inJustDecodeBounds字段,当inJustDecodeBounds为true时,调用BitmapFactory.decode时并没有把图片加载到内存中去,只是去测量图片的宽高,不不占用内存,当inSampleSize为false时,调用BitmapFactory.decoe时就把图片加载到内存去了,所有获取bitmap应在inJustDecodeBounds为false后的BitmapFactory.decode去获取。
- 设置编码格式
android中默认格式是ARG8888,我们解码图片一般用ARG565节省图片加载到内存的大小。
ALPHA_8 代表8位Alpha位图
ARGB_4444 代表16位ARGB位图
ARGB_8888 代表32位ARGB位图
RGB_565 代表8位RGB位图
位图位数越高代表其可以存储的颜色信息越多,当然图像也就越逼真
- 图片质量压缩
ByteArrayOutputStream out = new ByteArrayOutputStream();//字节流输出
bitmap.compress(Bitmap.CompressFormat.JPEG,50,out);//压缩成jpeg格式
compress中第一个参数是输出文件的格式,在Bitmap枚举类CompressFormat中定义,有JPEG,PNG
PNG,WEBP,一般选择JPEG,压缩出来的容量小,WEBP很耗时,
耗时时间比较:WEBP>PNG>JPEG,
压缩大小:PNG>WEBP>JPEG.
第二个参数是压缩的质量比例,也就是压缩像素的显示色彩,当100时表示不压缩。当为50时表示压缩50%的质量。设置这个参数可以有效的极大的缩小图片的大小,可以按照自己的需求进行设置,
但建议一般不要大于60.第三个参数就是想要写入的图片数据的字节流数组了。
- 字节流写出文件
我们经过上述步骤后,就拿到了字节流数据了,此时我们可以根据项目需求直接上传字节流或者保存为本地图片再上传。
ByteArrayOutputStream out = new ByteArrayOutputStream();//字节流输出
bitmap.compress(Bitmap.CompressFormat.JPEG, 50, out);//压缩成jpeg格式 压缩像素质量为50%
String fileName = imagePath.substring(imagePath.lastIndexOf("/") + 1, imagePath.lastIndexOf("."));//获取文件名
File outFile = new File("/storage/emulated/0/photoPickTemp", fileName + "_temp.jpeg");//创建压缩后的image文件
try {
if (!outFile.exists()) {//判断文件是否存在
if (outFile.createNewFile()) {//判断创建新文件是否成功
FileOutputStream fos = new FileOutputStream(outFile);
byte[] bytes = out.toByteArray();//字节数组
int count = bytes.length;
fos.write(bytes, 0, count);
fos.close();//关闭流
out.close();
}
}
} catch (Exception e) {
e.printStackTrace();
}
- 获取当前屏幕宽高
工具类
- 封装
public class ImageUtil {
public ImageUtil(){
}
public static File compressImage(String imagePath,int displayWidth,int displayHeight){
BitmapFactory.Options options=new BitmapFactory.Options();
options.inJustDecodeBounds=true;//只测量image 不加载到内存
BitmapFactory.decodeFile(imagePath,options);//测量image
options.inPreferredConfig= Bitmap.Config.RGB_565;//设置565编码格式 省内存
options.inSampleSize=calculateInSampleSize(options,displayWidth,displayHeight);//获取压缩比 根据当前屏幕宽高去压缩图片
options.inJustDecodeBounds=false;
Bitmap bitmap=BitmapFactory.decodeFile(imagePath,options);//按照Options配置去加载图片到内存
ByteArrayOutputStream out=new ByteArrayOutputStream();//字节流输出
bitmap.compress(Bitmap.CompressFormat.JPEG,50,out);//压缩成JPEG格式 压缩像素质量为50%
String fileName=imagePath.substring(imagePath.lastIndexOf("/")+1,imagePath.lastIndexOf("."));//获取文件名称
File outFile=new File("/storage/emulated/0/PhotoPickTemp",fileName+"_temp.jpeg");//创建压缩后的image文件
try {
if(!outFile.exists()){//判断新文件是否存在
if(outFile.createNewFile()){//判断创建新文件是否成功
FileOutputStream fos=new FileOutputStream(outFile);//创建一个文件输出流
byte[] bytes=out.toByteArray();//字节数组
int count=bytes.length;//字节数组的长度
fos.write(bytes,0,count);//写到文件中
fos.close();//关闭流
out.close();
}
}
} catch (IOException e) {
e.printStackTrace();
}
return outFile;
}
public static int calculateInSampleSize(BitmapFactory.Options options,int reqWidth,int reqHeight){//计算图片的压缩比
final int height=options.outHeight;//图片的高度
final int width=options.outWidth;//图片的宽度 单位1px 即像素点
int inSampleSize=1;//压缩比
if(height>reqHeight||width>reqWidth){
final int halfHeight=height/2;
final int halfWidth=width/2;
while ((halfHeight/inSampleSize)>=reqHeight
&&(halfWidth/inSampleSize)>=reqWidth){
inSampleSize*=2;
}
}
return inSampleSize;
}
}