0,0 → 1,371 |
;;================================================================================================;; |
;;//// ico.asm //// (c) mike.dld, 2007-2008, (c) diamond, 2009 ///////////////////////////////////;; |
;;================================================================================================;; |
;; ;; |
;; This file is part of Common development libraries (Libs-Dev). ;; |
;; ;; |
;; Libs-Dev is free software: you can redistribute it and/or modify it under the terms of the GNU ;; |
;; Lesser General Public License as published by the Free Software Foundation, either version 2.1 ;; |
;; of the License, or (at your option) any later version. ;; |
;; ;; |
;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without ;; |
;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;; |
;; Lesser General Public License for more details. ;; |
;; ;; |
;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;; |
;; If not, see <http://www.gnu.org/licenses/>. ;; |
;; ;; |
;;================================================================================================;; |
;; ;; |
;; References: ;; |
;; 1. "Icons in Win32" ;; |
;; by John Hornick, Microsoft Corporation ;; |
;; http://msdn2.microsoft.com/en-us/library/ms997538.aspx ;; |
;; ;; |
;;================================================================================================;; |
|
include 'ico_cur.inc' |
|
;;================================================================================================;; |
;;proc img.is.ico _data, _length ;////////////////////////////////////////////////////////////////;; |
img.is.ico: |
mov edx, 0x00010000 ; icon type = 1 |
jmp @f |
img.is.cur: |
mov edx, 0x00020000 ; cursor type = 2 |
@@: |
;;------------------------------------------------------------------------------------------------;; |
;? Determine if raw data could be decoded (is in ICO format) ;; |
;;------------------------------------------------------------------------------------------------;; |
;> _data = raw data as read from file/stream ;; |
;> _length = data length ;; |
;;------------------------------------------------------------------------------------------------;; |
;< eax = false / true ;; |
;;================================================================================================;; |
; test 1 (length of data): data must contain FileHeader |
mov ecx, [esp+8] |
sub ecx, sizeof.ico.FileHeader |
jb .nope |
; test 2: signature |
mov eax, [esp+4] |
cmp dword [eax], edx ; Reserved & Type |
jne .nope |
; test 3: count must be non-zero |
movzx eax, [eax + ico.FileHeader.Count] |
test eax, eax |
jz .nope |
; test 4 (length of data): data must containt Count dir entries |
shl eax, 4 |
sub ecx, eax |
jae .yep |
|
.nope: |
xor eax, eax |
ret 8 |
|
.yep: |
xor eax, eax |
inc eax |
ret 8 |
;endp |
|
;;================================================================================================;; |
proc img.decode.ico_cur _data, _length, _options ;////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? Decode data into image if it contains correctly formed raw data in ICO/CUR format ;; |
;;------------------------------------------------------------------------------------------------;; |
;> _data = raw data as read from file/stream ;; |
;> _length = data length ;; |
;> _options = options for decoding (e.g. background color) ;; |
;;------------------------------------------------------------------------------------------------;; |
;< eax = 0 (error) or pointer to image ;; |
;;================================================================================================;; |
locals |
count dd ? |
img dd ? |
main_img dd ? |
endl |
|
push ebx esi edi |
|
; img.is.ico has been already called by img.decode |
; stdcall img.is.ico, [_data], [_length] |
; or eax, eax |
; jz .error |
|
mov ebx, [_data] |
movzx eax, [ebx + ico.FileHeader.Count] |
mov [count], eax |
and [img], 0 |
and [main_img], 0 |
.loop: |
mov ecx, [ebx + sizeof.ico.FileHeader + ico.DirEntry.ByteSize] |
mov edx, [ebx + sizeof.ico.FileHeader + ico.DirEntry.ImageOffset] |
mov eax, [_length] |
sub eax, edx |
jb .skip |
cmp eax, ecx |
jb .skip |
cmp ecx, 12 ; length test, see img.is.bmp |
jb .skip |
add edx, [_data] |
push [_options] |
push ecx |
push edx |
call img.decode.ico._.decode_icon_data |
test eax, eax |
jz .skip |
push 0xFFFFFF ; set bgr to white if no given |
mov edx, [_options] |
test edx, edx |
jz @f |
cmp [edx + ImageDecodeOptions.UsedSize], ImageDecodeOptions.BackgroundColor + 4 |
jb @f |
add esp, 4 |
push [edx + ImageDecodeOptions.BackgroundColor] |
@@: |
call img.decode.ico._.decode_icon_mask |
test eax, eax |
jz .skip |
mov edx, [img] |
test edx, edx |
jz .first |
mov [edx + Image.Next], eax |
mov [eax + Image.Previous], edx |
jmp @f |
.first: |
mov [main_img], eax |
@@: |
mov [img], eax |
.skip: |
add ebx, sizeof.ico.DirEntry |
dec [count] |
jnz .loop |
|
mov eax, [main_img] |
pop edi esi ebx |
ret |
endp |
|
;;================================================================================================;; |
img.encode.cur: |
proc img.encode.ico _img, _p_length, _options ;///////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? Encode image into raw data in ICO format ;; |
;;------------------------------------------------------------------------------------------------;; |
;> _img = pointer to image ;; |
;;------------------------------------------------------------------------------------------------;; |
;< eax = 0 (error) or pointer to encoded data ;; |
;< _p_length = encoded data length ;; |
;;================================================================================================;; |
xor eax, eax |
ret |
endp |
|
|
;;================================================================================================;; |
;;////////////////////////////////////////////////////////////////////////////////////////////////;; |
;;================================================================================================;; |
;! Below are private procs you should never call directly from your code ;; |
;;================================================================================================;; |
;;////////////////////////////////////////////////////////////////////////////////////////////////;; |
;;================================================================================================;; |
|
img.decode.ico._.decode_icon_data: |
; create stack frame and jump to common BMP+ICO code |
push ebp |
mov ebp, esp |
sub esp, 12 |
mov byte [ebp - 3], 1 ; bIsIco |
jmp img.decode.bmp.common |
|
img.decode.ico._.decode_icon_mask: |
mov edx, [eax + Image.Width] |
add edx, 31 |
shr edx, 3 |
and edx, not 3 |
push edx |
imul edx, [eax + Image.Height] |
cmp ecx, edx |
pop edx |
jb .error.free |
mov edi, [eax + Image.Data] |
push ebp ebx eax |
xor ebp, ebp |
mov ebx, [eax + Image.Extended] |
cmp [ebx + bmp.Image.info.Height], 0 |
js @f |
push edx |
imul edx, [eax + Image.Height] |
add esi, edx |
pop edx |
lea ebp, [edx+edx] |
sub esi, edx |
@@: |
mov ebx, [eax + Image.Height] |
mov ecx, [eax + Image.Width] |
; for now, BMP code produces only 8 and 32 bpp images |
cmp [eax + Image.Type], Image.bpp8 |
jz .bpp8 |
.bpp32: |
mov edx, [esp+16] ; get background color |
.bpp32.extloop: |
push ecx |
.bpp32.innloop: |
lodsd |
bswap eax |
push 32 |
.bpp32.dwordloop: |
add eax, eax |
jnc @f |
mov [edi], edx |
@@: |
add edi, 4 |
dec ecx |
jz @f |
dec dword [esp] |
jnz .bpp32.dwordloop |
@@: |
pop eax |
test ecx, ecx |
jnz .bpp32.innloop |
sub esi, ebp |
pop ecx |
dec ebx |
jnz .bpp32.extloop |
pop eax ebx ebp |
ret 4 |
.bpp8: |
push edi |
mov edi, [eax + Image.Palette] |
mov eax, [esp+20] ; get background color |
; if palette already has index for bgr color, use it |
push ecx |
mov ecx, 256 |
repnz scasd |
jnz .bpp8.notfound |
not cl ; cl = index |
pop edx |
pop edi |
.bpp8.extloop: |
push edx |
.bpp8.innloop: |
lodsd |
bswap eax |
push 32 |
.bpp8.dwordloop: |
add eax, eax |
jnc @f |
mov [edi], cl |
@@: |
inc edi |
dec edx |
jz @f |
dec dword [esp] |
jnz .bpp8.dwordloop |
@@: |
pop eax |
test edx, edx |
jnz .bpp8.innloop |
sub esi, ebp |
pop edx |
dec ebx |
jnz .bpp8.extloop |
pop eax ebx ebp |
ret 4 |
.bpp8.notfound: |
; get maximum used color; if index < 255, then we can add one color to palette |
pop ecx |
pop edi |
pop eax |
mov edx, [eax + Image.Width] |
imul edx, ebx |
mov edi, [eax + Image.Data] |
xor ecx, ecx |
.bpp8.scanloop: |
cmp [edi], cl |
jb @f |
mov cl, [edi] |
@@: |
inc edi |
dec edx |
jnz .bpp8.scanloop |
inc cl |
jz .bpp8.nospace |
mov edx, [esp+8] |
mov edi, [eax + Image.Palette] |
mov [edi+ecx*4], edx ; set palette color |
mov edi, [eax + Image.Data] |
mov edx, [eax + Image.Width] |
push eax |
jmp .bpp8.extloop |
.bpp8.nospace: |
; convert to 24 bpp |
mov edx, [eax + Image.Width] |
imul edx, ebx |
lea edx, [edx*3] |
push eax |
invoke mem.alloc, edx |
mov edi, eax |
pop eax |
test edi, edi |
jz .error.free2 |
push eax esi edi |
mov esi, eax |
call img._.do_rgb |
pop edi esi eax |
xchg edi, [eax + Image.Data] |
mov byte [eax + Image.Type], Image.bpp24 |
push eax |
invoke mem.free, edi |
pop eax |
push eax |
mov ecx, [eax + Image.Width] |
.bpp24: |
mov edx, [esp+16] ; get background color |
.bpp24.extloop: |
push ecx |
.bpp24.innloop: |
lodsd |
bswap eax |
push 32 |
.bpp24.dwordloop: |
add eax, eax |
jnc @f |
mov [edi], dx |
ror edx, 16 |
mov [edi+2], dl |
ror edx, 16 |
@@: |
add edi, 4 |
dec ecx |
jz @f |
dec dword [esp] |
jnz .bpp24.dwordloop |
@@: |
pop eax |
test ecx, ecx |
jnz .bpp24.innloop |
sub esi, ebp |
pop ecx |
dec ebx |
jnz .bpp24.extloop |
pop eax ebx ebp |
ret 4 |
.error.free2: |
pop ebx ebp |
.error.free: |
stdcall img._.delete, eax |
xor eax, eax |
ret 4 |
|
;;================================================================================================;; |
;;////////////////////////////////////////////////////////////////////////////////////////////////;; |
;;================================================================================================;; |
;! Below is private data you should never use directly from your code ;; |
;;================================================================================================;; |
;;////////////////////////////////////////////////////////////////////////////////////////////////;; |
;;================================================================================================;; |
|
|
; |