Forum: PC-Programmierung WinAPI: Pixel in DIB Section manipulieren


von mammamia (Gast)


Lesenswert?

Hallo Leute,

mein WinApi Programm zeichnet momentan per "SetPixel" Bilder in das 
Fenster. Da aber mein Programm durch das ständige neuzeichnen total 
langsam ist, möchte ich das ganze in DIB machen. Leider bekomme ich es 
nicht hin, dass mein Byte-Array (mit den Farbinformationen in RGB) in 
die DIB Section zu zeichnen. hier sind die wesentlichen code-teile:

HBITMAP hBitmap, bitmap;
BYTE *pBits, testzz[5000];
BITMAPINFOHEADER bmih;
BITMAPINFO *pbmi;
void init_bmp(void);
HDC hdcMem;

hBitmap = CreateDIBSection(NULL, (BITMAPINFO *)&bmih, 0, (void**) 
pBits,NULL,0);

pBits = &testzz[0]; //in testzz sind die Farbinformationen

hDC = BeginPaint(hwnd, &ps);
hdcMem = CreateCompatibleDC(hDC);
GetObject(hBitmap, sizeof(HBITMAP), &bitmap);
SelectObject (hdcMem, hBitmap);
BitBlt(hDC, 10,40, 100, 50,  hdcMem, 0, 0, SRCCOPY);

EndPaint(hwnd, &ps);

Hat jemand eine Ahnung wie ich meine Pixel Informationen (testzz) in die 
DIB Section zeichnen kann? Danke im Voraus!

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Sieh Dir mal die Bedeutung des vierten Parameters von CreateDIBSection 
genauer an.

Das ist ein Pointer auf einen Pointer, der auf den von der DIB genutzten 
Speicher zeigen wird. Den Speicher stellt die Funktion selbst zur 
Verfügung (wenn Du nicht ein Filemapping-Objekt benutzt, aber das tust 
Du nicht).

Also musst Du nicht pBits selbst übergeben, sondern dessen Adresse. Und 
nach dem Aufruf von CreateDIBSection darfst Du pBits nicht verändern 
(was Du mit Deiner Zuweisung auf testzz tust).

Wenn der Inhalt von testzz in der DIB auftauchen soll, musst Du ihn 
hineinkopieren, und nicht den von der Funktion zurückgegebenen Pointer 
verändern.
1
hBitmap = CreateDIBSection(NULL, (BITMAPINFO *) &bmih, 0, &pBits, NULL, 0);
2
3
memcpy(pBits, testzz, 5000);

Der memcpy-Aufruf ist so natürlich mutig, weil nicht überprüft wird, ob 
a) pBits überhaupt irgendwohin zeigt (hBitmap nach Aufruf von 
CreateDIBSection überprüfen, pBits vor Aufruf auf NULL setzen, danach 
überprüfen, ob nicht NULL) und b) ob der Speicher, auf den pBits zeigt, 
groß genug ist für die hineinkopierten 5000 Bytes.

von mammamia (Gast)


Lesenswert?

YEAAAH funktioniert, vielen Dank!!!!!

von Platinenschwenker .. (platinenschwenker)


Lesenswert?

mammamia schrieb:
> YEAAAH funktioniert, vielen Dank!!!!!

Und hast du auch mal den Speicherverbrauch des Programms beobachtet, 
wenn sich das Fenster neuzeichnet?

Ich könnte mir vorstellen, dass der langsam anwächst..  :)

Fehlt da nicht ein

DeleteDC (hdcMem);

vor EndPaint?

Was meint Rufus?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

http://msdn.microsoft.com/en-us/library/dd183494(v=vs.85).aspx

As noted above, if hSection is NULL, the system allocates memory for the 
DIB. The system closes the handle to that memory when you later delete 
the DIB by calling the DeleteObject function.


Ansonsten ist es in der Tat ratsam, jedes Handle, jedes Objekt etc. nach 
Gebrauch zurückzugeben. Der Resourcenverbrauch eines laufenden 
Programmes kann z.B. mit dem ProcessExplorer untersucht werden.

von mammamia (Gast)


Lesenswert?

Da sich das Fenster immer neuzeichnet brauche ich die DIB Section nur 
einmal zu erzeugen und erst beim beenden des Pogrammes löschen oder?

Oder ist es ratsam bei jedem neuzeichnen die Section neu zu erzeugen?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Da muss ich passen. Vermutlich nicht; aber Du könntest mal das 
Ressourcenverhalten untersuchen, indem Du Dein Programm längere Zeit 
laufen und sehr oft das Fenster aktualisieren lässt und derweil mit dem 
Process Explorer zusiehst.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.