Hi,
In the last 2 days I've been trying to grab an image from a window into a BB buffer. Various ways I tried didn't work, and read/writepixel is dog slow.
This evening I was looking for a way to access Imagebuffers better, and I've figured it out!
Note that, this is not good programming practice, it's experimental, and future BB builds may break it.
The pointer to an imagebuffer is Imagebuffer + 72. By redirecting a Bank to this address, you can simply Poke directly to the image buffer! The functionality is like LockedPixels() in Blitz+
Additionaly you should be able to pass the Bank pointer to an external DLL and write direct to the buffer.
There are some quirks, lock/unlockbuffer isn't needed for regular image buffers, but they ARE needed to access the frontbuffer() & backbuffer() [thanks again Andreas!], and I don't yet know if B3D uses 32bit for all images internaly, adjustments would have to be made for that.
One other thing, whilst I was looking for 'access', some people who've tested it for me are telling me it's much faster than writepixelfast, so that's a bonus I guess :)
Here goes!
It's very important that you restore the bank back else you won't be able to free it properly :)
If you want to do some speed tests, note that in this demo I'm calling GetRGB often, and multiplying same values in Pokebuffer, those could be tweaked [thanks Andreas for that!]
Have fun!
Tom
In the last 2 days I've been trying to grab an image from a window into a BB buffer. Various ways I tried didn't work, and read/writepixel is dog slow.
This evening I was looking for a way to access Imagebuffers better, and I've figured it out!
Note that, this is not good programming practice, it's experimental, and future BB builds may break it.
The pointer to an imagebuffer is Imagebuffer + 72. By redirecting a Bank to this address, you can simply Poke directly to the image buffer! The functionality is like LockedPixels() in Blitz+
Additionaly you should be able to pass the Bank pointer to an external DLL and write direct to the buffer.
There are some quirks, lock/unlockbuffer isn't needed for regular image buffers, but they ARE needed to access the frontbuffer() & backbuffer() [thanks again Andreas!], and I don't yet know if B3D uses 32bit for all images internaly, adjustments would have to be made for that.
One other thing, whilst I was looking for 'access', some people who've tested it for me are telling me it's much faster than writepixelfast, so that's a bonus I guess :)
Here goes!
Graphics 800,600,32,2 SetBuffer BackBuffer() ; How to access an ImageBuffer directly ; ; NOTE!!!! This may not be safe to do, and future builds may break it! ; ; You'll need to add these definitions to kernel32.decls in your ; Userlibs folder. If you already have definitions from other code ; snippets, you'll have to rename these, and change references to ; them in the code. ; ;api_RtlMoveMemory%(Destination%,Source*,Length%) : "RtlMoveMemory" ;api_RtlMoveMemory2%(Destination*,Source%,Length%) : "RtlMoveMemory" ;api_RtlMoveMemory4%(Destination%,Source%,Length%) : "RtlMoveMemory" Const IMAGEBUFFER_OFFSET=72 image=CreateImage(256,256) iBuff=ImageBuffer(image) ; NEEDED! Activates the image buffer ?!?!? LockBuffer iBuff UnlockBuffer iBuff ; This Bank will be redirected & resized to point to the Imagebuffer Bank=CreateBank(4) ; This is a small check for later to show the Bank ; Pointer gets restored properly PokeInt(Bank,0,199) ; Store the old banks pointer so we can clean up properly OldBankInfo=CreateBank(8) StoreBankInfo(Bank,OldBankInfo) PointBankToImagebuffer(Bank,image) .redo t=MilliSecs() For y=0 To 255 For x=0 To 255 ; Bank, x, y, RGBA, ImageHeight PokeImageBuffer(Bank,x,y,GetRGB(x,0,y),256) Next Next time=MilliSecs() - t While Not MouseHit(1) Cls DrawImage image,MouseX(),MouseY() Text 0,0,"LMB to Exit, RMB to redraw square using Poke!" Text 0,12,"'Bank' size is: "+ BankSize(Bank) Text 0,24,"Redraw: "+ time Flip If MouseHit(2) Goto redo Wend ; Important! We must restore the old Bank so we can free it! RestoreBankInfo(Bank,OldBankInfo) ; Prove the old pointer is restored Text 0,24,"Check 'Bank' is restored (199?): "+ PeekInt(Bank,0) Text 0,36,"Bank Size is (4?): "+ BankSize(Bank) Flip WaitKey End FreeBank Bank FreeBank OldBankInfo Function GetRGB(Red,Green,Blue) Return Blue Or (Green Shl 8) Or (Red Shl 16) End Function Function PokeImageBuffer(buffer,x,y,rgba,imageH) PokeInt( buffer, (y*imageH*4) + (4*x), rgba ) End Function Function StoreBankInfo(b,info) Local temp=CreateBank(4) api_RtlMoveMemory2(temp,b+4,4) PokeInt(info,0,PeekInt(temp,0)) ; store old pointer api_RtlMoveMemory2(temp,b+8,4) PokeInt(info,4,PeekInt(temp,0)) ; store old size FreeBank temp End Function ; The clever bit, we change 'Bank' to point to the ImageBuffer! Function PointBankToImagebuffer(b,image) api_RtlMoveMemory4(b+4,ImageBuffer(image)+IMAGEBUFFER_OFFSET,4) size=ImageWidth(image) * ImageHeight(image) * 4 Local temp=CreateBank(4) PokeInt(temp,0,size) api_RtlMoveMemory(b+8,temp,4) FreeBank temp End Function Function RestoreBankInfo(b,info) Local temp=CreateBank(4) PokeInt(temp,0,PeekInt(info,0)) api_RtlMoveMemory(b+4,temp,4) ; restore old pointer PokeInt(temp,0,PeekInt(info,4)) api_RtlMoveMemory(b+8,temp,4) ; restore old size FreeBank temp End Function
It's very important that you restore the bank back else you won't be able to free it properly :)
If you want to do some speed tests, note that in this demo I'm calling GetRGB often, and multiplying same values in Pokebuffer, those could be tweaked [thanks Andreas for that!]
Have fun!
Tom