拍照指定裁剪大小

秋天来了

今年的冬天会比往年冷吗

也许要看棉被的厚度

需求来了

(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 绘制保存为图片提供的方法。此方法太好用了,不知道还真想不到。

相关推荐
空中海1 小时前
9.3 多端支持
flutter
见山是山-见水是水1 小时前
鸿蒙flutter第三方库适配 - JSON格式化工具应用
flutter·华为·json·harmonyos
lpfasd1231 小时前
Flutter 2026:从跨平台UI到AI原生全栈开发平台的蜕变
flutter·ui·ai-native
「、皓子~1 小时前
海狸IM技术升级:从Uniapp到Flutter的跨平台重构之路
flutter·重构·golang·uni-app·im·社交软件
张风捷特烈1 小时前
GetX 之死 | 8 年从未用过,以后将不会再用
android·前端·flutter
「、皓子~3 小时前
Flutter赋能海狸IM:打造高性能跨平台移动体验
flutter
见山是山-见水是水11 小时前
鸿蒙flutter第三方库适配 - 儿童故事
flutter·华为·harmonyos
2401_8396339113 小时前
鸿蒙flutter第三方库适配 - URL处理应用
flutter·华为·harmonyos
李李李勃谦14 小时前
Flutter 框架跨平台鸿蒙开发 - 星空日记
flutter·华为·harmonyos
2401_8396339114 小时前
鸿蒙flutter第三方库适配 - 看板应用
flutter·华为·harmonyos