Author Topic: My Windows Graphics Tutorial  (Read 32840 times)

dedndave

  • Member
  • *****
  • Posts: 8828
  • Still using Abacus 2.0
    • DednDave
Re: My Windows Graphics Tutorial
« Reply #15 on: November 24, 2013, 11:27:07 AM »
i've used it a lot - though, not much for 32-bit DIB's
Code: [Select]
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

  • Member
  • *****
  • Posts: 8828
  • Still using Abacus 2.0
    • DednDave
Re: My Windows Graphics Tutorial
« Reply #16 on: November 24, 2013, 11:29:07 AM »
as for the RGBQUAD structure, see how Andreas defines the structure in wininc
i think Hutch has it as byte, byte, byte, byte

dedndave

  • Member
  • *****
  • Posts: 8828
  • Still using Abacus 2.0
    • DednDave
Re: My Windows Graphics Tutorial
« Reply #17 on: November 24, 2013, 11:33:34 AM »
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
Code: [Select]
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

  • Member
  • *****
  • Posts: 8828
  • Still using Abacus 2.0
    • DednDave
Re: My Windows Graphics Tutorial
« Reply #18 on: November 24, 2013, 11:35:59 AM »
also, you have to initialize biSizeImage with (400x300x4) = 480000

dedndave

  • Member
  • *****
  • Posts: 8828
  • Still using Abacus 2.0
    • DednDave
Re: My Windows Graphics Tutorial
« Reply #19 on: November 24, 2013, 11:52:20 AM »
Quote
            if (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

  • Member
  • *****
  • Posts: 8828
  • Still using Abacus 2.0
    • DednDave
Re: My Windows Graphics Tutorial
« Reply #20 on: November 24, 2013, 12:05:58 PM »
console mode
Code: [Select]
;###############################################################################################

        .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
« Last Edit: November 24, 2013, 01:28:12 PM by dedndave »

jj2007

  • Member
  • *****
  • Posts: 13957
  • Assembly is fun ;-)
    • MasmBasic
Re: My Windows Graphics Tutorial
« Reply #21 on: November 24, 2013, 06:13:39 PM »
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

  • Member
  • ****
  • Posts: 743
Re: My Windows Graphics Tutorial
« Reply #22 on: November 24, 2013, 08:03:37 PM »
After succesfull call to CreateDIBSection(), call GetDIBits() 0 in lpvBits to get biSizeImage
or use GetObject() with DIBSECTION.
Example in C:
Code: [Select]
#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);
}
« Last Edit: November 24, 2013, 09:11:09 PM by TWell »

dedndave

  • Member
  • *****
  • Posts: 8828
  • Still using Abacus 2.0
    • DednDave
Re: My Windows Graphics Tutorial
« Reply #23 on: November 24, 2013, 08:14:11 PM »
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

  • Member
  • *****
  • Posts: 13957
  • Assembly is fun ;-)
    • MasmBasic
Re: My Windows Graphics Tutorial
« Reply #24 on: November 24, 2013, 08:49:52 PM »
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

  • Member
  • ****
  • Posts: 743
Re: My Windows Graphics Tutorial
« Reply #25 on: November 24, 2013, 09:05:48 PM »
size is bWidth*bHeight*4 ?

jj2007

  • Member
  • *****
  • Posts: 13957
  • Assembly is fun ;-)
    • MasmBasic
Re: My Windows Graphics Tutorial
« Reply #26 on: November 24, 2013, 09:20:50 PM »
size is bWidth*bHeight*4 ?

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

dedndave

  • Member
  • *****
  • Posts: 8828
  • Still using Abacus 2.0
    • DednDave
Re: My Windows Graphics Tutorial
« Reply #27 on: November 24, 2013, 10:05:21 PM »
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

  • Member
  • *****
  • Posts: 4198
  • Forgive your enemies, but never forget their names
Re: My Windows Graphics Tutorial
« Reply #28 on: November 24, 2013, 10:10:09 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

  • Member
  • *****
  • Posts: 8828
  • Still using Abacus 2.0
    • DednDave
Re: My Windows Graphics Tutorial
« Reply #29 on: November 24, 2013, 10:16:41 PM »
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