' ***********************************************************************
' Author : Elektro
' Last Modified On : 07-11-2014
' ***********************************************************************
' <copyright file="PixelUtil.vb" company="Elektro Studios">
' Copyright (c) Elektro Studios. All rights reserved.
' </copyright>
' ***********************************************************************
#Region " Usage Examples "
' **************************************************
' Count the number of Pixels that contains the image
' **************************************************
'
'' Create a new bitmap.
'Dim bmp As Bitmap = Bitmap.FromFile("C:\DesktopScreenshot.bmp", False)
'
'' Instance a PixelUtil Class.
'Dim bmpPixelUtil As New PixelUtil(bmp)
'
'' Display the pixel count.
'MessageBox.Show(String.Format("Total amount of Pixels: {0}", CStr(bmpPixelUtil.PixelCount)))
' ************************************************
' Searchs for an specific pixel color in the image
' ************************************************
'
'' Create a new bitmap.
'Dim bmp As Bitmap = Bitmap.FromFile("C:\DesktopScreenshot.bmp", False)
'
'' Instance a PixelUtil Class.
'Dim bmpPixelUtil As New PixelUtil(bmp)
'
'' Specify the RGB PixelColor to search.
'Dim FindColor As Color = Color.FromArgb(255, 174, 201)
'
'' Get the pixel data.
'Dim FoundPixels As List(Of PixelUtil.PixelData) = bmpPixelUtil.SearchColor(FindColor)
'
'' Loop through each pixel.
'For Each Pixel As PixelUtil.PixelData In FoundPixels
'
' Dim sb As New System.Text.StringBuilder
' With sb
'
' .AppendLine(String.Format("Index: {0}", CStr(Pixel.Index)))
' .AppendLine(String.Format("Coord: {0}", Pixel.Coordinates.ToString))
'
' MessageBox.Show(.ToString, "Pixel-Color Search")
'
' .Clear()
'
' End With
'
'Next Pixel
' *********************************************************************
' Retrieve the index, color, and coordinates of each pixel in the image
' *********************************************************************
'
'' Create a new bitmap.
'Dim bmp As Bitmap = Bitmap.FromFile("C:\DesktopScreenshot.bmp", False)
'
'' Instance a PixelUtil Class.
'Dim bmpPixelUtil As New PixelUtil(bmp)
'
'' Get the pixel data.
'Dim Pixels As List(Of PixelUtil.PixelData) = bmpPixelUtil.GetPixelData()
'
'' Loop through each pixel.
'For Each Pixel As PixelUtil.PixelData In Pixels
'
' Dim sb As New System.Text.StringBuilder
' With sb
'
' .AppendLine(String.Format("Index: {0}", CStr(Pixel.Index)))
' .AppendLine(String.Format("Color: {0}", Pixel.Color.ToString))
' .AppendLine(String.Format("Coord: {0}", Pixel.Coordinates.ToString))
'
' MessageBox.Show(.ToString, "Pixel Search")
'
' .Clear()
'
' End With
'
'Next Pixel
' ****************************************************************************
' Retrieve the index, color, and coordinates of a range of pixels in the image
' ****************************************************************************
'
'' Create a new bitmap.
'Dim bmp As Bitmap = Bitmap.FromFile("C:\DesktopScreenshot.bmp", False)
'
'' Instance a PixelUtil Class.
'Dim bmpPixelUtil As New PixelUtil(bmp)
'
'' Specify the pixel range to retrieve.
'Dim RangeMin As Integer = 1919I
'Dim RangeMax As Integer = 1921I
'
'' Get the pixel data.
'Dim FoundPixels As List(Of PixelUtil.PixelData) = bmpPixelUtil.GetPixelData(RangeMin, RangeMax)
'
'' Loop through each pixel.
'For Each Pixel As PixelUtil.PixelData In FoundPixels
'
' Dim sb As New System.Text.StringBuilder
' With sb
'
' .AppendLine(String.Format("Index: {0}", CStr(Pixel.Index)))
' .AppendLine(String.Format("Color: {0}", Pixel.Color.ToString))
' .AppendLine(String.Format("Coord: {0}", Pixel.Coordinates.ToString))
'
' MessageBox.Show(.ToString, "Pixel-Color Search")
'
' .Clear()
'
' End With
'
'Next Pixel
#End Region
#Region " Imports "
Imports System.ComponentModel
Imports System.Drawing.Imaging
Imports System.Runtime.InteropServices
#End Region
#Region " PixelUtil "
Public Class PixelUtil
#Region " Vars, Properties "
Private _PixelData As List(Of PixelData) = Nothing
Private _bmp As Bitmap = Nothing
Private _PixelCount As Integer = Nothing
''' <summary>
''' Gets the Bitmap object.
''' </summary>
''' <value>The BMP.</value>
Public ReadOnly Property bmp As Bitmap
Get
Return Me._bmp
End Get
End Property
''' <summary>
''' Gets the total amount of pixels that contains the Bitmap.
''' </summary>
''' <value>The pixel count.</value>
Public ReadOnly Property PixelCount As Integer
Get
Return Me._PixelCount
End Get
End Property
#End Region
#Region " Classes "
''' <summary>
''' Stores specific pixel information of an image.
''' </summary>
Public Class PixelData
''' <summary>
''' Gets or sets the pixel index.
''' </summary>
''' <value>The pixel index.</value>
Public Property Index As Integer
''' <summary>
''' Gets or sets the pixel color.
''' </summary>
''' <value>The pixel color.</value>
Public Property Color As Color
''' <summary>
''' Gets or sets the pixel coordinates relative to the image.
''' </summary>
''' <value>The pixel coordinates.</value>
Public Property Coordinates As Point
End Class
#End Region
#Region " Constructors "
''' <summary>
''' Prevents a default instance of the <see cref="PixelUtil"/> class from being created.
''' </summary>
Private Sub New()
End Sub
''' <summary>
''' Initializes a new instance of the <see cref="PixelUtil"/> class.
''' </summary>
''' <param name="bmp">Indicates the Bitmap image to process it's pixels.</param>
''' <exception cref="System.Exception">PixelFormat unsupported.</exception>
Public Sub New(ByVal bmp As Bitmap)
If Not bmp.PixelFormat = PixelFormat.Format24bppRgb Then
Throw New Exception("PixelFormat unsupported.")
End If
Me._bmp = bmp
Me._PixelCount = Me.[Count]
End Sub
#End Region
#Region " Public Methods "
''' <summary>
''' Returns a <c>'PixelData'</c> object containing information about each pixel in the image.
''' </summary>
''' <returns>List(Of PixelData).</returns>
Public Function GetPixelData() As List(Of PixelData)
If Me._PixelData Is Nothing Then
Me._PixelData = New List(Of PixelData)
' Lock the Bitmap bits.
Dim bmpRect As New Rectangle(0, 0, Me._bmp.Width, Me._bmp.Height)
Dim bmpData As BitmapData = Me._bmp.LockBits(bmpRect, ImageLockMode.ReadWrite, Me._bmp.PixelFormat)
' Get the address of the first line.
Dim Pointer As IntPtr = bmpData.Scan0
' Hold the bytes of the bitmap into a Byte-Array.
' NOTE: This code is specific to a bitmap with 24 bits per pixels.
Dim bmpBytes As Integer = (Math.Abs(bmpData.Stride) * bmpRect.Height)
Dim rgbData(bmpBytes - 1) As Byte
' Copy the RGB values into the array.
Marshal.Copy(Pointer, rgbData, 0, bmpBytes)
' Unlock the Bitmap bits.
Me._bmp.UnlockBits(bmpData)
' Loop through each 24bpp-RGB value.
For rgbIndex As Integer = 2 To rgbData.Length - 1 Step 3
' Set the pixel Data.
Dim Pixel As New PixelData
With Pixel
.Index = rgbIndex \ 3I
.Color = Color.FromArgb(red:=rgbData(rgbIndex),
green:=rgbData(rgbIndex - 1I),
blue:=rgbData(rgbIndex - 2I))
.Coordinates = New Point(X:=(.Index Mod bmpRect.Width),
Y:=(.Index - (.Index Mod bmpRect.Width)) \ bmpRect.Width)
End With
' Add the PixelData into the list.
Me._PixelData.Add(Pixel)
Next rgbIndex
End If
Return Me._PixelData
End Function
''' <summary>
''' Returns a <c>'PixelData'</c> object containing information about a range of pixels in the image.
''' </summary>
''' <returns>List(Of PixelData).</returns>
''' <exception cref="System.Exception">Pixel index is out of range</exception>
Public Function GetPixelData(ByVal RangeMin As Integer,
ByVal RangeMax As Integer) As List(Of PixelData)
If Not (Me._PixelCount >= RangeMin AndAlso Me._PixelCount <= RangeMax) Then
Throw New Exception("Pixel index is out of range.")
Return Nothing
End If
' Return the Pixel range.
Return (From Pixel As PixelData In Me.GetPixelData()
Where (Pixel.Index >= RangeMin AndAlso Pixel.Index <= RangeMax)).ToList
End Function
''' <summary>
''' Searchs for the specified pixel-color inside the image and returns all the matches.
''' </summary>
''' <param name="PixelColor">Indicates the color to find.</param>
''' <returns>List(Of PixelData).</returns>
Public Function SearchColor(ByVal PixelColor As Color) As List(Of PixelData)
Return (From Pixel As PixelData In Me.GetPixelData
Where Pixel.Color = PixelColor).ToList
End Function
#End Region
#Region " Private Methods "
''' <summary>
''' Counts the number of pixels that contains the image.
''' </summary>
''' <returns>The number of pixels.</returns>
Private Function [Count]() As Integer
' Lock the Bitmap bits.
Dim bmpRect As New Rectangle(0, 0, Me._bmp.Width, Me._bmp.Height)
Dim bmpData As BitmapData = Me._bmp.LockBits(bmpRect, ImageLockMode.ReadWrite, Me._bmp.PixelFormat)
' Get the address of the first line.
Dim Pointer As IntPtr = bmpData.Scan0
' Hold the bytes of the bitmap into a Byte-Array.
' NOTE: This code is specific to a bitmap with 24 bits per pixels.
Dim bmpBytes As Integer = (Math.Abs(bmpData.Stride) * bmpRect.Height)
Dim rgbData(bmpBytes - 1) As Byte
' Copy the RGB values into the array.
Marshal.Copy(Pointer, rgbData, 0, bmpBytes)
' Unlock the Bitmap bits.
Me._bmp.UnlockBits(bmpData)
Return rgbData.Count
End Function
#End Region
#Region " Hidden Methods "
''' <summary>
''' Serves as a hash function for a particular type.
''' </summary>
<EditorBrowsable(EditorBrowsableState.Never)>
Public Shadows Sub GetHashCode()
End Sub
''' <summary>
''' Determines whether the specified System.Object is equal to the current System.Object.
''' </summary>
<EditorBrowsable(EditorBrowsableState.Never)>
Public Shadows Sub Equals()
End Sub
''' <summary>
''' Returns a String that represents the current object.
''' </summary>
<EditorBrowsable(EditorBrowsableState.Never)>
Public Shadows Sub ToString()
End Sub
#End Region
End Class
#End Region