我有一个 PNG 图像,我正在通过 .NET 中的 System.Drawing API 对其进行操作。它有很大的透明区域,我想用白色填充替换透明区域——这样图像中就没有透明区域了。在图像编辑程序中很容易......但到目前为止,我在 C# 中没有成功。
有人可以给我一些指示吗?
我有一个 PNG 图像,我正在通过 .NET 中的 System.Drawing API 对其进行操作。它有很大的透明区域,我想用白色填充替换透明区域——这样图像中就没有透明区域了。在图像编辑程序中很容易......但到目前为止,我在 C# 中没有成功。
有人可以给我一些指示吗?
我不确定如何检测透明像素。我知道如果 Alpha 为 0,它是完全透明的,如果是 255,它是不透明的。我不确定您是否应该检查 Alpha == 0 或 Alpha != 255 ;如果您可以尝试并给我一个有用的反馈。
来自MSDN
alpha 分量指定颜色的透明度:0 表示完全透明,255 表示完全不透明。同样,A 值为 255 表示不透明颜色。从 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);
}
}
}
}
我的例子:
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
改用GetPixel
and SetPixel
。它更快,但更难理解。这是来自: MSDN的一个小修改示例
正如我在对您的问题的评论中所说,我正在考虑真正的 aplha 价值。这将使具有 50% 透明度 (128) 的黑色看起来像灰色而不是黑色。这样做的原因是“在图形编辑器中用白色替换 alpha”我想在你的图像下面创建一个新层,用白色填充,然后将两个层拼合在一起。这个例子会有同样的效果。
这可能会过度简化您的问题,但如果它位于表单或其他现成的控件上,您可以简单地将背景涂成白色,然后再将图像放在顶部。
获得位图对象的句柄后,只需执行以下操作:
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
}