I am working with mediaframes (Kinect) to get colour, Depth/Infrared frames on UWP in realtime. This is to store frame data on disk and later process it.
For colour, I get pixels in bytes by using Memorystream.
// Get the Individual color Frame
var vidFrame = clrFrame?.VideoMediaFrame;
{
if (vidFrame == null) return;
// create a UWP SoftwareBitmap and copy Color Frame into Bitmap
SoftwareBitmap sbt = new SoftwareBitmap(vidFrame.SoftwareBitmap.BitmapPixelFormat, vidFrame.SoftwareBitmap.PixelWidth, vidFrame.SoftwareBitmap.PixelHeight);
vidFrame.SoftwareBitmap.CopyTo(sbt);
// PixelFormat needs to be in 8bit for Colour only
if (sbt.BitmapPixelFormat != BitmapPixelFormat.Bgra8)
sbt = SoftwareBitmap.Convert(vidFrame.SoftwareBitmap, BitmapPixelFormat.Bgra8);
if (source != null)
{
var ignore = Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () =>
{
extBitmap = new WriteableBitmap(sbt.PixelWidth, sbt.PixelHeight);
sbt.CopyToBuffer(extBitmap.PixelBuffer);
byte[] pixels = PixelBufferToWriteableBitmap(extBitmap);
extBitmap.Invalidate();
await SavePixelsToFile(pixels);
});
}
}
public async Task<byte[]> PixelBufferToWriteableBitmap(WriteableBitmap wb)
{
using (Stream stream = wb.PixelBuffer.AsStream())
{
using (MemoryStream memoryStream = new MemoryStream())
{
await stream.CopyToAsync(memoryStream);
byte[] pixels = memoryStream.ToArray();
return pixels;
}
}
}
The Infrared pixelformat is Gray16 (in SoftwareBitmap); I want to keep the raw pixel data (so no data is lost from the frame) and write it to the localfolder in ushort[] array.
Following are the links, I came across on how to get set pixel from software bitmap. However, it is bgra to byte and I want to convert software bitmap into ushort.
How to set/get pixel from Softwarebitmap
https://learn.microsoft.com/en-us/windows/uwp/audio-video-camera/imaging
I am new at this and not sure how to proceed, with this.
Can someone please help?
EDIT
I figured that a buffer mediaframe can be converted to byte array by doing the following:
public async Task<byte[]> BufferStreamTobyte(BufferMediaFrame buffFrame) {
using (Stream stream = buffFrame.Buffer.AsStream())
{
using (MemoryStream memoryStream = new MemoryStream())
{
await stream.CopyToAsync(memoryStream);
byte[] pixels = memoryStream.ToArray();
return pixels;
}
}
}
But I am not sure if I loose information of Infrared frame by doing this. Since Infrared and Depth are 16 bits per pixel and this current byte conversion holds 8 bpp. For this ushort[] would be able to hold 16bpp. I very new to this and not sure so I hope I have gotten this right?
EDIT 2:
I have got the pixel data in byte[]. I understand that byte is 8 bits and short is 16 bits so I changed the length of the arrays:
int width = softwareBitmap.PixelWidth;
int height = softwareBitmap.PixelHeight;
int length = width * height * 2;
byte[] irbyteData = new byte[length]; // *2 to get 16 bit
var irshortData = new ushort[width * height]; // 16 bit ushort
IntPtr ptr = (IntPtr)pixelBytesAddress;
Marshal.Copy(ptr, irbyteData, 0, length); //seems to successfully get pixels from memory but not sure if this is lossless