I want to convert JPG file to BMP using OLE. I wrote the following code, but the SaveAsFile method doesn't work. What I do wrong? Are there other methods to do this?
BTW: This is my first post to win32asm community messageboard!
BTW: This is my first post to win32asm community messageboard!
.data
IID_IPicture dd 07BF80980h
dw 0BF32h,0101Ah
db 08Bh,0BBh,0,0AAh,0,030h,0Ch,0ABh
gpPicture dd 0
pstm dd ?
pstm2 dd ?
FILESIZE = 30474 ;size of jpeg file
gfx_title LABEL DWORD
include gfx_title4.inc ;jpeg file (db ..., db ..., db ..., ...)
;jpg converted to include file using BinToDb
pcbSize dd ?
.code
start:
invoke GlobalAlloc,GMEM_FIXED,FILESIZE
mov ecx,FILESIZE
mov esi,offset gfx_title
mov edi,eax
rep movsb
invoke CreateStreamOnHGlobal,eax,TRUE,addr pstm
invoke OleLoadPicture,pstm,FILESIZE,1,addr IID_IPicture,addr gpPicture
invoke GlobalAlloc,GMEM_FIXED,250000
invoke CreateStreamOnHGlobal,eax,TRUE,addr pstm2
push offset pcbSize
push 0
push dword ptr [pstm2]
mov edx,gpPicture
push edx
mov edx,[edx]
call dword ptr [edx+60] ;IPicture::SaveAsFile
;this doesn't work - returns E_FAIL
mov eax,gpPicture ;return number of bytes
invoke ExitProcess,eax
end start
With out really studying up you problem, are you sure that the method you want is the 60th DECIMAL offset, or the 60th HEX offset ;) . If there is confusion here it will for sure fail.
:alright:
NaN
:alright:
NaN
I am almost sure. I think this is the right offset because when I change 1 to 0 in the following line, everything works (but the program writes JPG instead of BMP):
invoke OleLoadPicture,pstm,FILESIZE,1,addr IID_IPicture,addr gpPicture
invoke OleLoadPicture,pstm,FILESIZE,1,addr IID_IPicture,addr gpPicture
IPicture::SaveAsFile
Saves the picture?s data into a stream in the same format that it would save itself into a file. Bitmaps use the BMP file format, metafiles the WMF format, and icons the ICO format. For more information, see the Win32 Programmer?s Reference.
HRESULT SaveAsFile( IStream * pstream ,
//Pointer to stream where picture writes its data
BOOL fSaveMemCopy ,
//Indicates whether to save the picture in memory
LONG* pcbSize
//Receives a pointer to the number of bytes written to stream
);
Parameters
pstream
Pointer to the stream into which the picture writes its data.
fSaveMemCopy
Flag indicating whether or not to save a copy of the picture in memory.
pcbSize
Pointer to the caller?s LONG variable to receive the number of bytes written into the stream. This value can be NULL, indicating that the caller does not require this information.
Return Values
This method supports the standard return values E_FAIL and E_INVALIDARG, as well as the following:
S_OK
The picture was saved successfully.
Saves the picture?s data into a stream in the same format that it would save itself into a file. Bitmaps use the BMP file format, metafiles the WMF format, and icons the ICO format. For more information, see the Win32 Programmer?s Reference.
HRESULT SaveAsFile( IStream * pstream ,
//Pointer to stream where picture writes its data
BOOL fSaveMemCopy ,
//Indicates whether to save the picture in memory
LONG* pcbSize
//Receives a pointer to the number of bytes written to stream
);
Parameters
pstream
Pointer to the stream into which the picture writes its data.
fSaveMemCopy
Flag indicating whether or not to save a copy of the picture in memory.
pcbSize
Pointer to the caller?s LONG variable to receive the number of bytes written into the stream. This value can be NULL, indicating that the caller does not require this information.
Return Values
This method supports the standard return values E_FAIL and E_INVALIDARG, as well as the following:
S_OK
The picture was saved successfully.
I gave your problem another 5 minutes or so to look it over (sorry, dont much time to myself these days). The above lists a flag to indicate if the stream is in memory or not. Your telling it that its not, however, your stream pointer is defined out of memory. This maybe where its failing.
I am almost sure. I think this is the right offset because when I change 1 to 0 in the following line, everything works (but the program writes JPG instead of BMP):
invoke OleLoadPicture,pstm,FILESIZE,1,addr IID_IPicture,addr gpPicture
invoke OleLoadPicture,pstm,FILESIZE,1,addr IID_IPicture,addr gpPicture
This is because 0 implies the picture object has its property set to keep the origional file format in the stream, when the bool value is FALSE. You definitely want it to be TRUE to do any conversions. (However the docs' i have also say that the provided stream must only be either a BMP, WMF, or ICO stream. No mention of JPG's at all (which is odd) ).
A little more digging around and i found this link (dated 2003): PICTTYPE
I suspect your screwed. There is not clear support for JPG types. For the OleLoadPicture or OleCreatePictureIndirect. The fact we have been using this to display JPG's seems to be a "patch" to the OS, somewhere down the line and not documented. My suspisions for this is probably because of rights to create JPG's. MS wants to display them from an OS point of view, but doesnt want to get into the legal BS, if someone like yourself wants to create JPG's with the OS's API.
:rolleyes:
Time to hit the web and write your engin, i guess.
:NaN:
I found another way to do this. Here is my little program. It creates a file, which contains decompressed JPEG (the generated raw file could be read eg. by Paint Shop Pro). Do you have any comments or suggestions how to optimize this code?
.data
gfx_title LABEL DWORD
include gfx_title4.inc ;jpeg file (db ..., db ..., db ..., ...)
;jpg converted to include file using BinToDb
bitmap BITMAP <?>
naz db "d.raw",0
dupa dd ?
IID_IPicture dd 07BF80980h
dw 0BF32h,0101Ah
db 08Bh,0BBh,0,0AAh,0,030h,0Ch,0ABh
.code
_Mapping2BMP proc uses esi jpeg_data:DWORD,sizeof_jpeg_data:DWORD,bitmap_struc:DWORD
LOCAL gdi_handle:DWORD
LOCAL pstm:DWORD
LOCAL gpPicture:DWORD
invoke GlobalAlloc,GMEM_FIXED,sizeof_jpeg_data
mov ecx,sizeof_jpeg_data
mov esi,jpeg_data
mov edi,eax
rep movsb
lea ecx,pstm
push ecx
push TRUE
push eax
call CreateStreamOnHGlobal
invoke OleLoadPicture,pstm,sizeof_jpeg_data,TRUE,offset IID_IPicture,addr gpPicture
mov eax,pstm
push eax
mov eax,[eax]
call dword ptr [eax+8] ;pstm->Release()
lea eax,gdi_handle
push eax
mov eax,gpPicture
push eax
mov eax,[eax]
call dword ptr [eax+12] ;gpPicture->get_Handle(&gdi_handle)
mov esi,bitmap_struc
invoke GetObject,gdi_handle,sizeof BITMAP,esi
mov ecx,gpPicture
mov [esi],ecx ;bitmap_struc.bmType=gpPicture
ret
_Mapping2BMP endp
_Kill_JPEG proc bitmap_struc:DWORD
mov eax,bitmap_struc
mov eax,[eax]
push eax
mov eax,[eax]
call dword ptr [eax+8] ;[bitmap_struc.bmType]->Release()
ret
_Kill_JPEG endp
start:
invoke _Mapping2BMP,addr gfx_title,30474,addr bitmap
invoke CreateFile,addr naz,GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0
push eax
invoke WriteFile,eax,bitmap.bmBits,416*180*3,addr dupa,0
call CloseHandle
invoke _Kill_JPEG,addr bitmap
invoke ExitProcess,eax
end start
Due to the use of file API's there really isnt much use of trying to optomize it. Your code looks fine to me. However, from a coding point of view you may find this GUID macro will make things a bit easier.
:alright:
NaN
Example:
;Make text equate
sIID_IPicture MGUID (7BF80980-BF32-101A-8BBB-00AA00300CAB)
;Define memory data
.data
IID_IPicture sIID_IPicture
:alright:
NaN