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