C# fast pixel rendering
Asked Answered
L

3

9

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?

Lavone answered 14/6, 2012 at 9:57 Comment(3)
How are you setting the pixels currently?Titian
Created a bitmap, using image.SetPixel(x, y, colour). After all that, calling graphics.drawImage(image, etc)Lavone
SetPixel is very slow. Look at the Scanline approach.Titian
B
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

Bismuthous answered 14/6, 2012 at 15:44 Comment(1)
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.Lavone
H
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?

Hegumen answered 14/6, 2012 at 10:27 Comment(2)
Thanks for your reply, but the answer link you've provided uses .SetPixel() in the conversion from WriteableBitmap to System.Drawing.Image.Lavone
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.Hegumen
H
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!

Hasid answered 14/6, 2012 at 16:30 Comment(3)
That link is no longer valid.Marlin
You realize you just downvoted an answer that a. is ~10 years old b. Is still available as a single file include on Nuget.org Did you even take the time to check the nuget package?Hasid
Regardless, I just updated it.Hasid

© 2022 - 2024 — McMap. All rights reserved.