图片压缩有很多方式
第一种,推荐使用一款三方的PictureSelector
源码地址https://github.com/wildma/PictureSelector
// 进入相册 以下是例子:用不到的 api 可以不写
PictureSelector.create(MainActivity.this)
.openGallery()//全部.PictureMimeType.ofAll()、图片.ofImage()、视频.ofVideo()
.theme()//主题样式(不设置为默认样式) 也可参考 demo values/styles 下 例如:R.style.picture.white.style
.maxSelectNum()// 最大图片选择数量 int
.minSelectNum()// 最小选择数量 int
.imageSpanCount(4)// 每行显示个数 int
.selectionMode()// 多选 or 单选 PictureConfig.MULTIPLE or PictureConfig.SINGLE
.previewImage()// 是否可预览图片 true or false
.previewVideo()// 是否可预览视频 true or false
.enablePreviewAudio() // 是否可播放音频 true or false
.compressGrade()// luban 压缩档次,默认 3 档 Luban.THIRD_GEAR、Luban.FIRST_GEAR、Luban.CUSTOM_GEAR
.isCamera()// 是否显示拍照按钮 true or false
.isZoomAnim(true)// 图片列表点击 缩放效果 默认 true
.sizeMultiplier(0.5f)// glide 加载图片大小 0~1 之间 如设置 .glideOverride()无效
.setOutputCameraPath("/CustomPath")// 自定义拍照保存路径,可不填
.enableCrop()// 是否裁剪 true or false
.compress()// 是否压缩 true or false
.compressMode()//系统自带 or 鲁班压缩 PictureConfig.SYSTEM_COMPRESS_MODE or LUBAN_COMPRESS_MODE
.glideOverride()// int glide 加载宽高,越小图片列表越流畅,但会影响列表图片浏览的清晰度
.withAspectRatio()// int 裁剪比例 如 16:9 3:2 3:4 1:1 可自定义
.hideBottomControls()// 是否显示 uCrop 工具栏,默认不显示 true or false
.isGif()// 是否显示 gif 图片 true or false
.freeStyleCropEnabled()// 裁剪框是否可拖拽 true or false
.circleDimmedLayer()// 是否圆形裁剪 true or false
.showCropFrame()// 是否显示裁剪矩形边框 圆形裁剪时建议设为 false true or false
.showCropGrid()// 是否显示裁剪矩形网格 圆形裁剪时建议设为 false true or false
.openClickSound()// 是否开启点击声音 true or false
.selectionMedia()// 是否传入已选图片 List<LocalMedia> list
.previewEggs()// 预览图片时 是否增强左右滑动图片体验(图片滑动一半即可看到上一张是否选中) true or false
.cropCompressQuality()// 裁剪压缩质量 默认 90 int
.compressMaxKB()//压缩最大值 kb compressGrade()为 Luban.CUSTOM_GEAR 有效 int
.compressWH() // 压缩宽高比 compressGrade()为 Luban.CUSTOM_GEAR 有效 int
.cropWH()// 裁剪宽高比,设置如果大于图片本身宽高则无效 int
.rotateEnabled() // 裁剪是否可旋转图片 true or false
.scaleEnabled()// 裁剪是否可放大缩小图片 true or false
.videoQuality()// 视频录制质量 0 or 1 int
.videoSecond()// 显示多少秒以内的视频 or 音频也可适用 int
.recordVideoSecond()//视频秒数录制 默认 60s int
.forResult(PictureConfig.CHOOSE_REQUEST);//结果回调 onActivityResult code
第二种,ImageUtil工具类
public class ImageUtil {
private static File file;
/**
* 保存图片
*
* @param newbitmap
* @param sNewImagePath
* @param isLargeProportion 是否为大比例图片
* @param quality 基本压缩比
* @return
* SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss MM");
String date = sDateFormat.format(new java.util.Date());
*/
public static boolean saveImage(Bitmap newbitmap, String sNewImagePath, boolean isLargeProportion, int quality) {
try {
File filedir = new File(Environment.getExternalStorageDirectory().getAbsolutePath());
if (!filedir.exists()) {
filedir.mkdirs();
}
File file = new File(sNewImagePath);
if (!file.exists()) {
file.createNewFile();
}
final FileOutputStream fileout = new FileOutputStream(sNewImagePath);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int options = quality;
newbitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);
if (!isLargeProportion) {
while (baos.toByteArray().length / 1024 > 100) {
baos.reset();
options -= 10;
newbitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);
}
}
baos.writeTo(fileout);
baos.flush();
baos.close();
fileout.flush();
fileout.close();
return true;
} catch (Exception e) {
System.gc();
return false;
} finally {
// if (newbitmap != null && !newbitmap.isRecycled()) {
// newbitmap.recycle();
// newbitmap = null;
// }
}
}
/**
* 图片按比例大小压缩方法(根据Bitmap图片压缩)
*
* @param image
* @return
*/
public static Bitmap getImage(Bitmap image) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
if (baos.toByteArray().length / 1024 > 1024) {// 判断如果图片大于1M,进行压缩避免在生成图片(BitmapFactory.decodeStream)时溢出
baos.reset();// 重置baos即清空baos
image.compress(Bitmap.CompressFormat.JPEG, 50, baos);// 这里压缩50%,把压缩后的数据存放到baos中
}
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
BitmapFactory.Options newOpts = new BitmapFactory.Options();
// 开始读入图片,此时把options.inJustDecodeBounds 设回true了
newOpts.inJustDecodeBounds = true;
Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);
newOpts.inJustDecodeBounds = false;
int w = newOpts.outWidth;
int h = newOpts.outHeight;
// 现在主流手机比较多是800*480分辨率,所以高和宽我们设置为
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了
isBm = new ByteArrayInputStream(baos.toByteArray());
bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);
if (isBm != null) {
try {
isBm.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (image != null && !image.isRecycled()) {
image.recycle();
image = null;
}
return compressImage(bitmap);// 压缩好比例大小后再进行质量压缩
}
/**
* 图片的质量压缩方法
*
* @param image
* @return
*/
public 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数据生成图片
if (baos != null) {
try {
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (isBm != null) {
try {
isBm.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (image != null && !image.isRecycled()) {
image.recycle();
image = null;
}
return bitmap;
}
public static final String str = Environment.getExternalStorageDirectory().getAbsolutePath()+"/DCIM/Camera";
// 这是路径
/**
* 生成文件夹
*
* @param filePath 图片保存的路径(先创建文件夹)
* @param url 下载的url
* @param imgName 图片的名称
* @param mContext 上下文
*/
public static void makeRootDirectory(String filePath, String url, String imgName, Activity mContext) {
try {
if (file == null) {
file = new File(filePath);
}
if (!file.exists()) {
file.mkdir();
}
DownLoadImg(file.toString(), url, imgName,mContext);
} catch (Exception e) {
}
}
/**
* 下载图片
*
* @param filePath 图片保存的路径
* @param url 下载的url
* @param imgName 图片的名称
*/
public static void DownLoadImg(String filePath, String url, String imgName, final Activity mContext) {
ToastUtil.getInstance().toastCentent("正在保存");
OkHttpUtils
.get()
.url(url)
.build()
.execute(new FileCallBack(filePath, imgName) {
@Override
public void inProgress(float progress) {
}
@Override
public void onError(Request request, Exception e) {
ToastUtil.getInstance().toastCentent("保存失败");
}
@Override
public void onResponse(File response) {
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri uri = Uri.fromFile(response);
intent.setData(uri);
mContext.sendBroadcast(intent);//发送广播,告诉相册刷新
ToastUtil.getInstance().toastCentent("保存成功");
}
});
}
}