Code archives/Graphics/Faster Pixelacces
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
| 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
| ||
| Sounds cool... how about a quick demo? |
| ||
| 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) |
| ||
| 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 |
| ||
| 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 |
| ||
| 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? |
| ||
| 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? |
| ||
| 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 :) |
| ||
| . |
Code Archives Forum