如何将黑色以外的颜色设置为使用 makeTransparent() 创建的图像
Posted
技术标签:
【中文标题】如何将黑色以外的颜色设置为使用 makeTransparent() 创建的图像【英文标题】:How do I set a color other than black to image created with makeTransparent() 【发布时间】:2014-10-21 11:51:36 【问题描述】:我在 c# Bitmap 对象上使用MakeTransparent()
函数调用将图像转换为透明图像。调用此方法时,它会通过设置 alpha 通道将背景颜色转换为透明,然后将背景颜色转换为黑色。
我需要找到一种快速将此背景颜色转换回白色或任何原始颜色的方法,因为有时我需要将图像展平为非 Alpha 通道启用格式。
Make transparent 似乎没有任何标志或重载可以让您告诉它不理会背景颜色,并且逐个像素地更改图像是低效的。任何人有任何建议或 GDI 技巧来解决这个问题?
【问题讨论】:
这是您必须处理的内部优化。如果您希望背景为白色,则只需将其绘制在白色背景上即可。如果你想恢复原来的背景颜色,那么你必须记住它是什么。 我可以写一个函数来用背景压平图像,但似乎应该有一个更简单的解决方案。 那就干脆别用这个功能了。手动操作。 【参考方案1】:似乎没有一种使用托管代码接口的快速方法来执行此操作。使用单独的像素操作,或使用非托管代码来更新像素似乎是唯一真正的选择。
【讨论】:
【参考方案2】:这在托管代码中实际上是可能的,通过使用Marshal.Copy
将支持字节数组从位图对象中复制出来,然后对其进行编辑,然后将其复制回来。
所以基本上,考虑到这种通用方法,您只需逐行检查像素,检测哪些像素具有您想要替换的颜色,然后将它们的 alpha 字节设置为 0。
请注意,“ARGB”是指一个读取像素的Int32
值内的组件顺序。由于这个值是 little-endian,因此给定偏移量处字节的实际顺序是相反的; B = 偏移 + 0,G = 偏移 + 1,R = 偏移 + 2,A = 偏移 + 3。
/// <summary>
/// Clears the alpha value of all pixels matching the given colour.
/// </summary>
public static Bitmap MakeTransparentKeepColour(Bitmap image, Color clearColour)
Int32 width = image.Width;
Int32 height = image.Height;
// Paint on 32bppargb, so we're sure of the byte data format
Bitmap bm32 = new Bitmap(width, height, PixelFormat.Format32bppArgb);
using (Graphics gr = Graphics.FromImage(bm32))
gr.DrawImage(image, new Rectangle(0, 0, width, height));
BitmapData sourceData = bm32.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, bm32.PixelFormat);
Int32 stride = sourceData.Stride;
// Copy the image data into a local array so we can use managed functions to manipulate it.
Byte[] data = new Byte[stride * height];
Marshal.Copy(sourceData.Scan0, data, 0, data.Length);
Byte colR = clearColour.R;
Byte colG = clearColour.G;
Byte colB = clearColour.B;
for (Int32 y = 0; y < height; y++)
Int32 inputOffs = y * stride;
for (Int32 x = 0; x < width; x++)
if (data[inputOffs + 2] == colR && data[inputOffs + 1] == colG && data[inputOffs] == colB)
data[inputOffs + 3] = 0;
inputOffs += 4;
// Copy the edited image data back.
Marshal.Copy(data, 0, sourceData.Scan0, data.Length);
bm32.UnlockBits(sourceData);
return bm32;
这可以很容易地通过容差级别而不是精确匹配来增强,例如Math.Abs(data[inputOffs + 2] - colR) < tolerance
,或者通过将字节实际转换为颜色对象并进行其他某种近似(如色调/饱和度/亮度) .
【讨论】:
以上是关于如何将黑色以外的颜色设置为使用 makeTransparent() 创建的图像的主要内容,如果未能解决你的问题,请参考以下文章
使用 CSS 将文本颜色设置为红色背景上的白色和白色背景上的黑色文本颜色