Parcourir chaque pixel de l'écran. (tableau)

Résolu
KcHeY
Messages postés
261
Date d'inscription
dimanche 23 mai 2004
Statut
Membre
Dernière intervention
22 septembre 2012
- 19 mai 2012 à 17:05
KcHeY
Messages postés
261
Date d'inscription
dimanche 23 mai 2004
Statut
Membre
Dernière intervention
22 septembre 2012
- 19 mai 2012 à 22:37
Bonjour,

Dans le but de trouver sur tout mon ecran, un pixel d'une couleur précise, j'ai essayé d'adapter un code trouvé sur ce site.
 LocationX = 0
        LocationY = 0
        Label1.Text = ""
        Label2.Text = ""
        Thread.Sleep(200)
        Dim colorVal As Int32 = GetPixel(desktopDc, CType(LocationX, Int16), CType(LocationY, Int16))
        Dim r As Int32 = colorVal And &HFF
        Dim g As Int32 = (colorVal And &HFF00) >> 8
        Dim b As Int32 = (colorVal And &HFF0000) >> 16
        Dim c As Color = Color.FromArgb(r, g, b)
        For LocationX = 0 To 1279
            If LocationX = 1279 Then
                LocationX = 0
                LocationY += 1
            Else If (LocationX 1279 & LocationY 760) Then
                    MessageBox.Show("R,G,B= " & r & ", " & g & ", " & b & vbNewLine & "mouse(x,y)= " & LocationX & " " & LocationY)
                End If
                Label1.Text = "R,G,B= " & r & ", " & g & ", " & b
                Label2.Text = "location(x,y)= " & LocationX & " " & LocationY
                Me.BackColor = c

        Next


En fait je souhaiterai qu'il parcours toute la largeur X de l'écran, une fois arrivé a droite, il descend d'un pixel sur la ligne Y, jusqu'a arrivé à x=1279 & y = 760, ou meme mieu, sans lui donné les dimentions de l'écran.
Pouvez vous m'aider a creer un tableau (double tableau ?)
Merci d'avance !

21 réponses

Utilisateur anonyme
19 mai 2012 à 17:26
Bonjour,

Sers toi de l'objet Screen et de sa propriété WorkingArea, de l'objet Bitmap (qui prendra la taille de WorkingArea), de l'objet Graphics et sa méthode CopyFromScreen (pour dessiner l'image écran sur le bitmap) et enfin de la fonction GetPixel de la classe Bitmap pour analyser la couleur de ton pixel sur le bitmap.
Je met mon code exemple de côté en attendant que tu me montres une ébauche du tiens
3
Utilisateur anonyme
19 mai 2012 à 17:48
La question était :
En fait je souhaiterai qu'il parcours toute la largeur X de l'écran, une fois arrivé a droite, il descend d'un pixel sur la ligne Y, jusqu'a arrivé à x=1279 & y = 760, ou meme mieu, sans lui donné les dimentions de l'écran.

Et puis tu utilises là une API ça fait plutôt moche.
Tu peux faire plus simple :
Dim b As New Bitmap(Screen.PrimaryScreen.WorkingArea.Width, Screen.PrimaryScreen.WorkingArea.Height)
Dim g As Graphics = Graphics.FromImage(b)
g.CopyFromScreen(New Point(0, 0), New Point(0, 0), Screen.PrimaryScreen.WorkingArea.Size)

For x = 0 To b.Width - 1
For y = 0 To b.Height - 1
If b.GetPixel(x, y) = Color.FromArgb(255, 255, 255) Then
MessageBox.Show(String.Format("Couleur blanche trouvée sur x={0} et y={1}", x, y))
End If
Next
Next
3
KcHeY
Messages postés
261
Date d'inscription
dimanche 23 mai 2004
Statut
Membre
Dernière intervention
22 septembre 2012

19 mai 2012 à 17:35
Bonjour banana32,

Je récupère la couleur du pixel à l'écran sans passer par un screen de l'ecran.
Ici J'appui sur la form, je relache ma souris sur le pixel désiré.
Mes labels affichent les coordonnées du pixel et sa couleur.

 Private Sub Form1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseUp
        Dim pt As Point = MousePosition()
        Dim colorVal As Int32 = GetPixel(desktopDc, CType(pt.X, Int16), CType(pt.Y, Int16))
        Dim r As Int32 = colorVal And &HFF
        Dim g As Int32 = (colorVal And &HFF00) >> 8
        Dim b As Int32 = (colorVal And &HFF0000) >> 16
        Dim c As Color = Color.FromArgb(r, g, b)
        'change la couleur de fond de la form
        Me.BackColor = c

        Label1.Text = "R,G,B= " & r & ", " & g & ", " & b
        Label2.Text = "mouse(x,y)= " & MousePosition.X & " " & MousePosition.Y
    End Sub



Si je veux savoir si la couleur du pixel est présente sur l'écran je fais :

Private Sub Timer2_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer2.Tick



        Dim colorVal As Int32 = GetPixel(desktopDc, CType(LocationX, Int16), CType(LocationY, Int16))
        Dim r As Int32 = colorVal And &HFF
        Dim g As Int32 = (colorVal And &HFF00) >> 8
        Dim b As Int32 = (colorVal And &HFF0000) >> 16
        Dim c As Color = Color.FromArgb(r, g, b)
        If Label1.Text.Contains("255, 255, 255") Then 'si je tombe sur un pixel de la couleur rvb(255,255,255), je m'en informe via messagebox.
        Timer2.Enabled = False
        Timer2.Stop()
        MessageBox.Show("couleur trouvé en " & LocationX & "," & LocationY)
        Else
        If LocationX = 1279 Then
        LocationY += 1
        LocationX = 0
        Else
        LocationX += 1
        Label1.Text = "R,G,B= " & r & ", " & g & ", " & b
        Label2.Text = "mouse(x,y)= " & LocationX & " " & LocationY
        Me.BackColor = c
        End If
        End If


Mais ça passe par un timer...
0
KcHeY
Messages postés
261
Date d'inscription
dimanche 23 mai 2004
Statut
Membre
Dernière intervention
22 septembre 2012

19 mai 2012 à 18:01
1000 fois plus rapide donc 100 merci
C'est l'utilisation d'API qui réduit la vitesse ?
Bonne journée merci
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Utilisateur anonyme
19 mai 2012 à 18:08
C'est l'utilisation d'API qui réduit la vitesse ?
Je ne sais pas.
Tu peux toujours poster un nouveau sujet pour poser cette question.
0
KcHeY
Messages postés
261
Date d'inscription
dimanche 23 mai 2004
Statut
Membre
Dernière intervention
22 septembre 2012

19 mai 2012 à 18:10
Ok ok dans tout les cas merci encore, ça fonctionne au top!
0
Utilisateur anonyme
19 mai 2012 à 19:11
Remarque : Pour analyser encore plus rapidement, tu peux aussi passer des bitmaps de différentes portions d'écran à plusieurs threads (en paramètre de la méthode Start du thread) ce qui réduira considérablement les temps de calcul.
0
KcHeY
Messages postés
261
Date d'inscription
dimanche 23 mai 2004
Statut
Membre
Dernière intervention
22 septembre 2012

19 mai 2012 à 19:19
Très bonne remarque merci :)
0
KcHeY
Messages postés
261
Date d'inscription
dimanche 23 mai 2004
Statut
Membre
Dernière intervention
22 septembre 2012

19 mai 2012 à 19:42
Il va falloir que j'apprenne à gérer les thread^^
Par exemple tout à l'heure j'ai voulu mettre cette action dans un backgroundWorker, mais je pouvais pas cibler ma forme.
Il faudrai que je relise tout les postes car je me rapel que NHenry m'avais redirigé vers une source qui parlé du thread autrement que par le bawkgroundworker.
0
Utilisateur anonyme
19 mai 2012 à 20:02
mais je pouvais pas cibler ma forme

C'est à dire ?
0
KcHeY
Messages postés
261
Date d'inscription
dimanche 23 mai 2004
Statut
Membre
Dernière intervention
22 septembre 2012

19 mai 2012 à 20:30
Je viens de rééssayer et ça fonctionne.
Désolé j'ai dis une bêtise, mais de tête l'erreur de tout à l'heure me parler de piles.... x) et que je ne pouvais pas faire appel à une form ou je ne sais quoi lancé depuis un autre thread.
Pour ce qui est de portionner l'écran, il faudrai que j'analyse du point x,y de chaque coin de l'écran jusqu'au centre de l'écran.
Donc ce que je dois faire à mon avis :

 Dim b As New Bitmap(Screen.PrimaryScreen.WorkingArea.Width / 2, Screen.PrimaryScreen.WorkingArea.Height /2)
        Dim g As Graphics = Graphics.FromImage(b)


C'est bien ça ?

Si je fais ça j'analyse seulement les quart supérieur gauche de l'ecran ?
0
KcHeY
Messages postés
261
Date d'inscription
dimanche 23 mai 2004
Statut
Membre
Dernière intervention
22 septembre 2012

19 mai 2012 à 20:36
En fait je t'ai dis que ça fonctionne mais ça trouve pas le pixel si je passe par BackgroungWorker
Je le lance comme ça :

BackgroundWorker1.RunWorkerAsync()


Dans le BW je lance ma fonction.

Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        Timer1.Enabled = False
        Timer1.Stop()
        rvb()
    End Sub


Mais ça ne trouve pas le pixel.
0
KcHeY
Messages postés
261
Date d'inscription
dimanche 23 mai 2004
Statut
Membre
Dernière intervention
22 septembre 2012

19 mai 2012 à 21:28
Je sais pas ce que j'ai bidouiller mais ça ne fonctionne plus x)

************** Texte de l'exception **************
System.ArgumentOutOfRangeException: InvalidArgument=La valeur '11' n'est pas valide pour 'SelectedIndex'.
Nom du paramètre : SelectedIndex
à System.Windows.Forms.ListBox.set_SelectedIndex(Int32 value)
à Boss_V1.ChercheColorPixel.rvb() dans C:\Users\Laura\Desktop\Boss V2\ChercheColorPixel.vb:ligne 46
à Boss_V1.Boss.ListBoxExecute_SelectedIndexChanged(Object sender, EventArgs e) dans C:\Users\Laura\Desktop\Boss V2\Boss.vb:ligne 147
à System.Windows.Forms.ListBox.OnSelectedIndexChanged(EventArgs e)
à System.Windows.Forms.ListBox.set_SelectedIndex(Int32 value)
à Boss_V1.Boss.Timer1_Tick(Object sender, EventArgs e) dans C:\Users\Laura\Desktop\Boss V2\Boss.vb:ligne 174
à System.Windows.Forms.Timer.OnTick(EventArgs e)
à System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m)
à System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

Pourtant je ne lui dis pas + 11 mais + 5.. sachant qu'il se trouve sur l'index 0.
Je sais vraiment pas ce que j'ai bidouillé.
Je te montre mon code tu y trouveras peut-être l'erreur.
Merci

Module ChercheColorPixel
    Private Declare Function SetCursorPos& Lib "user32" (ByVal X As Integer, ByVal Y As Integer)
    Dim Debut As String
    Dim Fin As String
    Dim d As String
    Dim RR As String
    Dim VV As String
    Dim BB As String
    Private desktopDc As IntPtr

    Sub rvb()
        Dim b As New Bitmap(Screen.PrimaryScreen.WorkingArea.Width, Screen.PrimaryScreen.WorkingArea.Height)
        Dim g As Graphics = Graphics.FromImage(b)
        g.CopyFromScreen(New Point(0, 0), New Point(0, 0), Screen.PrimaryScreen.WorkingArea.Size)

        d = "<CherchePixelColor> r=" 'd=chaine début
        Debut = InStr(1, Boss.ListBoxExecute.SelectedItem, d)  ' Position du <
        Fin = InStr(1, Boss.ListBoxExecute.SelectedItem, ",v=")   ' Position du <debutx =
        RR = Mid$(Boss.ListBoxExecute.SelectedItem, Debut + d.Length, Fin - Debut - d.Length)

        d = ",v=" 'd=chaine début
        Debut = InStr(1, Boss.ListBoxExecute.SelectedItem, d)  ' Position du <
        Fin = InStr(1, Boss.ListBoxExecute.SelectedItem, ",b=")   ' Position du <debutx =
        VV = Mid$(Boss.ListBoxExecute.SelectedItem, Debut + d.Length, Fin - Debut - d.Length)

        d = ",b=" 'd=chaine début
        Debut = InStr(1, Boss.ListBoxExecute.SelectedItem, d)  ' Position du <
        Fin InStr(1, Boss.ListBoxExecute.SelectedItem, ".")   ' Position du <debutx
        BB = Mid$(Boss.ListBoxExecute.SelectedItem, Debut + d.Length, Fin - Debut - d.Length)
        Thread.Sleep(200)
        For x = 0 To b.Width - 1
            For y = 0 To b.Height - 1
                If b.GetPixel(x, y) = Color.FromArgb(RR, VV, BB) Then
                    Thread.Sleep(200)
                    SetCursorPos&(x, y)
                    Boss.Timer1.Interval = 100
                    Boss.Timer1.Enabled = True
                    Boss.Timer1.Start()
                Else
                    Thread.Sleep(200)
                    Boss.Timer1.Enabled = True
                    Boss.Timer1.Interval = 100
                    Boss.Timer1.Start()
                    Boss.ListBoxExecute.SelectedIndex = Boss.ListBoxExecute.SelectedIndex + 5
                End If
            Next
        Next
    End Sub
End Module
0
KcHeY
Messages postés
261
Date d'inscription
dimanche 23 mai 2004
Statut
Membre
Dernière intervention
22 septembre 2012

19 mai 2012 à 21:35
Ah j'ai compris, je sort pas de la boucle je crois.
Du coup il relance mon timer sans sortir de la boucle.
Mais quand je fais exit sub ça ne l'arrete pas.
0
KcHeY
Messages postés
261
Date d'inscription
dimanche 23 mai 2004
Statut
Membre
Dernière intervention
22 septembre 2012

19 mai 2012 à 21:50
Bon j'ai résolu le problème ouf.

For x = 0 To b.Width - 1
            For y = 0 To b.Height - 1
                If b.GetPixel(x, y) = Color.FromArgb(RR, VV, BB) Then
                    SetCursorPos&(x, y)
                    Boss.Timer1.Enabled = True
                    Boss.Timer1.Interval = 100
                    Boss.Timer1.Start()
                End If
            Next
        Next


Mais comment gérer le retour ?
C'est à dire, si sur tout l'écran la couleur recherché n'est pas trouvé, descendre de 5 index dans ma listbox.
Parce que si je fais un else il descend de + 5 autant de fois qu'il ne trouve pas le pixel.

Merci
0
Utilisateur anonyme
19 mai 2012 à 22:05
Tu vas finir par trouver tout seul
SetCursorPos encore une API
Cursor.Position permet de déterminer la position ou déplacer le curseur.
0
KcHeY
Messages postés
261
Date d'inscription
dimanche 23 mai 2004
Statut
Membre
Dernière intervention
22 septembre 2012

19 mai 2012 à 22:15
Si je depasse les next, c'est qu'il n'y a pas de pixel détécté, c'est ça ?
Sinon pour Cursor.Position, fonctionne sur n'importe quelle fenêtre ?
En fait je fais un programme d'automatisation, tien je te le montre :p
0
KcHeY
Messages postés
261
Date d'inscription
dimanche 23 mai 2004
Statut
Membre
Dernière intervention
22 septembre 2012

19 mai 2012 à 22:21
Cool j'ai réussi à gérer le retour.
Merci à toi pour le partage de savoir et de temps.
Sinon tu as quoi contre les apis :p ?
0
Utilisateur anonyme
19 mai 2012 à 22:24
Si je depasse les next, c'est qu'il n'y a pas de pixel détécté, c'est ça ?
oui
Sinon pour Cursor.Position, fonctionne sur n'importe quelle fenêtre ?
Fais donc un essai :
cursor.position = new point(20,20)

messagebox.show(string.format("x={0}  y={1}",cursor.position.x,cursor.position.y))
0
Utilisateur anonyme
19 mai 2012 à 22:32
Je n'ai rien contre mais mieux vaut utiliser les outils du framework puisqu'ils existent
0