How to square crop a Flutter camera preview

独自空忆成欢 提交于 2019-12-05 08:19:55

I solved this by giving a specific size to my CameraPreview instance, by wrapping it in a Container:

  var size = MediaQuery.of(context).size.width;

  // ...

  Container(
    width: size,
    height: size,
    child: ClipRect(
      child: OverflowBox(
        alignment: Alignment.center,
        child: FittedBox(
          fit: BoxFit.fitWidth,
          child: Container(
            width: size,
            height:
                size / widget.cameraController.value.aspectRatio,
            child: camera, // this is my CameraPreview
          ),
        ),
      ),
    ),
  );

To respond to Luke's comment, I then used this code to square crop the resulting image. (Because even though the preview is square, the image captured is still standard ratio).

  Future<String> _resizePhoto(String filePath) async {
      ImageProperties properties =
          await FlutterNativeImage.getImageProperties(filePath);

      int width = properties.width;
      var offset = (properties.height - properties.width) / 2;

      File croppedFile = await FlutterNativeImage.cropImage(
          filePath, 0, offset.round(), width, width);

      return croppedFile.path;
  }

This uses https://github.com/btastic/flutter_native_image. It's been a while since I used this code - think it currently just works for portrait images, but should easily be extendable to handle landscape.

I have a code snippet similar to the one used in the answer.

Same as the answer, it supports cases when aspect ratio of the camera is different from aspect ratio of the screen.

Though my version has some difference: it does not require usage of media query to get the device size, so it will fit the width of any parent (not just full-screen-width)

          ....

          return AspectRatio(
            aspectRatio: 1,
            child: ClipRect(
              child: Transform.scale(
                scale: 1 / _cameraController.value.aspectRatio,
                child: Center(
                  child: AspectRatio(
                    aspectRatio: _cameraController.value.aspectRatio,
                    child: CameraPreview(_cameraController),
                  ),
                ),
              ),
            ),
          );

To center-square-crop the image, see the snippet below.

It works equally fine with images in portrait and landscape orientation. It also allows to optionally mirror the image (it can be useful if you want to retain original mirrored look from selfie camera)

import 'dart:io';
import 'dart:math';
import 'package:flutter/rendering.dart';
import 'package:image/image.dart' as IMG;

class ImageProcessor {
  static Future cropSquare(String srcFilePath, String destFilePath, bool flip) async {
    var bytes = await File(srcFilePath).readAsBytes();
    IMG.Image src = IMG.decodeImage(bytes);

    var cropSize = min(src.width, src.height);
    int offsetX = (src.width - min(src.width, src.height)) ~/ 2;
    int offsetY = (src.height - min(src.width, src.height)) ~/ 2;

    IMG.Image destImage =
      IMG.copyCrop(src, offsetX, offsetY, cropSize, cropSize);

    if (flip) {
        destImage = IMG.flipVertical(destImage);
    }

    var jpg = IMG.encodeJpg(destImage);
    await File(destFilePath).writeAsBytes(jpg);
  }
}

This code requires image package. Add it into pubspec.yaml:

  dependencies:
      image: ^2.1.4
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!