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?
In the end I do a bmp.Save() in PNG format.
UPDATE:
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 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.
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; } } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With