Home > Net >  Fastest way of setting pixels in C# is slow on small Bitmap
Fastest way of setting pixels in C# is slow on small Bitmap

Time:09-27

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:

  1. 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 of i ?

  2. why new without delete in innermost loop?

    this is heap trashing I would move the new before loops and delete after it. or get rid of it completely. This might boost speed a lot.

  3. 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 % operations

  4. why 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 the if before loops. Any if statement inside heavy duty loop is a major performance hit.

  5. Use multi threading to boost speed.

    so simply obtain your process affinity mask get the number n of CPU/cores divide the image to n regions and do each with its own thread.

  • Related