Visual Basic - Recorrer la pantalla píxel por píxel

Life is soft - evento anual de software empresarial
 
Vista:

Recorrer la pantalla píxel por píxel

Publicado por ebi (7 intervenciones) el 11/05/2009 18:50:23
Hola,

estoy recorriendo la pantalla para encontrar la localización de un objeto ajeno a mi aplicación. Voy píxel por píxel, buscando el color que yo quiero, rgb(240,240,224).

Lo que pasa es que es muy lento. He puesto "for i = 1 to 1280" y luego "for j = 1 to 1024", los dos con "step 50", y tarda 11 segundos, y tiene el problema de saltárse lo que busco.

Si pongo "step 1" supongo que tardará 2500 veces más (7 horas), lo cual es, lógicamente, inviable. Pero el procesador ni se inmuta, por lo que no sé dónde está el gasto de tiempo.

¿Hay otra forma de recorrer la pantalla en menos tiempo?

El código, de momento, es este:

<code>
Private Declare Function GetPixel Lib "gdi32.dll" (ByVal hdc As Integer, ByVal x As Integer, ByVal y As Integer) As Integer
Private Declare Function GetWindowDC Lib "user32.dll" (ByVal hwnd As Integer) As Integer
Private Declare Function GetDesktopWindow Lib "user32.dll" () As Integer

Dim Kol As Color
Dim Xpix As Integer
Dim Ypix As Integer

Public Function PixelColor(ByVal x As Integer, ByVal y As Integer) As Color
Dim winDc = GetWindowDC(GetDesktopWindow)
Dim color = GetPixel(winDc, x, y).ToString
PixelColor = System.Drawing.ColorTranslator.FromOle(color)
End Function

Public Sub JMScan()
Dim I As Integer
Dim J As Integer

For I = 1 To 1280 Step 50
For J = 1 To 1024 Step 50
Kol = PixelColor(I, J)
If (Kol.R = 240) And (Kol.G = 240) And (Kol.B = 224) Then
MsgBox(I & " x " & J) ' <-- aquí luego pondré otras cosas
End If
Application.DoEvents()
Next J
Next I
MsgBox("Escaneo Terminado")
End Sub
</code>
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder

RE:Recorrer la pantalla píxel por píxel

Publicado por ebi (7 intervenciones) el 12/05/2009 13:28:42
Bueno, lo voy a "solucionar" pidiendo al usuario un punto de partida, y buscar sólo en un rango de 200 x 200 píxeles a partir de ese punto.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Recorrer la pantalla píxel por píxel

Publicado por ebi (7 intervenciones) el 15/05/2009 15:42:31
Pues al final lo que hice fue un "imprimir pantalla" mediante código, guardarlo en una variable bitmap, y analizar esa variable. Es, calculando a ojo y sin exagerar, unas 50000 veces más rápido, para analizar toda la pantalla, que la forma en la que lo hacía en el post original (http://www.lawebdelprogramador.com/news/mostrar_new.php?id=93&texto=Visual+Basic&n1=533061&n2=0&n3=0&n4=0&n5=0&n6=0&n7=0&n8=0&n9=0&n0=0).

Es posible que simulando la pulsación de "imprimir panatalla" funcione, guardando después el clipboard en una variable bitmap, pero no deja de ser chavacano. Así que encontré el código puesto abajo.

El único fallo que le veo es que, si quieres escanear la pantalla muchas veces (por ejemplo dentro de un timer), la memoria RAM se llena a una velocidad alarmante. Con el timer a 20 (50 veces por segundo) tarda en llenar 1GB como unos 2-3 segundos. Funciona, ya que la va vaciando cuando la llena entera (en mi caso 2GB), pero es un cisco, ¿no? ¿No se quemará la ram si dejas el ordenador encendido una semana con el programa abierto?

Intentaré solucionarlo, puede que el problema sea el "Argazkia = Image.FromHbitmap(New IntPtr(hbmp))" que hay al final, ya que IntPtr(hbmp) no se vacía... Bueno, no lo sé.

Agur!


<code>
Const SRCCOPY As Integer = &HCC0020 'no sé para qué sirve, no lo usa
Dim Argazkia As Bitmap 'esta variable contendrá la imagen resultante
Dim ArgZabalera, ArgAltuera As Integer 'argzabalera guardará el ancho de la pantalla en píxeles, y argaltuera el ancho

Public Sub ArgazkiaEgin() 'subrutina a la que llamar para llenar la variable argazkia con lo que haya en ese momento en la pantalla
Dim hsdc, hmdc As Integer
Dim hbmp, hbmpold As Integer
Dim r As Integer

hsdc = CreateDC("DISPLAY", "", "", "")
hmdc = CreateCompatibleDC(hsdc)

ArgZabalera = GetDeviceCaps(hsdc, 8) 'calcula el ancho
ArgAltuera = GetDeviceCaps(hsdc, 10) 'calcula el alto
hbmp = CreateCompatibleBitmap(hsdc, ArgZabalera, ArgAltuera)

hbmpold = SelectObject(hmdc, hbmp)

r = BitBlt(hmdc, 0, 0, ArgZabalera, ArgAltuera, hsdc, 0, 0, 13369376)

hbmp = SelectObject(hmdc, hbmpold)

r = DeleteDC(hsdc)
r = DeleteDC(hmdc)

Argazkia = Image.FromHbitmap(New IntPtr(hbmp))

DeleteObject(hbmp)
End Sub
</code>
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar