Code archives/Graphics/DrawBank

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

Download source code

DrawBank by BlitzSupport
(Posted 18 years ago)
I couldn't find a previous example of this, oddly enough, though someone's surely done it. Not much use for real time games, but may come in handy for... other stuff.

If anyone can speed this up then please post here! (I get about 10 milliseconds for the boing.png image from BlitzMax "RockOut", on an Intel Core2Duo 6300 @ 1.86 GHz with Geforce 7600 GS, and about 330 milliseconds for any image that completely fills the screen without a mask.)

EDIT: Added background mask hack/fix and trivial, worthless optimisations.
f$ = "boing.png"

Graphics 1024, 768, 0, 2

; IMPORTANT! Required by DrawBank!

Global GW = GraphicsWidth ()
Global GH = GraphicsHeight ()
Global DB_RGB

SetDrawBankMask 255, 0, 255

Function SetDrawBankMask (r, g, b)

	tempbuffer = GraphicsBuffer ()
	temp = CreateImage (1, 1)

	SetBuffer ImageBuffer (temp)

	Plot 0, 0: GetColor 0, 0
	tr = ColorRed ()
	tg = ColorGreen ()
	tb = ColorBlue ()

	Color r, g, b: Plot 0, 0: GetColor 0, 0
	r = ColorRed ()
	g = ColorGreen ()
	b = ColorBlue ()

	FreeImage temp

	DB_RGB = ((r Shl 16) + (g Shl 8) + b) Or ~$00FFFFFF

	SetBuffer tempbuffer

	Color tr, tg, tb
	
End Function

Function DrawBank (bank, x, y, width, height, center = 0, masked = True)
	
	; Centre image on screen if required...
	
	If center
		x = x - width / 2
		y = y - height / 2
	EndIf
	
	; Alpha mask...
	
	mask = ((r Shl 16) + (g Shl 8) + b) Or ~$00FFFFFF

	; Scan across image...
	
	For w = 0 To width - 1

		; x-position plus current 'pixel' NOT off right of screen?

		If x + w < GW

			; Not off left of screen?
			
			If x + w > -1

				; Scan down image...
				
				For h = 0 To height - 1

					; Not off bottom of screen?
					
					If y + h < GH
	
						; Not off top of screen?
						
						If y + h > -1

							; Get current value in bank...
							
							argb = PeekInt (bank, pointer)
							
							; Assuming most cases use transparent mask...
							
							If argb <> DB_RGB
								WritePixelFast x + w, y + h, argb
							Else
								; User wants mask drawn...
								If Not masked
									WritePixelFast x + w, y + h, argb
								EndIf
							EndIf
							
							; Move to next value in bank (argb = 4 bytes = integer, hence PeekInt above)...
							
							pointer = pointer + 4

						Else
							
							; Off top of screen, so skip all pixels until on screen...
							
							h = h + (-y) - 1
							pointer = pointer + (h Shl 2) + 4
							
						EndIf	

					Else
						
						; Off bottom of screen, stop drawing this column...
						
						pointer = pointer + (height - h) Shl 2
						Exit
					
					EndIf
					
				Next

			Else
				
				; Off left of screen, so skip all pixels until on screen...
				
				pointer = pointer + (height - h) Shl 2
				
			EndIf

		Else
			
			; Off right of screen, so stop drawing...
			
			Exit
			
		EndIf
		
	Next
	
End Function

Function ImageToBank (bufferImage)

	; Slightly modified from http://www.blitzbasic.com/codearcs/codearcs.php?code=396
	; By Perturbatio
	
	bankImage = CreateBank ()
	
	bufOldBuffer = GraphicsBuffer ()
		
	SizeOfImage = ImageWidth (bufferImage) * ImageHeight (bufferImage)
	
	ResizeBank bankImage, (SizeOfImage * 4)
	
	SetBuffer ImageBuffer (bufferImage)
	LockBuffer ImageBuffer (bufferImage)

	For iLoopX = 0 To ImageWidth (bufferImage) - 1
		For iLoopY = 0 To ImageHeight (bufferImage) - 1
			PokeInt bankImage, ibankPointer, ReadPixelFast (iLoopX, iLoopY)
			iBankPointer = iBankPointer + 4
		Next
	Next

	UnlockBuffer ImageBuffer (bufferImage)
	SetBuffer bufOldBuffer
	
	Return bankImage
	
End Function

; Test...

ClsColor 64, 96, 128

SetBuffer BackBuffer ()

image = LoadImage (f$)

width = ImageWidth (image)
height = ImageHeight (image)

bank = ImageToBank (image)
FreeImage image

Repeat

	Cls
	
	mx = MouseX ()
	my = MouseY ()
	
	If KeyDown (203) Then xs# = xs - 0.1
	If KeyDown (205) Then xs = xs + 0.1
	If KeyDown (200) Then ys# = ys - 0.1
	If KeyDown (208) Then ys = ys + 0.1

	If mx <> lastx
		x# = mx
		xs = 0
	Else
		x = x + xs
	EndIf
	
	If my <> lasty
		y# = my
		ys = 0
	Else
		y = y + ys
	EndIf
	
	lastx = mx
	lasty = my
	
	LockBuffer BackBuffer ()
	
		ms = MilliSecs ()
		DrawBank bank, x, y, width, height, 1
		ticks = MilliSecs () - ms
	
	UnlockBuffer BackBuffer ()

	Text 20, 20, ticks

	Flip
	
Until KeyHit (1)

End