c++ Winapi - Bitmap Farbarray verarbeiten

01/16/2012 16:22 Knopfdruck#1
Folgendes Problem:

Ein Abbild vom Desktop wird erstellt und die Bits werden mit passenden Bitmapheadern erfolgreich als Bitmap gespeichert.
Sprich ich bin schonmal sicher, dass ich die Bildinformationen richtig einlese und speicher.

Die Bits befinden sich also im Array pbBits.
Bitmap-typisch sind die Bildinformationen schon upside-down im Array,
daher geben auch pbBits[0], pbBits[1] und pbBits[2] Farbinformationen (BGR) des linken Pixel der untersten Zeile.
Auch die restlichen Pixel dieser Zeile haben die richtigen farbwerte (Ich habs manuell überprüft anhand des abgespeicherten Bildes).
Meine Bildschirmbreite ist 1366 und die Höhe 768.
Wenn ich nun also die nächste Zeile auslesen will, wäre dies doch Pixel 1366+1, daher pbBits[4101],pbBits[4102],pbBits[4103](hoffe bringe hier logische dinge nicht durcheinander). Leider stimmen diese Farbwerte nicht mit denen des Bildes überein, daher gehe ich nun davon aus, dass die Fehlerquelle hier liegt.

Erkennt jemand von euch Unstimmigkeiten? Oder kennt ganz und gar eine bessere möglichkeit?

hier die Funktion:
Code:
int CaptureScreen(){
	// RETURN VALUES
	// 0 failure
	// 1 Success
	//

	int     nWidth  = GetSystemMetrics(SM_CXSCREEN);
	int     nHeight = GetSystemMetrics(SM_CYSCREEN);
 
	HWND    hWnd    = GetDesktopWindow();
	HDC     hdc     = GetDC(hWnd);
	HDC     memDC   = CreateCompatibleDC(hdc);
	HBITMAP hbm     = CreateCompatibleBitmap(hdc, nWidth, nHeight);
	HBITMAP hbmOld  = (HBITMAP)SelectObject(memDC, hbm);
 
	BitBlt(memDC, 0, 0, nWidth, nHeight, hdc, 0, 0, SRCCOPY);
                                 
	BITMAPINFO bmi;
 
	bmi.bmiHeader.biSize         = sizeof(BITMAPINFOHEADER);
	bmi.bmiHeader.biWidth        = nWidth;
	bmi.bmiHeader.biHeight       = nHeight;
	bmi.bmiHeader.biBitCount     = 24;
	bmi.bmiHeader.biPlanes       = 1;
	bmi.bmiHeader.biCompression  = BI_RGB;
	bmi.bmiHeader.biSizeImage    = 4 * nWidth * nHeight;

	BYTE *pbBits = new BYTE[bmi.bmiHeader.biSizeImage];

	GetDIBits( memDC,hbm,0,bmi.bmiHeader.biHeight,pbBits,&bmi,DIB_RGB_COLORS );

	////Alle Informationen die eine Bitmap braucht hier der Fileheader
	BITMAPFILEHEADER bfh;
	bfh.bfType      = ('M' << 8) + 'B';
	bfh.bfSize      = sizeof(BITMAPFILEHEADER) +bmi.bmiHeader.biSizeImage +sizeof(BITMAPINFOHEADER); 
	bfh.bfReserved1 = 0;
	bfh.bfReserved2 = 0;
	bfh.bfOffBits   = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
	

	//speichern
			HANDLE hfile = CreateFile(L"c:\\temp\\screen.bmp",GENERIC_WRITE,0,0,OPEN_ALWAYS,0,0); 
			DWORD dwWritten;
			WriteFile(hfile,&bfh,           sizeof(bfh),               &dwWritten, NULL); 
			WriteFile(hfile,&bmi.bmiHeader, sizeof(BITMAPINFOHEADER),  &dwWritten, NULL); 
			WriteFile(hfile,pbBits,         bmi.bmiHeader.biSizeImage, &dwWritten, NULL);
			CloseHandle(hfile);

		//verarbeitung
			int xxPos=750,yyPos=300;
			
		//TEST um zu gucken wie das Array nun wirklich aufgebaut ist... 1. zeile (yyPos=0) klappt ganz gut und stimmt
		//jedoch ab Zeile 2 yyPos=1 stimmen die Farbwerte nicht mit den manuell bestimmten Werten überein.
		FILE *fp;
		fp=fopen("c:\\temp\\test.txt", "w");
		
		fprintf(fp, "%d.",pbBits[yyPos*nWidth + xxPos*3]);  //blau
		fprintf(fp, "%d.",pbBits[yyPos*nWidth + xxPos*3+1]); //gruen
		fprintf(fp, "%d.",pbBits[yyPos*nWidth + xxPos*3+2]); //rot
		fprintf(fp, "# x%d y%d",xxPos,yyPos);

		fprintf(fp, "-------");
		fclose(fp);

	
	
	//clean up 
	SelectObject(memDC, hbmOld);
	DeleteDC(memDC);
	ReleaseDC(hWnd,hdc); 
	DeleteObject(hbm);
	delete[] pbBits;
	return 1;
}
Vielen Dank für eure Aufmerksamkeit ;)
peace out
01/16/2012 17:17 MoepMeep#2
Für mich wär eine andere Zeile eine Veränderung der Y-Achse. Liegt dort vllt dein Denkfehler? ;)
01/16/2012 18:54 Knopfdruck#3
Durch yyPos*nWidth überspringe ich doch alle RGB Triplets einer Zeile um eine Zeile nach "oben" zu gelangen.

Wobei dabei fällt mir gerade aus, dass ich diesen wert nocheinmal mit 3 Multiplizieren muss, da es sich ja um Triplets handelt

sprich 1366*3(nWidth*3) wären alle Einträge einer Zeile
wenn ich dann yyPos=1 wähle um in die Zeile mit der Koordinate (xxPos | 1) zu kommen entspricht das 1*1366*3 + xxPos

jedoch stimmen die Koordinaten immernich nicht überein
01/16/2012 19:57 MoepMeep#4
Ich muss gestehen, ich hatte mir den Code bisher nicht angeschaut. Mich hatte etwas am Text oben verwirrt.
Eine Zeile hat 1366Pixel(0-1365), also 4098 Felder im Array. Demzufolge wäre das ende des letzten Pixels bei [4097]. Pixxel 1367 fängt meiner Meinung nach bei [4098] an und nicht bei [4101].
01/16/2012 23:52 Knopfdruck#5
Du hast Recht, da liegt der erste Fehler.
Bisher habe ich auch noch rausgefunden, dass scheinbar nach dem Ende einer Zeile eine Determinierer-Sequenz liegt. Jedenfalls sind 4098 und 4099 jeweils 0 und passen nicht in den Code.

Werde das morgen mal überprüfen und mir dann eine Gleichung schreiben ;) Dann berichte ich mal ob es klappt oder immer noch nicht ;D
danke schonmal und schönen Abend noch
peace out


Alles klar nach dem ersten Kaffee des Tages habe ich den Fehler gefunden. Es Liegt tatsächlich an der berechnung der triplets... :D Einfach nur ärgerlich sowas, aber halt total logisch, das bei einer falschen berechnung alle folgenden Koordinaten falsch sind.

Daher vielen Dank @ MoepMoep, ohne den Fehler den du Aufgedeckt hast, hätte ich den folgenden gar nicht erst gesucht