[英]Alpha masking in c# System.Drawing?
I'm trying to draw an image, with a source Bitmap
and an alpha mask Bitmap
, using the System.Drawing.Graphics
object. 我正在尝试使用
System.Drawing.Graphics
对象绘制带有源Bitmap
和alpha蒙版Bitmap
的图像。 At the moment I loop X and Y and use GetPixel
and SetPixel
to write the source color and mask alpha to a third Bitmap
, and then render that. 目前我循环X和Y并使用
GetPixel
和SetPixel
将源颜色和掩码alpha写入第三个Bitmap
,然后渲染它。 However this is very inefficient and I am wondering if there is an faster way to achieve this? 然而,这是非常低效的,我想知道是否有更快的方法来实现这一目标?
The effect I'm after looks like this: 我之后的效果看起来像这样:
The grid pattern represents transparency; 网格图案代表透明度; you probably knew that.
你可能知道这一点。
Yes, the faster way to do this is to use Bitmap.LockBits
and use pointer arithmetic to retrieve the values instead of GetPixel
and SetPixel
. 是的,更快的方法是使用
Bitmap.LockBits
并使用指针算法来检索值而不是GetPixel
和SetPixel
。 The downside, of course, is that you have to use unsafe code; 当然,缺点是你必须使用不安全的代码; if you make a mistake, you can cause some really bad crashes in your program.
如果你犯了一个错误,你可以在程序中造成一些非常糟糕的崩溃。 But if you keep it simple and self-contained, it should be fine (hey, if I can do, you can do it too).
但如果你保持简单和自足,它应该没问题(嘿,如果我能做到,你也可以做到)。
For example, you could do something like this (not tested, use at your own risk): 例如,您可以执行以下操作(未经测试,使用风险自负):
Bitmap mask = ...;
Bitmap input = ...;
Bitmap output = new Bitmap(input.Width, input.Height, PixelFormat.Format32bppArgb);
var rect = new Rectangle(0, 0, input.Width, input.Height);
var bitsMask = mask.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
var bitsInput = input.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
var bitsOutput = output.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
unsafe
{
for (int y = 0; y < input.Height; y++)
{
byte* ptrMask = (byte*) bitsMask.Scan0 + y * bitsMask.Stride;
byte* ptrInput = (byte*) bitsInput.Scan0 + y * bitsInput.Stride;
byte* ptrOutput = (byte*) bitsOutput.Scan0 + y * bitsOutput.Stride;
for (int x = 0; x < input.Width; x++)
{
ptrOutput[4 * x] = ptrInput[4 * x]; // blue
ptrOutput[4 * x + 1] = ptrInput[4 * x + 1]; // green
ptrOutput[4 * x + 2] = ptrInput[4 * x + 2]; // red
ptrOutput[4 * x + 3] = ptrMask[4 * x]; // alpha
}
}
}
mask.UnlockBits(bitsMask);
input.UnlockBits(bitsInput);
output.UnlockBits(bitsOutput);
output.Save(...);
This example derives the alpha channel in the output from the blue channel in the mask image. 此示例从掩模图像中的蓝色通道输出alpha输出。 I'm sure you can change it to use the mask's red or alpha channel if required.
我确定你可以改变它,以便在需要时使用面具的红色或alpha通道。
Depending on your requirements this may be much easier: 根据您的要求,这可能会更容易:
The only drawback of this method is that it needs you to make sure the mask color is not used in your image. 此方法的唯一缺点是它需要您确保图像中未使用蒙版颜色。 I don't know if this is slower or faster than the manual way.
我不知道这比手动方式更慢还是更快。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.