Atlanta Custom Software Development 

 
   Search        Code/Page
 

User Login
Email

Password

 

Forgot the Password?
Services
» Web Development
» Maintenance
» Data Integration/BI
» Information Management
Programming
  Database
Automation
OS/Networking
Graphics
Links
Tools
» Regular Expr Tester
» Free Tools


In my previous 2 articles Part-1 (Opening and Closing AVI file) and Part-2 (Working with AVI Streams) you learned that how to open and close AVI file and Stream we also learned how to get basic information of AVI file and Streams. In this article we will have real fun with AVI and GDI APIs. This step by step tutorial will teach you how to grab frames from AVI and save as BMP file. Saving frame as BMP file requires basic understanding of BMP file format. If you are not familier with BMP file format then please check my article Working with Bitmap and DIB.

To make resusable piece of code I have wrapped my logic and declares in a class called clsAviFrames This class has the following public members.

Properties
  • Filename   : Full path of loaded AVI file, by setting this property class will initialize avi file.
  • FrameCount  : Number of frames in loaded AVI file
  • FrameDuration : Dration of each frame in miliseconds
  • BitsPerPixel : Color-depth of frame (Bits/Pixel)
  • Width     : Actual width of frame
  • Height    : Actual Height of frame
  • Name     : Name of loaded AVI file this might be some description.
  • Compression  : Compression type
  • StreamHandler : Preferred data handler for the stream.
  • StreamType  : Type of the data contained in the stream (i.e. Audio, Video, Text or MIDI)

Sub/Function
  • DrawFrame : Draw a specified frame to a specified DC.
  • SaveFrameBMP : Save a specified frame as BMP file


Lets start step by step implementation on our clsAviFrames class.

Lets start with declaration.

Click here to copy the following block
Option Explicit

Private m_sFileName As String
Private m_pAS As Long
Private m_pGF As Long
Private m_hDrawDib As Long
Private m_lFrames As Long
Private m_lFrameDuration As Long
Private m_tBMIH As BITMAPINFOHEADER
Private m_tBMIHBlank As BITMAPINFOHEADER
Private m_tBMI256 As BITMAPINFO256
Private m_tAVI As AVI_STREAM_INFO

Private Const ERR_BASE As Long = vbObjectError + 1024 + 77561
Private Const STREAM_TYPE_VIDEO = &H73646976  ' reads "vids"

'//////////////////////////////////////
'Constants for DIB color table identifiers
'//////////////////////////////////////
Const DIB_RGB_COLORS As Long = 0  '/* color table in RGBs */
Const DIB_PAL_COLORS As Long = 1  '/* color table in palette indices */

'//////////////////////////////////////
'Constants for the biCompression field
'//////////////////////////////////////
Const BI_RGB     As Long = 0
Const BI_RLE8     As Long = 1

'//////////////////////////////////////
'Constants for file access mode
'//////////////////////////////////////
Const OF_CREATE = &H1000
Const OF_EXIST = &H4000
Const OF_READ = &H0
Const OF_READWRITE = &H2
Const OF_SHARE_DENY_READ = &H30
Const OF_SHARE_DENY_WRITE = &H20
Const OF_SHARE_EXCLUSIVE = &H10
Const OF_VERIFY = &H400
Const OF_WRITE = &H1

'///////////////////////////////////
'//Structures to work with Bitmap
'///////////////////////////////////
Private Type RGBQUAD
  rgbBlue As Byte
  rgbGreen As Byte
  rgbRed As Byte
  rgbReserved As Byte
End Type

Private Type BITMAPFILEHEADER '14 bytes
  bfType As Integer  '"magic cookie" - must be "BM" (19778)
  bfSize As Long
  bfReserved1 As Integer
  bfReserved2 As Integer
  bfOffBits As Long
End Type

Private Type BITMAPINFOHEADER '40 bytes
  biSize As Long
  biWidth As Long
  biHeight As Long
  biPlanes As Integer
  biBitCount As Integer
  biCompression As Long
  biSizeImage As Long
  biXPelsPerMeter As Long
  biYPelsPerMeter As Long
  biClrUsed As Long
  biClrImportant As Long
End Type

Private Type BITMAP ' 24 bytes
  bmType As Long
  bmWidth As Long
  bmHeight As Long
  bmWidthBytes As Long
  bmPlanes As Integer
  bmBitsPixel As Integer
  bmBits As Long
End Type

Private Type BITMAPINFO256
  bmiHeader As BITMAPINFOHEADER
  bmiColors(0 To 255) As RGBQUAD
End Type

'///////////////////////////////////
'//Structures to work with AVI
'///////////////////////////////////
Private Type AVI_RECT
  left As Long
  top As Long
  right As Long
  bottom As Long
End Type

Private Type AVI_STREAM_INFO
  fccType As Long
  fccHandler As Long
  dwFlags As Long
  dwCaps As Long
  wPriority As Integer
  wLanguage As Integer
  dwScale As Long
  dwRate As Long
  dwStart As Long
  dwLength As Long
  dwInitialFrames As Long
  dwSuggestedBufferSize As Long
  dwQuality As Long
  dwSampleSize As Long
  rcFrame As AVI_RECT
  dwEditCount As Long
  dwFormatChangeCount As Long
  szName As String * 64
End Type

'////////////////////////////////////////////
'//APIs for Drawing DIB
'////////////////////////////////////////////
Private Declare Function DrawDibOpen Lib "MSVFW32.dll" () As Long

Private Declare Function DrawDibClose Lib "MSVFW32.dll" (ByVal hDD As Long) As Long

Private Declare Function DrawDibDraw Lib "MSVFW32.dll" ( _
    ByVal hDD As Long, ByVal hdc As Long, _
    ByVal xDst As Long, ByVal yDst As Long, _
    ByVal dxDst As Long, ByVal dyDst As Long, _
    lpbi As Any, lpBits As Any, _
    ByVal xSrc As Long, ByVal ySrc As Long, _
    ByVal dxSrc As Long, ByVal dySrc As Long, _
    ByVal wFlags As Long) As Long

'////////////////////////////////////////////
'//APIs for Drawing AVI
'////////////////////////////////////////////
Private Declare Function AVIStreamReadFormat Lib "avifil32.dll" ( _
    pavi As Any, _
    ByVal lPos As Long, _
    lpFormat As Any, _
    ByRef lpcbFormat As Long) As Long

Private Declare Function AVIStreamGetFrameOpen Lib "avifil32.dll" ( _
    ByVal pAVIStream As Long, _
    ByRef bih As Any) As Long

Private Declare Function AVIStreamGetFrame Lib "avifil32.dll" ( _
    ByVal pGetFrameObj As Long, _
    ByVal lPos As Long) As Long

Private Declare Function AVIStreamGetFrameClose Lib "avifil32.dll" ( _
    ByVal pGetFrameObj As Long) As Long

Private Declare Sub AVIFileInit Lib "avifil32.dll" ()

Private Declare Function AVIStreamInfo Lib "avifil32.dll" ( _
    ByVal pAVIStream As Long, _
    ByRef psi As Any, _
    ByVal lSize As Long) As Long

Private Declare Function AVIStreamStart Lib "avifil32.dll" ( _
    ByVal pavi As Long) As Long

Private Declare Function AVIStreamOpenFromFile Lib "avifil32.dll" Alias "AVIStreamOpenFromFileA" ( _
    ppavi As Any, ByVal szFile As String, _
    ByVal fccType As Long, ByVal lParam As Long, _
    ByVal mode As Long, pclsidHandler As Any _
    ) As Long

Private Declare Function AVIStreamSampleToTime Lib "avifil32.dll" ( _
    pavi As Any, _
    ByVal lSample As Long) As Long

Private Declare Function AVIStreamLength Lib "avifil32.dll" ( _
    ByVal pavi As Long) As Long

Private Declare Function ICInfo Lib "MSVFW32.dll" ( _
    ByVal fccType As Long, _
    ByVal fccHandler As Long, _
    lpicinfo As Any _
    ) As Long

Private Declare Function AVIStreamRelease Lib "avifil32.dll" ( _
    ByVal pavi As Long) As Long

Private Declare Sub AVIFileExit Lib "avifil32.dll" ()

'////////////////////////////////////////////
'//APIs for Bitmap and Memory DC
'////////////////////////////////////////////
Private Declare Function GetDIBits Lib "GDI32.dll" (ByVal aHDC As Long, _
    ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, _
    ByRef lpBits As Any, ByRef lpbi As Any, ByVal wUsage As Long) As Long

Private Declare Function GetObject Lib "GDI32.dll" Alias "GetObjectA" ( _
    ByVal hObject As Long, ByVal nCount As Long, ByRef lpObject As Any) As Long

Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long

Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long

Private Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long

Private Declare Function SelectObject Lib "gdi32" ( _
    ByVal hdc As Long, ByVal hObject As Long) As Long

Private Declare Function BitBlt Lib "gdi32" ( _
    ByVal hDestDC As Long, ByVal x As Long, ByVal y As Long, _
    ByVal nWidth As Long, ByVal nHeight As Long, _
    ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, _
    ByVal dwRop As Long) As Long

Private Declare Function CreateCompatibleBitmap Lib "gdi32" ( _
    ByVal hdc As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long

Private Declare Function GetDIBits256 Lib "gdi32" Alias "GetDIBits" ( _
    ByVal aHDC As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, _
    ByVal nNumScans As Long, lpBits As Any, _
    lpbi As Any, ByVal wUsage As Long) As Long

Private Declare Function CreateDCAsNull Lib "gdi32" Alias "CreateDCA" ( _
    ByVal lpDriverName As String, lpDeviceName As Any, _
    lpOutput As Any, lpInitData As Any) As Long

Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" ( _
    ByRef dest As Any, _
    ByRef src As Any, _
    ByVal dwLen As Long)

We will put some initialization code in Class_Initialize event

Click here to copy the following block
Private Sub Class_Initialize()
  LSet m_tBMIHBlank = m_tBMIH
  AVIFileInit
  m_hDrawDib = DrawDibOpen()
End Sub

AVIFileInit must be called before any other AVI API calls. DrawDibOpen must be called before you use any DrawDib API.

Now some cleanup code. Its very important that you free GDI and other resources when object is unloaded.

Click here to copy the following block
Private Sub Class_Terminate()
  UnloadFrames
  AVIFileExit
  DrawDibClose m_hDrawDib
End Sub

Private Sub UnloadFrames()
  Dim bS As Boolean

  ' close frame interface
  If (m_pGF) Then
    bS = (AVIStreamGetFrameClose(ByVal m_pGF) = 0)
    m_pGF = 0
  End If

  ' release avi stream
  If Not (m_pAS = 0) Then
    AVIStreamRelease ByVal m_pAS
    m_pAS = 0
  End If

  m_lFrames = 0
  m_lFrameDuration = 0

  ' reset bitmap info details:
  LSet m_tBMIH = m_tBMIHBlank
End Sub

Lets write some utility functions for our class. One important point which should be noted is the return value from the AVI APIs. AVI APIs return COM HRESULT instead of just success or failure. Folloing image will give you more idead about 2 bytes HRESULT.




An HRESULT is a 32 bit unsigned integer where the high bit indicates whether it is an error or a success. The remaining bits in the high word indicate the "facility" of the error -- into what broad category does this error fall? The low word indicates the specific error for that facility.

HRESULTS are therefore usually talked about in hex, as the bit structure is a lot easier to read in hex! Consider &H80070013, for example. The high bit is set, so this is an error. The facility code is 7 and the error code is &H0013 = 19 in decimal.

Click here to copy the following block
Private Function FAILED(ByVal hR As Long) As Boolean
  FAILED = Not (SUCCEEDED(hR))
End Function

Private Function SUCCEEDED(ByVal hR As Long) As Boolean
  SUCCEEDED = ((hR And &H80000000) = 0)
End Function

'//Four-Character Codes (FOURCC), a set of codes
'//that are four characters in length, was introduced by Microsoft
'//to clearly identify video data stream formats.
'//http://www.microsoft.com/whdc/archive/fourcc.mspx
Private Function FourCCToString(ByVal lFourCC As Long) As String
  Dim sRet As String
  Dim lUByte As Long
  sRet = Chr(lFourCC And &HFF)
  sRet = sRet & Chr((lFourCC And &HFF00&) \ &H100&)
  sRet = sRet & Chr((lFourCC And &HFF0000) \ &H10000)
  lUByte = (lFourCC And &H7F000000) \ &H1000000
  If (lFourCC And &H80000000) = &H80000000 Then
    lUByte = lUByte Or &H80&
  End If
  sRet = sRet & Chr(lUByte)
  FourCCToString = sRet
End Function

Private Function AVIStreamEndTime() As Long
  Dim lSample As Long
  lSample = AVIStreamStart(ByVal m_pAS) + AVIStreamLength(ByVal m_pAS)
  AVIStreamEndTime = AVIStreamSampleToTime(ByVal m_pAS, lSample)
End Function

Private Function FileExists(ByVal file As String, ByRef lErr As Long) As Boolean
  Dim sTest As String
  On Error Resume Next
  sTest = Dir(file)
  lErr = Err.Number
  FileExists = ((lErr = 0) And Len(sTest) > 0)
  On Error GoTo 0
End Function

Private Sub pErr(ByVal lErr As Long)
  Dim sMsg As String
  Select Case lErr
    Case 1
      sMsg = "File not found"
    Case 2
      sMsg = "Failed to open AVI file"
    Case 3
      sMsg = "Unable to open AVI frames"
    Case 4
      sMsg = "AVI contains no frames"
    Case 5
      sMsg = "Could not read the format of the AVI"
    Case 6
      sMsg = "Unsupported AVI format"
    Case Else
      sMsg = "Unexpected error " & lErr
  End Select
  Err.Raise ERR_BASE + lErr, App.EXEName & ".clsAviExtract", sMsg
End Sub

Now lets understand LoadFramesFromFile function which is called when you set FileName property. This function performs the following steps.
  • Call AVIStreamOpenFromFile to open VIDEO stream from a specified AVI file
  • Call AVIStreamGetFrameOpen to get handle to avi frames
  • Call AVIStreamLength to get number of frames and AVIStreamEndTime for total time of AVI. You can calculate FrameDuration using using totalTime / TotalFrames formula.
  • Call AVIStreamReadFormat to fill BITMAPINFOHEADER which contains all information regarding to frame Bitmap. Now if you observe the code then we have called AVIStreamReadFormat 3 times. First call is passing NULL (i.e. ByVal 0&) in 3rd parameter lpFormat which is pointer to a location indicating the size of the memory block. If lpFormat is NULL then 4th parameter lpcbFormat will be set to the amount of memory needed to return the format. In our case first call to AVIStreamReadFormat will return the size required to store Bitmap format and second call fills the BITMAPINFOHEADER with data. If you know the structuare of Bitmap then Bitmap with Bits/Pixel <= 8 uses color palette which is stored as an array of RGBQUAD type. If BitCount in BITMAPINFOHEADER is less than or equal to 8 bit than again you have to call AVIStreamReadFormat to fill color information in BITMAPINFO256 structure which consists BITMAPINFOHEADER and RGBQUAD both. So now you understand why we need to call AVIStreamReadFormat 3 times. First call to get size required to store format of frame. Second call is to find Bits/pixel of frame and last call to fill RGBQUAD only if Bits/Pixel <= 8 Bits.
  • Call AVIStreamInfo to retrive all information regarding opened stream.

Click here to copy the following block
Private Function LoadFramesFromFile(Filename As String) As Boolean
  Dim hR As Long
  Dim totalTime As Long
  Dim hIC As Long

  hR = AVIStreamOpenFromFile(m_pAS, Filename, STREAM_TYPE_VIDEO, _
      0, OF_READ Or OF_SHARE_EXCLUSIVE, ByVal 0&)
  If FAILED(hR) Then
    m_pAS = 0
    UnloadFrames
    pErr 2
    Exit Function
  End If

  ' open frames
  m_pGF = AVIStreamGetFrameOpen(ByVal m_pAS, ByVal 0&)
  If (m_pGF = 0) Then
    UnloadFrames  '//If error then cleanup
    pErr 3
    Exit Function
  End If

  ' get number of frames
  m_lFrames = AVIStreamLength(ByVal m_pAS)
  If (m_lFrames = 0) Then
    UnloadFrames  '//If error then cleanup
    pErr 4
    Exit Function
  End If

  ' calculate timer delay
  totalTime = AVIStreamEndTime()
  m_lFrameDuration = (totalTime / m_lFrames)

  ' Get the AVI format:
  Dim lSize As Long
  hR = AVIStreamReadFormat(ByVal m_pAS, 0, ByVal 0&, lSize)
  If (FAILED(hR) Or lSize < LenB(m_tBMIH)) Then
    pErr 5
    Exit Function
  End If

  'Debug.Print lSize
  lSize = LenB(m_tBMIH)

  hR = AVIStreamReadFormat(ByVal m_pAS, 0, m_tBMIH, lSize)
  If FAILED(hR) Then
    ' An error here may not actually be an error,
    ' just that we only read part of the buffer
    Debug.Print "Read format error: " & Hex(hR)
  End If
  
  '//Only if biBitCount <= 8 then we need palette info
  If (m_tBMIH.biBitCount <= 8) Then
    '//We need to fill m_tBMI256.bmiColors which contsins color info
    Select Case m_tBMIH.biBitCount
      Case 8
        lSize = LenB(m_tBMI256)
        hR = AVIStreamReadFormat(ByVal m_pAS, 0, m_tBMI256, lSize)
      Case Else
        pErr 6
    End Select
  End If

  ' Read AVI Info:
  AVIStreamInfo ByVal m_pAS, m_tAVI, LenB(m_tAVI)

  Debug.Print "Rate:" & m_tAVI.dwRate
  Debug.Print "Scale:" & m_tAVI.dwScale
  Debug.Print "FrameDuration:" & FrameDuration

  LoadFramesFromFile = True
End Function

Let discuss another important function DrawFrame which we will use to draw a frame on a specified DC (Device Context).

We have used DrawDibDraw API to implement DrawFrame function. You can display a sequence of bitmaps with the same dimensions and formats by using the DrawDibDraw function with the DrawDibBegin function. DrawDibBegin improves the efficiency of DrawDibDraw by preparing the DrawDib DC for drawing.

Very first thing we have done here is call to AVIStreamGetFrame API which returns pointer to packed DIB of a specified frame number. You can pass this pointer to DrawDibDraw API along with all other required arguments.

Click here to copy the following block
Public Sub DrawFrame( _
   ByVal lhDC As Long, _
   ByVal Index As Long, _
   Optional ByVal x As Long = 0, _
   Optional ByVal y As Long = 0, _
   Optional ByVal lWidth As Long = -1, _
   Optional ByVal lHeight As Long = -1, _
   Optional ByVal Transparent As Boolean = False _
  )
  Dim lpbi As Long

  ' Prepare parameters:
  If (lWidth < 0) Then lWidth = Width
  If (lHeight < 0) Then lHeight = Height
  Index = Index - 1

  ' Get the uncompressed frame:
  lpbi = AVIStreamGetFrame(ByVal m_pGF, Index)
  If (lpbi) Then
    ' Draw it directly onto the display:
    DrawDibDraw m_hDrawDib, lhDC, x, y, _
        lWidth, lHeight, ByVal lpbi, ByVal 0&, _
        0, 0, -1, -1, 0
  End If
End Sub

Now the most important function of our class which requires good understanding of GDI Apis and Bitmap structure.

Click here to copy the following block
Public Function SaveFrameBMP(FrameNumber As Long, SaveFileName As String, Optional BPP As Integer = 0) As Boolean
  Dim SaveBits() As Byte
  Dim fNum As Integer
  Dim RetVal As Long
  Dim hNewDc As Long, hNewBm As Long, hOldBm As Long, lhDC As Long

  Dim tBH As BITMAPFILEHEADER  '//Bitmap file header
  Dim tBI As BITMAPINFO256  '//Bitmap info + colortable
  Dim tBM As BITMAP

  '//If not valid selection then just set to frame BPP
  If BPP = 0 And BPP <> 1 And BPP <> 4 And BPP <> 8 And BPP <> 24 Then BPP = BitsPerPixel

  '//create compatible DC
  lhDC = CreateDCAsNull("DISPLAY", ByVal 0&, ByVal 0&, ByVal 0&)
  hNewDc = CreateCompatibleDC(lhDC)
  RetVal = DeleteDC(lhDC)

  '//create compatible bitmap
  lhDC = CreateDCAsNull("DISPLAY", ByVal 0&, ByVal 0&, ByVal 0&)
  hNewBm = CreateCompatibleBitmap(lhDC, Width, Height)
  RetVal = DeleteDC(lhDC)

  '//Select new bitmap in new DC
  hOldBm = SelectObject(hNewDc, hNewBm)

  '//Draw frame into DC
  Call DrawFrame(hNewDc, FrameNumber)

  '//Now restore old bitmap in our new dc
  RetVal = SelectObject(hNewDc, hOldBm)

  ' Set up BITMAPINFO

  '//Set up the header:
  RetVal = GetObject(hNewBm, LenB(tBM), tBM)
  With tBI.bmiHeader
    .biSize = LenB(tBI.bmiHeader)
    .biWidth = tBM.bmWidth
    .biHeight = tBM.bmHeight
    .biPlanes = 1
    .biBitCount = BPP
    If BPP = 8 Then
      '//Note: for 8 bit we need different apporch to find biSizeImage, check next step
      '//RLE compression can be used for 8 bit BMP
      '//on my test of 8-bit BMP BI_RLE was 6.08 KB and BI_RGB was 102 KB so huge size diff
      .biCompression = BI_RLE8  '//BI_RGB
    Else
      .biSizeImage = ImageBufferSize(BPP)
      .biCompression = BI_RGB
    End If
  End With

  '/////////////////////////////////////////
  ' Extract the DIBits
  Dim hDCComp As Long
  hDCComp = CreateDCAsNull("DISPLAY", ByVal 0&, ByVal 0&, ByVal 0&)

  If BPP <= 8 Then
    '// <=8 bit BMP uses palette for color index so we have to setup that
    '//Set up the palette: (m_tBMI256.bmiColors is filled up when we called AVIStreamReadFormat)
    Call CopyMemory(tBI.bmiColors(0), m_tBMI256.bmiColors(0), (2 ^ BPP) * LenB(tBI.bmiColors(0)))

    ' Find out the size of the buffer:
    RetVal = GetDIBits(hDCComp, hNewBm, 0, tBI.bmiHeader.biHeight, ByVal 0&, _
        tBI, DIB_RGB_COLORS)
  End If

  ReDim SaveBits(0 To tBI.bmiHeader.biSizeImage - 1)

  '//Get Actual Bytes of image into byte array
  RetVal = GetDIBits(hDCComp, hNewBm, 0, tBI.bmiHeader.biHeight, SaveBits(0), _
      tBI, DIB_RGB_COLORS)

  RetVal = DeleteDC(hDCComp)

  '/////////////////////////////////////////
  ' Prepare the BITMAPFILEHEADER
  With tBH
    .bfType = &H4D42  ' Filetype is 'BM'
    .bfOffBits = 14 + Len(tBI)
    .bfSize = .bfOffBits + tBI.bmiHeader.biSizeImage
  End With

  RetVal = DeleteObject(hNewBm)
  RetVal = DeleteDC(hNewDc)

  '//save it to disk
  fNum = FreeFile

  Open SaveFileName For Binary As fNum
  Put fNum, , tBH  'Write Fileheader
  Put fNum, , tBI  'Write BMPheader (info + Color table)
  Put fNum, , SaveBits()  'Write Actual Image Bytes
  Close fNum

  SaveFrameBMP = True
End Function

'//Returns number of bytes required for Image data (excluding headers)
Private Function ImageBufferSize(Optional BitsPerPix As Integer = 0) As Long
  If BitsPerPix = 0 Then BitsPerPix = m_tBMI256.bmiHeader.biBitCount
  Dim lScanSize As Long

  Select Case BitsPerPix
    Case 1
      lScanSize = Width / 8
      lScanSize = lScanSize + lScanSize Mod 4
      ImageBufferSize = lScanSize * Height
    Case 4
      lScanSize = Width / 2
      lScanSize = lScanSize + lScanSize Mod 4
      ImageBufferSize = lScanSize * Height
    Case 8
      lScanSize = Width
      lScanSize = lScanSize + lScanSize Mod 4
      ImageBufferSize = lScanSize * Height
      'ImageBufferSize = ((Width + 3) And &HFC) * Height
    Case Else '// > 8 Bit takes 3 bytes to store 1 pixel
      ImageBufferSize = ((Width * 3 + 3) And &HFFFFFFFC) * Height
  End Select
End Function

I have coded few important properties of AVI. Check the Filename property. When you set this property which is path of avi file, LoadFramesFromFile function is called along with Avi file parameter.

Click here to copy the following block
Public Property Get Filename() As String
  Filename = m_sFileName
End Property

Public Property Let Filename(ByVal value As String)
  UnloadFrames
  m_sFileName = value
  Dim lErr As Long
  If (FileExists(value, lErr)) Then
    LoadFramesFromFile m_sFileName
  Else
    pErr 1
  End If
End Property

Public Property Get Name() As String
  Dim sName As String
  Dim iPos As Long
  sName = StrConv(m_tAVI.szName, vbUnicode)
  iPos = InStr(sName, vbNullChar)
  If (iPos > 0) Then
    sName = left(sName, iPos - 1)
  End If
  Name = sName
End Property

Public Property Get Width() As Long
  Width = m_tBMIH.biWidth
End Property

Public Property Get Height() As Long
  Height = m_tBMIH.biHeight
End Property

Public Property Get BitsPerPixel() As Long
  BitsPerPixel = m_tBMIH.biBitCount
End Property

Public Property Get Compression() As Long
  Compression = m_tBMIH.biCompression
End Property

Public Property Get FrameCount() As Long
  FrameCount = m_lFrames
End Property

Public Property Get FrameDuration() As Long
  FrameDuration = m_lFrameDuration
End Property

'//Codec which handles the stream
'//http://www.microsoft.com/whdc/archive/fourcc.mspx
Public Property Get StreamHandler() As String
  StreamHandler = FourCCToString(m_tAVI.fccHandler)
End Property

'//Type of stream
'//http://www.microsoft.com/whdc/archive/fourcc.mspx
Public Property Get StreamType() As String
  StreamType = FourCCToString(m_tAVI.fccType)
End Property

This was all about our class clsAviFrames. I tried to make it as simple as possible. For fully working demo download the attached project file.

Other articles in this series

Working with AVI Files - Part 1 (Opening and Closing AVI file)
Working with AVI Files - Part 2 (Working with AVI streams)
Working with AVI Files - Part 3 (Working With Frames, AVI to BMP)


Submitted By : Nayan Patel  (Member Since : 5/26/2004 12:23:06 PM)

Job Description : He is the moderator of this site and currently working as an independent consultant. He works with VB.net/ASP.net, SQL Server and other MS technologies. He is MCSD.net, MCDBA and MCSE. In his free time he likes to watch funny movies and doing oil painting.
View all (893) submissions by this author  (Birth Date : 7/14/1981 )


Home   |  Comment   |  Contact Us   |  Privacy Policy   |  Terms & Conditions   |  BlogsZappySys

© 2008 BinaryWorld LLC. All rights reserved.