News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

My Windows Graphics Tutorial

Started by avcaballero, April 28, 2013, 09:31:50 PM

Previous topic - Next topic

dedndave

i've used it a lot - though, not much for 32-bit DIB's
For 16-bpp or 32-bpp non-palletized images, the color table must be three entries long;
the entries must specify the values of the red, green, and blue bitmasks.

dedndave

as for the RGBQUAD structure, see how Andreas defines the structure in wininc
i think Hutch has it as byte, byte, byte, byte

dedndave

i use it mostly for 256-color and 24-bit DIB's
you have to understand that, in C, structure definition works a little differently
what i do for a 256-color structure is create a special definition
BITMAPINFO256   STRUCT
  bmiHeader       BITMAPINFOHEADER <>
;   biSize          dd ?               ;BITMAPINFOHEADER structure size
;   biWidth         dd ?               ;image width in pixels
;   biHeight        dd ?               ;signed image height in pixels
;   biPlanes        dw ?               ;= 1
;   biBitCount      dw ?               ;= 8
;   biCompression   dd ?               ;= BI_RGB
;   biSizeImage     dd ?               ;image data bytes
;   biXPelsPerMeter dd ?               ;= 0
;   biYPelsPerMeter dd ?               ;= 0
;   biClrUsed       dd ?               ;= 0
;   biClrImportant  dd ?               ;= 0
  bmiColors       RGBQUAD 256 dup(<>)
BITMAPINFO256   ENDS


that simplifies the "translation" between C and ASM
maybe you can do something similar for 32-bit, with 3 RGBQUAD's

dedndave

also, you have to initialize biSizeImage with (400x300x4) = 480000

dedndave

Quoteif (nCompression == BI_BITFIELDS)
                nColors = 3; // 16 or 32 bpp have 3 colors(masks) in the color table if bitfield compression
            else
                nColors = 0; // 16 or 32 bpp have no color table if no bitfield compression

https://bitbucket.org/afriza/wince-screencapture/src/c208b8fa263e/DIBSectionLite.cpp?at=tip

dedndave

#20
console mode
;###############################################################################################

        .XCREF
        .NoList
        INCLUDE    \Masm32\Include\Masm32rt.inc
        .List

;###############################################################################################

BITMAPINFO32    STRUCT
  bmiHeader       BITMAPINFOHEADER <>
;   biSize          dd ?               ;BITMAPINFOHEADER structure size
;   biWidth         dd ?               ;image width in pixels
;   biHeight        dd ?               ;signed image height in pixels
;   biPlanes        dw ?               ;= 1
;   biBitCount      dw ?               ;= 32
;   biCompression   dd ?               ;= BI_RGB
;   biSizeImage     dd ?               ;image data bytes
;   biXPelsPerMeter dd ?               ;= 0
;   biYPelsPerMeter dd ?               ;= 0
;   biClrUsed       dd ?               ;= 0
;   biClrImportant  dd ?               ;= 0
BITMAPINFO32    ENDS

;###############################################################################################

        .DATA

pvBits  LPVOID ?

bmi BITMAPINFO32 <<BITMAPINFOHEADER,400,300,1,32,BI_RGB,480000,0,0,0,0>>

;***********************************************************************************************

        .DATA?

;###############################################################################################

        .CODE

;***********************************************************************************************

_main   PROC

    INVOKE  GetDC,HWND_DESKTOP
    xchg    eax,ebx
    INVOKE  CreateDIBSection,ebx,offset bmi,DIB_RGB_COLORS,offset pvBits,NULL,NULL
    xchg    eax,esi
    print   uhex$(pvBits),13,10
    .if esi
        INVOKE  DeleteObject,esi
    .endif
    INVOKE  ReleaseDC,HWND_DESKTOP,ebx
    print   chr$(13,10)
    inkey
    INVOKE  ExitProcess,0

_main   ENDP

;###############################################################################################

        END     _main

jj2007

Thanxalot, Dave, it works (and even without setting biSizeImage) :t

So effectively, you are only passing a header struct with no RGBQUAD, right? This works exactly as your version:
bmi BITMAPINFOHEADER <BITMAPINFOHEADER,400,300,1,32,BI_RGB,0,0,0,0,0>
::)

TWell

#22
After succesfull call to CreateDIBSection(), call GetDIBits() 0 in lpvBits to get biSizeImage
or use GetObject() with DIBSECTION.
Example in C:#define WIN32_LEAN_AND_MEAN
#include <windows.h>

int __cdecl WinMainCRTStartup(void)
{
BITMAPINFO bmi = {{sizeof(BITMAPINFOHEADER),200,200,1,32},};
RGBQUAD *prgbBits;
HDC hdcWin = GetDC(0);
HBITMAP hbm = CreateDIBSection(hdcWin, (BITMAPINFO *)&bmi,
DIB_RGB_COLORS, (void *)(&prgbBits), NULL, 0);
if (hbm) {
BITMAPFILEHEADER bfh = {0x4D42};
DIBSECTION ds;
GetObject(hbm, sizeof(DIBSECTION), &ds);
bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bfh.bfSize = bfh.bfOffBits + ds.dsBmih.biSizeImage;
HANDLE hFile = CreateFile("TestDIB3.bmp", GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD dwWritten = 0;
WriteFile( hFile, &bfh, sizeof(bfh), &dwWritten , NULL );
WriteFile( hFile, &ds.dsBmih, sizeof(BITMAPINFOHEADER), &dwWritten, NULL );
WriteFile( hFile, ds.dsBm.bmBits, ds.dsBmih.biSizeImage, &dwWritten, NULL );
CloseHandle( hFile );
DeleteObject(hbm);
}
ReleaseDC(0, hdcWin);
ExitProcess(0);
}

dedndave

ok - i have always pre-calculated biSizeImage
and - i may continue to do so, because that's how it's documented - lol
still interesting to note - maybe we can test that on various OS versions with different DIB bit-depths

but, that's how msdn documentation is
they're the ones that told us we need 3 RGBQUAD's when we don't

what's a little unfortunate with the CreateDIBSection function is that
we don't pass a total structure size - that would tell us for sure if we needed the bitmasks
i do know that, for 256-color images, the 4th byte of all RGBQUAD's must be 0 or the call will fail
just now, i tried the code above with 4 0FFFFFFFFh dword's following the structure
it created the DIB section, so we may be in good shape

i guess the one i haven't tried is 16 bpp
maybe playing with that one will give us some insight   :P

jj2007

Now I found a solution that looks correct, and works with both ML and JWasm:

bmi   BITMAPINFO <{BITMAPINFOHEADER, bWidth, bHeight, 1, 32, BI_RGB, bWidth*bHeight, 0, 0, 0, 0}, {}>
...
   mov hDC, rv(GetDC, hWnd)      ; use handle to main window
   mov hDib, rv(CreateDIBSection, eax, addr bmi, DIB_RGB_COLORS, addr ppvBits, 0, 0)


The good news is it returns a hDib.
The bad news is that GetLastError returns ERROR_NOT_ENOUGH_MEMORY.

But, following strictly the MSDN logic, this is not an error. It's just the crappy behaviour of a WinAPI that encounters an internal insignificant error but decides not to reset the error state in order to scare away the hobby coder :eusa_boohoo:

TWell


jj2007

Quote from: TWell on November 24, 2013, 09:05:48 PM
size is bWidth*bHeight*4 ?

Right :t
But it doesn't change the behaviour: non-zero hDib but complaints in GetLastError.

dedndave

if EAX is non-zero, then GetLastError returns undefined
(i.e., GetLastError is only meaningful if EAX tells you to look at it)
and - if you want to calc the size, don't forget that DIB lines are always multiples of 4 bytes

Gunther

Quote from: dedndave on November 24, 2013, 10:05:21 PM
if you want to calc the size, don't forget that DIB lines are always multiples of 4 bytes

I think that has to do with the BMP image format, hasn't it?

Gunther
You have to know the facts before you can distort them.

dedndave

the BMP image format includes (contains) a DIB
and - as far as i know, all uncompressed DIB lines are always multiples of 4 bytes
no matter what the bit-depth or image width are