如何将DrawingVisual转换为位图?

3
使用Visual C# 2010,我正在尝试从Windows Kinect接收到的帧中编写一个.avi文件。使用BitmapEncoder和PngBitmapEncoder(保存到流)可以轻松将帧保存为.png文件,但我无法随意将这些图像添加到此处提供的VideoStream: http://www.codeproject.com/Articles/7388/A-Simple-C-Wrapper-for-the-AviFile-Library 因为我需要能够将RenderTargetBitmap或DrawingVisual转换为System.Drawing.Bitmap。
我找到了类似的示例代码,但它们似乎都想要实例化Image类,而Visual Studio告诉我它是抽象的,无法实例化。
我一直在打转,却没有任何进展。
我只想做这样的事情:
...
renderBitmap.Render(dv);
Bitmap bmp=new Bitmap(dv);
VideoStream aviStream=aviManager.AddVideoStream(true,60,bmp);
...

但是Bitmap没有有用的构造函数可以让我从dv(DrawingVisual)得到bmp。 :(

这3行来自于此代码片段:

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);

1
我觉得你应该扩展你的示例代码。 "dv"来自哪里?它的类型是什么? - JcMaltaDev
我已经扩展了代码片段,以便更好地理解正在发生的事情。 - Duncan Davey
2个回答

2
使用 RenderTargetBitMap 的结果是一个 WPF BitMapSource,它并不会将 Visual 本身转换为 BitmapSource,而是包含了转换结果作为 BitmapSource。如果要将 BitmapSource 转换为 System.Drawing.Bitmap,请尝试使用这个 MSDN 论坛帖子 中修改过的代码。
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);  
}

创建了一个方法来返回您的位图。
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;
}

0
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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接