Pixelreading möglichst schnell
-
hallo allseits!
ich hab folgendes problem:
ich will ein programm in c/c++ programmieren, welches mittels pixel-readings tetris für mich spielen kann. soweit ich bis jetzt gelesen habe, ist für so eine anwendung Getpixel ungeeignet, da die funktion sehr langsam ist. gibt es da schnellere funktionen, mit denen ich sowas programmieren könnte?ich danke vielmals schon im vorhinein für die antworten!
---
lg
we
-
CreateCompatibleDC() + CreateCompatibleBitmap() + BitBlt() + GetDIBits()
-
danke vielmals für die schnelle hilfe!
werd jetzt mal schauen ob ich so zusammenbring=)---
lg
we
-
Wenn es dir auf Geschwindigkeit ankommt, kannst du auch eine kleine Klasse schreiben, die einiges im Voraus berechnet. Dazu gehören natürlich die Bytelänge einer Zeile, die Startdresse jeder Zeile in einem std::vector etc.
Praktisch eine Wrapperklasse um eine DIBSECTION. Sie stellt ebenfalls eine HBITMAP zur Verfügung, die in Kontexte eingewählt werden kann, aber ebenfalls einen Zeiger auf die Pixeldaten.
Vorteil: Bei Funktionen wie Get/SetPixel muss nicht mehr überlegt werden, ob es sich jetzt um eine Top-Bottom-Bmp oder umgekehrt handelt, die Länge einer Zeile muss nicht jedesmal neu berechnet werden und durch die Startadressen jeder Zeile ist es schließlich eine simple Addition.
Auch kannst du so natürlich eine Zeile in einem Rutsch verarbeiten-> Zeiger besorgen und nestprechend inkrementieren.Für Ideen zur Umsetzung siehe Petzold.
-
@whoever:
Evtl. Ideen... Das Spielfeld als Rect bzw Bitmap kopieren und dieses in ein Array kopieren... Im Array kannst du nun sehr schnell ermitteln, welcher Pixel welche Farbe hat... Hier muß man nicht mehr auf die langsame GetPixel API setzen...Eine evtl. weitere Idee wäre, die von dir kopierte Bitmap bzw dsa Spielfeld in ein Gitternetz zu unterteilen, z.b. 8x8 / 16x16 oder wie auch immer große Felder... Jetzt könnte man evtl. eine alle Pixel in einem Block addieren und durch die Anzahl der Pixel teilen... MIt diesem Wert kannst du beim nächsten Durchlauf ermitteln, ob sich in diesem Bereich etwas verändert hat oder nicht... (sollte zumindest funktionieren, wenn der Hintergrund fix und nicht animiert ist).
-
Das kleine projekt ist in der zwischenzeit etwas ausgeartet und ich programmiere jetzt nebenbei an einer bibliothek, welche mir eingespeicherte muster erkennt und am bildschirm findet.
für mein tetris-problem habe ich beschlossen, dass das programm mit dem ersten stein der ins spiel kommt die dimensionen des spielfelds bestimmt und dann die breite und höhe in einen raster einteilt (ich programmiere es zurzeit für eine version mit einem schwarzen "spielfeld" und der rest ist farbig, was mir die bestimmung des umrisses des "spielfelds" sehr leicht macht) von jeden dieser rasterquadrate nehme ich dann das pixel was genau in der mitte liegt und verwende dann diese punkte um zu bestimmen wie das spielfeld ausschaut. das schwierigste zur zeit ist die ki die mir dieses spiel spielt..
ich danke vielmals für die antworten und entschuldige mich herzlichst für jeweilige fehler und unklarheiten in diesem text! irgendwie komm ich in letzter zeit zu selten zum schlafen...---
lg
we
-
es wäre toll, wenn du die Umsetzung von CreateCompatibleDC() + CreateCompatibleBitmap() + BitBlt() + GetDIBits() postest, damit andere sehen, wie dus nun gemacht hast
-
mein sourcecode zum pixelauslesen und in einen string schreiben ist folgender:
//includes - windows.h nicht vergessen..//in diese struktur kommen die ganzen handler und daten von dem fenster, dessen
//name im programm in dem char-array windowname steht.
struct Parameter
{
RECT rect;
HWND g_hWnd;
HDC hDC;
HDC hDC2;
HBITMAP hBM;
HBITMAP hBMOld;
BITMAPINFO bmi;
BYTE *pbBits;
struct set *mSet;
};//eine struktur die höhe, breite und alle pixel eines bildes enthält
struct set
{
int sWidth;
int sHeight;
RGBTRIPLE *sPx;
};struct Parameter *param;
param = (struct Parametermalloc(sizeof(struct Parameter));
param->g_hWnd = FindWindow(NULL, windowname); //windowhandler
if (param->g_hWnd == NULL)
{
exit(EXIT_FAILURE);
}
GetWindowRect(param->g_hWnd,¶m->rect); //rect==koordinaten des fensters am bildschirm
param->mSet->sWidth = param->rect.right - param->rect.left;
param->mSet->sHeight = param->rect.bottom - param->rect.top;
param->hDC=GetDC(NULL);
param->hDC2 = CreateCompatibleDC(param->hDC);
param->hBM = CreateCompatibleBitmap(param->hDC, param->mSet->sWidth, param->mSet->sHeight);
param->hBMOld = (HBITMAP)SelectObject(param->hDC2, param->hBM);
BitBlt(param->hDC2, 0, 0, param->mSet->sWidth, param->mSet->sHeight, param->hDC, param->rect.left, param->rect.top, SRCCOPY);ZeroMemory(¶m->bmi, sizeof(param->bmi));
param->bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
param->bmi.bmiHeader.biWidth = param->mSet->sWidth;
param->bmi.bmiHeader.biHeight = param->mSet->sHeight;
param->bmi.bmiHeader.biBitCount = 24;
param->bmi.bmiHeader.biPlanes = 1;
param->bmi.bmiHeader.biCompression = BI_RGB;
param->bmi.bmiHeader.biSizeImage = param->mSet->sWidth * param->mSet->sHeight * 3;param->pbBits = malloc(sizeof(BYTE[param->bmi.bmiHeader.biSizeImage]));
GetDIBits( param->hDC2, param->hBM, 0, param->bmi.bmiHeader.biHeight, param->pbBits, ¶m->bmi, DIB_RGB_COLORS );
param->mSet->sPx = (RGBTRIPLE *)(param->pbBits);//hoffe das hilft soweit...