拍照指定裁剪大小

秋天来了

今年的冬天会比往年冷吗

也许要看棉被的厚度

需求来了

(1)自定义拍照界面。预览相机,并在上面添加其他操作的组件。如切换相机,拍照按钮,手电筒。

(2)拍好照片后直接裁剪指定范围。拍照的时候获取到照片为指定尺寸的全屏照片,如480p或720p或1080p。拍好照片后,上传到服务器为了减少识别压力,则裁剪照片获取中间部分。

实现的效果

省流-> 编写的DEMO地址

一、自定义拍照

1. 集成

官网提供了使用教程使用 Camera 插件实现拍照功能,按完整样例可以实现。

方便在页面中使用,则将

java 复制代码
void _initializeCamera() async {
    // Ensure that plugin services are initialized so that `availableCameras()`
    // can be called before `runApp()`
    WidgetsFlutterBinding.ensureInitialized();
​
    // Obtain a list of the available cameras on the device.
    final cameras = await availableCameras();
​
    // Get a specific camera from the list of available cameras.
    firstCamera = cameras.first;
​
    // To display the current output from the Camera,
    // create a CameraController.
    _controller = CameraController(
        // Get a specific camera from the list of available cameras.
        cameras.first,
        // Define the resolution to use.
        ResolutionPreset.high,
        enableAudio: false,
        imageFormatGroup: ImageFormatGroup.jpeg);
​
    // Next, initialize the controller. This returns a Future.
    _initializeControllerFuture = _controller.initialize();
​
    _valueNotifier.value = true;
  }

放到initState中进行初始化。

2. 提速

另一个需要注意点:final image = await _controller.takePicture();执行时间在3-4秒的处理时间,比常规的拍照慢了好多。

多次测试和验证后,确认原因为: "对焦"

解决方法:在拍照前,锁定聚焦。

csharp 复制代码
      // 设置对焦,提高拍照效率
      await _controller.setFocusMode(FocusMode.locked);
      await _controller.setExposureMode(ExposureMode.locked);

二、裁剪

自定义拍照后返回一个XFile可获取照片保存的路径。在上传之前,不需要用户手动裁剪,直接截取照片的指定位置(demo中为获取中间部分)。

1. 文件转ui.Image类型

读取文件转为ui.Image如下:

scss 复制代码
//通过 文件读取Image
  static Future<ui.Image> loadImageByFile(String path) async {
    var list = await File(path).readAsBytes();
    return loadImageByUint8List(list);
  }
​
  //通过[Uint8List]获取图片
  static Future<ui.Image> loadImageByUint8List(Uint8List list) async {
    ui.Codec codec = await ui.instantiateImageCodec(list);
    ui.FrameInfo frame = await codec.getNextFrame();
    return frame.image;
  }
2. 裁剪

获取到ui.Image后,使用PictureRecorder后将图片绘制需要的部分,并保存为ui.Image

ini 复制代码
double width = background.width.toDouble();
    double height = background.height.toDouble();
    PictureRecorder recorder = PictureRecorder();
    Canvas canvas = Canvas(recorder);
    Rect rect = Rect.fromLTWH(0, height / 3, width, height / 3);
    Rect dstRect = Rect.fromLTWH(0, 0, width, height / 3);
    canvas.drawImageRect(background, rect, dstRect, Paint());
    Picture picture = recorder.endRecording();
    ui.Image image = await picture.toImage(width.toInt(), height ~/ 3);
3. 保存到临时文件

裁剪好图片后,写入到文件,或展示。

ini 复制代码
// 写入到文件夹中
    ByteData? byteData = await image.toByteData(format: ImageByteFormat.png);
    if (null != byteData) {
      try {
        final Directory appCache = await getApplicationCacheDirectory();
        var filePath = "${appCache.path}/test${DateTime.now().millisecondsSinceEpoch}.png";
        File file = File(filePath);
        file = await file.writeAsBytes(byteData.buffer.asUint8List());
​
        setState(() {
          _croppedImagePath = file.path;
        });
      } on MissingPlatformDirectoryException catch (e) {
        debugPrint("保存图片失败,${e.message}");
      }
    }

保存到data/data/包名/cache/的目录下,可以自行切换。

三、 完成

搜索了很久没有找到flutter来实现裁剪图片的,有一个库image_cropper,主要还是需要用户参与,然后移动框进行裁剪,不是很符合我们的要求。

参考了Flutter 绘制番外 | 将你的 Canvas 绘制保存为图片提供的方法。此方法太好用了,不知道还真想不到。

相关推荐
君蓦6 小时前
Flutter 本地存储与数据库的使用和优化
flutter
problc15 小时前
Flutter中文字体设置指南:打造个性化的应用体验
android·javascript·flutter
lqj_本人1 天前
鸿蒙next选择 Flutter 开发跨平台应用的原因
flutter·华为·harmonyos
lqj_本人1 天前
Flutter&鸿蒙next 状态管理框架对比分析
flutter·华为·harmonyos
起司锅仔1 天前
Flutter启动流程(2)
flutter
hello world smile1 天前
最全的Flutter中pubspec.yaml及其yaml 语法的使用说明
android·前端·javascript·flutter·dart·yaml·pubspec.yaml
lqj_本人1 天前
Flutter 的 Widget 概述与常用 Widgets 与鸿蒙 Next 的对比
flutter·harmonyos
iFlyCai1 天前
极简实现酷炫动效:Flutter隐式动画指南第二篇之一些酷炫的隐式动画效果
flutter
lqj_本人1 天前
Flutter&鸿蒙next 中使用 MobX 进行状态管理
flutter·华为·harmonyos