嵌入父Grid的TransformedBitmap鼠标坐标转像素坐标问题求解
修复方案
问题根因
异常由你代码最后的模运算逻辑导致:p = new Point((p.X + w) % w, (p.Y + h) % h); 这行代码会把所有负坐标、大于图像尺寸的坐标全部折叠回[0, 原始图像宽度)、[0, 原始图像高度)的区间内,完全丢失了坐标位于图像外的信息,所以才会出现灰色区域的点被误判为在图像范围内的问题。
修复代码
直接删除模运算逻辑,保留逆变换后的原始坐标值即可,负数、大于图像尺寸的数值本身就能直接反映点在图像外的状态,调整后的TheGrid_MouseMove代码如下:
private void TheGrid_MouseMove(object sender, MouseEventArgs e) { // 直接获取鼠标相对于Image控件的坐标,不需要额外Translate转换 Point p = e.GetPosition(TheImage); if (TheImage.Source is BitmapSource bs) { // 控件坐标映射为当前显示位图的像素坐标 p = new Point( p.X * bs.PixelWidth / TheImage.ActualWidth, p.Y * bs.PixelHeight / TheImage.ActualHeight ); bool isInImage = false; if (TheImage.Source is TransformedBitmap tb) { // 逆变换回原始位图的坐标空间 Matrix inverse = tb.Transform.Value; inverse.Invert(); inverse.OffsetX = 0.0; inverse.OffsetY = 0.0; p = inverse.Transform(p); int originalW = tb.Source.PixelWidth; int originalH = tb.Source.PixelHeight; // 边界校验,判断坐标是否在原始图像有效范围内 isInImage = p.X >= 0 && p.X < originalW && p.Y >= 0 && p.Y < originalH; } // 输出坐标和边界状态,p值本身不会被折叠,超界区域会保留负数值或大于宽高的数值 TheLabel.Content = $"像素坐标:{p.ToString()} | 是否在图像内:{isInImage}"; } }
业务适配说明
对于ROI选择的需求:
- 图像内的坐标会落在
0 ≤ X < 原始图像宽度、0 ≤ Y < 原始图像高度区间内,可直接使用 - 超界区域的坐标会保留原始值(负数值、大于对应维度尺寸的数值),既可以准确判断超界状态,也可以保留用户选择超界区域的所有坐标信息。
如果有截取有效像素的需求,可在需要取值的时候再单独做截断/模运算处理,不要修改原始坐标值即可。
内容的提问来源于stack exchange,提问作者Craig W
相关产品推荐
相关产品推荐

