forked from KolibriOS/kolibrios
Ivan Baravy
201cf02d85
img.convert doesn't make opaque pixels transparent. gif decoder considers palette pixels opaque. git-svn-id: svn://kolibrios.org@8394 a494cfbc-eb01-0410-851d-a64ba20cac60
1585 lines
43 KiB
NASM
1585 lines
43 KiB
NASM
;;================================================================================================;;
|
|
;;//// gif.asm //// (c) mike.dld, 2007-2008 //////////////////////////////////////////////////////;;
|
|
;;================================================================================================;;
|
|
;;//// Partial (c) by Willow, Diamond and HidnPlayr //////////////////////////////////////////////;;
|
|
;;================================================================================================;;
|
|
;; ;;
|
|
;; 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. GIF LITE v3.0 (2004-2007) ;;
|
|
;; by Willow and Diamond ;;
|
|
;; svn://kolibrios.org/programs/media/gifview/trunk/gif_lite.inc ;;
|
|
;; 2. "GIF File Format Summary" ;;
|
|
;; from "Encyclopedia of Graphics File Formats" by O'Reilly ;;
|
|
;; http://www.fileformat.info/format/gif/ ;;
|
|
;; 3. "LZW and GIF explained" (1987) ;;
|
|
;; by Steve Blackstock, IEEE ;;
|
|
;; http://www.cis.udel.edu/~amer/CISC651/lzw.and.gif.explained.html ;;
|
|
;; 4. "Graphics Interchange Format (tm)" (June 15, 1987) ;;
|
|
;; by CompuServe Incorporated ;;
|
|
;; http://examples.oreilly.de/english_examples/gff/CDROM/GFF/VENDSPEC/GIF/GIF87A.TXT ;;
|
|
;; 5. "Graphics Interchange Format (sm)" (July 31, 1990) ;;
|
|
;; by CompuServe Incorporated ;;
|
|
;; http://examples.oreilly.de/english_examples/gff/CDROM/GFF/VENDSPEC/GIF/GIF89A.TXT ;;
|
|
;; ;;
|
|
;;================================================================================================;;
|
|
|
|
|
|
include 'gif.inc'
|
|
|
|
;;================================================================================================;;
|
|
proc img.is.gif _data, _length ;//////////////////////////////////////////////////////////////////;;
|
|
;;------------------------------------------------------------------------------------------------;;
|
|
;? Determine if raw data could be decoded (is in GIF format) ;;
|
|
;;------------------------------------------------------------------------------------------------;;
|
|
;> _data = raw data as read from file/stream ;;
|
|
;> _length = data length ;;
|
|
;;------------------------------------------------------------------------------------------------;;
|
|
;< eax = false / true ;;
|
|
;;================================================================================================;;
|
|
cmp [_length], sizeof.gif.Header
|
|
jb .nope
|
|
mov eax, [_data]
|
|
cmp dword[eax], 'GIF8'
|
|
jne .nope
|
|
cmp word[eax + 4], '7a'
|
|
je .yep
|
|
cmp word[eax + 4], '9a'
|
|
je .yep
|
|
|
|
.nope:
|
|
xor eax, eax
|
|
ret
|
|
|
|
.yep:
|
|
xor eax, eax
|
|
inc eax
|
|
ret
|
|
endp
|
|
|
|
;;================================================================================================;;
|
|
proc img.decode.gif _data, _length, _options ;////////////////////////////////////////////////////;;
|
|
;;------------------------------------------------------------------------------------------------;;
|
|
;? Decode data into image if it contains correctly formed raw data in GIF format ;;
|
|
;;------------------------------------------------------------------------------------------------;;
|
|
;> _data = raw data as read from file/stream ;;
|
|
;> _length = data length ;;
|
|
;;------------------------------------------------------------------------------------------------;;
|
|
;< eax = 0 (error) or pointer to image ;;
|
|
;;================================================================================================;;
|
|
locals
|
|
max_color dd ?
|
|
cur_color_table_size dd ?
|
|
transparent_color dd ?
|
|
background_color dd ?
|
|
options_bgr 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
|
|
|
|
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
|
|
img.decode.gif.options_bgr equ options_bgr
|
|
; offset of _length parameter for child functions with ebp-based frame
|
|
; child saved ebp, return address, 3 saved registers, 15 local variables
|
|
img.decode.gif._length_child equ _length + 4 + 4 + 4*3 + 4*15
|
|
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
|
|
; value for bgr color in transparent images
|
|
mov edx, 0xFFFFFF ; white bgr if no value given
|
|
mov ecx, [_options]
|
|
jecxz @f
|
|
cmp [ecx + ImageDecodeOptions.UsedSize], ImageDecodeOptions.BackgroundColor + 4
|
|
jb @f
|
|
mov edx, [ecx + ImageDecodeOptions.BackgroundColor]
|
|
@@:
|
|
mov [options_bgr], edx
|
|
mov dword [eax], edx
|
|
; 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 ebx, [_data]
|
|
sub [_length], sizeof.gif.Header
|
|
|
|
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 ; 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
|
|
@@:
|
|
|
|
; @@: cmp byte[ebx + gif.Block.Introducer], gif.Block.Introducer.Extension
|
|
; jne .next_image
|
|
; cmp byte[ebx + gif.Extension.Label], gif.Extension.Label.Comment
|
|
; jne .error
|
|
; add ebx, sizeof.gif.Extension
|
|
; stdcall ._.skip_data
|
|
; mov ebx, eax
|
|
; jmp @b
|
|
|
|
.next_image:
|
|
stdcall img._.new
|
|
or eax, eax
|
|
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
|
|
@@:
|
|
push eax
|
|
mov [eax + Image.Type], Image.bpp8i
|
|
|
|
add ecx, sizeof.gif.Image
|
|
invoke mem.alloc, ecx
|
|
pop edx
|
|
or eax, eax
|
|
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 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
|
|
|
|
mov esi, ebx
|
|
mov edi, [edx + Image.Extended]
|
|
mov ecx, sizeof.gif.ImageDescriptor
|
|
rep movsb
|
|
|
|
mov edi, [edx + Image.Palette]
|
|
mov esi, [global_color_table]
|
|
mov ecx, [global_color_table_size]
|
|
test [ebx + gif.ImageDescriptor.Packed], gif.ID.Packed.LocalColorTableFlag
|
|
jz @f
|
|
lea esi, [ebx + sizeof.gif.ImageDescriptor]
|
|
mov cl, [ebx + gif.ImageDescriptor.Packed]
|
|
and cl, gif.ID.Packed.SizeOfLocalColorTableMask
|
|
; 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
|
|
mov al, 0xff ; opaque
|
|
ror eax, 8
|
|
stosd
|
|
loop @b
|
|
add ebx, sizeof.gif.ImageDescriptor
|
|
stdcall ._.process_image
|
|
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 [edx + Image.Delay], 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.bpp8i
|
|
jz @f
|
|
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
|
|
|
|
.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
|
|
invoke mem.free, eax
|
|
@@:
|
|
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
|
|
|
|
;;================================================================================================;;
|
|
proc img.encode.gif _img, _p_length ;/////////////////////////////////////////////////////////////;;
|
|
;;------------------------------------------------------------------------------------------------;;
|
|
;? Encode image into raw data in GIF 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 ;;
|
|
;;================================================================================================;;
|
|
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
|
|
;;================================================================================================;;
|
|
|
|
|
|
;;================================================================================================;;
|
|
proc img.decode.gif._.process_extensions ;////////////////////////////////////////////////////////;;
|
|
;;------------------------------------------------------------------------------------------------;;
|
|
;? --- TBD --- ;;
|
|
;;------------------------------------------------------------------------------------------------;;
|
|
;> ebx = raw image data ;;
|
|
;> edx = image data ;;
|
|
;;------------------------------------------------------------------------------------------------;;
|
|
;< --- TBD --- ;;
|
|
;;================================================================================================;;
|
|
mov esi, ebx
|
|
xor eax, eax
|
|
mov [edx + Image.Delay], eax
|
|
|
|
.next_block:
|
|
dec [img.decode.gif._length]
|
|
js .exit_err
|
|
lodsb ; load gif.Block.Introducer
|
|
cmp al, gif.Block.Introducer.Extension
|
|
jne .exit
|
|
|
|
.ext_block:
|
|
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.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
|
|
|
|
.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, eax
|
|
rep movsb
|
|
pop edi
|
|
jmp .skip_ext
|
|
|
|
.exit_err:
|
|
xor eax, eax
|
|
|
|
.exit:
|
|
mov ebx, esi
|
|
ret
|
|
endp
|
|
|
|
;;================================================================================================;;
|
|
proc img.decode.gif._.process_image ;/////////////////////////////////////////////////////////////;;
|
|
;;------------------------------------------------------------------------------------------------;;
|
|
;? --- TBD --- ;;
|
|
;;------------------------------------------------------------------------------------------------;;
|
|
;> ebx = raw image data ;;
|
|
;> edx = image data ;;
|
|
;;------------------------------------------------------------------------------------------------;;
|
|
;< --- TBD --- ;;
|
|
;;================================================================================================;;
|
|
locals
|
|
width dd ?
|
|
img_start dd ?
|
|
img_end dd ?
|
|
row_end dd ?
|
|
pass dd ?
|
|
codesize dd ?
|
|
compsize dd ?
|
|
workarea dd ?
|
|
block_ofs dd ?
|
|
bit_count dd ?
|
|
CC dd ?
|
|
EOI dd ?
|
|
endl
|
|
|
|
invoke mem.alloc, 16 * 1024
|
|
mov [workarea], eax
|
|
or eax, eax
|
|
jz .error
|
|
|
|
mov ecx, [edx + Image.Width]
|
|
mov [width], ecx
|
|
mov eax, [edx + Image.Height]
|
|
imul eax, ecx
|
|
mov [img_end], eax
|
|
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
|
|
mov [row_end], ecx
|
|
|
|
@@: mov esi, ebx
|
|
mov edi, [edx + Image.Data]
|
|
|
|
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]
|
|
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
|
|
shl eax, cl
|
|
mov [CC], eax
|
|
mov ecx, eax
|
|
inc eax
|
|
mov [EOI], eax
|
|
mov eax, gif.Null shl 16
|
|
.filltable:
|
|
stosd
|
|
inc eax
|
|
loop .filltable
|
|
pop edi
|
|
mov [img_start], edi
|
|
add [img_end], edi
|
|
add [row_end], edi
|
|
.reinit:
|
|
mov edx, [EOI]
|
|
inc edx
|
|
push [codesize]
|
|
pop [compsize]
|
|
call .get_symbol
|
|
cmp eax, [CC]
|
|
je .reinit
|
|
call .output
|
|
.cycle:
|
|
movzx ebx, ax
|
|
call .get_symbol
|
|
cmp eax, [EOI]
|
|
je .end
|
|
cmp eax, edx
|
|
ja .error
|
|
je .notintable
|
|
cmp eax, [CC]
|
|
je .reinit
|
|
call .output
|
|
.add:
|
|
cmp edx, 0x00001000
|
|
jae .cycle
|
|
mov ecx, [workarea]
|
|
mov [ecx + edx * 4], ebx
|
|
inc edx
|
|
cmp edx, 0x1000
|
|
je .noinc
|
|
bsr ebx, edx
|
|
cmp ebx, [compsize]
|
|
jne .noinc
|
|
inc [compsize]
|
|
.noinc:
|
|
jmp .cycle
|
|
.notintable:
|
|
push eax
|
|
mov eax, ebx
|
|
call .output
|
|
push ebx
|
|
movzx eax, bx
|
|
call .output
|
|
pop ebx eax
|
|
jmp .add
|
|
.end:
|
|
mov edi, [img_end]
|
|
xor eax, eax
|
|
|
|
.exit:
|
|
cmp [workarea], 0
|
|
je @f
|
|
invoke mem.free, [workarea]
|
|
@@:
|
|
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 ebx, ebx
|
|
.ret:
|
|
ret
|
|
|
|
;;------------------------------------------------------------------------------------------------;;
|
|
|
|
img.decode.gif._.process_image.get_symbol:
|
|
mov ecx, [compsize]
|
|
push ecx
|
|
xor eax, eax
|
|
|
|
.shift:
|
|
dec [bit_count]
|
|
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
|
|
.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], 7
|
|
|
|
.loop1:
|
|
ror byte[esi], 1
|
|
rcr eax,1
|
|
loop .shift
|
|
pop ecx
|
|
rol eax, cl
|
|
|
|
.exit:
|
|
xor ecx, ecx
|
|
retn
|
|
|
|
;;------------------------------------------------------------------------------------------------;;
|
|
|
|
img.decode.gif._.process_image.output:
|
|
push esi eax edx
|
|
mov edx, [workarea]
|
|
|
|
.next:
|
|
pushw [edx + eax * 4]
|
|
mov ax, [edx + eax * 4 + 2]
|
|
inc ecx
|
|
cmp ax, gif.Null
|
|
jnz .next
|
|
shl ebx, 16
|
|
mov bx, [esp]
|
|
|
|
.loop2:
|
|
pop ax
|
|
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, [row_end]
|
|
jb .norowend
|
|
mov eax, [width]
|
|
push eax
|
|
sub edi, eax
|
|
add eax, eax
|
|
cmp [pass], 3
|
|
je @f
|
|
add eax, eax
|
|
cmp [pass], 2
|
|
je @f
|
|
add eax, eax
|
|
@@: add edi, eax
|
|
pop eax
|
|
cmp edi, [img_end]
|
|
jb .nextrow
|
|
mov edi, [img_start]
|
|
inc [pass]
|
|
cmp [pass], 4
|
|
je .done
|
|
add edi, eax
|
|
cmp [pass], 3
|
|
je @f
|
|
add edi, eax
|
|
cmp [pass], 2
|
|
je @f
|
|
add edi, eax
|
|
add edi, eax
|
|
@@:
|
|
|
|
.nextrow:
|
|
add eax, edi
|
|
mov [row_end], eax
|
|
xor eax, eax
|
|
|
|
.norowend:
|
|
cmp edi, [img_end]
|
|
jz .done
|
|
loop .loop2
|
|
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]
|
|
push eax
|
|
mov eax, [img.decode.gif.options_bgr]
|
|
mov dword [background_color], eax
|
|
mov dword [ecx], eax
|
|
pop eax
|
|
@@:
|
|
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.bpp8i
|
|
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 ;;
|
|
;;================================================================================================;;
|
|
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
|
|
;;================================================================================================;;
|
|
|
|
|
|
;
|