51,7 → 51,7 |
;;------------------------------------------------------------------------------------------------;; |
;< eax = false / true ;; |
;;================================================================================================;; |
cmp [_length], 6 |
cmp [_length], sizeof.gif.Header |
jb .nope |
mov eax, [_data] |
cmp dword[eax], 'GIF8' |
82,37 → 82,100 |
;< eax = 0 (error) or pointer to image ;; |
;;================================================================================================;; |
locals |
max_color dd ? |
cur_color_table_size dd ? |
transparent_color dd ? |
background_color dd ? |
prev_palette dd ? |
aux_palette dd ? |
img dd ? |
prev_img_data dd ? |
aux_img_data dd ? |
aux_img_type dd ? |
prev_num_colors dd ? |
main_img dd ? |
global_color_table dd ? |
global_color_table_size dd ? |
endl |
|
push ebx |
img.decode.gif.main_img equ main_img |
img.decode.gif.prev_img_data equ prev_img_data |
img.decode.gif.transparent_color equ transparent_color |
img.decode.gif.background_color equ background_color |
img.decode.gif._length equ _length |
img.decode.gif.prev_num_colors equ prev_num_colors |
img.decode.gif.prev_palette equ prev_palette |
img.decode.gif.max_color equ max_color |
img.decode.gif._data equ _data |
img.decode.gif.aux_img_data equ aux_img_data |
img.decode.gif.aux_img_type equ aux_img_type |
img.decode.gif.aux_palette equ aux_palette |
; offset of _length parameter for child functions with ebp-based frame |
; child saved ebp, return address, 3 saved registers, 14 local variables |
img.decode.gif._length_child equ _length + 4 + 4 + 4*3 + 4*14 |
img.decode.gif.max_color_child equ ebp + 4 + 4 + 4*3 |
img.decode.gif.cur_color_table_size_child equ ebp + 4 + 4 + 4*3 + 4 |
|
push ebx esi edi |
xor eax, eax |
mov [img], eax |
mov [main_img], eax |
mov [prev_img_data], eax |
mov [aux_img_data], eax |
mov [aux_img_type], eax |
mov [prev_palette], eax |
mov [aux_palette], eax |
; when no previous image is available, use background fill with 1-entry palette |
inc eax |
mov [prev_num_colors], eax |
lea eax, [background_color] |
mov [prev_palette], eax |
; guard against incorrect gif files, which use Restore-To-Background disposal method, but do not define bgr color |
mov dword [eax], 0xFFFFFF |
; guard against incorrect gif files without any color tables |
; "If no color table is available at |
; all, the decoder is free to use a system color table or a table of its own. In |
; that case, the decoder may use a color table with as many colors as its |
; hardware is able to support; it is recommended that such a table have black and |
; white as its first two entries, so that monochrome images can be rendered |
; adequately." (c) official gif documentation |
mov [global_color_table], gif_default_palette |
mov [global_color_table_size], 2 |
|
; img.is.gif is called by caller (img.decode) |
; stdcall img.is.gif, [_data], [_length] |
; or eax, eax |
; jz .error |
|
mov [global_color_table_size], 0 |
mov ebx, [_data] |
sub [_length], sizeof.gif.Header |
|
test [ebx + gif.Header.lsd.Packed], gif.LSD.Packed.GlobalColorTableFlag |
jz @f |
lea eax, [ebx + sizeof.gif.Header] |
mov [global_color_table], eax |
mov cl, [ebx + gif.Header.lsd.Packed] |
add ebx, sizeof.gif.Header |
; gif.LSD.Packed.GlobalColorTableFlag = 80h |
; test cl, gif.LSD.Packed.GlobalColorTableFlag |
; jz @f |
test cl, cl |
jns @f |
mov [global_color_table], ebx |
and cl, gif.LSD.Packed.SizeOfGlobalColorTableMask |
shr cl, gif.LSD.Packed.SizeOfGlobalColorTableShift |
mov eax, 2 |
; shr cl, gif.LSD.Packed.SizeOfGlobalColorTableShift ; here Shift = 0 |
push 2 |
pop eax |
shl eax, cl |
mov [global_color_table_size], eax |
lea eax, [eax * 3] |
sub [_length], eax |
jbe .error ; there must be at least 1 additional byte after color table |
movzx ecx, byte [ebx - sizeof.gif.Header + gif.Header.lsd.BackgroundColor] |
lea ecx, [ecx*3] |
mov ecx, [ebx + ecx] ; eax = xxBBGGRR, convert to Kolibri color |
bswap ecx |
shr ecx, 8 |
mov [background_color], ecx |
add ebx, eax |
@@: add ebx, sizeof.gif.Header |
@@: |
|
mov [img], 0 |
|
; @@: cmp byte[ebx + gif.Block.Introducer], gif.Block.Introducer.Extension |
; jne .next_image |
; cmp byte[ebx + gif.Extension.Label], gif.Extension.Label.Comment |
128,26 → 191,45 |
jz .error |
mov edx, [img] |
mov [eax + Image.Previous], edx |
push sizeof.gif.LogicalScreenDescriptor |
pop ecx |
test edx, edx |
jz @f |
mov [edx + Image.Next], eax |
xor ecx, ecx |
@@: |
mov [img], eax |
mov edx, eax |
push eax |
mov [eax + Image.Type], Image.bpp8 |
|
invoke mem.alloc, sizeof.gif.Image |
add ecx, sizeof.gif.Image |
invoke mem.alloc, ecx |
pop edx |
or eax, eax |
jz .error |
jz .error2 |
mov [edx + Image.Extended], eax |
xor ecx, ecx |
cmp [img], ecx |
jnz @f |
mov esi, [_data] |
add esi, gif.Header.lsd |
lea edi, [eax + sizeof.gif.Image] |
mov cl, sizeof.gif.LogicalScreenDescriptor |
rep movsb |
mov [main_img], edx |
@@: |
mov [img], edx |
|
stdcall ._.process_extensions |
|
cmp byte[ebx + gif.Block.Introducer], gif.Block.Introducer.ImageDescriptor |
cmp al, gif.Block.Introducer.ImageDescriptor |
jne .error |
sub [_length], sizeof.gif.ImageDescriptor |
jc .error |
movzx eax, [ebx + gif.ImageDescriptor.Width] |
movzx ecx, [ebx + gif.ImageDescriptor.Height] |
push edx |
stdcall img._.resize_data, [img], eax, ecx |
pop edx |
or eax, eax |
jz .error |
|
164,13 → 246,20 |
lea esi, [ebx + sizeof.gif.ImageDescriptor] |
mov cl, [ebx + gif.ImageDescriptor.Packed] |
and cl, gif.ID.Packed.SizeOfLocalColorTableMask |
shr cl, gif.ID.Packed.SizeOfLocalColorTableShift |
mov eax, 2 |
; here Shift = 0 |
; shr cl, gif.ID.Packed.SizeOfLocalColorTableShift |
push 2 |
pop eax |
shl eax, cl |
mov ecx, eax |
lea eax, [eax*3] |
add ebx, eax |
sub [_length], eax |
jbe .error ; because we load additional byte, check is 'jbe', not 'jc' |
@@: |
mov [cur_color_table_size], ecx |
dec [cur_color_table_size] |
@@: |
lodsd |
dec esi |
bswap eax |
179,24 → 268,105 |
loop @b |
add ebx, sizeof.gif.ImageDescriptor |
stdcall ._.process_image |
|
.decoded: |
or eax, eax |
push ebx |
mov edx, [img] |
push edx |
stdcall ._.superimpose |
pop edx |
push edx |
stdcall ._.dispose |
pop edx |
mov edx, [edx + Image.Previous] |
test edx, edx |
jz .nofreeprev |
mov ebx, [edx + Image.Extended] |
cmp [ebx + gif.Image.gce.DelayTime], 0 |
jnz .nofreeprev |
mov esi, [prev_palette] |
cmp esi, [edx + Image.Palette] |
jnz @f |
mov ecx, [prev_num_colors] |
stdcall ._.alloc_aux_palette |
test eax, eax |
jz .nofreeprev |
mov [prev_palette], eax |
@@: |
mov esi, [prev_img_data] |
cmp esi, [edx + Image.Data] |
jnz .noprevdata |
push 1 |
pop eax |
cmp [edx + Image.Type], Image.bpp8 |
jz @f |
stdcall img.destroy, [img] |
jmp .error |
mov al, 3 |
@@: |
cmp [aux_img_type], eax |
jb .resetaux |
mov edi, [aux_img_data] |
imul eax, [edx + Image.Width] |
imul eax, [edx + Image.Height] |
xchg eax, ecx |
rep movsb |
jmp .noprevdata |
.resetaux: |
mov [aux_img_type], eax |
mov eax, [aux_img_data] |
test eax, eax |
jz @f |
invoke mem.free, eax |
@@: |
xor eax, eax |
xchg eax, [edx + Image.Data] |
mov [aux_img_data], eax |
.noprevdata: |
cmp edx, [main_img] |
jnz @f |
mov eax, [edx + Image.Next] |
mov [main_img], eax |
mov esi, [eax + Image.Extended] |
mov edi, [edx + Image.Extended] |
mov [edx + Image.Extended], esi |
mov [eax + Image.Extended], edi |
push sizeof.gif.Image |
pop ecx |
rep movsb |
@@: |
stdcall img.destroy.layer, edx |
.nofreeprev: |
pop ebx |
test ebx, ebx |
jz .ret |
jmp .next_image |
|
@@: mov eax, [img] |
ret |
.error2: |
mov [img], edx |
|
.error: |
mov eax, [img] |
test eax, eax |
jz .ret |
cmp [main_img], eax |
jnz @f |
and [main_img], 0 |
@@: |
stdcall img.destroy.layer, eax |
.ret: |
mov eax, [aux_img_data] |
test eax, eax |
jz @f |
stdcall img.destroy, eax |
invoke mem.free, eax |
@@: |
xor eax, eax |
pop ebx |
mov eax, [aux_palette] |
test eax, eax |
jz @f |
invoke mem.free, eax |
@@: |
mov eax, [main_img] |
cmp [eax + Image.Next], 0 |
jz @f |
or [eax + Image.Flags], Image.IsAnimated |
@@: |
pop edi esi ebx |
ret |
endp |
|
225,26 → 395,6 |
|
|
;;================================================================================================;; |
proc img.decode.gif._.skip_data ;/////////////////////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? --- TBD --- ;; |
;;------------------------------------------------------------------------------------------------;; |
;> ebx = pointer to data blocks array ;; |
;;------------------------------------------------------------------------------------------------;; |
;< eax = pointer to data right after data blocks array ;; |
;;================================================================================================;; |
push ecx |
xor ecx, ecx |
@@: mov cl, [esi] |
or cl, cl |
jz @f |
lea esi, [esi + ecx + 1] |
jmp @b |
@@: pop ecx |
ret |
endp |
|
;;================================================================================================;; |
proc img.decode.gif._.process_extensions ;////////////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? --- TBD --- ;; |
254,65 → 404,65 |
;;------------------------------------------------------------------------------------------------;; |
;< --- TBD --- ;; |
;;================================================================================================;; |
push edx |
mov esi, ebx |
xor eax, eax |
mov [edx + Image.Delay], eax |
|
.next_block: |
mov al, [esi + gif.Block.Introducer] |
dec [img.decode.gif._length] |
js .exit_err |
lodsb ; load gif.Block.Introducer |
cmp al, gif.Block.Introducer.Extension |
je .ext_block |
; cmp al, gif.Block.Introducer.ImageDescriptor |
; je .exit |
; cmp al, gif.Block.Introducer.EndOfFile |
; je .exit |
jmp .exit |
jne .exit |
|
.ext_block: |
mov al, [esi + gif.Extension.Label] |
cmp al, gif.Extension.Label.PlainText |
je .plain_text_ext |
dec [img.decode.gif._length] |
js .exit_err |
lodsb ; load gif.Extension.Label |
cmp al, gif.Extension.Label.GraphicsControl |
je .graphics_control_ext |
cmp al, gif.Extension.Label.Comment |
je .comment_ext |
cmp al, gif.Extension.Label.Application |
je .application_ext |
jmp .exit |
; cmp al, gif.Extension.Label.PlainText |
; je .plain_text_ext |
; cmp al, gif.Extension.Label.Comment |
; je .comment_ext |
; cmp al, gif.Extension.Label.Application |
; je .application_ext |
; skip all other extensions |
.skip_ext: |
dec [img.decode.gif._length] |
js .exit_err |
lodsb ; load BlockSize |
.1: |
test al, al |
jz .next_block |
sub [img.decode.gif._length], eax |
jc .exit_err |
add esi, eax |
jmp .skip_ext |
|
.plain_text_ext: |
add esi, gif.PlainTextExtension.PlainTextData |
stdcall img.decode.gif._.skip_data |
jmp .next_ext_block |
|
.graphics_control_ext: |
dec [img.decode.gif._length] |
js .exit_err |
lodsb ; load BlockSize; must be sizeof.gif.GraphicsControlExtension |
cmp al, sizeof.gif.GraphicsControlExtension |
jnz .1 |
sub [img.decode.gif._length], eax |
jc .exit_err |
push edi |
movzx edi, [esi + gif.GraphicsControlExtension.DelayTime] |
mov [edx + Image.Delay], edi |
mov edi, [edx + Image.Extended] |
add edi, gif.Image.gce |
mov ecx, sizeof.gif.GraphicsControlExtension |
mov ecx, eax |
rep movsb |
pop edi |
jmp .next_ext_block |
jmp .skip_ext |
|
.comment_ext: |
add esi, gif.CommentExtension.CommentData |
stdcall img.decode.gif._.skip_data |
jmp .next_ext_block |
.exit_err: |
xor eax, eax |
|
.application_ext: |
add esi, gif.ApplicationExtension.ApplicationData |
stdcall img.decode.gif._.skip_data |
jmp .next_ext_block |
|
.next_ext_block: |
mov al, [esi + gif.Block.Introducer] |
cmp al, gif.Block.Introducer.EndOfData |
jne .exit |
inc esi |
jmp .next_block |
|
.exit: |
mov ebx, esi |
pop edx |
ret |
endp |
|
354,6 → 504,7 |
inc eax |
mov [row_end], eax |
and [pass], 0 |
and dword [img.decode.gif.max_color_child], 0 |
mov eax, [edx + Image.Extended] |
test [eax + gif.Image.info.Packed], gif.ID.Packed.InterleaceFlag |
jz @f |
362,15 → 513,21 |
@@: mov esi, ebx |
mov edi, [edx + Image.Data] |
|
push edi |
sub dword [img.decode.gif._length_child], 2 |
jc .error |
movzx ecx, byte[esi] |
inc esi |
cmp cl, 12 |
jae .error |
mov [codesize], ecx |
inc [codesize] |
mov edi, [workarea] |
xor eax, eax |
lodsb ; eax - block_count |
sub [img.decode.gif._length_child], eax |
jc .error |
add eax, esi |
push edi |
mov edi, [workarea] |
mov [block_ofs], eax |
mov [bit_count], 8 |
mov eax, 1 |
400,19 → 557,22 |
.cycle: |
movzx ebx, ax |
call .get_symbol |
cmp eax, [EOI] |
je .end |
cmp eax, edx |
jae .notintable |
ja .error |
je .notintable |
cmp eax, [CC] |
je .reinit |
cmp eax, [EOI] |
je .end |
call .output |
.add: |
cmp edx, 0x00001000 |
jae .cycle |
mov ecx, [workarea] |
mov [ecx + edx * 4], ebx |
cmp edx, 0x00000FFF |
jae .cycle |
inc edx |
cmp edx, 0x1000 |
je .noinc |
bsr ebx, edx |
cmp ebx, [compsize] |
jne .noinc |
436,15 → 596,26 |
cmp [workarea], 0 |
je @f |
invoke mem.free, [workarea] |
@@: xor eax, eax |
ret |
@@: |
mov ebx, [block_ofs] |
@@: |
dec [img.decode.gif._length_child] |
js @f |
movzx eax, byte [ebx] |
inc ebx |
test eax, eax |
jz .ret |
sub [img.decode.gif._length_child], eax |
jc @f |
add ebx, eax |
jmp @b |
|
.error: |
cmp [workarea], 0 |
je @f |
invoke mem.free, [workarea] |
@@: xor eax, eax |
inc eax |
@@: xor ebx, ebx |
.ret: |
ret |
|
;;------------------------------------------------------------------------------------------------;; |
455,32 → 626,35 |
xor eax, eax |
|
.shift: |
ror byte[esi], 1 |
rcr eax,1 |
dec [bit_count] |
jnz .loop1 |
jns .loop1 |
inc esi |
cmp esi, [block_ofs] |
jb .noblock |
push eax |
xor eax, eax |
sub [img.decode.gif._length_child], 1 |
jc .error_eof |
lodsb |
test eax, eax |
jnz .nextbl |
mov eax, [EOI] |
sub esi, 2 |
add esp, 8 |
jmp .exit |
.error_eof: |
add esp, 12 |
jmp img.decode.gif._.process_image.error |
|
.nextbl: |
sub [img.decode.gif._length_child], eax |
jc .error_eof |
add eax, esi |
mov [block_ofs], eax |
pop eax |
|
.noblock: |
mov [bit_count], 8 |
mov [bit_count], 7 |
|
.loop1: |
ror byte[esi], 1 |
rcr eax,1 |
loop .shift |
pop ecx |
rol eax, cl |
506,8 → 680,16 |
|
.loop2: |
pop ax |
stosb |
cmp al, byte [img.decode.gif.cur_color_table_size_child] |
jbe @f ; guard against incorrect GIFs |
mov al, 0 |
@@: cmp al, byte [img.decode.gif.max_color_child] |
jbe @f |
mov [img.decode.gif.max_color_child], al |
@@: stosb |
|
cmp edi, [img_end] |
jz .done |
cmp edi, [row_end] |
jb .norowend |
mov eax, [width] |
546,10 → 728,849 |
pop edx eax esi |
retn |
|
.done: |
lea esp, [esp+(ecx-1)*2] |
pop edx eax esi eax |
jmp img.decode.gif._.process_image.exit |
|
endp |
|
;;================================================================================================;; |
proc img.decode.gif._.is_logical_screen ;/////////////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? Determines whether GIF image occupies the whole logical screen ;; |
;;------------------------------------------------------------------------------------------------;; |
;> eax = extended image data ;; |
;> ebx = main image ;; |
;;------------------------------------------------------------------------------------------------;; |
;< ZF set <=> image area equals logical screen ;; |
;;================================================================================================;; |
mov ebx, [ebx + Image.Extended] |
cmp [eax + gif.Image.info.Left], 0 |
jnz @f |
cmp [eax + gif.Image.info.Top], 0 |
jnz @f |
mov cx, [eax + gif.Image.info.Width] |
cmp cx, [ebx + sizeof.gif.Image + gif.LogicalScreenDescriptor.ScreenWidth] |
jnz @f |
mov cx, [eax + gif.Image.info.Height] |
cmp cx, [ebx + sizeof.gif.Image + gif.LogicalScreenDescriptor.ScreenHeight] |
@@: retn |
endp |
|
main_img equ img.decode.gif.main_img |
transparent_color equ img.decode.gif.transparent_color |
background_color equ img.decode.gif.background_color |
prev_num_colors equ img.decode.gif.prev_num_colors |
prev_palette equ img.decode.gif.prev_palette |
max_color equ img.decode.gif.max_color |
prev_img_data equ img.decode.gif.prev_img_data |
_data equ img.decode.gif._data |
aux_img_data equ img.decode.gif.aux_img_data |
aux_img_type equ img.decode.gif.aux_img_type |
aux_palette equ img.decode.gif.aux_palette |
|
;;================================================================================================;; |
proc img.decode.gif._.superimpose ;///////////////////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? --- TBD --- ;; |
;;------------------------------------------------------------------------------------------------;; |
;> edx = image data ;; |
;;------------------------------------------------------------------------------------------------;; |
;< --- TBD --- ;; |
;;================================================================================================;; |
mov ebx, [main_img] |
mov eax, [edx + Image.Extended] |
or [transparent_color], -1 ; no transparent color |
test byte [eax + gif.Image.gce.Packed], 1 |
jz @f |
movzx ecx, byte [eax + gif.Image.gce.ColorIndex] |
mov [transparent_color], ecx |
cmp edx, ebx |
jnz .has_transparency |
shl ecx, 2 |
add ecx, [edx + Image.Palette] |
mov dword [background_color], 0xFFFFFF ; white background |
mov dword [ecx], 0xFFFFFF |
; mov esi, [_data] |
; test [esi+gif.Header.lsd.Packed], gif.LSD.Packed.GlobalColorTableFlag |
; jz @f |
; movzx ecx, [esi+gif.Header.lsd.BackgroundColor] |
; push ecx |
; shl ecx, 2 |
; add ecx, [edx + Image.Palette] |
; mov dword [ecx], 0xFFFFFF |
; pop ecx |
; lea ecx, [ecx*3] |
; add esi, ecx |
; mov byte [esi+sizeof.gif.Header+0], 0xFF |
; mov byte [esi+sizeof.gif.Header+1], 0xFF |
; mov byte [esi+sizeof.gif.Header+2], 0xFF |
@@: |
call img.decode.gif._.is_logical_screen |
jnz .has_transparency |
; image is not transparent, so keep it as is |
retn |
|
.has_transparency: |
; image has transparent areas, we must superimpose it on the previous |
mov ecx, [prev_num_colors] |
cmp ecx, 0x100 |
ja .superimpose_on_rgb |
; create common palette |
sub esp, 3FCh |
push eax |
mov edi, esp |
push ecx |
mov esi, [prev_palette] |
rep movsd |
pop ecx |
mov esi, [edx + Image.Palette] |
xor ebx, ebx |
mov edi, esp |
sub esp, 100h |
.create_palette_loop: |
push ecx |
lodsd |
cmp ebx, [transparent_color] |
jz .nochange |
cmp ebx, ecx |
jae @f |
cmp eax, [edi+ebx*4] |
jz .nochange |
@@: |
push edi |
repnz scasd |
pop edi |
jnz .increase_palette |
sub ecx, [esp] |
not ecx ; cl = index of new color in current palette |
jmp .palette_common |
.increase_palette: |
mov ecx, [esp] |
test ch, ch |
jnz .output_to_rgb |
inc dword [esp] |
mov [edi+ecx*4], eax |
jmp .palette_common |
.nochange: |
mov ecx, ebx |
.palette_common: |
mov [ebx+esp+4], cl |
pop ecx |
inc ebx |
cmp ebx, [max_color] |
jbe .create_palette_loop |
mov [max_color], ecx |
; if image occupies only part of logical screen, allocate memory for full logical screen |
mov ebx, [main_img] |
mov eax, [edx + Image.Extended] |
mov esi, [edx + Image.Data] |
call img.decode.gif._.is_logical_screen |
jz @f |
and [edx + Image.Data], 0 |
push edx |
movzx eax, [ebx + sizeof.gif.Image + gif.LogicalScreenDescriptor.ScreenHeight] |
push eax |
movzx eax, [ebx + sizeof.gif.Image + gif.LogicalScreenDescriptor.ScreenWidth] |
stdcall img._.resize_data, edx, eax |
pop edx |
test eax, eax |
jz .palette_nomem |
@@: |
; copy final palette to Image.Palette |
push esi esi |
mov esi, edi |
mov edi, [edx + Image.Palette] |
mov ecx, [max_color] |
dec [max_color] |
rep movsd |
mov esi, [prev_img_data] |
mov edi, [edx + Image.Data] |
; do superimpose, [esp] -> source data, esi -> prev image data |
; (NULL if previous image is filled with background color), esp+8 -> correspondence between |
; used palette and final palette, edi -> destination data |
mov ebx, [edx + Image.Extended] |
; first Top rows are copied from [prev_img_data] or filled with bgr |
movzx ecx, [ebx + gif.Image.info.Top] |
cmp ecx, [edx + Image.Height] |
jb @f |
mov ecx, [edx + Image.Height] |
@@: |
push ecx |
imul ecx, [edx + Image.Width] |
call .rep_movsb_or_stosb |
pop ecx |
; convert rows |
sub ecx, [edx + Image.Height] |
neg ecx |
push ecx |
cmp cx, [ebx + gif.Image.info.Height] |
jbe @f |
mov cx, [ebx + gif.Image.info.Height] |
@@: |
jecxz .norows |
.convert_rows: |
push ecx |
movzx ecx, [ebx + gif.Image.info.Left] |
cmp ecx, [edx + Image.Width] |
jb @f |
mov ecx, [edx + Image.Width] |
@@: |
push ecx |
call .rep_movsb_or_stosb |
pop ecx |
sub ecx, [edx + Image.Width] |
neg ecx |
push ecx edx |
mov edx, [esp+16] ; source data |
cmp cx, [ebx + gif.Image.info.Width] |
jbe @f |
mov cx, [ebx + gif.Image.info.Width] |
@@: |
jecxz .norowsi |
.rowsloop: |
movzx eax, byte [edx] |
inc edx |
cmp eax, [transparent_color] |
jz .rows_transparent |
mov al, [eax+esp+24] |
stosb |
call .lodsb |
jmp @f |
.rows_transparent: |
call .lodsb |
stosb |
@@: |
loop .rowsloop |
.norowsi: |
pop edx ecx |
sub cx, [ebx + gif.Image.info.Width] |
jbe @f |
call .rep_movsb_or_stosb |
@@: |
movzx eax, [ebx + gif.Image.info.Width] |
add [esp+8], eax |
pop ecx |
loop .convert_rows |
.norows: |
pop ecx |
sub cx, [ebx + gif.Image.info.Height] |
jbe @f |
imul ecx, [edx + Image.Width] |
call .rep_movsb_or_stosb |
@@: |
; free old image data if we have allocated new copy |
pop esi esi |
cmp esi, [edx + Image.Data] |
jz @f |
invoke mem.free, esi |
@@: |
; cleanup stack and return |
add esp, 500h |
retn |
.palette_nomem: |
mov [edx + Image.Data], esi |
jmp @b |
|
.output_to_rgb: |
pop ecx |
add esp, 500h |
; compose two palette-based images to one RGB image |
xor esi, esi |
xchg esi, [edx + Image.Data] |
push esi |
mov ebx, [_data] |
push [edx + Image.Palette] |
mov byte [edx + Image.Type], Image.bpp24 |
push edx |
movzx eax, [ebx + gif.Header.lsd.ScreenHeight] |
push eax |
movzx eax, [ebx + gif.Header.lsd.ScreenWidth] |
stdcall img._.resize_data, edx, eax |
pop edx |
test eax, eax |
jz .convrgb_nomem |
push esi |
mov edi, [edx + Image.Data] |
mov esi, [prev_img_data] |
mov ebx, [edx + Image.Extended] |
; first Top rows are copied from [prev_img_data] or filled with bgr |
movzx ecx, [ebx + gif.Image.info.Top] |
cmp ecx, [edx + Image.Height] |
jb @f |
mov ecx, [edx + Image.Height] |
@@: |
push ecx |
imul ecx, [edx + Image.Width] |
call .convrgb_prev |
pop ecx |
; convert rows |
sub ecx, [edx + Image.Height] |
neg ecx |
push ecx |
cmp cx, [ebx + gif.Image.info.Height] |
jbe @f |
mov cx, [ebx + gif.Image.info.Height] |
@@: |
jecxz .convrgb_norows |
.convrgb_convert_rows: |
push ecx |
movzx ecx, [ebx + gif.Image.info.Left] |
cmp ecx, [edx + Image.Width] |
jb @f |
mov ecx, [edx + Image.Width] |
@@: |
push ecx |
call .convrgb_prev |
pop ecx |
sub ecx, [edx + Image.Width] |
neg ecx |
push ecx edx |
mov edx, [esp+16] ; source data |
cmp cx, [ebx + gif.Image.info.Width] |
jbe @f |
mov cx, [ebx + gif.Image.info.Width] |
@@: |
jecxz .convrgb_norowsi |
.convrgb_rowsloop: |
movzx eax, byte [edx] |
inc edx |
cmp eax, [transparent_color] |
jz .convrgb_rows_transparent |
shl eax, 2 |
add eax, [esp+20] ; source palette |
mov eax, [eax] |
stosw |
shr eax, 16 |
stosb |
call .convrgb_lodsb |
jmp @f |
.convrgb_rows_transparent: |
call .convrgb_lodsb |
stosw |
shr eax, 16 |
stosb |
@@: |
loop .convrgb_rowsloop |
.convrgb_norowsi: |
pop edx ecx |
sub cx, [ebx + gif.Image.info.Width] |
jbe @f |
call .convrgb_prev |
@@: |
movzx eax, [ebx + gif.Image.info.Width] |
add [esp+8], eax |
pop ecx |
loop .convrgb_convert_rows |
.convrgb_norows: |
pop ecx |
sub cx, [ebx + gif.Image.info.Height] |
jbe @f |
imul ecx, [edx + Image.Width] |
call .convrgb_prev |
@@: |
; free old image data |
pop esi esi ;esi |
invoke mem.free;, esi |
retn |
.convrgb_nomem: |
pop esi esi |
retn |
|
.superimpose_on_rgb: |
; previous image is RGB, new image has transparent areas |
xor esi, esi |
xchg esi, [edx + Image.Data] |
push esi |
mov ebx, [_data] |
push [edx + Image.Palette] |
mov byte [edx + Image.Type], Image.bpp24 |
push edx |
movzx eax, [ebx + gif.Header.lsd.ScreenHeight] |
push eax |
movzx eax, [ebx + gif.Header.lsd.ScreenWidth] |
stdcall img._.resize_data, edx, eax |
pop edx |
test eax, eax |
jz .rgb_nomem |
push esi |
mov edi, [edx + Image.Data] |
mov esi, [prev_img_data] |
mov ebx, [edx + Image.Extended] |
; first Top rows are copied from [prev_img_data] or filled with bgr |
movzx ecx, [ebx + gif.Image.info.Top] |
cmp ecx, [edx + Image.Height] |
jb @f |
mov ecx, [edx + Image.Height] |
@@: |
push ecx |
lea ecx, [ecx*3] |
imul ecx, [edx + Image.Width] |
rep movsb |
pop ecx |
; convert rows |
sub ecx, [edx + Image.Height] |
neg ecx |
push ecx |
cmp cx, [ebx + gif.Image.info.Height] |
jbe @f |
mov cx, [ebx + gif.Image.info.Height] |
@@: |
jecxz .rgb_norows |
.rgb_convert_rows: |
push ecx |
movzx ecx, [ebx + gif.Image.info.Left] |
cmp ecx, [edx + Image.Width] |
jb @f |
mov ecx, [edx + Image.Width] |
@@: |
push ecx |
lea ecx, [ecx*3] |
rep movsb |
pop ecx |
sub ecx, [edx + Image.Width] |
neg ecx |
push ecx edx |
mov edx, [esp+16] ; source data |
cmp cx, [ebx + gif.Image.info.Width] |
jbe @f |
mov cx, [ebx + gif.Image.info.Width] |
@@: |
jecxz .rgb_norowsi |
.rgb_rowsloop: |
movzx eax, byte [edx] |
inc edx |
cmp eax, [transparent_color] |
jz .rgb_rows_transparent |
shl eax, 2 |
add eax, [esp+20] ; source palette |
mov eax, [eax] |
stosw |
shr eax, 16 |
stosb |
add esi, 3 |
jmp @f |
.rgb_rows_transparent: |
movsb |
movsb |
movsb |
@@: |
loop .rgb_rowsloop |
.rgb_norowsi: |
pop edx ecx |
sub cx, [ebx + gif.Image.info.Width] |
jbe @f |
lea ecx, [ecx*3] |
rep movsb |
@@: |
movzx eax, [ebx + gif.Image.info.Width] |
add [esp+8], eax |
pop ecx |
loop .rgb_convert_rows |
.rgb_norows: |
pop ecx |
sub cx, [ebx + gif.Image.info.Height] |
jbe @f |
imul ecx, [edx + Image.Width] |
lea ecx, [ecx*3] |
rep movsb |
@@: |
; free old image data |
pop esi esi ;esi |
invoke mem.free;, esi |
retn |
.rgb_nomem: |
pop esi esi |
retn |
|
.lodsb: |
xor eax, eax |
test esi, esi |
jz @f |
lodsb |
@@: retn |
|
.rep_movsb_or_stosb: |
test esi, esi |
jz .rmos1 |
rep movsb |
jmp .rmos2 |
.rmos1: xor eax, eax ; background index in final palette is 0 in bgr mode |
rep stosb |
.rmos2: retn |
|
.convrgb_prev: |
jecxz .convrgb_noprev |
test esi, esi |
jz .convrgb_prev_bgr |
@@: |
xor eax, eax |
lodsb |
shl eax, 2 |
add eax, [prev_palette] |
mov eax, [eax] |
stosw |
shr eax, 16 |
stosb |
loop @b |
retn |
.convrgb_prev_bgr: |
@@: |
mov eax, [background_color] |
stosw |
shr eax, 16 |
stosb |
loop @b |
.convrgb_noprev: |
retn |
.convrgb_lodsb: |
xor eax, eax |
test esi, esi |
jz @f |
lodsb |
shl eax, 2 |
add eax, [prev_palette] |
mov eax, [eax] |
retn |
@@: mov eax, [background_color] |
retn |
|
endp |
|
;;================================================================================================;; |
proc img.decode.gif._.dispose ;///////////////////////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? --- TBD --- ;; |
;;------------------------------------------------------------------------------------------------;; |
;> edx = image data ;; |
;;------------------------------------------------------------------------------------------------;; |
;< --- TBD --- ;; |
;;================================================================================================;; |
mov ebx, [edx + Image.Extended] |
mov al, [ebx + gif.Image.gce.Packed] |
shr al, 2 |
and al, 7 |
cmp al, 2 |
jz .background |
cmp al, 3 |
jz .previous |
; don't dispose - set prev_img and related vars to current image |
mov eax, [edx + Image.Data] |
mov [prev_img_data], eax |
cmp [edx + Image.Type], Image.bpp8 |
jnz @f |
mov eax, [max_color] |
inc eax |
mov [prev_num_colors], eax |
mov eax, [edx + Image.Palette] |
mov [prev_palette], eax |
retn |
@@: |
or [prev_num_colors], -1 |
and [prev_palette], 0 |
.previous: |
retn |
.background: |
cmp [prev_img_data], 0 |
jz .bgr_full |
mov ebx, [main_img] |
mov eax, [edx + Image.Extended] |
call img.decode.gif._.is_logical_screen |
jnz @f |
.bgr_full: |
xor eax, eax |
mov [prev_img_data], eax |
inc eax |
mov [prev_num_colors], eax |
lea eax, [background_color] |
mov [prev_palette], eax |
retn |
@@: |
cmp [prev_num_colors], 0x100 |
ja .rgb |
mov eax, [background_color] |
mov edi, [prev_palette] |
mov ecx, [prev_num_colors] |
repnz scasd |
jz .palette_ok |
cmp [prev_num_colors], 0x100 |
jz .convert_rgb |
push 1 |
pop eax |
stdcall img.decode.gif._.alloc_aux_img |
test eax, eax |
jz .previous |
mov ecx, [prev_num_colors] |
mov esi, [prev_palette] |
call img.decode.gif._.alloc_aux_palette |
test eax, eax |
jz .previous |
mov [prev_palette], eax |
mov eax, [background_color] |
stosd |
mov eax, [prev_num_colors] ; eax = index of background color |
inc [prev_num_colors] |
jmp .bpp8_common |
.palette_ok: |
push 1 |
pop eax |
stdcall img.decode.gif._.alloc_aux_img |
test eax, eax |
jz .previous |
sub edi, [prev_palette] |
shr edi, 2 |
lea eax, [edi-1] ; eax = index of background color |
.bpp8_common: |
push eax |
mov ebx, [_data] |
mov esi, [prev_img_data] |
mov edi, [aux_img_data] |
mov [prev_img_data], edi |
cmp esi, edi |
jz @f |
movzx ecx, [ebx + gif.Header.lsd.ScreenWidth] |
movzx eax, [ebx + gif.Header.lsd.ScreenHeight] |
imul ecx, eax |
push edi |
rep movsb |
pop edi |
@@: |
movzx esi, [ebx + gif.Header.lsd.ScreenHeight] |
movzx eax, [ebx + gif.Header.lsd.ScreenWidth] |
mov edx, [edx + Image.Extended] |
movzx ecx, [edx + gif.Image.info.Top] |
sub esi, ecx |
jbe .bpp8_ret |
imul ecx, eax |
add edi, ecx |
cmp si, [edx + gif.Image.info.Height] |
jb @f |
mov si, [edx + gif.Image.info.Height] |
@@: |
movzx ecx, [edx + gif.Image.info.Left] |
sub eax, ecx |
jbe .bpp8_ret |
add edi, ecx |
cmp ax, [edx + gif.Image.info.Width] |
jb @f |
mov ax, [edx + gif.Image.info.Width] |
@@: |
xchg eax, ecx |
movzx edx, [ebx + gif.Header.lsd.ScreenWidth] |
sub edx, ecx |
pop eax |
@@: |
push ecx |
rep stosb |
pop ecx |
add edi, edx |
dec esi |
jnz @b |
push eax |
.bpp8_ret: |
pop eax |
retn |
.convert_rgb: |
push 3 |
pop eax |
stdcall img.decode.gif._.alloc_aux_img |
test eax, eax |
jz .previous |
or [prev_num_colors], -1 |
mov ebx, [_data] |
mov esi, [prev_img_data] |
mov edi, [aux_img_data] |
mov [prev_img_data], edi |
movzx ecx, [ebx + gif.Header.lsd.ScreenWidth] |
movzx eax, [ebx + gif.Header.lsd.ScreenHeight] |
imul ecx, eax |
push edx |
xor edx, edx |
xchg edx, [prev_palette] |
add edi, ecx |
add esi, ecx |
add edi, ecx |
add edi, ecx |
@@: |
dec esi |
movzx eax, byte [esi] |
mov eax, [eax*4+edx] |
sub edi, 3 |
mov [edi], ax |
shr eax, 16 |
mov [edi+2], al |
loop @b |
pop edx |
movzx esi, [ebx + gif.Header.lsd.ScreenHeight] |
movzx eax, [ebx + gif.Header.lsd.ScreenWidth] |
mov edx, [edx + Image.Extended] |
movzx ecx, [edx + gif.Image.info.Top] |
sub esi, ecx |
jbe .convert_rgb_ret |
imul ecx, eax |
lea ecx, [ecx*3] |
add edi, ecx |
cmp si, [edx + gif.Image.info.Height] |
jb @f |
mov si, [edx + gif.Image.info.Height] |
@@: |
movzx ecx, [edx + gif.Image.info.Left] |
sub eax, ecx |
jbe .convert_rgb_ret |
lea ecx, [ecx*3] |
add edi, ecx |
cmp ax, [edx + gif.Image.info.Width] |
jb @f |
mov ax, [edx + gif.Image.info.Width] |
@@: |
xchg eax, ecx |
movzx edx, [ebx + gif.Header.lsd.ScreenWidth] |
sub edx, ecx |
mov eax, [background_color] |
lea edx, [edx*3] |
.convert_rgb_loop: |
push ecx |
@@: |
stosw |
shr eax, 16 |
stosb |
loop @b |
pop ecx |
add edi, edx |
dec esi |
jnz .convert_rgb_loop |
.convert_rgb_ret: |
retn |
.rgb: |
push 3 |
pop eax |
stdcall img.decode.gif._.alloc_aux_img |
test eax, eax |
jz .previous |
or [prev_num_colors], -1 |
and [prev_palette], 0 |
mov ebx, [_data] |
mov esi, [prev_img_data] |
mov edi, [aux_img_data] |
mov [prev_img_data], edi |
cmp esi, edi |
jz @f |
movzx ecx, [ebx + gif.Header.lsd.ScreenHeight] |
push ecx |
movzx eax, [ebx + gif.Header.lsd.ScreenWidth] |
imul ecx, eax |
lea ecx, [ecx*3] |
push edi |
rep movsb |
pop edi |
pop esi |
mov edx, [edx + Image.Extended] |
movzx ecx, [edx + gif.Image.info.Top] |
sub esi, ecx |
jbe .rgb_ret |
imul ecx, eax |
lea ecx, [ecx*3] |
add edi, ecx |
cmp si, [edx + gif.Image.info.Height] |
jb @f |
mov si, [edx + gif.Image.info.Height] |
@@: |
movzx ecx, [edx + gif.Image.info.Left] |
sub eax, ecx |
jbe .rgb_ret |
lea ecx, [ecx*3] |
add edi, ecx |
cmp ax, [edx + gif.Image.info.Width] |
jb @f |
mov ax, [edx + gif.Image.info.Width] |
@@: |
xchg eax, ecx |
movzx edx, [ebx + gif.Header.lsd.ScreenWidth] |
sub edx, ecx |
mov eax, [background_color] |
lea edx, [edx*3] |
.rgb_loop: |
push ecx |
@@: |
stosw |
shr eax, 16 |
stosb |
loop @b |
pop ecx |
add edi, edx |
dec esi |
jnz .rgb_loop |
.rgb_ret: |
retn |
|
endp |
|
;;================================================================================================;; |
proc img.decode.gif._.alloc_aux_img ;/////////////////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? Allocate auxiliary memory for previous image ;; |
;;------------------------------------------------------------------------------------------------;; |
;> eax = image type: 1 = bpp8, 3 = bpp24 ;; |
;;------------------------------------------------------------------------------------------------;; |
;< eax = [aux_img_data] ;; |
;;================================================================================================;; |
cmp [aux_img_type], eax |
jae @f |
push edx eax |
movzx ecx, [ebx + sizeof.gif.Image + gif.LogicalScreenDescriptor.ScreenWidth] |
mul ecx |
movzx ecx, [ebx + sizeof.gif.Image + gif.LogicalScreenDescriptor.ScreenHeight] |
mul ecx |
invoke mem.realloc, [aux_img_data], eax |
pop ecx edx |
test eax, eax |
jz @f |
mov [aux_img_type], ecx |
mov [aux_img_data], eax |
@@: retn |
|
endp |
|
;;================================================================================================;; |
proc img.decode.gif._.alloc_aux_palette ;/////////////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? Allocate and fill aux_palette ;; |
;;------------------------------------------------------------------------------------------------;; |
;> esi -> palette, ecx = palette size ;; |
;;------------------------------------------------------------------------------------------------;; |
;< [aux_palette] set ;; |
;;================================================================================================;; |
mov eax, [aux_palette] |
test eax, eax |
jnz @f |
push edx ecx |
invoke mem.alloc, 0x400 |
pop ecx edx |
test eax, eax |
jz .ret |
mov [aux_palette], eax |
@@: |
mov edi, eax |
rep movsd |
.ret: |
retn |
|
endp |
|
restore main_img |
restore transparent_color |
restore background_color |
restore prev_num_colors |
restore prev_palette |
restore max_color |
restore prev_img_data |
restore _data |
restore aux_img_data |
restore aux_img_type |
restore aux_palette |
|
;;================================================================================================;; |
;;////////////////////////////////////////////////////////////////////////////////////////////////;; |
;;================================================================================================;; |
;! Below is private data you should never use directly from your code ;; |