[GDI] Screen-Capturing

revelation

Mitglied
Hallo zusammen,

ich habe eine Anwendung, die ca. 25-30 mal einen Screenshot des aktuell gezeigten Desktops auslesen soll.
Die Daten müssen als Byte-Array vorliegen.

Das einzige Problem ist die Geschwindigkeit: Ich schaffe mit folgendem Code auf meinem Rechner (AthlonXP 2800+; 1024*768; 32BPP) nur 20-21 Bilder/sec.
Weil die Daten Anschließend noch komprimiert werden müssen, ist das nicht tragbar.

Hier der Code:
Code:
//pBits sei char ** und *pBits zeige auf ausreichend viel reservierten Speicher

// Bitmappuffer erstellen
HWND hWndDesktop  = GetDesktopWindow(); // Handle auf Bildschirmfenster erhalten
HDC hDCDesktop  = GetWindowDC(hWndDesktop); // DeviceContext erhalten
	
HDC hDCMem  = CreateCompatibleDC(hDCDesktop); // kompatiblen DC erstellen
	
int width  = GetDeviceCaps(hDCDesktop, HORZRES); // Bildschirmbreite ermitteln
int height  = GetDeviceCaps(hDCDesktop, VERTRES); // Bildschrimhöhe ermitteln

HBITMAP bmpMem  = CreateCompatibleBitmap(hDCDesktop, width, height); // Puffer erstellen

// Bitmap mit dem DC "verbinden"
SelectObject(hDCMem, bmpMem);

// Bitmap-Info setzen
ZeroMemory(&bmi, sizeof(bmi));

// Infos übertragen
bmi.bmiHeader.biSize        = sizeof(bmi.bmiHeader);
bmi.bmiHeader.biWidth       = width;
bmi.bmiHeader.biHeight      = height;
bmi.bmiHeader.biPlanes      = 1;
bmi.bmiHeader.biBitCount    = 16; // Ist aus Kompressionsgründen 16
bmi.bmiHeader.biCompression = BI_RGB;

// Bildschirminhalt in den Puffer übertragen
if(!BitBlt(hDCMem, 0, 0, bmi.bmiHeader.biWidth, bmi.bmiHeader.biHeight, hDCDesktop, 0, 0, SRCCOPY))
    return 0;
	
// Pointer auf Bitmapdaten erhalten
if(!GetDIBits(hDCMem, bmpMem, 0, bmi.bmiHeader.biHeight, *pBits, &bmi, DIB_RGB_COLORS))
    return 0;

// Bitmappuffer aufräumen
DeleteDC(hDCMem);
DeleteObject(bmpMem);
ReleaseDC(hWndDesktop, hDCDesktop);

Hat jemand eine Ahnung, wie man das beschleunigen könnte?
Wichtig ist nur der Pointer auf die Bitmapdaten.

Dank schonmal
Johannes
 
Zuletzt bearbeitet:
moin


Hab nicht so die Ahnung von dem Thema, aber wie wäre es erst alle Bilder aufzunehmen, abzuspeichern und dann am schluss sie zu komprimieren?

Mir ist schon klar das das relativ viel Speicher benötigen wird.


mfg
umbrasaxum
 
Danke für deine Antwort!

Leider hilft mir das nicht weiter:

Die Bilder sollen als "Life-Video" per Netzwerk gesendet werden, da kann man nicht erst alle Bilder speichern und dann gesammelt schicken... :)

Gruß
Johannes
 
Zuletzt bearbeitet:
Vielleicht mal versuchen den Code so gut wie möglich zu optimieren, d.h. alle Variablen die nur einmal initialisiert werden müssen auch nur einmal zu initialisieren.
 
Evtl. mal die 20 bis 30 Frames als Puffer vor-reservieren und dann nicht immer neu erstellen/zerstören sondern ringweise durcharbeiten.

Dann einfach immer in den nächsten Puffer BitBlten.

Und irgendwie dafür sorgen, dass sich der Kopf des Ring-Puffers nicht in den Schwanz beisst :)
 
Danke erstmal für eure Anregungen!

Ich war aber auch schon so schlau sämtliche Speicherreservierungen und Handleanforderungen nur noch so wenig wie möglich zu benutzen.
Mit entäuschendem Ergebnis: Der Geschwindigkeitsunterschied war NICHT messbar... :(

Weil ich irgendwann mal gelernt habe, dass man GDI-Handles nur so kurz wie möglich behalten soll, habe ich den Code wieder in seine Ursprungsform gebracht.

Was ich allerdings herausgefunden habe:
> 95% der Laufzeit gehen beim Aufruf von GetDIBits drauf!
Es muss doch irgendeinen Weg geben, direkt an den Speicher zu kommen!

Gruß
Johannes
 
Zuletzt bearbeitet:
moin


Ich weiss nicht ob es schneller ist, aber wie wäre es das gane mit DirectDraw zu machen anstatt mit GDI?!

Weisst du eigentlich ob dein Programm nur auf deinem PC zu langsam ist? Würde es für dich bei mir testen, wenn du interesse hast.


mfg
umbrasaxum
 
Ah, statt GetDIBits zu benutzen würde ich empfehlen, die eigene Bitmap mit CreateDIBSection zu erstellen. Da hast du von Anfang an einen Pointer auf die Pixeldaten.

Bei GetDIBits werden die Daten glaube ich ja auch noch mal kopiert.
 

Neue Beiträge

Zurück