Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create Video from ImageSource

Is there any easy way of adding ImageSources to a stack and create a video from it?

like image 317
Anders Avatar asked May 31 '11 21:05

Anders


2 Answers

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. DirectShow Pins

like image 160
goldengel Avatar answered Oct 07 '22 06:10

goldengel


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

like image 43
parapura rajkumar Avatar answered Oct 07 '22 06:10

parapura rajkumar