AutoHotkey Community

It is currently May 27th, 2012, 8:15 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 10 posts ] 
Author Message
 Post subject: Gdip_ImageSearch
PostPosted: September 6th, 2011, 5:29 pm 
Offline

Joined: April 22nd, 2007, 6:33 pm
Posts: 1833
I'm putting this here as it continually gets lost in the GDI+ thread. This is still a work in progress so can't be included in the library. Further testing is needed as there are still problems with it. There are 2 parts that everything needs to be tested with; with variation and without.

Bugs:
  • With variation, a no match takes a long time to complete
  • It has been reported that w and h paramteres work on neither


Code:
Gdip_ImageSearch(pBitmapHayStack, pBitmapNeedle, ByRef x, ByRef y, Variation=0, sx="", sy="", w="", h="")
{
   static _ImageSearch1, _ImageSearch2
   if !_ImageSearch1
   {
      MCode_ImageSearch1 := "83EC108B44242C9983E20303C28BC88B4424309983E20303C253C1F80255894424148B44244056C1F9023B44244C578944244"
      . "80F8DCA0000008B7C24348D148D000000000FAFC88B442444895424148B54242403C88D1C8A8B4C244C895C24183BC1894424407D7A895C24108D6424"
      . "008B6C2428C744243C000000008D6424008B44243C3B4424380F8D9400000033C985FF7E178BD58BF38B063B02752283C10183C20483C6043BCF7CED8"
      . "B44241C035C24148344243C0103C003C003E8EBC08B4424408B5C24108B4C244C83C00183C3043BC189442440895C24107C928B4424448B5424488B5C"
      . "2418035C241483C2013B54245089542448895C24180F8C5DFFFFFF8B5424548B4424585F5EC702FFFFFFFF5DC700FFFFFFFF83C8FF5B83C410C38B4C2"
      . "4548B5424408B4424585F89118B4C24445E5D890833C05B83C410C3"

      VarSetCapacity(_ImageSearch1, StrLen(MCode_ImageSearch1)//2)
      Loop % StrLen(MCode_ImageSearch1)//2      ;%
         NumPut("0x" SubStr(MCode_ImageSearch1, (2*A_Index)-1, 2), _ImageSearch1, A_Index-1, "char")
   }

   if !_ImageSearch2
   {
      MCode_ImageSearch2 :="83EC1C8B4424443B44244C535556578944241C0F8D760100008B4C24488B5424580FAFC88B4424608B742440894C24188B4C24"
      . "503BCA894C24140F8D320100008B54241833FF897C24108B5C24103B5C2444897C2428895424240F8D4E01000085F6C7442420000000000F8ECD00000"
      . "08B7424348D148A8B4C243003F7897424548D1C0AEB0A8DA424000000008D49008B6C2454B9030000000FB60C19BE030000000FB6342E8D2C013BF50F"
      . "8FA20000002BC83BF10F8C980000008B4C24300FB64C0A028B7424340FB67437028D2C013BF57F7F2BC83BF17C798B4C24300FB64C0A018B7424340FB"
      . "67437018D2C013BF57F602BC83BF17C5A0FB60B8B7424540FB6368D2C013BF57F492BC83BF17C438B4C24208B742440834424540483C10183C20483C3"
      . "0483C7043BCE894C24200F8C5BFFFFFF8B4C24148B7C24288B542424035424488344241001037C244CE9F7FEFFFF8B4C24148B5424588B74244083C10"
      . "13BCA894C24140F8CD2FEFFFF8B4C24508B7C241C8B5C2448015C241883C7013B7C245C897C241C0F8CA5FEFFFF8B5424648B4424685F5EC702FFFFFF"
      . "FF5DC700FFFFFFFF83C8FF5B83C41CC38B5424648B4424685F890A8B4C24185E5D890833C05B83C41CC3"

      VarSetCapacity(_ImageSearch2, StrLen(MCode_ImageSearch2)//2)
      Loop % StrLen(MCode_ImageSearch2)//2      ;%
         NumPut("0x" SubStr(MCode_ImageSearch2, (2*A_Index)-1, 2), _ImageSearch2, A_Index-1, "char")
   }
   
   if (Variation > 255 || Variation < 0)
      return -2

   Gdip_GetImageDimensions(pBitmapHayStack, hWidth, hHeight), Gdip_GetImageDimensions(pBitmapNeedle, nWidth, nHeight)
   
   if !(hWidth && hHeight && nWidth && nHeight)
      return -3
   if (nWidth > hWidth || nHeight > hHeight)
      return -4
   
   sx := (sx = "") ? 0 : sx
   sy := (sy = "") ? 0 : sy
   w := (w = "") ? hWidth-sx : w
   h := (h = "") ? hHeight-sy : h
   
   if (sx+w > hWidth-nWidth)
      w := hWidth-sx-nWidth+1
   
   if (sy+h > hHeight-nHeight)
      h := hHeight-sy-nHeight+1
     
   E1 := Gdip_LockBits(pBitmapHayStack, 0, 0, hWidth, hHeight, Stride1, Scan01, BitmapData1)
   E2 := Gdip_LockBits(pBitmapNeedle, 0, 0, nWidth, nHeight, Stride2, Scan02, BitmapData2)
   if (E1 || E2)
      return -5

   x := y := 0
   if (Variation = 0)
   {
      E := DllCall(&_ImageSearch1, "uint", Scan01, "uint", Scan02, "int", hWidth, "int", hHeight, "int", nWidth, "int", nHeight, "int", Stride1
      , "int", Stride2, "int", sx, "int", sy, "int", w, "int", h, "int*", x, "int*", y)
   }
   else
   {
      E := DllCall(&_ImageSearch2, "uint", Scan01, "uint", Scan02, "int", hWidth, "int", hHeight, "int", nWidth, "int", nHeight, "int", Stride1
      , "int", Stride2, "int", sx, "int", sy, "int", w, "int", h, "int", Variation, "int*", x, "int*", y)
   }
   Gdip_UnlockBits(pBitmapHayStack, BitmapData1), Gdip_UnlockBits(pBitmapNeedle, BitmapData2)
   return (E = "") ? -6 : E
}


Code:
int Gdip_ImageSearch1(unsigned int * HayStack, unsigned int * Needle, int w1, int h1, int w2, int h2, int Stride1, int Stride2, int sx, int sy, int w, int h, int * x, int * y)
{
   int tx, ty;
   int offset1 = Stride1/4, offset2 = Stride2/4;
   for (int y1 = sy; y1 < h; ++y1)
   {
      for (int x1 = sx; x1 < w; ++x1)
      {
         ty = y1;
         for (int y2 = 0; y2 < h2; ++y2)
         {
            tx = x1;
            for (int x2 = 0; x2 < w2; ++x2)
            {
               if (HayStack[tx+(ty*offset1)] != Needle[x2+(y2*offset2)])
                  goto NoMatch;
               tx++;
            }
            ty++;
         }
         x[0] = x1; y[0] = y1;
         return 0;
         NoMatch:
         continue;
      }
   }
   x[0] = -1; y[0] = -1;
   return -1;
}


Code:
int Gdip_ImageSearch2(unsigned char * HayStack, unsigned char * Needle, int w1, int h1, int w2, int h2, int Stride1, int Stride2, int sx, int sy, int w, int h, int v, int * x, int * y)
{
   int tx, ty, ph, pn, Ah, Rh, Gh, Bh, An, Rn, Gn, Bn;
   for (int y1 = sy; y1 < h; ++y1)
   {
      for (int x1 = sx; x1 < w; ++x1)
      {
         ty = y1;
         for (int y2 = 0; y2 < h2; ++y2)
         {
            tx = x1;
            for (int x2 = 0; x2 < w2; ++x2)
            {
               ph = (4*tx)+(ty*Stride1);
               pn = (4*x2)+(y2*Stride2);

               Ah = HayStack[3+ph]; An = Needle[3+pn];
               if (An > Ah+v || An < Ah-v) goto NoMatch;

               Rh = HayStack[2+ph]; Rn = Needle[2+pn];
               if (Rn > Rh+v || Rn < Rh-v) goto NoMatch;

               Gh = HayStack[1+ph]; Gn = Needle[1+pn];
               if (Gn > Gh+v || Gn < Gh-v) goto NoMatch;

               Bh = HayStack[ph]; Bn = Needle[pn];
               if (Bn > Bh+v || Bn < Bh-v) goto NoMatch;
               
               tx++;
            }
            ty++;
         }
         x[0] = x1; y[0] = y1;
         return 0;
         NoMatch:
         continue;
      }
   }
   x[0] = -1; y[0] = -1;
   return -1;
}


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: September 9th, 2011, 3:54 pm 
Offline

Joined: May 29th, 2011, 3:06 am
Posts: 85
Hi tic, thanks for posting this, I was never sure when I was using the gdi+ image search what version was working or latest or what.

Would it be possible to also include a parameter to allow a transparent color to be specified, like the *TransN AHK imagesearch option?

The reason I ask is because I have some scripts which use pngs where RGB:FF00FF is the transparent color, and I'd like to at some point add some features which would require doing these searches on GDI bitmaps instead. I know you can make pngs which have real transparency encoded, but neither MSPaint nor the PaintShopPro version I have can save them like this, so it's convenient to just use pink. Or maybe it would be more appropriate to run some sort of image processing function to set a color in the gdi bitmap transparent prior to searching - I don't know. Sorry if this has already been requested/discussed, but I thought I'd mention it, since it would make it more easily interchangeable with the AHK imagesearch, if you could specify a transparent color. Thanks.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: September 16th, 2011, 2:14 am 
this looks so complicate,
im quite new to autohotkey,
can someone explain allittle about how to use this script , such as an example


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: September 16th, 2011, 8:31 am 
Offline

Joined: February 7th, 2008, 9:48 pm
Posts: 509
imagy wrote:
is it possible to take a screenshot of the background window, and then use 'imagesearch' to find the coodinate

in another word, can i imagesearch on a picture-file instead of the screen



Code:
#SingleInstance, Force
#NoEnv
SetBatchLines, -1

#include gdip.ahk   ; download from here http://www.autohotkey.com/forum/topic32238.html


If !pToken := Gdip_Startup()
{
   MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
   ExitApp
}

file1=e:\imagetosearch_for.png      ;filepath to image to search in image
file2=e:\imagetosearch_in.png       ;filepath to imagefile


pBitmapneedle:=Gdip_CreateBitmapFromFile(file1)
pBitmapHaystack:=Gdip_CreateBitmapFromFile(file2)

Gdip_ImageSearch( pBitmapHayStack,pBitmapNeedle,  x,  y)


msgbox x coord =%x% y coord= %y%




Gdip_DisposeImage(pBitmaphaystack)
Gdip_DisposeImage(pBitmapneedle)
Gdip_Shutdown(pToken)
ExitApp




Gdip_ImageSearch(pBitmapHayStack, pBitmapNeedle, ByRef x, ByRef y, Variation=0, sx="", sy="", w="", h="")
{
   static _ImageSearch1, _ImageSearch2
   if !_ImageSearch1
   {
      MCode_ImageSearch1 := "83EC108B44242C9983E20303C28BC88B4424309983E20303C253C1F80255894424148B44244056C1F9023B44244C578944244"
      . "80F8DCA0000008B7C24348D148D000000000FAFC88B442444895424148B54242403C88D1C8A8B4C244C895C24183BC1894424407D7A895C24108D6424"
      . "008B6C2428C744243C000000008D6424008B44243C3B4424380F8D9400000033C985FF7E178BD58BF38B063B02752283C10183C20483C6043BCF7CED8"
      . "B44241C035C24148344243C0103C003C003E8EBC08B4424408B5C24108B4C244C83C00183C3043BC189442440895C24107C928B4424448B5424488B5C"
      . "2418035C241483C2013B54245089542448895C24180F8C5DFFFFFF8B5424548B4424585F5EC702FFFFFFFF5DC700FFFFFFFF83C8FF5B83C410C38B4C2"
      . "4548B5424408B4424585F89118B4C24445E5D890833C05B83C410C3"

      VarSetCapacity(_ImageSearch1, StrLen(MCode_ImageSearch1)//2)
      Loop % StrLen(MCode_ImageSearch1)//2      ;%
         NumPut("0x" SubStr(MCode_ImageSearch1, (2*A_Index)-1, 2), _ImageSearch1, A_Index-1, "char")
   }

   if !_ImageSearch2
   {
      MCode_ImageSearch2 :="83EC1C8B4424443B44244C535556578944241C0F8D760100008B4C24488B5424580FAFC88B4424608B742440894C24188B4C24"
      . "503BCA894C24140F8D320100008B54241833FF897C24108B5C24103B5C2444897C2428895424240F8D4E01000085F6C7442420000000000F8ECD00000"
      . "08B7424348D148A8B4C243003F7897424548D1C0AEB0A8DA424000000008D49008B6C2454B9030000000FB60C19BE030000000FB6342E8D2C013BF50F"
      . "8FA20000002BC83BF10F8C980000008B4C24300FB64C0A028B7424340FB67437028D2C013BF57F7F2BC83BF17C798B4C24300FB64C0A018B7424340FB"
      . "67437018D2C013BF57F602BC83BF17C5A0FB60B8B7424540FB6368D2C013BF57F492BC83BF17C438B4C24208B742440834424540483C10183C20483C3"
      . "0483C7043BCE894C24200F8C5BFFFFFF8B4C24148B7C24288B542424035424488344241001037C244CE9F7FEFFFF8B4C24148B5424588B74244083C10"
      . "13BCA894C24140F8CD2FEFFFF8B4C24508B7C241C8B5C2448015C241883C7013B7C245C897C241C0F8CA5FEFFFF8B5424648B4424685F5EC702FFFFFF"
      . "FF5DC700FFFFFFFF83C8FF5B83C41CC38B5424648B4424685F890A8B4C24185E5D890833C05B83C41CC3"

      VarSetCapacity(_ImageSearch2, StrLen(MCode_ImageSearch2)//2)
      Loop % StrLen(MCode_ImageSearch2)//2      ;%
         NumPut("0x" SubStr(MCode_ImageSearch2, (2*A_Index)-1, 2), _ImageSearch2, A_Index-1, "char")
   }
   
   if (Variation > 255 || Variation < 0)
      return -2

   Gdip_GetImageDimensions(pBitmapHayStack, hWidth, hHeight), Gdip_GetImageDimensions(pBitmapNeedle, nWidth, nHeight)
   
   if !(hWidth && hHeight && nWidth && nHeight)
      return -3
   if (nWidth > hWidth || nHeight > hHeight)
      return -4
   
   sx := (sx = "") ? 0 : sx
   sy := (sy = "") ? 0 : sy
   w := (w = "") ? hWidth-sx : w
   h := (h = "") ? hHeight-sy : h
   
   if (sx+w > hWidth-nWidth)
      w := hWidth-sx-nWidth+1
   
   if (sy+h > hHeight-nHeight)
      h := hHeight-sy-nHeight+1
     
   E1 := Gdip_LockBits(pBitmapHayStack, 0, 0, hWidth, hHeight, Stride1, Scan01, BitmapData1)
   E2 := Gdip_LockBits(pBitmapNeedle, 0, 0, nWidth, nHeight, Stride2, Scan02, BitmapData2)
   if (E1 || E2)
      return -5

   x := y := 0
   if (Variation = 0)
   {
      E := DllCall(&_ImageSearch1, "uint", Scan01, "uint", Scan02, "int", hWidth, "int", hHeight, "int", nWidth, "int", nHeight, "int", Stride1
      , "int", Stride2, "int", sx, "int", sy, "int", w, "int", h, "int*", x, "int*", y)
   }
   else
   {
      E := DllCall(&_ImageSearch2, "uint", Scan01, "uint", Scan02, "int", hWidth, "int", hHeight, "int", nWidth, "int", nHeight, "int", Stride1
      , "int", Stride2, "int", sx, "int", sy, "int", w, "int", h, "int", Variation, "int*", x, "int*", y)
   }
   Gdip_UnlockBits(pBitmapHayStack, BitmapData1), Gdip_UnlockBits(pBitmapNeedle, BitmapData2)
   return (E = "") ? -6 : E
}


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 22nd, 2011, 9:34 am 
Offline

Joined: August 3rd, 2011, 11:39 am
Posts: 22
Iggy_ wrote:
Would it be possible to also include a parameter to allow a transparent color to be specified, like the *TransN AHK imagesearch option?

Seconded. For me, having transparency is a must have.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 4th, 2011, 2:33 pm 
I added the first code you posted into the GDIP.ahk but only received an error level of -6 with the code below:-

Code:
pToken := Gdip_Startup()

file1:="Location of Haystack" ;specific to your file location
file2:="Location of needle" ;specific to your file location

my_haystack := Gdip_CreateBitmapFromFile(File1)
my_needle := Gdip_CreateBitmapFromFile(File2)

F4::
;if !Gdip_ImageSearch(pBitmapHayStack, pBitmapNeedle, x, y)
;   MsgBox, %x%`n%y%
MsgBox % Gdip_ImageSearch(my_haystack, my_needle, FoundX, FoundY)
Return

Gdip_ShutDown(pToken)


Report this post
Top
  
Reply with quote  
PostPosted: December 23rd, 2011, 2:23 am 
The above code with Gdip_CreateBitmapFromFile, doesnot work for me.

Same image search is successful for Gdip_BitmapFromScreen.

Can anyone please advise, if it imagesearch can work on file?


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: January 17th, 2012, 11:02 pm 
Offline

Joined: April 22nd, 2007, 6:33 pm
Posts: 1833
Are either of you running this on x64 ahk as that could provide an error level -6

swades wrote:
The above code with Gdip_CreateBitmapFromFile, doesnot work for me.

Same image search is successful for Gdip_BitmapFromScreen.

Can anyone please advise, if it imagesearch can work on file?


Are the files jpgs that you are using? Are you sure that 1 file is definitely within the other file? Please provide both images


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 18th, 2012, 7:09 pm 
Offline

Joined: October 11th, 2010, 12:30 pm
Posts: 406
Hi tic Another thread you mention that fastPixelGetColor would be thousands times faster with machine code. Would you please post such an example script? I saw your image search script with machine code so you must know how to do that.

_________________
My Scripts
Ain’t No Shame in Asking for Help!


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: April 3rd, 2012, 9:16 pm 
Offline

Joined: April 22nd, 2007, 6:33 pm
Posts: 1833
Hi kenn

I don't want to turn this thread into a general question thread, but should only relate to Image Searching to help bug test the function in the first post.

Simple pixel searching for 1 pixel will look like

Code:
int Gdip_PixelSearch(unsigned int * HayStack, int w, int h, int Stride, int ARGB, int * x, int * y)
{
   int offset = Stride/4;
   for (int y1 = 0; y1 < h; ++y1)
   {
      for (int x1 = 0; x1 < w; ++x1)
      {
         if (HayStack[x1+y1*offset] == ARGB)
         {
            x[0] = x1; y[0] = y1;
            return 0;
         }
      }
   }
   x[0] = -1; y[0] = -1;
   return -1;
}


Although this is not the speed I was talking of. The speed I was talking of would come into effect if you tried for example to find all the x,y coordinates of every pixel on the screen that matches a certain colour, as then it could return all of them in an array and only run through the code once. The only difference would be that ByRefs x and y would need to have the appropriate size for VarSetCapacity and the c++ function would dump the results into this "array"

Hope this helps a bit. Don't reply in this thread please. Thanks!


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 10 posts ] 

All times are UTC [ DST ]


Who is online

Users browsing this forum: Aravind, Google Feedfetcher, Stigg and 12 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group