Create Video from ImageSource
Is there any easy way of addi开发者_开发百科ng ImageSources to a stack and create a video from it?
I already did such a class. I only have to submit my "ImageInfo" which is a system.DrawingBitmap. This can be created easy by using the following code:
Public Function WpfBitmapSourceToBitmap(ByVal source As BitmapSource) As System.Drawing.Bitmap
If source Is Nothing Then Return Nothing
Dim bmp As New System.Drawing.Bitmap(source.PixelWidth, source.PixelHeight, System.Drawing.Imaging.PixelFormat.Format32bppPArgb)
Dim data As System.Drawing.Imaging.BitmapData = bmp.LockBits(New System.Drawing.Rectangle(System.Drawing.Point.Empty, bmp.Size), System.Drawing.Imaging.ImageLockMode.[WriteOnly], System.Drawing.Imaging.PixelFormat.Format32bppPArgb)
source.CopyPixels(Int32Rect.Empty, data.Scan0, data.Height * data.Stride, data.Stride)
bmp.UnlockBits(data)
Return bmp
End Function
Then I did a AviClass to add frames to it and store it as a AVI file with preselected Codec (for example XVid MPEG4)
Public Class clsAviWriter
Inherits MAINInterface.TB.Imaging.Pia7.clsDspTemplate
Private cAvi As AviReaderWriter.AviFile.AviManager
Private AviStream As AviReaderWriter.AviFile.VideoStream
Private AudioStream As AviReaderWriter.AviFile.AudioStream
Private cFps As clsTbQueue
Private OldFpsDate As Date = Now
''' <summary>
''' The image object to paint graphical objects on it
''' </summary>
''' <value>descriptor of the image</value>
Public Overrides Property ImageInfo() As MAINInterface.TB.Imaging.Pia7.clsImageInfo
Get
Return Me._ImageInfo
End Get
Set(ByVal value As MAINInterface.TB.Imaging.Pia7.clsImageInfo)
Me._ImageInfo = value
Call WriteFrame()
Call Me.OnPropertyChanged(Me.Guid)
End Set
End Property
Private Sub WriteFrame()
Dim D As Date = Now
Dim Fps As Single
Me.cFps.Values.Add(D.Subtract(Me.OldFpsDate).Ticks)
Me.OldFpsDate = D
Me.cFps.Trim()
Fps = 1000 / New TimeSpan(Me.cFps.Average).TotalMilliseconds
Me.cFps.BufferSize = TB.Math.myTrim(Fps * 1, 1, 1000)
If Me.AviStream IsNot Nothing Then
Me.AviStream.AddFrame(Me._ImageInfo.Image.Clone)
End If
End Sub
Public Sub New()
Me.ClassDescription = "Write images into an avi file"
Me.cFps = New clsTbQueue(10)
End Sub
Private Sub InitializeAvi()
Dim W As String
Dim Fps As Single
Dim di As New IO.DirectoryInfo(TB.SystemMain.AppPath & "Avi\")
TB.FileSystem.CreateDirectories(di)
W = IO.Path.Combine(di.FullName, "Record_" & Now.Ticks.ToString("0") & ".avi")
Me.cAvi = New AviReaderWriter.AviFile.AviManager(W, False)
Dim Opts As New AviReaderWriter.AviFile.Avi.AVICOMPRESSOPTIONS
Opts.fccType = 0
Opts.fccHandler = 1684633208
Opts.dwKeyFrameEvery = 0
Opts.dwQuality = 0 '0 ... 10000
Opts.dwFlags = 8 'AVICOMRPESSF_KEYFRAMES = 4
Opts.dwBytesPerSecond = 0
Opts.lpFormat = 0
Opts.lpParms = New IntPtr(0)
Opts.cbParms = 3532
Opts.dwInterleaveEvery = 0
Fps = 1000 / New TimeSpan(Me.cFps.Average).TotalMilliseconds
'Dim bm1 As Bitmap
'bm1 = TB.Imaging.CreateReScaledImage(Me.pic.Image, New Size(Me.pic.Image.Width, Me.pic.Image.Height), False)
Me.AviStream = cAvi.AddVideoStream(Opts, Math.Floor(TB.Math.myTrim(Fps, 1, 50)), Me._ImageInfo.Image.Clone)
End Sub
Public Overrides Property Run() As Boolean
Get
Return Me._Run
End Get
Set(ByVal value As Boolean)
If Me._Run <> value Then
Me._Run = value
If Me._Run = True Then
Call InitializeAvi()
Else
If Me.cAvi IsNot Nothing Then
Me.cAvi.Close()
Me.cAvi = Nothing
Me.AviStream = Nothing
End If
End If
Call Me.OnPropertyChanged(Me.Guid)
End If
End Set
End Property
End Class
For more codes look here: http://www.wischik.com/lu/programmer/avi_utils.html and MSDN or http://www.codeproject.com/KB/audio-video/avigenerator.aspx
I've posted the sourcecode to show how such a sequence can looks like (code above need some more references which are not public available). You can see that you just need to initialize, add frames, store the FPS value and safe it to harddisk.
Also if wanted, you can search for DirectShow to see how all works.
You can use
http://joshsmithonwpf.wordpress.com/2008/04/23/good-old-fashion-image-animations-in-wpf/
as an example. Afterwards you can use a screen capture program like snagit or microsoft expression encoder pro to capture it as a video
Josh Smith's blog pointed by Raj here (http://joshsmithonwpf.wordpress.com/2008/04/23/good-old-fashion-image-animations-in-wpf/) is a good example of showing images from a folder in the WPF app.
Once this is working you can look at Saveen Reddy's blog to convert app to video http://blogs.msdn.com/b/saveenr/archive/2008/09/22/wpf-xaml-saving-an-animation-as-an-avi-video-file.aspx
Use this library avifilewrapper search for the sample code on how to create an avi from bitmaps. This article explains how you can render your visuals to bitmaps. I don't think it will get any easier than that.
Since WPF does not include video encoding libraries, you'll need to lean on an external one to do the encoding. This blog post describes how you can use Windows Media Encoder to do so. Alternatively, you could bundle something like mencoder with your app and start it as an external process that you control and monitor from your app.
精彩评论