Code archives/Graphics/DrawPixmapRect()

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

Download source code

DrawPixmapRect() by TomToad
(Posted 18 years ago)
This function will let you draw a portion of a pixmap to the screen. The function currently only works with the DirectX driver.
SuperStrict

'This function will draw a rectangular portion of a pixmap to the screen
'pixmap = source pixmap
'x, y, Width = Screen coordinates of where to draw the pixmap
'SrcX, SrcY = the pixmap coordinates of what to draw
'Width, Height = the width and height of the rectangular section to draw

Function DrawPixmapRect( pixmap:TPixmap,x:Int,y:Int,SrcX:Int,SrcY:Int,Width:Int,Height:Int )
	'make sure parameters are valid and clip to the screen
	If SrcX >= Pixmap.Width Or SrcY >= Pixmap.Height Then Return 'rect right or bottom of pixmap
	If SrcX+Width < 0 Or SrcY+Height < 0 Then Return 'rect left or top of pixmap
	If SrcX < 0 Then Width :+ SrcX; SrcX = 0 'clip To Left of pixmap
	If SrcY < 0 Then Height :+ SrcY; SrcY = 0 'Clip to top of pixmap
	If SrcX + Width >= pixmap.Width Then Width :- (SrcX + Width) - pixmap.Width 'clip to the right of pixmap
	If SrcY + Height >= pixmap.Height Then Height :- (SrcY + Height) - pixmap.Height 'clip to the bottom of pixmap
	Local ScreenWidth:Int = GraphicsWidth()
	Local ScreenHeight:Int = GraphicsHeight()
	If x >= ScreenWidth Or y >= ScreenHeight Then Return 'off screen at right or bottom
	If x+Width < 0 Or y+Height < 0 Then Return 'off screen at left or top
	If x < 0 Then Width :+ x; x = 0 'clip to left edge
	If y < 0 Then Height :+ y; y = 0 'clip to top edge
	If x + Width >= ScreenWidth Then Width :- (x + Width) - ScreenWidth 'clip to right edge
	If y + Height >= ScreenHeight Then Height :- (y + Height) - ScreenHeight 'Clip to bottom

	'much of this is the same as DrawPixmap()
	Local srcdc:Int,destdc:Int
	Local surf:IDirectDrawSurface7
	Local renderSurf:IDirectDrawSurface7

	D3D7GraphicsDriver().EndScene

	TD3D7Max2DDriver(_max2dDriver).device.GetRenderTarget Varptr renderSurf
	
	renderSurf.GetDC Varptr destdc
	surf=TD3D7Max2DDriver(_max2dDriver).surffrompixmap( pixmap )
	surf.GetDC Varptr srcdc
	BitBlt destdc,x,y,Width,Height,srcdc,SrcX,SrcY,ROP_SRCCOPY 'this has changed to reflect the new parameters
	surf.ReleaseDC srcdc
	renderSurf.ReleaseDC destdc
	surf.Release_

	D3D7GraphicsDriver().BeginScene
End Function

'Here is an example of the function in use
Graphics 800,600

For Local t:Int = 1 To 100
	SetColor Rand(0,255),Rand(0,255),Rand(0,255)
	
	DrawOval Rand(-50,799),Rand(-50,599),Rand(10,200),Rand(10,200)
Next
SetColor 255,255,255

Local pixmap:TPixmap = GrabPixmap(0,0,800,600)

While Not KeyHit(KEY_ESCAPE) And Not AppTerminate()
	Local MX:Int = MouseX()
	Local MY:Int = MouseY()
	
	Cls
	DrawPixmapRect(pixmap,MX-50,MY-50,MX-50,MY-50,100,100)
	Flip
Wend

Comments

Jesse
(Posted 18 years ago)
nice! thanks for sharing.
does the BitBlt copy source area to a destiation pixmap? I guess it does.
is there any way to copy it directly to the render surface?
I think that would be twice as fast or maybe even faster.

Jesse
(Posted 18 years ago)
there is a bug in your code. When I move all the way to the left it should steel draw half of the image and it doesn't. Same thing when moving all the way to the top. It has to do do with your use of width and height for both source and destination pixmaps. You are adding SrcX/SrcY to width/height twice when on the left/top edge respectfully.
besides you don't need to do all of those calculations directx does auto clipping. this is your example with fps:
'Width, Height = the width and height of the rectangular section to draw

Function DrawPixmapRect( pixmap:TPixmap,x:Int,y:Int,SrcX:Int,SrcY:Int,Width:Int,Height:Int )
	'make sure parameters are valid And clip To the screen
	
	If SrcX >= Pixmap.Width Then Return 			'rect right of pixmap
	If SrcY >= Pixmap.Height Then Return			'rect bottom of pixmap
	If SrcX+Width < 0 Then Return 				'rect left of pixmap
	If SrcY+Height < 0 Then Return 				'rect top pixmap
	If SrcX < 0 Then Width :+ SrcX; SrcX = 0 		'clip To Left of pixmap
	If SrcY < 0 Then Height :+ SrcY; SrcY = 0 		'Clip to top of pixmap
	If SrcX + Width >= pixmap.Width Then 
		Width :- (SrcX + Width) - pixmap.Width 		'clip to the right of pixmap
	EndIf
	If SrcY + Height >= pixmap.Height Then 
		Height :- (SrcY + Height) - pixmap.Height 	'clip to the bottom of pixmap
	EndIf
	
	Local ScreenWidth:Int = GraphicsWidth()
	Local ScreenHeight:Int = GraphicsHeight()
	If x >= ScreenWidth Or y >= ScreenHeight Then Return 'off screen at right or bottom
	If x+Width < 0 Or y+Height < 0 Then Return 'off screen at left or top
	If x < 0 Then Width :+ x; x = 0 'clip to left edge
	If y < 0 Then Height :+ y; y = 0 'clip to top edge
	If x + Width >= ScreenWidth Then 
		Width :- (x + Width) - ScreenWidth 'clip to right edge
	EndIf
	If y + Height >= ScreenHeight Then 
		Height :- (y + Height) - ScreenHeight 'Clip to bottom
	EndIf
	
	'much of this is the same as DrawPixmap()
	Local srcdc:Int,destdc:Int
	Local surf:IDirectDrawSurface7
	Local renderSurf:IDirectDrawSurface7

	D3D7GraphicsDriver().EndScene

	TD3D7Max2DDriver(_max2dDriver).device.GetRenderTarget Varptr renderSurf
	
	renderSurf.GetDC Varptr destdc
	surf=TD3D7Max2DDriver(_max2dDriver).surffrompixmap( pixmap )
	surf.GetDC Varptr srcdc
	BitBlt destdc,x,y,Width,Height,srcdc,SrcX,SrcY,ROP_SRCCOPY 'this has changed to reflect the new parameters
	surf.ReleaseDC srcdc
	renderSurf.ReleaseDC destdc
	surf.Release_

	D3D7GraphicsDriver().BeginScene
End Function

'Here is an example of the function in use
Graphics 800,600

For Local t:Int = 1 To 100
	SetColor Rand(0,255),Rand(0,255),Rand(0,255)
	
	DrawOval Rand(-50,799),Rand(-50,599),Rand(10,200),Rand(10,200)
Next
SetColor 255,255,255

Local pixmap:TPixmap = GrabPixmap(0,0,800,600)
While Not KeyHit(KEY_ESCAPE) And Not AppTerminate()
	Local MX:Int = MouseX()
	Local MY:Int = MouseY()
		
	Cls
	DrawPixmapRect(pixmap,MX-250,MY-250,MX-250,MY-250,500,500)
	DrawText fps(),20,20
	Flip(0)
Wend

Global start:Long = 0
Global count:Int
Global flips:Int = 0
Function fps:Int()
	If start < MilliSecs()
		start = MilliSecs()+1000
		flips = count
		count = 0
	EndIf
	count :+ 1
	Return flips
EndFunction


and this is without all that extra code:
SuperStrict

'This function will draw a rectangular portion of a pixmap to the screen
'pixmap = source pixmap
'x, y, Width = Screen coordinates of where to draw the pixmap
'SrcX, SrcY = the pixmap coordinates of what to draw
'Width, Height = the width and height of the rectangular section to draw

Function DrawPixmapRect( pixmap:TPixmap,x:Int,y:Int,SrcX:Int,SrcY:Int,Width:Int,Height:Int )

	'much of this is the same as DrawPixmap()
	Local srcdc:Int,destdc:Int
	Local surf:IDirectDrawSurface7
	Local renderSurf:IDirectDrawSurface7

	D3D7GraphicsDriver().EndScene

	TD3D7Max2DDriver(_max2dDriver).device.GetRenderTarget Varptr renderSurf
	
	renderSurf.GetDC Varptr destdc
	surf=TD3D7Max2DDriver(_max2dDriver).surffrompixmap( pixmap )
	surf.GetDC Varptr srcdc
	BitBlt destdc,x,y,Width,Height,srcdc,SrcX,SrcY,ROP_SRCCOPY 'this has changed to reflect the new parameters
	surf.ReleaseDC srcdc
	renderSurf.ReleaseDC destdc
	surf.Release_

	D3D7GraphicsDriver().BeginScene
End Function

'Here is an example of the function in use
Graphics 800,600

For Local t:Int = 1 To 100
	SetColor Rand(0,255),Rand(0,255),Rand(0,255)
	
	DrawOval Rand(-50,799),Rand(-50,599),Rand(10,200),Rand(10,200)
Next
SetColor 255,255,255

Local pixmap:TPixmap = GrabPixmap(0,0,800,600)
While Not KeyHit(KEY_ESCAPE) And Not AppTerminate()
	Local MX:Int = MouseX()
	Local MY:Int = MouseY()
		
	Cls
	DrawPixmapRect(pixmap,MX-250,MY-250,MX-250,MY-250,500,500)
	DrawText fps(),20,20
	Flip(0)
Wend

Global start:Long = 0
Global count:Int
Global flips:Int = 0
Function fps:Int()
	If start < MilliSecs()
		start = MilliSecs()+1000
		flips = count
		count = 0
	EndIf
	count :+ 1
	Return flips
EndFunction


as you can see when the image is moved against the edge it starts to draw faster which means it is doing clipping on its own.

Code Archives Forum