captureHiResCroppedImage static method

Future<Image?> captureHiResCroppedImage({
  1. required Rect cropRect,
  2. required Size canvasSize,
  3. required Image image,
  4. required double rotationAngle,
  5. required double scale,
})

执行高保真裁剪

Implementation

static Future<ui.Image?> captureHiResCroppedImage({
  required Rect cropRect,
  required Size canvasSize,
  required ui.Image image,
  required double rotationAngle,
  required double scale,
}) async {
  // 1. 计算从"图片坐标系"到"屏幕坐标系"的变换矩阵
  final Matrix4 matrixToScreen = CoordinateTransformer.createImageToScreenMatrix(
    canvasSize: canvasSize,
    rotationAngle: rotationAngle,
    scale: scale,
    image: image,
  );

  // 2. 求逆矩阵,得到从"屏幕坐标系"返回"图片坐标系"的变换
  final Matrix4 screenToImageMatrix = Matrix4.inverted(matrixToScreen);

  // 3. 将屏幕上的裁剪框的四个角,通过逆矩阵变换回图片上的坐标
  final topLeft = MatrixUtils.transformPoint(screenToImageMatrix, cropRect.topLeft);
  final topRight = MatrixUtils.transformPoint(screenToImageMatrix, cropRect.topRight);
  final bottomLeft = MatrixUtils.transformPoint(screenToImageMatrix, cropRect.bottomLeft);
  final bottomRight = MatrixUtils.transformPoint(screenToImageMatrix, cropRect.bottomRight);

  // 4. 计算能完全包围这四个点的、在图片坐标系中的矩形边界 (sourceRect)
  final double minX = [topLeft.dx, topRight.dx, bottomLeft.dx, bottomRight.dx].reduce(math.min);
  final double maxX = [topLeft.dx, topRight.dx, bottomLeft.dx, bottomRight.dx].reduce(math.max);
  final double minY = [topLeft.dy, topRight.dy, bottomLeft.dy, bottomRight.dy].reduce(math.min);
  final double maxY = [topLeft.dy, topRight.dy, bottomLeft.dy, bottomRight.dy].reduce(math.max);

  final Rect sourceRect = Rect.fromLTRB(minX, minY, maxX, maxY);

  // 5. 计算新图片的尺寸(高保真尺寸)
  final int newWidth = sourceRect.width.round();
  final int newHeight = sourceRect.height.round();

  if (newWidth <= 0 || newHeight <= 0) return null;

  // 6. 使用 PictureRecorder 和 drawImageRect 进行高保真绘制
  final recorder = ui.PictureRecorder();
  final canvas = Canvas(recorder, Rect.fromLTWH(0, 0, newWidth.toDouble(), newHeight.toDouble()));

  final paint = Paint()..filterQuality = FilterQuality.high;
  final Rect destinationRect = Rect.fromLTWH(0, 0, newWidth.toDouble(), newHeight.toDouble());

  // 核心:从原图的 sourceRect 区域,绘制到新画布的 destinationRect 区域
  canvas.drawImageRect(image, sourceRect, destinationRect, paint);

  // 7. 生成最终的高清图片
  final picture = recorder.endRecording();
  return await picture.toImage(newWidth, newHeight);
}