Code archives/Graphics/Faster Pixelacces

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

Download source code

Faster Pixelacces by Vertex2004
Hi!
I have programmed 4 Function like BlitzPlus for Blitz3D(and maybe for Blitz2D if any person with Blitz2D can contact me)
that allows you a faster acces of the pixel in a buffer.
My function is 14,5 x faster than ReadPixelFast and 3,3 x faster than WritePixelFast.

The bank must be greator or equal sized like the image. For example: A Image is 100 * 200 Pixel big, and
- LockedFormat = 1 than is Banksize = 100*200*2 = 40000 byte
- LockedFormat = 2 than is Banksize = 100*200*2 = 40000 byte
- LockedFormat = 3 than is Banksize = 100*200*3 = 60000 byte
- LockedFormat = 4 than is Banksize = 100*200*4 = 80000 byte

To compute the offset by LockedFormat = 4 you can use this formel:
offset = y*400+x*4

Kernel32.decls:
.lib "kernel32.dll"
apiRtlMoveMemory(Destination*,Source,Length):"RtlMoveMemory"
apiRtlMoveMemory2(Destination,Source*,Length):"RtlMoveMemory"

cu olli
Function LockedFormat(buffer = 0) 
   Local bnkFormat, format 
    
   If buffer = 0 Then buffer = GraphicsBuffer() 
   bnkFormat = CreateBank(4) 
   apiRtlMoveMemory bnkFormat, buffer+104, 4 
   format = PeekInt(bnkFormat, 0) 
   FreeBank bnkFormat 
    
   Return format 
End Function 

Function LockedPitch(buffer = 0) 
   Local bnkPitch, pitch 
    
   If buffer=0 Then buffer = GraphicsBuffer() 
   bnkPitch = CreateBank(12) 
   apiRtlMoveMemory bnkPitch, buffer+92, 12 
   pitch = PeekInt(bnkPitch, 0)*PeekInt(bnkPitch, 8)/8 
   FreeBank bnkPitch 
    
   Return pitch 
End Function

Function CopyBufferToBank(bank, buffer = 0) 
   Local bnkInfo, size 
    
   If buffer=0 Then buffer = GraphicsBuffer() 
   bnkInfo = CreateBank(32) 
   apiRtlMoveMemory bnkInfo, buffer+72, 32 
   size = PeekInt(bnkInfo, 20)*PeekInt(bnkInfo, 24)*PeekInt(bnkInfo, 28)/8 
    
   If BankSize(bank)<size Or PeekInt(bnkInfo, 0)=0 Then 
      FreeBank bnkInfo 
      Return False 
   Else 
      apiRtlMoveMemory bank, PeekInt(bnkInfo, 0), size 
      FreeBank bnkInfo 
      Return True 
   EndIf 
End Function 

Function CopyBankToBuffer(bank, buffer = 0) 
   Local bnkInfo, size 
    
   If buffer=0 Then buffer = GraphicsBuffer() 
   bnkInfo = CreateBank(32) 
   apiRtlMoveMemory bnkInfo, buffer+72, 32 
   size = PeekInt(bnkInfo, 20)*PeekInt(bnkInfo, 24)*PeekInt(bnkInfo, 28)/8 
    
   If BankSize(bank)<size Or PeekInt(bnkInfo, 0)=0 Then 
      FreeBank bnkInfo 
      Return False 
   Else 
      apiRtlMoveMemory2 PeekInt(bnkInfo, 0), bank, size 
      FreeBank bnkInfo 
      Return True 
   EndIf 
End Function

; and for fun:
Function BufferWidth(buffer = 0) 
   Local bnkWidth, width 

   If buffer = 0 Then Return GraphicsWidth() 
   bnkWidth = CreateBank(4) 
   apiRtlMoveMemory bnkWidth, buffer+92, 4 
   width = PeekInt(bnkWidth, 0) 
   FreeBank bnkWidth 
    
   Return width 
End Function 

Function BufferHeight(buffer = 0) 
   Local bnkHeight, height 

   If buffer = 0 Then Return GraphicsHeight() 
   bnkHeight = CreateBank(4) 
   apiRtlMoveMemory bnkHeight, buffer+96, 4 
   height = PeekInt(bnkHeight, 0) 
   FreeBank bnkHeight 
    
   Return height 
End Function

Comments

BlitzSupport2004
Sounds cool... how about a quick demo?


MrCredo2004
hm is smilar to my DLL - i hack mem-adress+pixelformats from a bb-buffer and blend 2 images. All done in C++ code.
See Toolbox/FDLL/Alpha (with access to BB2D/BB3D-buffer)


Vertex2004
Yes MrCedo, but its the same like in BlitzPlus, if you want, you can have a direct acces with blitz to the pixels or you would it even faster then you must write a DLL in C/C++ or ASM.
BlitzSupport: Comming soon...

I must check it out, if worthwhile to write a DLL that include Poke/Peek-Commands, becouse Blitz use a queries for offsets, and I can delete it in my own commands.
cu olli


Vertex2004
OK here a little example:
(Bresenhamcirclealgorithmus by http://blitzbase.de/2c.htm)
Graphics 640, 480, 32, 1
SetBuffer BackBuffer()

bnkVideo = CreateBank(640*480*4)

start = MilliSecs()
For i=0 To 10000
	fastCircle(320, 240, Rand(10, 200), $00FFFF00, bnkVideo, 640, 480)
Next
time1 = MilliSecs()-start
; LockBuffer
; CopyBankToBuffer(bnkVideo)
; UnlockBuffer

LockBuffer
start = MilliSecs()
For i=0 To 10000
	fastCircle2(320, 240, Rand(10, 200), $00FFFF00)
Next
time2 = MilliSecs()-start
UnlockBuffer

start = MilliSecs()
Color 255, 255, 0
For i=0 To 10000
	radius = Rand(10, 200)
	Oval 320-radius, 240-radius, radius*2, radius*2
Next
time3 = MilliSecs()-start

Print "Poke: "+time1+"ms"
Print "WritePixelFast: "+time2+"ms"
Print "Oval: "+time3+"ms"

Flip : WaitKey : End

Function fastCircle2(xpos, ypos, radius, colour)
	Local x, y, p
	
	x = 0 : y = radius : p = 3-(radius Shl 2)
	While x<y
		WritePixelFast xpos - x,ypos - y, colour
		WritePixelFast xpos + x,ypos - y, colour
		WritePixelFast xpos - x,ypos + y, colour
		WritePixelFast xpos + x,ypos + y, colour
		WritePixelFast xpos - y,ypos - x, colour
		WritePixelFast xpos + y,ypos - x, colour
		WritePixelFast xpos - y,ypos + x, colour
		WritePixelFast xpos + y,ypos + x, colour

		If p<0 Then
			p = p+(x Shl 2)+6
		Else
			p = p+((x-y) Shl 2)+12
			y = y-1
		EndIf

		x = x+1
	Wend
	
	If x = y Then
		WritePixelFast xpos - x,ypos - y, colour
		WritePixelFast xpos + x,ypos - y, colour
		WritePixelFast xpos - x,ypos + y, colour
		WritePixelFast xpos + x,ypos + y, colour
	EndIf
End Function


Function fastCircle(xpos, ypos, radius, colour, bank, width, height)
	Local x, y, p
	
	x = 0 : y = radius : p = 3-(radius Shl 2)
	While x<y
		PokeInt bank, (ypos-y)*width*4+(xpos-x)*4, colour
		PokeInt bank, (ypos-y)*width*4+(xpos+x)*4, colour
		PokeInt bank, (ypos+y)*width*4+(xpos-x)*4, colour
		PokeInt bank, (ypos+y)*width*4+(xpos+x)*4, colour
		PokeInt bank, (ypos-x)*width*4+(xpos-y)*4, colour
		PokeInt bank, (ypos-x)*width*4+(xpos+y)*4, colour
		PokeInt bank, (ypos+x)*width*4+(xpos-y)*4, colour
		PokeInt bank, (ypos+x)*width*4+(xpos+y)*4, colour

		If p<0 Then
			p = p+(x Shl 2)+6
		Else
			p = p+((x-y) Shl 2)+12
			y = y-1
		EndIf

		x = x+1
	Wend
	
	If x = y Then
		PokeInt bank, (ypos-y)*width*4+(xpos-x)*4, colour
		PokeInt bank, (ypos-y)*width*4+(xpos+x)*4, colour
		PokeInt bank, (ypos+y)*width*4+(xpos-x)*4, colour
		PokeInt bank, (ypos+y)*width*4+(xpos+x)*4, colour
	EndIf
End Function



RGR2004
In the example above you must first flip and then print in full screen mode - otherwise you don't see the results..

A question: Is little more than 9 Seconds for an oval at 640x480 a good result?


aab2004
9.5% faster than WritePixelFast 4 me. Faster it is though.
Edit: 43.5% faster this time..then 12%.usefull.Can only really use these kinds of commands in intros\speech boxes etc. moments that can afford to be slowed a bit for the effects

"apiRtlMoveMemory" comes up as an unknown function. What am i supposed to be doing to be able to use this?


VP2005
There are a couple of optimisations still available.

Replace some of the arithmetic in fastCircle() with stored values (get rid of all those width*4).

Beats WritePixelFast hands down. I have been looking for this for my project ( http://www.blitzbasic.com/logs/userlog.php?user=2149&log=549 ), many thanks :)


bytecode772007
.


Code Archives Forum