c# - 使用 GDI+ 混合透明图像时的伪像

标签 c# image-processing gdi+ alphablending

我正在使用 C# 开发绘图程序原型(prototype)。

我生成了一个“画笔”图像,我按照鼠标位置将其混合到目标图像上。它有效,但在同一个地方反复混合会产生瑕疵。特别是,画笔上的透明像素往往会使目标图像变暗。

这是带有伪影的画笔和目标图像。右侧是相应的 alpha channel 。最后一行显示了我使用平刷(半透明圆盘)时的正确结果。

Bug illustrated

我做了一个示例程序来说明这个问题。

public static Bitmap GenerateBrush(double radius, Func<double, double, double> curve)
{
    int npx = (int)Math.Ceiling(radius) * 2 + 1;
    Bitmap bmp = new Bitmap(npx, npx, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
    for (int ix = 0; ix < npx; ix++) {
        for (int iy = 0; iy < npx; iy++) {
            double fx = 2.0 * ix / (double)(npx - 1) - 1.0;
            double fy = 2.0 * iy / (double)(npx - 1) - 1.0;
            double res = curve(fx, fy);
            bmp.SetPixel(ix, iy, Color.FromArgb((int)(res * 255), 255, 255, 255));
        }
    }
    return bmp;
}

static void Main(string[] args)
{
    var bmpDest = new Bitmap(200, 200, PixelFormat.Format32bppArgb);
    var graphDest = Graphics.FromImage(bmpDest);
    graphDest.Clear(Color.FromArgb(0, 255, 255, 255));

    var bmpSrc = GenerateBrush(40, delegate(double x, double y) {
        double d = Math.Max(1.0 - Math.Sqrt(x * x + y * y), 0.0);
        return 0.5 + Math.Sin((d - 0.5) * Math.PI) / 2;
    });
    
    var im = new ImageAttributes();
    im.SetColorMatrix(new ColorMatrix(
        new float[][] {
        new float[] { 1, 0, 0, 0, 0 },
        new float[] { 0, 1, 0, 0, 0 },
        new float[] { 0, 0, 0, 0, 0 },
        new float[] { 0, 0, 0, 0.3f, 0 },
        new float[] { .0f, .0f, .0f, .0f, 1 }
        }
    ));

    int nsteps = 2000;
    for (int i = 0; i < nsteps; i++) {
        var t = i / (float)nsteps;
        var xpos = 60 + (int)(Math.Sin(t*Math.PI*40) * 50);
        var ypos = 60 + (t>0.5 ? 20: -20);
        graphDest.DrawImage(bmpSrc, new Rectangle(xpos, ypos, 100, 100), 0, 0, 100, 100, GraphicsUnit.Pixel, im);
    }

    bmpDest.Save(@"test.png");
}

在我看来,这可能是由于 GDI+ 混合透明图像的方式存在精度问题。有什么想法吗?

-- 编辑

没有颜色矩阵的相同问题(删除 DrawImage() 中的最后一个参数):

enter image description here

-- 编辑 2

似乎没有人对此有答案 - 问题不够清楚吗?

最佳答案

是的,截断错误正在累积。您可以尝试对图像使用 PixelFormat.Format32bppPArgb 模式,但我不确定它是否有帮助。

万无一失的治疗方法是将画笔笔触累积到单 channel 图像中,然后使用该结果作为蒙版在 Canvas 上绘画。

关于c# - 使用 GDI+ 混合透明图像时的伪像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10861382/

相关文章:

c# - 数字相似度算法

c# - Linq to Entities 中的联合订单

c++ - 逐像素填充 cvHistogram 列表

c# - (C#) 如何获取屏幕的点与像素关系?

c# - 如何找到实际的可打印区域? (打印文件)

c# - NavigationService 删除 forwardstack

c# - 如何在触发器中设置属性 (WPF)

matlab - 连接SURF特征和Radon特征来训练SVM

c++ opencv findHomography()函数中的未定义关系

C#:是否有必要在自定义控件中处理图形元素?