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.Count
is the same as color channel count then why are you setting all the channels in each iteration ofi
?why
new
withoutdelete
in innermost loop?this is heap trashing I would move the
new
before loops anddelete
after 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.Count
times 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
i
loop. 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 == 4
and one for without it so you move theif
before loops. Anyif
statement 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
n
of CPU/cores divide the image ton
regions and do each with its own thread.