/programs/develop/libraries/libs-dev/libimg/bmp/bmp.asm |
---|
102,8 → 102,7 |
jnz .error |
; convert images with <= 8 bpp to 8bpp, other - to 32 bpp |
.normal: |
xor eax, eax |
inc eax ; Image.bpp8 |
m2m eax, Image.bpp8 |
cmp [ebx + bmp.Header.info.BitCount], 8 |
jbe @f |
mov al, Image.bpp32 |
119,8 → 118,7 |
pushd [ebx + bmp.Header.info.Width] |
jmp .create |
.old1: |
xor eax, eax |
inc eax ; Image.bpp8 |
m2m eax, Image.bpp8 |
cmp [ebx + bmp.Header.info.OldBitCount], 8 |
jbe @f |
mov al, Image.bpp32 |
/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 ;; |
/programs/develop/libraries/libs-dev/libimg/gif/gif.inc |
---|
61,7 → 61,9 |
gif.Block.Introducer.EndOfFile = 0x3B |
struct gif.ImageDescriptor ; GIF87a |
b gif.Block ; Introducer = 2Ch (',') |
; we read Introducer before parsing gif.ImageDescriptor, |
; so it is convenient to not include it in struct |
; b gif.Block ; Introducer = 2Ch (',') |
Left dw ? ; X position of image on the display |
Top dw ? ; Y position of image on the display |
Width dw ? ; Width of the image in pixels |
89,8 → 91,8 |
gif.Extension.Label.Application = 0xFF |
struct gif.PlainTextExtension ; GIF89a |
e gif.Extension ; Label = 01h |
BlockSize db ? ; Size of Extension Block (always 0Ch) |
; e gif.Extension ; Label = 01h |
; BlockSize db ? ; Size of Extension Block (always 0Ch) |
TextGridLeft dw ? ; X position of text grid in pixels |
TextGridTop dw ? ; Y position of text grid in pixels |
TextGridWidth dw ? ; Width of the text grid in pixels |
104,8 → 106,10 |
ends |
struct gif.GraphicsControlExtension ; GIF89a |
e gif.Extension ; Label = F9h |
BlockSize db ? ; Size of remaining fields (always 04h) |
; e gif.Extension ; Label = F9h |
; BlockSize db ? ; Size of remaining fields (always 04h) |
; previous fields are not included in this structure for convenience |
; (they are parsed before this) |
Packed db ? ; Method of graphics disposal to use |
DelayTime dw ? ; Hundredths of seconds to wait |
ColorIndex db ? ; Transparent Color Index |
130,8 → 134,9 |
;;------------------------------------------------------------------------------------------------;; |
struct gif.Image |
info gif.ImageDescriptor |
gce gif.GraphicsControlExtension |
info gif.ImageDescriptor |
; lsd gif.LogicalScreenDescriptor ; saved only in first image |
ends |
gif.Null equ 0x1000 |
/programs/develop/libraries/libs-dev/libimg/jpeg/jpeg.asm |
---|
474,8 → 474,8 |
; image type: 8 bpp for grayscale JPEGs, 24 bpp for normal, |
; 32 bpp for Adobe YCCK |
push Image.bpp8 |
pop eax |
cmp edi, 1 |
pop eax ; Image.bpp8 = 1 |
cmp edi, eax |
jz @f |
inc eax ; Image.bpp24 = 2 |
cmp edi, 3 |
1621,9 → 1621,9 |
stosd ; dd VFactor_i+1 - (height % VFactor_i) |
pop ecx |
xor eax, eax |
cmp ebp, 1 |
cmc |
rcr eax, 1 |
test ebp, ebp |
setnp al |
ror eax, 1 |
stosd ; dd DCPrediction |
mov eax, ebp |
stosd ; dd ComponentOffset |
/programs/develop/libraries/libs-dev/libimg/libimg.asm |
---|
35,12 → 35,9 |
include 'gif/gif.asm' |
include 'jpeg/jpeg.asm' |
include 'png/png.asm' |
include 'tga/tga.asm' |
include 'z80/z80.asm' |
mem.alloc dd ? |
mem.free dd ? |
mem.realloc dd ? |
dll.load dd ? |
;;================================================================================================;; |
proc lib_init ;///////////////////////////////////////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
60,6 → 57,14 |
call img.initialize.jpeg |
xor eax, eax |
cpuid |
cmp ecx, 'ntel' |
jnz @f |
mov dword [img._.do_rgb.handlers + (Image.bpp15-1)*4], img._.do_rgb.bpp15.intel |
mov dword [img._.do_rgb.handlers + (Image.bpp16-1)*4], img._.do_rgb.bpp16.intel |
@@: |
.ok: xor eax,eax |
ret |
endp |
211,26 → 216,257 |
mov ecx, [esi + Image.Width] |
imul ecx, [esi + Image.Height] |
mov eax, [esi + Image.Type] |
dec eax |
jz .bpp8 |
dec eax |
jz .bpp24 |
; 32 BPP -> 24 BPP |
jmp dword [.handlers + (eax-1)*4] |
align 16 |
.bpp8: |
; 8 BPP -> 24 BPP |
push ebx |
mov ebx, [esi + Image.Palette] |
mov esi, [esi + Image.Data] |
@@: |
movzx eax, byte [esi] |
add esi, 1 |
mov eax, [ebx + eax*4] |
mov [edi], eax |
add edi, 3 |
sub ecx, 1 |
jnz @b |
pop ebx |
ret |
; 15 BPP -> 24 BPP |
.bpp15.intel: |
push ebx ebp |
sub ecx, 4 |
jb .bpp15.tail |
align 16 |
.bpp15.intel.loop: |
repeat 2 |
mov ebx, [esi] |
mov al, [esi] |
mov ah, [esi+1] |
add esi, 4 |
and al, 0x1F |
and ah, 0x1F shl 2 |
mov ebp, ebx |
mov dl, al |
mov dh, ah |
shr al, 2 |
shr ah, 4 |
shl dl, 3 |
shl dh, 1 |
and ebp, 0x1F shl 5 |
add al, dl |
add ah, dh |
shr ebp, 2 |
mov [edi], al |
mov [edi+2], ah |
mov eax, ebx |
mov ebx, ebp |
shr eax, 16 |
shr ebx, 5 |
add ebx, ebp |
mov ebp, eax |
mov [edi+1], bl |
and eax, (0x1F) or (0x1F shl 10) |
and ebp, 0x1F shl 5 |
lea edx, [eax+eax] |
shr al, 2 |
mov ebx, ebp |
shr ah, 4 |
shl dl, 2 |
shr ebx, 2 |
shr ebp, 7 |
add al, dl |
add ah, dh |
mov [edi+3], al |
add ebx, ebp |
mov [edi+5], ah |
mov [edi+4], bl |
add edi, 6 |
end repeat |
sub ecx, 4 |
jnb .bpp15.intel.loop |
.bpp15.tail: |
add ecx, 4 |
jz .bpp15.done |
@@: |
mov eax, [esi] |
mov [edi], ax |
shr eax, 16 |
mov [edi+2], al |
add esi, 4 |
movzx eax, word [esi] |
mov ebx, eax |
add esi, 2 |
and eax, (0x1F) or (0x1F shl 10) |
and ebx, 0x1F shl 5 |
lea edx, [eax+eax] |
shr al, 2 |
mov ebp, ebx |
shr ebx, 2 |
shr ah, 4 |
shl dl, 2 |
shr ebp, 7 |
add eax, edx |
add ebx, ebp |
mov [edi], al |
mov [edi+1], bl |
mov [edi+2], ah |
add edi, 3 |
sub ecx, 1 |
jnz @b |
.bpp15.done: |
pop ebp ebx |
ret |
.bpp15.amd: |
push ebx ebp |
sub ecx, 4 |
jb .bpp15.tail |
align 16 |
.bpp15.amd.loop: |
repeat 4 |
if (% mod 2) = 1 |
mov eax, dword [esi] |
mov ebx, dword [esi] |
else |
movzx eax, word [esi] |
mov ebx, eax |
end if |
add esi, 2 |
and eax, (0x1F) or (0x1F shl 10) |
and ebx, 0x1F shl 5 |
lea edx, [eax+eax] |
shr al, 2 |
mov ebp, ebx |
shr ebx, 2 |
shr ah, 4 |
shl dl, 2 |
shr ebp, 7 |
add eax, edx |
add ebx, ebp |
mov [edi], al |
mov [edi+1], bl |
mov [edi+2], ah |
add edi, 3 |
end repeat |
sub ecx, 4 |
jnb .bpp15.amd.loop |
jmp .bpp15.tail |
; 16 BPP -> 24 BPP |
.bpp16.intel: |
push ebx ebp |
sub ecx, 4 |
jb .bpp16.tail |
align 16 |
.bpp16.intel.loop: |
repeat 2 |
mov ebx, [esi] |
mov al, [esi] |
mov ah, [esi+1] |
add esi, 4 |
and al, 0x1F |
and ah, 0x1F shl 3 |
mov ebp, ebx |
mov dl, al |
mov dh, ah |
shr al, 2 |
shr ah, 5 |
shl dl, 3 |
and ebp, 0x3F shl 5 |
add al, dl |
add ah, dh |
shr ebp, 3 |
mov [edi], al |
mov [edi+2], ah |
mov eax, ebx |
mov ebx, ebp |
shr eax, 16 |
shr ebx, 6 |
add ebx, ebp |
mov ebp, eax |
mov [edi+1], bl |
and eax, (0x1F) or (0x1F shl 11) |
and ebp, 0x3F shl 5 |
mov edx, eax |
shr al, 2 |
mov ebx, ebp |
shr ah, 5 |
shl dl, 3 |
shr ebx, 3 |
shr ebp, 9 |
add al, dl |
add ah, dh |
mov [edi+3], al |
add ebx, ebp |
mov [edi+5], ah |
mov [edi+4], bl |
add edi, 6 |
end repeat |
sub ecx, 4 |
jnb .bpp16.intel.loop |
.bpp16.tail: |
add ecx, 4 |
jz .bpp16.done |
@@: |
movzx eax, word [esi] |
mov ebx, eax |
add esi, 2 |
and eax, (0x1F) or (0x1F shl 11) |
and ebx, 0x3F shl 5 |
mov edx, eax |
shr al, 2 |
mov ebp, ebx |
shr ebx, 3 |
shr ah, 5 |
shl dl, 3 |
shr ebp, 9 |
add eax, edx |
add ebx, ebp |
mov [edi], al |
mov [edi+1], bl |
mov [edi+2], ah |
add edi, 3 |
sub ecx, 1 |
jnz @b |
.bpp16.done: |
pop ebp ebx |
ret |
.bpp16.amd: |
push ebx ebp |
sub ecx, 4 |
jb .bpp16.tail |
align 16 |
.bpp16.amd.loop: |
repeat 4 |
if (% mod 2) = 1 |
mov eax, dword [esi] |
mov ebx, dword [esi] |
else |
movzx eax, word [esi] |
mov ebx, eax |
end if |
add esi, 2 |
and eax, (0x1F) or (0x1F shl 11) |
and ebx, 0x3F shl 5 |
mov edx, eax |
shr al, 2 |
mov ebp, ebx |
shr ebx, 3 |
shr ah, 5 |
shl dl, 3 |
shr ebp, 9 |
add eax, edx |
add ebx, ebp |
mov [edi], al |
mov [edi+1], bl |
mov [edi+2], ah |
add edi, 3 |
end repeat |
sub ecx, 4 |
jnb .bpp16.amd.loop |
jmp .bpp16.tail |
align 16 |
.bpp24: |
; 24 BPP -> 24 BPP |
lea ecx, [ecx*3 + 3] |
239,23 → 475,24 |
rep movsd |
ret |
.bpp8: |
; 8 BPP -> 24 BPP |
push ebx |
mov ebx, [esi + Image.Palette] |
align 16 |
.bpp32: |
; 32 BPP -> 24 BPP |
mov esi, [esi + Image.Data] |
@@: |
movzx eax, byte [esi] |
add esi, 1 |
mov eax, [ebx + eax*4] |
mov eax, [esi] |
mov [edi], ax |
shr eax, 16 |
mov [edi+2], al |
add esi, 4 |
add edi, 3 |
sub ecx, 1 |
jnz @b |
pop ebx |
@@: |
ret |
endp |
;;================================================================================================;; |
335,6 → 572,32 |
endp |
;;================================================================================================;; |
proc img.destroy.layer _img ;/////////////////////////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? --- TBD --- ;; |
;;------------------------------------------------------------------------------------------------;; |
;> --- TBD --- ;; |
;;------------------------------------------------------------------------------------------------;; |
;< eax = false / true ;; |
;;================================================================================================;; |
mov eax, [_img] |
mov edx, [eax + Image.Previous] |
test edx, edx |
jz @f |
push [eax + Image.Next] |
pop [edx + Image.Next] |
@@: |
mov edx, [eax + Image.Next] |
test edx, edx |
jz @f |
push [eax + Image.Previous] |
pop [edx + Image.Previous] |
@@: |
stdcall img._.delete, eax |
ret |
endp |
;;================================================================================================;; |
proc img.destroy _img ;///////////////////////////////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? --- TBD --- ;; |
343,8 → 606,33 |
;;------------------------------------------------------------------------------------------------;; |
;< eax = false / true ;; |
;;================================================================================================;; |
;TODO: link Next and Previous |
stdcall img._.delete, [_img] |
push 1 |
mov eax, [_img] |
mov eax, [eax + Image.Previous] |
.destroy_prev_loop: |
test eax, eax |
jz .destroy_prev_done |
pushd [eax + Image.Previous] |
stdcall img._.delete, eax |
test eax, eax |
jnz @f |
mov byte [esp+4], 0 |
@@: |
pop eax |
jmp .destroy_prev_loop |
.destroy_prev_done: |
mov eax, [_img] |
.destroy_next_loop: |
pushd [eax + Image.Next] |
stdcall img._.delete, eax |
test eax, eax |
jnz @f |
mov byte [esp+4], 0 |
@@: |
pop eax |
test eax, eax |
jnz .destroy_next_loop |
pop eax |
ret |
endp |
417,9 → 705,9 |
endp |
;;================================================================================================;; |
proc img.flip _img, _flip_kind ;//////////////////////////////////////////////////////////////////;; |
proc img.flip.layer _img, _flip_kind ;////////////////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? Flip image ;; |
;? Flip image layer ;; |
;;------------------------------------------------------------------------------------------------;; |
;> _img = pointer to image ;; |
;> _flip_kind = one of FLIP_* constants ;; |
493,12 → 781,9 |
mov esi, [ebx + Image.Data] |
mov edi, [scanline_len] |
add edi, esi |
jmp dword [.handlers_horz + (eax-1)*4] |
dec eax |
jz .bpp8.2 |
dec eax |
jz .bpp24.2 |
.bpp32_horz: |
sub edi, 4 |
.next_line_horz: |
521,7 → 806,29 |
jnz .next_line_horz |
jmp .exit |
.bpp8.2: |
.bpp1x_horz: |
sub edi, 2 |
.next_line_horz1x: |
push ecx esi edi |
mov ecx, [ebx + Image.Width] |
@@: mov ax, [esi] |
mov dx, [edi] |
mov [edi], ax |
mov [esi], dx |
add esi, 2 |
sub edi, 2 |
sub ecx, 2 |
ja @b |
pop edi esi ecx |
add esi, [scanline_len] |
add edi, [scanline_len] |
dec ecx |
jnz .next_line_horz1x |
jmp .exit |
.bpp8_horz: |
dec edi |
.next_line_horz8: |
push ecx esi edi |
544,13 → 851,12 |
jnz .next_line_horz8 |
jmp .exit |
.bpp24.2: |
.bpp24_horz: |
sub edi, 3 |
.next_line_horz32: |
.next_line_horz24: |
push ecx esi edi |
mov ecx, [ebx + Image.Width] |
shr ecx, 1 |
@@: |
mov al, [esi] |
mov dl, [edi] |
566,14 → 872,14 |
mov [esi+2], dl |
add esi, 3 |
sub edi, 3 |
sub ecx, 1 |
jnz @b |
sub ecx, 2 |
ja @b |
pop edi esi ecx |
add esi, [scanline_len] |
add edi, [scanline_len] |
dec ecx |
jnz .next_line_horz32 |
jnz .next_line_horz24 |
.exit: |
xor eax, eax |
588,11 → 894,42 |
endp |
;;================================================================================================;; |
proc img.rotate _img, _rotate_kind ;//////////////////////////////////////////////////////////////;; |
proc img.flip _img, _flip_kind ;//////////////////////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? Rotate image ;; |
;? Flip all layers of image ;; |
;;------------------------------------------------------------------------------------------------;; |
;> _img = pointer to image ;; |
;> _flip_kind = one of FLIP_* constants ;; |
;;------------------------------------------------------------------------------------------------;; |
;< eax = false / true ;; |
;;================================================================================================;; |
push 1 |
mov ebx, [_img] |
@@: |
mov eax, [ebx + Image.Previous] |
test eax, eax |
jz .loop |
mov ebx, eax |
jmp @b |
.loop: |
stdcall img.flip.layer, ebx, [_flip_kind] |
test eax, eax |
jnz @f |
mov byte [esp], 0 |
@@: |
mov ebx, [ebx + Image.Next] |
test ebx, ebx |
jnz .loop |
pop eax |
ret |
endp |
;;================================================================================================;; |
proc img.rotate.layer _img, _rotate_kind ;////////////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? Rotate image layer ;; |
;;------------------------------------------------------------------------------------------------;; |
;> _img = pointer to image ;; |
;> _rotate_kind = one of ROTATE_* constants ;; |
;;------------------------------------------------------------------------------------------------;; |
;< eax = false / true ;; |
646,7 → 983,57 |
jz .rotate_ccw8 |
cmp [ebx + Image.Type], Image.bpp24 |
jz .rotate_ccw24 |
cmp [ebx + Image.Type], Image.bpp32 |
jz .rotate_ccw32 |
.next_column_ccw_low1x: |
dec ecx |
js .exchange_dims |
push ecx |
mov edx, [scanline_len_old] |
add [scanline_len_old], -2 |
mov ecx, [scanline_pixels_new] |
mov esi, [ebx + Image.Data] |
mov edi, [line_buffer] |
@@: mov ax, [esi] |
mov [edi], ax |
add esi, edx |
add edi, 2 |
sub ecx, 1 |
jnz @b |
mov eax, [scanline_pixels_new] |
mov edi, [ebx + Image.Data] |
lea esi, [edi + 2] |
mov edx, [scanline_len_old] |
@@: mov ecx, edx |
shr ecx, 2 |
rep movsd |
mov ecx, edx |
and ecx, 3 |
rep movsb |
add esi, 1 |
sub eax, 1 |
jnz @b |
mov eax, [scanline_len_new] |
sub [pixels_ptr], eax |
mov ecx, [scanline_pixels_new] |
mov esi, [line_buffer] |
mov edi, [pixels_ptr] |
mov edx, ecx |
shr ecx, 2 |
rep movsd |
mov ecx, edx |
and ecx, 3 |
rep movsb |
pop ecx |
jmp .next_column_ccw_low1x |
.rotate_ccw32: |
.next_column_ccw_low: |
dec ecx |
js .exchange_dims |
809,7 → 1196,59 |
jz .rotate_cw8 |
cmp [ebx + Image.Type], Image.bpp24 |
jz .rotate_cw24 |
cmp [ebx + Image.Type], Image.bpp32 |
jz .rotate_cw32 |
.next_column_cw_low1x: |
dec ecx |
js .exchange_dims |
push ecx |
mov edx, [scanline_len_old] |
add [scanline_len_old], -2 |
mov ecx, [scanline_pixels_new] |
mov esi, [pixels_ptr] |
add esi, -2 |
mov edi, [line_buffer] |
@@: mov ax, [esi] |
mov [edi], ax |
sub esi, edx |
add edi, 2 |
sub ecx, 1 |
jnz @b |
mov eax, [scanline_pixels_new] |
dec eax |
mov edi, [ebx + Image.Data] |
add edi, [scanline_len_old] |
lea esi, [edi + 2] |
mov edx, [scanline_len_old] |
@@: mov ecx, edx |
shr ecx, 2 |
rep movsd |
mov ecx, edx |
and ecx, 3 |
rep movsb |
add esi, 3 |
sub eax, 1 |
jnz @b |
mov eax, [scanline_len_new] |
sub [pixels_ptr], eax |
mov ecx, eax |
mov esi, [line_buffer] |
mov edi, [pixels_ptr] |
shr ecx, 2 |
rep movsd |
mov ecx, eax |
and ecx, 3 |
rep movsb |
pop ecx |
jmp .next_column_cw_low1x |
.rotate_cw32: |
.next_column_cw_low: |
dec ecx |
js .exchange_dims |
976,8 → 1415,94 |
ret |
endp |
;;================================================================================================;; |
proc img.rotate _img, _rotate_kind ;//////////////////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? Rotate all layers of image ;; |
;;------------------------------------------------------------------------------------------------;; |
;> _img = pointer to image ;; |
;> _rotate_kind = one of ROTATE_* constants ;; |
;;------------------------------------------------------------------------------------------------;; |
;< eax = false / true ;; |
;;================================================================================================;; |
push 1 |
mov ebx, [_img] |
@@: |
mov eax, [ebx + Image.Previous] |
test eax, eax |
jz .loop |
mov ebx, eax |
jmp @b |
.loop: |
stdcall img.rotate.layer, ebx, [_rotate_kind] |
test eax, eax |
jnz @f |
mov byte [esp], 0 |
@@: |
mov ebx, [ebx + Image.Next] |
test ebx, ebx |
jnz .loop |
pop eax |
ret |
endp |
;;================================================================================================;; |
proc img.draw _img, _x, _y, _width, _height, _xpos, _ypos ;///////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? Draw image in the window ;; |
;;------------------------------------------------------------------------------------------------;; |
;> _img = pointer to image ;; |
;>_x = x-coordinate in the window ;; |
;>_y = y-coordinate in the window ;; |
;>_width = maximum width to draw ;; |
;>_height = maximum height to draw ;; |
;>_xpos = offset in image by x-axis ;; |
;>_ypos = offset in image by y-axis ;; |
;;------------------------------------------------------------------------------------------------;; |
;< no return value ;; |
;;================================================================================================;; |
push ebx esi edi |
mov ebx, [_img] |
stdcall img._.validate, ebx |
test eax, eax |
jnz .done |
mov ecx, [ebx + Image.Width] |
sub ecx, [_xpos] |
jbe .done |
cmp ecx, [_width] |
jb @f |
mov ecx, [_width] |
@@: |
mov edx, [ebx + Image.Height] |
sub edx, [_ypos] |
jbe .done |
cmp edx, [_height] |
jb @f |
mov edx, [_height] |
@@: |
mov eax, [ebx + Image.Width] |
sub eax, ecx |
call img._.get_scanline_len |
shl ecx, 16 |
add ecx, edx |
mov edx, [_x - 2] |
mov dx, word [_y] |
mov esi, [ebx + Image.Type] |
mov esi, [type2bpp + (esi-1)*4] |
mov edi, [ebx + Image.Palette] |
mov ebx, [ebx + Image.Data] |
push ebp |
push 65 |
pop ebp |
xchg eax, ebp |
int 40h |
pop ebp |
.done: |
pop edi esi ebx |
ret |
endp |
;;================================================================================================;; |
;;////////////////////////////////////////////////////////////////////////////////////////////////;; |
;;================================================================================================;; |
;! Below are private procs you should never call directly from your code ;; |
1015,6 → 1540,7 |
xor ecx, ecx |
mov [eax + Image.Data], ecx |
mov [eax + Image.Type], ecx |
mov [eax + Image.Flags], ecx |
mov [eax + Image.Extended], ecx |
mov [eax + Image.Previous], ecx |
mov [eax + Image.Next], ecx |
1118,7 → 1644,10 |
jz .bpp8.1 |
cmp [ebx + Image.Type], Image.bpp24 |
jz .bpp24.1 |
shl eax, 2 |
add eax, eax |
cmp [ebx + Image.Type], Image.bpp32 |
jnz @f |
add eax, eax |
jmp @f |
.bpp24.1: |
lea eax, [eax*3] |
1135,7 → 1664,7 |
;;////////////////////////////////////////////////////////////////////////////////////////////////;; |
;;================================================================================================;; |
align 4 |
img._.formats_table: |
.bmp dd img.is.bmp, img.decode.bmp, img.encode.bmp |
; .ico dd img.is.ico, img.decode.ico, img.encode.ico |
1143,9 → 1672,27 |
.gif dd img.is.gif, img.decode.gif, img.encode.gif |
.png dd img.is.png, img.decode.png, img.encode.png |
.jpg dd img.is.jpg, img.decode.jpg, img.encode.jpg |
.tga dd img.is.tga, img.decode.tga, img.encode.tga |
.z80 dd img.is.z80, img.decode.z80, img.encode.z80 ;this must be the last entry as there are no |
;signatures in z80 screens at all |
dd 0 |
align 4 |
type2bpp dd 8, 24, 32, 15, 16 |
img._.do_rgb.handlers: |
dd img._.do_rgb.bpp8 |
dd img._.do_rgb.bpp24 |
dd img._.do_rgb.bpp32 |
dd img._.do_rgb.bpp15.amd ; can be overwritten in lib_init |
dd img._.do_rgb.bpp16.amd ; can be overwritten in lib_init |
img.flip.layer.handlers_horz: |
dd img.flip.layer.bpp8_horz |
dd img.flip.layer.bpp24_horz |
dd img.flip.layer.bpp32_horz |
dd img.flip.layer.bpp1x_horz |
dd img.flip.layer.bpp1x_horz |
;;================================================================================================;; |
;;////////////////////////////////////////////////////////////////////////////////////////////////;; |
;;================================================================================================;; |
1160,7 → 1707,7 |
export \ |
lib_init , 'lib_init' , \ |
0x00010003 , 'version' , \ |
0x00010004 , 'version' , \ |
img.is_img , 'img.is_img' , \ |
img.info , 'img.info' , \ |
img.from_file , 'img.from_file' , \ |
1172,11 → 1719,15 |
img.encode , 'img.encode' , \ |
img.create , 'img.create' , \ |
img.destroy , 'img.destroy' , \ |
img.destroy.layer, 'img.destroy.layer', \ |
img.count , 'img.count' , \ |
img.lock_bits , 'img.lock_bits' , \ |
img.unlock_bits , 'img.unlock_bits' , \ |
img.flip , 'img.flip' , \ |
img.rotate , 'img.rotate' |
img.flip.layer , 'img.flip.layer' , \ |
img.rotate , 'img.rotate' , \ |
img.rotate.layer, 'img.rotate.layer', \ |
img.draw , 'img.draw' |
; import from deflate unpacker |
; is initialized only when PNG loading is requested |
1187,11 → 1738,21 |
import kfar_arc, \ |
deflate_unpack2, 'deflate_unpack2' |
align 4 |
; mutex for unpacker loading |
deflate_loader_mutex dd 0 |
; default palette for GIF - b&w |
gif_default_palette: |
db 0, 0, 0 |
db 0xFF, 0xFF, 0xFF |
section '.data' data readable writable align 16 |
; uninitialized data - global constant tables |
mem.alloc dd ? |
mem.free dd ? |
mem.realloc dd ? |
dll.load dd ? |
; data for YCbCr -> RGB translation |
color_table_1 rd 256 |
/programs/develop/libraries/libs-dev/libimg/libimg.inc |
---|
34,12 → 34,21 |
Data dd ? |
Palette dd ? ; used iff Type eq Image.bpp8 |
Extended dd ? |
Flags dd ? ; bitfield |
Delay dd ? ; used iff Image.IsAnimated is set in Flags |
ends |
; values for Image.Type |
; must be consecutive to allow fast switch on Image.Type in support functions |
Image.bpp8 = 1 |
Image.bpp24 = 2 |
Image.bpp32 = 3 |
Image.bpp15 = 4 |
Image.bpp16 = 5 |
; bits in Image.Flags |
Image.IsAnimated = 1 |
FLIP_VERTICAL = 0x01 |
FLIP_HORIZONTAL = 0x02 |
FLIP_BOTH = FLIP_VERTICAL or FLIP_HORIZONTAL |
/programs/develop/libraries/libs-dev/libimg/png/png.asm |
---|
515,6 → 515,8 |
mov [edi+2], al |
mov al, [esi+3] |
mov [edi+3], al |
add esi, 4 |
add edi, 4 |
sub ecx, 4 |
jnz @b |
sub edx, 1 |
737,8 → 739,10 |
sub ebx, ecx |
jc .convert_done |
@@: |
mov ax, [esi] |
add esi, 2 |
convert_16_to_8 |
add esi, 2 |
mov [edi], al |
add edi, 1 |
sub ecx, 2 |
jnz @b |
821,8 → 825,10 |
sub ebx, ecx |
jc .convert_done |
@@: |
mov ax, [esi] |
add esi, 4 |
convert_16_to_8 |
add esi, 4 |
mov [edi], al |
add edi, 1 |
sub ecx, 4 |
jnz @b |
/programs/develop/libraries/libs-dev/libimg/tga/tga.asm |
---|
0,0 → 1,250 |
;;================================================================================================;; |
;;//// tga.asm //// (c) Nable, 2007-2008 /////////////////////////////////////////////////////////;; |
;;================================================================================================;; |
;; ;; |
;; 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. Hiview 1.2 by Mohammad A. REZAEI ;; |
;; ;; |
;;================================================================================================;; |
include 'tga.inc' |
;;================================================================================================;; |
proc img.is.tga _data, _length ;//////////////////////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? Determine if raw data could be decoded (is in Targa format) ;; |
;;------------------------------------------------------------------------------------------------;; |
;> _data = raw data as read from file/stream ;; |
;> _length = data length ;; |
;;------------------------------------------------------------------------------------------------;; |
;< eax = false / true ;; |
;;================================================================================================;; |
cmp [_length], 18 |
jbe .nope |
mov eax, [_data] |
push ebx |
mov ebx,[eax+1] ;bl=cmatype,bh=subtype |
cmp bl,1 ;cmatype is in [0..1] |
ja .nope |
cmp bh,11 ;subtype is in [1..3] (non-rle) or in [9..11] (rle) |
ja .nope |
cmp bh,9 |
jae .cont1 |
cmp bh,3 |
ja .nope |
.cont1: ;continue testing |
mov ebx,[eax+16] ;bl=bpp, bh=flags //image descriptor |
test ebx,111b ;bpp must be 8, 15, 16, 24 or 32 |
jnz .maybe15 |
shr bl,3 |
cmp bl,4 |
ja .nope |
jmp .cont2 |
.maybe15: |
cmp bl,15 |
jne .nope |
.cont2: ;continue testing |
test bh,tga.flags.interlace_type ;deinterlacing is not supported yet |
jnz .nope |
cmp byte[eax+7],24 ;test palette bpp - only 24 and 32 are supported |
je .yep |
cmp byte[eax+7],32 ;test palette bpp - only 24 and 32 are supported |
je .yep |
.nope: |
xor eax, eax |
pop ebx |
ret |
.yep: |
xor eax, eax |
inc eax |
pop ebx |
ret |
endp |
;;================================================================================================;; |
proc img.decode.tga _data, _length ;//////////////////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? Decode data into image if it contains correctly formed raw data in Targa format ;; |
;;------------------------------------------------------------------------------------------------;; |
;> _data = raw data as read from file/stream ;; |
;> _length = data length ;; |
;;------------------------------------------------------------------------------------------------;; |
;< eax = 0 (error) or pointer to image ;; |
;;================================================================================================;; |
locals |
IMGwidth dd ? |
IMGheight dd ? |
IMGbpp dd ? |
DupPixelCount dd ? |
TgaBlockCount dd ? |
endl |
pushad |
cld ;paranoia |
and [DupPixelCount],0 ;prepare variables |
and [TgaBlockCount],0 ;prepare variables |
mov eax,[_data] |
movzx esi,byte[eax] |
lea esi,[esi+eax+18] ;skip comment and header |
mov ebx,[eax+12] |
movzx ecx,bx ;ecx=width |
shr ebx,16 ;ebx=height |
mov [IMGwidth],ecx |
mov [IMGheight],ebx |
movzx edx,byte[eax+16] |
cmp edx,16 |
jnz @f |
dec edx ;16bpp tga images are really 15bpp ARGB |
@@: |
sub edx, 16 - Image.bpp16 ; 15 -> Image.bpp15, 16 -> Image.bpp16 |
mov [IMGbpp],edx |
stdcall img.create,ecx,ebx,edx |
mov [esp+28],eax ;save return value |
test eax,eax ;failed to allocate? |
jz .locret ;then exit |
cmp edx,8 |
jne .palette_parsed |
mov edi,[eax+Image.Palette] |
mov ecx,[_data] |
cmp byte[ecx+2],3 ;we also have grayscale subtype |
jz .write_grayscale_palette ;that don't hold palette in file |
cmp byte[ecx+2],11 |
jz .write_grayscale_palette |
mov dh,[ecx+7] ;size of colormap entries in bits |
movzx ecx,word[ecx+5] ;number of colormap entries |
cmp dh,24 |
jz .skip_24bpp_palette ;test if colormap entries are 24bpp |
rep movsd ;else they are 32 bpp |
jmp .palette_parsed |
.write_grayscale_palette: |
push eax |
mov ecx,0x100 |
xor eax,eax |
@@: |
stosd |
add eax,0x010101 |
loop @b |
pop eax |
jmp .palette_parsed |
.skip_24bpp_palette: |
push eax |
@@: |
lodsd |
dec esi |
and eax,0xFFFFFF |
; bswap eax |
; shr eax,8 |
stosd |
loop @b |
pop eax |
.palette_parsed: |
mov edi,[eax+Image.Data] |
imul ebx,[IMGwidth] ;ebx=width*height |
mov edx,[IMGbpp] |
add edx,7 |
shr edx,3 ;edx=bytes per pixel |
mov dh,dl ;dh=dl=bytes per pixel |
mov eax,[_data] |
cmp byte[eax+2],9 |
jb .not_an_rle |
.tga_read_rle_pixel: |
cmp [DupPixelCount],0 ;Duplicate previously read pixel? |
jg .duplicate_previously_read_pixel |
dec [TgaBlockCount] ;Decrement pixels remaining in block |
jns .read_non_rle_pixel |
xor eax,eax |
lodsb |
test al,al ;Start of duplicate-pixel block? |
jns .2 |
and al,0x7f |
mov [DupPixelCount],eax ;Number of duplications after this one |
and [TgaBlockCount],0 ;Then read new block header |
jmp .read_non_rle_pixel |
.2: |
mov dword[TgaBlockCount],eax |
.read_non_rle_pixel: |
xor eax,eax |
mov dl,dh |
@@: |
shl eax,8 |
lodsb |
dec dl |
jnz @b |
cmp dh,3 |
jne .put_pixel |
bswap eax |
shr eax,8 |
jmp .put_pixel |
.duplicate_previously_read_pixel: |
dec [DupPixelCount] |
.put_pixel: |
mov dl,dh |
push eax |
@@: |
stosb |
shr eax,8 |
dec dl |
jnz @b |
pop eax |
dec ebx |
jnz .tga_read_rle_pixel |
jmp .locret |
.not_an_rle: |
movzx edx,dl ;dh contains bpp too (for decoding needs) |
imul edx,ebx |
mov ecx,edx |
rep movsb ;just copy the image |
.locret: |
popad |
ret |
endp |
;;================================================================================================;; |
proc img.encode.tga _img, _p_length ;/////////////////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? Encode image into raw data in Targa 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 ;; |
;;================================================================================================;; |
;;////////////////////////////////////////////////////////////////////////////////////////////////;; |
;;================================================================================================;; |
;;================================================================================================;; |
;;////////////////////////////////////////////////////////////////////////////////////////////////;; |
;;================================================================================================;; |
;! Below is private data you should never use directly from your code ;; |
;;================================================================================================;; |
;;////////////////////////////////////////////////////////////////////////////////////////////////;; |
;;================================================================================================;; |
; |
/programs/develop/libraries/libs-dev/libimg/tga/tga.inc |
---|
0,0 → 1,35 |
;;================================================================================================;; |
;;//// tga.inc //// (c) Nable, 2007-2008 /////////////////////////////////////////////////////////;; |
;;================================================================================================;; |
;; ;; |
;; 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/>. ;; |
;; ;; |
;;================================================================================================;; |
struct tga.FileHeader |
CommentLength db ? |
ColormapType db ? |
SubType db ? |
DontKnow1 dw ? |
ColormapSize dw ? |
ColormapBpp db ? |
DontKnow2 dd ? |
Width dw ? |
Height dw ? |
BitPerPixel db ? |
DontKnow3 db ? |
ends |
tga.flags.top_down_row_order equ 32 ;bit5 |
tga.flags.interlace_type equ 192;bits6/7 |
/programs/develop/libraries/libs-dev/libimg/z80/z80.asm |
---|
0,0 → 1,257 |
;;================================================================================================;; |
;;//// z80.asm //// (c) Nable, 2007-2008 /////////////////////////////////////////////////////////;; |
;;================================================================================================;; |
;; ;; |
;; 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. ;; |
;; ;; |
;;================================================================================================;; |
include 'z80.inc' |
;;================================================================================================;; |
proc img.is.z80 _data, _length ;//////////////////////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? Determine if raw data could be decoded (is in z80 screen format) ;; |
;;------------------------------------------------------------------------------------------------;; |
;> _data = raw data as read from file/stream ;; |
;> _length = data length ;; |
;;------------------------------------------------------------------------------------------------;; |
;< eax = false / true ;; |
;;================================================================================================;; |
xor eax,eax |
cmp [_length],6929 |
setz al |
je @f |
cmp [_length],6912 |
setz al |
@@: |
ret |
endp |
;;================================================================================================;; |
proc img.decode.z80 _data, _length ;//////////////////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? Decode data into image if it contains correctly formed raw data in z80 screen format ;; |
;;------------------------------------------------------------------------------------------------;; |
;> _data = raw data as read from file/stream ;; |
;> _length = data length ;; |
;;------------------------------------------------------------------------------------------------;; |
;< eax = 0 (error) or pointer to image ;; |
;;================================================================================================;; |
;--------------------------------------------------------------------------------------------------- |
;During the decoding: |
;bl - PixelLeft (this means how much pixels left to put in current string) |
;bh - CurrentString |
;High half of ebx - use DualStos (two frames per one pixel_write) |
;cl - PixelColorIndexInPalette |
;ch - BackgroundColorIndexInPalette |
;High half of ecx - blinking flag |
;edx - address of current attribute byte |
;--------------------------------------------------------------------------------------------------- |
locals |
frame1 dd ? |
OffsetIn2ndFrame dd ? |
endl |
xor eax,eax |
pushad |
cld ;paranoia |
stdcall img.create,256,192,Image.bpp8 |
test eax,eax |
jz img.decode.z80.locret ;test if allocation failed |
mov [frame1],eax |
mov esi,z80._._16color_palette |
mov ecx,16 |
mov edi,[eax+Image.Palette] |
rep movsd ;write palette for the first frame |
mov esi,[_data] |
cmp [_length],6929 |
jne @f |
add esi,17 ;in case of 6929 byte files we just skip the info in the begininning. |
@@: |
;--------------------------------------------------------------------------------------------------- |
;At first we'll determine if there are any blinking pixels |
;if no - we'll produce statical single image |
mov ecx,768 |
lea edx,[esi+6912-768];edx points to attribute area |
xor ebx,ebx ;begin from <0,0> (for further decoding) |
@@: |
test byte[edx+ecx-1],z80.BlinkFlag ;such addressing is a good optimisation |
;(as I hope), edx is unchanged |
jnz .decode_z80_with_blinking |
loop @b |
.decode_z80_without_blinking: |
jmp .decode_z80_main_stage |
.decode_z80_with_blinking: |
or ebx,0xFFFF0000 ;use DualStos |
mov ecx,eax ;eax still points to the first frame |
stdcall img.create,256,192,Image.bpp8 |
test eax,eax |
jz img.decode.z80.failed |
mov [eax+Image.Previous],ecx |
mov [ecx+Image.Next],eax |
mov esi,z80._._16color_palette |
mov ecx,16 |
mov edi,[eax+Image.Palette] |
rep movsd ;write palette for the second frame |
mov eax,[eax+Image.Data] |
mov [OffsetIn2ndFrame],eax |
;------------------------------------------------------------------------------- |
.decode_z80_main_stage: |
;2nd stage - convert z80 screen to 8bpp image with palette |
.decode_z80_main_stage_main_loop: |
test bl,7 |
jnz .decode_z80_main_stage_put_now |
._z80_update_attributes: |
movsx ecx,byte[edx] ;note that BlinkFlag is the highest bit in attribute |
;byte, so ecx's highest bit is set automatically |
shl ecx,5 |
shr cl,5 |
and ch,0xF |
test ch,1000b |
jz @f |
or ecx,1000b ;it has the same size with 'or cl,1000b' but could be faster |
@@: |
inc edx |
lodsb |
mov ah,al |
.decode_z80_main_stage_put_now: |
shl ah,1 |
;------------------------------------------------------------------------------- |
._z80_put_pixel: |
;In: CF - put pixel with color CL, !CF - pixel with color CH |
;High parts of ebx and ecx - as described above |
mov al,cl ;'mov' doesn't affect flags |
jc @f |
mov al,ch |
@@: |
stosb ;'stosb' doesn't affect flags |
test ebx,ebx |
jns @f |
test ecx,ecx |
jns .1 |
mov al,ch |
.1: |
xchg [OffsetIn2ndFrame],edi |
stosb |
xchg [OffsetIn2ndFrame],edi |
@@: |
inc bl ;next pixel |
jz .decode_z80_main_stage_row_finished |
jmp .decode_z80_main_stage_main_loop |
;------------------------------------------------------------------------------- |
.decode_z80_main_stage_row_finished: |
cmp bh,191 ;is image finished? |
jb .decode_z80_main_stage_image_not_finished ;no. |
.decode_z80_finish: |
jmp .locret ;now really finished |
;------------------------------------------------------------------------------- |
;or not finished yet. Branch according to a row number (see documentation) |
.decode_z80_main_stage_next_third: |
sub bh,7 |
sub edi,256*(8-1) |
jmp .decode_z80_main_stage_main_loop |
.decode_z80_main_stage_image_not_finished: |
;next row |
add bh,8 ;refer to documentation |
add edi,256*(8-1) |
;if finished row is 63 or 127 then we process next third of the image |
cmp bh,63+8 |
je .decode_z80_main_stage_next_third |
cmp bh,127+8 |
je .decode_z80_main_stage_next_third |
cmp bh,56+8 ;if finished row in [56;63) or [120;127) or [184;191) |
jb .decode_z80_main_stage_main_loop |
cmp bh,63+8 |
jb .4 |
cmp bh,120+8 |
jb .decode_z80_main_stage_main_loop |
cmp bh,127+8 |
jb .4 |
cmp bh,184+8 |
jb .decode_z80_main_stage_main_loop |
;note that if we are here then bh is < 191 (see label .2) but >= 184+8 |
.4: |
;and if we here then bh is in [56;63) or [120;127) or [184;191) |
sub bh,(8+56-1) |
sub edi,256*(8+56-1) |
sub edx,z80.AttrString*8 |
jmp .decode_z80_main_stage_main_loop |
img.decode.z80.locret: |
popad |
ret |
img.decode.z80.failed: |
stdcall img.destroy,[frame1] |
jmp img.decode.z80.locret |
endp |
;;================================================================================================;; |
proc img.encode.z80 _img, _p_length ;/////////////////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? Encode image into raw data in z80 screen 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 ;; |
;;================================================================================================;; |
;;////////////////////////////////////////////////////////////////////////////////////////////////;; |
;;================================================================================================;; |
;;================================================================================================;; |
;;////////////////////////////////////////////////////////////////////////////////////////////////;; |
;;================================================================================================;; |
;! Below is private data you should never use directly from your code ;; |
;;================================================================================================;; |
;;////////////////////////////////////////////////////////////////////////////////////////////////;; |
;;================================================================================================;; |
z80._._16color_palette: |
dd 0 ; black |
dd 0x000000b0 ; blue |
dd 0x00b00000 ; red |
dd 0x00b000b0 ; magenta |
dd 0x0000b000 ; green |
dd 0x0000b0b0 ; cyan |
dd 0x00b0b000 ; yellow |
dd 0x00b0b0b0 ; gray |
dd 0 ; black |
dd 0x000000ff ; light blue |
dd 0x00ff0000 ; light red |
dd 0x00ff00ff ; light magenta |
dd 0x0000ff00 ; light green |
dd 0x0000ffff ; light cyan |
dd 0x00ffff00 ; light yellow |
dd 0x00ffffff ; white |
/programs/develop/libraries/libs-dev/libimg/z80/z80.inc |
---|
0,0 → 1,23 |
;;================================================================================================;; |
;;//// z80.inc //// (c) Nable, 2007-2008 /////////////////////////////////////////////////////////;; |
;;================================================================================================;; |
;; ;; |
;; 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/>. ;; |
;; ;; |
;;================================================================================================;; |
z80.PixColor equ 000111b |
z80.BgrColor equ 111000b |
z80.BrightFlag equ (1 shl 6) |
z80.BlinkFlag equ (1 shl 7) |
z80.AttrString equ 32 |