From 1b6868a0225c0a636959f5eac837fcbbb08fd688 Mon Sep 17 00:00:00 2001 From: "Evgeny Grechnikov (Diamond)" Date: Sun, 24 May 2009 16:47:14 +0000 Subject: [PATCH] libimg, version 4: * decoder for animated GIFs * some fixes in PNG and JPEG decoders * internal image representation now allows 15 and 16 bpp (without conversions in decoders) * decoder for TGA, Z80 from Nable git-svn-id: svn://kolibrios.org@1079 a494cfbc-eb01-0410-851d-a64ba20cac60 --- .../libraries/libs-dev/libimg/bmp/bmp.asm | 6 +- .../libraries/libs-dev/libimg/gif/gif.asm | 1247 +++++++++++++++-- .../libraries/libs-dev/libimg/gif/gif.inc | 17 +- .../libraries/libs-dev/libimg/jpeg/jpeg.asm | 10 +- .../libraries/libs-dev/libimg/libimg.asm | 675 ++++++++- .../libraries/libs-dev/libimg/libimg.inc | 11 +- .../libraries/libs-dev/libimg/png/png.asm | 10 +- .../libraries/libs-dev/libimg/tga/tga.asm | 250 ++++ .../libraries/libs-dev/libimg/tga/tga.inc | 35 + .../libraries/libs-dev/libimg/z80/z80.asm | 257 ++++ .../libraries/libs-dev/libimg/z80/z80.inc | 23 + 11 files changed, 2353 insertions(+), 188 deletions(-) create mode 100644 programs/develop/libraries/libs-dev/libimg/tga/tga.asm create mode 100644 programs/develop/libraries/libs-dev/libimg/tga/tga.inc create mode 100644 programs/develop/libraries/libs-dev/libimg/z80/z80.asm create mode 100644 programs/develop/libraries/libs-dev/libimg/z80/z80.inc diff --git a/programs/develop/libraries/libs-dev/libimg/bmp/bmp.asm b/programs/develop/libraries/libs-dev/libimg/bmp/bmp.asm index 0a6ee2e9e2..b52c6e45d7 100644 --- a/programs/develop/libraries/libs-dev/libimg/bmp/bmp.asm +++ b/programs/develop/libraries/libs-dev/libimg/bmp/bmp.asm @@ -102,8 +102,7 @@ endl 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 @@ endl 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 diff --git a/programs/develop/libraries/libs-dev/libimg/gif/gif.asm b/programs/develop/libraries/libs-dev/libimg/gif/gif.asm index 845379764a..07e4a2277d 100644 --- a/programs/develop/libraries/libs-dev/libimg/gif/gif.asm +++ b/programs/develop/libraries/libs-dev/libimg/gif/gif.asm @@ -51,7 +51,7 @@ proc img.is.gif _data, _length ;//////////////////////////////////////////////// ;;------------------------------------------------------------------------------------------------;; ;< eax = false / true ;; ;;================================================================================================;; - cmp [_length], 6 + cmp [_length], sizeof.gif.Header jb .nope mov eax, [_data] cmp dword[eax], 'GIF8' @@ -82,36 +82,99 @@ proc img.decode.gif _data, _length ;//////////////////////////////////////////// ;< 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 @@ -128,26 +191,45 @@ endl 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 -@@: - mov [img], eax - mov edx, eax + xor ecx, ecx + @@: + 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,12 +246,19 @@ endl 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 @@ -179,24 +268,105 @@ endl 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 eax, [img] - ret + 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 - stdcall img.destroy, eax -@@: - xor eax, eax - pop ebx + 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 @@ -224,26 +394,6 @@ endp ;;================================================================================================;; -;;================================================================================================;; -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 ;////////////////////////////////////////////////////////;; ;;------------------------------------------------------------------------------------------------;; @@ -254,65 +404,65 @@ proc img.decode.gif._.process_extensions ;////////////////////////////////////// ;;------------------------------------------------------------------------------------------------;; ;< --- 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 - - .plain_text_ext: - add esi, gif.PlainTextExtension.PlainTextData - stdcall img.decode.gif._.skip_data - jmp .next_ext_block +; 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, 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 - - .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_err: + xor eax, eax .exit: mov ebx, esi - pop edx ret endp @@ -354,6 +504,7 @@ endl 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 @@ endl @@: 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 @@ endl .cycle: movzx ebx, ax call .get_symbol - cmp eax, edx - jae .notintable - cmp eax, [CC] - je .reinit 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 - cmp edx, 0x00000FFF - jae .cycle inc edx + cmp edx, 0x1000 + je .noinc bsr ebx, edx cmp ebx, [compsize] jne .noinc @@ -436,15 +596,26 @@ endl 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 @@ img.decode.gif._.process_image.get_symbol: 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 @@ img.decode.gif._.process_image.output: .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,8 +728,847 @@ img.decode.gif._.process_image.output: 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 ;;================================================================================================;; ;;////////////////////////////////////////////////////////////////////////////////////////////////;; diff --git a/programs/develop/libraries/libs-dev/libimg/gif/gif.inc b/programs/develop/libraries/libs-dev/libimg/gif/gif.inc index 264233eafc..d45a7ff31b 100644 --- a/programs/develop/libraries/libs-dev/libimg/gif/gif.inc +++ b/programs/develop/libraries/libs-dev/libimg/gif/gif.inc @@ -61,7 +61,9 @@ gif.Block.Introducer.ImageDescriptor = 0x2C 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.Comment = 0xFE 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 @@ struct gif.PlainTextExtension ; GIF89a 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 @@ ends ;;------------------------------------------------------------------------------------------------;; struct gif.Image - gce gif.GraphicsControlExtension info gif.ImageDescriptor + gce gif.GraphicsControlExtension +; lsd gif.LogicalScreenDescriptor ; saved only in first image ends gif.Null equ 0x1000 diff --git a/programs/develop/libraries/libs-dev/libimg/jpeg/jpeg.asm b/programs/develop/libraries/libs-dev/libimg/jpeg/jpeg.asm index fe9d6a4b9d..88b8274ba1 100644 --- a/programs/develop/libraries/libs-dev/libimg/jpeg/jpeg.asm +++ b/programs/develop/libraries/libs-dev/libimg/jpeg/jpeg.asm @@ -474,8 +474,8 @@ img.decode.jpg: ; 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 @@ handle_progressive: 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 diff --git a/programs/develop/libraries/libs-dev/libimg/libimg.asm b/programs/develop/libraries/libs-dev/libimg/libimg.asm index 6e740dd20f..7e61ffa0bc 100644 --- a/programs/develop/libraries/libs-dev/libimg/libimg.asm +++ b/programs/develop/libraries/libs-dev/libimg/libimg.asm @@ -35,11 +35,8 @@ include 'bmp/bmp.asm' include 'gif/gif.asm' include 'jpeg/jpeg.asm' include 'png/png.asm' - -mem.alloc dd ? -mem.free dd ? -mem.realloc dd ? -dll.load dd ? +include 'tga/tga.asm' +include 'z80/z80.asm' ;;================================================================================================;; proc lib_init ;///////////////////////////////////////////////////////////////////////////////////;; @@ -60,6 +57,14 @@ proc lib_init ;///////////////////////////////////////////////////////////////// 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,10 +216,267 @@ proc img._.do_rgb ;///////////////////////////////////////////////////////////// mov ecx, [esi + Image.Width] imul ecx, [esi + Image.Height] mov eax, [esi + Image.Type] - dec eax - jz .bpp8 - dec eax - jz .bpp24 + 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 +@@: + 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] + mov esi, [esi + Image.Data] + shr ecx, 2 + rep movsd + ret + +align 16 +.bpp32: ; 32 BPP -> 24 BPP mov esi, [esi + Image.Data] @@ -231,31 +493,6 @@ proc img._.do_rgb ;///////////////////////////////////////////////////////////// @@: ret -.bpp24: -; 24 BPP -> 24 BPP - lea ecx, [ecx*3 + 3] - mov esi, [esi + Image.Data] - shr ecx, 2 - rep movsd - ret - -.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], ax - shr eax, 16 - mov [edi+2], al - add edi, 3 - sub ecx, 1 - jnz @b - pop ebx - ret endp ;;================================================================================================;; @@ -334,6 +571,32 @@ proc img.create _width, _height, _type ;//////////////////////////////////////// ret 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 ;///////////////////////////////////////////////////////////////////////////;; ;;------------------------------------------------------------------------------------------------;; @@ -343,8 +606,33 @@ proc img.destroy _img ;///////////////////////////////////////////////////////// ;;------------------------------------------------------------------------------------------------;; ;< 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 @@ proc img.unlock_bits _img, _lock ;////////////////////////////////////////////// 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 @@ endl 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 @@ endl 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 @@ endl 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 @@ endl 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,9 +894,40 @@ endl 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 ;; @@ -646,7 +983,57 @@ endl 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 @@ endl 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,6 +1415,92 @@ endl 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 ;;================================================================================================;; ;;////////////////////////////////////////////////////////////////////////////////////////////////;; @@ -1015,6 +1540,7 @@ proc img._.new ;//////////////////////////////////////////////////////////////// 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 @@ img._.get_scanline_len: ;/////////////////////////////////////////////////////// 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 @@ img._.get_scanline_len: ;/////////////////////////////////////////////////////// ;;////////////////////////////////////////////////////////////////////////////////////////////////;; ;;================================================================================================;; - +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,8 +1672,26 @@ img._.formats_table: .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,23 +1707,27 @@ align 4 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' , \ img.to_file , 'img.to_file' , \ img.from_rgb , 'img.from_rgb' , \ img.to_rgb , 'img.to_rgb' , \ - img.to_rgb2 , 'img.to_rgb2' , \ + img.to_rgb2 , 'img.to_rgb2' , \ img.decode , 'img.decode' , \ 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 @@ library kfar_arc, '../File Managers/kfar_arc.obj' 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 diff --git a/programs/develop/libraries/libs-dev/libimg/libimg.inc b/programs/develop/libraries/libs-dev/libimg/libimg.inc index aa28ea26bb..96163c3638 100644 --- a/programs/develop/libraries/libs-dev/libimg/libimg.inc +++ b/programs/develop/libraries/libs-dev/libimg/libimg.inc @@ -34,11 +34,20 @@ struct Image 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 -Image.bpp8 = 1 +; 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 diff --git a/programs/develop/libraries/libs-dev/libimg/png/png.asm b/programs/develop/libraries/libs-dev/libimg/png/png.asm index 1a125f4eac..0191667f22 100644 --- a/programs/develop/libraries/libs-dev/libimg/png/png.asm +++ b/programs/develop/libraries/libs-dev/libimg/png/png.asm @@ -515,6 +515,8 @@ align 4 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 @@ end repeat sub ebx, ecx jc .convert_done @@: - convert_16_to_8 + mov ax, [esi] add esi, 2 + convert_16_to_8 + mov [edi], al add edi, 1 sub ecx, 2 jnz @b @@ -821,8 +825,10 @@ end repeat sub ebx, ecx jc .convert_done @@: - convert_16_to_8 + mov ax, [esi] add esi, 4 + convert_16_to_8 + mov [edi], al add edi, 1 sub ecx, 4 jnz @b diff --git a/programs/develop/libraries/libs-dev/libimg/tga/tga.asm b/programs/develop/libraries/libs-dev/libimg/tga/tga.asm new file mode 100644 index 0000000000..82051a75bf --- /dev/null +++ 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 . ;; +;; ;; +;;================================================================================================;; +;; ;; +;; 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 ;; +;;================================================================================================;; +;;////////////////////////////////////////////////////////////////////////////////////////////////;; +;;================================================================================================;; + +; \ No newline at end of file diff --git a/programs/develop/libraries/libs-dev/libimg/tga/tga.inc b/programs/develop/libraries/libs-dev/libimg/tga/tga.inc new file mode 100644 index 0000000000..d277ac322c --- /dev/null +++ b/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 . ;; +;; ;; +;;================================================================================================;; + +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 diff --git a/programs/develop/libraries/libs-dev/libimg/z80/z80.asm b/programs/develop/libraries/libs-dev/libimg/z80/z80.asm new file mode 100644 index 0000000000..5f7efddfe4 --- /dev/null +++ b/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 . ;; +;; ;; +;;================================================================================================;; +;; ;; +;; 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 diff --git a/programs/develop/libraries/libs-dev/libimg/z80/z80.inc b/programs/develop/libraries/libs-dev/libimg/z80/z80.inc new file mode 100644 index 0000000000..4be190035a --- /dev/null +++ b/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 . ;; +;; ;; +;;================================================================================================;; +z80.PixColor equ 000111b +z80.BgrColor equ 111000b +z80.BrightFlag equ (1 shl 6) +z80.BlinkFlag equ (1 shl 7) +z80.AttrString equ 32 \ No newline at end of file