将视频渲染到画布中的特定区域

时间:2012-11-15 12:15:02

标签: wpf video wpf-controls media-player render

我创建了自己的画布(黑色区域),我绘制的元素不是从Shape派生的。相反,我使用覆盖方法Canvas.OnRender中的DrawingContext绘制。

问题是,我想播放视频文件并将帧渲染到我画布的特定区域(例如红色矩形) - 也在OnRender中。但通常MediaPlayer直接绑定到一个刷子,它填充了UIElement的完整背景。

任何帮助?

enter image description here

好的,这里有更多解释。我可以向任何方向滚动,平移和缩放画布,然后使用drawingContext影响我在OnRender中绘制的内容。下图显示了一个带有图像(门)的画布,它是从网络摄像头逐帧出现的。因此,只要我的画布无效,我就可以在drawingContext.DrawImage中使用BitmapSource。我仍然可以画出我的原语。 MediaPlayer / MediaElement的问题在于我没有逐帧获取它,但我仍想将其渲染为类似于画布中的网络摄像头图像。

enter image description here

3 个答案:

答案 0 :(得分:2)

尝试将Clip应用到您的Canvas,如下所示:

<Canvas Width="800" Height="600" Background="Black">
    <Canvas.Clip>
        <RectangleGeometry Rect="0,0,10,10" />
             <!-- whatever you want -->    
    </Canvas.Clip>
</Canvas>

答案 1 :(得分:1)

最后,我想出了如何实现这一目标。您只需要一个MediaPlayer并将其输入到每个Canvas.OnRender循环中的drawingContext.DrawVideo中。下面的示例图片和代码。我还包括从视频中捕获帧(BitmapSource)的方法,以及如何将其转换为旧的System.Drawing.Bitmap。

public partial class RenderCanvas : UserControl
{
    readonly MediaPlayer player;

    public RenderCanvas()
    {
        InitializeComponent();

        player = new MediaPlayer();
        player.Open(new Uri(@"test.avi", UriKind.Relative));
        player.Play();
    }

    protected override void OnRender(DrawingContext drawingContext)
    {
        base.OnRender(drawingContext);

        if (player != null && player.Source != null)
            drawingContext.DrawVideo(player, new Rect(0, 0, 200, 150));

        // draw any shape in front of the video
        drawingContext.DrawEllipse(Brushes.Blue, new Pen(Brushes.Red, 5), new Point(150, 150), 60, 60);
    }

    BitmapSource GetBitmapSourceFromVideo()
    {
        var drawingVisual = new DrawingVisual();
        var renderTargetBitmap = new RenderTargetBitmap(player.NaturalVideoWidth, player.NaturalVideoHeight, 96, 96, PixelFormats.Default);
        using (var drawingContext = drawingVisual.RenderOpen())
        {
            drawingContext.DrawVideo(player, new Rect(0, 0, player.NaturalVideoWidth, player.NaturalVideoHeight));
        }

        renderTargetBitmap.Render(drawingVisual);

        return renderTargetBitmap;
    }

    System.Drawing.Bitmap GetBitmapFromVideo()
    {
        BitmapSource bitmapSource = GetBitmapSourceFromVideo();

        var encoder = new PngBitmapEncoder();
        encoder.Frames.Add(BitmapFrame.Create(bitmapSource));
        using (var stream = new MemoryStream())
        {
            encoder.Save(stream);
            stream.Seek(0, SeekOrigin.Begin);

            return (System.Drawing.Bitmap)System.Drawing.Image.FromStream(stream);
        }
    }
}

这里是示例应用程序的XAML代码。 RenderCanvas的XAML没有变化。

<Window x:Class="CanvasTest_OnRender.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:CanvasTest_OnRender="clr-namespace:CanvasTest_OnRender" Title="MainWindow" Height="350" Width="525">
    <Grid>
        <CanvasTest_OnRender:RenderCanvas />
    </Grid>
</Window>

User drawn ellipse in front of video

答案 2 :(得分:0)

我想通过内存流播放视频(带音频)播放,此代码有帮助吗?