2011-05-31 18 views
11

¿Hay alguna manera fácil de agregar ImageSources a una pila y crear un video a partir de ella?Crear video desde ImageSource

+0

Si pudiera votar esto un par de veces más, lo haría. Esto es algo que me encantaría poder hacer también. – Tim

Respuesta

1

El blog de Josh Smith señalado por Raj aquí (http://joshsmithonwpf.wordpress.com/2008/04/23/good-old-fashion-image-animations-in-wpf/) es un buen ejemplo de mostrar imágenes de una carpeta en la aplicación WPF.

Una vez que esto está trabajando se puede ver en el blog de Saveen Reddy aplicación para convertir a video http://blogs.msdn.com/b/saveenr/archive/2008/09/22/wpf-xaml-saving-an-animation-as-an-avi-video-file.aspx

+0

Sí, eso no es un problema, entiendo su enfoque. Pero debe haber una API o algo para crear un AVI sin comprimir, etc. de las imágenes. Gracias. – Anders

1

utilizar esta biblioteca avifilewrapper búsqueda del código de ejemplo sobre cómo crear un avi de mapas de bits. Esta article explica cómo puede renderizar sus imágenes en mapas de bits. No creo que sea más fácil que eso.

1

Dado que WPF no incluye bibliotecas de codificación de video, necesitará apoyarse en una externa para hacer la codificación. This blog post describe cómo puede usar Windows Media Encoder para hacerlo. Alternativamente, podría agrupar algo como mencoder con su aplicación e iniciarlo como un proceso externo que usted controla y supervisa desde su aplicación.

8

Ya hice tal clase. Solo tengo que enviar mi "ImageInfo" que es un system.DrawingBitmap. Esto puede ser creado fácilmente utilizando el siguiente código:

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 

Entonces hice un AviClass añadir marcos a él y almacenarlo como un archivo AVI con preseleccionado Codec (por ejemplo, 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 

para más códigos vistazo aquí: http://www.wischik.com/lu/programmer/avi_utils.html y MSDN o http://www.codeproject.com/KB/audio-video/avigenerator.aspx

he publicado el código fuente para mostrar cómo una secuencia de este tipo puede parece (el código de necesitar algunos más referencias que no son públicos disponibles). Puede ver que solo necesita inicializar, agregar marcos, almacenar el valor de FPS y protegerlo en el disco duro.

También si lo desea, puede buscar DirectShow para ver cómo funciona todo. DirectShow Pins

Cuestiones relacionadas