Windows应用中基于WriteableBitmap实现PNG黑转白逐像素颜色转换
实现PNG黑色像素转白色的完整方案
看起来你已经搭好了代码框架,我来帮你补全WriteableBitmap的像素处理部分,实现逐像素把黑色转为白色,同时完整保留原PNG的透明背景。
完整代码实现
public void colorImageChange() { StreamResourceInfo sri = Application.GetResourceStream(new Uri("Assets/Picto_1604_Panther_Black.png", UriKind.Relative)); if (sri == null || sri.Stream == null) { // 资源加载失败的容错处理 return; } BitmapImage src = new BitmapImage(); src.SetSource(sri.Stream); sri.Stream.Dispose(); // 及时释放流资源,避免内存占用 // 初始化可写位图,选择带alpha通道的Pbgra32格式适配透明PNG WriteableBitmap bitmap = new WriteableBitmap( src.PixelWidth, src.PixelHeight, src.DpiX, src.DpiY, PixelFormats.Pbgra32, null ); // 锁定像素缓冲区,准备修改 bitmap.Lock(); try { IntPtr bufferPtr = bitmap.BackBuffer; int stride = bitmap.BackBufferStride; int totalPixels = bitmap.PixelWidth * bitmap.PixelHeight; byte[] pixelData = new byte[totalPixels * 4]; // 每个像素占4字节:B→G→R→A // 将缓冲区数据复制到数组方便操作 Marshal.Copy(bufferPtr, pixelData, 0, pixelData.Length); // 遍历每个像素,修改黑色为白色 for (int i = 0; i < pixelData.Length; i += 4) { // Pbgra32格式下,字节顺序是蓝、绿、红、透明度 byte blue = pixelData[i]; byte green = pixelData[i+1]; byte red = pixelData[i+2]; byte alpha = pixelData[i+3]; // 判断是否为纯黑色(RGB通道均为0) if (red == 0 && green == 0 && blue == 0) { // 转为白色,保持原透明度不变 pixelData[i] = 255; // 蓝色通道 pixelData[i+1] = 255; // 绿色通道 pixelData[i+2] = 255; // 红色通道 // alpha通道保留原值,无需修改 } } // 将修改后的像素数据写回缓冲区 Marshal.Copy(pixelData, 0, bufferPtr, pixelData.Length); // 通知位图内容已更新 bitmap.AddDirtyRect(new Int32Rect(0, 0, bitmap.PixelWidth, bitmap.PixelHeight)); } finally { // 必须解锁缓冲区,防止内存泄漏 bitmap.Unlock(); } // 这里可以把修改后的bitmap绑定到UI控件显示 // yourImageControl.Source = bitmap; }
关键细节说明
- 像素格式选型:选用
PixelFormats.Pbgra32是因为它原生支持alpha通道,能完美保留原PNG的透明背景,每个像素由4个字节按蓝、绿、红、透明度的顺序存储。 - 资源管理:加载完图片流后立即调用
Dispose()释放资源,避免不必要的内存占用。 - 缓冲区安全操作:通过
Lock()锁定缓冲区后才能修改像素,操作完成后必须在finally块中执行Unlock(),防止资源泄漏。 - 透明背景保留:修改时仅调整RGB通道的值,原alpha通道保持不变,确保透明区域不会被破坏。
内容的提问来源于stack exchange,提问作者Rachel
相关产品推荐
相关产品推荐

