使用unsafe将透明度写入位图并保留原始颜色?

时间:2014-09-28 07:30:53

标签: c# .net winforms transparency unsafe

在此代码中,我创建透明位图,但将列表测试点中的像素着色为黄色。 我如何保持透明,但要着色的像素或与原始颜色保持一致的黄色?

private void button2_Click(object sender, EventArgs e)
{
    Graphics g;
    g = Graphics.FromImage(bmpBackClouds);
    g.Clear(Color.Transparent);
    g.Dispose();
    BitmapData b1 = bmpBackClouds.LockBits(new System.Drawing.Rectangle(0, 0,
                    bmpBackClouds.Width, bmpBackClouds.Height), 
                    System.Drawing.Imaging.ImageLockMode.ReadWrite,
                    System.Drawing.Imaging.PixelFormat.Format32bppArgb);

    int stride = b1.Stride;
    int i;

    System.IntPtr Scan0 = b1.Scan0;

    unsafe
    {
        byte* p;

        for (i = 0; i < testpoints.Count; i++)
        {
            p = (byte*)(void*)Scan0;

            p += (int)testpoints[i].Y * stride + (int)testpoints[i].X * 4;

            p[1] = p[2] = (byte)255;
            p[0] = (byte)0;
            p[3] = (byte)255;
        }
    }
    bmpBackClouds.UnlockBits(b1);
    bmpBackClouds.Save(@"c:\temp\yellowbmpcolor.png", ImageFormat.Png);
}

1 个答案:

答案 0 :(得分:1)

您的代码可以通过微小的修正来正常工作:

删除删除图像的部分:

Graphics g;
g = Graphics.FromImage(bmpBackClouds);
g.Clear(Color.Transparent);
g.Dispose();

这会消除图像,你最终也不会有任何内容。

然后更改此

        p[1] = p[2] = (byte)255;
        p[0] = (byte)0;
        p[3] = (byte)255;

到那个:

        p[3] = 0;

测试点列表中的部分将是透明的,其颜色通道完好无损。

这有点难以察觉; - )

最好的测试是阅读它并恢复alpha通道和瞧,原始图像又回来了!

注意如果您希望通过第一行使整个Bitmap透明 - 这不起作用。 GDI处理透明度存在漏洞;大概是为了节省时间,当您尝试使用它来制作图像的一部分或所有图像都是透明的时,它不会保留原始颜色。对Graphics.ClearGraphics等其他Graphics.FillRectangle方法都适用。

..所以如果你想完全清除一个图像的alpha通道,使用上面的代码就可以了,显然​​没有列表和所有像素的循环..