Read pixels from another program.
Read pixels from another program.
How can I read pixels from whatever program that is displaying screen data on whatever part of the screen I instruct the program to look at?
For this project, reading a single pixel from a few sceeen coordinates will be fine.
I will eventually want an overlay to float above the pixels being read at the time.
Any ideas or similar projects?
For this project, reading a single pixel from a few sceeen coordinates will be fine.
I will eventually want an overlay to float above the pixels being read at the time.
Any ideas or similar projects?
Re: Read pixels from another program.
There are 2 methods to program bugless.
But only the third works fine.
Win10, Pb x64 5.71 LTS
But only the third works fine.
Win10, Pb x64 5.71 LTS
Re: Read pixels from another program.
Thanks, I was hoping for something that could read 9 individual pixels, in less than 1 millisecond. To be honest I only want to check if it is black or white (or close to either).
I saw the use of GetPixel_() in that thread, tried that out, and it takes around 18 milliseconds to get one single pixel's colour. I won't be able to use that.
I also see BitBlt being used, and said to be faster, but I don't really understand how it is used yet. Is it possible to quickly read one single pixels colour with BitBlt?
I saw the use of GetPixel_() in that thread, tried that out, and it takes around 18 milliseconds to get one single pixel's colour. I won't be able to use that.
I also see BitBlt being used, and said to be faster, but I don't really understand how it is used yet. Is it possible to quickly read one single pixels colour with BitBlt?
Re: Read pixels from another program.
Would it be easier to do If I only wanted to read from a single window of another running program?
Re: Read pixels from another program.
Just wondering, why do you need to read other programs pixels ?
Re: Read pixels from another program.
I'm planning a little visual communication setup - I have written the encoder program, which will make 8 boxes black or white depending if the bit of data is set, now I want to write a decoder, and I want the 2 to be seperate for various reasons.Fred wrote: Sun Aug 25, 2024 7:44 pm Just wondering, why do you need to read other programs pixels ?
I also plan to get a program to read the score or other data from a retro computer emulator during gameplay.
Re: Read pixels from another program.
Looks cool 
Re: Read pixels from another program.
Maybe try this non-threaded version (I haven't timed it). You can use Red(), Green() and Blue() on the result if needed; or for your black/white test the result will simply be #Black or #White.matalog wrote: Sun Aug 25, 2024 7:05 pmI saw the use of GetPixel_() in that thread, tried that out, and it takes around 18 milliseconds to get one single pixel's colour. I won't be able to use that.
Code: Select all
Procedure PixelColor(x,y)
c=-1
hDC=GetDC_(0)
If hDC
c=GetPixel_(hDC,x,y)
ReleaseDC_(0,hDC)
EndIf
ProcedureReturn c
EndProcedure
Re: Read pixels from another program.
I was just about to post a similar approach as BarryG.
Scanning 9 Pixels takes around 5 ms on my outdated Laptop...
(Activate the DPI-Aware switch)
Scanning 9 Pixels takes around 5 ms on my outdated Laptop...
(Activate the DPI-Aware switch)
Code: Select all
Define hwnd, hdc, pt.Point,p1.Point, rc.RECT, x, y
Define wid = 3, hig = 3,size = 50
Dim color(wid,hig)
OpenWindow(0,0,0,wid*size,hig*size,"", #PB_Window_Tool|#PB_Window_SystemMenu)
CanvasGadget(0,5,5,WindowWidth(0)-10,WindowHeight(0)-10)
StickyWindow(0, 1)
Repeat
Define time = ElapsedMilliseconds()
If pt\x <> DesktopMouseX() Or pt\y <> DesktopMouseY()
pt\x = DesktopMouseX()
pt\y = DesktopMouseY()
hwnd = WindowFromPoint_(PeekQ(pt))
If hwnd
hdc = GetDC_(hwnd)
If hdc
For y = 0 To hig-1
For x = 0 To wid-1
p1\x = pt\x + x - wid/2
p1\y = pt\y + y - hig/2
If ScreenToClient_(hwnd , p1)
color(x, y) = GetPixel_(hdc, p1\x, p1\y)
EndIf
Next
Next
ReleaseDC_(hwnd, hdc)
EndIf
EndIf
SetWindowTitle(0, Str(ElapsedMilliseconds() - time) + " ms")
StartDrawing(CanvasOutput(0))
For y = 0 To hig-1
For x = 0 To wid-1
Box(OutputWidth()/wid*x,OutputHeight()/hig*y,OutputWidth()/wid,OutputHeight()/hig,color(x,y))
Next
Next
StopDrawing()
EndIf
While WindowEvent():If Event()=#PB_Event_CloseWindow:End:EndIf:Wend
ForEver
Re: Read pixels from another program.
Thanks, yes, the way you use GetPixel_() seems to be faster.
The pixel coordinates seem to be different from purebasic, coordinates, is that possible?
The pixel coordinates seem to be different from purebasic, coordinates, is that possible?
Re: Read pixels from another program.
the coordinates used in GetPixel_ are relative to the window (client area) rather than the entire screen. The origin (0, 0) in window coordinates is usually the top-left corner of the window's client area.
Therefore I use ScreenToClient_ to convert the screen coordinates (DesktopMouseX() / DesktopMouseY()) to the windows coordinates.
Also the DPI scaling affects the coordinates, that's why you have to enable the "Enable DPI aware executable" switch in the Compiler Options.
Therefore I use ScreenToClient_ to convert the screen coordinates (DesktopMouseX() / DesktopMouseY()) to the windows coordinates.
Also the DPI scaling affects the coordinates, that's why you have to enable the "Enable DPI aware executable" switch in the Compiler Options.
Re: Read pixels from another program.
Can you see why this is taking a much longer time in my program, I would like it to be a procedure:
It seems to take around 150 ms to read the 9 pixels.
Code: Select all
Global lastcol.i=1234,newcol.i=0,tot.i=0
Global Dim pi.i(9)
Procedure PixelColor(x,y)
Shared pi
c=-1
hDC=GetDC_(0)
If hDC
For a=1 To 9
pi(a)=GetPixel_(hDC,a*50-20+50,100)
;SetPixel_(hDC,a*50-20+1+50,100+1,255)
Next
ReleaseDC_(0,hDC)
EndIf
ProcedureReturn c
EndProcedure
StartTime.q = ElapsedMilliseconds()
PixelColor(0,0)
newcol=pi(9)
Debug ElapsedMilliseconds() - StartTime
Re: Read pixels from another program.
Nevermind, I got that just as fast as yours:
Code: Select all
Global lastcol.i=1234,newcol.i=0,tot.i=0
Define hwnd, hdc, pt.Point,p1.Point, rc.RECT, x, y
Define wid = 3, hig = 3,size = 50
Dim color(wid,hig)
Global Dim pi.i(9)
Procedure PixelColor(x,y)
Shared pi,pt,pi
c=-1
hwnd = WindowFromPoint_(PeekQ(pt))
hdc = GetDC_(hwnd)
If hDC
For a=1 To 9
pi(a)=GetPixel_(hDC,a*50-20+50,100)
;SetPixel_(hDC,a*50-20+1+50,100+1,255)
Next
ReleaseDC_(0,hDC)
EndIf
ProcedureReturn c
EndProcedure
StartTime.q = ElapsedMilliseconds()
PixelColor(0,0)
newcol=pi(9)
Debug ElapsedMilliseconds() - StartTime
Re: Read pixels from another program.
To test if GetPixel_() works for what I want I have 2 programs here that should be run together. Their debugged output's should be the same if GetPixel_() was working as I expected.
What is causing the strangley randomly wrong debugged numbers in the first program?
Run the first program first, then, it will wait for the second program to be run, and both will print to debug windows.
The second program uses its own image and POINT to test the pixels, the first program uses GetPixel_() on the second program's image.
And the second program.
What is causing the strangley randomly wrong debugged numbers in the first program?
Run the first program first, then, it will wait for the second program to be run, and both will print to debug windows.
The second program uses its own image and POINT to test the pixels, the first program uses GetPixel_() on the second program's image.
Code: Select all
Global lastcol.i=1234,newcol.i=0,tot.i=0
Define hwnd, hdc, pt.Point,p1.Point, rc.RECT
Define wid = 3, hig = 3,size = 50
Dim color(wid,hig)
Global Dim pi.i(9)
Procedure PixelColor(x,y)
Shared pi,pt,pi,p1
c=-1
hwnd = WindowFromPoint_(PeekQ(pt))
hdc = GetDC_(hwnd)
If hDC
For a=1 To 9
p1\x=a*50+3+20
p1\y=100+3
ScreenToClient_(hwnd,p1)
pi(a)=GetPixel_(hDC,p1\x,p1\y)
SetPixel_(hDC,p1\x+1,p1\y+1,255)
SetPixel_(hDC,p1\x+1,p1\y,255)
SetPixel_(hDC,p1\x+1,p1\y-1,255)
SetPixel_(hDC,p1\x,p1\y+1,255)
SetPixel_(hDC,p1\x,p1\y-1,255)
SetPixel_(hDC,p1\x-1,p1\y,255)
SetPixel_(hDC,p1\x-1,p1\y+1,255)
SetPixel_(hDC,p1\x-1,p1\y-1,255)
Next
ReleaseDC_(0,hDC)
EndIf
ProcedureReturn c
EndProcedure
Repeat
PixelColor(0,0)
newcol=pi(9)
If newcol<>lastcol
tot=tot+1
temp=0
For x=1 To 8
power.i=1<<((x-1))
temp=temp+Bool(pi(x)>10000)*power
Next
Debug temp
lastcol=newcol
EndIf
Until tot>60
Code: Select all
Global lastcol.i=1234,newcol.i=0,tot.i=0
#width=500
#height=900
OpenWindow(0,0,0,#width,#height,"Flash Bits")
CreateImage(0,#width,#height)
ImageGadget(0,0,0,#width,#height,ImageID(0))
Global byte.a=0
Global x.i=0
Global flip.a=0
Global temp.a=0
StartDrawing(ImageOutput(0))
Box(0,0,#width,#height,0)
Box(0,0,#width,#height,0)
StopDrawing()
SetGadgetState(0,ImageID(0))
For t=1 To 100
byte=t
StartDrawing(ImageOutput(0))
For x=1 To 8
power.i=1<<((x-1))
Box(x*50,0,50,700,#White*Bool(byte & power))
Next
StopDrawing()
SetGadgetState(0,ImageID(0))
StartDrawing(ImageOutput(0))
Box(9*50,0,40,800,flip*#White)
If flip
flip=0
Else
flip=1
EndIf
temp=0
For x=1 To 8
power.i=Pow(2,x-1)
temp=temp+Bool(Point(x*50+2,100+2)>10000)*power
Next
s$="Point()= "+Str(temp)
Debug s$
StopDrawing()
SetGadgetState(0,ImageID(0))
Event =WindowEvent()
Select Event
Case #PB_Event_CloseWindow
End
EndSelect
Delay(1000)
Next
Repeat
Event =WindowEvent()
Select Event
Case #PB_Event_CloseWindow
End
EndSelect
Until 0
End