0

I'm trying to scan my whole screen for a particular color, after that I will check if the color is found or not. However the process using Bitmap and GetPixel seems to be taking forever. I heard of something that I can use which us Bitlock with Bitmap, but I couldn't figure out how I can Implement it in my code.

Here it is my code that I'm using to scan my screen:

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;

namespace ConsoleApp1
{
    internal class Program
    {
        public static Point location = new Point(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);

        static void Main(string[] args)
        {
            for (int x = 0; x < location.X; x++)
            {
                for (int y = 0; y < location.Y; y++)
                {
                    Console.WriteLine(GrabColor(x,y));
                }

                Thread.Sleep(1000);
            }
        }

        public static Color GrabColor(int x, int y)
        {
            using (var bitmap = new Bitmap(1,1))
            {
                using (Graphics graphics = Graphics.FromImage(bitmap))
                {
                    graphics.CopyFromScreen(new Point(x,y), new Point(0,0), new Size(1,1));
                }

                return bitmap.GetPixel(0, 0);
            }
        }
    }
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Cod3rMax
  • 23
  • 4
  • 1
    Does this answer your question? [C# - Faster Alternatives to SetPixel and GetPixel for Bitmaps for Windows Forms App](https://stackoverflow.com/questions/24701703/c-sharp-faster-alternatives-to-setpixel-and-getpixel-for-bitmaps-for-windows-f) – Flexz Nov 23 '22 at 12:01
  • Of course you can use `LockBits` and use pointer arithmetic (which is always pixel format-dependent), but you can also try my dedicated [library](https://github.com/koszeggy/KGySoft.Drawing#fast-bitmap-manipulation) exactly for this purpose. – György Kőszeg Nov 23 '22 at 12:02
  • @Flexz thank you but no, because I'm looking to understand and use the concept of Lockbits – Cod3rMax Nov 23 '22 at 12:04
  • @GyörgyKőszeg yeah that's what i'm looking for using LockBits i want to use it and understand it as well how it works on my code. – Cod3rMax Nov 23 '22 at 12:08

1 Answers1

0

I have previously used Lockbits for this.

Lock bits give you a pointer to the start of the bitmap, called scan0. How many bytes each pixel takes up is determined by the PixelFormat of the bitmap. The remaining useful information is the width of a the line, in bytes, called the stride .

The examples for these functions all use various Marshall calls. I instead used "unsafe" code. To do this you need to enable unsafe code for the project and declare your function as unsafe too.

There after you do it with pointer arithmetic as needed.

Note that the lock operation is expensive, so if you can get all the pixel values you need in one hit, rather than separate calls that will be quicker for you.

Edit:

This is the code I used to solve a specific (slightly different problem) some time ago:

     GraphicsPath gp = new GraphicsPath();
    
            BitmapData bd = wheel.LockBits(new Rectangle(new Point(0, 0), wheel.Size), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
            int* pBase = (int*)bd.Scan0.ToPointer(); //int is 32-bit, so is an ARGB color
            int transp = pBase[0]; //top left is transparent
            int i = 0;
            for (int y = 0; y < wheel.Height; y++)
            {
                for (int x = 0; x < wheel.Width; x++)
                {
                    if (pBase[i] != transp)
                        gp.AddRectangle(new Rectangle(x, y, 1, 1));
                    i++;
                }
            }
            wheel.UnlockBits(bd);

Copying only the not transparent bits of an image, for a different project long long ago (it targeted .Net 2!). Still works though.