Android图片实现压缩处理的实例代码
作者:MrZang 发布时间:2022-05-28 20:29:12
标签:Android,图片,压缩
整理文档,搜刮出一个Android图片实现压缩处理的实例代码,稍微整理精简一下做下分享。
详解:
1.获取本地图片File文件 获取BitmapFactory.Options对象 计算原始图片 目标图片宽高比 计算输出的图片宽高
2.根据宽高比计算options.inSampleSize值(缩放比例 If set to a value > 1, requests the decoder to subsample the original image, returning a smaller image to save memory.)得到bitmap位图 根据位图对象获取新的输出位图对象 Bitmap.createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter)Creates a new bitmap, scaled from an existing bitmap, whenpossible.
3.获取图片方向调整、失量压缩图片保持在1024kb以下
//进行大小缩放来达到压缩的目的
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(srcImagePath, options);
//根据原始图片的宽高比和期望的输出图片的宽高比计算最终输出的图片的宽和高
float srcWidth = options.outWidth;
float srcHeight = options.outHeight;
float maxWidth = outWidth;
float maxHeight = outHeight;
float srcRatio = srcWidth / srcHeight; //原始图片宽高比
float outRatio = maxWidth / maxHeight; //目标图片宽高比
float actualOutWidth = srcWidth;
float actualOutHeight = srcHeight;
if (srcWidth > maxWidth || srcHeight > maxHeight) {
if(srcRatio>outRatio){ //原始宽高比大于目标宽高比
actualOutWidth = maxWidth;
actualOutHeight = actualOutWidth / srcRatio;
}else if(srcRatio<outRatio){ //原始宽高比小于目标宽高比
actualOutHeight = maxHeight;
actualOutWidth = actualOutHeight * srcRatio;
}
}else{
actualOutWidth = maxWidth;
actualOutHeight = maxHeight;
}
options.inSampleSize = computSampleSize(options, actualOutWidth, actualOutHeight);
options.inJustDecodeBounds = false;
Bitmap scaledBitmap = null;
try {
scaledBitmap = BitmapFactory.decodeFile(srcImagePath, options);
} catch (OutOfMemoryError e) {
e.printStackTrace();
}
if (scaledBitmap == null) {
return null;
}
//生成最终输出的bitmap
Bitmap actualOutBitmap = Bitmap.createScaledBitmap(scaledBitmap, (int) actualOutWidth, (int) actualOutHeight, true);
//释放原始位图资源
if(scaledBitmap!=actualOutBitmap){ //判断目标位图是否和原始位图指向栈目标相同
scaledBitmap.recycle();
scaledBitmap = null;
}
//处理图片旋转问题
ExifInterface exif = null;
try {
exif = new ExifInterface(srcImagePath);
int orientation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION, 0);
Matrix matrix = new Matrix();
if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
matrix.postRotate(90);
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) {
matrix.postRotate(180);
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {
matrix.postRotate(270);
}
actualOutBitmap = Bitmap.createBitmap(actualOutBitmap, 0, 0,
actualOutBitmap.getWidth(), actualOutBitmap.getHeight(), matrix, true);
} catch (IOException e) {
e.printStackTrace();
return null;
}
//进行有损压缩
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int options_ = 100;
actualOutBitmap.compress(Bitmap.CompressFormat.JPEG, options_, baos);//质量压缩方法,把压缩后的数据存放到baos中 (100表示不压缩,0表示压缩到最小)
int baosLength = baos.toByteArray().length;
while (baosLength / 1024 > maxFileSize) {//循环判断如果压缩后图片是否大于maxMemmorrySize,大于继续压缩
baos.reset();//重置baos即让下一次的写入覆盖之前的内容
options_ = Math.max(0, options_ - 10);//图片质量每次减少10
actualOutBitmap.compress(Bitmap.CompressFormat.JPEG, options_, baos);//将压缩后的图片保存到baos中
baosLength = baos.toByteArray().length;
if (options_ == 0)//如果图片的质量已降到最低则,不再进行压缩
break;
}
actualOutBitmap.recycle();
//将bitmap保存到指定路径
FileOutputStream fos = null;
String filePath = getOutputFileName(srcImagePath);
try {
fos = new FileOutputStream(filePath);
//包装缓冲流,提高写入速度
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fos);
bufferedOutputStream.write(baos.toByteArray());
bufferedOutputStream.flush();
} catch (FileNotFoundException e) {
return null;
} catch (IOException e) {
return null;
} finally {
if (baos != null) {
try {
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//获取位图缩放比例
private int computSampleSize(BitmapFactory.Options options, float reqWidth, float reqHeight) {
float srcWidth = options.outWidth;//20
float srcHeight = options.outHeight;//10
int sampleSize = 1;
if (srcWidth > reqWidth || srcHeight > reqHeight) {
int withRatio = Math.round(srcWidth / reqWidth);
int heightRatio = Math.round(srcHeight / reqHeight);
sampleSize = Math.min(withRatio, heightRatio);
}
return sampleSize;
}
压缩比例换算:
float srcWidth = options.outWidth;
float srcHeight = options.outHeight;
float widthScale = outWidth / srcWidth;//目标/原始 宽比例
float heightScale = outHeight / srcHeight; //目标原始 高比
//对比宽高比选择较大的一种比例
float scale = widthScale > heightScale ? widthScale : heightScale;
float actualOutWidth = srcWidth;
float actualOutHeight = srcHeight;
if (scale < 1) {
actualOutWidth = srcWidth * scale;
actualOutHeight = srcHeight * scale;
}
设置缩放比例--生成新的位图
Matrix matrix1 = new Matrix();
matrix1.postScale(scale, scale);// 放大缩小比例
//生成最终输出的bitmap
Bitmap actualOutBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix1, true);
if (actualOutBitmap != scaledBitmap) {
scaledBitmap.recycle();
scaledBitmap = null;
System.gc();
}
参考:https://github.com/guizhigang/LGImageCompressor
来源:http://www.jianshu.com/p/b468d2a01065?utm_source=tuicool&utm_medium=referral


猜你喜欢
- Feign远程调用Multipartfile参数今天在写业务代码的时候遇到的问题, 前端请求A服务,能正确把参数给到A服务<参数里面包
- Android安装apk文件并适配Android 7.0详解首先在AndroidManifest.xml文件,activity同级节点注册p
- ContentProvider是内容提供者,可以跨进程提供数据。大家都知道,ContentProvider的启动,是在Application
- 一、线程组 /** * A thread group represents a set of threads. In addition,
- 一直做Android前端,今天突然心血来潮想搭建一个后台玩玩。平时都是需要什么样的接口直接出个接口文档扔给后台的兄弟,自己从来不操心他们内部
- Selenium IDE 是Firefox 浏览器的一个插件, 它会记录你对Firefox的操作,并且可以回放它的操作。 用法简单,不过我觉
- 一、String类概述String类代表字符串,java程序中的所有字符串文字(例如"abc")都被实现为此类的实例。也
- 1、AndroidManifest.xml中将activity<activity &nb
- 本文已收录《Java常见面试题》系列,Git 开源地址:https://gitee.com/mydb/interviewHashSet 实现
- 本文实例讲述了winform基于异步委托实现多线程摇奖器。分享给大家供大家参考。具体实现方法如下:using System;using Sy
- 摘要 &n
- 前言C# 时间戳与 标准时间的转其实不难,但需要注意下,基准时间的问题。格林威治时间起点: 1970 年 1 月 1 日的 00:00:00
- 一、代码@Componentpublic class BService { @Autowired &
- Android EditText限制输入字符类型的方法总结前言:最近的项目上需要限制EditText输入字符的类型,就把可以实现这个功能的方
- spring的refresh方法前置知识方法入口// org.springframework.context.support.Abstrac
- JPA主键@Id,@IdClass,@Embeddable,@EmbeddedId1、自动主键默认情况下,主键是一个连续的64位数字(lon
- 前言 之前的文章有介绍ActivityGroup,不少人问嵌套使用的问题,同样的需求在Fragment中也存在,幸好在最新的An
- Dubbo服务暴露机制前言在进行服务暴露机制的分析之前,必须谈谈什么是URL,在Dubbo服务暴露过程中URL是无处不在的,贯穿了整个过程。
- spring mvc中的@PathVariable是用来获得请求url中的动态参数的,十分方便,复习下: @Controller publ
- 在App中经常看到这样的tab底部导航栏那么这种效果是如何实现,实现的方式有很多种,最常见的就是使用Fragment+RadioButton