captureHiResCroppedImage static method
执行高保真裁剪
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);
}