Using Pointers In Managed Code
November 6, 2012 Leave a comment
I am getting ready for my Kinect presentation at RDU’s code camp. One of the techniques that you have to absolutely use with the tidal wave of data that the Kinect sends you is pointers. For example, I have some code that is straight from this book where I turn the video image from the the Kinect ColorSensor a darker shade of blue.
In a default WPF application, I added the following class-level variables:
KinectSensor kinectSensor = null; WriteableBitmap colorImageBitmap = null; Byte[] colorData = null;
I then wired up the Kinect:
kinectSensor = KinectSensor.KinectSensors[0]; kinectSensor.ColorStream.Enable(); kinectSensor.ColorFrameReady += new EventHandler<ColorImageFrameReadyEventArgs>(kinectSensor_ColorFrameReady); kinectSensor.Start();
I then added the following code to the event handler as the video frames come in (30 per second, each frame about 1.5 megs):
if (colorImageFrame != null) { if (colorImageBitmap == null) { colorImageBitmap = new WriteableBitmap( colorImageFrame.Width, colorImageFrame.Height, 96, 96, PixelFormats.Bgr32, null); this.kinectImage.Source = colorImageBitmap; } if (colorData == null) { colorData = new Byte[colorImageFrame.PixelDataLength]; } colorImageFrame.CopyPixelDataTo(colorData); Int32 newColor = 0; for (int i = 0; i < colorData.Length; i = i + 4) { Int32 oldColor = colorData[i]; newColor = (Int32)colorData[i] + 50; if (newColor > 255) { newColor = 255; } colorData[i] = (byte)newColor; } colorImageBitmap.WritePixels( new Int32Rect(0, 0, colorImageFrame.Width, colorImageFrame.Height), colorData, colorImageFrame.Width * colorImageFrame.BytesPerPixel, 0); }
This code works – but it gets too slow when using an under powered computer. To use pointers, I first needed to mark my project as unsafe:
I then added the unsafe keyword to the event handler:
unsafe void kinectSensor_ColorFrameReady(object sender, ColorImageFrameReadyEventArgs e)
And finally, I replaced the managed loop with a loop that uses pointers:
int noOfPixelBytes = colorData.Length; fixed (byte* imageBase = colorData) { byte* imagePosition = imageBase; byte* imageEnd = imageBase + noOfPixelBytes; Int32 newColor = 0; while (imagePosition != imageEnd) { newColor = *imagePosition + 50; if (newColor > 255) { newColor = 255; } *imagePosition = (byte)newColor; imagePosition += 4; } }
This speed things up considerably. A couple of things to note:
The fixed keyword pins the location of imageBase to 1 location so the garbage collector doesn’t move it around. Also, note that I refer the to value of the current byte via imagePosition* (*imagePosition = (byte)newColor) – when I want to move 4 bytes over, I increment the imagePosition (imagePosition += 4)
I am looking forward to Saturday hopefully this presentation will go off without a hitch…