News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Graphics

Started by Jimg, February 16, 2009, 01:47:52 AM

Previous topic - Next topic

Jimg

And after a little more digging, the answer to my previous questions is-

The documentation says it doesn't return bmBits for a non-dib.

Testing shows otherwise.

Is this yet another case of incorrect windows api documentation?

NightWare

Quote from: Jimg on April 06, 2009, 06:53:06 PM
After screwing around for a month and a half, I just discovered this whole thing was a waste of time... ...Is this yet another case of incorrect windows api documentation?
it's a bit more complicate, you MUST fill structures of information to allow the use of functions. beside, for 32bits it can appear easy, but for 16/24bits screens or data, it's another story... it's why dib sections are supposed to be used...  :wink

BogdanOntanu

Quote from: Jimg on April 06, 2009, 09:55:07 PM
And after a little more digging, the answer to my previous questions is-

The documentation says it doesn't return bmBits for a non-dib.

Testing shows otherwise.

Is this yet another case of incorrect windows api documentation?

IF the documentation states that it should not return a valid value in  bmBits member THEN it is possible that this will be the case on any new version or on any new Windows update... and in this case your program will stop working.

It is better to respect the official recommendations even if testing shows otherwise.
Ambition is a lame excuse for the ones not brave enough to be lazy.
http://www.oby.ro

Rainstorm

I've been trying out some GDI & bitmap related stuff too.
Bitmaps are stored usually as DIBs is that right ?... - so if a file has to be opened & worked on.. - I open it  then edit its as a DDB, then save it back again to disk as a DIB. - is this the usual procedure.. ? if not.. what's the usual way of doing this.

thanks

Jimg

I find the terminology confusing myself.  Bitmaps on disk are Bitmaps.  There is no dib or ddb, they are just bitmaps in the correct format.  The first d stands for device, and there is no device.
Their colors and form may happen to be compatible with the screen, but don't rely on it.

The procedure for editing really depends upon what you want to do.  Normally, you are not supposed to edit a ddb directly, you are supposed to only make changes to a ddb by loading it into a device context and using the gdi procedures.   As far as writing a bitmap back out of a DC to a file, I haven't done that yet, we will have to get one of the graphics gurus to give us an example.

If you just want to make some simple changes, you can work directly on the bitmap file itself without using gdi.

What kind of things are you trying to do to the bitmap?

dedndave

wow - all this sounds overly compicated - lol
is this the directX interface ?

Rainstorm

thanks for the response. - I get the part about making changes to the DDB via a device context.
jimq wrote..
QuoteWhat kind of things are you trying to do to the bitmap?
maybe just some basic GDI editing/drawing with a pen or something, & then to save it -Just want to get a general idea about that whole part

>> dendave , its in the GDI section in the SDK

- Jimq, About it being stored as a DIB, these are some excerpts from the SDK that give that impression.
QuoteBitmaps should be saved in a file that uses the established bitmap file format and assigned a name with the three-character .bmp extension.
this format seems to be the same as the DIB format with the same structures. - maybe just the BITMAPFILEHEADER, is not mentioned there
QuoteThe DIB file format was designed to ensure that bitmapped graphics created using one application can be loaded and displayed in another application, retaining the same appearance as the original.
if its meant to be used as such, it would brobably be stored with that format too.. or at least in a form taht retains the format, also
QuoteIf you are writing an application that stores a bitmap image in a file, you should use the bitmap file format described in Bitmap Storage.
(which is the same as the DIB format)

jmq wrote
QuoteAs far as writing a bitmap back out of a DC to a file, I haven't done that yet, we will have to get one of the graphics gurus to give us an example.
just glanced, There's an example in the SDK, after a quick look.. it seems they first use CreateFile to create the file then initialize the DIB structures..(including the BITMAPFILEHEADER structure) & pass them to WriteFile .

they say this too,(the example uses the BITMAPINFO structure)
QuoteNote that the BITMAPINFO structure cannot be used with either a BITMAPV4HEADER or a BITMAPV5HEADER structure.
which was kinda confusing

Jimg

Looks like you're well on your way.  Have fun :U

Rainstorm

not really, still hazy on the whole topic..& could do with some directions..   : )  & would like to know the usual ways people use for doing this,  whether the bitmap after opening is converted into a DDB for GDI operations.

Jimg

I would like to know also.  I know several ways, but most of them are really ugly.  From OleLoadPicturePath with the ugly, confusing com syntax, to gdiplus, with ridiculous object nonsense and complication.

I would say the best way, if you are working on an actual .bmp bitmap and not .png or some later format, would be the LoadImage api.  It's straightforward, and you can get either a dib or ddb in one shot.

Darrel

fyi:  When I started working on bitmaps, I found CreateDIBSection gives me direct access to the bits. As things have developed I do quite a bit of manipulation of the bits, so this seems to be the easiest approach. I'm not sure of speed. I had some queries on the speed of some of my drawing procedures. Now I do all my manipulation of bits in the background, some are bitmaps some are in hdc's and some are just blocks of memory, depending on the procedure in use. With the amount of manipulation I'm doing I am definitely interested if there is a faster approach.

Good day,

Darrel

Jimg

After finally listening to NightWare and using a dibsection, I think it is definitely the best way.  My only problem with the process is the final step, the SetDIBitsToDevice call to put the results to the screen.

If I'm doing the whole bitmap of the same size as the screen, no problem.  If I'm trying to do some random block move, e.g. a 100 pixel square from the middle of the source dib to the upper right of the screen, it take about ten trial and error step before I get it right.  I just don't understand the parameters in SetDIBitsToDevice. -

hdc,XDest,YDest  are ok, no problems

dwWidth - Specifies the width, in logical units, of the DIB.
dwHeight - Specifies the height, in logical units, of the DIB.

  Aren't these values the number of bits wide and high you want to copy, not the "width of the DIB" itself?

XSrc - Specifies the x-coordinate, in logical units, of the lower-left corner of the DIB.

  is this one always zero as the description implies or the actual first pixel horzontally you want to copy?

YSrc - Specifies the y-coordinate, in logical units, of the lower-left corner of the DIB.

  This one is always a guess.  Is it zero?  Is it the height,  Is it something else?

uStartScan - Specifies the starting scan line in the DIB.

  Again, always a trial and error.  What is this value?

cScanLines - Specifies the number of DIB scan lines contained in the array pointed to by the lpvBits parameter.

  Isn't this values just the height.  Isn't it always in the lpbmi BITMAPINFO structure?


Ugh!


NightWare

Quote from: Jimg on April 17, 2009, 12:49:57 PM
dwWidth/dwHeight

Aren't these values the number of bits wide and high you want to copy, not the "width of the DIB" itself?
it's the number of PIXELS in the dib CONCERNED by the work (can be 8/16/24/32 bits depending of the format), you need to define them (the limits of your WORK).

Quote from: Jimg on April 17, 2009, 12:49:57 PM
XSrc/YSrc

is this one always zero as the description implies or the actual first pixel horzontally you want to copy?
This one is always a guess.  Is it zero?  Is it the height,  Is it something else?
here both represent the start coords (always in pixels, from 0 to (width/height)-1), for the transformation of the dib (your source) to the ddb (display device).

Quote from: Jimg on April 17, 2009, 12:49:57 PM
uStartScan/cScanLines

Again, always a trial and error.  What is this value?
Isn't this values just the height.  Isn't it always in the lpbmi BITMAPINFO structure?
here it looks like it's simply the height limits for the display, honestly i've never played a lot with this parameter, all i can say is : with half the height of the dib, it display the first half part of the dib (in the second part of the display, so i suppose the ddb consider the last display line as the first scanline...)
so, in brief :

XDest/YDest   = DESTINATION start coords
dwWidth/dwHeight   = SOURCE width/height TO PROCESS (not necesseraly all the area)
XSrc/YSrc   = SOURCE start coords
uStartScan/cScanLines   = DESTINATION height limits

i hope it help...  :wink

Jimg

Here's an example from a program I'm working on.

What this is, is a custom cursor, 100 pixels square, white background with antialiased circles and grids in 256 color gray scale, used as an alpha channel to blend with the background.

I blend the cursor with the background (hidden buffer that drew the screen), and use SetDIBitsToDevice to copy to the screen.

On the next call, I copy a cursor sized block from the original full sized hidden buffer to the screen at the location of the cursor.

Note that all dibs were created with bih.biHeight set to the negative of the height wanted.


This copies the cursor/background blend to the screen:

    inv GetDC,hWin
    mov hdc,eax
    mov ecx,100         ; size of the dib
    sub ecx,prevmh      ; number of scan lines to show, starting from the top
    inv SetDIBitsToDevice,hdc,prevmcx,prevmcy,prevmw,prevmh,0,ecx,0,100,dibmc.bits,addr dibmc.bih,DIB_RGB_COLORS
    inv ReleaseDC,hWin,hdc

where:
prevmcx is the left x coordinate of where to put the cursor image
prevmcy is the upper y coordinate for the image
prevmw is the width of the cursor image, usually 100 unless we are at the edge of the screen
prevmh is the height of the cursor image, usually 100 unless overlapping top or bottom.
dibmc is a 100 x 100 dib.

Notice I have to subtract the height wanted from the dib height to get SrcY, which took a long time to figure out because it just doesn't make any sense to me.


To restore the screen back to it's original condition before drawing the cursor elsewhere,
I copy a cursor sized block from the orginal back buffer of size mwidth x mheight.

    inv GetDC,hWin  ; yes, remove our cursor from the screen
    mov hdc,eax
    mov esi,dibh1.bits  ; source is hidden buffer 1 in this case.
    mov edi,offset dibh1.bih
    mov ecx,mheight
    sub ecx,prevmcy
    sub ecx,prevmh       
    inv SetDIBitsToDevice,hdc,prevmcx,prevmcy,prevmw,prevmh,prevmcx,ecx,0,mheight,esi,edi,DIB_RGB_COLORS   
    inv ReleaseDC,hWin,hdc

In this case, uStartScan is zero, and
SrcY is the height of the dib minus upper y-coordinate minus the number of lines to copy.

This is not what I would call intuitively obvious.

NightWare

for the copy :
>mov ecx,100         ; size of the dib
no, width or height of the dib, if you want, but not the size... plus why do you set this width/height for the Y source start ? should be zero... you copy from 0,0 to 99,99 no ? should be :
inv SetDIBitsToDevice,hdc,prevmcx,prevmcy,prevmw,prevmh,0,0,0,100,dibmc.bits,addr dibmc.bih,DIB_RGB_COLORS

dito for the restore code, should be :
inv SetDIBitsToDevice,hdc,prevmcx,prevmcy,prevmw,prevmh,0,0,0,100,dibh1.bits,addr dibh1.bih,DIB_RGB_COLORS

remember that the unique case where you don't have 0,0,0,height, it's when you don't start to copy from 0,0 coords of the source