Search code examples
c#wpfkinect

Problems calculating stride and offset in WritePixels


I am writing a Kinect application, where I use the color image from the sensor. I get a 640 x 480 color image, I copy the data from the sensor to a WriteableBitmap, with the WritePixels method. When I use the whole color image I have no issues. But I would like to use only the middle part of the image. But I can't get stride and or offset right?

To copy the whole image I do the following:

_colorImageWritableBitmap.WritePixels(
                new Int32Rect(0, 0, colorImageFrame.Width, colorImageFrame.Height),
                _colorImageData,
                colorImageFrame.Width * Bgr32BytesPerPixel,
                0);

As I mention I only want the middle part of the image. I would like to start at a width at 185px and take the next 270px, and stop there. And I use the the whole height.

My PixelFormat is bgr32, so to calculate the byte pr. pixel I use:

var bytesPrPixel = (PixelFormats.Bgr32.BitsPerPixel + 7)/8;

And my stride:

var stride = bytesPrPixel*width;

The writepixel method:

_colorImageWritableBitmap.WritePixels(
                new Int32Rect(0, 0, colorImageFrame.Width, colorImageFrame.Height),
                _colorImageData, stride, offset);

But when I change the width to other than 640, the image gets wrong (hidden in noise).

Can someone help me, to understand what I am doing wrong here?


Solution

  • You have to properly copy the pixels from the source bitmap. Assuming that the source colorImageFrame is also a BitmapSource, you would do it this way:

    var width = 270;
    var height = 480;
    var x = (colorImageFrame.PixelWidth - width) / 2;
    var y = 0;
    var stride = (width * colorImageFrame.Format.BitsPerPixel + 7) / 8;
    var pixels = new byte[height * stride];
    colorImageFrame.CopyPixels(new Int32Rect(x, y, width, height), pixels, stride, 0);
    

    Now you could write the pixel buffer to your WriteableBitmap by:

    colorImageWritableBitmap.WritePixels(
        new Int32Rect(0, 0, width, height), pixels, stride, 0);
    

    Or instead of using WriteableBitmap, you just create a new BitmapSource, like:

    var targetBitmap = BitmapSource.Create(
        width, height, 96, 96, colorImageFrame.Format, null, pixels, stride);
    

    However, the easiest way to create a crop of the source bitmap might be to used a CroppedBitmap like this:

    var targetBitmap = new CroppedBitmap(
        colorImageFrame, new Int32Rect(x, y, width, height));