ifndef                  _PICTURE_ASM
_PICTURE_ASM            equ     1

; ------------------------------------------------------
; Load BMP JPEG GIF EMF WMF ICO pictures in memory done by Siekmanski
; Copyright (c) 2005-2016, Siekmanski and Franck Charlet
; All rights reserved.
; ------------------------------------------------------

; ------------------------------------------------------
; Structures
PICTURE                 struct
Datas                   dword   ?
_Width                  dword   ?
Height                  dword   ?
Bits                    dword   ?
Orig_Width              dword   ?
Orig_Height             dword   ?
PICTURE                 ends

; ------------------------------------------------------
; Variables
                        .data

IID_IPicture            GUID    sIID_IPicture

                        .code

; ------------------------------------------------------
; Includes
                        include Files.asm

; ------------------------------------------------------
; Name: Load_PICTURE
; Desc: Load a BMP GIF JPG EMF WMF ICO file into memory
Load_PICTURE            proc    uses ebx esi edi PICTURE_FName:dword, PICTURE_Struct:dword, Color_Key:dword
                        local   PICTURE_Buffer:dword
                        local   FSize:dword
                        local   DatOffset:dword
                        local   pStream:dword
                        local   pPicture:LPIPICTURE
                        local   hdcTemp:HDC
                        local   hbmpTemp:HBITMAP
                        local   binfo:BITMAPINFO
                        local   pBits:dword
                        local   IPicWidth:dword
                        local   IPicHeight:dword
                  
                        mov     esi, PICTURE_Struct
                        mov     [esi + PICTURE.Datas], NULL
                        mov     [esi + PICTURE.Bits], 32        ; Only 32 bits

                        ; Load texture into memory
                        invoke  Load_File, PICTURE_FName, addr FSize
                        test    eax, eax
                        jz      Err_PIC_Load
                        mov     PICTURE_Buffer, eax

                        invoke  CreateStreamOnHGlobal, PICTURE_Buffer, TRUE, addr pStream
                        cmp     eax, S_OK
                        jne     Err_PIC_CStream

                        invoke  OleLoadPicture, pStream, NULL, TRUE, addr IID_IPicture, addr pPicture
                        cmp     eax, S_OK
                        jne     Err_PIC_Stream

                        invoke  GetDC,NULL
                        push    eax
                        invoke  CreateCompatibleDC, eax
                        mov     hdcTemp, eax
                        pop     eax
                        invoke  DeleteDC, eax

                        ; Get IPicture width and height
                        COINVOKE pPicture, IPicture.get_Width, addr IPicWidth
                        COINVOKE pPicture, IPicture.get_Height, addr IPicHeight

                        ; Convert to pixels
                        invoke  GetDeviceCaps, hdcTemp, LOGPIXELSX
                        invoke  MulDiv, IPicWidth, eax, HIMETRIC_INCH
                        mov     [esi + PICTURE._Width], eax
                        invoke  GetDeviceCaps, hdcTemp, LOGPIXELSY
                        invoke  MulDiv, IPicHeight, eax, HIMETRIC_INCH
                        mov     [esi + PICTURE.Height], eax

                        invoke  RtlZeroMemory, addr binfo.bmiHeader, sizeof BITMAPINFOHEADER

                        mov     binfo.bmiHeader.biSize, sizeof BITMAPINFOHEADER
                        mov     eax, [esi + PICTURE.Bits]
                        mov     binfo.bmiHeader.biBitCount, ax
                        mov     eax, [esi + PICTURE._Width]
                        mov     binfo.bmiHeader.biWidth, eax
                        mov     eax, [esi + PICTURE.Height]
                        mov     binfo.bmiHeader.biHeight, eax
                        mov     binfo.bmiHeader.biCompression, BI_RGB
                        mov     binfo.bmiHeader.biPlanes, 1

                        invoke  CreateDIBSection, hdcTemp,addr binfo, DIB_RGB_COLORS, addr pBits, NULL, 0
                        test    eax, eax
                        jz      Err_PIC_DIB
                        mov     hbmpTemp, eax

                        invoke  SelectObject, hdcTemp, hbmpTemp
                        mov     eax, IPicHeight
                        neg     eax

                        COINVOKE pPicture, IPicture.Render, hdcTemp, 0, 0, [esi + PICTURE._Width], [esi + PICTURE.Height], 0, IPicHeight, IPicWidth, eax, 0

                        cmp     eax, S_OK
                        jne     Err_PIC_Render

                        mov     eax, [esi + PICTURE._Width]
                        mov     ebx, [esi + PICTURE.Height]
                        ; Fix the sizes
                        .if     eax > ebx
                                mov     [esi + PICTURE.Height], eax
                        .endif
                        .if     eax < ebx
                                mov     [esi + PICTURE._Width], ebx
                        .endif

                        imul    eax, ebx
                        push    eax
                        mov     eax, [esi + PICTURE._Width]
                        imul    eax, [esi + PICTURE.Height]
                        shl     eax, 2
                        mov     eax, ALLOCMEM(eax)
                        pop     ecx
                        test    eax, eax
                        jz      Err_PIC_Render
                        mov     [esi + PICTURE.Datas], eax
                        mov     edi, eax

                        mov     esi, pBits                      ; 32 bits image datas
Copy_32BitPixels:       lodsb
                        ror     eax, 8
                        lodsb
                        ror     eax, 8
                        lodsb
                        ror     eax, 8 
                        lodsb
                        bswap   eax
                        and     eax, 000ffffffh
                        mov     edx, Color_Key
                        test    edx, edx
                        js      _No_Set_Alpha_32
                        and     edx, 000ffffffh
                        cmp     edx, eax
                        jne     _No_Set_Alpha_32
                        mov     eax, 0ff000000h                 ; Turn alpha channel on for this color
_No_Set_Alpha_32:       xor     eax, 0ff000000h
                        stosd
                        loop    Copy_32BitPixels
                        invoke  DeleteObject, hbmpTemp
                        invoke  DeleteDC, hdcTemp
                        SAFE_RELEASE pPicture
                        SAFE_RELEASE pStream
                        mov     eax, TRUE                       ; Loaded
                        ret
Err_PIC_Render:         invoke  DeleteObject, hbmpTemp
Err_PIC_DIB:            invoke  DeleteDC, hdcTemp
                        SAFE_RELEASE pPicture
Err_PIC_Stream:         SAFE_RELEASE pStream
                        xor     eax, eax                        ; Not loaded
                        ret
Err_PIC_CStream:        FREEMEM PICTURE_Buffer
Err_PIC_Load:           xor     eax, eax                        ; Not loaded
                        ret
Load_PICTURE            endp

; ------------------------------------------------------
; Name: Unload_PICTURE
; Desc: Free an allocated picture
Unload_PICTURE          proc    uses esi PICTURE_Struct:dword
                        mov     esi, PICTURE_Struct
                        test    esi, esi
                        jz      @F
                        mov     eax, [esi + PICTURE.Datas]
                        test    eax, eax
                        jz      @F
                        FREEMEM eax
@@:                     ret
Unload_PICTURE          endp

endif
