Page 1 of 2

AVI2BMP - avi videostream to single bitmap frames

Posted: Thu Sep 25, 2003 8:08 am
by dige
Code updated For 5.20+

Code: Select all

; Converts a avi videostream file into single bitmap images
; dige 09/2003
#streamtypeVIDEO = $73646976
#AVIGETFRAMEF_BESTDISPLAYFMT = 1
#AVI_ERR_OK = 0
#Lib = 0

Procedure AVI2BMP ( avifile.s, bmpfile.s )
  *ptr.BITMAPINFOHEADER
  bfh.BITMAPFILEHEADER
  
  bmpdir.s = GetPathPart( bmpfile )
  bmpfile  = GetFilePart( bmpfile )
  
  res = CallFunction( #Lib, "AVIFileOpen", @pAVIFile, @avifile.s, #OF_SHARE_DENY_WRITE, 0 )
  
  If res = #AVI_ERR_OK
    
    res = CallFunction( #Lib, "AVIFileGetStream", pAVIFile, @pAVIStream, #streamtypeVIDEO, 0 )
    If res = #AVI_ERR_OK
      
      firstFrame = CallFunction( #Lib, "AVIStreamStart", pAVIStream )
      numFrames  = CallFunction( #Lib, "AVIStreamLength", pAVIStream )
      
      pGetFrameObj = CallFunction( #Lib, "AVIStreamGetFrameOpen", pAVIStream, #AVIGETFRAMEF_BESTDISPLAYFMT )
      
      For a = firstFrame To ( numFrames - 1 ) - firstFrame
        *ptr = CallFunction( #Lib, "AVIStreamGetFrame", pGetFrameObj, a )
        If *ptr And OpenFile ( 0, bmpdir + Right("000" + Str(a), 4 ) + "_" + bmpfile )
          
          bfh\bfType = $4d42
          bfh\bfSize = SizeOf(BITMAPFILEHEADER) + *ptr\biSize + *ptr\biSizeImage
          bfh\bfReserved1 = 0
          bfh\bfReserved2 = 0
          bfh\bfOffBits = SizeOf(BITMAPFILEHEADER) + *ptr\biSize
          
          WriteData(0,@bfh, SizeOf(BITMAPFILEHEADER) )
          WriteData( 0,*ptr, SizeOf(BITMAPINFOHEADER) )
          WriteData(0, *ptr+SizeOf(BITMAPINFOHEADER), *ptr\biSizeImage)
          
          CloseFile (0)
        EndIf
      Next
      CallFunction( #Lib, "AVIStreamGetFrameClose", pGetFrameObj )
    EndIf
    CallFunction( #Lib, "AVIFileRelease", pAVIFile )
  EndIf
  MessageRequester( "AVI2BMP", Str(numFrames) + " Frames extracted",  0 )
EndProcedure

OpenLibrary  ( #Lib , "AVIFIL32.DLL")
CallFunction ( #Lib,  "AVIFileInit" )
avifile.s = OpenFileRequester ( "Select AVI File", "", "Video|*.avi", 0 )
bmpfile.s = SaveFileRequester ( "BMP Savepath", GetPathPart( avifile.s )+"Avi2bmp.bmp", "Bild|*bmp", 0  )

If avifile And bmpfile : AVI2BMP( avifile, bmpfile ) : EndIf

CallFunction( #Lib, "AVIFileExit" )
CloseLibrary( #Lib )

Posted: Thu Sep 25, 2003 7:53 pm
by vanleth
Perfect!

Just what I needed, thx Dige

Posted: Thu Sep 25, 2003 11:05 pm
by LCD
Great, thank you very much. Btw. Is there a internal function to re-scale the video in memory? No resize Image or Resize Gadged., I want to read out the rescaled video with pointers.

Posted: Tue May 10, 2005 8:53 am
by dige
that is a small extension of the code above, if you wanna get the
avi frame as PB-image ( requested by Xombie @ irc ):

Replace this part:

Code: Select all

*ptr = CallFunction( #Lib, "AVIStreamGetFrame", pGetFrameObj, a )
        If *ptr And OpenFile ( 0, bmpdir + Right("000" + Str(a), 4 ) + "_" + bmpfile )
       
          bfh\bfType = $4d42
          bfh\bfSize = SizeOf(BITMAPFILEHEADER) + *ptr\biSize + *ptr\biSizeImage
          bfh\bfReserved1 = 0
          bfh\bfReserved2 = 0
          bfh\bfOffBits = SizeOf(BITMAPFILEHEADER) + *ptr\biSize
       
          WriteData( @bfh, SizeOf(BITMAPFILEHEADER) )
          WriteData( *ptr, SizeOf(BITMAPINFOHEADER) )
          WriteData( *ptr+SizeOf(BITMAPINFOHEADER), *ptr\biSizeImage)
       
          CloseFile (0)
        EndIf
with this part:

Code: Select all

; by DiGe English Forum 10.05.2005
*bih.BITMAPINFOHEADER = CallFunction( AviDll, "AVIStreamGetFrame", pGetFrameObj, a )
If *bih
  ImgID = CreateImage ( #PB_Any,  *bih\biWidth, *bih\biHeight )
  hBmp  = UseImage( ImgID )
  hdc   = GetDC_(#Null)
  hCDC  = CreateCompatibleDC_(hdc)
  If hCDC
    SelectObject_( hCDC, hBmp )
    SetDIBits_( hCDC, hBmp, 0, *bih\biHeight, *bih + SizeOf(BITMAPINFOHEADER), *bih, #DIB_RGB_COLORS) 
    DeleteDC_(hCDC)
  EndIf
  ReleaseDC_(#Null, hdc)
EndIf

; ... some image processing ...

FreeImage( ImgID )
... have fun

bye dige

Posted: Tue May 10, 2005 1:11 pm
by THCM
Nice Code! Dige do You have an idea how to do BMP2AVI using Purebasic?

Posted: Tue May 10, 2005 1:58 pm
by dige
Yes ;-)

.... next week I'll release a Lib for Purebasic to Read and Create
AVI Files ... please be patient.

cya dige

Posted: Tue May 10, 2005 2:26 pm
by THCM
That's good news! I'll keep my eyes open and my fingers crossed!

Posted: Tue May 10, 2005 6:32 pm
by Blade
Sounds great! :)

Posted: Wed May 11, 2005 10:57 am
by Pantcho!!
:lol: Sweeeeeeeeeet! looking forward for that lib.

Posted: Wed May 11, 2005 3:19 pm
by naw
Please post your Lib in the Announcements Forum, will be really useful.

Posted: Sat Jun 11, 2005 11:53 am
by inc.
First of all, Im a noob in PB.
How can I display these via AVIStreamGetFrame extracted frames to a PB Image on a specific frame in a window?

BTW I got an error thrown out by the debugger: "#image object not initialized"

Thanks!

Posted: Sat Jun 11, 2005 1:07 pm
by blueznl
a lib... think you could release source as well?

Posted: Sat Jun 11, 2005 1:11 pm
by inc.
I got it almost working by modding the procedure above like this:

Code: Select all

Procedure AVI2BMP ( avifile.s, bmpfile.s )
  *ptr.BITMAPINFOHEADER
  bfh.BITMAPFILEHEADER
 
  bmpdir.s = GetPathPart( bmpfile )
  bmpfile  = GetFilePart( bmpfile )
 
  res = CallFunction( #Lib, "AVIFileOpen", @pAVIFile, @avifile.s, #OF_SHARE_DENY_WRITE, 0 )
 
  If res = #AVI_ERR_OK

    res = CallFunction( #Lib, "AVIFileGetStream", pAVIFile, @pAVIStream, #streamtypeVIDEO, 0 )
    If res = #AVI_ERR_OK

      firstFrame = CallFunction( #Lib, "AVIStreamStart", pAVIStream )
      numFrames  = CallFunction( #Lib, "AVIStreamLength", pAVIStream )

      pGetFrameObj = CallFunction( #Lib, "AVIStreamGetFrameOpen", pAVIStream, #AVIGETFRAMEF_BESTDISPLAYFMT )

ImgID = CreateImage ( #PB_Any, 704, 576 )
hBmp  = UseImage(ImgID)
  
      For a = firstFrame To ( numFrames - 1 ) - firstFrame
        *bih.BITMAPINFOHEADER = CallFunction( AviDll, "AVIStreamGetFrame", pGetFrameObj, a )
Delay(29)
If *bih
  ImgID = CreateImage ( #PB_Any, *bih\biWidth, *bih\biHeight )
  hBmp  = UseImage(ImgID)
  hdc   = GetDC_(#Null)
  hCDC  = CreateCompatibleDC_(hdc)
  If hCDC
    SelectObject_( hCDC, hBmp )
    SetDIBits_( hCDC, hBmp, 0, *bih\biHeight, *bih + SizeOf(BITMAPINFOHEADER), *bih, #DIB_RGB_COLORS)
    DeleteDC_(hCDC)
  EndIf
  ReleaseDC_(#Null, hdc)
  ImageGadget(#Image_0, 230, 40, 704, 576, hBmp, #PB_Image_Border) 
EndIf 
      Next
      CallFunction( #Lib, "AVIStreamGetFrameClose", pGetFrameObj )
    EndIf
    CallFunction( #Lib, "AVIFileRelease", pAVIFile )
  EndIf
  MessageRequester( "AVI2BMP", Str(numFrames) + " Frames extracted",  0 )
EndProcedure
I use a regular window where the generated Imagegadget(#Image_0) out of the procedure above displays the Avi Contend.
BUT: There's something like a flickering white horizontal bar moving from the bottom to the top. I think its cause the display rate doesnt match the internal AVI Framerate.

How can I make that procedure that it displays the "running" Frames in the Imagegadget in a proper way? I tried applying the Delay, but it just affects the speed of that moving bar.

Intention of this: Making a Mediaplayer using the avifil32.dll.

As everytime: Thanks a lot
Inc.

Posted: Sat Jun 11, 2005 1:52 pm
by inc.
It works ....

In the procedure I did let everytime re-generate The whole Imagegadget.

Changing the line

Code: Select all

ImageGadget(#Image_0, 230, 40, 704, 576, hBmp, #PB_Image_Border)
to

Code: Select all

SetGadgetState(#Image_0, hBmp)
and creating an Imagegadget in the Gadgetlist at the beginning works perfect.

thanks anyway

Posted: Fri Jun 24, 2005 4:51 pm
by THCM
@dige Hi! Do you have any news about your lib?