1

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

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

有什么帮助吗?

在此处输入图像描述

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

在此处输入图像描述

4

3 回答 3

2

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

<Canvas Width="800" Height="600" Background="Black">
    <Canvas.Clip>
        <RectangleGeometry Rect="0,0,10,10" />
             <!-- whatever you want -->    
    </Canvas.Clip>
</Canvas>
于 2012-11-15T17:17:20.620 回答
2

最后我想出了如何实现这一点。您只需要一个 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>

用户在视频前面绘制的椭圆

于 2012-11-18T22:18:59.747 回答
0

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

于 2018-02-15T18:05:12.287 回答