public void EnsureLossLessRoundTrip() { using (var stream = GetResource("scary_face.bmp")) using (var image = Image.FromStream(stream)) using (var bmp = new Bitmap(image)) { var data = bmp.LockBits( new Rectangle(Point.Empty, image.Size), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); var argbStride = image.Width * 4; var rgbStride = image.Width * 3; var dest = new byte[argbStride * image.Height]; var dest2 = new byte[rgbStride * image.Height]; var original = new byte[rgbStride * image.Height]; fixed(byte *originalPtr = original) fixed(byte *destPtr = dest) fixed(byte *dest2Ptr = dest2) { // Put the original 24bit RGB pixel data into an array for // later validation. Buffer.MemoryCopy( (void *)data.Scan0, originalPtr, original.Length, original.Length); // Convert the source 24bit RGB pixel data to 32bit ARGB. // This conversion is lossless. LibYuv.RGB24ToARGB( (byte *)data.Scan0, rgbStride, destPtr, argbStride, image.Width, image.Height); // Convert the newly created 32bit ARGB back to the original // 24bit RGB. This conversion is lossless. LibYuv.ARGBToRGB24( destPtr, argbStride, dest2Ptr, rgbStride, image.Width, image.Height); } // Ensure that the data survived the round trip. CollectionAssert.AreEqual(original, dest2); // And this is sanity check, to ensure that we're infact // doing something. CollectionAssert.AreNotEqual(original, dest); bmp.UnlockBits(data); } }
private unsafe BitmapSource GetBitmapFromImage() { var captureData = k4a_image_get_buffer(this.image.Handle); var captureSize = (int)this.image.Size; switch (image.Format) { case ImageFormat.ColorMJPG: { this.bitmapDecoder = new BitmapDecoder(this.imagingFactory, ContainerFormatGuids.Jpeg); this.stream = new WICStream(this.imagingFactory, new DataPointer(captureData, captureSize)); this.bitmapDecoder.Initialize(this.stream, DecodeOptions.CacheOnLoad); this.frame = this.bitmapDecoder.GetFrame(0); this.formatConverter = new FormatConverter(this.imagingFactory); formatConverter.Initialize(frame, PixelFormat.Format32bppPBGRA, BitmapDitherType.None, null, 0.0, BitmapPaletteType.Custom); return(formatConverter); } case ImageFormat.ColorBGRA32: return(new Bitmap(this.imagingFactory, image.WidthPixels, image.HeightPixels, PixelFormat.Format32bppPBGRA, new DataRectangle(captureData, image.StrideBytes), captureSize)); case ImageFormat.IR16: case ImageFormat.Depth16: return(new Bitmap(this.imagingFactory, image.WidthPixels, image.HeightPixels, PixelFormat.Format16bppGrayFixedPoint, new DataRectangle(captureData, image.StrideBytes), captureSize)); case ImageFormat.ColorNV12: { int textureWidth = this.image.WidthPixels; int textureHeight = this.image.HeightPixels; var imagePixels = textureWidth * textureHeight; var nv12Span = new Span <byte>(captureData.ToPointer(), captureSize); var nv12ySpan = nv12Span.Slice(0, imagePixels); var nv12uvSpan = nv12Span.Slice(nv12ySpan.Length, (int)(imagePixels * 0.5)); var bitmap = new Bitmap(this.imagingFactory, image.WidthPixels, image.HeightPixels, PixelFormat.Format32bppPBGRA, BitmapCreateCacheOption.CacheOnLoad); using (var bitmapLock = bitmap.Lock(BitmapLockFlags.Write)) { var ptr = (byte *)bitmapLock.Data.DataPointer.ToPointer(); fixed(byte *yptr = nv12ySpan) fixed(byte *uvptr = nv12uvSpan) { _ = LibYuv.NV12ToARGB(yptr, textureWidth, uvptr, textureWidth, ptr, textureWidth * 4, textureWidth, textureHeight); } } return(bitmap); } case ImageFormat.ColorYUY2: { int textureWidth = this.image.WidthPixels; int textureHeight = this.image.HeightPixels; var imagePixels = textureWidth * textureHeight; var yuv2Span = new Span <byte>(captureData.ToPointer(), captureSize); var bitmap = new Bitmap(this.imagingFactory, image.WidthPixels, image.HeightPixels, PixelFormat.Format32bppPBGRA, BitmapCreateCacheOption.CacheOnLoad); using (var bitmapLock = bitmap.Lock(BitmapLockFlags.Write)) { var ptr = (byte *)bitmapLock.Data.DataPointer.ToPointer(); fixed(byte *yuv2ptr = yuv2Span) { _ = LibYuv.YUY2ToARGB(yuv2ptr, textureWidth * 2, ptr, textureWidth * 4, textureWidth, textureHeight); } } return(bitmap); } case ImageFormat.Custom8: case ImageFormat.Custom16: case ImageFormat.Custom: default: throw new NotImplementedException($"Format not implemented: {image.Format}."); } }