如何修改BitmapImage的颜色?WinForms修改Bitmap的方法不适配怎么办
BitmapImage灰度图自定义染色实现方案
方法1:复用已有WinForms逻辑(Bitmap互转)
如果不想重写之前成熟的灰度改色逻辑,可以通过类型互转实现兼容:
- 第一步:将
BitmapImage转为System.Drawing.Bitmap
public Bitmap BitmapImageToBitmap(BitmapImage bitmapImage) { using (MemoryStream outStream = new MemoryStream()) { BitmapEncoder encoder = new BmpBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(bitmapImage)); encoder.Save(outStream); return new Bitmap(outStream); } }
- 第二步:调用你之前已经实现的Bitmap灰度图改色方法处理
- 第三步:将处理完成的
Bitmap转回BitmapImage
public BitmapImage BitmapToBitmapImage(Bitmap bitmap) { using (MemoryStream stream = new MemoryStream()) { bitmap.Save(stream, ImageFormat.Png); stream.Position = 0; BitmapImage result = new BitmapImage(); result.BeginInit(); result.CacheOption = BitmapCacheOption.OnLoad; result.StreamSource = stream; result.EndInit(); result.Freeze(); // 跨线程使用必须添加此行 return result; } }
注意:.NET Core/.NET 5+项目需要先安装NuGet包
System.Drawing.Common才能使用GDI+相关类型。
方法2:WPF原生像素操作(无GDI+依赖)
如果不想引入GDI+依赖,可以直接操作BitmapImage的像素数据实现灰度图染色,核心逻辑是读取每个像素的灰度值作为目标颜色的亮度权重,替换对应像素值即可:
public BitmapImage TintGrayscaleImage(BitmapImage source, System.Windows.Media.Color targetColor) { int width = source.PixelWidth; int height = source.PixelHeight; int stride = width * 4; // BGRA32格式每个像素占4字节 byte[] pixelData = new byte[height * stride]; source.CopyPixels(pixelData, stride, 0); // 遍历像素完成染色 for (int i = 0; i < pixelData.Length; i += 4) { // 灰度图R/G/B通道值相等,取任意通道作为亮度值即可 byte luminance = pixelData[i]; // 用亮度值作为权重计算目标颜色分量 pixelData[i] = (byte)(targetColor.B * luminance / 255); pixelData[i + 1] = (byte)(targetColor.G * luminance / 255); pixelData[i + 2] = (byte)(targetColor.R * luminance / 255); // 保留原透明度逻辑,不需要透明效果可直接赋值为luminance pixelData[i + 3] = pixelData[i + 3] == 0 ? (byte)0 : luminance; } // 生成处理后的BitmapImage BitmapSource bitmapSource = BitmapSource.Create(width, height, source.DpiX, source.DpiY, System.Windows.Media.PixelFormats.Bgra32, null, pixelData, stride); using (MemoryStream ms = new MemoryStream()) { PngBitmapEncoder encoder = new PngBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(bitmapSource)); encoder.Save(ms); ms.Position = 0; BitmapImage result = new BitmapImage(); result.BeginInit(); result.CacheOption = BitmapCacheOption.OnLoad; result.StreamSource = ms; result.EndInit(); result.Freeze(); return result; } }
- 调用示例:
var redTintedImage = TintGrayscaleImage(originalGrayscaleImage, System.Windows.Media.Colors.Red);
该方法默认适配BGRA32格式的灰度图,若你的图像为其他像素格式,对应调整
PixelFormats参数和像素读取逻辑即可。
内容的提问来源于stack exchange,提问作者Groer
相关产品推荐
相关产品推荐

