TMediaPlayer, Videobild Capture als Bitmap speichern, Lösung!
-
Hallo Leute,
ich habe hier mal was für euch, in Sachen TMediaPlayer.
Heute Mittag erhielt ich eine Anfrage per Email, wie
man ein Videobild Capturen kann, mit anderen Worten:
Abspeichern des aktuellen Frames eines Videos als Bitmap.Wer so eine Funktion schon hat, der hat sicherlich wie ich
eine Ableitung der Klasse TMediaPlayer erstellt und die
Funktion "Paint()" umgeschriebenFür alle die aber eine möglichst einfache Methode suchen, und
auch für den Fragenden, habe ich mir heute mal eine Lösung überlegt.Der Einfachste Weg ist, wenn wir ein Display für den MediaPlayer wählen
auf dessen Canvas wir Problemlos zugreifen können, dazu kommt das übliche
Panel nicht in Frage, aber unsere Form schon.
Leider wird das nicht Unterstützt das man die Form zur Entwurfzeit als
Display wählen kann, daher lassen wir dieses Proberty offen.Hier mal die Reihenfolge:
1. Form und MediaPlayer erstellen nach eigenem ermessen
2. Ein Button, der bei seiner OnClick Auslösung das Frame speichern soll.
3. SaveDialog nicht vergessen
4. Display proberty beim MediaPlayer offen lassen!5. Im FormShow Event der Form folgendes Eintragen:
MediaPlayer1->Display = Form1; // Die Form als Display zuweisen
6. Erzeugt eine Globale Variable namens VideoRect
TRect VideoRect;
7. Im OnClick Event eures Buttons zum speichern des Videobildes schreibt ihr folgendes:
bool PlayGo = false; //Video nicht weiter spielen VideoRect = MediaPlayer1->DisplayRect; //Videobild Größe hollen if (MediaPlayer1->Mode != mpPaused) { //frage ob MediaPlayer Pausiert wurde PlayGo = true; //wenn nicht dann weiter spielen ja (true) MediaPlayer1->Pause(); //MediaPlayer Pausieren } if (SaveDialog1->Execute()) { //SaveDialog aufrufen Graphics::TBitmap *bild = new Graphics::TBitmap; // neue Bitmap erstellen bild->Width = VideoRect.Right; //Bitmap die Videobreite zuordnen bild->Height = VideoRect.Bottom; //das Gleiche mit der Höhe bild->Canvas->CopyRect(VideoRect,Form1->Canvas,VideoRect); // Videobild in Bitmap kopieren bild->SaveToFile(SaveDialog1->FileName); // Bitmap abspeichern delete bild; // bild Zeiger löschen; } if (PlayGo) { // wenn Video weiterspielen MediaPlayer1->Resume(); // Video weiterspielen }
8. Versucht diese Vorgehensweise zu Verstehen und den Code entsprechen euren
Vorstellungen anzugleichen, vergesst aber bitte auch nicht try-catch um Exeptions
abzufangen, und und...
Wenn euch TRect nicht bekannt ist, so macht euch über die Hilfe und Suchfunktion im
Forum etwas schlau, so werdet ihr schnell dazu fähig sein das Videobild in der Mitte
der Form anzuzeigen, bzw. an einer beliebigen Stelle. Dafür Zuständig ist das Proberty
"MediaPlayer1->DisplayRect;"
Damit kann man auch das Videobild verkleinern oder vergrößern.Für weitere Fragen bin ich gerne offen.
gruß Micha
PS:
Wenn das Interesse Besteht, würde ich mir auch die Mühe machen einige Tutorials
zum TMediaPlayer zu schreiben, vorallem was "guttes" Fullscreen angeht (und
nicht wie im Verweiß der FAQ), sowie unterschidliche Darstellungsgrößen, Datentypen, Fehlerbehandlung und und und ...
-
promicha schrieb:
Der Einfachste Weg ist, wenn wir ein Display für den MediaPlayer wählen
auf dessen Canvas wir Problemlos zugreifen können, dazu kommt das übliche
Panel nicht in Frage[...]Wo ist das Problem beim Panel?
TCanvas *canv = new TCanvas(); canv->Handle = GetDC(Panel1->Handle); Image1->Canvas->CopyRect(Panel1->ClientRect, canv, Panel1->ClientRect); ...
vorallem was "guttes" Fullscreen angeht (und
nicht wie im Verweiß der FAQ)Was genau ist "gutes Fullscreen", bzw. was ist am FAQ-Link schlecht?
-
Das Problem beim Panel ist, das ich nur Graues BtnFace im
Bild erhalte, ich habe es so versucht und normalerweise
müßte es auch Funktionieren, tut es aber nicht. Ich habe
das gleiche auch mit anderen möglichen Komponenten versucht,
ohne Erfolg, das Einzige was bei mir Funktioniert ist die
Form.Fullscreen, schon mal einen Player geschrieben mit Verwendung
des FAQ-Link Beispiels? (Der Link)Der Reihe nach:
// Get a handle to the MediaPlayer display window // may be "AVIWnd32" for WinNT HDisplayWindow = FindWindow("AVIWnd", NULL);
Also erst mal Prüfen auf welches System der Player läuft,
oder alle Fenster abfragen und das nehmen welches mit AVIWnd
beginnt.
und man sollte es schon so Schreiben:HWND HDisplayWindow = FindWindow("AVIWnd", NULL);
sonst weiss der Compiler nicht was HDisplayWindow sein soll.
Ist ja auch nur ein Schönheitsfehler, somit übersehbar.Das Funktioniert soweit ganz gut, aber wie Steuer ich jetzt
den Player? Ich kann dem AVIwindow doch kein Popup-Menu zuordnen
(Mit einfachen Mitteln wärend der Entwurfzeit).
Und ich möchte gerne per OnMouseMove feststellen ob die Maus im
unteren Bildschirmrand sitzt, damit ich dort die Steuerbuttons
einblenden kann.
Wir haben bei dieser Methode leider ein fremdes Fenster, welches
wir nicht wärend der Entwurfzeit Bearbeiten können, nützen wir
aber unsere Form als Display, so haben wir die Möglichkeiten die
ich oben erwähnte.
Und mit:SetWindowPos(Form1->Handle, HWND_TOPMOST, 0, 0, Screen->Width, Screen->Height, NULL);
bekommen wir unsere Form auch in Fullscreen. Sollte man jetzt sagen das wir
genauso gut dieses AVI Fenster unseren Vorstellungen anpassen können, dann
hat das nichts mehr mit der IDE und VCL zu tun, das ist dann WinAPI.Als Zusatz sei noch gesagt, das Capturen aus diesem Player-Fenster
funktioniert auch tadellos, habs getestet.Graphics::TBitmap *bild = new Graphics::TBitmap; bild->Width = MediaPlayer1->DisplayRect.Right; bild->Height = MediaPlayer1->DisplayRect.Bottom; TCanvas *Capture = new TCanvas(); Capture->Handle = GetDC(HDisplayWindow); if (Capture->Handle) bild->Canvas->CopyRect(MediaPlayer1->DisplayRect, Capture, MediaPlayer1->DisplayRect); delete Capture; bild->SaveToFile(SaveDialog1->FileName); delete bild;
gruß Micha