Occasionally I need to write an app that reads pixels from the screen. When searching small chunks of the screen, the windows GetPixel API works fine, but if I need to search the whole screen, that gets too slow. One way that I have found that is about twice as fast as GetPixel is copying the screen to a bitmap and using the Bitmap's GetPixel method. Below is an extension method that works with the Screen class to find pixels.
Module ScreenExtensions
<Extension()> _
Public Function FindPixelsByColor(ByVal CurrentScreen As Screen, ByVal SearchColor As Color) As List(Of Point)
Dim ScreenBitmap As Bitmap = Nothing
Dim ScreenCopier As Graphics = Nothing
If CurrentScreen Is Nothing Then Throw New ArgumentException("The screen object is nothing.")
If SearchColor = Color.Empty Then Throw New ArgumentException("The search color is empty.")
Try
' Initialize our output of points.
Dim OutputPoints As New List(Of Point)
' Create the bitmap object that will be used to store the image of the screen.
ScreenBitmap = New Bitmap(CurrentScreen.WorkingArea.Width, CurrentScreen.WorkingArea.Height, _
Imaging.PixelFormat.Format32bppArgb)
' Create the graphics object that will be used to copy the screen
ScreenCopier = Graphics.FromImage(ScreenBitmap)
' Copy from the screen to the bitmap, so we can search for the pixels we are looking for
ScreenCopier.CopyFromScreen(New Point(0, 0), New Point(0, 0), _
New Size(CurrentScreen.WorkingArea.Width, CurrentScreen.WorkingArea.Height))
Dim ScreenColor As Color
' Loop through all of the pixels in the bitmap
For x As Integer = 0 To CurrentScreen.WorkingArea.Width - 1
For y As Integer = 0 To CurrentScreen.WorkingArea.Height - 1
' Get the color at the current pixel from the screenshot.
ScreenColor = ScreenBitmap.GetPixel(x, y)
' Compare the color from the screenshot with the desired color. We need to level off the alpha
' for this compare to work properly. All colors from the screenshot have an alpha of 255.
If ScreenColor = Color.FromArgb(255, SearchColor) Then
' If we have a match, then add the current x,y to our output.
OutputPoints.Add(New Point(x, y))
End If
Next
Next
Return OutputPoints
Catch ex As Exception
Throw New Exception("Unable to perform pixel search.", ex)
Finally
If ScreenBitmap IsNot Nothing Then ScreenBitmap.Dispose()
If ScreenCopier IsNot Nothing Then ScreenCopier.Dispose()
End Try
End Function
End Module
Colorized by: CarlosAg.CodeColorizer
To use this class. You can simply call it from any screen object. For example:
Dim l As List(Of Point)
l = Screen.PrimaryScreen.FindPixelsByColor(Color.FromArgb(128, 128, 128))
MessageBox.Show(l.Count.ToString())
Colorized by: CarlosAg.CodeColorizer