Improvement: detect the color of a pixel on screen and move the mouse

-2

This code is written by someone and this function code is as follows:

According to color pixel location can be found and click on position was found, so far, the performance is excellent but a problem with this code, quickly find the position and the color is too low that is about 3 second (3000) it takes.

Is it possible to be done to increase speed or speed improvement?

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Threading;
using System.IO;
using System.Media;

namespace Login_Button_Click_for_Puzzle_Pirates
{
    public partial class frmMain : Form
    {
        [DllImport("user32.dll")]
        static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData,
          int dwExtraInfo);


        public enum MouseEventFlags : uint
        {
            LEFTDOWN = 0x00000002,
            LEFTUP = 0x00000004,
            MIDDLEDOWN = 0x00000020,
            MIDDLEUP = 0x00000040,
            MOVE = 0x00000001,
            ABSOLUTE = 0x00008000,
            RIGHTDOWN = 0x00000008,
            RIGHTUP = 0x00000010,
            WHEEL = 0x00000800,
            XDOWN = 0x00000080,
            XUP = 0x00000100
        }

        public frmMain()
        {
            InitializeComponent();
        }

        private void btnLogin_Click(object sender, EventArgs e)
        {


            // takes a snapshot of the screen
            Bitmap bmpScreenshot = Screenshot();

            // makes the background of the form a screenshot of the screen
            this.BackgroundImage = bmpScreenshot;

            // find the color and check if it exists
            Point location;
            bool success = FindBitmap(Properties.Resources.bmpLogin, bmpScreenshot, out location);

            // check if it found the bitmap
            if (success == false)
            {
                MessageBox.Show("Couldn't find color!");
                return;
            }


            // move the mouse to location
           Cursor.Position = location;


            // click
            MouseClick();

        }

        /// <summary>
        /// Simulates a mouse click
        /// </summary>
        private void MouseClick()
        {
            mouse_event((uint)MouseEventFlags.LEFTDOWN, 0, 0, 0, 0);
            Thread.Sleep((new Random()).Next(20, 30));
            mouse_event((uint)MouseEventFlags.LEFTUP, 0, 0, 0, 0);
        }

        /// <summary>
        /// Takes a snapshot of the screen
        /// </summary>
        /// <returns>A snapshot of the screen</returns>
        private Bitmap Screenshot()
        {
            // this is where we will store a snapshot of the screen
            Bitmap bmpScreenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);


            // creates a graphics object so we can draw the screen in the bitmap (bmpScreenshot)
            Graphics g = Graphics.FromImage(bmpScreenshot);

            // copy from screen into the bitmap we created
            g.CopyFromScreen(0, 0, 0, 0, Screen.PrimaryScreen.Bounds.Size);

            // return the screenshot
            return bmpScreenshot;
        }

        private bool FindBitmap(Bitmap bmpNeedle, Bitmap bmpHaystack, out Point location)
        {
            for(int outerX = 0; outerX < bmpHaystack.Width - bmpNeedle.Width; outerX++)
            {
                for (int outerY = 0; outerY < bmpHaystack.Height - bmpNeedle.Height; outerY++)
                {
                    for (int innerX = 0; innerX < bmpNeedle.Width; innerX++)
                    {
                        for (int innerY = 0; innerY < bmpNeedle.Height; innerY++)
                        {
                            Color cNeedle = bmpNeedle.GetPixel(innerX, innerY);
                            Color cHaystack = bmpHaystack.GetPixel(innerX + outerX, innerY + outerY);

                            if (cNeedle.R != cHaystack.R || cNeedle.G != cHaystack.G || cNeedle.B != cHaystack.B)
                            {
                                goto notFound;
                            }
                        }
                    }
                    location = new Point(outerX, outerY);
                    return true;
                notFound:
                    continue;
                }
            }
            location = Point.Empty;
            return false;
        }

        private void frmMain_Load(object sender, EventArgs e)
        {

        }
    }
}
c#
winforms
asked on Stack Overflow Aug 23, 2016 by Mohammad • edited Aug 23, 2016 by Raktim Biswas

1 Answer

2

Yes, this can be done faster. GetPixel is a notoriously slow function. You need to lock the bitmap and retrieve the raw pixel data, then you can search it for the color you're looking for.

There are other answers on Stack Overflow which provide examples, see here: Bitmap.Lockbits confusion

answered on Stack Overflow Aug 23, 2016 by Erik • edited May 23, 2017 by Community

User contributions licensed under CC BY-SA 3.0