You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用WriteableBitmap修改JPG图像像素无效果的问题求助

问题原因分析

嘿,我来帮你搞定这个问题!你遇到的核心问题其实和DPI关系不大,主要是像素格式不匹配导致你的像素修改代码根本没执行:

  • 你的SetPixel方法里有个关键判断:if (!wbm.Format.Equals(PixelFormats.Bgra32)) return;,而JPG图片默认加载后,BitmapImage的像素格式通常是Bgr24(因为JPG本身不支持Alpha通道),完全不符合BGRA32的要求。所以当你从JPG转成WriteableBitmap后,这个判断直接让方法提前返回,像素修改的逻辑根本没机会运行!
  • 另外,你混用了WinForms/GDI+的System.Drawing.Color和WPF的System.Windows.Media.Color,虽然这里没报错,但容易造成混淆,建议统一使用WPF的颜色类型。
解决方案

下面给你两种可行的解决思路,推荐第一种,因为保持格式统一会让后续逻辑更稳妥:

方案1:加载图片时强制解码为BGRA32格式

修改你的ConvertToBitmap方法,在加载BitmapImage时指定解码格式为BGRA32,这样转成的WriteableBitmap就完全符合SetPixel的格式要求了:

public WriteableBitmap ConvertToBitmap(string fileName)
{
    BitmapImage bitmap = new BitmapImage();
    bitmap.BeginInit();
    bitmap.UriSource = new Uri(fileName, UriKind.Relative);
    // 强制将图片解码为BGRA32格式
    bitmap.DecodePixelFormat = PixelFormats.Bgra32;
    // 加载时立即解码并缓存,避免旧格式干扰
    bitmap.CacheOption = BitmapCacheOption.OnLoad;
    bitmap.EndInit();
    
    WriteableBitmap newbitmap = new WriteableBitmap(bitmap);
    return newbitmap;
}

方案2:修改SetPixel方法适配多种像素格式(可选)

如果你不想强制转换图片格式,可以修改SetPixel方法,去掉格式判断,或者针对常见格式(比如JPG的Bgr24)做适配处理。同时把颜色类型换成WPF的System.Windows.Media.Color:

public void SetPixel(WriteableBitmap wbm, int x, int y, System.Windows.Media.Color c)
{
    // 边界检查
    if (y >= wbm.PixelHeight || x >= wbm.PixelWidth || y < 0 || x < 0)
        return;

    wbm.Lock();
    IntPtr buff = wbm.BackBuffer;
    int stride = wbm.BackBufferStride;
    unsafe
    {
        byte* pbuff = (byte*)buff.ToPointer();
        int pixelByteSize = wbm.Format.BitsPerPixel / 8;
        int pixelOffset = y * stride + x * pixelByteSize;

        // 适配BGRA32格式
        if (wbm.Format == PixelFormats.Bgra32)
        {
            pbuff[pixelOffset] = c.B;
            pbuff[pixelOffset + 1] = c.G;
            pbuff[pixelOffset + 2] = c.R;
            pbuff[pixelOffset + 3] = c.A;
        }
        // 适配JPG常见的Bgr24格式(无Alpha通道)
        else if (wbm.Format == PixelFormats.Bgr24)
        {
            pbuff[pixelOffset] = c.B;
            pbuff[pixelOffset + 1] = c.G;
            pbuff[pixelOffset + 2] = c.R;
        }
        // 可以继续添加其他格式的处理逻辑
    }
    wbm.AddDirtyRect(new Int32Rect(x, y, 1, 1));
    wbm.Unlock();
}

调用时也要把System.Drawing.Color换成WPF的颜色:

// 全图设为黑色
SetPixel(wbmap, x, y, System.Windows.Media.Color.FromArgb(255, 0, 0, 0));
// 小方块设为红色
SetPixel(wbmap, x, y, System.Windows.Media.Color.FromArgb(255, 255, 0, 0));
额外优化提示
  • 如果你需要批量修改大量像素,建议一次性锁定WriteableBitmap后修改整个区域,最后只调用一次AddDirtyRect传入整个图像范围(比如new Int32Rect(0,0,wbmap.PixelWidth,wbmap.PixelHeight)),这样比每次修改单个像素都调用一次性能要好得多。
  • DPI确实不是问题,它只会影响图片在界面上的显示缩放,不会干扰像素修改的底层逻辑。

内容的提问来源于stack exchange,提问作者Iggy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 03:58:16