气泡测量:画笔涂抹标记、橡皮擦清除、ROI外可正常拖动图像
This commit is contained in:
@@ -386,6 +386,7 @@ namespace XP.ImageProcessing.RoiControl.Controls
|
||||
private int _bubbleThreshold = 128;
|
||||
private int _bubbleBrushSize = 5;
|
||||
private bool _bubbleBrushDragging;
|
||||
private readonly System.Collections.Generic.Stack<byte[]> _bubbleUndoStack = new();
|
||||
|
||||
public void SetBubbleTool(BubbleSubTool tool) => _bubbleTool = tool;
|
||||
public void SetBubbleThreshold(int val) => _bubbleThreshold = val;
|
||||
@@ -1183,7 +1184,54 @@ namespace XP.ImageProcessing.RoiControl.Controls
|
||||
|
||||
private void ApplyBrushAt(Point pos)
|
||||
{
|
||||
// 画笔/橡皮:下一步实现
|
||||
if (_bubbleMask == null || !_bubbleRoi.HasValue) return;
|
||||
|
||||
var roi = _bubbleRoi.Value;
|
||||
int w = _bubbleMask.PixelWidth, h = _bubbleMask.PixelHeight;
|
||||
int cx = (int)pos.X, cy = (int)pos.Y;
|
||||
int r = _bubbleBrushSize;
|
||||
bool erase = _bubbleTool == BubbleSubTool.Eraser;
|
||||
|
||||
int roiX0 = Math.Max(0, (int)roi.X), roiY0 = Math.Max(0, (int)roi.Y);
|
||||
int roiX1 = Math.Min(w, (int)roi.Right), roiY1 = Math.Min(h, (int)roi.Bottom);
|
||||
|
||||
// 计算笔刷影响的矩形区域
|
||||
int x0 = Math.Max(roiX0, cx - r), y0 = Math.Max(roiY0, cy - r);
|
||||
int x1 = Math.Min(roiX1, cx + r + 1), y1 = Math.Min(roiY1, cy + r + 1);
|
||||
if (x0 >= x1 || y0 >= y1) return;
|
||||
|
||||
int regionW = x1 - x0, regionH = y1 - y0;
|
||||
int stride = w * 4;
|
||||
|
||||
// 读取整行范围的像素
|
||||
var pixels = new byte[regionW * regionH * 4];
|
||||
_bubbleMask.CopyPixels(new System.Windows.Int32Rect(x0, y0, regionW, regionH), pixels, regionW * 4, 0);
|
||||
|
||||
int r2 = r * r;
|
||||
for (int py2 = y0; py2 < y1; py2++)
|
||||
{
|
||||
for (int px2 = x0; px2 < x1; px2++)
|
||||
{
|
||||
int dx = px2 - cx, dy = py2 - cy;
|
||||
if (dx * dx + dy * dy > r2) continue;
|
||||
|
||||
int idx = ((py2 - y0) * regionW + (px2 - x0)) * 4;
|
||||
if (erase)
|
||||
{
|
||||
pixels[idx + 0] = 0; pixels[idx + 1] = 0;
|
||||
pixels[idx + 2] = 0; pixels[idx + 3] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
pixels[idx + 0] = 0; // B
|
||||
pixels[idx + 1] = 140; // G
|
||||
pixels[idx + 2] = 255; // R
|
||||
pixels[idx + 3] = 180; // A
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_bubbleMask.WritePixels(new System.Windows.Int32Rect(x0, y0, regionW, regionH), pixels, regionW * 4, 0);
|
||||
}
|
||||
|
||||
private void UpdateBubbleResult()
|
||||
@@ -1216,6 +1264,9 @@ namespace XP.ImageProcessing.RoiControl.Controls
|
||||
{
|
||||
if (_bubbleMask == null || !_bubbleRoi.HasValue || ImageSource == null) return;
|
||||
|
||||
// 保存快照用于撤销
|
||||
SaveMaskSnapshot();
|
||||
|
||||
var roi = _bubbleRoi.Value;
|
||||
int px = (int)pos.X, py = (int)pos.Y;
|
||||
if (!roi.Contains(pos)) return;
|
||||
@@ -1310,6 +1361,26 @@ namespace XP.ImageProcessing.RoiControl.Controls
|
||||
return gray;
|
||||
}
|
||||
|
||||
private void SaveMaskSnapshot()
|
||||
{
|
||||
if (_bubbleMask == null) return;
|
||||
int w = _bubbleMask.PixelWidth, h = _bubbleMask.PixelHeight;
|
||||
int stride = w * 4;
|
||||
var snapshot = new byte[stride * h];
|
||||
_bubbleMask.CopyPixels(snapshot, stride, 0);
|
||||
_bubbleUndoStack.Push(snapshot);
|
||||
}
|
||||
|
||||
/// <summary>撤销上一次魔棒/画笔操作</summary>
|
||||
public void UndoBubble()
|
||||
{
|
||||
if (_bubbleMask == null || _bubbleUndoStack.Count == 0) return;
|
||||
var snapshot = _bubbleUndoStack.Pop();
|
||||
int w = _bubbleMask.PixelWidth, h = _bubbleMask.PixelHeight;
|
||||
_bubbleMask.WritePixels(new System.Windows.Int32Rect(0, 0, w, h), snapshot, w * 4, 0);
|
||||
UpdateBubbleResult();
|
||||
}
|
||||
|
||||
/// <summary>清除气泡测量所有状态</summary>
|
||||
public void ClearBubbleMeasure()
|
||||
{
|
||||
@@ -1327,6 +1398,7 @@ namespace XP.ImageProcessing.RoiControl.Controls
|
||||
_bubbleRoiResizing = false;
|
||||
_bubbleBrushDragging = false;
|
||||
_bubbleTool = BubbleSubTool.Roi;
|
||||
_bubbleUndoStack.Clear();
|
||||
}
|
||||
|
||||
// 气泡工具切换事件
|
||||
@@ -1657,11 +1729,16 @@ namespace XP.ImageProcessing.RoiControl.Controls
|
||||
}
|
||||
if ((_bubbleTool == BubbleSubTool.Brush || _bubbleTool == BubbleSubTool.Eraser) && _bubbleRoi.HasValue)
|
||||
{
|
||||
_bubbleBrushDragging = true;
|
||||
ApplyBrushAt(pos);
|
||||
mainCanvas.CaptureMouse();
|
||||
e.Handled = true;
|
||||
return;
|
||||
// 只在 ROI 内才启动画笔,ROI 外不拦截,让图像正常拖动
|
||||
if (_bubbleRoi.Value.Contains(pos))
|
||||
{
|
||||
SaveMaskSnapshot();
|
||||
_bubbleBrushDragging = true;
|
||||
ApplyBrushAt(pos);
|
||||
mainCanvas.CaptureMouse();
|
||||
e.Handled = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// 魔棒在 MouseUp(CanvasClicked)中处理
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user