遇坑过程
想保存Glide的缓存图片(失败)
一开始是想用Glide的硬盘缓存图片的,不过他计算的key值无法获取到(或许我不会),那就无法知道文件名字,这方法不行
自己用BitmapFactory压缩(忽大忽小)
上网看https://blog.csdn.net/jdsjlzx/article/details/44228935,用BitmapFactory压缩,效果是有些图片是尺寸是会变小,可是有些体积反而变大了(这也不太对)
下面是核心代码的使用demo
使用方法save(getimage(imagePath), Environment.getExternalStorageDirectory()+"/2.png", Bitmap.CompressFormat.PNG);
/**
* 图片按比例大小压缩方法
*
* @param srcPath (根据路径获取图片并压缩)
* @return
*/
public static Bitmap getimage(String srcPath) {
BitmapFactory.Options newOpts = new BitmapFactory.Options();
// 开始读入图片,此时把options.inJustDecodeBounds 设回true了
newOpts.inJustDecodeBounds = true;
Bitmap bitmap = BitmapFactory.decodeFile(srcPath, newOpts);// 此时返回bm为空
newOpts.inJustDecodeBounds = false;
int w = newOpts.outWidth;
int h = newOpts.outHeight;
float hh = 2560f;// 图片最大的高度为
float ww = 1440f;// 图片最大的宽度为
// 缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
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了
bitmap = BitmapFactory.decodeFile(srcPath, newOpts);
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 = 90;
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数据生成图片
return bitmap;
}
/**
* 保存图片
*
* @param src 源图片
* @param filePath 要保存到的文件路径
* @param format 格式
* @return {@code true}: 成功<br>{@code false}: 失败
*/
public static boolean save(Bitmap src, String filePath, Bitmap.CompressFormat format) throws IOException {
return save(src, (new File(filePath)), format);
}
/**
* 保存图片
*
* @param src 源图片
* @param file 要保存到的文件
* @param format 格式
* @return {@code true}: 成功<br>{@code false}: 失败
*/
public static boolean save(Bitmap src, File file, Bitmap.CompressFormat format) throws IOException {
return save(src, file, format, false);
}
/**
* 保存图片
*
* @param src 源图片
* @param filePath 要保存到的文件路径
* @param format 格式
* @param recycle 是否回收
* @return {@code true}: 成功<br>{@code false}: 失败
*/
public static boolean save(Bitmap src, String filePath, Bitmap.CompressFormat format, boolean recycle) throws IOException {
return save(src, (new File(filePath)), format, recycle);
}
/**
* 保存图片
*
* @param src 源图片
* @param file 要保存到的文件
* @param format 格式
* @param recycle 是否回收
* @return {@code true}: 成功<br>{@code false}: 失败
*/
public static boolean save(Bitmap src, File file, Bitmap.CompressFormat format, boolean recycle) throws IOException {
if (isEmptyBitmap(src) || file.exists()) return false;
System.out.println(src.getWidth() + ", " + src.getHeight());
OutputStream os = null;
boolean res = false;
try {
os = new BufferedOutputStream(new FileOutputStream(file));
res = src.compress(format, 100, os);
if (recycle && !src.isRecycled()) src.recycle();
} catch (IOException e) {
e.printStackTrace();
} finally {
os.close();
}
return res;
}
/**
* 判断bitmap对象是否为空
*
* @param src 源图片
* @return {@code true}: 是<br>{@code false}: 否
*/
private static boolean isEmptyBitmap(Bitmap src) {
return src == null || src.getWidth() == 0 || src.getHeight() == 0;
}
最后Luban完美解决
最后看到https://github.com/Curzibn/Luban/blob/master/README.md,使用Luban压缩,可以完美解决问题
Luban.with(this)
.load(path1) // 传人要压缩的图片列表
.ignoreBy(100) // 忽略不压缩图片的大小
.setTargetDir(Environment.getExternalStorageDirectory()+"/aaaaa") // 设置压缩后文件存储位置
.setCompressListener(new OnCompressListener() { //设置回调
@Override
public void onStart() {
// TODO 压缩开始前调用,可以在方法内启动 loading UI
}
@Override
public void onSuccess(File file) {
// TODO 压缩成功后调用,返回压缩后的图片文件
Log.d(TAG, "onSuccess: "+file.exists());
}
@Override
public void onError(Throwable e) {
// TODO 当压缩过程出现问题时调用
Log.d(TAG, "onError: "+e);
}
}).launch(); //启动压缩
总结
因为以前也没想过与研究压缩图片的事情,一开始时候一直想的事情是控制图片尺寸,最后发现尺寸一样的图片,人看上去也一样的图片,而大小可能相差很大。