#c# #asp.net #wpf #mediaelement
#c# #asp.net #wpf #mediaelement
Вопрос:
Я должен показывать кадры из медиа-элемента в элементе управления изображением, например, в видео. Я попытался захватить продолжающиеся кадры из медиа-элемента с помощью таймера и привязать это растровое изображение к источнику изображения. Но при установке масштаба равным 1 кажется, что кадры захватываются очень медленно. И при уменьшении масштаба до 0,3 или ниже захват выполняется очень быстро. но качество кадра снижается. Есть ли какой-нибудь способ решить эту проблему? Короче говоря, я хочу отображать кадры из медиа-элемента в источник изображения без каких-либо задержек и с оригинальным качеством.
<MediaElement x:Name="MediaEL" Volume="0" ScrubbingEnabled="True" SnapsToDevicePixels="True" MediaOpened="MediaEL_MediaOpened" LoadedBehavior="Manual" MediaEnded="MediaEL_MediaEnded" MediaFailed="MediaEL_MediaFailed">
</MediaElement>
<Image Name="ImageViewerMediaEL" />
ScreenShotimer = new DispatcherTimer();
ScreenShotimer.Interval = TimeSpan.FromMilliseconds(35);//35//
ScreenShotimer.Tick = ScreenShotimer_Tick;
public Bitmap TakeScreenshot(MediaElement medElement, double scale)
{
Bitmap screenBitmap = null;
double actualHeight = medElement.NaturalVideoHeight;
double actualWidth = medElement.NaturalVideoWidth;
double renderHeight = actualHeight * scale;
double renderWidth = actualWidth * scale;
if ((int)renderWidth > 0 amp;amp; (int)renderHeight > 0)
{
RenderTargetBitmap renderTarget = new RenderTargetBitmap((int)renderWidth,
(int)renderHeight, 96, 96, PixelFormats.Default);
VisualBrush sourceBrush = new VisualBrush(medElement);
DrawingVisual drawingVisual = new DrawingVisual();
DrawingContext drawingContext = drawingVisual.RenderOpen();
using (drawingContext)
{
drawingContext.PushTransform(new ScaleTransform(scale, scale));
drawingContext.DrawRectangle(sourceBrush, null, new Rect(new System.Windows.Point(0, 0),
new System.Windows.Point(actualWidth, actualHeight)));
}
renderTarget.Render(drawingVisual);
MemoryStream stream = new MemoryStream();
BitmapEncoder encoder = new BmpBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(renderTarget));
encoder.Save(stream);
screenBitmap = new Bitmap(stream);
}
return screenBitmap;
}
Ответ №1:
Использование WinForms Bitmap
в приложении WPF, похоже, не требуется.
Повторно используйте один экземпляр RenderTargetBitmap, который создается только при необходимости и присваивается свойству источника элемента изображения.
Кроме того, повторно используйте DrawingVisual и рисуйте прямоугольник с помощью VisualBrush только при изменении размера.
private readonly DrawingVisual visual = new DrawingVisual();
private RenderTargetBitmap bitmap;
...
private void OnTimerTick(object sender, EventArgs e)
{
var width = MediaEL.NaturalVideoWidth;
var height = MediaEL.NaturalVideoHeight;
if (width > 0 amp;amp; height > 0)
{
if (bitmap == null ||
bitmap.PixelWidth != width ||
bitmap.PixelHeight != height)
{
using (var dc = visual.RenderOpen())
{
dc.DrawRectangle(
new VisualBrush(MediaEL), null,
new Rect(0, 0, width, height));
}
bitmap = new RenderTargetBitmap(
width, height, 96, 96, PixelFormats.Default);
ImageViewerMediaEL.Source = bitmap;
}
bitmap.Render(visual);
}
}
Приведенный выше код отлично работает для меня с Wildlife.wmv от Microsoft и интервалом таймера 35 мс.