这是【Flutter 问题系列第 74 篇】,如果觉得有用的话,欢迎关注专栏。
- 一:问题描述
- 二:引入,获取依赖
- 三:根据数据类型指定压缩方式
- 3-1:Uint8List → Uint8List
- 3-2:File → File
- 3-3:File → Uint8List
- 3-4:Asset → Uint8List
- 解释说明
- 四:完整代码
项目中用到了百度 OCR 图像识别的功能,如果上传的图片大于 4 兆的话,就会提示因图片过大识别失败。
所以需要对上传的图像进行压缩,在 Flutter 中如何对图像数据进行压缩呢?
二:引入,获取依赖这里用到了 pub 上的第三方插件库 flutter_image_compress,同时支持在 Android 和 iOS 上运行。截止到发文最新版本是 1.1.0 。
在项目的配置文件 pubspec.yaml
中引入依赖,如下图所示
然后在终端执行 flutter pub get
命令获取依赖。
这里我根据官方文档指定的数据类型,封装了四种不同的图像数据转换的方法,
这里自定义一个压缩图片的工具类 CompressUtil
,并指定其最小分辨率的高度和宽度。
如下代码所示
class CompressUtil {
static int minHeight = 1920; // 指定最小分辨率的高度
static int minWidth = 1080; // 指定最小分辨率的宽度
}
然后在当前工具类中,定义了如下四个压缩的方法,简单明了,不需要你对插件有了解,直接拿走使用就行。
3-1:Uint8List → Uint8List第一种压缩方式的参数类型是 Uint8List ,返回值类型是 Future
,如下代码所示
/// 压缩方式一 Uint8List -> Uint8List
static Future u8ToU8(Uint8List list) async {
int quality = imageQuality(list.length);
Uint8List result = await FlutterImageCompress.compressWithList(
list,
minWidth: minWidth,
minHeight: minHeight,
quality: quality,
);
debugPrint("压缩后图片的大小:${size(result.length)}");
return result;
}
3-2:File → File
第二种压缩方式的参数类型是 File,返回值类型是 Future
,如下代码所示
/// 压缩方式二 File -> File
static Future fileToFile(File file) async {
// 图片质量
int quality = imageQuality(file.readAsBytesSync().length);
// 缓存路径
Directory cache = await getTemporaryDirectory();
int time = DateTime.now().millisecondsSinceEpoch;
String savePath = cache.path + "/AllenSu_$time.jpg"; // 指定压缩后图片的路径
File? result = await FlutterImageCompress.compressAndGetFile(
file.path,
savePath,
minWidth: minWidth,
minHeight: minHeight,
quality: quality,
);
if (result != null) {
debugPrint("压缩后图片的大小:${size(result.readAsBytesSync().length)}");
}
return result;
}
获取文件路径这里用到了插件 path_provider,需要在 pubspec.yaml
文件中引入。
压缩后图片的路径你可以修改为自定义的路径。
3-3:File → Uint8List第三种压缩方式的参数类型是 File,返回值类型是 Future
,如下代码所示
/// 压缩方式三 File -> Uint8List
static Future fileToU8(File file) async {
// 图片质量
int quality = imageQuality(file.readAsBytesSync().length);
Uint8List? result = await FlutterImageCompress.compressWithFile(
file.path,
minWidth: minWidth,
minHeight: minHeight,
quality: quality,
);
if (result != null) {
debugPrint("压缩后图片的大小:${size(result.length)}");
}
return result;
}
3-4:Asset → Uint8List
第三种压缩方式的参数类型是 String(其实就是图片的路径 path),返回值类型是 Future
,如下代码所示
/// 压缩方式四 Asset -> Uint8List
static Future assetToU8(String assetName) async {
File file = File(assetName);
// 图片质量
int quality = imageQuality(file.readAsBytesSync().length);
Uint8List? result = await FlutterImageCompress.compressAssetImage(
assetName,
minWidth: minWidth,
minHeight: minHeight,
quality: quality,
);
if (result != null) {
debugPrint("压缩后图片的大小:${size(result.length)}");
}
return result!;
}
以上四种压缩图片的方式满足正常开发是没有问题的。
解释说明代码中的方法 imageQuality(int length)
和 size((int length))
是我自己扩展的,原因如下
- 对于方法 imageQuality,是为了根据传入的图片字节长度,返回指定的图片质量。如果你想固定压缩图片的质量,可以不用在意这个方法。
- 对于方法 size,是为了方便查看图片的大小,因为图片的大小是字节数组的长度,看起来不太方便,所以进行了转换,如果图片小于 1 兆,则显示 KB,如果图片大于 1 兆,则显示 MB,并保留一位小数。
我并没有把代码中的注释去掉,因为我觉得你在调试的时候应该可以用得到。
四:完整代码以上是对封装的工具类进行了拆分,对工具类的每个方法进行了解释说明。
但为方便大家复制,最后把完整的代码贴到这里,如下
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/widgets.dart';
import 'package:flutter_image_compress/flutter_image_compress.dart';
import 'package:path_provider/path_provider.dart';
// ------------------------------------------------------
// author:Allen Su
// date :2022/7/9 00:08
// usage :图片压缩工具类
// ------------------------------------------------------
class CompressUtil {
static int minHeight = 1920; // 指定最小分辨率的高度
static int minWidth = 1080; // 指定最小分辨率的宽度
/// 压缩方式一 Uint8List -> Uint8List
static Future u8ToU8(Uint8List list) async {
int quality = imageQuality(list.length);
Uint8List result = await FlutterImageCompress.compressWithList(
list,
minWidth: minWidth,
minHeight: minHeight,
quality: quality,
);
debugPrint("压缩后图片的大小:${size(result.length)}");
return result;
}
/// 压缩方式二 File -> File
static Future fileToFile(File file) async {
// 图片质量
int quality = imageQuality(file.readAsBytesSync().length);
// 缓存路径
Directory cache = await getTemporaryDirectory();
int time = DateTime.now().millisecondsSinceEpoch;
String savePath = cache.path + "/AllenSu_$time.jpg";
File? result = await FlutterImageCompress.compressAndGetFile(
file.path,
savePath,
minWidth: minWidth,
minHeight: minHeight,
quality: quality,
);
if (result != null) {
debugPrint("压缩后图片的大小:${size(result.readAsBytesSync().length)}");
}
return result;
}
/// 压缩方式三 File -> Uint8List
static Future fileToU8(File file) async {
// 图片质量
int quality = imageQuality(file.readAsBytesSync().length);
Uint8List? result = await FlutterImageCompress.compressWithFile(
file.path,
minWidth: minWidth,
minHeight: minHeight,
quality: quality,
);
if (result != null) {
debugPrint("压缩后图片的大小:${size(result.length)}");
}
return result;
}
/// 压缩方式四 Asset -> Uint8List
static Future assetToU8(String assetName) async {
File file = File(assetName);
// 图片质量
int quality = imageQuality(file.readAsBytesSync().length);
Uint8List? result = await FlutterImageCompress.compressAssetImage(
assetName,
minWidth: minWidth,
minHeight: minHeight,
quality: quality,
);
if (result != null) {
debugPrint("压缩后图片的大小:${size(result.length)}");
}
return result!;
}
/// 根据传入的图片字节长度,返回指定的图片质量
static int imageQuality(int length) {
debugPrint("压缩前图片的大小:${size(length)}");
int quality = 100; // 图片质量指数
int m = 1024 * 1024; // 1 兆
if (length = 0.5 * m && length = 1 * m && length = 2 * m && length = 3 * m && length
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?