Маскирование растровых изображений C # с использованием небезопасного кода

Я использую следующий код для создания масок изображений на 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);
    }
}

Но это ПУТЬ слишком медленно ... Что является небезопасным эквивалентом этого? Будет ли выделено быстрее?

В конце я делаю bmp.Save () в формате PNG.

ОБНОВЛЕНИЕ:

Прочитав [Ссылка удалена, опасный сайт], как было предложено MusiGenesis, я заставил его работать, используя следующий код (для всех, кому он нужен):

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);

Альфа-канал: 0 означает полную прозрачность, 255 означает отсутствие прозрачности в этом пикселе.

Я уверен, что вы легко сможете модифицировать цикл для рисования прямоугольника :)


person Tom    schedule 15.09.2011    source источник
comment
Разве вы не можете сделать это за один цикл? Это будет уже намного быстрее.   -  person Ortiga    schedule 15.09.2011
comment
второй цикл выполняется несколько раз для каждого прямоугольника или прозрачности, которые я применяю к растровому изображению. объединение циклов по-прежнему не даст такого быстрого результата, как использование небезопасного кода.   -  person Tom    schedule 15.09.2011
comment
Вы правильно используете свойства Width и Height вашего BitmapData объекта внутри ваших циклов. Доступ к этим свойствам в Bitmap сам замедлит код (это распространенная ошибка при обработке изображений .NET).   -  person MusiGenesis    schedule 15.09.2011


Ответы (1)


Вы по-прежнему можете значительно ускорить цикл, выполняя меньше операций записи.

Создайте одну строку байтов в буфере и попросите среду выполнения .net скопировать их в управляемую память. На моем компьютере это примерно в 10-15 раз быстрее.

// 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);

Если вы хотите сохранить «одну итерацию цикла для каждого пикселя», вам следует хотя бы один раз записать значение каждого пикселя. Это вдвое сокращает время работы моего компьютера.

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;
        }
    }
}
person gnud    schedule 28.08.2019