senseiwa
senseiwa

Reputation: 2489

Insufficient buffer size using WriteableBitmap?

I am modifying the ColorBasic Kinect example in order to display an image overlaid to the video stream. So what I've done is to load an image with transparent background (now a GIF but it may change), and write to the displayed bitmap.

The error I'm getting is that the buffer I'm writing to is too small.

I cannot see what the actual error is (I'm a complete newbie in XAML/C#/Kinect), but the WriteableBitmap is 1920x1080, and the bitmap I want to copy is 200x200, so why am I getting this error? I cannot see how a transparent background could be of any harm, but I am beginning to suspect that...

Note that without the last WritePixels, the code works and I see the webcam's output. My code follows.

The overlay image:

public BitmapImage overlay = new BitmapImage(new Uri("C:\\users\\user\\desktop\\something.gif"));

The callback function that displays the Kinect's webcam (see the default example ColorBasic) with my very small modifications:

private void Reader_ColorFrameArrived(object sender, ColorFrameArrivedEventArgs e)
{
    // ColorFrame is IDisposable
    using (ColorFrame colorFrame = e.FrameReference.AcquireFrame())
    {
        if (colorFrame != null)
        {
            FrameDescription colorFrameDescription = colorFrame.FrameDescription;

            using (KinectBuffer colorBuffer = colorFrame.LockRawImageBuffer())
            {
                this.colorBitmap.Lock();

                // verify data and write the new color frame data to the display bitmap
                if ((colorFrameDescription.Width == this.colorBitmap.PixelWidth) && (colorFrameDescription.Height == this.colorBitmap.PixelHeight))
                {
                    colorFrame.CopyConvertedFrameDataToIntPtr(
                        this.colorBitmap.BackBuffer,
                        (uint)(colorFrameDescription.Width * colorFrameDescription.Height * 4),
                        ColorImageFormat.Bgra);

                    this.colorBitmap.AddDirtyRect(new Int32Rect(0, 0, this.colorBitmap.PixelWidth, this.colorBitmap.PixelHeight));
                }

                if(this.overlay != null)
                {
                    // Calculate stride of source
                    int stride = overlay.PixelWidth * (overlay.Format.BitsPerPixel / 8);

                    // Create data array to hold source pixel data
                    byte[] data = new byte[stride * overlay.PixelHeight];

                    // Copy source image pixels to the data array
                    overlay.CopyPixels(data, stride, 0);

                    this.colorBitmap.WritePixels(new Int32Rect(0, 0, overlay.PixelWidth, overlay.PixelHeight), data, stride, 0);
                }

                this.colorBitmap.Unlock();
            }
        }
    }
}

Upvotes: 3

Views: 1495

Answers (1)

Chubosaurus Software
Chubosaurus Software

Reputation: 8161

Your overlay.Format.BitsPerPixel / 8 will be 1 (because it's a gif), but you're trying to copy it to something that is not a gif, probably BGRA (32 bit). Thus you got a huge difference in size (4x).


.WritePixels should take in the stride value of the destination buffer, but you past it the stride value of the overlay (this can cause weird problems as well).


And finally, even if it went 100% smooth your overlay will not actually "overlay" anything, it will replace -- since I don't see any alpha bending math in your code.

Switch your .gif to a .png (32bit) and see if that helps.

Also, if you're looking for an AlphaBltMerge type code: I wrote the entire thing here.. it's very easy to understand.


Merge 2 - 32bit Images with Alpha Channels

Upvotes: 2

Related Questions