前言
项目中遇到,需要用户上传图片的场景。结果用户上传的、特别是拍摄后的图片,分辨率很大,长宽2000多3000甚至更高,一个图片5MB以上。 造成之后,从网络上加载这些图片,比较慢。
所以,不得不在上传前进行压缩后,再上传。
FileUtils 文件写入
/**
* desc :
* author : stone
* email : aa86799@163.com
* time : 2019/5/29 9:19
*/
public class FileUtils {
//获取指定文件目录的内部文件(路径)
public static File getAlbumStorageDir(Context context, String directory) {
File file;
//有sdcard
if (TextUtils.equals(Environment.getExternalStorageState(), Environment.MEDIA_MOUNTED)) {
file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), directory);
} else {
file = new File(context.getCacheDir(), directory);
}
if (!file.mkdirs()) {
LogUtils.e("ExtensionSignActivity", "Directory not created");
}
return file;
}
//保存 jpg/png的 Bitmap
public static String saveBmp2Local(Context context, Bitmap bmp, String picName, boolean isPng) {
// 声明文件对象
File file = null;
// 声明输出流
FileOutputStream outStream = null;
try {
file = new File(getAlbumStorageDir(context, LFConfig.IMG_DIRECTORY_NAME), picName + (isPng ? ".png" : ".jpg"));
// 获得输出流,如果文件中有内容,追加内容
outStream = new FileOutputStream(file);
bmp.compress(isPng ? Bitmap.CompressFormat.PNG : Bitmap.CompressFormat.JPEG, 90, outStream);
} catch (Exception e) {
e.getStackTrace();
} finally {
try {
if (outStream != null) {
outStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
if (file != null) {
return file.getPath();
}
return null;
}
//保存gif。使用nio写入
public static String saveGif2Local(Context context, ByteBuffer byteBuffer, String picName) throws FileNotFoundException {
// 声明文件对象
File file = null;
// 声明输出流
FileOutputStream outStream = null;
FileChannel channel = null;
try {
file = new File(getAlbumStorageDir(context, LFConfig.IMG_DIRECTORY_NAME), picName + ".gif");
// 获得输出流,如果文件中有内容,追加内容
outStream = new FileOutputStream(file);
channel = outStream.getChannel();
//不能确定channel.write()能一次性写入buffer的所有数据
//所以通过判断是否有余留循环写入
while (byteBuffer.hasRemaining()) {
channel.write(byteBuffer);
}
} catch (Exception e) {
e.getStackTrace();
} finally {
try {
if (outStream != null) {
outStream.close();
}
if (channel != null) {
channel.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
if (file != null) {
return file.getPath();
}
return null;
}
}
Glide加载并压缩
结合rxjava#Obserable,在子线程中, 对图片路径做map变换。
用glide加载图片变换为 Bitmap 或 GifDrawable。
订阅后,进行压缩并保存到本地。
关于gif压缩,暂未考虑。
/**
* 存储到本地
* @param item 原始图片路径
*/
private void compressAndSaveItem(final String item) {
String[] strArray = item.split("\\.");
if (strArray.length > 0 && strArray[strArray.length - 1].toLowerCase().equals("gif")) {//判断后缀名是否是gif
Observable.just(item)
.observeOn(Schedulers.io()) //整体运行行在子线程
.compose(RxJavaUtil.rxLife(PublishProductActivity.this)) //结合了rxlifecycle库
.map(s -> GlideApp.with(PublishProductActivity.this)
.asGif()
.load(s)
.fitCenter()
.submit()//原始分辨率
// .submit(720, 1080) //自定义分辨率
.get())
.subscribe(result -> {
int pointIndex = item.lastIndexOf(".");
int nameStartIndex = item.lastIndexOf("/") + 1;
int end;
if (pointIndex < nameStartIndex) {
end = item.length();
} else {
end = pointIndex;
}
String fileName = item.substring(nameStartIndex, end);
String path = FileUtils.saveGif2Local(PublishProductActivity.this,
result.getBuffer(), fileName + "_copy");
/*
* 有了保存的压缩图片路径 path
* do other thing
*/
}, error -> {
error.printStackTrace();
});
} else {
Observable.just(item)
.observeOn(Schedulers.io())//整体运行行在子线程
.compose(RxJavaUtil.rxLife(PublishProductActivity.this)) //结合了rxlifecycle库
.map(s -> GlideApp.with(PublishProductActivity.this)
.asBitmap()
.load(s)
.fitCenter()
.submit()//原始分辨率
// .submit(720, 1080) //自定义分辨率
.get())
.subscribe(result -> {
int pointIndex = item.lastIndexOf(".");
int nameStartIndex = item.lastIndexOf("/") + 1;
int end;
if (pointIndex < nameStartIndex) {
end = item.length();
} else {
end = pointIndex;
}
String fileName = item.substring(nameStartIndex, end);
//缩放bitmap都为原宽高的1/2
Bitmap scaleBitmap = Bitmap.createScaledBitmap(result,
result.getWidth() / 2, result.getHeight() / 2, true);
String path = FileUtils.saveBmp2Local(PublishProductActivity.this, scaleBitmap
, fileName + "_copy",
strArray[strArray.length - 1].toLowerCase().equals("png"));
/*
* 有了保存的压缩图片路径 path
* do other thing
*/
}, error -> {
error.printStackTrace();
});
}
遇到了gif图片不显示的问题
太坑了,GifDrawable # getBuffer(),用nio保存的逻辑是没问题的。结果保存后的图片,无法展示了,貌似可能是Glide的bug,只能 删除掉 gif相关的代码,不使用glide处理了。