Ответ 1
Ознакомьтесь с этим руководством по использованию LockBits
:
http://www.BobPowell.net/lockingbits.htm
Это будет на порядок быстрее, чем при использовании SetPixel
.
Я использую следующий код для создания масок изображений в С#:
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.
UPDATE:
Прочитав [Ссылка удалена, опасный сайт], как предложено 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 без прозрачности для этого пикселя.
Я уверен, что вы можете легко изменить цикл для рисования прямоangularьника :)
Ознакомьтесь с этим руководством по использованию LockBits
:
http://www.BobPowell.net/lockingbits.htm
Это будет на порядок быстрее, чем при использовании SetPixel
.
Вы все еще можете значительно ускорить цикл, делая меньше операций записи.
Создайте одну строку байтов в буфере и попросите среду выполнения .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;
}
}
}