AVI2BMP - avi videostream to single bitmap frames

Share your advanced PureBasic knowledge/code with the community.
dige
Addict
Addict
Posts: 1391
Joined: Wed Apr 30, 2003 8:15 am
Location: Germany
Contact:

AVI2BMP - avi videostream to single bitmap frames

Post 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 )
vanleth
User
User
Posts: 79
Joined: Sat Jun 28, 2003 4:39 am
Location: Denmark - Valby

Post by vanleth »

Perfect!

Just what I needed, thx Dige
LCD
Enthusiast
Enthusiast
Posts: 206
Joined: Sun Jun 01, 2003 10:55 pm
Location: Austria, Vienna
Contact:

Post 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.
My PC
Ryzen 9 5950, 64 GB RAM, nVidia RTX A4000, Win 10
Ryzen 7 1700, 32 GB RAM, nVidia RTX A2000, Win 10
dige
Addict
Addict
Posts: 1391
Joined: Wed Apr 30, 2003 8:15 am
Location: Germany
Contact:

Post 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
THCM
Enthusiast
Enthusiast
Posts: 276
Joined: Fri Apr 25, 2003 5:06 pm
Location: Gummersbach - Germany
Contact:

Post by THCM »

Nice Code! Dige do You have an idea how to do BMP2AVI using Purebasic?
The Human Code Machine / Masters' Design Group
dige
Addict
Addict
Posts: 1391
Joined: Wed Apr 30, 2003 8:15 am
Location: Germany
Contact:

Post by dige »

Yes ;-)

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

cya dige
THCM
Enthusiast
Enthusiast
Posts: 276
Joined: Fri Apr 25, 2003 5:06 pm
Location: Gummersbach - Germany
Contact:

Post by THCM »

That's good news! I'll keep my eyes open and my fingers crossed!
The Human Code Machine / Masters' Design Group
Blade
Enthusiast
Enthusiast
Posts: 362
Joined: Wed Aug 06, 2003 2:49 pm
Location: Venice - Italy, Japan when possible.
Contact:

Post by Blade »

Sounds great! :)
Pantcho!!
Enthusiast
Enthusiast
Posts: 538
Joined: Tue Feb 24, 2004 3:43 am
Location: Israel
Contact:

Post by Pantcho!! »

:lol: Sweeeeeeeeeet! looking forward for that lib.
naw
Enthusiast
Enthusiast
Posts: 573
Joined: Fri Apr 25, 2003 4:57 pm

Post by naw »

Please post your Lib in the Announcements Forum, will be really useful.
Ta - N
inc.
Enthusiast
Enthusiast
Posts: 406
Joined: Thu May 06, 2004 4:28 pm
Location: Cologne/GER

Post 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!
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Post by blueznl »

a lib... think you could release source as well?
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
inc.
Enthusiast
Enthusiast
Posts: 406
Joined: Thu May 06, 2004 4:28 pm
Location: Cologne/GER

Post 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.
inc.
Enthusiast
Enthusiast
Posts: 406
Joined: Thu May 06, 2004 4:28 pm
Location: Cologne/GER

Post 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
THCM
Enthusiast
Enthusiast
Posts: 276
Joined: Fri Apr 25, 2003 5:06 pm
Location: Gummersbach - Germany
Contact:

Post by THCM »

@dige Hi! Do you have any news about your lib?
The Human Code Machine / Masters' Design Group
Post Reply