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

Comments

Matty
(Posted 18 years ago)
I draw from banks all the time in my 2D games, though have my own routines (which I'd be willing to share if they were tidy enough), and even on an older PC if it's done right can still be very quick - for the right sorts of graphics, and it saves on video memory since you are simply pixelplotting from system memory.

BlitzSupport
(Posted 18 years ago)
Good point regarding video memory, and I suppose it's fine for board/grid-based games...

I tried another angle on this by pre-calculating the rectangle to be scanned 'inside' the bank, skipping tons of If/Then checks within the nested loops, and I got a staggering increase of... well, zero per-cent.

Looks like this is limited more by the actual drawing rather than the plotting algorithm...

EDIT: Oops, background mask was failing on different bit-depth screens. Ungodly hack added -- SetDrawBankMask (r, g, b)!

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

	;---------------------------------------------------------------------------
	; Check where edges are on screen. leftx/rightx and topy/bottomy describe
	; a rectangle within the bank 'texture'...
	;---------------------------------------------------------------------------

	; Left edge (all edges are checked similarly)...
	
	If x > -1

		; On screen? If not, exit function...
		
		If x > GW - 1
			Return
		Else
			leftx = 0 ; Otherwise, use left edge of bank...
		EndIf

	Else

		; Off left of screen, so go this many pixels 'into' the bank...

		leftx = 0 - x

	EndIf

	; Right edge...

	If x + width > 0
		If x + width > GW
			rightx = GW - x
		Else
			rightx = width
		EndIf
	Else
		Return
	EndIf

	; Top edge...

	If y > -1
		If y > GH - 1
			Return
		Else
			topy = 0
		EndIf
	Else
		topy = 0 - y
	EndIf

	; Bottom edge...

	If y + height > 0
		If y + height > GH
			bottomy = GH - y
		Else
			bottomy = height
		EndIf
	Else
		Return
	EndIf

	; Set start of texture, 'into' the bank...
	
	pointer = pointer + leftx * height Shl 2 ; (x Shl 2) = (x * 4)

	; Scan across image...

	For w = leftx To rightx - 1
	
		xw = x + w

		; Move pointer 'down' by top offset...
		
		pointer = pointer + topy Shl 2

		; Scan down image...
		
		For h = topy To bottomy - 1

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

		Next

		; Jump remainder of 'pixels' off bottom...
		
		pointer = pointer + (height - bottomy) Shl 2 ; Ah, good old trial-and-error...

	Next

End Function

Function ImageToBank (bufferImage)

	; Slightly modified from <a href="http://www.blitzbasic.com/codearcs/codearcs.php?code=396" target="_blank">http://www.blitzbasic.com/codearcs/codearcs.php?code=396</a>
	; 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 ()

	shifted = KeyDown (42)

	If shifted
		xs# = 0
		ys# = 0
		If KeyHit (203) Then x# = x - 1
		If KeyHit (205) Then x = x + 1
		If KeyHit (200) Then y# = y - 1
		If KeyHit (208) Then y = y + 1
	Else
		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
	EndIf
	
	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


DareDevil
(Posted 18 years ago)
Hi! have optimized all function and organize


f$ = "boing.png"

Graphics 1024, 768, 0, 2


Function BankImage_SetMask(a_BankImage, r, g, b)
	Local l_IdBank = 3*4
	PokeInt a_BankImage, l_IdBank,((r Shl 16) + (g Shl 8) + b) Or ~$00FFFFFF
End Function

Function BankImage_SetAlpha(a_BankImage, Alpha%=0 )
	Local l_IdBank = 4*4
	PokeInt a_BankImage, l_IdBank, Alpha Shl 8
End Function

Function BankImage_Draw(a_BankImage, x, y, center = False,  a_Masked = False)
	
	; ===>
	Local l_LoopX%, l_LoopY%, l_ARGB%
	Local l_IdBank%, l_IdBankXa%, l_IdBankXb%, l_IdBankYa%, l_IdBankYb%;
	Local l_PX%, l_PY%;
	; ===>
	Local l_ImgWidth%		= PeekInt (a_BankImage, l_IdBank) : l_IdBank = l_IdBank + 4
	Local l_ImgHeight%	= PeekInt (a_BankImage, l_IdBank) : l_IdBank = l_IdBank + 4
	Local l_ColorMask%	= PeekInt (a_BankImage, l_IdBank) : l_IdBank = l_IdBank + 4
	Local l_Alpha%			= PeekInt (a_BankImage, l_IdBank) : l_IdBank = l_IdBank + 4
	Local GW% = GraphicsWidth()-1
	Local GH% = GraphicsHeight()-1
	Local l_OffsetBankY = l_ImgWidth*4
	; ===>
	; 
	Local l_StXa%, l_StXb%,l_StYa%,l_StYb%
	If (center) Then 
		l_StXa% = x - (l_ImgWidth /2)
		l_StXb% = x + (l_ImgWidth /2) - 1
		l_StYa% = y - (l_ImgHeight/2)
		l_StYb% = y + (l_ImgHeight/2) - 1 
	Else
		l_StXa% = x 
		l_StXb% = x + l_ImgWidth  - 1
		l_StYa% = y 
		l_StYb% = y + l_ImgHeight - 1 
	EndIf
	; ===>
	; image overscreen 
	If ((l_StXa > GW ) Or (l_StYa > GH ) Or (l_StXb < 0  ) Or (l_StYb < 0  )) Then Return
	; ===>
	If (l_StXa < 0 ) Then l_IdBankXa = Abs(l_StXa)*4							: l_StXa% = 0; Abs(l_StXa)*4
	If (l_StYa < 0 ) Then l_IdBankYa = Abs(l_StYa)*l_OffsetBankY	: l_StYa% = 0; Abs(l_StYa)*l_OffsetBankY
	If (l_StXb >=GW) Then l_IdBankXb = (l_StXb-GW)*4 : l_StXb = GW
	If (l_StYb >=GH) Then l_StYb = GH
	; ===>
	l_IdBank = l_IdBank + l_IdBankXa+l_IdBankYa
	If (a_Masked) Then
		Local l_color% = 0
		; ===>
		For l_LoopY = l_StYa To l_StYb;l_ImgHeight - 1
			; ===>
			For l_LoopX = l_StXa To l_StXb
				; ===>
				l_color = PeekInt( a_BankImage, l_IdBank)
				If(l_color<>l_ColorMask) Then WritePixelFast l_LoopX, l_LoopY, l_color;+l_Alpha
				l_IdBank = l_IdBank + 4
				; ===>
			Next
			; ===>
			l_IdBank = l_IdBank + (l_IdBankXb+l_IdBankXa)
			; ===>
		Next
		; ===>
	Else
		; ===>
		For l_LoopY = l_StYa To l_StYb;l_ImgHeight - 1
			; ===>
			For l_LoopX = l_StXa To l_StXb
				; ===>
				WritePixelFast l_LoopX, l_LoopY, PeekInt(a_BankImage, l_IdBank);+l_Alpha
				l_IdBank = l_IdBank + 4
				; ===>
			Next
			; ===>
			l_IdBank = l_IdBank + (l_IdBankXb+l_IdBankXa)
			; ===>
		Next
		; ===>
	EndIf
	
	
	
	
	
	
	
	; ===>
	;l_StXa = 0 : l_StYa=0
	; ===>
	; 
;	If (a_Masked) Then
;		Local l_color% = 0
;		; ===>
;		; Scan across image...
;		For l_LoopY = l_StYa To l_StYb;l_ImgHeight - 1
;			l_IdBank = l_LoopY * l_BankY + l_IdBankX + l_IdBankY
;			; ===>
;			For l_LoopX = l_StXa To l_StXb
;				; ===>
;				l_color = PeekInt( a_BankImage, l_IdBank)
;				If(l_color<>l_ColorMask) Then WritePixelFast l_LoopX+x, l_LoopY+y, l_color
;				l_IdBank = l_IdBank + 4
;				; ===>
;			Next
;			; ===>
;		Next
;	Else
		; ===>
		; Scan across image...
;	For l_LoopY = l_StYa To l_StYb;l_ImgHeight - 1
;			; ===>
;		l_IdBank = 16+(l_LoopY * l_OffsetBankY) ;+ l_IdBankY + l_IdBankX; + 16
;			; ===>
;			For l_LoopX = l_StXa To l_StXb
;				; ===>
;				WritePixelFast l_LoopX, l_LoopY, PeekInt (a_BankImage, l_IdBank)+l_Alpha
;				l_IdBank = l_IdBank + 4
;				; ===>
;			Next
;			; ===>
;		Next
;	EndIf
	; ===>
End Function

Function BankImage_Load(Filename$)
	; ===>
	Local l_BufferImage = LoadImage (Filename)
	; ===>
	; Slightly modified from Code Archives entry 396 by Perturbatio!
	Local l_ImgWidth%			= ImageWidth (l_BufferImage)
	Local l_ImgHeight%		= ImageHeight(l_BufferImage)
	Local l_SizeOfImage%	= l_ImgWidth * l_ImgHeight * 4 ; il 4 e il contenitore del colore ARGB
	Local l_SizeVariable%	= 4*4;
	Local l_BankImage%   	= CreateBank (l_SizeOfImage+l_SizeVariable)
	Local l_ColorMask%		= 0
	Local l_Alpha%				= 0
	; ===>
	Local l_OldBuffer% = GraphicsBuffer ()
	Local l_LoopX, l_LoopY, l_IdBank;
	; ===>
	SetBuffer ImageBuffer (l_BufferImage)
	LockBuffer ImageBuffer (l_BufferImage)
	PokeInt l_BankImage, l_IdBank, l_ImgWidth	: l_IdBank = l_IdBank + 4	; Store Variable Width
	PokeInt l_BankImage, l_IdBank, l_ImgHeight: l_IdBank = l_IdBank + 4	; Store Variable Height
	PokeInt l_BankImage, l_IdBank, l_ColorMask: l_IdBank = l_IdBank + 4	; Store Variable Color Mask
	PokeInt l_BankImage, l_IdBank, l_Alpha		: l_IdBank = l_IdBank + 4	; Store Variable Alpha
	; ===>
	For l_LoopY = 0 To l_ImgHeight - 1
		For l_LoopX = 0 To l_ImgWidth - 1
			PokeInt l_BankImage, l_IdBank, ReadPixelFast( l_LoopX, l_LoopY)
			l_IdBank = l_IdBank + 4
		Next
	Next
	; ===>
	UnlockBuffer ImageBuffer (l_BufferImage)
	SetBuffer l_OldBuffer
	; ===>
	FreeImage l_BufferImage
	; ===>
	Return l_BankImage
	; ===>
End Function

; Test...

ClsColor 64, 96, 128

SetBuffer BackBuffer ()


Local bank = BankImage_Load(f$)
Local ScreenMW% = GraphicsWidth() *.5
Local ScreenMH% = GraphicsHeight()*.5

Local  ticks#, ticksAdd#, cnt#

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 KeyDown (57) Then Stop
	
	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, 1,128,128,128,True
	BankImage_SetMask	( bank, 0, 0, 0)
	;BankImage_Draw		( bank, GraphicsWidth()*.5, GraphicsHeight()*.5, True, True)
	BankImage_Draw		( bank, x, y, True, True)
	ticks = MilliSecs () - ms
	;===>
	If (ticksAdd<10000) Then
		ticksAdd = ticksAdd + ticks
		cnt=cnt+1
	EndIf
	;===>
	UnlockBuffer BackBuffer ()
	
	Local l_Line=10
	Local l_InterLine = 15
	
	Color 255,0,0
	If ticks>0 Then 
		Text 20, l_Line, "Ms: " + Float(Int(ticks)) + " FPS: " + Float(Int((1000.0*100.0)/ticks))/100														: l_Line = l_Line+l_InterLine
		Text 20, l_Line, "Statistic Time for 10 seconds"																																				: l_Line = l_Line+l_InterLine
		Text 20, l_Line, "Midle time"																																														: l_Line = l_Line+l_InterLine
		Text 20, l_Line, "Ms: " + Float(Int(100.0*ticksAdd/cnt))/100.0 + " FPS: " + Float(Int(1000.0/(ticksAdd/cnt)*100))/100.0	: l_Line = l_Line+l_InterLine
	Else
		Text 20, l_Line, "Ms: " + Float(Int(ticks)) + " FPS: " + 0										: l_Line = l_Line+l_InterLine
		Text 20, l_Line, "Statistic Time for 10 seconds"															: l_Line = l_Line+l_InterLine
		Text 20, l_Line, "Midle time"																									: l_Line = l_Line+l_InterLine
		Text 20, l_Line, "Ms: " + Float(Int(100.0*ticksAdd/cnt))/100.0 + " FPS: " + 0	: l_Line = l_Line+l_InterLine
	EndIf
	Color 255,255,255
	
	Flip
	
Until KeyHit (1)

End



BlitzSupport
(Posted 18 years ago)
Wow, that's excellent. You got boing.png from 10-12 ms down to 2-3 ms! I also tried a picture larger than the display, which took 300+ ms before, and now takes only 23 ms!


Me: Looks like this is limited more by the actual drawing rather than the plotting algorithm...


Boy, do I feel stupid...

However, there's one minor problem, which I addressed in my update: if you use a non-zero RGB mask (eg. 255, 0, 255) then the results may be wrong in full-screen mode.

For example, your code works fine with Graphics w, h, 0, 2, but with Graphics w, h Blitz will choose the fastest bit-depth, which is 16 in my case, and the mask colours are then incorrect when you read them back, so the mask is drawn when it shouldn't be. (You can test this by forcing the full-screen bit-depth.)

I'm sure it's possible to calculate the correct values for 16/24/32-bit, rather than using my clumsy pixel read/write routine.

Anyway, many thanks for your contribution, which I'll be trying to understand!

Please could you consider declaring your code as Public Domain so that people can use it without worry or restriction?

DareDevil
(Posted 18 years ago)
Pleace test the modify function

Thanks!


Function BankImage_SetMask(a_BankImage, r, g, b)
	Local l_IdBank = 3*4
	;===>
	If (r<0  ) Then r=0
	If (r>255) Then r=255
	;===>
	If (g<0  ) Then g=0
	If (g>255) Then g=255
	;===>
	If (b<0  ) Then b=0
	If (b>255) Then b=255
	;===>
	Select GraphicsDepth() 
		;===>
		Case 16
			PokeInt a_BankImage, l_IdBank,(((r Shl 16) + (g Shl 8) + b) Shl 16) Or ~$FFFF
		;===>
		Case 24
			PokeInt a_BankImage, l_IdBank,(((r Shl 16) + (g Shl 8) + b) Shl  8) Or ~$FFFFFF
		;===>
		Default; 32Bit
			PokeInt a_BankImage, l_IdBank, ((r Shl 16) + (g Shl 8) + b) Or ~$00FFFFFF
		;===>
	End Select
End Function

Function BankImage_SetAlpha(a_BankImage, Alpha%=0 )
	;===>
	Local l_IdBank = 4*4
	;===>
	If (Alpha<0  ) Then Alpha=0
	If (Alpha>255) Then Alpha=255
	;===>
	Select GraphicsDepth() 
		;===>
		Case 16
			PokeInt a_BankImage, l_IdBank, (Alpha Shr 4) Shr 12
		;===>
		Case 24
			PokeInt a_BankImage, l_IdBank,0
		;===>
		Default ; 32Bit
			PokeInt a_BankImage, l_IdBank, Alpha Shl 24
		;===>
	End Select
	;===>
End Function


DareDevil
(Posted 18 years ago)
PS: the modify and all code is public domain ;)

good work

BlitzSupport
(Posted 18 years ago)
Hi DareDevil,

Thanks very much! I found a couple of minor problems in the last update:

Function BankImage_SetMask(a_BankImage, r, g, b)
	Local l_IdBank = 3*4

; Should be...

Function BankImage_SetMask(a_BankImage, r, g, b)
	Local l_IdBank = 2*4 ; CORRECT = 2*4


Function BankImage_SetAlpha(a_BankImage, Alpha%=0 )
	;===>
	Local l_IdBank = 4*4

; Should be...

Function BankImage_SetAlpha(a_BankImage, Alpha%=0 )
	;===>
	Local l_IdBank = 3*4 ; CORRECT = 3*4


A slightly more difficult problem is that the mask still doesn't work in 16-bit mode here. After a lot of trial-and-error, it seems to me that you have to use my plot/read pixel method to get the correct RGB values. This is because you can't tell what exact display mode is being used: for example, plotting 255, 0, 255 in 16-bit mode, then reading back, gives 248, 0, 248 for me.

It seems that I am probably being given an RGB565 mode in 16-bit depth, ie. 5 red bits, 6 green bits and 5 blue bits (so 255, 0, 255 becomes 248, 0, 248). I'm not totally sure, but I think this depends on the graphics card/drivers, but you may get a different 16-bit format instead of RGB565 on a different graphics card, and you can't tell how to read the bits since you don't know the RGB format.

Since there's no way to tell what RGB format you have from within Blitz, I think you have to use the plot/read method for now to determine the correct mask values. I think I'll have a look at the Blitz3D SDK source and see if I can get any ideas...

DareDevil
(Posted 18 years ago)
I had forgotten the format rgb 555 and 565, of your system plot and read are more effective

;)

Perturbatio
(Posted 18 years ago)
I wrote this: ImageToBank, BankToImage functions Many, many moons ago (when I first started using B3D I think).

It's vaguely in the same vein.

BlitzSupport
(Posted 18 years ago)
Perturbatio: I know -- I ripped ImageToBank off and credited you -- thanks! (See above.)

On the subject of determining the backbuffer format, I think I'm getting somewhere, as I've just managed to create a PureBasic DLL that gets the DirectDraw DDSURFACEDESC2 information, which includes some useful stuff:

dwHeight.l
dwWidth.l
dwRefreshRate.l
ddpfPixelFormat.DDPIXELFORMAT


It correctly gets width/height/refresh rate (only in full-screen?), and I think I can get the correct mask information from the pixel format structure, though that's a job for another day...

If anyone has PB 4 and wants to try it (sorry, I don't have FTP at the moment, and it's really not worth a download anyway), this is what I've got so far... not much, but it seems to work!

; Blitz test code (in same folder as dd7test.dll)...

Graphics 640, 480, 0, 1
result = Test (SystemProperty ("DirectDraw7"))
Print result


; Blitz dd7test.decls file (plain text) -> goes in Blitz\userlibs folder...

.lib "dd7test.dll"

Test% (device)


; PureBasic 4 code (compile as 'Shared DLL'):

Structure DDCOLORKEY 
  dwColorSpaceLowValue.l 
  dwColorSpaceHighValue.l 
EndStructure 

Structure DDPIXELFORMAT 
  dwSize.l 
  dwFlags.l 
  dwFourCC.l 
  dwRGBBitCount.l 
  dwRBitMask.l 
  dwGBitMask.l 
  dwBBitMask.l 
  dwRGBAlphaBitMask.l 
EndStructure 

Structure DDSCAPS 
  dwCaps.l 
EndStructure 

Structure DDSCAPS2 
  dwCaps.l 
  dwCaps2.l 
  dwCaps3.l 
  dwCaps4.l 
EndStructure 

Structure DDSURFACEDESC2 
  dwSize.l 
  dwFlags.l 
  dwHeight.l 
  dwWidth.l 
  lPitch.l 
  dwBackBufferCount.l 
  dwRefreshRate.l 
  dwAlphaBitDepth.l 
  dwReserved.l 
  lpSurface.l 
  ddckCKDestOverlay.DDCOLORKEY 
  ddckCKDestBlt.DDCOLORKEY 
  ddckCKSrcOverlay.DDCOLORKEY 
  ddckCKSrcBlt.DDCOLORKEY 
  ddpfPixelFormat.DDPIXELFORMAT 
  ddsCaps.DDSCAPS2 
  dwTextureStage.l 
EndStructure 

ProcedureDLL Test (IDD.IDirectDraw7)

	test.DDSURFACEDESC2
	test\dwSize = SizeOf (DDSURFACEDESC2)
	
	result = IDD\GetDisplayMode(@test)
	
	MessageRequester ("Test", "Screen size: " + Str (test\dwWidth) + " x " + Str (test\dwHeight) + " @ " + Str (test\dwRefreshRate) + " Hz")
	
	ProcedureReturn test\dwWidth

EndProcedure

DataSection 
  IID_IDirectDraw7: 
    Data.l $15e65ec0 
    Data.w $3b9c, $11d2 
    Data.b $b9, $2f, $00, $60, $97, $97, $ea, $5b 
EndDataSection  


Code Archives Forum