Reputation: 31
Using Visual C# 2010, I'm trying to write an .avi file from frames received from a Windows Kinect. The frames can be saved easily enough as .png files with the use of a BitmapEncoder and PngBitmapEncoder (saving to a stream) but I can't add these images at my discretion to a VideoStream provided here: http://www.codeproject.com/Articles/7388/A-Simple-C-Wrapper-for-the-AviFile-Library because I need to be able to convert either a RenderTargetBitmap or a DrawingVisual to a System.Drawing.Bitmap.
I've found example codes that do similar things but they all seem to want to instantiate the Image class which Visual Studio tells me is abstract and can't be instantiated.
I'm going round in circles and not getting anywhere.
I just want to do something like this:
...
renderBitmap.Render(dv);
Bitmap bmp=new Bitmap(dv);
VideoStream aviStream=aviManager.AddVideoStream(true,60,bmp);
...
But Bitmap has no useful constructors to get me from dv (DrawingVisual) to bmp. :(
Those 3 lines come from this snippet:
var renderBitmap=new RenderTargetBitmap(colorWidth,colorHeight,96.0,96.0,PixelFormats.Pbgra32);
DrawingVisual dv=new DrawingVisual();
using(DrawingContext dc=dv.RenderOpen())
{
VisualBrush backdropBrush=new VisualBrush(Backdrop);
dc.DrawRectangle(backdropBrush,null,new Rect(0,0,colorWidth,colorHeight));
VisualBrush colorBrush=new VisualBrush(MaskedColor);
dc.DrawRectangle(colorBrush,null,new Rect(0,0,colorWidth,colorHeight));
VisualBrush watermarkBrush=new VisualBrush(Watermark);
dc.DrawRectangle(watermarkBrush,null,new Rect(colorWidth-96,colorHeight-80,64,48));
}
renderBitmap.Render(dv);
Bitmap bmp=new Bitmap(dv);
VideoStream aviStream=aviManager.AddVideoStream(true,60,bmp);
Upvotes: 3
Views: 4870
Reputation: 1
private BitmapSource ToBitmapSource(Visual visual, Brush transparentBackground)
{
var bounds = VisualTreeHelper.GetDescendantBounds(visual);
var scale = VisualTreeHelper.GetDpi(visual);
var bitmapSource = new RenderTargetBitmap(
(int)(bounds.Width * scale.DpiScaleX),
(int)(bounds.Height * scale.DpiScaleY),
scale.PixelsPerInchX,
scale.PixelsPerInchY,
PixelFormats.Pbgra32);
var drawingVisual = new DrawingVisual();
using (var drawingContext = drawingVisual.RenderOpen())
{
drawingContext.DrawRectangle(transparentBackground, null, new Rect(bounds.Size));
drawingContext.DrawRectangle(new VisualBrush(visual), null, new Rect(bounds.Size));
}
bitmapSource.Render(drawingVisual);
return bitmapSource;
}
private System.Drawing.Bitmap BitmapFromSource(BitmapSource bitmapsource)
{
System.Drawing.Bitmap bitmap;
using (MemoryStream outStream = new MemoryStream())
{
BitmapEncoder enc = new BmpBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(bitmapsource));
enc.Save(outStream);
bitmap = new System.Drawing.Bitmap(outStream);
}
return bitmap;
}
Upvotes: 0
Reputation: 54532
The result of using RenderTargetBitMap is a WPF BitMapSource it doesn't convert the Visual itself to a BitmapSource
, it contains the result of the conversion as a BitmapSource
. In order to convert a BitmapSource
to a System.Drawing.Bitmap
try using a modified version of the code from this MSDN Forum Post.
renderBitmap.Render(dv);
BitmapSource bmp = renderBitmap;
using(MemoryStream outStream = new MemoryStream())
{
BitmapEncoder enc = new BmpBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(bmp));
enc.Save(outStream);
System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(outStream);
VideoStream aviStream=aviManager.AddVideoStream(true,60,bitmap);
}
Created a Method to return your Bitmap
renderBitmap.Render(dv);
BitmapSource bmp =renderBitmap;
VideoStream aviStream = aviManager.AddVideoStream(true, 60, ConvertToBitmap(bmp));
private System.Drawing.Bitmap ConvertToBitmap(BitmapSource target)
{
System.Drawing.Bitmap bitmap;
using (MemoryStream outStream = new MemoryStream())
{
BitmapEncoder enc = new BmpBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(target));
enc.Save(outStream);
bitmap = new System.Drawing.Bitmap(outStream);
}
return bitmap;
}
Upvotes: 2