Bitmap eines Frames aus einer MPEG-Datei fischen
Bitmap eines Frames aus einer MPEG-Datei fischen
Hi Leuts,
Für eine Anwendung zur Analyse von MPEG-Dateien, suche ich eine Möglichkeit, einen einzigen, ganz bestimmten Frame rendern zu lassen und als Bitmap in die Anwendung zu bekommen.
Kann mir da einer der Freaks einen Hinweis geben?
Dank im voraus !
Für eine Anwendung zur Analyse von MPEG-Dateien, suche ich eine Möglichkeit, einen einzigen, ganz bestimmten Frame rendern zu lassen und als Bitmap in die Anwendung zu bekommen.
Kann mir da einer der Freaks einen Hinweis geben?
Dank im voraus !
- Falko
- Admin
- Beiträge: 3535
- Registriert: 29.08.2004 11:27
- Computerausstattung: PC: MSI-Z590-GC; 32GB-DDR4, ICore9; 2TB M2 + 2x3TB-SATA2 HDD; Intel ICore9 @ 3600MHZ (Win11 Pro. 64-Bit),
Acer Aspire E15 (Win11 Home X64). Purebasic LTS 6.11b1
HP255G8 Notebook @AMD Ryzen 5 5500U with Radeon Graphics 2.10 GHz 3.4GHz, 32GB_RAM, 3TB_SSD (Win11 Pro 64-Bit) - Kontaktdaten:
Ich würde dir ja gerne einen Beispielcode geben, aber im Moment habe ich damit
Probleme mit dem PB-source in Vergindung mit meiner GraKa HIS9200SE und PB3.92 den Beispielscode MovieSprite.pb ausführen zu können.
Aber Tips kann ich schon mal vermitteln
Was du dazu verwenden müßtest wären einmal aus der Hilfe
Movie
und weiter im PB-Ordner/sources stehen Beispiele wie PlayMovie.pb
und MovieSprite.pb.
Damit hast du dann eigendlich alles was du brauchst um eine MPEG anzuzeigen, pausieren, weiterspielen, frameposition auslesen und
über Spritefunktionen diese als BMP zu speichern.
MfG Falko
[Edit] Meine GraKa ist i.O. Aber der source spielt nicht alle Mpeg's ab.
Ein kleineres Format lief ohne Probleme.
Probleme mit dem PB-source in Vergindung mit meiner GraKa HIS9200SE und PB3.92 den Beispielscode MovieSprite.pb ausführen zu können.
Aber Tips kann ich schon mal vermitteln

Was du dazu verwenden müßtest wären einmal aus der Hilfe
Movie
und weiter im PB-Ordner/sources stehen Beispiele wie PlayMovie.pb
und MovieSprite.pb.
Damit hast du dann eigendlich alles was du brauchst um eine MPEG anzuzeigen, pausieren, weiterspielen, frameposition auslesen und
über Spritefunktionen diese als BMP zu speichern.
MfG Falko
[Edit] Meine GraKa ist i.O. Aber der source spielt nicht alle Mpeg's ab.
Ein kleineres Format lief ohne Probleme.
- Falko
- Admin
- Beiträge: 3535
- Registriert: 29.08.2004 11:27
- Computerausstattung: PC: MSI-Z590-GC; 32GB-DDR4, ICore9; 2TB M2 + 2x3TB-SATA2 HDD; Intel ICore9 @ 3600MHZ (Win11 Pro. 64-Bit),
Acer Aspire E15 (Win11 Home X64). Purebasic LTS 6.11b1
HP255G8 Notebook @AMD Ryzen 5 5500U with Radeon Graphics 2.10 GHz 3.4GHz, 32GB_RAM, 3TB_SSD (Win11 Pro 64-Bit) - Kontaktdaten:
Habe jetzt einen Top-Source aus dem englischen Forum gefunden, womit
Bilder aus mpeg's kopiert werden können. Der Author dieses Source
ist 'Inner' aus dem englischen Forum. Zusätzlich habe ich dann den einfachsten Teil (Bilder mit Zählnr. abspeichern) hinzugefügt
MfG Falko
Bilder aus mpeg's kopiert werden können. Der Author dieses Source
ist 'Inner' aus dem englischen Forum. Zusätzlich habe ich dann den einfachsten Teil (Bilder mit Zählnr. abspeichern) hinzugefügt

MfG Falko
Code: Alles auswählen
; ---------------------------------------------------------------------
;Written by Inner from english forum at Date 25 Apr 2003
;
; CaptureFrame(#Movie, #Image, #Memory)
;
; Copies the current frame of the #Movie to the #Image.
; The movie must pe paused when calling this, otherwise it will fail.
; The #Image should be the same size as the movie (MovieWidth(), MovieHeight())
; You must provide an unused memory bank number for temporary storage.
;
; ---------------------------------------------------------------------
Structure PB_StructureMovie
Movie.l ; IGraphBuilder DirectShow pointer
MediaControl.l ; IMediaControl DirectShow pointer
MediaEvent.l ; IMediaEventEx DirectShow pointer
Window.l ; IVideoWindow DirectShow pointer
Audio.l ; IBasicAudio DirectShow pointer
Video.l ; IBasicVideo DirectShow pointer
MediaSeeking.l ; IMediaSeeking DirectShow pointer
State.l ; State of the movie
EndStructure
Procedure.l CaptureFrame(MovieNumber, ImageNumber, MemoryBank)
Protected *Movie.PB_StructureMovie, *Video.IBasicVideo, *Window.IVideoWindow
Protected *ImageData.BITMAPINFOHEADER, DataSize, Parent, Result
!extrn _PB_Movie_ObjectsArea
!mov eax, [_PB_Movie_ObjectsArea]
!mov [esp+12], eax
*Movie + MovieNumber * SizeOf(PB_StructureMovie)
*Window = *Movie\Window
*Video = *Movie\Video
Result = 0
If *Video\GetCurrentImage(@DataSize, 0) = #S_OK
*ImageData = AllocateMemory(DataSize)
If *ImageData
If *Video\GetCurrentImage(@DataSize, *ImageData) = #S_OK
Result = SetDIBits_(0, UseImage(ImageNumber), 0, *ImageData\biHeight, *ImageData+*ImageData\biSize, *ImageData, #DIB_RGB_COLORS)
EndIf
FreeMemory(MemoryBank)
EndIf
EndIf
*Window\get_Owner(@Parent)
RedrawWindow_(Parent,0,0,#RDW_INVALIDATE)
ProcedureReturn Result
EndProcedure
; ---------------------------------------------------------------------
; Code example:
; ---------------------------------------------------------------------
#Movie = 0
#Image = 0
#Memory = 0
#Window = 0
#Gadget_Capture = 0
#Gadget_Image = 1
#Gadget_Tracker = 2
Path$="MovieCap\"
If ExamineDirectory(0,Path$, "*.*") = 0 ; if Directory not existing?
CreateDirectory(Path$)
EndIf
Nr=0
If InitMovie()
FileName$ = OpenFileRequester("Choose Movie","","Movie Files|*.mpg;*.avi;*.mpeg|All Files|*.*", 0)
If LoadMovie(#Movie, FileName$)
Width = MovieWidth()
Height = MovieHeight()
Length = MovieLength()
FPS = MovieInfo(0) / 1000
CreateImage(#Image, Width , Height)
If OpenWindow(#Window, 0, 0, Width , Height*2 + 35, #PB_Window_SystemMenu|#PB_Window_Screencentered|#PB_Window_Invisible, "Frame Capture")
If CreateGadgetList(WindowID())
ButtonGadget(#Gadget_Capture,0, Height+5, 100, 25, "Capture Frame")
TrackBarGadget(#Gadget_Tracker,110,Height+5,Width-110,20,0,Length/FPS,#PB_TrackBar_Ticks)
ImageGadget(#Gadget_Image, 0, Height+35, Width, Height, UseImage(#Image))
PlayMovie(#Movie, WindowID())
HideWindow(#Window, 0)
Repeat
Event = WindowEvent()
If Event = #PB_EventGadget And EventGadgetID() = #Gadget_Capture
PauseMovie()
CaptureFrame(#Movie, #Image, #Memory)
Nr=Nr+1
SaveImage(#Image,Path$+"movie"+Str(Nr)+".bmp",#PB_ImagePlugin_BMP)
SetGadgetState(#Gadget_Image, UseImage(#Image))
ResumeMovie()
EndIf
If Event = #PB_EventGadget And EventGadgetID() = #Gadget_Tracker
; PauseMovie()
MovieSeek(GetGadgetState(#Gadget_Tracker)*FPS)
; ResumeMovie()
EndIf
If Event = 0
Delay(1)
EndIf
Until Event = #PB_EventCloseWindow
EndIf
EndIf
EndIf
EndIf
End
Danke Falko,
leider komme ich damit aber nicht an das gewünschte Ziel.
Es geht ja nicht darum, das Video abzuspielen, sondern nur einen ganz bestimmten Frame als Bitmap herauszuziehen.
Beim Abspielen kann man das Video ja nicht framegenau anhalten und selbst wenn man an dem gesuchten Frame startet, wie bekommt man den Stop vor dem nächsten Frame hin?
nach wie vor ratlos
jear
leider komme ich damit aber nicht an das gewünschte Ziel.
Es geht ja nicht darum, das Video abzuspielen, sondern nur einen ganz bestimmten Frame als Bitmap herauszuziehen.
Beim Abspielen kann man das Video ja nicht framegenau anhalten und selbst wenn man an dem gesuchten Frame startet, wie bekommt man den Stop vor dem nächsten Frame hin?
nach wie vor ratlos
jear
- Falko
- Admin
- Beiträge: 3535
- Registriert: 29.08.2004 11:27
- Computerausstattung: PC: MSI-Z590-GC; 32GB-DDR4, ICore9; 2TB M2 + 2x3TB-SATA2 HDD; Intel ICore9 @ 3600MHZ (Win11 Pro. 64-Bit),
Acer Aspire E15 (Win11 Home X64). Purebasic LTS 6.11b1
HP255G8 Notebook @AMD Ryzen 5 5500U with Radeon Graphics 2.10 GHz 3.4GHz, 32GB_RAM, 3TB_SSD (Win11 Pro 64-Bit) - Kontaktdaten:
Rings hat's dir ja schon gesagt
. Ich war so frei und habe es noch etwas abgeändert. Wenn du es angehalten hast, kannst du unten auf den Schieber klicken und grob vor oder zurück gehen. Mit den Cursortasten für rechts/links kannst du die Bildposition feiner abstimmen.
[Edit] auch die Bildgröße läßt sich jetzt ändern
So, jetzt hier noch ein bischen zum Verstehen abgeändert

[Edit] auch die Bildgröße läßt sich jetzt ändern

So, jetzt hier noch ein bischen zum Verstehen abgeändert

Code: Alles auswählen
; ---------------------------------------------------------------------
;Written by Inner from english forum at Date 25 Apr 2003
;----------------------------
;Falko: Erweitert, sodas man auch größere Bilder
;machen kann. Ebenso eine Pause-, und Resumefunktion jetzt vorhanden.
;
; CaptureFrame(#Movie, #Image, #Memory)
;
; Copies the current frame of the #Movie to the #Image.
; The movie must pe paused when calling this, otherwise it will fail.
; The #Image should be the same size as the movie (MovieWidth(), MovieHeight())
; You must provide an unused memory bank number for temporary storage.
;
; ---------------------------------------------------------------------
Structure PB_StructureMovie
Movie.l ; IGraphBuilder DirectShow pointer
MediaControl.l ; IMediaControl DirectShow pointer
MediaEvent.l ; IMediaEventEx DirectShow pointer
Window.l ; IVideoWindow DirectShow pointer
Audio.l ; IBasicAudio DirectShow pointer
Video.l ; IBasicVideo DirectShow pointer
MediaSeeking.l ; IMediaSeeking DirectShow pointer
State.l ; State of the movie
EndStructure
Procedure.l CaptureFrame(MovieNumber, ImageNumber, MemoryBank)
Protected *Movie.PB_StructureMovie, *Video.IBasicVideo, *Window.IVideoWindow
Protected *ImageData.BITMAPINFOHEADER, DataSize, Parent, Result
!extrn _PB_Movie_ObjectsArea
!mov eax, [_PB_Movie_ObjectsArea]
!mov [esp+12], eax
*Movie + MovieNumber * SizeOf(PB_StructureMovie)
*Window = *Movie\Window
*Video = *Movie\Video
Result = 0
If *Video\GetCurrentImage(@DataSize, 0) = #S_OK
*ImageData = AllocateMemory(DataSize)
If *ImageData
If *Video\GetCurrentImage(@DataSize, *ImageData) = #S_OK
Result = SetDIBits_(0, UseImage(ImageNumber), 0, *ImageData\biHeight, *ImageData+*ImageData\biSize, *ImageData, #DIB_RGB_COLORS)
EndIf
FreeMemory(MemoryBank)
EndIf
EndIf
*Window\get_Owner(@Parent)
RedrawWindow_(Parent,0,0,#RDW_INVALIDATE)
ProcedureReturn Result
EndProcedure
; ---------------------------------------------------------------------
; Code example:
; ---------------------------------------------------------------------
#Movie = 0
#Image = 0
#Image2 = 1
#Memory = 0
#Window = 0
#Gadget_Capture = 0
#Gadget_Image = 1
#Gadget_Tracker = 2
#Pause=3
#Weiter=4
Path$="MovieCap\"
If ExamineDirectory(0,Path$, "*.*") = 0 ; if Directory not existing?
CreateDirectory(Path$)
EndIf
Nr=0
If InitMovie()
FileName$ = OpenFileRequester("Choose Movie","","Movie Files|*.mpg;*.avi;*.mpeg|All Files|*.*", 0)
If LoadMovie(#Movie, FileName$)
Width = MovieWidth()
Height = MovieHeight()
Length = MovieLength()
FPS = MovieInfo(0) / 1000
CreateImage(#Image, Width , Height)
If OpenWindow(#Window, 0, 0, Width , Height*2 + 35, #PB_Window_SystemMenu|#PB_Window_Screencentered|#PB_Window_Invisible, "Frame Capture")
If CreateGadgetList(WindowID())
ButtonGadget(#Gadget_Capture,0, Height+5, 100, 25, "Capture Frame")
ButtonGadget(#Pause,130, Height+5, 100, 25, "Pause Frame")
ButtonGadget(#Weiter,260, Height+5, 100, 25, "Resume Frame")
TrackBarGadget(#Gadget_Tracker,60,Height+30,Width-60,20,0,Length/FPS,#PB_TrackBar_Ticks)
ImageGadget(#Gadget_Image, 0, Height+50, Width, Height, UseImage(#Image))
PlayMovie(#Movie, WindowID())
HideWindow(#Window, 0)
Repeat
Event = WindowEvent()
If Event = #PB_EventGadget And EventGadgetID() = #Gadget_Capture
CaptureFrame(#Movie, #Image, #Memory)
Nr=Nr+1
SetGadgetState(#Gadget_Image, UseImage(#Image))
CopyImage(#Image,#Image2)
ResizeImage(#Image2, 640, 480); z.B hier eine größere BMP erstellen
SaveImage(#Image2,Path$+"movie"+Str(Nr)+".bmp",#PB_ImagePlugin_BMP)
ActivateGadget(#Gadget_Tracker)
Event=#Gadget_Tracker
EndIf
If Event = #PB_EventGadget And EventGadgetID() = #Pause
PauseMovie()
ActivateGadget(#Gadget_Tracker)
EndIf
If Event = #PB_EventGadget And EventGadgetID() = #Weiter
ResumeMovie()
ActivateGadget(#Gadget_Tracker)
EndIf
If Event = #PB_EventGadget And EventGadgetID() = #Gadget_Tracker
Pos.l= GetGadgetState(#Gadget_Tracker)
MovieSeek(GetGadgetState(#Gadget_Tracker)*FPS)
ResumeMovie()
PauseMovie()
EndIf
If Event = 0
Delay(1)
EndIf
Until Event = #PB_EventCloseWindow
EndIf
EndIf
EndIf
EndIf
End
@Falko,
vielen Dank für Deine Mühen und Hilfen.
Wenn ich hier eine solche Frage stelle, habe ich mich schon eingehend mit der Thematik beschäftigt und rumgesucht. Wenn ich auch hier im Forum neu bin, neu im Geschäft bin ich nicht. Programmiere seit 1964 als man dazu noch die Nadeln durch oder um den Ringkern herum führte.
Wie gesagt es geht um MPEG-Dateien nicht um AVI's. Genauer noch um MPEG-2 Dateien. Mit MPEG-1 und AVI's läuft das Movie-Repertoire, mit MPEG-2's nicht. Das gilt auch für Deinen Code, zumindest auf meiner Maschine und die hat alles, was man zur Videobearbeitung braucht. Da es mir um MPEG-2's geht hatte ich das Ganze mit AVI's nicht probiert.
Das Problem liegt wohl an den Werten die PB-Movie zurückliefert.
Während das inhaltlich gleiche Video als DV-AVI korrekt mit der Länge von 1460 Frames und 25 FPS erkannt wird, hat die MPEG-2 die sagenhafte Länge von 499061030 Frames und es werden 17241 FPS zurückgemeldet.
Um welche Werte handelt es sich denn da ? Ist das ein Fehler in PB? Gibt es irgendwo einen Hinweis, wie man die gemeldeten Werte behandeln muss?
... oder habe ich nur nicht "genug programmiert" ?
vielen Dank für Deine Mühen und Hilfen.
Wenn ich hier eine solche Frage stelle, habe ich mich schon eingehend mit der Thematik beschäftigt und rumgesucht. Wenn ich auch hier im Forum neu bin, neu im Geschäft bin ich nicht. Programmiere seit 1964 als man dazu noch die Nadeln durch oder um den Ringkern herum führte.
Wie gesagt es geht um MPEG-Dateien nicht um AVI's. Genauer noch um MPEG-2 Dateien. Mit MPEG-1 und AVI's läuft das Movie-Repertoire, mit MPEG-2's nicht. Das gilt auch für Deinen Code, zumindest auf meiner Maschine und die hat alles, was man zur Videobearbeitung braucht. Da es mir um MPEG-2's geht hatte ich das Ganze mit AVI's nicht probiert.
Das Problem liegt wohl an den Werten die PB-Movie zurückliefert.
Während das inhaltlich gleiche Video als DV-AVI korrekt mit der Länge von 1460 Frames und 25 FPS erkannt wird, hat die MPEG-2 die sagenhafte Länge von 499061030 Frames und es werden 17241 FPS zurückgemeldet.
Um welche Werte handelt es sich denn da ? Ist das ein Fehler in PB? Gibt es irgendwo einen Hinweis, wie man die gemeldeten Werte behandeln muss?
... oder habe ich nur nicht "genug programmiert" ?
So ganz aufgeben möchte ich noch nicht.
Daher die Frage an die Moderation oder wen immer es interessieren mag :
- Ist es den PB-Entwicklern bewusst, dass die Movie-Funktionen für MPEG2-Dateien falsche Werte liefern, sodass sich damit nichts anfangen lässt?
- Kann die Erscheinung vom genutzten PC abhängig sein? (Fahre DirectX 9 unter WinXP auf einem P4 3.0 HT)
- Hat jemand da draußen ähnliche oder andere Erfahrungen?
Danke
Daher die Frage an die Moderation oder wen immer es interessieren mag :
- Ist es den PB-Entwicklern bewusst, dass die Movie-Funktionen für MPEG2-Dateien falsche Werte liefern, sodass sich damit nichts anfangen lässt?
- Kann die Erscheinung vom genutzten PC abhängig sein? (Fahre DirectX 9 unter WinXP auf einem P4 3.0 HT)
- Hat jemand da draußen ähnliche oder andere Erfahrungen?
Danke
- Andre
- PureBasic Team
- Beiträge: 1765
- Registriert: 11.09.2004 16:35
- Computerausstattung: MacBook Core2Duo mit MacOS 10.6.8
Lenovo Y50 i7 mit Windows 10 - Wohnort: Saxony / Deutscheinsiedel
- Kontaktdaten:
Ist eine gute Möglichkeit, dann am besten aber inkl. einem kleinen Beispiel-Code + paar Links zu Beispiel-MPEG2-Dateien.grapy hat geschrieben:Am Besten beschreibst Du den Bug mal im englischen Forum. Mal sehen was Fred(der PB-Entwickler) dazu meint.![]()

Alternativ auch hier und ich leite es dann weiter.
