11

So I'm trying to find a certain pattern in the middle of the screen in a given area. I'm using the AutoItX library and the PixelSearch method.

  • Rectangle X: 1980
  • Rectangle Y: 630
  • Rectangle Size X: 1240
  • Rectangle Size Y: 180

It's not returning that the pattern has been found, but if I adjust the cords of the rectangle to 0, 0 it shows that the pattern has been found.

The following script used:

  public void MonsterScan()
  {
    if(SixStarMax() == true)
    {
        Console.WriteLine("Pattern found");
    }
  }

  public bool SixStarMax()
  {
    Rectangle rect = new Rectangle(1980, 630, 1240, 180);
    autoSumPoint = AutoItX.PixelSearch(rect, 0xF8F0E0); // 0xF8F0E0
    autoSumPoint2 = AutoItX.PixelSearch(rect, 0xB7AD9F); // 0xB7AD9F
    autoSumPoint3 = AutoItX.PixelSearch(rect, 0xCDC6B8); // 0xCDC6B8
    autoSumPoint4 = AutoItX.PixelSearch(rect, 0x949084); // 0x949084

    if (rect.Contains(autoSumPoint2) == true && rect.Contains(autoSumPoint2) == true && rect.Contains(autoSumPoint3) == true && rect.Contains(autoSumPoint4) == true)
    {
      AutoItX.MouseMove(autoSumPoint.X, autoSumPoint.Y);
      return true;
    }
    else
    {
      return false;
    }
  }

Edit:

Tried to adjust the cordinates to my first screen and I get an error thrown.

System.AccessViolationException: 'An attempt was made to read or write to protected memory. This often indicates that other memory is damaged. '
user4157124
  • 2,809
  • 13
  • 27
  • 42
Tweath
  • 124
  • 6
  • 24
  • 1
    An AccessViolationException error like this comes from the native part of AutoIt (not from the .net wrapper). You should try to contact AutoIt maker. – Simon Mourier Oct 06 '17 at 07:41

2 Answers2

4

AutoItX' PixelSearch() has a bug. Possible solutions :

  • See if it's fixed in latest beta.
  • Change coordinates (an old version had X/Y switched).
  • Use PixelGetColor().
  • Find a 3rd party image search dll.
user4157124
  • 2,809
  • 13
  • 27
  • 42
0

You can code it without any external library and be very fast by reading the bytes internally. Don't forget to include System.Drawing.Imaging and System.Linq in the using statements and compile it with the 'Unsafe' option in Project options.

public bool SixStarMax()
{
    Rectangle rect = new Rectangle(1980, 630, 1240, 180);

    Bitmap bitmapToScan = GetScreenPart(rect);

    Point?[] autoSumPoints = new Point?[4];

    autoSumPoints[0] = SearchForColor(bitmapToScan, 0xF8F0E0);
    autoSumPoints[1] = SearchForColor(bitmapToScan, 0xB7AD9F);
    autoSumPoints[2] = SearchForColor(bitmapToScan, 0xCDC6B8);
    autoSumPoints[3] = SearchForColor(bitmapToScan, 0x949084);

    //return true if all points return a value
    bool containsAll = autoSumPoints.All(p => p.HasValue);

    if (containsAll) Cursor.Position = autoSumPoints[0].Value;
    return containsAll;
}

public Bitmap GetScreenPart(Rectangle rect)
{
    //initialize bitmap
    Bitmap bmp = new Bitmap(rect.Width, rect.Height, PixelFormat.Format32bppArgb);

    //fill bitmap
    using (Graphics g = Graphics.FromImage(bmp))
        g.CopyFromScreen(new Point(rect.Left, rect.Top), new Point(rect.Right, rect.Bottom), rect.Size);

    return bmp;
}

public Point? SearchForColor(Bitmap image, uint color)
{
    Rectangle rect = new Rectangle(0, 0, image.Width, image.Height);

    BitmapData data = image.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb);

    //works for 32-bit pixel format only
    int ymin = rect.Top, ymax = Math.Min(rect.Bottom, image.Height);
    int xmin = rect.Left, xmax = Math.Max(rect.Right, image.Width) - 1;

    int strideInPixels = data.Stride / 4; //4 bytes per pixel
    unsafe
    {
        uint* dataPointer = (uint*)data.Scan0;
        for (int y = ymin; y < ymax; y++)
            for (int x = xmin; x < xmax; x++)
            {
                //works independently of the data.Stride sign
                uint* pixelPointer = dataPointer + y * strideInPixels + x;
                uint pixel = *pixelPointer;
                bool found = pixel == color;
                if (found)
                {

                    image.UnlockBits(data);
                    return new Point(x, y);

                }
            }
    }
    image.UnlockBits(data);
    return null;
}