Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Se puede leer pixels del monitor fuera de nuestro programa?

Iniciado por Mercuriot, 22 de Junio de 2008, 10:14:57 PM

« anterior - próximo »

Mercuriot

Es decir, quiero capturar los valores RGB de cada pixel de ciertas regiones de la pantalla (las esquinas y bordes) para luego sacar el valor RGB predominante de cada una de esas regiones y enviar estos valores finales a un dispositivo electrónico conectado a la PC.

La parte electrónica y la interface ya esta, pero no se cono obtener los valores RGB, ¿alguna idea?
Quizá sea fácil pero jamás programé en bajo nivel... son mis primeras experiencias, en mi presentación lo explico bien.

Esa "captura de valores RGB" necesito que sea de cualquiera de estas 2 formas, que entiendo que son procedimientos bastante diferentes (no?):

* En tiempo real, sea lo que sea que se este ejecutando o mostrando en ese momento por el monitor.

* O que, cuando abra un reproductor de video mediante un codec o filtro (supongo que administrado por FFDSHOW), se tomen los valores RGB de regiones que estén dentro de la resolución del video mostrado (de la peli quiero decir).

Espero haberme expresado lo más correctamente posible. Disculpen si estoy pidiendo algo imposible o si postié en el lugar incorrecto.

Espero sus ideas, gracias.

fiero

Hola Mercuriot,

Puedes obtener el tamaño del escritorio asi:

tx=GetSystemMetrics(SM_CXSCREEN);
ty=GetSystemMetrics(SM_CYSCREEN);

Ahora creas un BITMAP y un CDC (mfc) con las dimensiones del escritorio:

unsigned char *dat;
CDC dc;
HBITMAP hBitmap;
BITMAPV4HEADER info;
ZeroMemory( &info, sizeof(BITMAPV4HEADER) );
info.bV4Size=sizeof(BITMAPV4HEADER);
info.bV4Width=tx;
info.bV4Height=-ty;
info.bV4Planes=1;
info.bV4BitCount=24;
hBitmap=CreateDIBSection(NULL,(BITMAPINFO*)&info,DIB_RGB_COLORS,(void**)&dat,NULL,0);
dc.CreateCompatibleDC(NULL);
dc.SelectObject(hBitmap);

Ahora en "dat" tienes un puntero donde podrás leer directamente los pixels. Solo tienes que copiar el contenido del escritorio a tu bitmap (esta es la parte que tienes que repetir si quieres leer los pixels en tiempo real):

CDC *dcDesktop;
dcDesktop=CWnd::GetDesktopWindow()->GetDC();
dc.BitBlt(0, 0, tx, ty, dcDesktop, 0, 0, SRCCOPY);
CWnd::GetDesktopWindow()->ReleaseDC(dcDesktop);

Despues de esto puedes leer los pixeles a través del puntero "dat". CDC es una clase de las MFC, pero puedes hacer lo mismo con los DC del API de windows.

saludos!
www.videopanoramas.com Videopanoramas 3D player

[EX3]

Ya que leo en tu presentacion que te manejas tambien con el Visual Basic 6 aqui un codigo similar y quizas algo mas sencillo al que te han puesto arriba en C++ pero en Visual Basic:

Abre un proyecto nuevo y mete en el formulario un PictureBox y un Timer a 1 milisegundo de intervalo y despues copia todo el codigo en formulario:

Option Explicit

' Declaraciones para leer los pixeles de la pantalla:
Private Declare Function GetPixel Lib "gdi32" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long) As Long
Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long) As Long
Private Declare Function GetDesktopWindow Lib "user32" () As Long

' Declaracion de la API para obtener la posicion del cursor del raton en la pantalla:
Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long

Private Type POINTAPI
   X As Long
   Y As Long
End Type

Dim desktopHwnd As Long, desktopDC As Long
Dim cursor As POINTAPI
Dim Color As Long, R As Long, G As Long, B As Long ' Color y componentes del color.

Private Sub Form_Load()
   Me.AutoRedraw = True
   desktopHwnd = GetDesktopWindow() ' Obtenemos el id del escritorio.
   desktopDC = GetDC(desktopHwnd) ' Obtenemos el puntero al contexto del escritorio.
End Sub

Private Sub Form_Unload(Cancel As Integer)
   Call ReleaseDC(desktopHwnd, desktopDC) ' Liberamos el puntero al contexto.
   End
End Sub

' Devuelve los componentes rojo, verde y azul de un color:
Private Sub GetRGB(ByVal Color As Long, ByRef Red As Long, ByRef Green As Long, ByRef Blue As Long)
   Blue = (Color And &HFF0000) / (2 ^ 16)
   Green = (Color And &HFF00&) / (2 ^ 8)
   Red = (Color And &HFF&)
End Sub

Private Sub Timer1_Timer()
   Call GetCursorPos(cursor) ' Leemos la posicion del cursor en pantalla.
   Color = GetPixel(desktopDC, cursor.X, cursor.Y) ' Leemos el valor del pixel segun la coordenada del cursor.
   Picture1.BackColor = Color ' Mostramos el color en el PictureBox.
   
   ' Mostramos los valores RGB del color:
   Call GetRGB(Color, R, G, B)
   
   Me.Cls
   Me.Print "Rojo: " & CStr(R)
   Me.Print "Verde: " & CStr(G)
   Me.Print "Azul: " & CStr(B)
End Sub

El proyecto simplemente es un formulario donde se mostrara el color que hay en las coordenadas del cursor del raton y los valores por separado de sus componentes en tiempo real. Si necesitas saber las dimensiones en pixeles de la resolucion de pantalla usa estas dos llamadas:
Width = Screen.Width \ Screen.TwipsPerPixelX
Height = Screen.Height \ Screen.TwipsPerPixelY

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

Mercuriot

EX3, gracias por el codigo pero ya lo tenía y de todas formas me presenta 2 problemas: la variable COLOR tira error por valer -1 y ademas que solo me sirve para el formulario que se este mostrando, no para, por ejemplo, una ventana del Winamp donde se muestre un video.

Fiero, la verdad que no entendi te entendi nada :oops:
pero me puse a leer por internet y parece que puede andar, me bajare el Visual C y despues  comento que tal me fue, muchas gracias.


Y sobre lo de hacerlo parecido a un filtro de codecs... alguien sabe algo?

[EX3]

Cita de: "Mercuriot"EX3, gracias por el codigo pero ya lo tenía y de todas formas me presenta 2 problemas: la variable COLOR tira error por valer -1 y ademas que solo me sirve para el formulario que se este mostrando, no para, por ejemplo, una ventana del Winamp donde se muestre un video.
Mi codigo lee cualquier pixel de la pantalla, no solo del propio formulario. Es mas, acabo de probar reproduciendo un video en Windows Media Player y lee los pixeles del video (ha leido hasta los pixeles de una ventana renderizando graficos con DirectX). De por si, mi codigo si lo adaptas, lo pdorias correr en un programa sin ventana, solo codigo (programando un timer o un bucle, sin usar el control Timer). Revisalo por que te puede ser util y esta funcionando.

Sobre que la variable color tire -1, si trabajas en RGB, como en mi codigo, dificilmente podras obtener un valor por debajo de 0, -1 seria blanco en un rango ARGB/RGBA (&HFFFFFFFF), asi que algo has hecho mal al copiar el codigo de arriba.

Salu2...

P.D.: Y este codigo esta funcionando en Vista.
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.