Pixelsuche, TBitmap mit Scanline
-
Hallo, liebe Community.
Ich möchte, dass mein Programm überprüft ob sich eine bestimmte Farbe sich irgendwo auf dem Bildschirm befindet.
Ich habe dafür einen Timer erstellt und das hier reingepackt:if(screen==1) { dc = GetDC(NULL); hBitmap = CreateCompatibleBitmap(dc, iSizeW, iSizeH); bmp->Height=iSizeH; bmp->Width=iSizeW; bmp->Handle=hBitmap; bmp->PixelFormat=pf32bit; screen=0; } ypix = reinterpret_cast<TRGBTriple *>(bmp->ScanLine[scany]); scanx++; if(scanx < bmp->Width) { scany++; scanx = 0; } if(scany < bmp->Height) { scany = 0; scanx = 0; } if(ypix->rgbtBlue == 215 && ypix->rgbtGreen==38 && ypix->rgbtRed ==255) { MessageBox(0,"Gefunden","test1",MB_OK); screen=1; } if(screen==1) { ReleaseDC(0,dc); }
Wenn ich jetzt das Programm mit dem debugger starte kommt eine Fehlermeldung nach dem Programmstart:
Im Projekt xxx.exe ist eine Exception der Klasse EInvalidGraphicOperation mit der Meldung "Bereichsüberschreitung bei Zeilenindex" aufgetreten.
Kann mir vielleicht jemand bitte sagen was ich falsch gemacht habe?
mfg
Igromanru
-
schonmal die Bitmap einem TImage zugewiesen um zu schauen, ob du wirklich einen Screenshot gemacht hast und das Bild nicht leer ist? Weil in deinem Code wird bisher kein Screenshot gemacht.
greetz KN4CK3R
-
Also ich habe das Problem gefunden wieso der Fehler kam.^^
Ich habe nämlich ausversehen screen als 0 deklariert.int screen = 0;
Aber sonst hast du recht, es kommt nur ein schwarzes Bild raus.
Hab nicht ganz kapiert wie man ein screenshot macht. Muss nochmal nachschauen, oder kann mir vielleicht jemand hier schreiben wie man es am besten macht?EDIT: Weil ich finde ganze Zeit wie man ein screenshot Speichert, da hab ich bis jetzt nicht richtig verstanden welcher Teil zum screenshot erstellen gehört.
Beispiel: Link
-
Hallo,
Dann schau mal in die FAQ unter Screenshot
http://www.c-plusplus.net/forum/viewtopic-var-t-is-39305-and-start-is-0-and-postdays-is-0-and-postorder-is-asc-and-highlight-is-.html
-
Deine beiden Abfragen sind falsch herum:
if(scanx >= bmp->Width) if(scany >= bmp->Height)
Außerdem solltest du vorher 'scanx' auf 0 setzen und auch 'ypix' um 1 erhöhen (sonst liest du immer den ersten Pixel jeder Zeile -) ...
Und irgendwie fehlt da auch noch die eigentliche Schleife, um alle Zeilen (scany) und Spalten(scanx) durchzugehen (oder willst du wirklich im Timer nur jeweils einen Pixel überprüfen? Bei kleinstem Timerwert von ca. 15ms und einem Bild der Größe 1024*768 wären das dann ca. 11800s = 196min = 3h 16min
)
-
Braunstein schrieb:
Hallo,
Dann schau mal in die FAQ unter Screenshot
http://www.c-plusplus.net/forum/viewtopic-var-t-is-39305-and-start-is-0-and-postdays-is-0-and-postorder-is-asc-and-highlight-is-.htmlIch habe die "Version 1" unter screenshots schon mal gesehn, deshalb hab ich es auch so aufgebaut.
Ich habe jetzt so gemacht:dc = GetDC(NULL); hBitmap = CreateCompatibleBitmap(dc, iSizeW, iSizeH); bmp->PixelFormat=pf24bit; bmp->Handle=hBitmap; Image1->Picture->Assign(bmp); ypix = reinterpret_cast<TRGBTriple *>(bmp->ScanLine[scany]); scanx++; if(scanx < bmp->Width) { scany++; scanx = 0; } if(scany < bmp->Height) { scany = 0; scanx = 0; } if(ypix->rgbtBlue == 215 && ypix->rgbtGreen==38 && ypix->rgbtRed ==255) { MessageBox(0,"Gefunden","test1",MB_OK); screen=1; } ReleaseDC(0,dc);
Aber bei Image1 wird trotzdem nur schwatzes Bild.
EDIT:
Th69 schrieb:
Deine beiden Abfragen sind falsch herum:
if(scanx >= bmp->Width) if(scany >= bmp->Height)
Außerdem solltest du vorher 'scanx' auf 0 setzen und auch 'ypix' um 1 erhöhen (sonst liest du immer den ersten Pixel jeder Zeile -) ...
Und irgendwie fehlt da auch noch die eigentliche Schleife, um alle Zeilen (scany) und Spalten(scanx) durchzugehen (oder willst du wirklich im Timer nur jeweils einen Pixel überprüfen? Bei kleinstem Timerwert von ca. 15ms und einem Bild der Größe 1024*768 wären das dann ca. 11800s = 196min = 3h 16min
)
Danke, ich werde später einen neuen Thread erstellen. Das Problem jetzt ist, dass kein screenshot gemacht wird.
-
hast du dich hier
[url]c = GetDC(NULL); [/url]
nur verschrieben? Im weiteren Verlauf verwendest du dc.
-
Braunstein schrieb:
hast du dich hier
[url]c = GetDC(NULL); [/url]
nur verschrieben? Im weiteren Verlauf verwendest du dc.Ja, verschrieben, sonst würde ja der gebugger dabei meckern.
-
die Version 1 in den FAQs sieht auch anders aus wie deine Version...
greetz KN4CK3R
-
Nicht ganz.
Bei der Version1 steht:HDC HScreenDC = GetDC(0); Image1->Picture->Bitmap->Handle = CreateCompatibleBitmap(HScreenDC, Form1->Width, Form1->Height);
Bei mir steht:
dc = GetDC(NULL); hBitmap = CreateCompatibleBitmap(dc, iSizeW, iSizeH); bmp->Handle=hBitmap; Image1->Picture->Assign(bmp);
Wenn ich es so mache wie dort steht:
hBitmap = CreateCompatibleBitmap(dc, iSizeW, iSizeH); Image1->Picture->Bitmap->Handle=hBitmap;
Kommt auch schwarzes Bild raus.
Und wenn ich genau so wie bei Version 1 mache, kommt auch das selbe.
int result = GetDeviceCaps(dc, RASTERCAPS); if (result & RC_PALETTE) { int palette_size = GetDeviceCaps(dc, SIZEPALETTE); if (palette_size == 256) { const size_t size = sizeof(LOGPALETTE) + 255 * sizeof(PALETTEENTRY); unsigned char* pBuffer = new unsigned char[size]; LPLOGPALETTE lplogpal = reinterpret_cast<LPLOGPALETTE>(pBuffer); lplogpal->palVersion = 0x300; lplogpal->palNumEntries = 256; GetSystemPaletteEntries(dc, 0, 256, lplogpal->palPalEntry); Image1->Picture->Bitmap->Palette = CreatePalette(lplogpal); delete [] pBuffer; } } ReleaseDC(0, dc);
-
igromanru schrieb:
Nicht ganz.
Bei der Version1 steht:HDC HScreenDC = GetDC(0);
Bei mir steht:
dc = GetDC(NULL);
0 und NULL sind nicht das selbe NULL ist nichts und
du willst ja einen Screenshot vom Desptop und der hat das Handel 0.
-
naja, nur dass dir eben noch der wichtige Screenshot Teil fehlt...den willst du offenbar übersehen.
greetz KN4CK3R
-
Hallo
VergissEs schrieb:
0 und NULL sind nicht das selbe NULL ist nichts und
du willst ja einen Screenshot vom Desptop und der hat das Handel 0.Das stimmt nicht, 0 und NULL sind in C++ identisch, in C ist NULL als Zeiger auf 0 definiert. In diesem konkreten Fall mit dem Handle führt jedenfalls beides zum gleichen Ziel : GetDC bekommt einen Zeiger auf 0, denn "0" wird impliziet auf void* gecastet.
Hier die konkrete Implemetation von NULL im Builder aus der Datei _null.h :
#ifndef NULL # if defined(__cplusplus) || defined(_Windows) # define NULL 0 # else # define NULL ((void *)0) # endif #endif
bis bald
akari/edit akari : Korrektur siehe Post von MFK
-
KN4CK3R schrieb:
naja, nur dass dir eben noch der wichtige Screenshot Teil fehlt...den willst du offenbar übersehen.
greetz KN4CK3R
HDC HWindowDC = GetWindowDC(Form1->Handle); BitBlt(Image1->Picture->Bitmap->Canvas->Handle, 0, 0, Image1->Picture->Bitmap->Width, Image1->Picture->Bitmap->Height, HWindowDC, 0, 0, SRCCOPY); ReleaseDC(Form1->Handle, HWindowDC);
Danke.
Ich habe aber noch eine Frage. Ist BitBlt nicht nur um die Bitmap anzeigen zu lassen? Also brauch ich es für die Scanline garnicht?
-
akari schrieb:
0 und NULL sind in C identisch, in C++ ist NULL als Zeiger auf 0 definiert.
Andersrum
-
Könnt ihr bitte bei der Thema bleiben und mir den letzen Tipp geben?^^
Ich habe jetzt so aufgebaut:
int iSizeW = GetSystemMetrics( 0 ); int iSizeH = GetSystemMetrics( 1 ); HDC dc; HDC cdc; HBITMAP hBitmap; int scanx=0, scany=0; TRGBTriple *xpix; TRGBTriple *ypix; DWORD WINAPI ScanFunc( LPVOID lpParam ) { while(1) { if(scanthread==true) { Graphics::TBitmap *bmp = new Graphics::TBitmap(); dc = GetDC(NULL); hBitmap = CreateCompatibleBitmap(dc, iSizeW, iSizeH); bmp->Height=iSizeH; bmp->Width=iSizeW; bmp->PixelFormat=pf24bit; bmp->Handle=hBitmap; for(scanx=0; scanx < bmp->Width; scanx++) { ypix = reinterpret_cast<TRGBTriple *>(bmp->ScanLine[scany]); if(ypix->rgbtBlue == 191 && ypix->rgbtGreen==89 && pix->rgbtRed ==255) { MessageBox(0,"Gefunden","test1",MB_OK); } for(scany=0; scany<bmp->Height; scany++) { } } ReleaseDC(0,dc); ReleaseDC(0,cdc); delete bmp; } Sleep(10); }
Ist es so richtig? Ansonsten fehlt mit der Teil mit BitBlt, den ich nicht ganz verstanden hab. Kann mir vielleicht jemand erklähren? Weiß gerade nicht wie ich es ohne Image1->Picture->Bitmap->Canvas->Handle einsetzen soll.
-
ja der BitBlt Teil ist ja grad der wichtige Teil. BitBlt kopiert die Bilddaten von der Quelle zum Ziel.
greetz KN4CK3R
-
DWORD WINAPI ScanFunc( LPVOID lpParam ) { while(1) { if(scanthread==true) { Graphics::TBitmap *bmp = new Graphics::TBitmap(); dc = GetDC(NULL); hBitmap = CreateCompatibleBitmap(dc, iSizeW, iSizeH); bmp->Height=iSizeH; bmp->Width=iSizeW; bmp->PixelFormat=pf24bit; bmp->Handle=hBitmap; cdc = GetWindowDC(0); BitBlt(bmp->Canvas->Handle, 0, 0, bmp->Width, bmp->Height, cdc, 0, 0, SRCCOPY); for(scanx=0; scanx < bmp->Width; scanx++) { ypix = reinterpret_cast<TRGBTriple *>(bmp->ScanLine[scany]); if(ypix->rgbtBlue == 191 && ypix->rgbtGreen==89 && ypix->rgbtRed ==255) { MessageBox(0,"Gefunden","test1",MB_OK); } for(scany=0; scany<bmp->Height; scany++) { } } ReleaseDC(0,dc); ReleaseDC(0,cdc); delete bmp; } Sleep(10); } }
Wenn ich es richtig verstanden hab, dann muss es so gehen oder?
Das Problem ist, ich kriege beim starten des Threads wieder die Fehlermeldung. Und kann deshalb nicht testen. Aber wieso kommt der Fehler wenn sich diesmal alles normal abläuft?
-
Debugger oder den Teil erstmal auskommentieren und schauen ob dein Screenshot jetzt stimmt.
greetz KN4CK3R
-
Der Fehler wird durch GetDC(0) erzeugt.
Wie soll ich es ohne GetDC(0) testen?EDIT: Einmal hat es geklappt. Hab sogar dann die bmp auf der Image gesehn aber, dann kam gleich eine Fehlemeldung "EOutOfResources... "falsche parameter".