Results 1 to 3 of 3

Thread: [C++ & Delphi] Fast FindColor(RGB)Tolerance!

  1. #1
    Member
    Join Date
    Jan 2012
    Posts
    30
    Bots Posted
    0
    Post Thanks / Like
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    [C++ & Delphi] Fast FindColor(RGB)Tolerance!

    Delphi:
    Code:
    type
      PRGBQuadArray = ^TRGBQuadArray;
      TRGBQuadArray = array [0..0] of TRGBQuad;
    
     
    function FindColorTolerance(Client: HDC; Color: Integer; var dx, dy: Integer; x1, y1, x2, y2, Tolerance: Integer): Boolean;
    const
      Offset: array [0..0] of Integer = (1);
    var
      Color_rgbRed, Color_rgbGreen, Color_rgbBlue: Integer;
      bmpW, bmpH: Integer;
      bmi: TBitmapInfo;
      DIBHandle: HBitmap;
      CompDC: HDC;
      PrevObj: HGDIOBJ;
      Pixels: PRGBQuadArray;
      I, H, L, HW: Integer;
      J: Integer;
    begin
      Result := False;
    
     
      Color_rgbRed := Color; //(Color and $ff);
      Color_rgbGreen := Color shr 8; //(Color and $ff00) shr 8;
      Color_rgbBlue := Color shr 16; //(Color and $ff0000) shr 16;
    
     
      bmpW := x2 - x1 + 1;
      bmpH := y2 - y1 + 1;
    
     
      FillMemory(@bmi, SizeOf(TBitmapInfo), 0);
      with bmi.bmiHeader do
      begin
        biSize        := SizeOf(TBitmapInfoHeader);
        biWidth       := bmpW;
        biHeight      := -bmpH;
        biPlanes      := 1;
        biBitCount    := 32;
        biCompression := BI_RGB;
      end;
    
     
      try
        DIBHandle := CreateDIBSection(0, bmi, DIB_RGB_COLORS, Pointer(Pixels), 0, 0);
    
     
        CompDC := CreateCompatibleDC(Client);
        PrevObj := SelectObject(CompDC, DIBHandle);
    
     
        BitBlt(CompDC, 0, 0, bmpW, bmpH, Client, x1, y1, SRCCOPY);
    
     
        H := High(Offset);
        L := Length(OffSet);
        HW := (bmpH - 1) * (bmpW - 1);
        Tolerance := Sqr(Tolerance);
    
     
        for J := 0 to H do
        begin
          if Result then
            Break;
    
     
          I := 0 - OffSet[J];
          while ( i < HW - OffSet[J] ) do
          begin
            Inc(I, L);
            if Tolerance >= (Sqr(Color_rgbRed - Pixels^[I].rgbRed)
               +Sqr(Color_rgbGreen - Pixels^[I].rgbGreen)
               +Sqr(Color_rgbBlue - Pixels^[I].rgbBlue)) then
            begin
              dx := x1 + (I mod bmpW);
              dy := y1 + (I div bmpW);
              Result := True;
              Break;
            end;
          end;
        end;
    
     
      finally
        PrevObj := SelectObject(CompDC, PrevObj);
        DeleteDC(CompDC);
        DeleteObject(DIBHandle);
      end;
    
     
    end;
    C++: (only returns an array of pixels, actual searching with RGB, HSL, or XYZ tolerance is not applied)
    Code:
    colorArray colorArray::fromDC(HDC zdc)
    {
        HBITMAP hbmp = (HBITMAP)GetCurrentObject(zdc, OBJ_BITMAP);
    
        BITMAP bmp;
        if (GetObject(hbmp, sizeof(BITMAP), &bmp) == 0) throw "Invalid device context";
    
        HDC bufferDC = CreateCompatibleDC(GetDC(0));
        HBITMAP bufferBitmap = CreateCompatibleBitmap(GetDC(0), bmp.bmWidth, bmp.bmHeight);
        DeleteObject(SelectObject(bufferDC, bufferBitmap));
    
        BitBlt(bufferDC, 0, 0, bmp.bmWidth, bmp.bmHeight, zdc, 0, 0, SRCCOPY);
    
        int dataSize = ((bmp.bmWidth * 32 + 31) / 32) * 4 * bmp.bmHeight;
    
        BITMAPINFO bmpInfo;
        bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
        bmpInfo.bmiHeader.biWidth = bmp.bmWidth;
        bmpInfo.bmiHeader.biHeight = -bmp.bmHeight;
        bmpInfo.bmiHeader.biPlanes = 1;
        bmpInfo.bmiHeader.biBitCount = 32;
        bmpInfo.bmiHeader.biCompression = BI_RGB;
        bmpInfo.bmiHeader.biSizeImage = dataSize;
    
        myColor* newData = (myColor*)malloc(dataSize);
    
        GetDIBits (bufferDC, bufferBitmap, 0, bmp.bmHeight, newData, &bmpInfo, DIB_RGB_COLORS);
    
        DeleteDC(bufferDC);
        DeleteObject(bufferBitmap);
    
        colorArray newColorArray(newData, bmp.bmWidth, bmp.bmHeight);
        return newColorArray;
    }
    It was a goal of mine to make a fast and efficient pixel finding function. Here are two examples of some of my work. Useful to those who are interested..
    Last edited by MiLk; 01-07-2012 at 01:14 PM.

  2. #2
    Member
    Join Date
    Jul 2011
    Posts
    39
    Bots Posted
    1
    Post Thanks / Like
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    That's actually really cool. I'm sure it's super fast, which is really necessary for scanning an entire screen or a large part of it. Nice share. I've written stuff like this in php and ahk, it's kind of fun working with gdi and images.

  3. #3
    Member
    Join Date
    Jan 2012
    Posts
    30
    Bots Posted
    0
    Post Thanks / Like
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yeah iv experimented with almost everything CreateDIBSection, Scanlines, GetDIBits..

    GetDIBits seems to be the best option

Posting Permissions

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