The MASM Forum

General => The Workshop => Topic started by: zedd151 on March 12, 2025, 02:18:44 AM

Title: gdiplus tests
Post by: zedd151 on March 12, 2025, 02:18:44 AM
Continuing on with my graphics related code... my first  time writing gdiplus code that was not already pre-canned into a procedure by someone else. It took me a hot minute to figure out that I needed a unicode string for the image path... :rofl:

Tests opening an image and displaying using gdiplus.
Using StretchBlt also, to fill the client area with the image, even when resized.
Image is a cropped version of hutchs "downtown Sydney Australia" banner from the forum.
Have tested this program using *.jpg, *.png, and non-animated *.gif files.

    include \masm32\include\masm32rt.inc
    include \masm32\include\gdiplus.inc
    includelib \masm32\lib\gdiplus.lib
   
    DlgProc proto :dword, :dword, :dword, :dword
   
    writefilex      proto :dword, :dword, :dword


        cwidth          equ  1024              ; desired client area width
        cheight        equ  576                ; desired client area height

    .data
        gdipBmp        dd 0                    ; image object
        hBmpgdip        dd 0                    ; image HBITMAP
        picname        db "sydney.jpg", 0      ; image filename in ascii
        upicname        db 128 dup (0)          ; image file name in unicode
       
    .data?
        gdii        GdiplusStartupInput <?>
        GDIPtoken      dd ?
     
    .code

    start proc
    local hInstance:dword
        invoke GetModuleHandle, NULL
        mov hInstance, eax
       
        ;---------------------  GdiPlus Startup code -------
       
        mov gdii.GdiplusVersion, 1
        mov gdii.DebugEventCallback, 0
        mov gdii.SuppressBackgroundThread, 0
        mov gdii.SuppressExternalCodecs, 0
        invoke GdiplusStartup, addr GDIPtoken, addr gdii, 0
       
        ;----------------------------------------------------

        invoke MultiByteToWideChar, CP_ACP, 0, addr picname, -1, addr upicname, 128 ; convert ascii to unicode

        fn GdipCreateBitmapFromFile, addr upicname, addr gdipBmp        ; open image file, create image object
        invoke GdipCreateHBITMAPFromBitmap, gdipBmp, addr hBmpgdip, 0  ; get HBITMAP, from image object
        invoke GdipDisposeImage, gdipBmp                                ; dispose image object

        invoke DialogBoxParam, hInstance, 100, 0, addr DlgProc, 0      ;; create dialog box, from resource dilalog
       
        ;--------------------  GdiPlus Shutdown code -------
       
        invoke GdiplusShutdown, GDIPtoken
       
        ;----------------------------------------------------
        invoke ExitProcess, eax
    start endp

    DlgProc proc hWin:dword, uMsg:dword, wParam:dword, lParam:dword
    local hDC:dword, ps:PAINTSTRUCT, rct:RECT, hBrush:dword, hBrush_old:dword
    local mDC:dword, hBmp:dword, hBmp_old:dword, hPen:dword, hPen_old:dword
    local x:dword, y:dword, wwid:dword, whgt:dword, cwid:dword, chgt:dword
        .if uMsg == WM_INITDIALOG

          ;; resizing Client Area to exact dimensions, specified by cwidth and cheight

          invoke GetWindowRect, hWin, addr rct ;; get window current dimensions.
          mov eax, rct.right                  ;; obtain current window width by subtracting left boundary
          sub eax, rct.left                    ;; from the right boundary
          mov wwid, eax                        ;; store current window width
          mov eax, rct.bottom                  ;; obtain current window height by subtracting top boundary
          sub eax, rct.top                    ;; from the bottom boundary
          mov whgt, eax                        ;; store current window height

          invoke GetClientRect, hWin, addr rct ;; get client area current dimensions.
          mov eax, rct.right                  ;; obtain current client width by subtracting left boundary
          sub eax, rct.left                    ;; from the right boundary
          mov cwid, eax                        ;; store current client area width
          mov eax, rct.bottom                  ;; obtain current client height by subtracting top boundary
          sub eax, rct.top                    ;; from the bottom boundary
          mov chgt, eax                        ;; store client area height

          ;; calculate the difference between desired client area width and current client area width
          mov eax, cwidth
          sub eax, cwid

          ;; adjust the window width according to the difference calculated above
          add wwid, eax

          ;; calculate the difference between desired client area height and current client area height
          mov eax, cheight
          sub eax, chgt
          ;; adjust the window height according to the difference calculated height
          add whgt, eax

          ;; center the main window
          ;; obtain client area of the desktop, not including the task bar
          invoke SystemParametersInfoA, SPI_GETWORKAREA, 0, addr rct, 0

          ;; center window width
          mov eax, rct.right
          sub eax, wwid
          sar eax, 1
          mov x, eax

          ;; center window height
          mov eax, rct.bottom
          sub eax, whgt
          sar eax, 1
          mov y, eax

          ;; implement the centering of the resized main window
          invoke MoveWindow, hWin, x, y, wwid, whgt, TRUE

        .elseif uMsg == WM_SIZE
          invoke InvalidateRect, hWin, 0, 0
        .elseif uMsg == WM_PAINT
          invoke BeginPaint, hWin, addr ps
          mov hDC, eax                          ; window client area DC
         
          ;; get client area rectangle
          invoke GetClientRect, hWin, addr rct

          invoke CreateCompatibleDC, hDC
          mov mDC, eax                          ; memory DC

          invoke SelectObject, mDC, hBmpgdip    ; select image HBITMAP

          invoke StretchBlt, hDC, 0, 0, rct.right, rct.bottom, mDC, 0, 0, 276, 213, SRCCOPY

          invoke DeleteDC, mDC

          invoke EndPaint, hWin, addr ps
        .elseif uMsg == WM_CLOSE
          invoke EndDialog, hWin, 0
        .endif
        xor eax, eax
        ret
    DlgProc endp

    writefilex proc lpName:dword, lpData:dword, fl:dword
    local hOutput:dword
    local bw :dword
        invoke CreateFile, lpName, GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, 0, 0
        cmp eax, -1
      jne @F
        fn MessageBox, 0, lpName, "Couldn't read File!", MB_OK
        xor eax, eax
        xor ecx, ecx
        jmp xit
      @@:
        mov hOutput, eax
        invoke WriteFile, hOutput, lpData, fl, addr bw, NULL
        invoke CloseHandle, hOutput
        mov eax, 1
      xit:
        ret
    writefilex endp

    end
   
    (https://i.postimg.cc/dtJkLmy1/untitled.png)

I think everything here is proper in regards to the gdiplus code.
What about using gdiplus code in WM_PAINT?? I have zero clue myself.
Using StretchBlt on a large image, when resizing smaller the results are not very appealing.
If nothing else, I have a way now to load and use .jpg, .png or .gif files in my programs, without relying on others work. *except as research material, into trying to understand gdi+.  :smiley:
Title: Re: Gdi+ tests
Post by: NoCforMe on March 12, 2025, 04:28:03 AM
Here's your WM_PAINT handler for GDI+, good buddy:
.data
GDIhBitmap DD ? ;Global GDI+ bitmap handle

;=================================
; Open image before WM_PAINT runs:
; Note: "ImageFilename" must be Unicode
;=================================
INVOKE GdipLoadImageFromFile, OFFSET ImageFilename, OFFSET GDIhBitmap

;==================
; WM_PAINT handler:
;==================
LOCAL gdiHgraphics:DWORD

do_paint:
INVOKE BeginPaint, hWin, ADDR ps
MOV hDC, EAX

; Get graphics "object" from DC handle:
INVOKE GdipCreateFromHDC, hDC, ADDR gdiHgraphics

; Display image at (X,Y) with dimensions (W,H):
Invoke GdipDrawImageRectI, gdiHgraphics, GDIhBitmap, X, Y, W, H

INVOKE EndPaint, hWin, ADDR ps
XOR EAX, EAX
RET

You've already done the first part (opening the image with GdipLoadImageFromFile(); that gets done outside of the WM_PAINT handler.

Many thanks to "mabdelouahab" of this forum who provided these magic incantations ...

Title: Re: Gdi+ tests
Post by: zedd151 on March 12, 2025, 04:35:17 AM
Quote from: NoCforMe on March 12, 2025, 04:28:03 AMHere's your WM_PAINT handler for GDI+, good buddy
; Display image at (X,Y) with dimensions (W,H):
    Invoke GdipDrawImageRectI, gdiHgraphics, GDIhBitmap, X, Y, W, H

Thanks chum.  :tongue:
And mabdelouahab, for the
Quote from: NoCforMe on March 12, 2025, 04:28:03 AMmagic incantations ...
:thumbsup:

I new there had to be a gdi+ way to draw the image ... back to more experimentation...

The MS documentation is weird when searching for gdiplus functions
"Creates a Graphics::Graphics object that is associated with a specified device context." ... like that tells ME something. lol

In a "real" program I would probably put the gdi+ startup code in either WM_INITDIALOG, or WM_CREATE depending on the GUI design, and the gdi+ shutdown call in WM_CLOSE.
Title: Re: Gdi+ tests
Post by: NoCforMe on March 12, 2025, 05:00:17 AM
Yes, documentation. Ugh.
This Micro$oft Learn page (https://learn.microsoft.com/en-us/windows/win32/gdiplus/-gdiplus-graphics-flat) has a table of all the "flat" GDI+ functions--that is, the functions removed from their C++ "wrapper" and exposed for us non-C++ programmers. It's a little clunky, but search for the function you want info on and it'll show the parameters and other good stuff if you click on it.
Title: Re: Gdi+ tests
Post by: zedd151 on March 12, 2025, 05:03:39 AM
Quote from: NoCforMe on March 12, 2025, 05:00:17 AMYes, documentation. Ugh.
This Micro$oft Learn page (https://learn.microsoft.com/en-us/windows/win32/gdiplus/-gdiplus-graphics-flat) has a table of all the "flat" GDI+ functions--that is, the functions removed from their C++ "wrapper" and exposed for us non-C++ programmers. It's a little clunky, but search for the function you want info on and it'll show the parameters and other good stuff if you click on it.
Thanks for the tip, and no thanks to Microsoft.  :biggrin:
I like the win32.hlp method of presenting information. Too bad gdi+, and some others never made it in there.
Title: Re: Gdi+ tests
Post by: TimoVJL on March 12, 2025, 05:56:27 AM
Do we need GdipDeleteGraphics after GdipCreateFromHDC ?
Title: Re: Gdi+ tests
Post by: zedd151 on March 12, 2025, 06:10:52 AM
Quote from: TimoVJL on March 12, 2025, 05:56:27 AMDo we need GdipDeleteGraphics after GdipCreateFromHDC ?
I dunno, I am still learning about gdi+, and why I am asking questions here.   :azn:

I just downloaded  from MS, windows-win32-gdiplus.pdf for my research...   :eusa_dance:

 gdi+ reference (https://learn.microsoft.com/en-us/windows/win32/gdiplus/-gdiplus-class-gdi-reference)
Button on the left of that page to Download PDF.


Title: Re: Gdi+ tests
Post by: zedd151 on March 12, 2025, 06:16:24 AM
... whoops.  :eusa_boohoo:
AGAIN! Quoted the above post, meaning to modify it.  :greensml:
Title: Re: Gdi+ tests
Post by: NoCforMe on March 12, 2025, 06:36:21 AM
Quote from: TimoVJL on March 12, 2025, 05:56:27 AMDo we need GdipDeleteGraphics after GdipCreateFromHDC ?
Maybe, to prevent resource leaks.
Although the "graphics" object might be automagically deleted by Windows on program exit.
Title: Re: Gdi+ tests
Post by: adeyblue on March 12, 2025, 12:03:52 PM
QuoteDo we need GdipDeleteGraphics after GdipCreateFromHDC ?
Yes. GDIhBitmap also needs GdipDisposeImage-ing

Title: Re: Gdi+ tests
Post by: zedd151 on March 12, 2025, 12:12:08 PM
Quote from: adeyblue on March 12, 2025, 12:03:52 PM
QuoteDo we need GdipDeleteGraphics after GdipCreateFromHDC ?
Yes. GDIhBitmap also needs GdipDisposeImage-ing
Thanks adeyblue. I am still doing research on gdi+ stuff.

Haven't seen you around here in a hot minute...  :smiley:
Title: Re: Gdi+ tests
Post by: NoCforMe on March 12, 2025, 12:43:19 PM
Quote from: adeyblue on March 12, 2025, 12:03:52 PM
QuoteDo we need GdipDeleteGraphics after GdipCreateFromHDC ?
Yes. GDIhBitmap also needs GdipDisposeImage-ing
OK, I looked that up in my GDI+ help file; it says
QuoteDisposes the specified Image object.

Hmm, that's not very helpful.
So what, exactly, does it mean to "dispose" [of?] an image object?
I know delete and destroy, but not dispose ...

Man, all this C++/"object" sophistry ...
Title: Re: Gdi+ tests
Post by: zedd151 on March 12, 2025, 01:17:47 PM
Quote from: NoCforMe on March 12, 2025, 12:43:19 PMSo what, exactly, does it mean to "dispose" [of?] an image object?
I gunna try to find out...

I am going to try it where I would normally delete any gdi objects, either before EndPaint, or in WM_CLOSE.

Or maybe better, just before calling the gdiplus shutdown api.

I would have to see an example of how/when it is used. Or at least a more detailed description of the order of execution, i.e., where in the gdiplus chain of events this needs to be called. If that makes any sense. I'm tired and need sleep.  :tongue:

Title: Re: Gdi+ tests
Post by: zedd151 on March 12, 2025, 01:19:43 PM
Quote from: NoCforMe on March 12, 2025, 12:43:19 PMSo what, exactly, does it mean to "dispose" [of?] an image object?
I gunna try to find out...

I am going to try it where I would normally delete any gdi objects, either before EndPaint, or in WM_CLOSE.

Or maybe better, just before calling the gdiplus shutdown api.

I would have to see an example of how/when it is used. Or at least a more detailed description of the order of execution, i.e., where in the gdiplus chain of events this needs to be called, if that makes any sense.
I'm tired and need sleep.  :tongue:

Title: Re: Gdi+ tests
Post by: TimoVJL on March 12, 2025, 01:34:34 PM
When object goes out of scope in OOP language, it will be destroyed after that.

So if object is created with GdipCreateFromHDC() in WM_PAINT, it should be destroyed with GdipDeleteGraphics() after it isn't needed anymore.
Title: Re: Gdi+ tests
Post by: zedd151 on March 12, 2025, 01:42:48 PM
Quote from: TimoVJL on March 12, 2025, 01:34:34 PMWhen object goes out of scope in OOP language, it will be destroyed after that.

So if object is created with GdipCreateFromHDC() in WM_PAINT, it should be destroyed with GdipDeleteGraphics() after it isn't needed anymore.

After the drawing has taken place, I would assume. Thanks Timo. Some things in MS documentation aren't always very clear.

Later:
Bbbbut wait a minute, I am not using GdipCreateFromHDC... did you look at my source code in post #1? I was following various gdiplus examples with bits and pieces from here and there... until I got everything working....
Title: Re: Gdi+ tests
Post by: TimoVJL on March 12, 2025, 02:23:31 PM
Quote from: zedd151 on March 12, 2025, 01:42:48 PMLater:
Bbbbut wait a minute, I am not using GdipCreateFromHDC... did you look at my source code in post #1? I was following various gdiplus examples with bits and pieces from here and there... until I got everything working....
That GdipCreateFromHDC thing started at post #2
Title: Re: Gdi+ tests
Post by: zedd151 on March 12, 2025, 02:25:03 PM
Quote from: TimoVJL on March 12, 2025, 02:23:31 PMThat GdipCreateFromHDC thing started at post #2
Ah, okay. That was meant for NoCforMe.... you should have been more specific.  :smiley:

Since you posted right after one of my posts, it appeared to me that your post was meant for me.
Title: Re: Gdi+ tests
Post by: NoCforMe on March 12, 2025, 02:40:12 PM
Quote from: TimoVJL on March 12, 2025, 01:34:34 PMWhen object goes out of scope in OOP language, it will be destroyed after that.

So if object is created with GdipCreateFromHDC() in WM_PAINT, it should be destroyed with GdipDeleteGraphics() after it isn't needed anymore.
OK. But what about this other function, GdipDisposeImage(): when (and why) is it needed?

What does it mean to "dispose" [of] an image?
Title: Re: Gdi+ tests
Post by: NoCforMe on March 12, 2025, 02:49:39 PM
Well, a partial answer, anyhow, from good old Stack Overflow (https://stackoverflow.com/questions/30004391/how-to-release-an-object-created-from-gdipcreatebitmapfromhbitmap):
QuoteThat being said, GdipCreateBitmapFromHBITMAP() returns a pointer to a GpBitmap object (which is wrapped by the Bitmap class in C++). GdipDisposeImage() is the correct way to release that object (which is called by the Image destructor in C++).

So it may not be needed here, since we're not creating a GpBitmap object using GdipCreateBitmapFromHBITMAP().

God damn, this shit be complicated ... too complicated ...
Title: Re: Gdi+ tests
Post by: zedd151 on March 12, 2025, 02:55:11 PM
Quote from: NoCforMe on March 12, 2025, 02:40:12 PMOK. But what about this other function, GdipDisposeImage(): when (and why) is it needed?
I think it has to do with how HBITMAP is created. Heres mine.

        fn GdipCreateBitmapFromFile, addr upicname, addr gdipBmp        ; open image file, create image object
        invoke GdipCreateHBITMAPFromBitmap, gdipBmp, addr hBmpgdip, 0  ; get HBITMAP, from image object
        invoke GdipDisposeImage, gdipBmp                                ; dispose image object

I use hBmpgdip (HBITMAP) from here in WM_PAINT to blit the image to DC with
Not sure still if I need to call GdipDeleteGraphics() by what Timo says...

It seems there are many ways to do very similar things with gdi+, and I understand none of them. Yet.  :eusa_boohoo:
Title: Re: Gdi+ tests
Post by: NoCforMe on March 12, 2025, 02:58:13 PM
Yeah, it'd be nice to find some kind of tutorial or at least a better explanation of how all that shit works that's better than Micro$oft's documentation.

Too lazy to look for it at the moment ...
Title: Re: Gdi+ tests
Post by: zedd151 on March 12, 2025, 03:19:53 PM
Quote from: NoCforMe on March 12, 2025, 02:58:13 PMYeah, it'd be nice to find some kind of tutorial...
Too lazy to look for it at the moment ...
I just did a quick forum search for both gdi+ and gdip...  Shoulda done that even before starting this topic.  :eusa_dance:
Seems there are a lot of topics covering gdi+/gdiplus..

Should be some good examples (hopefully not buggy code) somewhere here already.  :biggrin:
Maybe tomorrow, its late here.
Title: Re: Gdi+ tests
Post by: sinsi on March 12, 2025, 03:26:49 PM
How to release an object created from GdipCreateBitmapFromHBITMAP? (https://stackoverflow.com/questions/30004391/how-to-release-an-object-created-from-gdipcreatebitmapfromhbitmap)

QuoteThat being said, GdipCreateBitmapFromHBITMAP() returns a pointer to a GpBitmap object (which is wrapped by the Bitmap class in C++). GdipDisposeImage() is the correct way to release that object (which is called by the Image destructor in C++).

I would imagine it's like an interface - you ask for an object and it gives you a reference.
Once you've finished with it you release it.
Title: Re: Gdi+ tests
Post by: zedd151 on March 12, 2025, 03:47:58 PM
It might just be easier to take the approach that hutch did in masm64 SDK examples. Load the .jpg or other image file and set it into a static control, rather than using WM_PAINT explicitly to draw/blit/stretch it to DC.  :tongue:

I don't know if his code regarding gdiplus is totally kosher now, after all I have been reading about gdi+ throughout the day. I don't see any Delete apis called there for gdip objects, unless I missed it.

And I will say it before NoCforMe does... Classes schmlasses.  :biggrin:
They don't make things easy for an assembly programmer.
Title: Re: Gdi+ tests
Post by: sinsi on March 12, 2025, 04:00:44 PM
This might have some items of interest

https://github.com/VFPX/Win32API/tree/master/libraries/gdiplus (https://github.com/VFPX/Win32API/tree/master/libraries/gdiplus)
Title: Re: Gdi+ tests
Post by: zedd151 on March 12, 2025, 04:11:25 PM
Yes, I have seen that while doing some research today. Thanks.
It's just that there seems to be several different paths to open and display .jpg, .png, .gif images. But nothing I have read yet, tells me which api should follow another in the code flow if that makes any sense.
The code I posted in the first post works, but I don't know if the gdiplus code flow is complete.

It's not like plain old gdi, where you can check Task Manager for gdi leaks, if I am not mistaken. Gdiplus might be leaking like a sieve.

I am very tired now. I'll get back to this tomorrow.
Title: Re: Gdi+ tests
Post by: TimoVJL on March 12, 2025, 06:04:53 PM
avcaballero made an example for GDIPlus
https://board.flatassembler.net/topic.php?p=193082 (https://board.flatassembler.net/topic.php?p=193082)
Title: Re: Gdi+ tests
Post by: NoCforMe on March 12, 2025, 07:23:49 PM
Quote from: sinsi on March 12, 2025, 04:00:44 PMThis might have some items of interest

https://github.com/VFPX/Win32API/tree/master/libraries/gdiplus (https://github.com/VFPX/Win32API/tree/master/libraries/gdiplus)

Sorry, not sorry: that really doesn't help.
It's the same documentation of the GDI+ flat functions that I already have in a Windows help (.chm) file. All it does is give the function parameters and return values: it doesn't really explain what the function does in any detail. That's what we need here.
Title: Re: Gdi+ tests
Post by: sinsi on March 12, 2025, 07:52:34 PM
Quote from: NoCforMe on March 12, 2025, 07:23:49 PMSorry, not sorry: that really doesn't help.
Did you look at any?

You asked the question earlier
Quote from: NoCforMe on March 12, 2025, 02:40:12 PMOK. But what about this other function, GdipDisposeImage(): when (and why) is it needed?


The link gives an answer as to why
QuoteDECLARE INTEGER GdipDisposeImage IN gdiplus;
    INTEGER img 
Parameters:
img [in] Identifies the Image created by GdipLoadImageFromFile, GdipLoadImageFromStream and other Image constructors.
Title: Re: Gdi+ tests
Post by: NoCforMe on March 12, 2025, 08:26:29 PM
Quote from: sinsi on March 12, 2025, 07:52:34 PMThe link gives an answer as to why
QuoteDECLARE INTEGER GdipDisposeImage IN gdiplus;
    INTEGER img 
Parameters:
img [in] Identifies the Image created by GdipLoadImageFromFile, GdipLoadImageFromStream and other Image constructors.
No it doesn't!
How is that in any way an explanation of what it does?
What does it mean to "dispose" [of] an image?
Since this is a different verb from "delete" or "destroy", it leads one to believe that it does something different from those actions. But what?
And when do we need to use this? with what types of "objects"?
Do you see how a real explanation of how this stuff works is what's needed (for us who don't know yet)?
Title: Re: Gdi+ tests
Post by: sinsi on March 12, 2025, 08:38:38 PM
Jeez man, ever heard of a synonym?

To me, it's self-explanatory.
You create/load/bring into being an image from a file/stream/etc.
You dispose of/delete/destroy/kill it when you're finished using it.

That's a bit more information than MS give you.
Title: Re: Gdi+ tests
Post by: TimoVJL on March 12, 2025, 08:49:13 PM
Have to understand OOP principles.
Every COM object have method Release and OOP object delete or ~
and other are just synonyms for same purpose.
I haven't found any good simple info for GDIPlusFlat API, that is for non-OOP languages.

Name GdipDisposeImage() quite is logical, it don't delete nor destroy that image, just release it's object and it's resources from memory.
Title: Re: Gdi+ tests
Post by: NoCforMe on March 12, 2025, 08:50:08 PM
Quote from: sinsi on March 12, 2025, 08:38:38 PMJeez man, ever heard of a synonym?

To me, it's self-explanatory.
You create/load/bring into being an image from a file/stream/etc.
You dispose of/delete/destroy/kill it when you're finished using it.

That's a bit more information than MS give you.

Is it, though? MS does say
QuoteReleases resources used by the Image object.

Which may seem obvious, but it's nice to at least have a hint, a clue as to what a function does ...
Title: Re: Gdi+ tests
Post by: NoCforMe on March 12, 2025, 09:10:22 PM
I've reached a conclusion about using the GDI+ "flat" API:
The best way to figure out how to use this stuff (600+ functions) is, to use that internet abbreviation,
FAFO
Title: Re: Gdi+ tests
Post by: zedd151 on March 12, 2025, 09:14:44 PM
Quote from: NoCforMe on March 12, 2025, 09:10:22 PMI've reached a conclusion about using the GDI+ "flat" API:
The best way to figure out how to use this stuff (600+ functions) is, to use that internet abbreviation,
FAFO

I had to look that up.  :joking:  :rofl:
It went right over my head.

Either that, or "fake it until you make it".  :tongue:

I guess I'll just stick to drawing lines, pixels, ellipses and rectangles, and more importantly polygons!  :biggrin:  :biggrin:
Title: Re: Gdi+ tests
Post by: jj2007 on March 12, 2025, 09:53:08 PM
Calls used in my ImgPaintP proc (tested, no leaks); GdipDisposeImage and GdipDeleteGraphics are indeed the last actions required.
invGdip GdipCreateBitmapFromHBITMAP, eax, 0, esp
invGdip GdipCreateBitmapFromStream, #
invGdip GdipCreateBitmapFromHBITMAP, eax, 0, esp
invGdip GdipCreateHBITMAPFromBitmap, gsi.jjImgObject, addr gdiFil
invGdip GdipCreateFromHDC, ecx, addr gsi.jjGraphicsObj
invGdip GdipImageGetFrameDimensionsList, giImage, addr Dimensio
invGdip GdipImageGetFrameCount, giImage, addr DimensionIDs, add
invGdip GdipImageSelectActiveFrame, giImage, addr DimensionIDs
invGdip GdipGetPropertyItemSize, giImage, PropertyTagFrameDelay
invGdip GdipGetPropertyItem, giImage, PropertyTagFrameDelay, prop
invGdip GdipGetPropertyItemSize, giImage, PropertyTagDocumentName
invGdip GdipGetPropertyItem, giImage, PropertyTagDocumentName, pr
invGdip GdipGetPropertyItemSize, giImage, PropertyTagLoopCount, a
invGdip GdipGetPropertyItem, giImage, PropertyTagLoopCount, propS
invGdip GdipScaleWorldTransform, gsi.jjGraphicsObj, FP4(4.0)
invGdip GdipGetImageWidth, gsi.jjImgObject, esp
invGdip GdipGetImageHeight, gsi.jjImgObject, esp
invGdip GdipImageRotateFlip, gsi.jjImgObject, [edi.GuiImageZOOM].
invGdip GdipRotateWorldTransform, gsi.jjImgObject, FP4(45.0), Mat
invGdip GdipSaveImageToFile, giImage, ecx, eax, offset imgQuali
invGdip GdipDisposeImage, ebx
invGdip GdipDeleteGraphics, gsi.jjGraphicsObj
Title: Re: Gdi+ tests
Post by: zedd151 on March 12, 2025, 10:00:33 PM
Quote from: jj2007 on March 12, 2025, 09:53:08 PMCalls used in my ImgPaintP proc (tested, no leaks); GdipDisposeImage and GdipDeleteGraphics are indeed the last actions required.

From what was posted here, I understand that GdipDeleteGraphics is definitely needed if GdipCreateFromHDC is called.

Which, in my exapmle  in #1 I do not use GdipCreateFromHDC .

Are there other gdip apis that would need GdipDeleteGraphics also?

When is GdipDeleteGraphics actually needed? Or is it a standard function that should always be called kinda like EndPaint?

I do call GdipDisposeImage, though. I think in the right place, too.

Listing 20+ apis, doesnt tell us what is definitely neeeded for a simple example as I posted in the original post here, jj2007.

I just want to know for now, if the code in that example is complete (as far as the gdip stuff) or is there an api call that is missing???

I am using gdi StretchBlt to do the actual drawing to the DC.
Title: Re: Gdi+ tests
Post by: daydreamer on March 12, 2025, 10:19:27 PM
My experience of memory leak in gdi, was long ago it worked a little while until all create pen and brush stopped working and program started to draw black and white
That why delete objects are important

"fake it until you make it".  :tongue:
It's so true in demo/game graphics development from slowest x86 faking it with luts and cheat like pseudo 3d and pre rendered 3d objects and light to new gaming computers making it with real time rendering with pixelshaders


Title: Re: Gdi+ tests
Post by: TimoVJL on March 12, 2025, 10:22:15 PM
GdipCreateHBITMAPFromBitmap just create GDI bitmap, not object.
GdipDeleteGraphics is only for Graphics object.
GdipCreateBitmapFromFile create GpBitmap object, that you delete with GdipDisposeImage.
So a your GdipDisposeImage was in right place.
Title: Re: Gdi+ tests
Post by: zedd151 on March 12, 2025, 10:25:18 PM
Quote from: daydreamer on March 12, 2025, 10:19:27 PMMy experience of memory leak in gdi, was long ago it worked a little while until all create pen and brush stopped working and program started to draw black and white
That why delete objects are important

"fake it until you make it".  :tongue:
It's so true in demo/game graphics development from slowest x86 faking it with luts and cheat like pseudo 3d and pre rendered 3d objects and light to new gaming computers making it with real time rendering with pixelshaders

Um. Okay. How does that answer a single question about GDI+?
GDI leaks are easily seen in Task Manager cause by not deleting the usual object (pens, brushes), and possibly not deleting memory DC. Or would that one be a memory leak??
I don't think that applies to GDI+ and it's apis.

There are no GDI leaks in my example, btw.
Title: Re: Gdi+ tests
Post by: zedd151 on March 12, 2025, 10:28:42 PM
Quote from: TimoVJL on March 12, 2025, 10:22:15 PMGdipCreateHBITMAPFromBitmap just create GDI bitmap, not object.
GdipDeleteGraphics is only for Graphics object.
GdipCreateBitmapFromFile create GpBitmap object, that you delete with GdipDisposeImage.
So a your GdipDisposeImage was in right place.

Thank you for taking the time to look at my code. :azn:
Do I need to call GdipDeleteGraphics?

I am a bit mystified with this gdi+ stuff.
I had thought I had done enough research before posting the example. And I believe everything I need is already in the code.
Title: Re: Gdi+ tests
Post by: TimoVJL on March 12, 2025, 10:32:29 PM
No with #1 code, as Graphic object wasn't created in that code
Title: Re: Gdi+ tests
Post by: zedd151 on March 12, 2025, 10:35:52 PM
Quote from: TimoVJL on March 12, 2025, 10:32:29 PMNo with #1 code, as Graphic object wasn't created in that code
Thank you. That is all I needed to know at this time.

Now everybody...
See, this is what happens when you throw around function names that are not relevant to the topic at hand (meaning my example in post #1).

It causes major confusion to those trying to learn something new. In this case, ME. And NoCforMe as well.

Case closed for me, problem non existent, carry on.
Sheesh! Over 14 hours to finally get the answers that really mattered regarding my posted code.

Thread Closed!

Just kidding about that last one  :skrewy:

I am satisfied using BitBlt or StretchBlt to draw it to the DC. I ain't gunna try doing it with gdiplus at this time.  :smiley:

But to be clear, Timo.. if I do use a gdi+ API to draw to the DC, will I then need to use GdipDeleteGraphics?
Title: Re: Gdi+ tests
Post by: TimoVJL on March 12, 2025, 10:50:04 PM
Quoteto be clear, Timo.. if I do use a gdi+ API to draw to the DC, will I then need to use GdipDeleteGraphics?
Just in case, that you use GdipCreateFromHDC or similar function
Title: Re: Gdi+ tests
Post by: zedd151 on March 12, 2025, 10:51:23 PM
Quote from: TimoVJL on March 12, 2025, 10:50:04 PM
Quoteto be clear, Timo.. if I do use a gdi+ API to draw to the DC, will I then need to use GdipDeleteGraphics?
Just in case, that you use GdipCreateFromHDC or similar function
Okay, now I think I got it. Thanks man!

:biggrin:
I'll tinker some more with gdi+ in the future.
For now, this is enough for me to begin using smaller (in kb) images instead of huge 24 bit bitmaps. I will polish up the code, and post it as a "proper example" for others to possibly learn from, away from the distractions here in this WIP thread.

Thanks to all that posted helpful information, and to those that had good (possibly misguided) intentions.
And thank you once again Timo, your help has been invaluable.

Do you have any gdi+ examples in C that you could share, Timo?
I am not adverse to learning from C example code. (As long as it will compile with gcc that is)  :smiley:
... if you don't have anything already written, that's ok.
Title: Re: Gdi+ tests
Post by: jj2007 on March 13, 2025, 03:47:45 AM
Quote from: zedd151 on March 12, 2025, 10:00:33 PMAre there other gdip apis that would need GdipDeleteGraphics also?

In my code it's GdipCreateFromHDC that creates the graphics object to be deleted later.
Title: Re: Gdi+ tests
Post by: zedd151 on March 13, 2025, 03:48:53 AM
That's what I understood from earlier. Thx for the confirmation.  :thumbsup:

Quote from: TimoVJL on March 12, 2025, 01:34:34 PMif object is created with GdipCreateFromHDC() in WM_PAINT, it should be destroyed with GdipDeleteGraphics() after it isn't needed anymore.

Title: Re: Gdi+ tests
Post by: NoCforMe on March 13, 2025, 09:30:20 AM
@Zedd: to lessen the confusion here, you should realize that since there are several types of "objects" here, you need to use the relevant function (not an API: the whole schmear is the API) to release/delete/destroy/dispose that object:
So if you create a bitmap, then you wouldn't use GdipDeleteGraphics(), because that applies to a different class of objects (graphics vs. bitmaps). (Unless you create a graphic object from a bitmap, in which case you would use that function.)

I've been able to figure at least that much out so far ...
Title: Re: Gdi+ tests
Post by: zedd151 on March 13, 2025, 09:36:57 AM
All I know is my little example is fine as far as the gdi+ code goes. And I'm happy as a camper to be done with gdi+. Yuck. What a big mess.  :biggrin:
Title: Re: Gdi+ tests
Post by: jj2007 on March 13, 2025, 09:53:10 AM
Quote from: zedd151 on March 13, 2025, 09:36:57 AMYuck. What a big mess.  :biggrin:

Agreed :badgrin:

include \masm32\MasmBasic\Res\MbGui.asm
Event Paint
  GuiImage CL$(), fit
GuiEnd

P.S.: Drag tweety over the exe, then size the window :smiley:
Title: Re: Gdi+ tests
Post by: NoCforMe on March 13, 2025, 09:55:46 AM
I second that emotion.
So Zedd: any motivation on your part to look into DirectDraw? Since you've been taking the Magical Mystery Tour of Win32 Graphics Techniques?
Title: Re: Gdi+ tests
Post by: zedd151 on March 13, 2025, 10:03:01 AM
Quote from: NoCforMe on March 13, 2025, 09:55:46 AMI second that emotion.
So Zedd: any motivation on your part to look into DirectDraw? Since you've been taking the Magical Mystery Tour of Win32 Graphics Techniques?
Hell no. After this fiasco. (Not really a fiasco, my code was okay in the end, but the confusion after - definite fiasco)
I think DirectDraw would break my brain.

Quote from: jj2007 on March 13, 2025, 09:53:10 AMP.S.: Drag tweety over the exe, then size the window :smiley:

"GdiPlusEasy.exe"... Easy my ass! 49 gdiplus functions/apis???  :dazzled:  (whatever the hell you'd call 'em, David)

But it was a cute feature.  :azn:  animate on resizing
Bug report: Menu items do not work on click.  :biggrin:

Yves (https://i.postimg.cc/PJg3q2tr/yves.gif)          Yours (https://i.postimg.cc/nLpW7RqX/Tweetie.gif)

Free Yves! Let him go... can't you see he is flapping his wings faster while in captivity trying to escape?
Title: Re: Gdi+ tests
Post by: adeyblue on March 13, 2025, 02:31:36 PM
Quote from: zedd151 on March 13, 2025, 10:03:01 AM"GdiPlusEasy.exe"... Easy my ass! 49 gdiplus functions/apis???  :dazzled:  (whatever the hell you'd call 'em, David)

I remember when JJ would be posting in astonishment at the prospect of such a simple task needing to import 10 dlls and nearly 300 functions. What happened to that guy? Looks like he's gotten into bed with  the bloat industry *idk what the smiley codes are, imagine there's one here*
Title: Re: Gdi+ tests
Post by: zedd151 on March 13, 2025, 02:49:08 PM
Sound about right.  :joking:
Title: Re: Gdi+ tests
Post by: NoCforMe on March 13, 2025, 02:51:51 PM
Point taken.

In fairness to JJ, though, everything he does, all that pain he goes through with those 10 DLLs and 300 functions, ends up in his baby, his project, MasmBasic. Where it then becomes available to its users (I'm not one of them, BTW) as a very easy-to-use facility, often accomplishing in a single line of code what it takes the rest of us 10 or 100 times that. Which is a pretty good piece of work if you ask me.

Regarding terminology: since when did "functions" become aggrandized to "APIs"? An API ("application programming interface") is the entire collection of things--functions, structures, enumerations, etc.--that accomplish certain tasks. GDI+ is an API; GdipDeleteGraphics() is just a function within that API.

I notice this undue promotion of meaning occurs in lots of other places online, not just here. But let's nip it in the bud, shall we?
Title: Re: gdiplus tests
Post by: zedd151 on March 13, 2025, 02:56:34 PM
Yes, Professor.  :biggrin:
Title: Re: gdiplus tests
Post by: NoCforMe on March 13, 2025, 03:19:55 PM
That's "Perfessor" to you.
Title: Re: gdiplus tests
Post by: sinsi on March 13, 2025, 05:20:59 PM
Quote from: NoCforMe on March 13, 2025, 02:51:51 PMRegarding terminology: since when did "functions" become aggrandized to "APIs"? An API ("application programming interface") is the entire collection of things--functions, structures, enumerations, etc.--that accomplish certain tasks. GDI+ is an API; GdipDeleteGraphics() is just a function within that API.
To nitpick further, traditionally a "function" was a procedure you called and got a result back.
Not all Windows procedures return a result, so not all Windows procedures are functions.
Perhaps we could use the term "Windows API call"?
:biggrin:
Title: Re: Gdi+ tests
Post by: jj2007 on March 13, 2025, 07:31:39 PM
Quote from: zedd151 on March 13, 2025, 10:03:01 AMBut it was a cute feature.  :azn:  animate on resizing

Well, not really a feature :badgrin:

Some trigger is needed to animate a GIF: a timer, resizing, mousemove...

GuiParas equ "An image, hooray!!!!", w300, h300, icon Butterfly
include \masm32\MasmBasic\Res\MbGui.asm

Event Message
  If_ uMsg_==WM_MOUSEMOVE Then GuiCls

Event Paint
  GuiImage CL$(), fit
GuiEnd
Title: Re: gdiplus tests
Post by: jj2007 on March 13, 2025, 07:46:58 PM
Quote from: adeyblue on March 13, 2025, 02:31:36 PMI remember when JJ would be posting in astonishment at the prospect of such a simple task needing to import 10 dlls and nearly 300 functions. What happened to that guy? Looks like he's gotten into bed with  the bloat industry

A Hello World in MasmBasic weighs in at 32kBytes. That is bloat in Masm terms, I agree - but it's still tiny in comparison to a QT Hello World at several MB.

If you choose Say (https://www.jj2007.eu/MasmBasicQuickReference.htm#Mb1366) "Hello World" instead of Print, that adds only 512 bytes: no external libs, just a call to a built-in Windows feature.

The animated GIF in seven lines (https://masm32.com/board/index.php?topic=12605.msg137000#msg137000) of source code costs 57kBytes. Serious bloat, of course :bgrin:

It's a compromise: some bloat, yes, but in turn you get comfortable graphics, string handling, file io (e.g. GetFiles (https://www.jj2007.eu/MasmBasicQuickReference.htm#Mb1056)) and much more. Hutch managed to keep all modules of Masm32 separate, they don't depend on each other, and therefore you can indeed produce a 1024 byte Hello World. But you have to add a lot of work for even simple things. MasmBasic has a core block of over 200 functions that costs around 32kBytes, and they do depend on each other, so no way to keep them as tiny as pure Masm32. I can live with that :cool:

I attach another example. Here is the source:
include \masm32\MasmBasic\MasmBasic.inc
  Init
  Say FileRead$(uCL$())
EndOfCode

The text in the file passed via the commandline (e.g. by dragging over the exe) must be UTF-16. I'd like to know whether it works for those of you who have an OS in Russian, Chinese or Arabic. I get an Italian voice ;-)

Don't drag TheHolyBible.txt over the exe, it might choke :bgrin:
Title: Re: gdiplus tests
Post by: zedd151 on March 13, 2025, 11:44:00 PM
Quote from: jj2007 on March 13, 2025, 07:31:39 PM
Quote from: zedd151 on March 13, 2025, 10:03:01 AMBut it was a cute feature.  :azn:  animate on resizing

Well, not really a feature :badgrin:
Do you realize how many mistakes, accidents, or otherwise 'not by design' inventions there are, that are multimillion dollar industries today?   :biggrin:
Title: Re: gdiplus tests
Post by: sinsi on March 14, 2025, 02:55:18 AM
My attempt at GDI+ GIF animation.
I've tried to make it MASM32 compatible  :biggrin:
No comments though  :eusa_boohoo:
Title: Re: gdiplus tests
Post by: zedd151 on March 14, 2025, 03:24:07 AM
@sinsi:

Seems a little off. I opened the .gif in ImageReady and the animation displays properly there, RoadRunner runs.
But in your example, looks like RoadRunner has the shakes or is shivering, rather than running.

At least it shows the concept of getting the individual .gif frames. And working with multi frame gifs in general.

Used this your gif with jochens example from #59, and it animates better with his, but still not perfect.

Carry on with your gdiplus tests, guys. The more the merrier.  :eusa_dance:
Title: Re: gdiplus tests
Post by: sinsi on March 14, 2025, 04:15:28 AM
It's on a timer, changing the delay helps a little.
The main problem is that the background doesn't get erased.

It was a quick test to see the steps involved in actually getting it to animate.
The next step is smoothing it out.

Not too bad for ~10 lines of gdiplus code and an hour of frustration on google :biggrin:
Title: Re: gdiplus tests
Post by: zedd151 on March 14, 2025, 04:27:26 AM
Quote from: sinsi on March 14, 2025, 04:15:28 AMIt's on a timer, changing the delay helps a little.
tried that, to no great improvement
QuoteThe main problem is that the background doesn't get erased.
Sounds like a likely possible cause
QuoteIt was a quick test to see the steps involved in actually getting it to animate.
The next step is smoothing it out.
okay, so it really is experimental test code
QuoteNot too bad for ~10 lines of gdiplus code and an hour of frustration on google :biggrin:
:biggrin:
Title: Re: gdiplus tests
Post by: sinsi on March 14, 2025, 04:48:14 AM
Updated. Now double buffered and resizable (looks crap when embiggened).
Might try a bigger GIF with more frames next.
Title: Re: gdiplus tests
Post by: zedd151 on March 14, 2025, 04:55:09 AM
Thats better. You're getting there.

btw I had to, in both cases, complete the path to "gdiplus.lib":
to --> "includelib  \masm32\lib\gdiplus.lib"

otherwise no problem assembling and linking

Title: Re: gdiplus tests
Post by: sinsi on March 14, 2025, 05:00:58 AM
Quote from: zedd151 on March 14, 2025, 04:55:09 AMThats better. You're getting there.
Gee, thanks grandpa

Quote from: zedd151 on March 14, 2025, 04:55:09 AMbtw I had to, in both cases, complete the path to "gdiplus.lib":
to --> "includelib  \masm32\lib\gdiplus.lib"
Yeah, I use a VS batch file and the Windows SDK libraries and binaries.
Title: Re: gdiplus tests
Post by: zedd151 on March 14, 2025, 05:03:00 AM
Quote from: sinsi on March 14, 2025, 05:00:58 AM
Quote from: zedd151 on March 14, 2025, 04:55:09 AMThats better. You're getting there.
Gee, thanks grandpa

Quote from: zedd151 on March 14, 2025, 04:55:09 AMbtw I had to, in both cases, complete the path to "gdiplus.lib":
to --> "includelib  \masm32\lib\gdiplus.lib"
Yeah, I use a VS batch file and the Windows SDK libraries and binaries.

Ok, that's fine. It wasn't a major job to fix it.
You young whippersnappers...  :biggrin:
Title: Re: gdiplus tests
Post by: NoCforMe on March 14, 2025, 06:28:45 AM
Quote from: sinsi on March 13, 2025, 05:20:59 PM
Quote from: NoCforMe on March 13, 2025, 02:51:51 PMRegarding terminology: since when did "functions" become aggrandized to "APIs"? An API ("application programming interface") is the entire collection of things--functions, structures, enumerations, etc.--that accomplish certain tasks. GDI+ is an API; GdipDeleteGraphics() is just a function within that API.
To nitpick further, traditionally a "function" was a procedure you called and got a result back.
Not all Windows procedures return a result, so not all Windows procedures are functions.
Perhaps we could use the term "Windows API call"?
:biggrin:

Welll, to expand on the pedantry just a bit more, technically speaking a "function" is, in mathematical terms, a black box (formula, etc.) that for each input value (x) produces a single output value (y) (so a parabola is a function while an ellipse is not).

However, as you point out, not all Win32, ahem, things that you call behave this way; some produce no output, while others produce more than a single value. So mathematically speaking they ain't functions.

But we need to call these things something, right? (My instinct is to call them "subroutines".) So Micro$oft, and practically everyone else out there has chosen to call them "functions". Which pretty much works for me; no need for hairsplitting here, even if it's not mathematically correct.

I just came up with another name: why don't we call them "Flamzingers"? That oughta settle it for good. (Somehow, though, I don't really see this catching on ...)
Title: Re: gdiplus tests
Post by: Vortex on March 14, 2025, 06:46:00 AM
Hello,

Here is a GdipCreateBitmapFromGdiDib example. This demo reads a bitmap file from disc and retrieves the handle of the image with help of GdiPlus function :

   .IF uMsg==WM_CREATE

        mov     eax,OFFSET StartupInfo
        mov     GdiplusStartupInput.GdiplusVersion[eax],1
        mov     GdiplusStatus,eax

        invoke  GdiplusStartup,ADDR token,ADDR StartupInfo,0

        invoke  ReadFileToMem,ADDR filename,ADDR pMem,\
                ADDR pBytesRead

        mov     eax,pMem
        mov     ecx,BITMAPFILEHEADER.bfOffBits[eax]
        lea     edx,[eax+ecx]                               ; points the array of bytes that contains the pixel data
        add     eax,SIZEOF BITMAPFILEHEADER                 ; points the BITMAPINFO structure

        invoke  GdipCreateBitmapFromGdiDib,eax,edx,\
                ADDR BmpImage
                                                            ; creates a Bitmap object based on a BITMAPINFO structure and
                                                            ; an array of pixel data                                                                                                                       
        invoke  GdipCreateHBITMAPFromBitmap,BmpImage,\
                ADDR hBitmap,0

        invoke  VirtualFree,pMem,0,MEM_RELEASE
Title: Re: gdiplus tests
Post by: zedd151 on March 14, 2025, 06:56:38 AM
@: NoCforMe
How about if we just call it a thingy.  :tongue:

If I or anyone else calls it an api, function, or anything else while also mentioning it by name, I am 100% certain that you or anyone else here that reads it will know exactly what I am talking about. Semantics, pedantics or any other kind of antics aside. 

Stop being a buzzkill.  :skrewy:

@Vortex:
Nice example, Vortex.

We are testing using gdiplus functions, for some of us, using gdiplus for the first time. Most of what is posted here is experimental or test code, not fully debugged examples. Thanks for your excellent contribution, it is appreciated.
Title: Re: gdiplus tests
Post by: jj2007 on March 14, 2025, 07:42:07 AM
Quote from: sinsi on March 14, 2025, 04:48:14 AMUpdated

You might use a lighter background. The animated-looney-toons-image-0017.gif is transparent (tweetie isn't)
Title: Re: gdiplus tests
Post by: NoCforMe on March 14, 2025, 07:46:20 AM
Quote from: zedd151 on March 14, 2025, 06:56:38 AM@: NoCforMe
Stop being a buzzkill.  :skrewy:
No.
Title: Re: gdiplus tests
Post by: zedd151 on March 14, 2025, 08:24:39 AM
Quote from: jj2007 on March 14, 2025, 07:42:07 AMis transparent (tweetie isn't)
I'm working on one that will be.  :tongue:
Title: Re: gdiplus tests
Post by: TimoVJL on March 14, 2025, 08:30:57 AM
https://en.m.wikipedia.org/wiki/Function_(computer_programming) (https://en.m.wikipedia.org/wiki/Function_(computer_programming))
Title: Re: gdiplus tests
Post by: zedd151 on March 14, 2025, 09:00:59 AM
Quote from: zedd151 on March 14, 2025, 08:24:39 AM
Quote from: jj2007 on March 14, 2025, 07:42:07 AMis transparent (tweetie isn't)
I'm working on one that will be.  :tongue:
Scratch that idea.
It had been so long that I had used ImageReady or Gimp to make transparent animated .gifs, I had forgotten much of what I once knew. Maybe some time in the future. A shame though, I have a 500 pixel wide clean copy of tweety in .gif with transparency. I fubarred my first several attempts so far. I might simply be missing a setting. They all had a white background.  :rolleyes:
(https://i.postimg.cc/SKM5jTRY/Tweety-Large.gif)
from https://officialpsds.com/tweety-fun-gif-rvyz32
Title: Re: gdiplus tests
Post by: NoCforMe on March 14, 2025, 09:19:30 AM
Needs sound: "I tawt I taw a putty tat!".
Title: Re: gdiplus tests
Post by: zedd151 on March 14, 2025, 01:18:18 PM
Here is my latest, a few minor needed changes based on example in #1. No animations here though, Sorry guys.

First I put the gdip startup code into a procedure, is called from WM_INITDIALOG
Also, put the image loading code into a procedure, is called from WM_INITDIALOG as well

Added a routine using GetOpenFileName, to choose an image file upon program starup, rather than using a hard coded image name. Gets called after loading the image.

I added code to get the image size. The client area will now be automatically sized exactly to the image size. rather than using hard coded image dimensions.

Some issues linger regarding image size.  :rolleyes:  if too large or small... (larger than screen dimensions, smaller than minimized window client)
For the larger images, I *could* use scrollbars on the main window, with all the phun that it entails.  :toothy:

A few other errata also to attend to, before it's ready for prime time.
Another thing, this program does not handle images with transparency.
Title: Re: gdiplus tests
Post by: NoCforMe on March 14, 2025, 04:16:01 PM
Interesting hybrid: you're using GDI+ to load image files and create handles to the bitmaps, but then you're using GDI (StretchBlt()) to actually display the image.

Was that intentional? does it work better for you that way?
Title: Re: gdiplus tests
Post by: zedd151 on March 14, 2025, 04:36:56 PM
Quote from: NoCforMe on March 14, 2025, 04:16:01 PMInteresting hybrid: you're using GDI+ to load image files and create handles to the bitmaps, but then you're using GDI (StretchBlt()) to actually display the image.

Was that intentional? does it work better for you that way?
At the time I first created it, I didn't know how to use gdi+ to do that. It worked fine like that, so I kept it.
Besides, I only really needed gdiplus only to load jpg,png,gif.etc. files. (Anything other than bmp's)
Why complicate simplicity?
Title: Re: gdiplus tests
Post by: daydreamer on March 15, 2025, 04:04:28 AM
Quote from: zedd151 on March 14, 2025, 04:36:56 PM
Quote from: NoCforMe on March 14, 2025, 04:16:01 PMInteresting hybrid: you're using GDI+ to load image files and create handles to the bitmaps, but then you're using GDI (StretchBlt()) to actually display the image.

Was that intentional? does it work better for you that way?
At the time I first created it, I didn't know how to use gdi+ to do that. It worked fine like that, so I kept it.
Besides, I only really needed gdiplus only to load jpg,png,gif.etc. files. (Anything other than bmp's)
Why complicate simplicity?
thats very helpful jpg,png directly used smaller files than uncompressed .bmp photos and no extra manually work convert files to .bmp's and gifs for cartoon and animations  :thumbsup:
Title: Re: gdiplus tests
Post by: NoCforMe on March 15, 2025, 07:40:41 AM
Quote from: zedd151 on March 14, 2025, 04:36:56 PM
Quote from: NoCforMe on March 14, 2025, 04:16:01 PMInteresting hybrid: you're using GDI+ to load image files and create handles to the bitmaps, but then you're using GDI (StretchBlt()) to actually display the image.

Was that intentional? does it work better for you that way?
At the time I first created it, I didn't know how to use gdi+ to do that. It worked fine like that, so I kept it.
Besides, I only really needed gdiplus only to load jpg,png,gif.etc. files. (Anything other than bmp's)
Why complicate simplicity?

Why indeed?
It turns out that your choice of hybrid processing may be the easier one.
You could use GDI+ to display the image (at a fixed size) after opening it from a file, using GdipDrawImageRectI() in your WM_PAINT handler instead of StretchBlt(). In that case, 6 of one, half a dozen of the other.

However, if you wanted to also resize the image dynamically (in the WM_PAINT handler), then it'd take an extra step for GDI+; you'd need to use something like GdipScaleWorldTransform() first, then use GdipDrawImageRectI(), whereas with GDI you can use StretchBlt() to resize and display the image.

Good to know you can mix & match stuff here.
Title: Re: gdiplus tests
Post by: zedd151 on March 15, 2025, 07:42:58 AM
Quote from: NoCforMe on March 15, 2025, 07:40:41 AMGood to know you can mix & match stuff here.
Yes. Before I first tried that, I wasn't certain that it would work. But alas, it did.  :biggrin:

One thing that I am not sure about. Would a gdiplus leak show up in task manager as a gdi leak? Or some form of memory leak? Or neither (something else)??
Title: Re: gdiplus tests
Post by: NoCforMe on March 15, 2025, 07:54:31 AM
Excellent question.
Wish I could answer it.
Process Explorer?
Title: Re: gdiplus tests
Post by: zedd151 on March 15, 2025, 08:09:42 AM
Quote from: NoCforMe on March 15, 2025, 07:54:31 AMExcellent question.
Wish I could answer it.
Process Explorer?
I might purposely not delete or dispose of any gdiplus related handles, to find out... then wait for a possible crash. All while watching task manager.
Then run the program in olly, if it had crashed in the previous run, to see if and where any exceptions occur. Some basic troubleshooting of a self inflicted injury.  :cool:  I'll report my findings.
Title: Re: gdiplus tests
Post by: NoCforMe on March 15, 2025, 08:40:02 AM
Um, I don't think you're going to get a crash as a consequence of not releasing a few GDI/GDI+ objects. It's going to take a lot more than that to get to any kind of exception or crash due to resource depletion. I suppose you could do something in a loop that consumes lots of handles or other "objects".

Why not do that--not delete stuff--and then just use Task Manager to see how many GDI objects you have each time you run the app?
Title: Re: gdiplus tests
Post by: zedd151 on March 15, 2025, 08:51:48 AM
Quote from: zedd151 on March 15, 2025, 08:09:42 AMI'll report my findings.
Okay, after commenting out the call here
    mov eax, lp_gdipBmp
    mov eax, [eax]                                                                  ;; get gdipBmp into eax (from lp_gdipBmp)
 ;    invoke GdipDisposeImage, eax                                                    ; dispose gdipBmp
No noticeable difference in gdi objects, no matter if minimized, maximized, or hidden behind other windows.
Arbitrary difference in memory usage. Or I should say either one could be a few hundred kb +- the other version. The version without that call, could be either a few kb more than the version with it, or vice versa. Without any rhyme or reason. Go figure.  :rolleyes:
Results of that test inconclusive. Also, no  crashes.
Title: Re: gdiplus tests
Post by: jj2007 on March 15, 2025, 07:32:37 PM
Quote from: NoCforMe on March 14, 2025, 04:16:01 PMthen you're using GDI (StretchBlt()) to actually display the image

GuiImage (https://www.jj2007.eu/MasmBasicQuickReference.htm#Mb1404) "\Masm32\examples\exampl04\car\car.jpg", fit  ; uses GdipDrawImageRectI, which stretches the image as desired

Quote from: NoCforMe on March 15, 2025, 07:40:41 AMGood to know you can mix & match stuff here.

I've always thought that Gdi+ handles are different from Gdi handles, but it seems they aren't. Good to know indeed.

Title: Re: gdiplus tests
Post by: zedd151 on March 16, 2025, 12:17:56 AM
Quote from: jj2007 on March 15, 2025, 07:32:37 PM
Quote from: NoCforMe on March 15, 2025, 07:40:41 AMGood to know you can mix & match stuff here.
I've always thought that Gdi+ handles are different from Gdi handles, but it seems they aren't. Good to know indeed.
So did a lot of members. There is not a lot of info about that on the forum. Most example code uses either plain gdi or uses gdiplus.
I just tried it as an experiment. Voila! It worked.  :azn:

Title: Re: gdiplus tests
Post by: zedd151 on March 16, 2025, 12:31:07 AM
Quote from: jj2007 on March 15, 2025, 07:32:37 PM"\Masm32\examples\exampl04\car\car.jpg", fit  ; uses GdipDrawImageRectI, which stretches the image as desired
I didn't see that anywhere in the import names in olly for the 'car' example in the Masm32 SDK, I looked:
Names in car
Address    Section    Type    (  Name                                    Comment
00402000  .rdata    Import  (  gdi32.CreateCompatibleBitmap
00402004  .rdata    Import  (  gdi32.CreateCompatibleDC
00402008  .rdata    Import  (  gdi32.DeleteDC
0040200C  .rdata    Import  (  gdi32.SelectObject
00402010  .rdata    Import  (  gdi32.BitBlt
00402014  .rdata    Import  (  gdi32.DeleteObject
00402018  .rdata    Import  (  gdi32.GetDeviceCaps
00402020  .rdata    Import  (  kernel32.MulDiv
00402024  .rdata    Import  (  kernel32.SizeofResource
00402028  .rdata    Import  (  kernel32.SetLastError
0040202C  .rdata    Import  (  kernel32.LockResource
00402030  .rdata    Import  (  kernel32.LoadResource
00402034  .rdata    Import  (  kernel32.FindResourceA
00402038  .rdata    Import  (  kernel32.GetModuleHandleA
0040203C  .rdata    Import  (  kernel32.GetCommandLineA
00402040  .rdata    Import  (  kernel32.ExitProcess
00402048  .rdata    Import    ole32.CoTaskMemFree
0040204C  .rdata    Import    ole32.CoTaskMemAlloc
00402050  .rdata    Import    ole32.CreateStreamOnHGlobal
00402054  .rdata    Import    ole32.CoUninitialize
00402058  .rdata    Import    ole32.CoInitialize
00402060  .rdata    Import    oleaut32.OleLoadPicture
00402068  .rdata    Import  (  user32.LoadCursorA
0040206C  .rdata    Import  (  user32.GetSystemMetrics
00402070  .rdata    Import  (  user32.RegisterClassExA
00402074  .rdata    Import  (  user32.LoadIconA
00402078  .rdata    Import  (  user32.GetDC
0040207C  .rdata    Import  (  user32.DefWindowProcA
00402080  .rdata    Import  (  user32.CreateWindowExA
00402084  .rdata    Import  (  user32.BeginPaint
00402088  .rdata    Import  (  user32.UpdateWindow
0040208C  .rdata    Import  (  user32.MessageBoxA
00402090  .rdata    Import  (  user32.DispatchMessageA
00402094  .rdata    Import  (  user32.GetMessageA
00402098  .rdata    Import  (  user32.PostQuitMessage
0040209C  .rdata    Import  (  user32.EndPaint
004020A0  .rdata    Import  (  user32.ShowWindow
004020A4  .rdata    Import  (  user32.TranslateMessage
Nor any other gdiplus functions, unless OleLoadPicture does it internally.
That is one of the first examples I had looked at when looking for code to load images other than bitmaps. Seemed like a rather clunky way to load a jpg file, imo.
Title: Re: gdiplus tests
Post by: NoCforMe on March 16, 2025, 07:46:38 AM
OK; so now we come to the matter of image quality. Does GDI or GDI+ yield the better image quality? Especially if the image is stretched?

I know that some rendering techniques result in really crappy images, but I can't remember exactly which ones those were.
Title: Re: gdiplus tests
Post by: zedd151 on March 16, 2025, 08:19:31 AM
I have noticed that shrinking a large image with StretchBlt results in crappy quality for some images. There would be black lines at some intervals upon resizing the window smaller (using the size borders). Ill run some tests with screenshots when I get the chance.

I would like to think that gdiplus functions would yield better results, being more modern than the legacy gdi functions. Testing that will also come at some later time.

Here is a quick one using StretchBlt. Original image size 1024x768
shrunk dynamically using the sizing border. (window edge)  Not black lines for this image, but... looks like crap.
(https://i.postimg.cc/fT87cSTv/untitled.png)
original zipped and attached
Title: Re: gdiplus tests
Post by: NoCforMe on March 16, 2025, 08:51:28 AM
Can you maybe do some side-by-side comparisons? like GDI in one window and GDI+ in the other?
Title: Re: gdiplus tests
Post by: zedd151 on March 16, 2025, 08:55:51 AM
Quote from: NoCforMe on March 16, 2025, 08:51:28 AMCan you maybe do some side-by-side comparisons? like GDI in one window and GDI+ in the other?
Yes, but that will take a little time to get the gdiplus code 'just right'. Time that I don't have today. Maybe in a couple days. Remind me if I don't post something here by Monday or Tuesday regarding quality in gdiplus. I forget a lot of things here lately.
Title: Re: gdiplus tests
Post by: zedd151 on March 21, 2025, 04:00:47 AM
Quote from: sinsi on March 14, 2025, 04:48:14 AMMight try a bigger GIF with more frames next.
I played around with your program today, sinsi.
The gif I used here is not Transparent, I just wanted to see how well it displayed.

Is there any way to correlate the delay per frame in the code, to what the frame delay is in the gif file rather than a 'one size fits all' timer delay?
What I mean is, is there any way to get the information from the gif file, for the delay for each frame? As you might have noticed, I have only a slight clue about gdiplus functions. The MS documentation isn't a great help, either.

Screenshot of program
(https://i.postimg.cc/8kHVJvfz/untitled.png)

Original gif file... I had made this years ago, for use as an avatar on another forum.
(https://i.postimg.cc/Yq9Tvswd/pacman-final.gif)
Title: Re: gdiplus tests
Post by: daydreamer on March 21, 2025, 06:48:50 AM
Is it possible make old moonlander game,but with rotating a image of moonlander,instead of original vectorgraohics ?
Old atari game from 1970"s running on 6502 1.8 mhz
Title: Re: gdiplus tests
Post by: zedd151 on March 21, 2025, 07:06:52 AM
Quote from: daydreamer on March 21, 2025, 06:48:50 AMIs it possible make old moonlander game,but with rotating a image of moonlander,instead of original vectorgraohics ?
If you can get screenshots, sure. Maybe using DosBox or similar?
1. Just make all of the graphics elements into seperate bitmaps {taken from screenshot(s)}
2. Using mspaint or other similar tool to create each frame using the graphics elements created in step 1, incuding the background.
3. Use ImageReady, Gimp or similar program to create the animated .gif file from the indidual bitmaps (created in step 2) that represent the animation frames. There are undoubtedly other tools out now, that can do similar tasks. Even possibly do all of these within the same program.

Similar steps were used in creating the pacman gif file above.
Title: Re: gdiplus tests
Post by: sinsi on March 21, 2025, 07:15:06 AM
Quote from: zedd151 on March 21, 2025, 04:00:47 AMIs there any way to correlate the delay per frame in the code, to what the frame delay is in the gif file rather than a 'one size fits all' timer delay?
What I mean is, is there any way to get the information from the gif file, for the delay for each frame? As you might have noticed, I have only a slight clue about gdiplus functions. The MS documentation isn't a great help, either.

I started to look into it but lost interest...

    invoke  GdipGetPropertyItemSize,GpImage,PropertyTagFrameDelay,addr delaysize
    invoke  GdipGetPropertyItem,GpImage,PropertyTagFrameDelay,delaysize,addr delay

PropertyTagFrameDelay (https://learn.microsoft.com/en-us/windows/win32/gdiplus/-gdiplus-constant-property-item-descriptions#propertytagframedelay) has more information, among other interesting stuff :biggrin:
Title: Re: gdiplus tests
Post by: zedd151 on March 21, 2025, 07:16:02 AM
Quote from: sinsi on March 21, 2025, 07:15:06 AMI started to look into it but lost interest...
    invoke  GdipGetPropertyItemSize,GpImage,PropertyTagFrameDelay,addr delaysize
    invoke  GdipGetPropertyItem,GpImage,PropertyTagFrameDelay,delaysize,addr delay

Thanks sinsi, I'll look into that... eventually.  :smiley:
It's not an urgent need, but it might be useful in the future.
Title: Re: gdiplus tests
Post by: jj2007 on March 21, 2025, 09:02:59 AM
Quote from: sinsi on March 21, 2025, 07:15:06 AMPropertyTagFrameDelay (https://learn.microsoft.com/en-us/windows/win32/gdiplus/-gdiplus-constant-property-item-descriptions#propertytagframedelay) has more information, among other interesting stuff :biggrin:

Looks vaguely familiar (https://www.jj2007.eu/MasmBasicQuickReference.htm#Mb1407) :cool:
(https://i.postimg.cc/0bmNWgCb/Gdip-Get-Property-Item-Size.png) (https://postimg.cc/0bmNWgCb)
Title: Re: gdiplus tests
Post by: daydreamer on March 21, 2025, 07:05:38 PM
Quote from: zedd151 on March 21, 2025, 07:06:52 AM
Quote from: daydreamer on March 21, 2025, 06:48:50 AMIs it possible make old moonlander game,but with rotating a image of moonlander,instead of original vectorgraohics ?
1. Just make all of the graphics elements into seperate bitmaps {taken from screenshot(s)}
https://nasa3d.arc.nasa.gov/search/lunar (https://nasa3d.arc.nasa.gov/search/lunar)
I have several 3d programs,so i can make old 3d pre-rendered graphics from 3d models, like baldurs gate
If you look thru 3d models, background could be made from one of landing sites

Title: Re: gdiplus tests
Post by: zedd151 on March 21, 2025, 07:37:32 PM
If it is your own programs daydreamer (that you have the source code for), the simplest way for you would be to output .bmp files at certain intervals rather than the method I mentioned earlier. Then work with those .bmp files to compile your gif animation from.

That would effectively remove at least some of the work to be done manually.
Keep in mind that even compressed (optimized) .gif animations can get large (in file size) very fast.
Generally the frame rate should be between 10-15 frames per second. Along with any optimizations, this should help keep the file size down to an acceptable level.

Huge (in pixel dimensions) .gif animations tend to take much longer to display, and use up much more memory when doing so. (I have at some point, tested using full screen sized .gif animations; 640x480, 800x600, etc.)

The results are much slower animations regardless of desired frame rate. At least that has been my experience in the past. (Almost 20 years ago)

Have fun!  :biggrin:

Later:
With today's faster processors and computers with tons of memory, results these days might be better, as far as using and displaying .gif animations with large dimensions and file sizes.