Code archives/Graphics/Screen Capture Mod

This code has been declared by its author to be Public Domain code.

Download source code

Screen Capture Mod by TomToad2006
Put this code into (BlitzMAX)\mod\toad.mod\capture.mod directory and build the module.
Usage:
Function ScreenCapture:TPixMap()

Will capture the screen and return it in a pixmap. If you call this function before calling Graphics, you'll capture the desktop image.

Function GetScreenCapturWidth:int()

will return the width of the captured image

Function GetScreenCaptureHeight:int()

Will get the Height of the captured image

Edit: Don't need all the lines I commented out :)
Module toad.capture

Import BRL.Pixmap
Import pub.Win32
Import BRL.Basic

Extern "Win32"
	Function GetPixel:Int(hdc:Int,x:Int,y:Int)
End Extern

Private
Global Width:Int
Global Height:Int

Public
Function ScreenCapture:TPixmap()
	Local Pixmap:TPixmap
	Local Pixel:Int
	Local hdc:Int = GetDC(Null)
	
	Width:Int = GetDeviceCaps(hdc,HORZRES)
	Height:Int = getdevicecaps(hdc,VERTRES)
	Pixmap = CreatePixmap(Width,Height,PF_RGBA8888)
	For Local y = 0 To Height - 1
		For Local x = 0 To Width - 1
			Pixel = GetPixel(hdc,x,y)
			WritePixel(PixMap,x,y,$FF000000+(Pixel & $ff)Shl 16+(Pixel & $ff00)+(Pixel & $ff0000)Shr 16)
		Next
	Next
	
	Return PixMap

End Function

Function GetScreenCaptureWidth:Int()
	Return Width
End Function

Function GetScreenCaptureHeight:Int()
	Return Height
End Function

Comments

Boiled Sweets2006
I use this to draw the desktop in the loop

DrawPixmap( desktopPixMap, 0, 0 )


This causes the screen saver to run rather jerkily, is there a better way?


TomToad2006
Try loading the pixmap into a TImage
Local DeskTopImage:TImage = LoadImage(desktopPixMap)

You can capture and load all in one line with
Local DesktopImage:TImage = LoadImage(ScreenCapture())

That's the way I did it in my SpinIt screensaver. One problem though is that some older cards can't handle a TImage as big as the desktop so you might be better off loading as an animation.
Local DeskTopImage:TImage = LoadAnimImage(ScreenCapture(),TileWidth,TileHeight,0,CellWidth*CellHeight)

Where TileWidth and TileHeight are the width and height of the tiles in pixels, and CellWidth and CellHeight are the number of tiles in the X and Y directions.


Who was John Galt?2006
Cheers Tom this one was useful for me.


fredborg2008
Hi,

GetPixel is terribly slow when Aero is enabled in Vista. It's much faster to copy the screen to a different bitmap and then read from that.

This is one way of doing that:
Import pub.win32

SuperStrict 

Extern "win32"
	Function ReleaseDC:Int(hwnd:Int,hdc:Int)
	Function GetPixel:Int(hdc:Int,x:Int,y:Int)
End Extern

Const SRCCOPY:Int = $CC0020

Function GrabScreen:TPixmap(x:Int=0,y:Int=0,width:Int=0,height:Int=0)
	
	Local hdc:Int = GetDC(Null)
	
	If width  <= 0 Then width  = 100000000000
	If height <= 0 Then height = 100000000000
	
	Local maxWidth:Int	= GetDeviceCaps(hdc,HORZRES)-x
	Local maxHeight:Int = GetDeviceCaps(hdc,VERTRES)-y
	
	width	= Min(maxWidth,width)
	height	= Min(maxHeight,height)

	Local newHdc:Int = CreateCompatibleDC(hdc)
	If newHdc = 0 Then Return Null
	
	Local newBmp:Int = CreateCompatibleBitmap(hdc,width,height)
	If newBmp = 0
		ReleaseDC(Null,newHdc)
		Return Null
	EndIf
	
	If SelectObject(newHdc, newBmp) = False 
		Return Null
	EndIf
		
	If BitBlt(newHdc,0,0,width,height,hdc,x,y,SRCCOPY) = False
		Return Null
	EndIf
	
	Local pixmap:TPixmap = CreatePixmap(width,height,PF_RGBA8888)
	
	For Local y:Int = 0 Until height
		For Local x:Int = 0 Until width
			Local pixel:Int = GetPixel(newHdc,x,y)
			WritePixel(pixmap,x,y,$FF000000+(pixel & $ff) Shl 16 + (pixel & $ff00) + (pixel & $ff0000) Shr 16)
		Next
	Next
	
	DeleteObject(newBmp)
	ReleaseDC(Null,newHdc)
	
	Return pixmap

End Function



Code Archives Forum