我使用黑白图片作为蒙版,在应用矩形后生成漂亮的轮廓。不幸的是,为了消除黑色,我使用了 MakeTransparent 方法,不幸的是它非常慢,在我的代码中我必须执行这样的过程两次,在 20 个图像的情况下大约需要 5 秒。还有其他解决方案可以加快此过程吗?
Bitmap contour = new Bitmap(
imageMaskCountour.Width, imageMaskCountour.Height, PixelFormat.Format32bppArgb);
using (Graphics g = Graphics.FromImage(contour))
{
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
g.FillRectangle(ContourBrush, 0, 0, contour.Width, contour.Height);
g.DrawImage(
imageMaskCountour,
new Rectangle(0, 0, contour.Width, contour.Height),
new Rectangle(0, 0, imageMaskCountour.Width, imageMaskCountour.Height),
GraphicsUnit.Pixel);
}
contour.MakeTransparent(Color.Black);
编辑:
我尝试添加LockBitmap并添加以下方法:
public void MakeTransparent(Color color)
{
for (int y = 0; y < this.Height; y++)
{
for (int x = 0; x < this.Width; x++)
{
if (this.GetPixel(x, y) == color)
{
this.SetPixel(x, y, Color.Transparent);
}
}
}
}
但是速度要慢得多。
最佳答案
您在位图上执行的每个操作都需要锁定和解锁位。这使得它非常慢。请参阅this answer如何通过锁定一次、操作所有数据并最终解锁来直接访问位图数据。
以下代码是使用刚才提到的直接访问的常规位图的扩展方法。它实现了您的方法的逻辑。请注意,我将 Height
和 Width
保存到局部变量中。我这样做是因为我认识到如果像循环条件一样多次使用它会慢得多。
警告:
底层代码仅适用于PixelFormat.Format32bppArgb
,see PixelFormat reference 。
该代码让您了解如何直接访问像素数据,并且也可以适应其他像素格式。
如果要适应其他像素格式,必须遵守以下几点。
- 正确写入颜色值的一个目标像素的字节大小。
- 通过
Bitmap.Stride
属性进行正确的行寻址,see Stride for reference 。在PixelFormat.Format32bppArgb
的情况下,步幅通过以下方式与宽度匹配:Bitmap.Stride == Bitmap.Width * 4
,因此不需要调整行地址。
public static void FastMakeTransparent(this Bitmap bitmap, Color color)
{
BitmapData bitmapData = bitmap.LockBits(
new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
unsafe
{
int* pixelPointer = (int*)bitmapData.Scan0;
int bitmapHeight = bitmap.Height;
int bitmapWidth = bitmap.Width;
int colorInt = color.ToArgb();
int transparentInt = Color.Transparent.ToArgb();
for (int i = 0; i < bitmapHeight; ++i)
{
for (int j = 0; j < bitmapWidth; ++j)
{
if (*pixelPointer == colorInt)
*pixelPointer = transparentInt;
++pixelPointer;
}
}
}
bitmap.UnlockBits(bitmapData);
}
在我的 Intel Core2Duo P8400 (2.26 GHz) CPU 上使用秒表类进行基准测试。
Bitmap size 1000x1000 random filled accumulated time of 100 runs
Target AnyCPU .NetFramework 4.5.2
Release build
MakeTransparent Ticks: 24224801 | Time: 2422 ms
FastMakeTransparent Ticks: 1332730 | Time: 133 ms
Debug build
MakeTransparent Ticks: 24681178 | Time: 2468 ms
FastMakeTransparent Ticks: 5976810 | Time: 597 ms
关于c# - Bitmap.MakeTransparent() 太慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43133902/