Need to improve screen capture speed

Just starting out? Need help? Post your questions and find answers here.
AndyMK
Enthusiast
Enthusiast
Posts: 541
Joined: Wed Jul 12, 2006 4:38 pm
Location: UK

Need to improve screen capture speed

Post by AndyMK »

Hi all, I have been looking in to making a simple remote desktop app and found some good code on the forum. The GDI method works well but is very slow. The clipboard method is very fast but makes clipboard functions useless to other apps while my app is running. I used Blitz+ for a while and it included a function that returned a pointer to the desktop video buffer. Is this possible with Purebasic or is there a faster way to capture the Desktop. I also looked in to a Dx8 method but that was just way over my head. Thanks in advance.

Update:

I just found some code that seems to run very well but i cant seem to resize the image.

Code: Select all

Procedure MakeDesktopScreenshot(ImageNr,x,y,Width,Height) 
   hImage = CreateImage(ImageNr,Width,Height) 
   hDC    = StartDrawing(ImageOutput(imagenr)) 
   DeskDC = GetDC_(GetDesktopWindow_()) 
      BitBlt_(hDC,0,0,Width,Height,DeskDC,x,y,#SRCCOPY) 
   StopDrawing() 
   ReleaseDC_(GetDesktopWindow_(),DeskDC)
   ProcedureReturn hImage 
EndProcedure 

OpenWindow(1,0,0,720,450,"",#PB_Window_SystemMenu|#PB_Window_ScreenCentered) 
  CreateGadgetList(WindowID(1)) 
  hDeskBmp = MakeDesktopScreenshot(2,0,0,1440,900)
  ImageGadget(2,0,0,720,450,hDeskBmp)
  
Repeat
    Delay(100)

    hDeskBmp = MakeDesktopScreenshot(2,0,0,1440,900)
    ;Resize here
    SetGadgetState(2,hDeskBmp)
      
Until WindowEvent()=#PB_Event_CloseWindow
Another Update:

Managed to resize the image by adding

Code: Select all

hImage=ResizeImage(imagenr,720,450)
in between

Code: Select all

StopDrawing()
and

Code: Select all

ReleaseDC_(GetDesktopWindow_(),DeskDC)
but the resize command kills the CPU.

So my question now is, can i resize using a faster method?
User avatar
idle
Always Here
Always Here
Posts: 5098
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Post by idle »

this should do it a bit quicker than image resize and includes the mouse cursor

Code: Select all

Procedure Screenshot(hImage,srcDc,ScreenWidth,ScreenHeight,tWidth,tHeight)   
   
   Protected pcin.CURSORINFO,iconinfo.ICONINFO
   
   #CAPTUREBLT = $40000000 
   If hImage = 0
       hImage = CreateImage(#PB_Any,tWidth,tHeight,32)
              
   EndIf 
   
   If hImage
    hdc = StartDrawing(ImageOutput(hImage))
              
    ;BitBlt_(hdc,0,0,tWidth,tHeight,srcdc,0,0,#SRCCOPY | #CAPTUREBLT)
     
    p.POINTAPI
    p\x = 0
    p\y = 0
    
    SetStretchBltMode_(hdc,#HALFTONE)
    SetBrushOrgEx_(hdc, 0, 0, @p)
    StretchBlt_(hdc, 0, 0, tWidth, tHeight, srcDc, 0, 0,ScreenWidth,ScreenHeight, #SRCCOPY | #CAPTUREBLT)     

   
    pcin\hCursor = GetCursor_()
    pcin\cbSize = SizeOf(pcin)
    GetCursorInfo_(pcin)
    mx = pcin\ptScreenPos\x
    my = pcin\ptScreenPos\y    
    
    DrawIconEx_(hdc, mx-10,my-10,pcin\hCursor, 0,0,0,0,   #DI_DEFAULTSIZE|#DI_NORMAL)        
    StopDrawing() 
    ReleaseDC_(#Null,srchdc)
    ReleaseDC_(#Null,hdc)
    
      
   EndIf 
   ProcedureReturn hImage
EndProcedure
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

but what if you want to restrict the screen shot to a particular application window and not the entire desktop?
Last edited by SFSxOI on Sun Jul 27, 2008 2:19 am, edited 1 time in total.
User avatar
idle
Always Here
Always Here
Posts: 5098
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Post by idle »

use this

Code: Select all

rect.rect
hwnd = GetForegroundWindow_()
GetWindowRect_(hwnd,@rect)
  
rect\left
rect\top
rect\right
rect\bottom
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

idle,

that doesn't capture the cursor tho in the window?
User avatar
idle
Always Here
Always Here
Posts: 5098
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Post by idle »

I see no reason why it wouldn't, are you passing in the hdc to the desktop?
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

Yep, passing the hdc for desktop. If the mouse is captured by a full screen application it doesn't include the cursor tho. No big deal, I just saw the post and it was something to play around with a little.
User avatar
idle
Always Here
Always Here
Posts: 5098
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Post by idle »

There are loads of alternatives around, check out netmaestro examples perhaps some of them will do it.
jesperbrannmark
Enthusiast
Enthusiast
Posts: 536
Joined: Mon Feb 16, 2009 10:42 am
Location: sweden
Contact:

Re: Need to improve screen capture speed

Post by jesperbrannmark »

Trying to put the two samples together. I think I fail in the screen hDc. Could anyone help me?

Code: Select all

Structure PointAPI 
  x.l 
  y.l 
EndStructure 
Procedure Screenshot(hImage,srcDc,ScreenWidth,ScreenHeight,tWidth,tHeight)   
  
  Protected pcin.CURSORINFO,iconinfo.ICONINFO
  
  #CAPTUREBLT = $40000000 
  If hImage = 0
    hImage = CreateImage(#PB_Any,tWidth,tHeight,32)
    
  EndIf 
  
  If hImage
    hdc = StartDrawing(ImageOutput(hImage))
    
    ;BitBlt_(hdc,0,0,tWidth,tHeight,srcdc,0,0,#SRCCOPY | #CAPTUREBLT)
    
    p.POINTAPI
    p\x = 0
    p\y = 0
    
    SetStretchBltMode_(hdc,#HALFTONE)
    SetBrushOrgEx_(hdc, 0, 0, @p)
    StretchBlt_(hdc, 0, 0, tWidth, tHeight, srcDc, 0, 0,ScreenWidth,ScreenHeight, #SRCCOPY | #CAPTUREBLT)     
    
    
    pcin\hCursor = GetCursor_()
    pcin\cbSize = SizeOf(pcin)
    GetCursorInfo_(pcin)
    mx = pcin\ptScreenPos\x
    my = pcin\ptScreenPos\y    
    
    DrawIconEx_(hdc, mx-10,my-10,pcin\hCursor, 0,0,0,0,   #DI_DEFAULTSIZE|#DI_NORMAL)        
    StopDrawing() 
    ReleaseDC_(#Null,srchdc)
    ReleaseDC_(#Null,hdc)
    
    
  EndIf 
  ProcedureReturn hImage
EndProcedure

OpenWindow(1,0,0,720,450,"",#PB_Window_SystemMenu|#PB_Window_ScreenCentered) 
img=CreateImage(#PB_Any,1440,900)

img = Screenshot(img,0,0,0,1440,900)
ImageGadget(2,0,0,720,450,img)

Repeat
  Delay(100)
  
  hDeskBmp = Screenshot(img,0,0,0,1440,900)
  ;Resize here
  SetGadgetState(2,img)
  
Until WindowEvent()=#PB_Event_CloseWindow
User avatar
idle
Always Here
Always Here
Posts: 5098
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Need to improve screen capture speed

Post by idle »

use GetDC_(0) to get the desktops hdc
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
ultralazor
Enthusiast
Enthusiast
Posts: 186
Joined: Sun Jun 27, 2010 9:00 am

Re: Need to improve screen capture speed

Post by ultralazor »

This supports resizing window+gadget. Cursor flicker kills this method though..

Code: Select all

Procedure Screenshot(hImage,srcDc,ScreenWidth,ScreenHeight,tWidth,tHeight)   
  
  Protected pcin.CURSORINFO,iconinfo.ICONINFO
  
  #CAPTUREBLT = $40000000
  If hImage = 0
    hImage = CreateImage(#PB_Any,tWidth,tHeight,32)
    
  EndIf
  
  If hImage
    hdc = StartDrawing(ImageOutput(hImage))
    
    ;BitBlt_(hdc,0,0,tWidth,tHeight,srcdc,0,0,#SRCCOPY | #CAPTUREBLT)
    
    p.POINT
    p\x = 0
    p\y = 0
    
    SetStretchBltMode_(hdc,#HALFTONE)
    SetBrushOrgEx_(hdc, 0, 0, @p)
    StretchBlt_(hdc, 0, 0, tWidth, tHeight, srcDc, 0, 0,ScreenWidth,ScreenHeight, #SRCCOPY | #CAPTUREBLT)     
    
    
    pcin\hCursor = GetCursor_()
    pcin\cbSize = SizeOf(pcin)
    GetCursorInfo_(pcin)
    mx = pcin\ptScreenPos\x
    my = pcin\ptScreenPos\y   
    
    DrawIconEx_(hdc, mx-10,my-10,pcin\hCursor, 0,0,0,0,   #DI_DEFAULTSIZE|#DI_NORMAL)       
    StopDrawing()
    ReleaseDC_(#Null,srchdc)
    ReleaseDC_(#Null,hdc)
    
    
  EndIf
  ProcedureReturn hImage
EndProcedure

If OpenWindow(0,0,0,720,450,"",#PB_Window_MaximizeGadget|#PB_Window_SizeGadget|#PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
  ;SmartWindowRefresh(0,#True)
  ExamineDesktops()
  mimg=CreateImage(#PB_Any,DesktopWidth(0),DesktopHeight(0))
  ImageGadget(0,0,0,WindowWidth(0),WindowHeight(0),ImageID(mimg))
  mimg=Screenshot(mimg,GetDC_(GetDesktopWindow_()),DesktopWidth(0),DesktopHeight(0),GadgetWidth(0),GadgetHeight(0))
  SetGadgetState(0,ImageID(mimg))

  Repeat
    ResizeGadget(0,0,0,WindowWidth(0),WindowHeight(0))
    mimg=Screenshot(mimg,GetDC_(GetDesktopWindow_()),DesktopWidth(0),DesktopHeight(0),GadgetWidth(0),GadgetHeight(0))
    SetGadgetState(0,ImageID(mimg))
  Until WaitWindowEvent(100)=#PB_Event_CloseWindow
EndIf
so many ideas so little time..
Post Reply