Copy DIB to array?

Blitz3D Forums/Blitz3D Programming/Copy DIB to array?

FlagDKT(Posted 2010) [#1]
How to copy bytes from a DIB pointer (using GETDC method) to an array without using getpixel() that is very slow?
I need to access data directly but I cannot access memory as far as I know..
BitBlt won't work with banks or array pointers..It needs a DC

Maybe I could use apiRtlMoveMemory() but it needs a memory pointer not a DC..


Adam Novagen(Posted 2010) [#2]
I don't mean to sound like a total idiot, but... I have no idea what you're talking about. XD What is a DIB, what is GETDC, and come to that, what is a DC? o.O


dynaman(Posted 2010) [#3]
DIB - Device Independant Bitmap.
GETDC - Get Device Context. (I think)
DC - Device Context. (In thise case a graphics device)

Sorry, I don't know how to answer the original question though. I had enough trouble doing this in .net way back.


Adam Novagen(Posted 2010) [#4]
DIB - Device Independant Bitmap.
GETDC - Get Device Context. (I think)
DC - Device Context. (In thise case a graphics device)


Oh, okay, clears that up. So um... How does this relate at all to Blitz3D... ?


dynaman(Posted 2010) [#5]
> How does this relate at all to Blitz3D... ?

It was the original question, my guess is that FlagDKT has a pointer to some screen memory and is trying to get an image of it. Although I thought someone had written a library to do that.


Serpent(Posted 2010) [#6]
GetDIBits is probably what you're looking for. It will save the 4-byte BGRA values at the specified memory address. You'll just need to get the memory address of the array. See MSDN for more info on GetDIBits.
If you want an example of using GetDIBits in Blitz, I move everything into a bank, and then into a Blitz Buffer in my screenshot code in the archives. Screenshot Functions


FlagDKT(Posted 2010) [#7]
Cool Serpent!
I guess it is much faster than getPixel() method?

I'm going to try it, I will let you know :)


FlagDKT(Posted 2010) [#8]
LocBnk = CreateBank(76)
MoveMemoryObjInt(LocBnk,DestinationBuffer,76)
Loc = PeekInt(LocBnk,72)
FreeBank LocBnk
GetDIBitsInt hDC,hMemBmp,0,BufferHeight,Loc,bmi,0


Loc is the memory pointer where GetDIBitsInt() will write. It is the 72th byte of LocBnk. right?

why do you use MoveMemoryObjInt() ?

After GetDIBitsInt(), should I read the Locbnk bank ?But it is only 76 bytes long..uhm
How to access copied data now?I have only a memory pointer..Loc

I'm missing something...


Serpent(Posted 2010) [#9]
Before I begin, yes this method is MUCH faster than using thousands of getPixel() calls. The command executes in less than 1ms if I remember correctly (on my machine at least) and it gets all the data in a nice 4-byte integer progression.


Alright - a definite explanation of my screenshot code is in order. It's not very intuitive and due to my bad practices it lacks comments :P

The idea of this function was to capture an image from the DC and put it into a Blitz 'Buffer' (e.g. ImageBuffer, BackBuffer, TextureBuffer, FrontBuffer). So, unless you're doing something different and really don't want to try and comprehend my explanation, just skip to where I talk about using the GetDIBits function.

So the first thing I needed to do was get the memory address of the actual Bitmap data for the Buffer. This is what the LocBnk and Loc stuff is all about.
According to:
http://translate.google.com/translate?hl=en&ie=UTF-8&sl=ru&tl=en&u=http://blitz.pp.ru/forum/showthread.php%3Fs%3D969a613d7deeb67f32385669ba81bcbb%26threadid%3D203%26perpage%3D15%26highlight%3D%26pagenumber%3D1&prev=_t&rurl=translate.google.com
there, the integer of the Blitz Buffer information which specifies the location of the bitmap data is at offset 72. Hence, I copy 76 bytes of info to the bank, and then read the last four as an integer, placing it into the 'Loc' variable.

Skip this if you want:
The 'ObjInt' part of it is due to the different ways you can get Blitz to pass parameters to user-declared functions. Whenever you create special objects as such (like Banks), Blitz will create an internal structure in memory which stores info about the bank. The handle returned by functions like CreateBank is a pointer to this internal structure, not the bank data itself. I think at least :P.
I don't want the memory to be copied to the internal Blitz structure, so I use the * symbol as a data type instead of % in the .decls file. This means that Blitz will pass the memory location of the data automatically to the user-declared function. So in my terms, ObjInt means the first variable is declared with a * so it is ideal for Banks, and the second is declared as an int (%) so it's ideal for handles, pointers, etc.



Okay, so after those four lines of code and a lot of (attempted) explaining, the location of the bitmap data for a Blitz Buffer is stored in the Loc variable. Now, the exciting bit. My GetDIBitsInt saves the bitmap data to the memory location Specified by the Loc variable.

Due to weird things like auto-rounding of Bitmap sizes to the nearest 16 in terms of width, or powers of 2 (in 3D modes), this function requires tweaking to work. But depending on what you want to do, you'll need a similiar thing.



In my example, you'll noticed that I've put 'Int' on the end of GetDIBits. This indicates that Blitz will pass a pointer that I specify as a straight-out integer.

I don't know why you need the values in an array, but if you do (and the array wasn't a roundabout way of putting them in an image or something) then you'll need to find the pointer to your array so you can pass it to GetDIBits. If you're content with getting the data into a bank, that's easily done by manipulating memory with RTLMoveMemory.

If you can give more of an indication of what you need to do this for that would be great, or at least confirm that you need it in an array or not something else :)


eeek that was long for me :) - well not really compared to some of the stuff i've posted before XD


FlagDKT(Posted 2010) [#10]
Wow thanx! :D

Just a question now:
how to use RTLMoveMemory to fill a blitz bank or array with image data?


Serpent(Posted 2010) [#11]
I made a mistake in that last post :P

You don't even need one RTLMoveMemory call to fill a blitz bank with image data. I'm not sure how to get the data into an array directly, but for a bank you just need to use a * in the .decls file because then Blitz will pass the pointer to the Bank data to the user-declared function.

Here's my example (a modified version of my screenshot function):

.decls Required:
.lib "gdi32.dll"
BitBlt%(hDestDC%,X%,Y%,nWidth%,nHeight%,hSrcDC,XSrc,YSrc,dwRop)
CreateCompatibleDC%(hdc%)
CreateCompatibleBitmap%(hdc%,Width%,Height%)
SelectObject%(obj%,selobj%)
DeleteDC(hdc%)
DeleteObject(hdc%)
GetDIBits%(hDC%,hbmp%,uStartScan%,uScanLines%,lpvBits*,lpbi*,uUsage%)

.lib "user32.dll"
GetDC%(hWnd%)
ReleaseDC%(hWnd%,hDC%)
Note that the parameter 'lpvBits' in GetDIBits has an * for its type.

Example Code:
Note that 'SRCCOPY' is used as one of the parameters for BitBlt. It tells it to just copy the data. There are other options as well.

One more note: In the 'bmi' bank (my BITMAPINFO structure) you'll notice that a negative value is saved in it for the height. This is because of a feature of GetDIBits. If the height is positive, it will get an image from bottom-up. If the height is negative it will get an image top-down.
In most work with Blitz top-down is the useful option, which is why I haven't bothered to have another parameter or something to allow the user to specify whether the image is top-down or bottom-up.


FlagDKT(Posted 2010) [#12]
great!
Thank you very much Serpent! :)