11

是否有任何简单的方法可以将 ImageSources 添加到堆栈并从中创建视频?

4

5 回答 5

8

我已经上过这样的课了。我只需要提交我的“ImageInfo”,它是一个 system.DrawingBitmap。这可以通过使用以下代码轻松创建:

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

然后我做了一个 AviClass 向它添加帧并将其存储为具有预选编解码器的 AVI 文件(例如 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

有关更多代码,请查看此处: http: //www.wischik.com/lu/programmer/avi_utils.htmlMSDNhttp://www.codeproject.com/KB/audio-video/avigenerator.aspx

我已经发布了源代码来展示这样一个序列的外观(上面的代码需要更多不公开的引用)。您可以看到您只需要初始化、添加帧、存储 FPS 值并将其安全到硬盘。

此外,如果需要,您可以搜索 DirectShow 以查看所有工作原理。 DirectShow 引脚

于 2011-06-10T11:35:50.740 回答
1

您可以使用

http://joshsmithonwpf.wordpress.com/2008/04/23/good-old-fashion-image-animations-in-wpf/

举个例子。之后,您可以使用 snagit 或 microsoft expression encoder pro 之类的屏幕捕获程序将其捕获为视频

于 2011-05-31T22:02:07.233 回答
1

使用这个库avifilewrapper搜索有关如何从位图创建 avi 的示例代码。本文介绍了如何将视觉效果呈现为位图。我不认为它会比这更容易。

于 2011-06-09T16:29:46.300 回答
1

由于 WPF 不包含视频编码库,因此您需要依靠外部库来进行编码。此博客文章介绍了如何使用 Windows Media Encoder 来执行此操作。或者,您可以将诸如 mencoder 之类的东西与您的应用程序捆绑在一起,并将其作为您从应用程序控制和监视的外部进程启动。

于 2011-06-10T10:22:26.717 回答
1

Raj 指出的 Josh Smith 的博客 ( http://joshsmithonwpf.wordpress.com/2008/04/23/good-old-fashion-image-animations-in-wpf/ ) 是显示文件夹中图像的一个很好的例子WPF 应用程序。

一旦这个工作正常,您可以查看 Saveen Reddy 的博客,将应用程序转换为视频 http://blogs.msdn.com/b/saveenr/archive/2008/09/22/wpf-xaml-saving-an-animation-as-一个-avi-video-file.aspx

于 2011-06-09T05:08:15.077 回答