Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 1078 → Rev 1079

/programs/develop/libraries/libs-dev/libimg/gif/gif.asm
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 ;;