Results 1 to 18 of 18

Thread: [Source] FindColor(Tolerance) using ScanLines

  1. #1
    Join Date
    Feb 2006
    Location
    Belgium
    Posts
    3,137
    Mentioned
    3 Post(s)
    Quoted
    5 Post(s)

    Default [Source] FindColor(Tolerance) using ScanLines

    Well, I notice many people do (no offence) a very newbish thing...
    They use GetPixel for colorfinding functions...
    Of course it works and it's good to learn it, but at a certain point you should move on to better techniques because GetPixel is incredibly slow.
    It has to make an api call for every pixel.

    I've quickly put together a function which uses scanlines.
    A small explanation...
    Colorfunctions that use scanlines get a complete bitmap of the client canvas and then get line by line rows of pixels to find a color in.

    I've tried to comment it so it's clear how everything works and easier to use to make your own functions.
    This is not the best technique, but it's good, fast and reliable.

    SCAR Code:
    function FindColor(var x, y: Integer; Color, xs, ys, xe, ye, Tolerance: Integer; Window: Hwnd): Boolean;
    var
      Bmp: TBitmap; // Bitmap of the client
      tmpDC: HDC; // Device context of the client's window handle
      Size: TRect; // Rect(angle) of the client's window
      cx, cy: Integer; // For-loop vars
      Line: PRGB32Array; // The scanline
    begin
      Result := False; // In case the color isn't found => Result = False
      x := -1; // In case the color isn't found => x = -1
      y := -1; // In case the color isn't found => y = -1
      Bmp := TBitmap.Create; // We create our bitmap instance
      tmpDC := GetWindowDC(Window); // We get the device context of the client's window handle
      GetWindowRect(Window, Size); // We get the rect(angle) of the client's window
      Bmp.Width := Size.Right - Size.Left; // We set the width of our bitmap
      Bmp.Height := Size.Bottom - Size.Top; // We set the height of our bitmap
      BitBlt(Bmp.Canvas.Handle, 0, 0, Bmp.Width, Bmp.Height, tmpDC, 0, 0, SRCCOPY);
      // ^^^ We copy the client's canvas onto the bitmap
      Bmp.PixelFormat := pf32bit; // We set the bitmap to 32bits
      DeleteDC(tmpDC); // We delete the device context to avoid memory leakage
      for cy := ys to ye do // Loop for the rows of pixels (y)
      begin          
        if cy >= Bmp.Height then Break; // Break the loop if you reach the end of the bitmap
        Line := Bmp.ScanLine[cy]; // We retrieve the scanline (line of pixels) from the bitmap for the current y
        for cx := xs to xe do // Loop for the colums of pixels (x)
        begin
          if cx >= Bmp.Width then Break; // Break the loop if you reach the end of the bitmap
          if (SimilarColors(RGB(Line[cx].R, Line[cx].G, Line[cx].B), Color, Tolerance)) then
          // ^^^ We convert the RGB values of the current pixel to a color and compare it with the tolerance to the entered color
          begin // If the color is similar (or for tol 0 the same) then...
            Result := True; // Result of the function
            x := cx; // Returned x-value
            y := cy;  // Returned y-value
            Line := nil; // Free the scanline to avoid memory leaks
            Bmp.Free; // Free the bitmap to avoid memory leaks
            Exit; // Exit the function
          end;
        end;
      end;
      Line := nil; // Free the scanline to avoid memory leaks
      Bmp.Free; // Free the bitmap to avoid memory leaks
    end;

    For this function to work you will need 2 things, the following type declarations:
    SCAR Code:
    type
      TRGB32 = packed record
        B, G, R, A: Byte;
      end;
      TRGB32Array = packed array[0..MaxInt div SizeOf(TRGB32) - 1] of TRGB32;
      PRGB32Array = ^TRGB32Array;

    and the following 2 functions to compare the colors (which can also be found on my site (http://stuart.existhost.com/freddy/productions/ or http://freddy.impsoft.net)
    SCAR Code:
    function ColorRGB(SColor, i: Integer): Extended;
    var
      Color: TColor;
    begin
      Color := ColorToRGB(SColor);
      Result := 0;
      case i of
        1: result := GetRValue(Color);
        2: result := GetGValue(Color);
        3: result := GetBValue(Color);
      end;
    end;

    function SimilarColors(Color1, Color2, Tolerance: Integer): Boolean;
    begin
      Result := False;
      if (Abs(Round(ColorRGB(Color1, 1)) - Round(ColorRGB(Color2, 1))) <= Tolerance) then
        if (Abs(Round(ColorRGB(Color1, 2)) - Round(ColorRGB(Color2, 2))) <= Tolerance) then
          if (Abs(Round(ColorRGB(Color1, 3)) - Round(ColorRGB(Color2, 3))) <= Tolerance) then
            Result := True;
    end;

    I hope you can learn something from this, have fun

    EDIT:
    (And for those who might want to use this for scar... You need to use GetClientWindowHandle in scar to return the selected client window if you didn't know already)

  2. #2
    Join Date
    Mar 2006
    Posts
    3,051
    Mentioned
    1 Post(s)
    Quoted
    0 Post(s)

    Default

    Is this the same thing that is already implemented in SCAR? A lot of those functions look very familiar.

  3. #3
    Join Date
    Feb 2006
    Location
    Belgium
    Posts
    3,137
    Mentioned
    3 Post(s)
    Quoted
    5 Post(s)

    Default

    Meh, the techniques i and scar use are different from this and different from eachother, but... it comes down to the fact that they're fast, this does in like 50-200ms what it'd do with getpixel in 2 seconds or something, getting the bitmap is actually what slows it down the most

  4. #4
    Join Date
    Feb 2006
    Posts
    411
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    it takes 50-200ms to get the clients screen into a array of intergers?
    www.rscheata.net
    Home of iBot on neXus: a multi-client, minimizable, Hyrid, Color, Reflection, scriptable, multi-threaded Java Bot.

  5. #5
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    2,984
    Mentioned
    3 Post(s)
    Quoted
    1 Post(s)

    Default

    Amazing, i can learn a lot from you. Nice site too btw, made it all yourself ?
    Administrator's Warning:


  6. #6
    Join Date
    Feb 2006
    Location
    Belgium
    Posts
    3,137
    Mentioned
    3 Post(s)
    Quoted
    5 Post(s)

    Default

    Quote Originally Posted by ruler View Post
    it takes 50-200ms to get the clients screen into a array of intergers?
    It can go faster, it just depends on ur cpu speed... if you got a slow one then the function will be slower, there's no way around that

    Quote Originally Posted by Sumilion View Post
    Amazing, i can learn a lot from you. Nice site too btw, made it all yourself ?
    Free template

  7. #7
    Join Date
    Feb 2006
    Posts
    411
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    The runescape entire client 702x502 not a entire desktop.
    Takes 50-200ms? to make into a array of intergers?

    by the look of your code, keep in mind i dont know how to run it but.

    iBot takes 15ms to make a short[][][] array.
    and 6ms to do a search with tolerance with no result over entire client screen.

    So estimate is this taking about 80 percent:
    if (SimilarColors(RGB(Line[cx].R, Line[cx].G, Line[cx].B), Color, Tolerance)).

    If one can show me a list of function types and operations avaiable i can optimze it.
    www.rscheata.net
    Home of iBot on neXus: a multi-client, minimizable, Hyrid, Color, Reflection, scriptable, multi-threaded Java Bot.

  8. #8
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    2,984
    Mentioned
    3 Post(s)
    Quoted
    1 Post(s)

    Default

    Quote Originally Posted by Freddy1990 View Post
    Free template
    No offence, but i thought so , otherwise my respect would've grown even more and we wouldnt want that.
    Administrator's Warning:


  9. #9
    Join Date
    Feb 2006
    Location
    Belgium
    Posts
    3,137
    Mentioned
    3 Post(s)
    Quoted
    5 Post(s)

    Default

    Quote Originally Posted by ruler View Post
    The runescape entire client 702x502 not a entire desktop.
    Takes 50-200ms? to make into a array of intergers?
    There are pc's who can run this in under 10ms, as i said, it all depends on cpu speed.

    And well, you could shorten down those 2 functions for the toelrance comparison to this i guess:
    SCAR Code:
    function SimilarColors(Color1, Color2, Tolerance: Integer): Boolean;
    var
      C1, C2: TColor;
    begin
      Result := False;
      C1 := ColorToRGB(Color1);
      C2 := ColorToRGB(Color2);
      if (Abs(Round(GetRValue(C1) - GetRValue(C2))) <= Tolerance) then
        if (Abs(Round(GetGValue(C1) - GetGValue(C2))) <= Tolerance) then
          if (Abs(Round(GetBValue(C1) - GetBValue(C2))) <= Tolerance) then
            Result := True;
    end;

    Makes it a bit faster...
    My pc does this in an average 23.44 ms (Thats for an entire scan without result of the rs window btw)

  10. #10
    Join Date
    Feb 2006
    Posts
    411
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    remove every method call, make it one method.
    www.rscheata.net
    Home of iBot on neXus: a multi-client, minimizable, Hyrid, Color, Reflection, scriptable, multi-threaded Java Bot.

  11. #11
    Join Date
    Feb 2006
    Location
    Belgium
    Posts
    3,137
    Mentioned
    3 Post(s)
    Quoted
    5 Post(s)

    Default

    That doesn't help...

  12. #12
    Join Date
    Feb 2006
    Posts
    411
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    use bit shifts not methods.
    www.rscheata.net
    Home of iBot on neXus: a multi-client, minimizable, Hyrid, Color, Reflection, scriptable, multi-threaded Java Bot.

  13. #13
    Join Date
    Feb 2006
    Posts
    411
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    /**
    *
    * @param color
    * @param type
    * COLOR_TYPE_AWT or COLOR_TYPE_SCAR
    */
    public RGB(int color, int type) {
    if (type == COLOR_TYPE_AWT) {
    r = (short) ((color >> 16) & 0xff);
    g = (short) ((color >> 8) & 0xff);
    b = (short) ((color) & 0xff);
    } else if (type == COLOR_TYPE_SCAR) {
    r = (short) ((color) & 0xff);
    g = (short) ((color >> 8) & 0xff);
    b = (short) ((color >> 16) & 0xff);
    }
    }
    www.rscheata.net
    Home of iBot on neXus: a multi-client, minimizable, Hyrid, Color, Reflection, scriptable, multi-threaded Java Bot.

  14. #14
    Join Date
    Feb 2006
    Location
    Belgium
    Posts
    3,137
    Mentioned
    3 Post(s)
    Quoted
    5 Post(s)

    Default

    Here you go, I haven't tested it, but it should work... happy?
    SCAR Code:
    function SimilarColors(Color1, Color2, Tolerance: Integer): Boolean;
    begin
      Result := False;
      if (Abs((Color1 and $ff) - (Color2 and $ff)) <= Tolerance) then
        if (Abs(((Color1 and $ff00) shr 8) - ((Color2 and $ff00) shr 8)) <= Tolerance) then
          if (Abs(((Color1 and $ff0000) shr 16) - ((Color2 and $ff0000) shr 16)) <= Tolerance) then
            Result := True;
    end;

  15. #15
    Join Date
    Feb 2006
    Posts
    411
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    please speed test
    www.rscheata.net
    Home of iBot on neXus: a multi-client, minimizable, Hyrid, Color, Reflection, scriptable, multi-threaded Java Bot.

  16. #16
    Join Date
    Feb 2006
    Location
    Amsterdam
    Posts
    13,692
    Mentioned
    146 Post(s)
    Quoted
    130 Post(s)

    Default

    Quote Originally Posted by Freddy1990 View Post
    Here you go, I haven't tested it, but it should work... happy?
    SCAR Code:
    function SimilarColors(Color1, Color2, Tolerance: Integer): Boolean;
    begin
      Result := False;
      if (Abs((Color1 and $ff) - (Color2 and $ff)) <= Tolerance) then
        if (Abs(((Color1 and $ff00) shr 8) - ((Color2 and $ff00) shr 8)) <= Tolerance) then
          if (Abs(((Color1 and $ff0000) shr 16) - ((Color2 and $ff0000) shr 16)) <= Tolerance) then
            Result := True;
    end;
    Is the Result := False; nessecairy? (And would that matter to speed?)



    The best way to contact me is by email, which you can find on my website: http://wizzup.org
    I also get email notifications of private messages, though.

    Simba (on Twitter | Group on Villavu | Website | Stable/Unstable releases
    Documentation | Source | Simba Bug Tracker on Github and Villavu )


    My (Blog | Website)

  17. #17
    Join Date
    Feb 2006
    Location
    Belgium
    Posts
    3,137
    Mentioned
    3 Post(s)
    Quoted
    5 Post(s)

    Default

    Quote Originally Posted by Wizzup? View Post
    Is the Result := False; nessecairy? (And would that matter to speed?)
    Kinda, delphi sometimes has this weird annoying habbit...
    But anyway, you could as well write it like this:
    SCAR Code:
    function SimilarColors(Color1, Color2, Tolerance: Integer): Boolean;
    begin
      Result := ((Abs((Color1 and $ff) - (Color2 and $ff)) <= Tolerance) and
        (Abs(((Color1 and $ff00) shr 8) - ((Color2 and $ff00) shr 8)) <= Tolerance) and
        (Abs(((Color1 and $ff0000) shr 16) - ((Color2 and $ff0000) shr 16)) <= Tolerance));
    end;

    Quote Originally Posted by ruler View Post
    please speed test
    *says some un-understandble stuff*
    average 11ms

    Well, as i said..., i didn't write the original function so i can't help that it sux

  18. #18
    Join Date
    Feb 2006
    Location
    London, England
    Posts
    2,045
    Mentioned
    2 Post(s)
    Quoted
    0 Post(s)

    Default

    Quote Originally Posted by Wizzup? View Post
    Is the Result := False; nessecairy? (And would that matter to speed?)
    In delphi you must define everything

    PHP Code:
    Result := False;
    := 0
    etc.

    Otherwise you get a load of hints saying:

    PHP Code:
    Variable 'i' might not have been initialized
    With such a big project like SCAR etc. if this message came up for every procedure, you would have to constantly weed through all the hints just to find the error messages. Because of this, putting Result := False, i := 0; etc. becomes second nature

    You will see more of this in the dpr files in the repos.

    Hope that helps.
    SRL Wiki | SRL Rules | SRL Stats
    Ultimate SCAR Scripting Tutorial | Starblaster100's Auth System | Join the official SRL IRC now!


    Help Keep SRL Alive! Please disable Advert Blockers on SRL! Help Keep SRL Alive!


Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Similar Threads

  1. Replies: 4
    Last Post: 11-04-2007, 03:51 AM
  2. FindColor
    By Sp0rky in forum OSR Help
    Replies: 26
    Last Post: 08-01-2007, 08:46 PM
  3. Need help with If not FindColor
    By philowns in forum OSR Help
    Replies: 3
    Last Post: 08-01-2007, 03:36 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •