Possibility to read the AVI file frame by frame is an essential feature of AVI Processor Add-on for Graphics Mill. Using this feature you can display the video file on the screen, save each frame to separate files, or create new videos based on these frames. This section describes how to do it.
The main class you should use to read AVI files with AVI Processor Add-on is Aurigma.GraphicsMill.Codecs.AviReader. Further, this class will be referred as AVI reader or merely - reader. This class is a collection of AviFrame objects which represent a single video frame.
Through the reader you can access to an audio manager represented by the Aurigma.GraphicsMill.Codecs.AviAudioManager class. It is used to work with audio tracks (audio streams) of the video movie. You can read about audio managers in the Working with Audio Track topic.
To start reading data from the AVI file, you need to open it in the reader. You can do it with the Open method. Alternatively, you can simply pass the file name to the constructor of the AVI reader.
When the file is opened by the reader, no data actually is loaded into memory. The Open method initializes internal memory structures, and loads video data only on demand. However it locks the file, so another application can neither delete nor modify it.
After you opened the reader, you can retrieve video data. As stated above, the reader object
can be interpreted as a collection of frames. You can use it with a foreach
statement:
' Getting frames in For Each statement Dim frame As Aurigma.GraphicsMill.Codecs.IFrame For Each frame In reader ' ... frame processing code is omitted for brevity Console.WriteLine("Frame #{0} is processed.", frame.Index) Next
// Getting frames in foreach statement foreach (Aurigma.GraphicsMill.Codecs.AviFrame frame in reader) { // ... frame processing code is omitted for brevity Console.WriteLine("Frame #{0} is processed.", frame.Index); }
Alternatively you can get individual frame by its index using the LoadFrame(Int32) method. To get the total
number of frames in the reader, use the FrameCount property. This way you
can iterate through frames using the for
statement:
' Getting frames in For statement by index Dim I As Integer Dim frame As Aurigma.GraphicsMill.Codecs.IFrame For I = 0 To reader.FrameCount frame = reader.LoadFrame(I) ' ... frame processing code is omitted for brevity Console.WriteLine("Frame #{0} is processed.", frame.Index) Next
// Getting frames in for statement by index Aurigma.GraphicsMill.Codecs.IFrame frame; for (int i=0;i<reader.FrameCount;i++) { frame = reader.LoadFrame(i); // ... frame processing code is omitted for brevity Console.WriteLine("Frame #{0} is processed.", frame.Index); }
It is not always convenient to work with frame indices (i.e. exact frame number). Usually it is more preferable to operate with the timing information. E.g. instead of "give me the frame number 1575", you may prefer "give me the frame on the 01:03 (min:sec) position" . In this case you can use the TimeToFrameIndex(Int32) method which converts the timing to the exact frame number. There is also a contrary version of this function, called FrameIndexToTime(Int32) which works vice versa - frame index is converted to the timing value.
All timing values in Graphics Mill for .NET (and in particular in AVI Processor Add-on) are measured in 1/100 of seconds.
As soon as you get the frame object from the reader, you can extract the bitmap stored in this frame. To do it, use the GetBitmap(Bitmap) method of the frame object. It will return an instance of Aurigma.GraphicsMill.Bitmap class. You can use all means of Graphics Mill for .NET to operate with this bitmap. See the code example below:
Public Shared Sub ConvertAviToGifFiles(ByVal inputAviFilename As String, _ ByVal outputPath As String) Dim reader As New Aurigma.GraphicsMill.Codecs.AviReader reader.Open(inputAviFilename) ' Note, you should create new empty instance ' of the bitmap (rather than use uninitialized ' variable). Dim bitmap As New Aurigma.GraphicsMill.Bitmap Dim frame As Aurigma.GraphicsMill.Codecs.IFrame For Each frame In reader ' Load the current frame image. frame.GetBitmap(bitmap) ' Process the bitmap. In our case we will reduce number of ' colors before saving the image to GIF. It will wash out ' most colors, however makes the size or result files extremely ' small. bitmap.ColorManagement.ConvertToIndexed(4, _ Aurigma.GraphicsMill.ColorPaletteType.Adaptive, Nothing) ' Save the bitmap to GIF file. The make of the file will contain ' the frame number. bitmap.Save(outputPath & "\frame_" & frame.Index & ".gif") Next bitmap.Dispose() reader.Close() End Sub
public static void ConvertAviToGifFiles(string inputAviFilename, string outputPath) { Aurigma.GraphicsMill.Codecs.AviReader reader; reader = new Aurigma.GraphicsMill.Codecs.AviReader(inputAviFilename); // Note, you should create new empty instance // of the bitmap (rather than use uninitialized // variable). Aurigma.GraphicsMill.Bitmap bitmap = new Aurigma.GraphicsMill.Bitmap(); foreach (Aurigma.GraphicsMill.Codecs.IFrame frame in reader) { // Load the current frame image. frame.GetBitmap(bitmap); // Process the bitmap. In our case we will reduce number of // colors before saving the image to GIF. It will wash out // most colors, however makes the size or result files extremely // small. bitmap.ColorManagement.ConvertToIndexed(4, Aurigma.GraphicsMill.ColorPaletteType.Adaptive, null); // Save the bitmap to GIF file. The make of the file will contain // the frame number. bitmap.Save(outputPath + @"\frame_" + frame.Index + ".gif"); } // Cleanup. bitmap.Dispose(); reader.Close(); }
If you need to get a resized version of the image, you can use the GetThumbnail(Bitmap, Int32, Int32) method instead of GetBitmap(Bitmap). It will work noticeable faster comparing to loading the bitmap with GetBitmap(Bitmap) and resizing it with the Resize transform.
AVI reader enables you to get not only video data, but additional infromation about video like duration, compression type, width, height, etc. The reader object provides a number of properties which can be used to extract this information. See the code example below for more details:
Public Shared Sub GetVideoInfo(ByVal inputAviFilename As String) Dim reader As Aurigma.GraphicsMill.Codecs.AviReader reader = New Aurigma.GraphicsMill.Codecs.AviReader(inputAviFilename) System.Windows.Forms.MessageBox.Show(String.Format( _ "Dimensions: {0}x{1}" & vbNewLine & _ "Duration: {2} [hh:mm:ss]" & _ vbNewLine & "FPS: {3}", _ reader.Width, _ reader.Height, _ TimeSpan.FromSeconds(CInt(reader.Duration / 100)), _ reader.FramesPerSecond)) reader.Close() End Sub
public static void GetVideoInfo(string inputAviFilename) { Aurigma.GraphicsMill.Codecs.AviReader reader; reader = new Aurigma.GraphicsMill.Codecs.AviReader(inputAviFilename); System.Windows.Forms.MessageBox.Show( String.Format("Dimensions: {0}x{1}\nDuration: {2} [hh:mm:ss]\nFPS: {3}", reader.Width, reader.Height, TimeSpan.FromSeconds(reader.Duration / 100), reader.FramesPerSecond)); reader.Close(); }