Clickar a un color

Iniciado por flyice, 9 Julio 2014, 15:23 PM

0 Miembros y 1 Visitante están viendo este tema.

flyice

Hola.
Necesito hacer que cuando aparezca un color en la pantalla del ordenador, el mouse vaya directo a él y lo clicke.
Definiría el color en el código.
¿Cómo podría hacerlo?

engel lex

Te toca hacer un programa que lea los pixeles de la pantalla
El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.

Eleкtro

#2
Te hago la mitad del trabajo, ahora, para ubicar las coordenadas relativas a la imagen por el momento no se me ocurre el modo de hacerlo, pero algo se podrá hacer obteniendo el índice del pixel encontrado (cosa que hago) usandola en alguna fórmula aritmética con el ancho y alto de la imagen.

Public Class PixelData
       Public Index As Integer
       Public Color As Color
       Public Coordinates As Point
   End Class

   Friend Function GetPixelData(ByVal bmp As Bitmap) As List(Of PixelData)

       If Not bmp.PixelFormat = Imaging.PixelFormat.Format24bppRgb Then
           Throw New Exception("PixelFormat no soportado en esta función.")
       End If

       ' Lock the bitmap's bits.  
       Dim rect As New Rectangle(0, 0, bmp.Width, bmp.Height)
       Dim bmpdata As Drawing.Imaging.BitmapData =
           bmp.LockBits(rect, Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat)

       ' Get the address of the first line.
       Dim ptr As IntPtr = bmpdata.Scan0

       ' Declare an array to hold the bytes of the bitmap.
       ' This code is specific to a bitmap with 24 bits per pixels.
       Dim bytes As Integer = Math.Abs(bmpdata.Stride) * bmp.Height
       Dim rgbValues(bytes - 1) As Byte

       ' Copy the RGB values into the array.
       Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes)

       ' Unlock the bits.
       bmp.UnlockBits(bmpdata)

       ' Set the Data to return.
       Dim Pixels As New List(Of PixelData)

       ' Loop through each 24bpp-RGB value.
       For Index As Integer = 2 To rgbValues.Length - 1 Step 3

           Pixels.Add(New PixelData With
                      {
                          .Index = Index \ 3I,
                          .Color = Color.FromArgb(rgbValues(Index), rgbValues(Index - 1I), rgbValues(Index - 2I)),
                          .Coordinates = Point.Empty
                      })

       Next Index

       Return Pixels

   End Function


EDITO: Fórmula encontrada.

Nota: Lo he testeado con una imagen a resolución 2560x1600, el retorno de datos es practicamente instantaneo, la búsqueda puede variar según lo lejos que se encuentre el pixel en la iteración.

Código (vbnet) [Seleccionar]
   ''' <summary>
   ''' Stores specific pixel information of an image.
   ''' </summary>
   Friend 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

   ''' <summary>
   ''' Returns a <c>'PixelData'</c> object containing information about each pixel of an image.
   ''' </summary>
   ''' <param name="bmp">Indicates the Bitmap image to process.</param>
   ''' <returns>List(Of PixelData).</returns>
   ''' <exception cref="System.Exception">PixelFormat unsupported.</exception>
   Friend Function GetPixelData(ByVal bmp As Bitmap) As List(Of PixelData)

       If Not bmp.PixelFormat = Imaging.PixelFormat.Format24bppRgb Then
           Throw New Exception("PixelFormat unsupported.")
       End If

       ' Lock the Bitmap bits.
       Dim bmpRect As New Rectangle(0, 0, bmp.Width, bmp.Height)
       Dim bmpData As Drawing.Imaging.BitmapData =
           bmp.LockBits(bmpRect, Imaging.ImageLockMode.ReadWrite, 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.
       Runtime.InteropServices.Marshal.Copy(Pointer, rgbData, 0, bmpBytes)

       ' Unlock the Bitmap bits.
       bmp.UnlockBits(bmpData)

       ' Instance the object to return.
       Dim Pixels As New List(Of PixelData)

       ' Loop through each 24bpp-RGB value.
       For rgbIndex As Integer = 2 To rgbData.Length - 1 Step 3

           ' Get the pixel values.
           Dim PixelIndex As Integer = rgbIndex \ 3I
           Dim PixelCoordX As Integer = PixelIndex Mod bmpRect.Width
           Dim PixelCoordY As Integer = (PixelIndex - PixelCoordX) \ bmpRect.Width
           Dim PixelColorR As Short = rgbData(rgbIndex)
           Dim PixelColorG As Short = rgbData(rgbIndex - 1I)
           Dim PixelColorB As Short = rgbData(rgbIndex - 2I)

           ' Set the pixel Data.
           Dim Pixel As New PixelData
           With Pixel
               .Index = PixelIndex
               .Color = Color.FromArgb(PixelColorR, PixelColorG, PixelColorB)
               .Coordinates = New Point(PixelCoordX, PixelCoordY)
           End With

           ' Add the PixelData into the list.
           Pixels.Add(Pixel)

       Next rgbIndex

       Return Pixels

   End Function


Ejemplo de uso:

Código (vbnet) [Seleccionar]
   Public Sub Test() Handles Button1.Click

       ' Create a new bitmap.
       Dim bmp As Bitmap = Bitmap.FromFile("Imagen de la pantalla.bmp", False)

       ' Specify the RGB PixelColor to search.
       Dim FindColor As Color = Color.FromArgb(255, 174, 201)

       ' Get the pixel data.
       Dim Pixels As List(Of PixelData) = Me.GetPixelData(bmp)

        ' Loop through each pixel.
       For Each Pixel As PixelData In Pixels

           If Pixel.Color.Equals(FindColor) Then

               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

           End If

       Next Pixel

   End Sub


Saludos








Eleкtro

Aquí os dejo una versión mejorada y extendida de lo anterior, por si a alguien le sirve:

Código (vbnet) [Seleccionar]
' ***********************************************************************
' 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