UWP中SoftwareBitmap的像素获取与设置:是否有Bitmap.Get/SetPixel等效方法?
在UWP中操作SoftwareBitmap像素:替代Get/SetPixel的方案
嘿,刚好我对这个问题很熟悉!首先得明确:UWP的SoftwareBitmap类并没有像WinForms的Bitmap那样自带GetPixel/SetPixel方法,不过我们可以通过它的BitmapBuffer来实现完全等效的功能,下面一步步给你讲清楚怎么搞:
核心原理
SoftwareBitmap的像素数据都存在BitmapBuffer里,我们可以锁定这个缓冲区,把像素数据复制到字节数组中,然后根据图像的像素格式(比如最常用的BGRA8)计算每个像素的字节位置,就能读取或者修改颜色了,最后再把修改后的字节写回缓冲区就行。
具体实现代码
1. 读取指定坐标的像素颜色
public static Color GetSoftwareBitmapPixel(SoftwareBitmap bitmap, int x, int y) { // 先做参数合法性检查 if (bitmap == null || x < 0 || x >= bitmap.PixelWidth || y < 0 || y >= bitmap.PixelHeight) throw new ArgumentOutOfRangeException("参数超出范围啦"); // 这里以最常用的BGRA8格式为例,其他格式需要调整逻辑 if (bitmap.BitmapPixelFormat != BitmapPixelFormat.Bgra8) throw new NotSupportedException("目前只支持BGRA8格式的SoftwareBitmap哦"); using (var buffer = bitmap.LockBuffer(BitmapBufferAccessMode.Read)) using (var reference = buffer.CreateReference()) { // 获取像素数据的字节数组 ((IMemoryBufferByteAccess)reference).GetBuffer(out byte[] pixels, out uint capacity); // 计算每行的字节数(也就是 stride) uint stride = buffer.GetPlaneDescription(0).Stride; // 计算目标像素的起始字节偏移:行数*每行字节数 + 列数*每个像素的字节数(BGRA8是4字节) int pixelOffset = (int)(y * stride + x * 4); // BGRA格式的顺序是蓝、绿、红、透明通道,所以要对应读取 byte blue = pixels[pixelOffset]; byte green = pixels[pixelOffset + 1]; byte red = pixels[pixelOffset + 2]; byte alpha = pixels[pixelOffset + 3]; return Color.FromArgb(alpha, red, green, blue); } }
2. 修改指定坐标的像素颜色
public static void SetSoftwareBitmapPixel(SoftwareBitmap bitmap, int x, int y, Color color) { // 参数合法性检查不能少 if (bitmap == null || x < 0 || x >= bitmap.PixelWidth || y < 0 || y >= bitmap.PixelHeight) throw new ArgumentOutOfRangeException("参数超出范围啦"); if (bitmap.BitmapPixelFormat != BitmapPixelFormat.Bgra8) throw new NotSupportedException("目前只支持BGRA8格式的SoftwareBitmap哦"); using (var buffer = bitmap.LockBuffer(BitmapBufferAccessMode.ReadWrite)) using (var reference = buffer.CreateReference()) { ((IMemoryBufferByteAccess)reference).GetBuffer(out byte[] pixels, out uint capacity); uint stride = buffer.GetPlaneDescription(0).Stride; int pixelOffset = (int)(y * stride + x * 4); // 按照BGRA的顺序写入颜色值 pixels[pixelOffset] = color.B; pixels[pixelOffset + 1] = color.G; pixels[pixelOffset + 2] = color.R; pixels[pixelOffset + 3] = color.A; } }
几个重要的注意点
- 像素格式适配:上面的代码是针对
BGRA8格式写的,这是UWP里SoftwareBitmap最常用的格式。如果你的图像是其他格式(比如Rgba8、Gray8灰度图),得调整每个像素的字节数和通道顺序。比如Gray8每个像素只有1字节,直接读对应偏移的字节就行。 - 性能优化:如果要批量处理大量像素,建议一次性操作整个字节数组,别反复调用Get/Set方法——毕竟每次锁定缓冲区和复制内存都有开销,批量处理能快很多。
- IMemoryBufferByteAccess接口:这个接口是用来访问内存缓冲区字节的COM接口,需要你手动在代码里声明一下:
[ComImport] [Guid("5B0D3235-4DBA-4D44-865E-8F1D0E4FD04D")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] unsafe interface IMemoryBufferByteAccess { void GetBuffer(out byte* buffer, out uint capacity); }
(要是你用的是.NET 5+或者WinUI 3,可能需要稍微调整这个接口的声明,或者用更简洁的内存访问方式)
内容的提问来源于stack exchange,提问作者Diego Alejandro Llanos Gareca
相关产品推荐
相关产品推荐

