本文介绍了使用不安全代码的C#位图图像遮罩的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用以下代码在C#中制作图像蒙版:

I'm using the following code to make image masks in C#:

for(int x = 0; x < width; x++)
{
    for(int y = 0; y < height; y++)
    {
        bmp.SetPixel(x,y,Color.White);
    }
}

for(int x = left; x < width; x++)
{
    for(int y = top; y < height; y++)
    {
        bmp.SetPixel(x,y,Color.Transparent);
    }
}

但是它太慢了……与此不安全等效的是什么?会更快分配吗?

But it's WAY too slow... What is the unsafe equivalent to this? Will it be allot faster?

最后,我以PNG格式执行bmp.Save().

In the end I do a bmp.Save() in PNG format.

更新:

按照MusiGenesis的建议阅读 [链接已删除,危险站点] 之后,我使用以下代码(需要它的人)使它起作用:

After reading through [Link removed, dangerous site] as suggested by MusiGenesis, I made it work using the following code (for anyone who needs it):

Bitmap     bmp = new Bitmap(1000,1000,PixelFormat.Format32bppArgb);
BitmapData bmd = bmp.LockBits(new Rectangle(0, 0, bmp.Width,bmp.Height),
                                  System.Drawing.Imaging.ImageLockMode.ReadWrite,
                                  bmp.PixelFormat);

int PixelSize=4;

unsafe
{
    for(int y=0; y<bmd.Height; y++)
    {
        byte* row=(byte *)bmd.Scan0+(y*bmd.Stride);

        for(int x=0; x<bmd.Width; x++)
        {
            row[x*PixelSize]     = 0;   //Blue  0-255
            row[x*PixelSize + 1] = 255; //Green 0-255
            row[x*PixelSize + 2] = 0;   //Red   0-255
            row[x*PixelSize + 3] = 50;  //Alpha 0-255
        }
    }
}

bmp.UnlockBits(bmd);

bmp.Save("test.png",ImageFormat.Png);

Alpha通道:0为完全透明,255为该像素不透明.

Alpha channel: 0 being fully transparent, 255 being no transparency on that pixel.

我确定您可以轻松地修改绘制矩形的循环:)

I'm sure you can easily modify the loop for painting a rectangle :)

推荐答案

通过减少写入操作,您仍然可以大大加快循环速度.

You can still speed up your loop by quite a lot, by doing fewer write operations.

在缓冲区中创建一行字节,然后要求.net运行时将其复制到托管内存.在我的计算机上,这大约快10到15倍.

Create a single row of bytes in a buffer, and ask the .net runtime to copy those to managed memory. This is roughly 10-15 times faster on my computer.

// Build a "row" array and copy once for each row
// You can also build the full byte array and do only one
// call to Marshal.Copy, but that of course takes more memory.

var bytesPerPixel = 4;
byte[] row = new byte[bmp.Width * bytesPerPixel];
for (var i = 0; i < bmp.Width; ++i)
{
    var offset = i * bytesPerPixel;

    row[offset+0] = 0; //Blue  0-255
    row[offset+1] = 255; //Green 0-255
    row[offset+2] = 0;   //Red   0-255
    row[offset+3] = 50;  //Alpha 0-255
}

var bits = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, bmp.PixelFormat);
for (var i = 0; i < bits.Height; ++i)
{
    Marshal.Copy(row, 0, bits.Scan0 + (i * bits.Stride), row.Length);
}
bmp.UnlockBits(bits);

如果要保持每个像素的一个循环迭代",则至少应只写入一次每个像素值.这样可以减少我计算机上的运行时间.

If you want to keep your "one loop iteration for each pixel", you should at least only write each pixel value once. This halves the running time on my computer.

var pixel = (uint)(a << 24) | (uint)(r << 16) | (uint)(g << 8) | (b);
unsafe
{
    for (int y = 0; y < bmd.Height; y++)
    {
        var row = (uint*) ((byte*)bmd.Scan0 + (y * bmd.Stride));

        for (int x = 0; x < bmd.Width; x++)
        {
            row[x] = pixel;
        }
    }
}

这篇关于使用不安全代码的C#位图图像遮罩的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-28 06:39
查看更多