8

I'm developing depth processing (Xbox Kinect, Asus Xtion, etc) applications using OpenNI.

I need a really simple and fast way of drawing on a Windows form when new depth data is available from the sensor (30 or 60 fps depending on resolution).

Currently I'm invalidating a double-buffered panel from a seperate thread when the data becomes available, and then setting pixels of a bitmap in the panel's paint method, yielding a predictably awful 5fps.

System.Drawing.Graphics seems to lack a fast way to set individual pixels, unless anyone can instruct otherwise.

I literally just need to set pixel colours, so would like to avoid using third party high speed rendering APIs if possible, and ideally use something as native as possible.

Does anyone have any suggestions?

Toby Wilson
  • 1,467
  • 5
  • 19
  • 42

3 Answers3

7

If you're using Bitmaps, then you should use LockBits and UnlockBits to access the data directly in memory. In C#, you can get some extra performance by using unsafe code blocks and pointers.

See this link for more information: http://web.archive.org/web/20150227183132/http://bobpowell.net/lockingbits.aspx

elixenide
  • 44,308
  • 16
  • 74
  • 100
Chris Dunaway
  • 10,974
  • 4
  • 36
  • 48
  • This was a drastic improvement. I couldn't achieve more than 10 fps when drawing a blank 640x480 bitmap so the conclusion is that System.Drawing is just fundamentally not fast. This solution, combined with scaling the image down and only rendering some of the pixels to achieve the required FPS was the answer. – Toby Wilson Jun 15 '12 at 07:36
4

image.SetPixel() is very slow when you are replacing many pixels per frame and you need many frames per second.

It will be a lot faster when you use a WriteableBitmap and call CopyPixels

This way you can fill the array with pixel data using multiple threads and simply blit the array to the image in a single call.

EDIT

Note that WriteableBitmap is a WPF class. If you are bound to WinForms you might need to create your own implementation. WPF/WinForms/GDI interop: converting a WriteableBitmap to a System.Drawing.Image?

Community
  • 1
  • 1
Emond
  • 50,210
  • 11
  • 84
  • 115
  • Thanks for your reply, but the answer link you've provided uses .SetPixel() in the conversion from WriteableBitmap to System.Drawing.Image. – Toby Wilson Jun 14 '12 at 12:39
  • Yes, and that is horrible for speed. An alternative would be to write to an array and use an encoder (PNG, BMP, ...) to turn it into an image an display it. The main problem with SetPixel is that it sets a single pixel. – Emond Jun 14 '12 at 12:54
0

You could try my LINQ image processing library to work with your "buffer-bitmaps". It uses an accessible LINQ syntax but is very performant for large bitmaps. It is available on Nuget as a single file include in your project.

Hope that helps!

Ani
  • 10,826
  • 3
  • 27
  • 46