具有零阿尔法色值显示为黑(Color value with alpha of zero shows

2019-09-28 19:45发布

我使用.NET 4.0。 我不知道如果这是一个框架的错误,如果它是一个GDI +的事情。 我只是发现了它,而写一个应用程序来交换颜色通道。

让我试着解释这个问题。 我读的像素从一个位图,交换的渠道,写出来到另一个位图。 (具体而言,我设置的输出图像的等于输入图像的alpha RGB值,并且输出的alpha等于输入的绿色通道...或者,把它简洁地说,A => RGB和G => A.)的代码是如下:

for (int y = 0; y < input.Height; y++)
{
    for (int x = 0; x < input.Width; x++)
    {
        Color srcPixel = input.GetPixel(x, y);

        int alpha = srcPixel.A;
        int green = srcPixel.G;

        Color destPixel = Color.FromArgb(green, alpha, alpha, alpha);

        output.SetPixel(x, y, destPixel);
    }
}

同样,我已经试过这样:

        int color = green << 24 | alpha << 16 | alpha << 8 | alpha;

        Color destPixel = Color.FromArgb(color);

        output.SetPixel(x, y, destPixel);

在大多数情况下,它的工作原理。

问题:无论的RGB值是什么,当α为零时,所得到的RGB值始终为纯黑色(R:0,G:0,B:0)。 我不知道这是否是某种FromArgb的()“优化” - 使用.net反射,我没有看到FromArgb()做任何事情奇怪 - 或者,如果Bitmap.SetPixel是罪魁祸首 - 更容易,因为它推迟到本机代码,我不能看着它。 无论哪种方式,当α为零时,象素是黑色的。 这不是我所期望的行为。 我需要保持RGB通道完好。

起初我以为这是一个乘预阿尔法的问题,因为我用我的家庭自酿DDS装载机(我符合规范,并且从来没有给我任何问题)加载DDS文件,但是当我指定一个明确的阿尔法255,就像这样:

        Color destPixel = Color.FromArgb(255, alpha, alpha, alpha);

... RGB通道正确显示 - 也就是说,他们没有原来的黑色 - 所以这绝对是GDI中的东西+是错误地假定RGB值可以忽略,如果阿尔法是零......这对我来说,似乎是一个非常愚蠢的假设,但是,不管。

进一步加剧了问题是颜色类型是不可改变的,这是有道理的结构,但它意味着我不能创建一个颜色,然后分配阿尔法...,如果SetPixel()是罪魁祸首,就不会怎样都无所谓。 (:零阿尔法=零RGB我已经通过设置它,并看到了同样的结果后立即再次歌厅像素测试这一点)。

所以,我的问题:有没有人处理这个问题,并想出了一个比较简单的解决方法吗? 在努力保持我的依赖下来,我讨厌导入第三方图像库,但因为GDI +是使我的颜色通道车的假设,我可能不会有一个选择。

谢谢你的帮助。

编辑:我解决了这个,但我不能发布另外七个小时的答案。 真棒。

Answer 1:

抱歉耽搁了。 无论如何,我应该在这多一点的时间在发布前的工作,因为我发现了大约五分钟,十分钟后的解决方案。 需要明确的是,我没有找到一个解决陈述GDI +问题,但我找到一个合适的解决办法。 我想过怎样,在其他的API,我会锁定一个表面和直接传送字节到另一面,所以我把这种方法。 从MSDN的一点帮助后,这里是我的代码(没有错误处理):

Bitmap input = Bitmap.FromFile(filename) as Bitmap;

int byteCount = input.Width * input.Height * 4;

var inBytes  = new byte[byteCount];
var outBytes = new byte[byteCount];

var inBmpData = input.LockBits(new Rectangle(0, 0, input.Width, input.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

Marshal.Copy(inBmpData.Scan0, inBytes, 0, byteCount);

for (int y = 0; y < input.Height; y++)
{
    for (int x = 0; x < input.Width; x++)
    {
        int offset = (input.Width * y + x) * 4;

    //  byte blue  = inBytes[offset];
        byte green = inBytes[offset + 1];
    //  byte red   = inBytes[offset + 2];
        byte alpha = inBytes[offset + 3];

        outBytes[offset]     = alpha;
        outBytes[offset + 1] = alpha;
        outBytes[offset + 2] = alpha;
        outBytes[offset + 3] = green;
    }
}

input.UnlockBits(inBmpData);

Bitmap output = new Bitmap(input.Width, input.Height, PixelFormat.Format32bppArgb);

var outBmpData = output.LockBits(new Rectangle(0, 0, output.Width, output.Height), ImageLockMode.WriteOnly, output.PixelFormat);

Marshal.Copy(outBytes, 0, outBmpData.Scan0, outBytes.Length);

output.UnlockBits(outBmpData);

注:元帅是在System.Runtime.InteropServices; 的BitmapData(inBmpData,outBmpData),ImageLockMode和的PixelFormat是System.Drawing.Imaging下。

这不仅工作完美,但它是惊人速度更快。 我将使用这个技术从现在起,我所有的信道交换需求。 (我已经用它在另一个类似的应用程序。)

很抱歉的不必要的岗位。 我至少希望这个解决方案能够帮助别人。



文章来源: Color value with alpha of zero shows up as black
标签: gdi+ alpha