UWP平台图像擦除功能实现咨询:跟随光标移动擦除图像
UWP 鼠标/光标擦除图像功能实现方案
核心思路
通过WriteableBitmap承载可编辑图像,监听鼠标/触摸指针事件,在光标划过的区域修改像素的Alpha通道为透明(或指定背景色),实现擦除效果。配合圆形区域遍历,让擦除轨迹更自然。
实现步骤
- 布局上用
Image控件绑定WriteableBitmap,监听指针按下、移动、释放事件 - 将目标图像加载为
WriteableBitmap,获得像素级编辑权限 - 在指针事件中计算光标对应原始图像的像素坐标,遍历指定半径内的像素并修改透明度
- 刷新位图更新UI
代码示例
XAML 布局
<Grid> <Image x:Name="EraseImage" Stretch="None" PointerPressed="EraseImage_PointerPressed" PointerMoved="EraseImage_PointerMoved" PointerReleased="EraseImage_PointerReleased"/> </Grid>
C# 后台逻辑
using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Media.Imaging; using Windows.Foundation; using System; using Windows.Storage; public sealed partial class MainPage : Page { private WriteableBitmap _editableBitmap; private bool _isErasing; private readonly int _eraseRadius = 20; // 可自定义擦除大小 public MainPage() { this.InitializeComponent(); LoadTargetImage(); } private async void LoadTargetImage() { // 示例加载项目Assets文件夹中的图片,可替换为用户选择的图像文件 var imageFile = await StorageFile.GetFileFromApplicationUriAsync( new Uri("ms-appx:///Assets/target-image.png")); using (var fileStream = await imageFile.OpenReadAsync()) { _editableBitmap = new WriteableBitmap(1, 1); await _editableBitmap.SetSourceAsync(fileStream); EraseImage.Source = _editableBitmap; } } private void EraseImage_PointerPressed(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e) { _isErasing = true; var cursorPoint = e.GetCurrentPoint(EraseImage).Position; ClearPixelArea(cursorPoint); e.Handled = true; } private void EraseImage_PointerMoved(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e) { if (_isErasing) { var cursorPoint = e.GetCurrentPoint(EraseImage).Position; ClearPixelArea(cursorPoint); e.Handled = true; } } private void EraseImage_PointerReleased(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e) { _isErasing = false; e.Handled = true; } private void ClearPixelArea(Point cursorCenter) { if (_editableBitmap == null) return; // 转换控件坐标为原始位图像素坐标(适配Stretch缩放) var scaleX = _editableBitmap.PixelWidth / EraseImage.ActualWidth; var scaleY = _editableBitmap.PixelHeight / EraseImage.ActualHeight; var originX = (int)(cursorCenter.X * scaleX); var originY = (int)(cursorCenter.Y * scaleY); // 读取并修改像素数据 using (var pixelStream = _editableBitmap.PixelBuffer.AsStream()) { var pixelData = new byte[_editableBitmap.PixelWidth * _editableBitmap.PixelHeight * 4]; pixelStream.Read(pixelData, 0, pixelData.Length); // 遍历圆形区域,设置像素为透明 for (int y = originY - _eraseRadius; y <= originY + _eraseRadius; y++) { for (int x = originX - _eraseRadius; x <= originX + _eraseRadius; x++) { if (x >= 0 && x < _editableBitmap.PixelWidth && y >= 0 && y < _editableBitmap.PixelHeight) { var distance = Math.Sqrt(Math.Pow(x - originX, 2) + Math.Pow(y - originY, 2)); if (distance <= _eraseRadius) { var pixelIndex = (y * _editableBitmap.PixelWidth + x) * 4; pixelData[pixelIndex + 3] = 0; // Alpha通道设为0,完全透明 } } } } // 写回修改后的像素 pixelStream.Seek(0, System.IO.SeekOrigin.Begin); pixelStream.Write(pixelData, 0, pixelData.Length); } // 通知UI刷新 _editableBitmap.Invalidate(); } }
注意事项
- 图像格式:若使用JPG等无透明通道的格式,擦除区域会显示黑色背景,建议改用PNG格式或设置Image控件的背景色
- 性能优化:大尺寸图像擦除时可缩小
_eraseRadius,或采用分块处理避免UI卡顿 - 多设备支持:代码原生支持触摸操作,无需额外修改即可适配触屏设备
内容的提问来源于stack exchange,提问作者Swann
相关产品推荐
相关产品推荐

