拍照指定裁剪大小

秋天来了

今年的冬天会比往年冷吗

也许要看棉被的厚度

需求来了

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

相关推荐
ALLIN16 小时前
Flutter 三种方式实现页面切换后保持原页面状态
flutter
Dabei16 小时前
Flutter 国际化
flutter
Dabei16 小时前
Flutter MQTT 通信文档
flutter
Dabei19 小时前
Flutter 中实现 TCP 通信
flutter
孤鸿玉19 小时前
ios flutter_echarts 不在当前屏幕 白屏修复
flutter
前端 贾公子21 小时前
《Vuejs设计与实现》第 16 章(解析器) 上
vue.js·flutter·ios
tangweiguo030519871 天前
Flutter 数据存储的四种核心方式 · 从 SharedPreferences 到 SQLite:Flutter 数据持久化终极整理
flutter
0wioiw01 天前
Flutter基础(②④事件回调与交互处理)
flutter
肥肥呀呀呀1 天前
flutter配置Android gradle kts 8.0 的打包名称
android·flutter
吴Wu涛涛涛涛涛Tao1 天前
Flutter 实现「可拖拽评论面板 + 回复输入框 + @高亮」的完整方案
android·flutter·ios