|
合成ならWPFでもとりあえずできます。
合成した画像をファイルに保存したりピクセルデータを取得することもできるので、
あとはDirectShowやVFW APIなどを使用してAVIやWMVなどに出力することができるのでは?
(DirectShowプログラミングやった事ないので詳しいことは分からない)
// サンプル
// Windows1 XAML
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="356" Width="876">
<Grid SnapsToDevicePixels="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="400"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="250"/>
<RowDefinition />
</Grid.RowDefinitions>
<Grid Name="grid1" Grid.Column="0" Grid.Row="0">
<Rectangle Margin="0,0,100,50" SnapsToDevicePixels="True">
<Rectangle.Fill>
<DrawingBrush Opacity="0.5">
<DrawingBrush.Drawing>
<VideoDrawing x:Name="MyVideoDrawingA" Rect="0,0,300,200" />
</DrawingBrush.Drawing>
</DrawingBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle Margin="102,59,0,0" SnapsToDevicePixels="True">
<Rectangle.Fill>
<DrawingBrush Opacity="0.5">
<DrawingBrush.Drawing>
<VideoDrawing x:Name="MyVideoDrawingB" Rect="0,0,300,200" />
</DrawingBrush.Drawing>
</DrawingBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
<Image Margin="6,0,12,3" Name="image1" Stretch="Fill" Grid.Column="1" />
<Button Grid.Row="1" Height="23" Margin="0,6,0,0" Name="button1" VerticalAlignment="Top" HorizontalAlignment="Left" Width="76" Click="button1_Click">Play</Button>
<Button Grid.Column="1" Grid.Row="1" HorizontalAlignment="Right" Margin="0,3,0,0" Name="button2" Width="75" Height="23" VerticalAlignment="Top" Click="button2_Click">保存</Button>
<Label Grid.Column="1" Grid.Row="1" Margin="127,3,144,0" Name="label1" Height="28" VerticalAlignment="Top">↑Bitmapに描画したキャプチャ画像</Label>
</Grid>
</Window>
// コード
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using System.IO;
using Microsoft.Win32;
namespace WpfApplication1
{
public partial class Window1 : Window
{
DispatcherTimer tmr;
MediaPlayer MyPlayerA, MyPlayerB;
public Window1()
{
InitializeComponent();
MyPlayerA = new MediaPlayer(); MyPlayerB = new MediaPlayer();
MyPlayerA.Open(new Uri(@"d:\a.wmv", UriKind.Absolute)); MyPlayerB.Open(new Uri(@"d:\b.wmv", UriKind.Absolute));
MyVideoDrawingA.Player = MyPlayerA; MyVideoDrawingB.Player = MyPlayerB;
tmr = new DispatcherTimer();
tmr.Interval =new TimeSpan(0, 0, 0, 0, 33);
tmr.Tick += new EventHandler(tmr_Tick);
MyPlayerA.MediaEnded += new EventHandler(MyPlayer_MediaEnded); MyPlayerB.MediaEnded += new EventHandler(MyPlayer_MediaEnded);
}
void MyPlayer_MediaEnded(object sender, EventArgs e)
{
tmr.Stop();
}
void tmr_Tick(object sender, EventArgs e)
{
image1.Source = CreateBitmapSourceFromVisual(grid1.ActualWidth, grid1.ActualHeight, grid1);
}
private void button1_Click(object sender, RoutedEventArgs e)
{
MyPlayerA.Play(); MyPlayerB.Play();
tmr.Start();
}
private void button2_Click(object sender, RoutedEventArgs e)
{
MyPlayerA.Pause(); MyPlayerB.Pause();
SaveFileDialog sfd = new SaveFileDialog();
if (sfd.ShowDialog() == true)
BitmapSave(grid1.ActualWidth, grid1.ActualHeight, grid1, sfd.FileName);
MyPlayerA.Play(); MyPlayerB.Play();
}
private static BitmapSource CreateBitmapSourceFromVisual(Double width, Double height, Visual visualToRender)
{
if (visualToRender == null)
return null;
RenderTargetBitmap bmp = new RenderTargetBitmap((Int32)Math.Ceiling(width), (Int32)Math.Ceiling(height), 96, 96, PixelFormats.Pbgra32);
bmp.Render(visualToRender);
return bmp;
}
private void BitmapSave(Double width, Double height, Visual visualToRender, string filename)
{
RenderTargetBitmap bmp = new RenderTargetBitmap((Int32)Math.Ceiling(width), (Int32)Math.Ceiling(height), 96, 96, PixelFormats.Pbgra32);
bmp.Render(visualToRender);
// ファイルに保存せずにピクセルデータを直接いじりたい場合は
// RenderTargetBitmapのCopyPixelsメソッドでバイト配列などにピクセルデータをコピーできるので
// コピー後あれこれする
//int stride = (int)((bmp.PixelWidth * bmp.Format.BitsPerPixel + 7) / 8);
//byte[] pixs = new byte[stride * bmp.PixelHeight];
//bmp.CopyPixels(pixs, stride, 0);
BitmapFrame bmf = BitmapFrame.Create(bmp);
FileStream fs = new FileStream(filename, FileMode.Create);
// jpgで保存
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
encoder.QualityLevel = 100;
encoder.Frames.Add(bmf);
encoder.Save(fs);
fs.Close();
}
}
}
|