flutter_luban和flutter_image_compress
最近在做flutter的项目的时候用到了图片上传和图片压缩,开始使用的压缩库是flutter_luban,压缩的效果不错,但是在一些比较老的手机上面压缩的效率很慢,一个5、6M的图片压缩需要大概30秒的时间,后来获取图片的时候先把图片的质量缩小了,然后再压缩,压缩的时长并没有改变。再后来只能先换了一个三方库flutter_image_compress先解决问题,然后有时间研究了下之前的库压缩慢的问题进行对比。
flutter_luban压缩介绍
flutter_luban方法调用起来也比较简单,先将需要压缩的图片封装到CompressObject类中,然后调用Luban.compressImage既可。
CompressObject compressObject = CompressObject(
imageFile: image,
path: path
);
Luban.compressImage(compressObject).then((_path) {
// _path为压缩后图片路径
File newImage = new File(_path);
});
然后来看下compressImage方法的具体实现
static Future<String> compressImage(CompressObject object) async {
return compute(_lubanCompress, object);
}
然后就是调用到了_lubanCompress这个方法。从这个方法可以看出,flutter_luban只支持jpg和png格式的图片压缩,然后基本的步骤为
- 图片的宽高进行的一系列的计算和校验
- 然后根据不同的请款进行不同的压缩方式,其中例如宽高比例在0.5626到1之间,高度小于1664,图片大小小于150K,则按照传入的压缩比例进行图片质量压缩。
- 如果不需要直接进行质量压缩的,会根据传入的压缩模式进行压缩
- 没有传入压缩模式的,则根据图片大小,大于500K则进行_small2LargeCompressImage,小于500K则进行_large2SmallCompressImage
static String _lubanCompress(CompressObject object) {
// 首先是将文件类型转换为图片类型
// 这个转换过程大概耗费了10S左右,因为需要大量的计算
Image image = decodeImage(object.imageFile.readAsBytesSync());
var length = object.imageFile.lengthSync();
print(object.imageFile.path);
bool isLandscape = false;
// 这里可以看出该算法只支持jpg和png的图片类型
const List<String> jpgSuffix = ["jpg", "jpeg", "JPG", "JPEG"];
const List<String> pngSuffix = ["png", "PNG"];
// 判断图片类型
bool isJpg = _parseType(object.imageFile.path, jpgSuffix);
bool isPng = false;
if (!isJpg) isPng = _parseType(object.imageFile.path, pngSuffix);
// 获取图片大小,保持高>宽的方向,计算宽高比
double size;
int fixelW = image.width;
int fixelH = image.height;
double thumbW = (fixelW % 2 == 1 ? fixelW + 1 : fixelW).toDouble();
double thumbH = (fixelH % 2 == 1 ? fixelH + 1 : fixelH).toDouble();
double scale = 0;
if (fixelW > fixelH) {
scale = fixelH / fixelW;
var tempFixelH = fixelW;
var tempFixelW = fixelH;
fixelH = tempFixelH;
fixelW = tempFixelW;
isLandscape = true;
} else {
scale = fixelW / fixelH;
}
// 存储文件
var decodedImageFile;
if (isJpg)
decodedImageFile = new File(
object.path + '/img_${DateTime.now().millisecondsSinceEpoch}.jpg');
else if (isPng)
decodedImageFile = new File(
object.path + '/img_${DateTime.now().millisecondsSinceEpoch}.png');
else
throw Exception("flutter_luban don't support this image type");
if (decodedImageFile.existsSync()) {
decodedImageFile.deleteSync();
}
// 对于图片的长款进行一系列的计算
var imageSize = length / 1024;
if (scale <= 1 && scale > 0.5625) {
if (fixelH < 1664) {
if (imageSize < 150) {
// 如果宽高比例在0.5626到1之间,高度小于1664,图片大小小于150K,则按照传入的压缩比例进行图片质量压缩
decodedImageFile
.writeAsBytesSync(encodeJpg(image, quality: object.quality));
return decodedImageFile.path