Fast Bitmap modifying using BitmapData and pointers in C#

岁酱吖の 提交于 2020-03-04 12:35:13

问题


I am capturing data from some camera (array of RAW data).

Then I'm mapping this data to RGB values according to color palette.

I need to map it as fast as possible, so I use BitmapDdata and edit pixels in unsafe piece of code using pointers.

public void dataAcquired(int[] data)
{
    Bitmap bmp = new Bitmap(width, height); 
    BitmapData data = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

    for (int i = 0; i < data.Length; i++)
    {
        int x = i % bmp.Width;
        int y = i / bmp.Width;
        Rgb rgb = mapColors[data[i]];

        unsafe
        {
            byte* ptr = (byte*)data.Scan0;
            ptr[(x * 3) + y * data.Stride] = rgb.b;
            ptr[(x * 3) + y * data.Stride + 1] = rgb.g;
            ptr[(x * 3) + y * data.Stride + 2] = rgb.r;
        }
    }
    bmp.UnlockBits(data);
}

And I'm doing this for every incoming frame. It works fine, but it still takes something like 30ms for each frame for 320x240 pixels.

Is it possible to make it even more faster? Maybe I couldlock/unlock data in memory only once, but I'm not sure about this.


回答1:


Instead of calculating x and y for each pixel, you could make them loop counters, like this:

for( y = 0;  y < bmp.Height;  y++ )
    for( x = 0;  x < bmp.Width;  x++ )

Better yet, ditch x and y altogether and just keep incrementing the ptr pointer instead of recalculating an offset from the ptr pointer three times per pixel.

Try this (warning: I have not checked it.)

public void dataAcquired()
{
    Bitmap bmp = new Bitmap(width, height); 
    BitmapData data = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
    unsafe
    {
        int i = 0;
        byte* ptr = (byte*)data.Scan0;
        for( int y = 0;  y < bmp.Height;  y++ )
        {
            byte* ptr2 = ptr;
            for( int x = 0;  x < bmp.Width;  x++ )
            {
                Rgb rgb = mapColors[data[i++]];
                *(ptr2++) = rgb.b;
                *(ptr2++) = rgb.g;
                *(ptr2++) = rgb.r;
            }
            ptr += data.Stride;
        }
    }
    bmp.UnlockBits(data);
}



回答2:


Try run code in parallel: change

for (int i = 0; i < data.Length; i++) {
  ...
}

into

  Parallel.For(0, data.Length, (i) => {
    int x = i % bmp.Width;
    int y = i / bmp.Width;
    Rgb rgb = mapColors[data[i]];

    unsafe {
      byte* ptr = (byte*) data.Scan0;
      ptr[(x * 3) + y * data.Stride] = rgb.b;
      ptr[(x * 3) + y * data.Stride + 1] = rgb.g;
      ptr[(x * 3) + y * data.Stride + 2] = rgb.r;
    }
  });


来源:https://stackoverflow.com/questions/28323448/fast-bitmap-modifying-using-bitmapdata-and-pointers-in-c-sharp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!