C/C++ PixelSearch autoit en c++

ToOnS

Membre Actif
Inscrit
8 Avril 2009
Messages
974
Reactions
0
#21
ah oui j'oubliais y'a autoit dans le titre ... merci FF
Code:
#include <windows.h>
#include <stdio.h>

// Some macro's to help people out
#define ARGB_TO_COLORREF(a)		(COLORREF)(((a) & 0xFF00FF00) | (((a) & 0xFF0000) >> 16) | (((a) & 0xFF) << 16)) // ARGB to ABGR
#define BitmapPixel(b, x, y)	((b)->pixels[(y) * (b)->width + (x)]) // pixel is ARGB
#define GetAValue(cr)			(int)((cr) >> 24)
#define ColorNoAlpha(p)			((p) & 0x00FFFFFF)

typedef struct _BITMAPCAPTURE {
	HBITMAP hbm;
	LPDWORD pixels;
	INT     width;
	INT     height;
} BITMAPCAPTURE;

BOOL CaptureScreen(BITMAPCAPTURE *bmpCapture) // by Napalm
{
	BOOL bResult = FALSE;
	if(!bmpCapture)
		return bResult;
	
	ZeroMemory(bmpCapture, sizeof(BITMAPCAPTURE));
	
    HDC hdcScreen  = GetDC(NULL);
	HDC hdcCapture = CreateCompatibleDC(NULL);
	int nWidth     = GetSystemMetrics(SM_CXVIRTUALSCREEN),
	    nHeight    = GetSystemMetrics(SM_CYVIRTUALSCREEN);
	
	// Bitmap is stored top down as BGRA,BGRA,BGRA when used as
	// DWORDs endianess would change it to ARGB.. windows COLORREF is ABGR
	LPBYTE lpCapture;
	BITMAPINFO bmiCapture = { {
		sizeof(BITMAPINFOHEADER), nWidth, -nHeight, 1, 32, BI_RGB, 0, 0, 0, 0, 0,
	} };
	
	bmpCapture->hbm = CreateDIBSection(hdcScreen, &bmiCapture,
		DIB_RGB_COLORS, (LPVOID *)&lpCapture, NULL, 0);
	if(bmpCapture->hbm){
		HBITMAP hbmOld = (HBITMAP)SelectObject(hdcCapture, bmpCapture->hbm);
		BitBlt(hdcCapture, 0, 0, nWidth, nHeight, hdcScreen, 0, 0, SRCCOPY);
		SelectObject(hdcCapture, hbmOld);
		bmpCapture->pixels = (LPDWORD)lpCapture;
		bmpCapture->width  = nWidth;
		bmpCapture->height = nHeight;
		bResult = TRUE;
	}
	
	DeleteDC(hdcCapture);
	DeleteDC(hdcScreen);
	return bResult;
}

// looking for a pixel color that can never exist, but scans all pixels
void YourOriginalMethod()
{
    int x = 0, y = 0;
    HDC hDC = GetDC(HWND_DESKTOP);
    int Sx = GetSystemMetrics(SM_CXVIRTUALSCREEN);
    int Sy = GetSystemMetrics(SM_CYVIRTUALSCREEN);
    while(1)
    {
		COLORREF rgb = GetPixel(hDC, x, y);
		int r = GetRValue(rgb);
		int g = GetGValue(rgb);
		int b = GetBValue(rgb);
		if(r == 256){
			break;
		}
		if(g == 256){
			break;
		}
		if(b == 256){
			break;
		}
		x++;
		if(x >= Sx){
			x = 0;
			y++;
		}
		if(y >= Sy){
			break;
		}
    }
	ReleaseDC(HWND_DESKTOP, hDC);
}

// same as above but uses bitmap cache
void YourMethodWithCache(BITMAPCAPTURE *grab)
{
	int x = 0, y = 0;
    while(1)
    {
		COLORREF rgb = ARGB_TO_COLORREF(BitmapPixel(grab, x, y));
		int r = GetRValue(rgb);
		int g = GetGValue(rgb);
		int b = GetBValue(rgb);
		if(r == 256){
			break;
		}
		if(g == 256){
			break;
		}
		if(b == 256){
			break;
		}
		x++;
		if(x >= grab->width){
			x = 0;
			y++;
		}
		if(y >= grab->height){
			break;
		}
    }
}

// scans all pixels and report first one found
void NormalMethod(BITMAPCAPTURE *grab, DWORD pixel_color)
{
	int x, y, rx, ry, c, found;
	found = 0;
	for(y = 0; y < grab->height; y++){
		for(x = 0; x < grab->width; x++){
			if(ColorNoAlpha(BitmapPixel(grab, x, y)) == pixel_color){
				if(!found){
					rx = x;
					ry = y;
					found = 1;
				}
			}
		}
	}
	if(found)
		printf("found first 0x%08X pixel at (%d, %d)\n", pixel_color, rx, ry);

}

// scan only the pixels needed and reports
void FastMethod(BITMAPCAPTURE *grab, DWORD pixel_color)
{
	int x, y, rx, ry, c, found;
	found = 0;
	for(y = 0; y < grab->height && !found; y++){
		for(x = 0; x < grab->width && !found; x++){
			if(ColorNoAlpha(BitmapPixel(grab, x, y)) == pixel_color)
				found = 1;
		}
	}
	if(found)
		printf("found first 0x%08X pixel at (%d, %d)\n", pixel_color, --x, --y);
}

// My uber method
void NapalmsSuperMegaFastMethod(BITMAPCAPTURE *grab, DWORD dwPixelColor)
{
	DWORD dwPos = 0, dwMax = (grab->width * grab->height);
	while(dwPos < dwMax){
		if(ColorNoAlpha(grab->pixels[dwPos]) == dwPixelColor)
			break;
		dwPos++;
	}
	if(dwPos < dwMax)
		printf("found first 0x%08X pixel at (%d, %d)\n", dwPixelColor,
			(dwPos % grab->width), (dwPos / grab->width));
}



typedef struct _CODESPEED {
	LARGE_INTEGER s, e, f, o;
} CODESPEED;

inline BOOL StartCodeSpeed(CODESPEED *cs) // by Napalm
{
	ZeroMemory(cs, sizeof(CODESPEED));
	if(!QueryPerformanceFrequency(&cs->f))
		return FALSE;
	QueryPerformanceCounter(&cs->s);
	QueryPerformanceCounter(&cs->e);
	cs->o.QuadPart = (cs->e.QuadPart - cs->s.QuadPart);
	QueryPerformanceCounter(&cs->s);
	return TRUE;
}

inline VOID EndCodeSpeed(CODESPEED *cs) // by Napalm
{
	QueryPerformanceCounter(&cs->e);
}

LPCSTR GetCodeSpeed(CODESPEED *cs) // by Napalm
{
	static CHAR szBuffer[512];
	LPCSTR lpcszTime[5] = { "seconds", "ms", "us", "ns" };
	double dResult = (cs->e.QuadPart - cs->s.QuadPart - cs->o.QuadPart),
		dFreq = (double)cs->f.QuadPart;
	
	strcpy(szBuffer, "<1 ns");
	for(int i = 1; i < 5 && dFreq > 0; i++){
		if((int)(dResult / dFreq) > 0){
			dResult = (dResult * i) / (dFreq * i);
			sprintf(szBuffer, "%.5g %s\n", dResult, lpcszTime[i - 1]);
			break;
		}
		dFreq /= 1000.0f;
	}
	
	return (LPCSTR)szBuffer;
}


int main(int argc, char *argv[])
{
	CODESPEED cs;
	BITMAPCAPTURE grab;
	DWORD dwWhiteColor = 0x00FFFFFF; // ARGB
	
	if(!CaptureScreen(&grab)){
		printf("error: grabbing screen.\n");
		return 1;
	}
	
	StartCodeSpeed(&cs);
	printf("Machine is running at %.4gGHz\n", (((double)cs.f.QuadPart / 1000.0f) / 1000.0f));
	printf("Each method scans %u pixels!\n\n", grab.width * grab.height);
	
	StartCodeSpeed(&cs);
	YourOriginalMethod();
	EndCodeSpeed(&cs);
	printf("YourMethod took %s\n", GetCodeSpeed(&cs));
	
	StartCodeSpeed(&cs);
	YourMethodWithCache(&grab);
	EndCodeSpeed(&cs);
	printf("YourMethod took %s\n", GetCodeSpeed(&cs));
	
	StartCodeSpeed(&cs);
	NormalMethod(&grab, dwWhiteColor);
	EndCodeSpeed(&cs);
	printf("NormalMethod took %s\n", GetCodeSpeed(&cs));
	
	StartCodeSpeed(&cs);
	FastMethod(&grab, dwWhiteColor);
	EndCodeSpeed(&cs);
	printf("FastMethod took %s\n", GetCodeSpeed(&cs));
	
	StartCodeSpeed(&cs);
	NapalmsSuperMegaFastMethod(&grab, dwWhiteColor);
	EndCodeSpeed(&cs);
	printf("NapalmsSuperMegaFastMethod took %s\n", GetCodeSpeed(&cs));
	
	DeleteObject(grab.hbm);
	return 0;
}
je sais plus trop d'ou ca vien , surement de google
 
Inscrit
15 Avril 2011
Messages
457
Reactions
1
#22
Non, en fait je me suis gourré, c'est parce que j'ai mis un cout à chaque boucle, je pensais pas que ça prenait du temps. Finalement, j'ai refait, ça met que 18 ms, c'est mieux :p




PS: N'empêche que j'aimerais quand même intégrer les fonctions AutoIt dans mon code C++, je ne sais toujours pas comment résoudre le problème :(

Quand j'utilise PixelSearch, j'ai le message d'erreur suivant : "undefined reference to 'AU3_PixelSearch@32'".
Quand j'utilise PixelGetColor, j'ai le message d'erreur suivant : "undefined reference to 'AU3_PixelGetColor@8'".
A mon avis, c'est un problème de lecture de la DLL, mais je n'y connais rien...
 

FastFrench

Membre Actif
Inscrit
19 Octobre 2010
Messages
214
Reactions
0
#23
@ToOnS : ça semble plus complet ainsi. Ca reste optimisable, mais c'est pas mal. A noter cependant que les temps affichés sont biaisés (en toute rigueur, ils devraient intégrer le temps de capture).

Un petit défi : qui se sent d'attaque pour optimiser NapalmsSuperMegaFastMethod ?
 
Inscrit
15 Avril 2011
Messages
457
Reactions
1
#24
Code:
bool Paysan::recherche_cereale()
{
    int x1=330;
    int y1=60;
    int x2=1270;
    int y2=710;
    HDC hdc;
    COLORREF test;
    for (x1;x1<x2;x1++)
    {
        y1=60;
        for (y1;y1<y2;y1++)
        {
            test=GetPixel(hdc,x1,y1);
        }
    }
    //m_cereale_x=
    //m_cereale_y=
    return 0;
}

Maintenant, j'ai le même problème, mais avec GetPixel, c'est bizarre, c'est pas une fonction d'AutoIt.

Erreur : undefined reference to 'GetPixel@12'.
 
A

Anonymous

Invité
#25
il faut inclure la libgdi32.a à ton projet.
 
Inscrit
15 Avril 2011
Messages
457
Reactions
1
#26
Ouais, c'est bon j'ai réussi, mais GetPixel me retourne un DWORD et j'aimerais le convertir en hexa.
De plus, je crois que j'ai aussi un problème avec le handle, car GetPixel me retourne toujours la même valeur, comment puis-je mettre l'écran entier par défaut ?


PS : Maintenant, lorsque j'aurais une erreur du type "undefined reference to @fonction" je saurais que ça vient d'un fichier .a non linké ;)
 
Haut Bas