C# PixelSearch (search screen for pixel)

05/14/2009 04:18 ProtoBit#1
This is a very similar to Auto-its PixelSearch functions (since that's what i intended to make it)

Basically it creates a bitmap of a region on the screen, converts the image to a 2d array and loops through the array searching for the inputed color.

NOTE: to compile this in a VC# 2008 you will need to allow unsafe code (HOW: Project->Properties->Build->Allow unsafe code)

Code:
        public static Point PixelSearch(Rectangle rect, int PixelColor, int Shade_Variation)
        {
            Color Pixel_Color = Color.FromArgb(PixelColor);

            Point Pixel_Coords = new Point(-1, -1);
            Bitmap RegionIn_Bitmap = CaptureScreenRegion(rect);
            BitmapData RegionIn_BitmapData = RegionIn_Bitmap.LockBits(new Rectangle(0, 0, RegionIn_Bitmap.Width, RegionIn_Bitmap.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

            int[] Formatted_Color = new int[3] { Pixel_Color.B, Pixel_Color.G, Pixel_Color.R }; //bgr

            unsafe
            {
                for (int y = 0; y < RegionIn_BitmapData.Height; y++)
                {
                    byte* row = (byte*)RegionIn_BitmapData.Scan0 + (y * RegionIn_BitmapData.Stride);

                    for (int x = 0; x < RegionIn_BitmapData.Width; x++)
                    {
                        if (row[x * 3] >= (Formatted_Color[0] - Shade_Variation) & row[x * 3] <= (Formatted_Color[0] + Shade_Variation)) //blue
                        {
                            if (row[(x * 3) + 1] >= (Formatted_Color[1] - Shade_Variation) & row[(x * 3) + 1] <= (Formatted_Color[1] + Shade_Variation)) //green
                            {
                                if (row[(x * 3) + 2] >= (Formatted_Color[2] - Shade_Variation) & row[(x * 3) + 2] <= (Formatted_Color[2] + Shade_Variation)) //red
                                {
                                    Pixel_Coords = new Point(x + rect.X, y + rect.Y);
                                    goto end;
                                }
                            }
                        }
                    }
                }
            }

        end:
            return Pixel_Coords;
        }

        private static Bitmap CaptureScreenRegion(Rectangle rect)
        {
            Bitmap BMP = new Bitmap(rect.Width, rect.Height, PixelFormat.Format24bppRgb);
            Graphics GFX = System.Drawing.Graphics.FromImage(BMP);
            GFX.CopyFromScreen(rect.X, rect.Y, 0, 0, rect.Size, CopyPixelOperation.SourceCopy);
            return BMP;
        }
btw: performance wise this is about 3-4 ms slower than Autoits (23ms vs 26ms), so if you REALLY need that much of a difference then you might get improvement if you just call the function from autoitx.dll

big credit to dude at [Only registered and activated users can see links. Click Here To Register...] which was very helpful, and some other dude with capture screen region function
08/31/2009 06:29 NargalaX#2
Yo sup. This was a great find to me, and I'd love to use it, but I'm getting around 32 errors.

What namespaces do I need to include?


Thank you!!

Nevermind, got it.
10/14/2009 02:15 Otagtubt#3
I added an overloaded method signature to allow rgb to be passed in as seperate values. It's easier to find r g b with photoshop.

public static Point PixelSearch(Rectangle rect, int r, int b, int g, int Shade_Variation) {
Color Pixel_Color = Color.FromArgb(r, g, b);

However... I can't seem to find the pixel color with the code. I checked the color code by taking a screenshot and importing that into photoshop. from there i got the rgb values right out of photoshop and plugged them in to the search. The snippet IS pulling the data off the screen, and to verify it's in the right section i was saving the bmp to a file. It's the right section, but it wont find the color.

in my last attempt i also added a sliderbar to allow some flux in the shade variation. values allowed in the slider are 0-50 which sets the shade_variation... still fails.

Any idea what i'm missing?
12/26/2010 23:32 jonasX#4
Did I need a funcion for Bitmap RegionIn_Bitmap = CaptureScreenRegion(rect); ?
Cant find CaptureScreenRegion();
12/31/2010 17:36 cooletobi#5
Code:
            Bitmap bmp = null;
            bmp = new Bitmap(xresolution, yresolution);

            Graphics graphic = Graphics.FromImage(bmp);
            graphic.CopyFromScreen(new Point(placement.rcNormalPosition.X,   placement.rcNormalPosition.Y),
            new Point(0, 0), new Size(ixresolution, yresolution));

            Color color = new Color();
            color = bmp.GetPixel(x, y);

            color.R; // red color
            color.B; // blue color
            color.G; // green color
12/31/2010 19:14 Gertos#6
You are using the CopyFromScreen function.
Be carfull with it, from my lasts work with it I know it has a handle-resource-leak.
In my case, I could use the funktion a few 10.000 times and then windows crashed.
( Don't know if they have fixed it in the meantime.)

This funktion should work better:
Code:
       public static Bitmap GetBitmap(int x, int y, int dx, int dy)
        {
            Bitmap screenCopy = new Bitmap(dx, dy); 
            using (Graphics gdest = Graphics.FromImage(screenCopy)) 

            using (Graphics gsrc = Graphics.FromHwnd(IntPtr.Zero)) 
            { 
                IntPtr hSrcDC = gsrc.GetHdc(); 
                IntPtr hDC = gdest.GetHdc(); 
                int retval = BitBlt(hDC, 0, 0, dx, dy, hSrcDC, x, y, (int)CopyPixelOperation.SourceCopy); 

                gdest.ReleaseHdc(); 
                gsrc.ReleaseHdc(); 
            }

            return screenCopy;
        }
04/13/2019 14:48 InfamousZeus#7
Thanks, but for pixelsearch function in autoitx.dll, there are 2 parameters called shade and step. Any idea of what they are?