Author Topic: Bare Minimum GDIplus code to save different Image Types.  (Read 13942 times)

nidud

  • Member
  • *****
  • Posts: 2388
    • https://github.com/nidud/asmc
Re: Bare Minimum GDIplus code to save different Image Types.
« Reply #15 on: April 25, 2020, 02:41:19 AM »
deleted
« Last Edit: February 26, 2022, 03:41:50 AM by nidud »

Siekmanski

  • Member
  • *****
  • Posts: 2593
Re: Bare Minimum GDIplus code to save different Image Types.
« Reply #16 on: April 25, 2020, 03:51:57 AM »
I think the JPG quality encoder parameters for 64 bit are organized in an other way as in 32 bit code?
Creative coders use backward thinking techniques as a strategy.

nidud

  • Member
  • *****
  • Posts: 2388
    • https://github.com/nidud/asmc
Re: Bare Minimum GDIplus code to save different Image Types.
« Reply #17 on: April 25, 2020, 06:23:08 AM »
deleted
« Last Edit: February 26, 2022, 03:42:01 AM by nidud »

Siekmanski

  • Member
  • *****
  • Posts: 2593
Re: Bare Minimum GDIplus code to save different Image Types.
« Reply #18 on: April 25, 2020, 07:37:38 PM »
This is my first work in 64 bit coding.  :biggrin:
Did the same direct approach as in my 32 bit GdiPlus examples but it failed.
Don't know if the EncoderParameters object is different in 64 bit.
I'm not sure if I did the addressing of the pointer to the JpgQualityLevel parameter value correctly....

   mov   JpgQualityLevel,10
   lea   eax,JpgQualityLevel
   mov   Qptr,eax      

It saves a jpg file but the Encoder Quality has no effect.
Tried all kind of alignments for the EncoderParameters object.

@nidud
Could you make a memory dump of the ( filled ) EncoderParameters object of your working example?
So I can compare the values and alignments.
Creative coders use backward thinking techniques as a strategy.

nidud

  • Member
  • *****
  • Posts: 2388
    • https://github.com/nidud/asmc
Re: Bare Minimum GDIplus code to save different Image Types.
« Reply #19 on: April 25, 2020, 08:13:29 PM »
deleted
« Last Edit: February 26, 2022, 03:42:12 AM by nidud »

hutch--

  • Administrator
  • Member
  • ******
  • Posts: 10026
  • Mnemonic Driven API Grinder
    • The MASM32 SDK
Re: Bare Minimum GDIplus code to save different Image Types.
« Reply #20 on: April 25, 2020, 08:28:17 PM »
I tried a whole collection of variations on the JPG code in 64 bit but could not get the extra parameters to work. This is the library format that I got to work but no extra parameters for the last argument,

    invoke GdipSaveImageToFile,hGdip,L(filename),pCLSID,NULL

Algo

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

SaveAsJPGx proc bmHandle:QWORD,filename:QWORD

    LOCAL hGdip  :QWORD
    LOCAL pCLSID :QWORD

  .data
    CLSID_ImageType1 GUID <0557CF401h,01A04h,011D3h,<09Ah,073h,000h,000h,0F8h,01Eh,0F3h,02Eh>>
  .code

    mov pCLSID, ptr$(CLSID_ImageType1)

    invoke GdipCreateBitmapFromHBITMAP,bmHandle,0,ptr$(hGdip)
    invoke GdipSaveImageToFile,hGdip,L(filename),pCLSID,NULL
    invoke GdipDisposeImage,hGdip

    ret

SaveAsJPGx endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
hutch at movsd dot com
http://www.masm32.com    :biggrin:  :skrewy:

Siekmanski

  • Member
  • *****
  • Posts: 2593
Re: Bare Minimum GDIplus code to save different Image Types.
« Reply #21 on: April 25, 2020, 09:20:03 PM »
nidud, thank you very much for the list dump.  :thumbsup:
It made things clear to me and now I did succeed to do the direct approach in 64 bit as well.

@Hutch, problem solved.  :biggrin:

EDIT: source code update

Code: [Select]
    include \masm32\include64\masm64rt.inc

.data?
pImage                  dq ?
JpgQualityLevel         dd ?
FilenameW               dw  MAX_PATH dup (?)

.data
CLSID_ImageType         GUID <0557CF401h,01A04h,011D3h,<09Ah,073h,000h,000h,0F8h,01Eh,0F3h,02Eh>> ; JPG image type
JPG_EncoderParameters   dq 1    ; Number of parameters in this structure
CLSID_EncoderQuality    GUID <01d5be4b5h,0fa4ah,0452dh,<09ch,0ddh,05dh,0b3h,051h,005h,0e7h,0ebh>>
                        dd 1    ; Number of the parameter values
                        dd 4    ; ValueTypeLong
                        dq offset JpgQualityLevel

szWomanImage            db "Woman.bmp",0
szWoman                 db "Woman.jpg",0
   
.code
entry_point proc

    conout lf,"  64bit GDIplus Jpg Quality Encoder",lf,lf

    GdiPlusBegin                    ; initialise GDIPlus

    invoke  MultiByteToWideChar,CP_ACP,0,addr szWomanImage,-1,addr FilenameW,MAX_PATH-1
    invoke  GdipCreateBitmapFromFile,addr FilenameW,addr pImage
    test    rax,rax
    jnz     Done
   
    mov     JpgQualityLevel,50      ; 0 to 100

    invoke  MultiByteToWideChar,CP_ACP,0,addr szWoman,-1,addr FilenameW,MAX_PATH-1
    invoke  GdipSaveImageToFile,pImage,addr FilenameW,addr CLSID_ImageType,addr JPG_EncoderParameters

    invoke  GdipDisposeImage,pImage
Done:

    waitkey "  Press any key to continue ..."

    GdiPlusEnd                      ; GdiPlus cleanup

    invoke  ExitProcess,0
    ret

entry_point endp

end
Creative coders use backward thinking techniques as a strategy.

hutch--

  • Administrator
  • Member
  • ******
  • Posts: 10026
  • Mnemonic Driven API Grinder
    • The MASM32 SDK
Re: Bare Minimum GDIplus code to save different Image Types.
« Reply #22 on: April 25, 2020, 09:55:59 PM »
Great, it works well, I have tested it from 10% to 75% and the results are perfect.
hutch at movsd dot com
http://www.masm32.com    :biggrin:  :skrewy:

hutch--

  • Administrator
  • Member
  • ******
  • Posts: 10026
  • Mnemonic Driven API Grinder
    • The MASM32 SDK
Re: Bare Minimum GDIplus code to save different Image Types.
« Reply #23 on: April 25, 2020, 11:54:55 PM »
Made the code into module format, works fine.

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

SaveImgAsJpg proc BmpHndl:QWORD,filename:QWORD,quality:QWORD

    LOCAL pImage :QWORD

  ; ------------------------------------------------------------------------

  .data?
    QualityLevel@@@@@@@@   dd ?    ; mangle to avoid accidental duplicates

  .data
    CLSID_ImageType1 GUID <0557CF401h,01A04h,011D3h,<09Ah,073h,000h, \
                           000h,0F8h,01Eh,0F3h,02Eh>> ; JPG image type

    JPG_EncoderParameters  dd 1    ; Number of parameters in this structure
                           dd 0    ; alignment !
    CLSID_EncoderQuality   GUID <01d5be4b5h,0fa4ah,0452dh,<09ch,0ddh, \
                                 05dh,0b3h,051h,005h,0e7h,0ebh>>
                           dd 1    ; Number of the parameter values
                           dd 4    ; ValueTypeLong
    JpgQualityParameterPTR dq offset QualityLevel@@@@@@@@

  .code

  ; ------------------------------------------------------------------------

    cmp quality, 100
    ja default
    jmp next

  default:
    mov quality, 75                                             ; default for quality error

  next:
    rcall GdipCreateBitmapFromHBITMAP,BmpHndl,0,ptr$(pImage)    ; convert BMP handle
    mov rax, quality                                            ; set the quality level
    mov QualityLevel@@@@@@@@, eax                               ; 100 = highest, 0 = lowest
    invoke GdipSaveImageToFile,pImage,L(filename), \
           ADDR CLSID_ImageType1,ADDR JPG_EncoderParameters     ; write JPG image to file
    rcall GdipDisposeImage,pImage                               ; delete GDIP handle

    ret

SaveImgAsJpg endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤


I should mangle all of the names to ensure no accidents.
hutch at movsd dot com
http://www.masm32.com    :biggrin:  :skrewy:

Siekmanski

  • Member
  • *****
  • Posts: 2593
Re: Bare Minimum GDIplus code to save different Image Types.
« Reply #24 on: April 26, 2020, 12:32:17 AM »
Cool.  :cool:

Finally started exploring 64bit coding.
Working my way thru MACROS and addressing modes, still have a lot to learn...

Made my first Routine in 64bit.

Code: [Select]
    include \masm32\include64\masm64rt.inc

.const
Image_BMP       equ 0
Image_JPG       equ 1
Image_GIF       equ 2
Image_TIF       equ 5
Image_PNG       equ 6

.data?
pImage                  dq ?
pImageTemp              dq ?
JpgQualityLevel         dd ?

.data
CLSID_ImageTypes        GUID <0557CF400h,01A04h,011D3h,<09Ah,073h,000h,000h,0F8h,01Eh,0F3h,02Eh>> ; For all image types
JPG_EncoderParameters   dq 1    ; Number of parameters in this structure
CLSID_EncoderQuality    GUID <01d5be4b5h,0fa4ah,0452dh,<09ch,0ddh,05dh,0b3h,051h,005h,0e7h,0ebh>>
                        dd 1    ; Number of the parameter values
                        dd 4    ; ValueTypeLong
                        dq offset JpgQualityLevel
.code

SaveJpgQualityImage proc pGdiPlusImage:QWORD,pFilename:QWORD,Image_Quality:DWORD

    invoke  GdipCloneImage,pGdiPlusImage,addr pImageTemp ; make a copy of the image to work with.

    mov     eax,Image_Quality
    mov     JpgQualityLevel,eax
    mov     byte ptr [CLSID_ImageTypes],Image_JPG
   
    invoke  GdipSaveImageToFile,pImageTemp,L(pFilename),addr CLSID_ImageTypes,addr JPG_EncoderParameters
    invoke  GdipDisposeImage,pImageTemp
    ret
SaveJpgQualityImage endp
   
entry_point proc

    conout lf,"  64bit GDIplus Jpg Quality Encoder",lf,lf

    GdiPlusBegin                    ; initialise GDIPlus

; Load a test Image
    invoke  GdipCreateBitmapFromFile,L("Woman.bmp"),addr pImage
    test    rax,rax
    jnz     Done

    invoke  SaveJpgQualityImage,pImage,"Woman.jpg",50

    invoke  GdipDisposeImage,pImage
Done:

    waitkey "  Press any key to continue ..."

    GdiPlusEnd                      ; GdiPlus cleanup

    invoke  ExitProcess,0
    ret

entry_point endp

end
Creative coders use backward thinking techniques as a strategy.

hutch--

  • Administrator
  • Member
  • ******
  • Posts: 10026
  • Mnemonic Driven API Grinder
    • The MASM32 SDK
Re: Bare Minimum GDIplus code to save different Image Types.
« Reply #25 on: April 26, 2020, 01:18:04 AM »
Once you get a feel for it, its great stuff, lots more registers, massive amounts of memory and without having to keep making prototypes, you can code very fast with practice.
hutch at movsd dot com
http://www.masm32.com    :biggrin:  :skrewy:

Siekmanski

  • Member
  • *****
  • Posts: 2593
Re: Bare Minimum GDIplus code to save different Image Types.
« Reply #26 on: April 26, 2020, 03:56:24 AM »
@Hutch
Having fun already, prepare for some questions later.  :biggrin:

Bare Minimum 64 bit GDIplus code to save different Image Types, PixelFormat and colorconversions.
Only 1 GUID used for all the Image Types.
Now you can find a balance between Image quality and file size.

You need to replace the old 64bit "gdiplus.lib" with a newer version.
The lib is included in the Lib folder, it's from the Microsoft SDK Windows v7.1A.

Hope I didn't violate the 64 bit coding rules, else let me know......
Creative coders use backward thinking techniques as a strategy.

Vortex

  • Member
  • *****
  • Posts: 2724
Re: Bare Minimum GDIplus code to save different Image Types.
« Reply #27 on: April 26, 2020, 05:40:20 AM »
Hello Siekmanski,

I was able to build your example GDIplus64_color_conversions with Pelle's 64-bit import library. An alternative to SDK Windows v7 :

Code: [Select]
\PellesC\lib\Win64\gdiplus.lib

Siekmanski

  • Member
  • *****
  • Posts: 2593
Re: Bare Minimum GDIplus code to save different Image Types.
« Reply #28 on: April 26, 2020, 06:20:21 AM »
Nice that it works.
Still have to find my way in 64 bit coding, maybe the code can be improved?
Creative coders use backward thinking techniques as a strategy.

jj2007

  • Member
  • *****
  • Posts: 13335
  • Assembly is fun ;-)
    • MasmBasic
Re: Bare Minimum GDIplus code to save different Image Types.
« Reply #29 on: April 29, 2020, 07:07:49 AM »
A little bit off topic: I am trying (successfully) to implement...

GdipDrawImageRectRectI(*graphics, GpImage *image, INT dstx, INT dsty, INT dstwidth, INT dstheight, INT srcx, INT srcy, INT srcwidth, INT srcheight, GpUnit srcUnit, GpImageAttributes* imageAttributes, DrawImageAbort callback, VOID * callbackData)

... to zoom into a picture. It works fine. Then I want to save the image using GdipSaveImageToFile

GdipSaveImageToFile(GpImage *image, WCHAR* filename, CLSID* clsidEncoder, EncoderParameters* encoderParams)

That works fine, too, but it saves the original image, not the zoomed one. Does Draw write to the bitmap/the image?

My understanding was that graphics is the equivalent of a DC in "normal" GDI, while image is the bitmap. Since GdipSaveImageToFile saves the bitmap, I expected to see the zoomed version. What's wrong with my logic? And how could I get access to the zoomed (or otherwise modified) image?

Unfortunately, the documentation is lousy :cool: