Bitmap.MakeTransparent()太慢

时间:2017-03-31 06:30:40

标签: c# algorithm optimization drawing

我使用黑白图片作为蒙版,在应用矩形后生成漂亮的轮廓。不幸的是,为了摆脱黑色我使用MakeTransparent方法,不幸的是它非常慢,在我的代码中我必须执行两次这样的过程,在20个图像的情况下需要大约5秒。有没有其他解决方案来加快这个程序?

        Bitmap contour = new Bitmap(imageMaskCountour.Width, imageMaskCountour.Height, System.Drawing.Imaging.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);
                }
            }
        }
    }

但速度要慢得多。

1 个答案:

答案 0 :(得分:1)

您对位图所做的每个操作都需要对位进行锁定和解锁。这使其非常缓慢。请参见this answer,如何通过一次锁定,操作所有数据并最终对其进行解锁直接访问位图数据。

以下代码是使用上述直接访问的常规Bitmap的扩展方法。它实现了方法的逻辑。请注意,我将HeightWidth保存到局部变量。之所以这样做,是因为我认识到在循环条件下多次使用它的速度也很慢。

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上具有Stopwatch类的基准。

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