Screen capture issue

Just starting out? Need help? Post your questions and find answers here.
Etayson
Enthusiast
Enthusiast
Posts: 110
Joined: Sun Jun 05, 2016 5:01 pm

Screen capture issue

Post by Etayson »

Here is a small piece of code that captures the screen. Over time (It’s always different) the capture stops working(BitBlt_ doesn`t capture new image) or breaks with an error => ImageOutput(0) is NULL (0 value)
What is the problem can be?
[Windows 10, Unicode mode, threadSafe, PB 5.31 x64]

Code: Select all

Procedure capturescreen(i)
  Protected srcDC, trgDC, BMPHandle.l, dm.DEVMODE, hDC, resultImg = 0, bitBlt, outputId, ScreenWidth, ScreenHeight, wx, wy, ci.CURSORINFO
  Protected xpos, ypos
  
  
  Repeat
    ScreenWidth = GetSystemMetrics_(#SM_CXSCREEN)
    ScreenHeight = GetSystemMetrics_(#SM_CYSCREEN)
    If wx<>ScreenWidth Or wy<>ScreenHeight
      wx = ScreenWidth      
      wy = ScreenHeight
      
      If IsImage(0)
        FreeImage(0)
      EndIf
      
      If Not CreateImage(0, ScreenWidth, ScreenHeight, 24)        
        Break
      EndIf
    EndIf
    srcDC = GetDC_(#Null);CreateDC_("DISPLAY", "", "", #Null)
    trgDC = CreateCompatibleDC_(srcDC)
    BMPHandle = CreateCompatibleBitmap_(srcDC, ScreenWidth, ScreenHeight)
    SelectObject_( trgDC, BMPHandle)    
    bitBlt = BitBlt_(trgDC, 0, 0, ScreenWidth, ScreenHeight, srcDC, 0, 0, #SRCCOPY)    
    
    hDC = StartDrawing(ImageOutput(0) )     
    DrawImage(BMPHandle, 0, 0)
    ci\cbSize = SizeOf(CURSORINFO)
    GetCursorInfo_(@ci)
    xpos = ci\ptScreenPos\x
    ypos = ci\ptScreenPos\y
    GetIconInfo_(ci\hCursor, iconinfo.ICONINFO)      
    DrawIconEx_(hDC, xpos - iconinfo\xHotspot ,ypos - iconinfo\yHotspot, ci\hCursor, 32, 32, 0, 0, #DI_NORMAL|#DI_COMPAT )    
    StopDrawing() 
    
    CopyImage(0, 5)
    ResizeImage(5, 580 , 580)
    SetGadgetAttribute(0, #PB_Canvas_Image , ImageID(5))
    FreeImage(5)
    
    DeleteObject_(trgDC)
    ReleaseDC_(BMPHandle, srcDC)
    ReleaseDC_(#Null, srcDC)
    DeleteObject_(BMPHandle)         
    Delay(50)
  ForEver
  
  If IsImage(0)
    FreeImage(0)
  EndIf
  
EndProcedure

If OpenWindow(0, 0, 0, 600, 600, "CaptureScreenInUnicodeMode", #PB_Window_SystemMenu | #PB_Window_ScreenCentered |#PB_Window_SizeGadget | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
  
  CanvasGadget(0,  10, 10, 580, 580)   
  CreateThread(@capturescreen(),0)
  Repeat
    Event = WindowEvent() 
    Delay(10)    
  Until Event = #PB_Event_CloseWindow
  
EndIf
Last edited by Etayson on Fri Apr 26, 2024 7:27 pm, edited 3 times in total.
User avatar
jacdelad
Addict
Addict
Posts: 2032
Joined: Wed Feb 03, 2021 12:46 pm
Location: Riesa

Re: Screen capture issue

Post by jacdelad »

Hi,
I have no problems here (Windows 10 x64, PB 6.11 Beta 1 x64 ASM). What is "over time"? Some seconds, minutes, hours??

A thing to mention:
The whole ScreenWidth/ScreenHeight-thing, do you expect the screen to change resolution? If not, I wouldn't put this inside the loop.
Good morning, that's a nice tnetennba!

PureBasic 6.21/Windows 11 x64/Ryzen 7900X/32GB RAM/3TB SSD
Synology DS1821+/DX517, 130.9TB+50.8TB+2TB SSD
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8452
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: Screen capture issue

Post by netmaestro »

Try with this at the top of your code:

Code: Select all

#CAPTUREBLT = $40000000 
And then apply the flag to your BitBllt command:

Code: Select all

bitBlt = BitBlt_(trgDC, 0, 0, ScreenWidth, ScreenHeight, srcDC, 0, 0, #SRCCOPY|#CAPTUREBLT)
If you don't use the CAPTUREBLT flag layered windows won't get included.
BERESHEIT
Etayson
Enthusiast
Enthusiast
Posts: 110
Joined: Sun Jun 05, 2016 5:01 pm

Re: Screen capture issue

Post by Etayson »

jacdelad wrote: Wed Apr 24, 2024 5:12 pm Hi,
I have no problems here (Windows 10 x64, PB 6.11 Beta 1 x64 ASM). What is "over time"? Some seconds, minutes, hours??

A thing to mention:
The whole ScreenWidth/ScreenHeight-thing, do you expect the screen to change resolution? If not, I wouldn't put this inside the loop.
I just took out a piece of code. In fact, there is quite a large program for remote access. And yes, it needs to track changes in the size of the desktop. This particular code breaks for me in different ways, sometimes after 5 minutes, sometimes after a minute..
Now i have error =>the specified #Image is not initialised.
I've been dancing with a tambourine for a week now around screen capture, I've already tried different capture options. Always the same image crashes or the capture is not updated.
Etayson
Enthusiast
Enthusiast
Posts: 110
Joined: Sun Jun 05, 2016 5:01 pm

Re: Screen capture issue

Post by Etayson »

netmaestro wrote: Wed Apr 24, 2024 5:36 pm Try with this at the top of your code:

Code: Select all

#CAPTUREBLT = $40000000 
And then apply the flag to your BitBllt command:

Code: Select all

bitBlt = BitBlt_(trgDC, 0, 0, ScreenWidth, ScreenHeight, srcDC, 0, 0, #SRCCOPY|#CAPTUREBLT)
If you don't use the CAPTUREBLT flag layered windows won't get included.
I tried this and tried with this

Code: Select all

DeskDC = GetDC_(GetDesktopWindow_())      
      If DeskDC        
        BitBlt_(hDC,0,0,w,h,DeskDC,0,0,#SRCCOPY|#CAPTUREBLT)        
      EndIf        
      ReleaseDC_(GetDesktopWindow_(),DeskDC)
The same issue.
PeDe
Enthusiast
Enthusiast
Posts: 305
Joined: Sun Nov 26, 2017 3:13 pm

Re: Screen capture issue

Post by PeDe »

Perhaps the error is in 'BMPHandle.l''? Integer would be correct.

Peter
Etayson
Enthusiast
Enthusiast
Posts: 110
Joined: Sun Jun 05, 2016 5:01 pm

Re: Screen capture issue

Post by Etayson »

PeDe wrote: Wed Apr 24, 2024 5:54 pm Perhaps the error is in 'BMPHandle.l''? Integer would be correct.
Peter
Yeah, it was originally BMPHandle.i then I saw somewhere that use BMPHandle.l. Anyway result is the same.
PeDe
Enthusiast
Enthusiast
Posts: 305
Joined: Sun Nov 26, 2017 3:13 pm

Re: Screen capture issue

Post by PeDe »

Windows 7 x64
The Task Manager shows me that the number of GDI objects is constantly increasing. I think only 10,000 are allowed, but I'm not sure. With my slow PC it takes a long time to count up, I've only cracked the 3,000 mark.

Edit:
Here there was the first visible error with 9,999 GDI objects. Then the value fluctuated around 10,000 until there was the error with 'The specified #Image is not initialized.

Peter
Etayson
Enthusiast
Enthusiast
Posts: 110
Joined: Sun Jun 05, 2016 5:01 pm

Re: Screen capture issue

Post by Etayson »

PeDe wrote: Wed Apr 24, 2024 6:39 pm Windows 7 x64
The Task Manager shows me that the number of GDI objects is constantly increasing. I think only 10,000 are allowed, but I'm not sure. With my slow PC it takes a long time to count up, I've only cracked the 3,000 mark.

Edit:
Here there was the first error with 9.999 GDI objects.

Peter
Exactly, you're right GetIconInfo_ is produce GDI objects.. need to be clear i think with DeleteObject_(iconinfo\hbmMask)
DeleteObject_(iconinfo\hbmColor)

Edit: Thanks Peter, you save my brain. Now all works like sharm.
Etayson
Enthusiast
Enthusiast
Posts: 110
Joined: Sun Jun 05, 2016 5:01 pm

Re: Solved! Screen capture issue

Post by Etayson »

Hi, need advice on how to improve the operation of the screen capture procedure and transmitting it over the Internet.
There is image 0, into which the screen is copied using BitBilt, there is also other buffer in memory where stored previous frame.
The image 0 is divided into rectangles for example, 20*12 pixels. Each rectangle in current frame is compared with the previous frame and if there is a discrepancy, then this rectangle is copied to the accumulation buffer.
Then this accumulation buffer is encoded by a Jpeg plugin and transmitted via the Internet.
But there is a problem with the artifacts. When simply encode the some image using Jpeg, it comes out fine. But if encode a buffer consisting of rectangles from different screen chats, then some ugly artifacts appear.
The goal is to minimize traffic as much as possible, but at the same time ensure that the image is acceptable. Therefore, using plugins like PNG is not an option.
Image
Edit: The artifact appears when not the entire frame is transmitted, but some pieces of the frame. For example, when the cursor moves, only rectangles located in the cursor area are transmitted. And this is where these artifacts appear.
Post Reply