I'm trying to edit pixels of a Bitmap (960x510), and I'm using the fastest method I could find. But it's still painfully slow (7 FPS).
unsafe
{
BitmapData bitmapData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, bmp.PixelFormat);
int bytesPerPixel = Image.GetPixelFormatSize(bmp.PixelFormat) / 8;
int heightInPixels = bitmapData.Height;
int widthInBytes = bitmapData.Width * bytesPerPixel;
byte* PtrFirstPixel = (byte*)bitmapData.Scan0;
for(int y = 0; y < heightInPixels; y )
{
byte* currentLine = PtrFirstPixel (y * bitmapData.Stride);
for (int x = 0; x < widthInBytes; x = x bytesPerPixel)
{
for (int i = 0; i < Shaders.Count; i )
{
rgba color = new rgba(currentLine[x], currentLine[x 1], currentLine[x 2], -1);
if (bytesPerPixel == 4) color.a = currentLine[x 3];
Shaders[i].pixel(new xy(x * bytesPerPixel % bmp.Width, x * bytesPerPixel / bmp.Height), color);
currentLine[x] = (byte)color.r;
currentLine[x 1] = (byte)color.g;
currentLine[x 2] = (byte)color.b;
if (bytesPerPixel == 4) currentLine[x 3] = (byte)color.a;
}
}
}
bmp.UnlockBits(bitmapData);
}
The method inside Shaders[i].pixel changes the color.r, color.g, color.b and color.a values.
How can I increase performance?
CodePudding user response:
I do not code in C# but you are doing too much operations per color channel and pixel not sure what you re trying to do but most likely you could optimize it a lot for example:
why 3 loops?
this stuff is usually done in 2 loops and the last loop unrolled or done at once. Also I assume
Shaders.Countis the same as color channel count then why are you setting all the channels in each iteration ofi?why
newwithoutdeletein innermost loop?this is heap trashing I would move the
newbefore loops anddeleteafter it. or get rid of it completely. This might boost speed a lot.why computing
(x * bytesPerPixel % bmp.Width, x * bytesPerPixel / bmp.Height)?You are computing it
heightInPixels*Shaders.Counttimes instead of once. This can be precomputed once into a LUT before for loops instead of computing it again and again. This is major speed boost.btw if LUT is out of question due to low memory you could at least move the computation before
iloop. Also if you change the bmp x resolution to power of 2 to get rid of all the / and % operationswhy
if (bytesPerPixel == 4) currentLine[x 3] = (byte)color.a;You can have 2 copies of code one for
bytesPerPixel == 4and one for without it so you move theifbefore loops. Anyifstatement inside heavy duty loop is a major performance hit.Use multi threading to boost speed.
so simply obtain your process affinity mask get the number
nof CPU/cores divide the image tonregions and do each with its own thread.
