以编程方式用白色填充替换图像中的透明区域?

时间:2011-03-24 20:34:19

标签: c# png system.drawing system.drawing.imaging

我有一个PNG图像,我正在通过.NET中的System.Drawing API进行操作。它有很大的透明区域,我想用白色填充替换透明区域 - 这样图像中就没有透明区域。在图像编辑程序中很容易......但到目前为止,我在C#中没有成功。

有人可以给我一些指示吗?

4 个答案:

答案 0 :(得分:3)

我的例子:

    public void FillPngWhite(Bitmap bmp)
    {
        if (bmp.PixelFormat != PixelFormat.Format32bppArgb)
            throw new ApplicationException("Not supported PNG image!");

        // Lock the bitmap's bits.  
        Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
        BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadWrite, bmp.PixelFormat);

        // Get the address of the first line.
        IntPtr ptr = bmpData.Scan0;

        // Declare an array to hold the bytes of the bitmap.
        int bytes  = Math.Abs(bmpData.Stride) * bmp.Height;
        byte[] rgbaValues = new byte[bytes];

        // Copy the RGB values into the array.
        System.Runtime.InteropServices.Marshal.Copy(ptr, rgbaValues, 0, bytes);

        // array consists of values RGBARGBARGBA

        for (int counter = 0; counter < rgbaValues.Length; counter += 4)
        {
            double t = rgbaValues[counter + 3]/255.0; // transparency of pixel between 0 .. 1 , easier to do math with this
            double rt = 1 - t; // inverted value of transparency

            // C = C * t + W * (1-t) // alpha transparency for your case C-color, W-white (255)
            // same for each color
            rgbaValues[counter] = (byte) (rgbaValues[counter]*t + 255*rt); // R color
            rgbaValues[counter + 1] = (byte)(rgbaValues[counter + 1] * t + 255 * rt); // G color
            rgbaValues[counter + 2] = (byte)(rgbaValues[counter + 2] * t + 255 * rt); // B color

            rgbaValues[counter + 3] = 255; // A = 255 => no transparency 
        }
        // Copy the RGB values back to the bitmap
        System.Runtime.InteropServices.Marshal.Copy(rgbaValues, 0, ptr, bytes);

        // Unlock the bits.
        bmp.UnlockBits(bmpData);
    }

这是不同的原因:

我使用LockBits代替GetPixelSetPixel。它更快,但更难理解。这是来自MSDN

的一个小修改示例

正如我在你的问题的评论中所说的那样,我正在考虑真正的aplha价值。这将使50%透明度(128)的黑色看起来像灰色而不是黑色。原因是“在图形编辑器中用白色替换alpha”我想象在你的图像下面创建一个填充了白色的新图层,然后将两个图层拼合在一起。这个例子也有同样的效果。

答案 1 :(得分:2)

我不确定如何检测透明像素。我知道如果Alpha是0,它是完全透明的,如果它是255则是不透明的。我不确定你是否应该检查Alpha == 0或Alpha!= 255;如果你可以尝试并给我一个有用的反馈。

来自MSDN

  

alpha组件指定   颜色的透明度:0是完全的   透明,255是完全不透明的。   同样,A值为255表示   不透明的颜色。 A的值为1   通过254表示a   半透明的颜色。颜色   随着A的临近,变得越来越不透明   255。

    void  Foo(Bitmap image)
    {
        for (int y = 0; y < image.Height; ++y)
        {
            for (int x = 0; x < image.Width; ++x)
            {
                // not very sure about the condition.                   
                if (image.GetPixel(x, y).A != 255)
                {
                    image.SetPixel(x,y,Color.White);
                }
            }
        }

    }

答案 2 :(得分:0)

获得位图对象的句柄后,只需执行以下操作:

Bitmap yourImage = HOWEVER YOU LOAD YOUR IMAGE;
int width = YOUR IMAGE WIDTH;
int height = YOUR IMAGE HEIGHT;

Color c;
Color white = new Color(255,255,255,255)
for(int w = 0; w < width; w++)
for(int h = 0; h < height; h++)
{
    c = yourImage.GetPixel(w,h);
    yourImage.SetPixel(w,h, ((((short)(c.A)) & 0x00FF) <= 0)? white:c); //replace 0 here with some higher tolerance if needed
}

答案 3 :(得分:0)

这可能会过度简化您的问题,但如果它位于表单或其他随时可用的控件上,您可以在将图像放在顶部之前简单地绘制背景白色。