You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

相机拍照作InkCanvas背景,缩放墨迹时笔宽未同步的解决求助

解决InkCanvas墨迹缩放时笔宽不同步的问题

这个场景我太熟悉了!之前做类似的图片标注工具时也踩过这个坑——光是缩放墨迹的位置和线条长度,笔宽会显得完全不匹配原始图像的尺寸,要么太细要么太粗。确实,PenTipTransform就是解决这个问题的关键,下面给你具体的实现思路和代码示例:

核心原理

PenTipTransformInkDrawingAttributes里的矩阵属性,专门用来控制笔尖(也就是笔宽)的变换逻辑。它默认是单位矩阵,当我们给它应用和墨迹几何形状一致的缩放矩阵后,笔宽就能和墨迹的整体缩放比例保持同步,不会出现“线条长度缩放了但笔宽没跟上”的脱节情况。

实现步骤

1. 计算正确的缩放比例

首先得明确两个关键尺寸:

  • 原始照片的实际像素尺寸(比如用originalImage.PixelWidth/originalImage.PixelHeight获取)
  • 背景图像在InkCanvas中的显示尺寸(如果背景是拉伸显示的,要先计算拉伸后的实际宽高,不能直接用InkCanvas的ActualWidth/ActualHeight

假设我们要把墨迹从InkCanvas的显示尺寸放大到原始照片的尺寸,缩放比例公式为:

double scaleX = 原始照片像素宽度 / InkCanvas中图像显示宽度;
double scaleY = 原始照片像素高度 / InkCanvas中图像显示高度;

2. 遍历墨迹并应用双重缩放

我们需要对每个墨迹做两件事:一是缩放墨迹的几何形状(你已经实现的部分),二是用PenTipTransform同步缩放笔宽。

针对WPF的代码示例:

// 准备笔宽缩放矩阵
double scaleX = originalImage.PixelWidth / displayedImageWidth;
double scaleY = originalImage.PixelHeight / displayedImageHeight;
Matrix penScaleMatrix = new Matrix(scaleX, 0, 0, scaleY, 0, 0);

// 遍历所有墨迹(ToList避免遍历过程中集合变更报错)
foreach (var stroke in inkCanvas.Strokes.ToList())
{
    // 缩放墨迹的几何形状(你已完成的逻辑)
    var scaleTransform = new ScaleTransform(scaleX, scaleY);
    stroke.Geometry = stroke.Geometry.GetTransformedGeometry(scaleTransform);

    // 关键操作:给笔宽应用同步缩放
    stroke.DrawingAttributes.PenTipTransform *= penScaleMatrix;
}

针对UWP的代码示例:

UWP的InkStroke处理逻辑略有不同,用PointTransform控制墨迹位置,PenTipTransform同样用来处理笔宽:

double scaleX = originalImage.PixelWidth / displayedImageWidth;
double scaleY = originalImage.PixelHeight / displayedImageHeight;
Matrix3x2 penScaleMatrix = Matrix3x2.CreateScale((float)scaleX, (float)scaleY);

var strokes = inkCanvas.InkPresenter.StrokeContainer.GetStrokes();
foreach (var stroke in strokes)
{
    // 缩放墨迹的位置和形状
    stroke.PointTransform *= Matrix3x2.CreateScale((float)scaleX, (float)scaleY);

    // 同步缩放笔宽
    stroke.DrawingAttributes.PenTipTransform *= penScaleMatrix;
}

注意事项

  • 如果背景图像是按比例拉伸(比如Stretch.Uniform),一定要先计算图像在InkCanvas中的实际显示宽高,不能直接用InkCanvas的尺寸,否则缩放比例会出错,导致笔宽和线条缩放不匹配。
  • 处理完墨迹后,保存时可以把变换后的墨迹叠加到原始图像上,或者单独保存墨迹层,这样就能得到和原始图像尺寸完全匹配的标注图了。

内容的提问来源于stack exchange,提问作者Seige

火山引擎 最新活动