Flutter 学习 之 图片的选择裁切保存
Posted 一叶飘舟
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter 学习 之 图片的选择裁切保存相关的知识,希望对你有一定的参考价值。
在实际任务中免不了对图片进行裁切 文件格式转换 图片的选取等操作 这里做一个记录
1. Flutter 图片选择工具 image_picker
2. 图片裁切工具 image_cropper
3. 图片保存到相册image_gallery_saver
图片选择器
介绍
这里我选择的是image_picker
优点
- 官方出品的插件
- 可以直接调用相册和相机无需提前申请权限
- 可以多选和单选选择丰富
缺点 - 多选需要长按没有明显的提示
使用
- 引用组件
- 封装他的一个方法(以单选为例子)
enum ImageFrom
camera,
gallery
///选择一个图片
///[from] 是相机还是图库
///可选参数
///[maxWidth] 宽度,
///[maxHeight] 高度,
///[imageQuality] 质量
static pickSinglePic(ImageFrom from,
double? maxWidth, double? maxHeight, int? imageQuality) async
ImageSource source;
switch (from)
case ImageFrom.camera:
source = ImageSource.camera;
break;
case ImageFrom.gallery:
source = ImageSource.gallery;
break;
final pickerImages = await ImagePicker().pickImage(
source: source,
imageQuality: imageQuality,
maxWidth: maxWidth,
maxHeight: maxHeight,
);
return pickerImages;
使用:
final pickerImages = await ImageUtil.pickSinglePic(score);
图片裁切
使用
- 引用组件
- 在androidMainifest中增加一个View
<activity
android:name="com.yalantis.ucrop.UCropActivity"
android:screenOrientation="portrait"
android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
- 封装成一个方法
///裁切图片
///[image] 图片路径或文件
///[width] 宽度
///[height] 高度
///[aspectRatio] 比例
///[androidUiSettings]UI 参数
///[iosUiSettings] ios的ui 参数
static cropImage(
required image,
required width,
required height,
aspectRatio,
androidUiSettings,
iOSUiSettings) async
String imagePth = "";
if (image is String)
imagePth = image;
else if (image is File)
imagePth = image.path;
else
throw ("文件路径错误");
final croppedFile = await ImageCropper().cropImage(
sourcePath: imagePth,
maxWidth: FormatUtil.num2int(width),
maxHeight: FormatUtil.num2int(height),
aspectRatio: aspectRatio ??
CropAspectRatio(
ratioX: FormatUtil.num2double(width),
ratioY: FormatUtil.num2double(height)),
uiSettings: [
androidUiSettings ??
AndroidUiSettings(
toolbarTitle:
'图片裁切($FormatUtil.num2int(width)*$FormatUtil.num2int(height))',
toolbarColor: Colors.blue,
toolbarWidgetColor: Colors.white,
initAspectRatio: CropAspectRatioPreset.original,
hideBottomControls: false,
lockAspectRatio: true),
iOSUiSettings ??
IOSUiSettings(
title: 'Cropper',
),
],
);
return croppedFile;
///数字转成Int
///[number] 可以是String 可以是int 可以是double 出错了就返回0;
static num2int(number)
try
if (number is String)
return int.parse(number);
else if (number is int)
return number;
else if (number is double)
return number.toInt();
else
return 0;
catch (e)
return 0;
///数字转成double
///[number] 可以是String 可以是int 可以是double 出错了就返回0;
static num2double(number)
try
if (number is String)
return double.parse(number);
else if (number is int)
return number.toDouble();
else if (number is double)
return number;
else
return 0.0;
catch (e)
return 0.0;
使用
File? _userImage = File(pickerImages.path);
if (_userImage != null)
final croppedFile = await ImageUtil.cropImage(
image: _userImage,
width: 256,
height: 512);
图片保存
- 引入插件
- 封装组件
///保存Uint8List 到相册
///[image]Uint8List 数组
///[quality] 质量
///[name] 保存的名字
static saveImage2Album(image, quality = 100, name = "photo") async
final result =
await ImageGallerySaver.saveImage(image, quality: quality, name: name);
return result;
他还有一个保存文件的方法
_saveVideo() async
var appDocDir = await getTemporaryDirectory();
String savePath = appDocDir.path + "/temp.mp4";
await Dio().download("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4", savePath);
final result = await ImageGallerySaver.saveFile(savePath);
print(result);
使用
保存前注意先申请一下存储权限
PermissionUtil.checkPermission(
permissionList: [Permission.photos, Permission.storage],
onFailed: () => ToastUtil().showCenterToast("图片处理错误"),
onSuccess: () async
final result = await FileUtil.saveImage2Album(finalImgBuffer!,
quality: 100, name: "photo");
if (result != null)
ToastUtil().showCenterToast("保存成功~~~");
else
ToastUtil().showCenterToast("保存失败~~~");
);
Flutter 中对 图片文件的操作
图片间格式的转换等操作
图片文件转换成Base64
转换思路 File=>Uint8List =>Base64
使用场景:有些接口需要多图片上传使用base64进行多组图片上传操作
///文件转 Uint8List
static file2Uint8List(File file) async
Uint8List imageBytes = await file.readAsBytes();
return imageBytes;
/// unit8List 转base64
static uint8List2Base64(Uint8List uint8list)
String base64 = base64Encode(uint8list);
return base64;
Base64转dart.ui中的Image
使用场景:从接口获取的base64要画在Canvas上需要转换的格式
import 'dart:ui' as ui;
///base64 转成需要的Image文件 这个Image是UI 下面的Image和Image widget不同 !!!
///[asset] base64 无头字符串
///[width]宽度
///[height] 高度
static Future<ui.Image> base64ToImage(String asset, width, height) async
Uint8List bytes = base64Decode(asset);
ui.Codec codec = await ui.instantiateImageCodec(bytes,
targetWidth: width, targetHeight: height);
ui.FrameInfo fi = await codec.getNextFrame();
return fi.image;
用Canvas绘画
用 recorder 记录绘画的结果保存Picture
///canvas的记录工具 用来保存canvas的
final recorder = ui.PictureRecorder();
///canvas 绘图工具
Canvas canvas = Canvas(recorder);
///画笔 颜色为传入颜色 状态是填充
Paint paint = Paint();
paint.color = bgColor;
paint.style = PaintingStyle.fill;
///底下跟我画个背景
canvas.drawRect(Rect.fromLTWH(0, 0, width, height), paint);
///顶上再画个人
paint.color = Colors.black;
paint.style = PaintingStyle.stroke;
paint.strokeWidth = 10;
ui.Image image = await base64ToImage(imageFile,
width: width.toInt(), height: height.toInt());
canvas.drawImage(image, Offset.zero, paint);
// 转换成图片
///记录画的canvas
Picture picture = recorder.endRecording();
将Picture 转换成ByteData
最终转换成 Uint8List 显示在屏幕上
///获取到的picture 转换成 ByteData
///[picture] canvas画然后记录的文件
///[width] 宽度
///[height] 高度
static Future<ByteData?> picture2ByteData(
ui.Picture picture, double width, double height) async
ui.Image img = await picture.toImage(width.toInt(), height.toInt());
debugPrint('img的尺寸: $img');
ByteData? byteData = await img.toByteData(format: ui.ImageByteFormat.png);
return byteData;
将ByteData 转成 Uint8List
作用是可以显示在ImageWidget上 或者后续转成Base64 或者直接保存到本地
/// 将ByteData 转成 Uint8List
/// [data] ByteData数据
/// return [Uint8List] Uint8List
static byteData2Uint8List(ByteData data)
return data.buffer.asUint8List();
以上是关于Flutter 学习 之 图片的选择裁切保存的主要内容,如果未能解决你的问题,请参考以下文章
node.js(express)中使用Jcrop进行图片裁切上传
node.js(express)中使用Jcrop进行图片裁切上传