News:

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

Main Menu

Re: JpgTool application

Started by six_L, June 02, 2020, 03:13:04 AM

Previous topic - Next topic

six_L

thanks Hutch!
a bit problem is that temporary file of  @@@@.@@@ were left on the hard disk at sometimes.   
ResImageLoad proc ResID:QWORD

    LOCAL hRes  :QWORD
    LOCAL pRes  :QWORD
    LOCAL lRes  :QWORD
    LOCAL pbmp  :QWORD
    LOCAL hBmp  :QWORD
    LOCAL npng  :QWORD

    mov hRes, rv(FindResource,0,ResID,RT_RCDATA)        ; find the resource
    mov pRes, rv(LoadResource,0,hRes)                   ; load the resource
    mov lRes, rv(SizeofResource,0,hRes)                 ; get its size
    mrm npng, "@@@@.@@@"                                ; temp file name

    invoke save_file,npng,pRes,lRes                     ; create the temp file

    invoke GdipCreateBitmapFromFile,L(npng),ADDR pbmp   ; create a GDI+ bitmap
    invoke GdipCreateHBITMAPFromBitmap,pbmp,ADDR hBmp,0 ; create normal bitmap handle from it
    invoke GdipDisposeImage,pbmp                        ; remove the GDI+ bitmap

    invoke DeleteFile,npng                              ; delete the temp file

    mov rax, hBmp                                       ; return the bitmap handle in RAX

    ret

ResImageLoad endp

Say you, Say me, Say the codes together for ever.

hutch--

>     invoke DeleteFile,npng                              ; delete the temp file

You would need to make sure that the resource you load is valid or you may feed the wrong info to the procedure. None the less even if you have managed to crash it with the wrong data, a simple text file is easy enough to fix, just delete it. Be aware that RC.EXE will leave junk behind if you feed it the wrong info as well.

TimoVJL

There is a GdipCreateBitmapFromResource() function for that purpose ?
May the source be with you

hutch--


six_L

the following code by Vortex can load bitmap from res. but jpg can't. so the created exefile is large.
CreateBmpFromMem PROC USES RSI RDI hWnd:QWORD,pBmp:QWORD
LOCAL hDC:QWORD

invoke  GetDC,hWnd
test    rax,rax
jz      @f
mov     hDC,rax
mov     rsi,pBmp
lea     rdi,[rsi + SIZEOF BITMAPFILEHEADER]  ; start of the BITMAPINFOHEADER header
xor rax,rax
mov     eax,BITMAPFILEHEADER.bfOffBits[rsi]
add     rsi,rax
invoke  CreateDIBitmap,hDC,rdi,CBM_INIT,rsi,rdi,DIB_RGB_COLORS
push rax
invoke  ReleaseDC,hWnd,hDC
pop rax
@@:
ret

CreateBmpFromMem ENDP

ResImageLoad proc ResID:QWORD
LOCAL hRes:QWORD
LOCAL pRes:QWORD
LOCAL lRes:QWORD
LOCAL hBitmap:QWORD

invoke FindResource,0,ResID,RT_RCDATA
mov hRes, rax
invoke LoadResource,0,hRes
mov pRes, rax ; load the resource
invoke SizeofResource,0,hRes
mov lRes, rax ; get its size
invoke CreateBmpFromMem,hWinMain,pRes
        mov     hBitmap,rax
invoke GdipCreateBitmapFromHBITMAP,hBitmap,0,addr pImg
invoke CloseHandle,hBitmap
mov rax, pImg                                       ; return the image handle in RAX

ret

ResImageLoad endp
Say you, Say me, Say the codes together for ever.

hutch--

You can use LoadImage() to load a BMP file, you don't need GDI+.

With Timo's suggestion, the function in 64 bit does not seem to work. Any variation in labelling the resource does not change the error message. The version I use has been super reliable since I originally wrote it, that is why I use it and it will load most formats, JPG BMP TIF PNG and GIF and while its the wrong function it will load an icon as well.

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

GetResImg proc ResID:QWORD

    LOCAL lbmp  :QWORD

    invoke GdipCreateBitmapFromResource,hInstance,ResID,ptr$(lbmp)

    invoke MessageBox,hWnd,LastError$(),"LastError$",MB_ICONINFORMATION

    mov rax, lbmp

    ret

GetResImg endp

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

TimoVJL

In C, GdipCreateBitmapFromStream()#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <shlwapi.h>

#pragma comment(lib, "gdiplus.lib")
#pragma comment(lib, "shlwapi.lib")
...
HBITMAP BitmapFromResource(HMODULE hMod, LPCTSTR ResID)
{
HBITMAP hBitmap = NULL;
HRSRC hRSrc = FindResource(hMod, ResID, RT_RCDATA);
if (!hRSrc) return 0;
DWORD nSize = SizeofResource(hMod, hRSrc);
HGLOBAL hResData = LoadResource(hMod, hRSrc);
PVOID pResData = LockResource(hResData);
IStream* pStream = NULL;
pStream = SHCreateMemStream(pResData, nSize);
FreeResource(hResData);
GpBitmap *gpBitmap;
int rc = GdipCreateBitmapFromStream(pStream, &gpBitmap);
pStream->lpVtbl->Release(pStream);
if (!rc) {
rc = GdipCreateHBITMAPFromBitmap(gpBitmap, &hBitmap, 0);
GdipDisposeImage(gpBitmap);
return hBitmap;
}
return 0;
}
May the source be with you

hutch--

Looks good but its a different set of functions, it does not include "GdipCreateBitmapFromResource".

six_L

#8
hi,TimoVJL
thanks you for the SHCreateMemStream(pResData, nSize)
_PSHCreateMemStream typedef PROTO :QWORD,:QWORD
PSHCreateMemStream  typedef ptr _PSHCreateMemStream

.data?

hShlwapi_dll dq ?
lPSHCreateMemStream PSHCreateMemStream ?

_GdipCreateImageFromResource proc ResID:QWORD
LOCAL hRes:QWORD
LOCAL pRes:QWORD
LOCAL lRes:QWORD
LOCAL @IStream:QWORD

invoke FindResource,0,ResID,RT_RCDATA
mov hRes, rax
invoke LoadResource,0,hRes
mov pRes, rax ; load the resource
invoke SizeofResource,0,hRes ; get its size
mov lRes, rax

invoke lPSHCreateMemStream,pRes,lRes
mov @IStream,rax
invoke FreeResource,hRes
invoke GdipLoadImageFromStream,@IStream,addr pImg
mov rax, pImg                                       ; return the IMAGE handle in RAX

ret

_GdipCreateImageFromResource endp

invoke LoadLibrary,CStr("Shlwapi.dll")
.if eax
mov hShlwapi_dll,rax
invoke GetProcAddress,hShlwapi_dll,CStr("SHCreateMemStream")
mov lPSHCreateMemStream,rax
.else
invoke MessageBox,NULL,CStr("Shlwapi.dll load Failed"),CStr("LoadLibrary"),MB_OK
.endif

invoke _GdipCreateImageFromResource,IDC_IMGID
mov _GpImage,rax
Say you, Say me, Say the codes together for ever.

hutch--

Hi timo,

I got this to work from the C++ code you posted. About the only thing I could not convert was the line,

    pStream->lpVtbl->Release(pStream);

I could not find a construction in the shlwapi or anywhere else that would do this.

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

LoadResImage proc ResID:QWORD

    LOCAL MemStream :QWORD
    LOCAL pBMP      :QWORD
    LOCAL hBMP      :QWORD
    LOCAL hRsc      :QWORD
    LOCAL rSiz      :QWORD
    LOCAL rDat      :QWORD
    LOCAL strm      :QWORD

    mov MemStream, rvcall(GetProcAddress,rvcall(GetModuleHandle,"shlwapi.dll"),"SHCreateMemStream")

    mov hRsc, rvcall(FindResource,0,ResID,RT_RCDATA)        ; find the resource
    mov rSiz, rvcall(SizeofResource,0,hRsc)                 ; get its size
    mov rDat, rvcall(LoadResource,0,hRsc)                   ; load the resource

    mov strm, rvcall(MemStream,rDat,rSiz)                   ; create the memory stream

    rcall GdipCreateBitmapFromStream,strm,ptr$(pBMP)        ; create a GDI+ bitmap
    rcall GdipCreateHBITMAPFromBitmap,pBMP,ptr$(hBMP),0     ; convert it to a Windows bitmap
    rcall GdipDisposeImage,pBMP                             ; delete the GDI+ bitmap

    mov rax, hBMP                                           ; return the bitmap handle

    ret

LoadResImage endp

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

Vortex

Hi Hutch,

pStream->lpVtbl->Release(pStream);

The code to release streams :

ReleasePict:

    mov     rcx,pPicture
    mov     rax,QWORD PTR [rcx]
    call    IPicture.Release[rax]

ReleaseStream:

    mov     rcx,pStream
    mov     rax,QWORD PTR [rcx]
    call    IStream.Unknown.Release[rax]


Attached is my library loading various image formats from memory and file. It's converted to Masm 64-bit.

Vortex

Hello,

Here is a GdipCreateBitmapFromResource sample.

   .ifeq edx,WM_CREATE

        mov     rax,OFFSET StartupInfo
        mov     GdiplusStartupInput.GdiplusVersion[rax],1

        invoke  GdiplusStartup,ADDR token,ADDR StartupInfo,0
     
        invoke  GdipCreateBitmapFromResource,hInstance,1000,\
                ADDR BmpImage

        invoke  GdipCreateHBITMAPFromBitmap,BmpImage,\
                ADDR hBitmap,0

        invoke  GdipDisposeImage,BmpImage

hutch--

Thanks Erol, these will be very useful.

hutch--

Erol,

A question, have you used any different library for any of the GDI+ functions ?

I can run your example and it builds fine and works correctly but when I paste your code into a test piece I am using, I get an error message that "GdipCreateBitmapFromResource" can't find the resource.


LoadResImage proc ResID:QWORD

    LOCAL hMemDC   :QWORD
    LOCAL BmpImage :QWORD

    invoke  GdipCreateBitmapFromResource,hInstance,ResID,ADDR BmpImage

    ; rcall MessageBox,hWnd,LastError$(),"LastError$",MB_ICONINFORMATION

    invoke  GdipCreateHBITMAPFromBitmap,BmpImage,ADDR hBmp,0

    invoke  GdipDisposeImage,BmpImage

    mov rax, hBmp

    ret

LoadResImage endp


I moved the init and shutdown to the start of the test piece and replaced the ones I normally use but it did not change anything.


  .data?
    hBmp        dq ?
    stui GdiplusStartupInput <?>
    token       dq ?
  .code
    ........

    mov     rax,OFFSET stui
    mov     GdiplusStartupInput.GdiplusVersion[rax],1
    invoke  GdiplusStartup,ADDR token,ADDR stui,0
    ........

    invoke GdiplusShutdown,token





TimoVJL

Quote from: hutch-- on June 03, 2020, 01:38:31 AM
Hi timo,

I got this to work from the C++ code you posted. About the only thing I could not convert was the line,

    pStream->lpVtbl->Release(pStream);

I could not find a construction in the shlwapi or anywhere else that would do this.


It was just C, not C++, in C++ it's pStream.Release();

mov rax,pStream
mov rax, [rax]
call [rax+10h]
as Release offset is 0+8+8 = 16typedef struct IUnknownVtbl {
    BEGIN_INTERFACE
    HRESULT (STDMETHODCALLTYPE *QueryInterface)(IUnknown*,REFIID,void**);
    ULONG (STDMETHODCALLTYPE *AddRef)(IUnknown*);
    ULONG (STDMETHODCALLTYPE *Release)(IUnknown*);
    END_INTERFACE
} IUnknownVtbl;

interface IUnknown {
    CONST_VTBL struct IUnknownVtbl *lpVtbl;
};
May the source be with you