The MASM Forum Archive 2004 to 2012

Project Support Forums => The GeneSys Development System => Topic started by: Vortex on July 27, 2008, 08:19:32 PM

Title: Converting BMP to JPG
Post by: Vortex on July 27, 2008, 08:19:32 PM
Inspired by this thread (http://www.masm32.com/board/index.php?topic=9528.0), I wrote an example of converting a BMP in memory to a JPG file. The GeneSys installation provides gdiplus.inc and gdiplus.lib

Other conversion options :

Quoteimage/gif
image/tiff
image/png


include GDIpBmpToJPG.inc
include gdiplus.inc

EXTERN pImage:BYTE

UnicodeStr PROTO :DWORD,:DWORD
GetEncoderClsid PROTO :DWORD,:DWORD

.data
szFileName  db 'test.bmp',0
jpegFile    db 'test.jpg',0
ImgType     db 'image/jpeg',0
message     db 'BMP file converted to JPG',0
caption     db 'GDI+ demo',0

.data?
StartupInfo     GdiplusStartupInput <?>
buffer          db 32 dup(?)
pImageCodecInfo dd ?
token           dd ?
BmpImage        dd ?

.code

start:

    mov     eax,OFFSET StartupInfo
    mov     GdiplusStartupInput.GdiplusVersion[eax],1
    invoke GdiplusStartup,ADDR token,ADDR StartupInfo,0
    invoke UnicodeStr,ADDR szFileName,ADDR buffer
; convert szFileName to UNICODE

    mov     eax,OFFSET pImage
    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  UnicodeStr,ADDR jpegFile,ADDR buffer
    invoke  GetEncoderClsid,ADDR ImgType,ADDR pImageCodecInfo
; get the class identifier (CLSID) of the encoder
        ; The encoder can be bmp,jpeg,gif,tiff or png
    invoke  GdipSaveImageToFile,BmpImage,ADDR buffer,eax,0
; save the image file
    invoke  VirtualFree,pImageCodecInfo,0,MEM_RELEASE

    invoke  GdipDisposeImage,BmpImage ; release the image
    invoke  GdiplusShutdown,token ; shutdown the GDI+ system
    invoke  MessageBox,0,ADDR message,ADDR caption,MB_OK
    invoke  ExitProcess,0

GetEncoderClsid PROC USES ebx edi sMimeType:DWORD,pMem:DWORD

LOCAL numEncoders:DWORD
LOCAL nSize:DWORD
LOCAL _buffer[32]:BYTE

    invoke  GdipGetImageEncodersSize,ADDR numEncoders,ADDR nSize
    invoke  VirtualAlloc,0,nSize,MEM_COMMIT,PAGE_READWRITE
    mov     edi,eax
    mov     eax,pMem ; = pImageCodecInfo
    mov     DWORD PTR [eax],edi
    invoke  GdipGetImageEncoders,numEncoders,nSize,edi
    invoke  UnicodeStr,sMimeType,ADDR _buffer
    mov     ebx,numEncoders
@@:
    invoke  StrCmpW,ADDR _buffer,ImageCodecInfo.MimeType[edi]
    test    eax,eax
    jnz     @f
    sub     ebx,1
    add     edi,SIZEOF ImageCodecInfo
    jmp     @b
@@:
    lea     eax,[edi+ImageCodecInfo.Clsid]
    ret

GetEncoderClsid ENDP

UnicodeStr PROC USES esi src:DWORD,dest:DWORD

    mov     esi,src
    mov     edx,dest
    xor     eax,eax
    sub     eax,1
@@:
    add     eax,1
    movzx   ecx,BYTE PTR [esi+eax]
    mov     WORD PTR [edx+eax*2],cx
    test    ecx,ecx
    jnz     @b
    ret

UnicodeStr ENDP

END start

[attachment deleted by admin]
Title: Re: Converting BMP to JPG
Post by: PBrennick on July 29, 2008, 01:10:35 AM
Vortex,

EXTERN pImage:BYTE ?

Anyway, I am going to play with the Capture example. I always disliked the bitmap thing. The problem with me, though, is that when it comes to working with graphics I am pretty dense, maybe stupid.  ::)

-- Paul
Title: Re: Converting BMP to JPG
Post by: Vortex on July 29, 2008, 05:26:28 PM
Hi Paul,

The BMP image is converted to a MS COFF object module to be linked with the project module :

bin2coff image.bmp image.obj _pImage

The image is now encapsulated in the object module as a binary data block :

Microsoft (R) COFF Binary File Dumper Version 5.12.8078
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

\GeneSys\bin\dumpbin /HEADERS image.obj


Dump of file image.obj

File Type: COFF OBJECT

FILE HEADER VALUES
             14C machine (i386)
               1 number of sections
               0 time date stamp Thu Jan 01 02:00:00 1970
           323D6 file pointer to symbol table
               1 number of symbols
               0 size of optional header
             184 characteristics
                   Line numbers stripped
                   Bytes reversed
                   32 bit word machine

SECTION HEADER #1
   .data name
       0 physical address
       0 virtual address
   3239A size of raw data
      3C file pointer to raw data
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
C0300040 flags
         Initialized Data
         4 byte align
         Read Write


The label pImage is the reference to the data block containing the BMP image bytes.
Title: Re: Converting BMP to JPG
Post by: Vortex on July 31, 2008, 05:45:49 PM
This new version has the capacity to set the compression level of JPG images.

To set the compression level, modify the value of ImgQuality :

ImgQuality dd  50 ; compression = 50 %
[attachment deleted by admin]
Title: Re: Converting BMP to JPG
Post by: Vortex on August 07, 2008, 05:51:24 PM
This new example loads a bitmap image with GdipCreateBitmapFromFile and saves the JPEG to a stream created by CreateStreamOnHGlobal. The JPEG in memory can be edited \ modifed before saving to disc. GetHGlobalFromStream and GlobalLock are used to determine the address of the JPEG image. The method IStream::Seek is called to find the size of the image. The JPEG is saved before terminating the application.

[attachment deleted by admin]
Title: Re: Converting BMP to JPG
Post by: PBrennick on August 07, 2008, 08:20:06 PM
Vortex,
Okay, so now I will try to make good use of your hard work by applying it to the Capture utility. I always wanted to extend its capabilities, anyway, so now it might be a good time to do so now that the file sizes will be more manageable.

-- Paul
Title: Re: Converting BMP to JPG
Post by: Vortex on August 07, 2008, 08:30:41 PM
Hi Paul,

Once you get hBitmap the handle to the desktop, I guess you can use the GdipCreateBitmapFromHBITMAP function to create a bitmap object.