diff --git a/programs/develop/libraries/libs-dev/libimg/convert.asm b/programs/develop/libraries/libs-dev/libimg/convert.asm index 398b73c552..c91d639fca 100644 --- a/programs/develop/libraries/libs-dev/libimg/convert.asm +++ b/programs/develop/libraries/libs-dev/libimg/convert.asm @@ -17,15 +17,70 @@ ;; ;; ;;================================================================================================;; + + ;;================================================================================================;; proc img.convert _src, _dst, _dst_type, _flags, _param ;; ;;------------------------------------------------------------------------------------------------;; -;? scale _image ;; +;? convert _image ;; ;;------------------------------------------------------------------------------------------------;; ;> [_src] = pointer to source image ;; +;> [_dst] = pointer to destination image, or 0 to create a new one ;; +;> [_dst_type] = Image.Type of resulting image ;; ;> [_flags] = see libimg.inc ;; -;> [_dst_type] = the Image.Type of converted image ;; -;> [_dst] = pointer to destination image, if any ;; +;> [_param] = depends on _flags fields, see libimg.inc ;; +;;------------------------------------------------------------------------------------------------;; +;< eax = 0 / pointer to converted image ;; +;< ecx = error code / undefined ;; +;;================================================================================================;; + push ebx esi edi 0 0 + mov ebx, [_src] + @@: + mov eax, [ebx + Image.Previous] + test eax, eax + jz .loop + mov ebx, eax + jmp @b + .loop: + stdcall img.convert.layer, ebx, [_dst], [_dst_type], [_flags], [_param] + test eax, eax + jz .error + cmp dword[esp + 4], 0 + jnz @f + mov [esp + 4], eax + @@: + mov ecx, [esp] + jecxz @f + mov [ecx + Image.Next], eax + @@: + push [ebx + Image.Flags] + pop [eax + Image.Flags] + push [ebx + Image.Delay] + pop [eax + Image.Delay] + mov [eax + Image.Previous], ecx + mov [esp], eax + mov ebx, [ebx + Image.Next] + test ebx, ebx + jnz .loop + .quit: + pop eax eax edi esi ebx + ret + .error: + pop eax eax edi esi ebx + ret +endp + + +;;================================================================================================;; +proc img.convert.layer _src, _dst, _dst_type, _flags, _param ;; +;;------------------------------------------------------------------------------------------------;; +;? convert _image layer ;; +;;------------------------------------------------------------------------------------------------;; +;> [_src] = pointer to source image ;; +;> [_dst] = pointer to destination image, or 0 to create a new one ;; +;> [_dst_type] = Image.Type of resulting image ;; +;> [_flags] = see libimg.inc ;; +;> [_param] = depends on _flags fields, see libimg.inc ;; ;;------------------------------------------------------------------------------------------------;; ;< eax = 0 / pointer to converted image ;; ;< ecx = error code / undefined ;; @@ -34,6 +89,8 @@ locals width rd 1 height rd 1 endl + push ebx esi edi + mov ebx, [_src] mov eax, 1 mov ecx, [_dst_type] @@ -151,6 +208,13 @@ endl mov eax, [_dst] jmp .quit + .bpp8g_to_bpp8g: + mov ecx, [ebx + Image.Width] + imul ecx, [ebx + Image.Height] + rep movsb + mov eax, [_dst] + jmp .quit + .bpp8g_to_bpp24: mov ecx, [ebx + Image.Width] imul ecx, [ebx + Image.Height] @@ -199,6 +263,19 @@ endl jnz @b mov eax, [_dst] jmp .quit + .bpp24_to_bpp32: + mov ecx, [ebx + Image.Width] + imul ecx, [ebx + Image.Height] + @@: + lodsw + ror eax, 16 + lodsb + rol eax, 16 + stosd + dec ecx + jnz @b + mov eax, [_dst] + jmp .quit .bpp32: @@ -561,25 +638,28 @@ end repeat .error: xor eax, eax .quit: + pop edi esi ebx ret endp img.convert.bpp8i.table: - dd Image.bpp24, img.convert.bpp8i_to_bpp24 + dd Image.bpp24, img.convert.layer.bpp8i_to_bpp24 img.convert.bpp8g.table: - dd Image.bpp24, img.convert.bpp8g_to_bpp24 - dd Image.bpp1, img.convert.bpp8g_to_bpp1 + dd Image.bpp24, img.convert.layer.bpp8g_to_bpp24 + dd Image.bpp8g, img.convert.layer.bpp8g_to_bpp8g + dd Image.bpp1, img.convert.layer.bpp8g_to_bpp1 img.convert.bpp24.table: - dd Image.bpp24, img.convert.bpp24_to_bpp24 - dd Image.bpp8g, img.convert.bpp24_to_bpp8g + dd Image.bpp24, img.convert.layer.bpp24_to_bpp24 + dd Image.bpp8g, img.convert.layer.bpp24_to_bpp8g + dd Image.bpp32, img.convert.layer.bpp24_to_bpp32 img.convert.bpp32.table: - dd Image.bpp24, img.convert.bpp32_to_bpp24 + dd Image.bpp24, img.convert.layer.bpp32_to_bpp24 img.convert.bpp15.table: - dd Image.bpp24, img.convert.bpp15_to_bpp24 + dd Image.bpp24, img.convert.layer.bpp15_to_bpp24 img.convert.bpp16.table: - dd Image.bpp24, img.convert.bpp16_to_bpp24 + dd Image.bpp24, img.convert.layer.bpp16_to_bpp24 img.convert.bpp1.table: - dd Image.bpp24, img.convert.bpp1_to_bpp24 + dd Image.bpp24, img.convert.layer.bpp1_to_bpp24 img.convert.bpp8a.table: - dd Image.bpp24, img.convert.bpp8a_to_bpp24 + dd Image.bpp24, img.convert.layer.bpp8a_to_bpp24 diff --git a/programs/develop/libraries/libs-dev/libimg/libimg.asm b/programs/develop/libraries/libs-dev/libimg/libimg.asm index d2228b720d..556fbc75f2 100644 --- a/programs/develop/libraries/libs-dev/libimg/libimg.asm +++ b/programs/develop/libraries/libs-dev/libimg/libimg.asm @@ -1,2811 +1,2818 @@ -;;================================================================================================;; -;;//// libimg.asm //// (c) mike.dld, 2007-2008, (c) diamond, 2009, (c) dunkaist, 2011-2013 ///////;; -;;================================================================================================;; -;; ;; -;; 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 . ;; -;; ;; -;;================================================================================================;; - - -format MS COFF - -public @EXPORT as 'EXPORTS' - -include '../../../../struct.inc' -include '../../../../proc32.inc' -include '../../../../macros.inc' -include '../../../../config.inc' -;include '../../../../debug.inc' -purge section,mov,add,sub - -include 'libimg.inc' - -section '.flat' code readable align 16 - -include 'bmp/bmp.asm' -include 'gif/gif.asm' -include 'jpeg/jpeg.asm' -include 'png/png.asm' -include 'tga/tga.asm' -include 'z80/z80.asm' -include 'ico_cur/ico_cur.asm' -include 'pcx/pcx.asm' -include 'xcf/xcf.asm' -include 'tiff/tiff.asm' -include 'pnm/pnm.asm' -include 'wbmp/wbmp.asm' -include 'xbm/xbm.asm' - -include 'scale.asm' -include 'convert.asm' -;include 'transform.asm' - -;;================================================================================================;; -proc lib_init ;///////////////////////////////////////////////////////////////////////////////////;; -;;------------------------------------------------------------------------------------------------;; -;? Library entry point (called after library load) ;; -;;------------------------------------------------------------------------------------------------;; -;> eax = pointer to memory allocation routine ;; -;> ebx = pointer to memory freeing routine ;; -;> ecx = pointer to memory reallocation routine ;; -;> edx = pointer to library loading routine ;; -;;------------------------------------------------------------------------------------------------;; -;< eax = 1 (fail) / 0 (ok) (library initialization result) ;; -;;================================================================================================;; - mov [mem.alloc], eax - mov [mem.free], ebx - mov [mem.realloc], ecx - mov [dll.load], edx - - or edx,edx - jz @f - invoke dll.load, @IMPORT - @@: - - 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 - -;;================================================================================================;; -proc img.is_img _data, _length ;//////////////////////////////////////////////////////////////////;; -;;------------------------------------------------------------------------------------------------;; -;? --- TBD --- ;; -;;------------------------------------------------------------------------------------------------;; -;> --- TBD --- ;; -;;------------------------------------------------------------------------------------------------;; -;< --- TBD --- ;; -;;================================================================================================;; - push ebx - mov ebx, img.formats_table - @@: stdcall [ebx + FormatsTableEntry.Is], [_data], [_length] - or eax, eax - jnz @f - add ebx, sizeof.FormatsTableEntry - cmp dword[ebx], 0 - jnz @b - xor eax, eax - @@: pop ebx - ret -endp - -;;================================================================================================;; -proc img.info _data, _length ;////////////////////////////////////////////////////////////////////;; -;;------------------------------------------------------------------------------------------------;; -;? --- TBD --- ;; -;;------------------------------------------------------------------------------------------------;; -;> --- TBD --- ;; -;;------------------------------------------------------------------------------------------------;; -;< --- TBD --- ;; -;;================================================================================================;; - xor eax, eax - ret -endp - -;;================================================================================================;; -proc img.from_file _filename ;////////////////////////////////////////////////////////////////////;; -;;------------------------------------------------------------------------------------------------;; -;? --- TBD --- ;; -;;------------------------------------------------------------------------------------------------;; -;> --- TBD --- ;; -;;------------------------------------------------------------------------------------------------;; -;< eax = 0 / pointer to image ;; -;;================================================================================================;; - xor eax, eax - ret -endp - -;;================================================================================================;; -proc img.to_file _img, _filename ;////////////////////////////////////////////////////////////////;; -;;------------------------------------------------------------------------------------------------;; -;? --- TBD --- ;; -;;------------------------------------------------------------------------------------------------;; -;> --- TBD --- ;; -;;------------------------------------------------------------------------------------------------;; -;< eax = false / true ;; -;;================================================================================================;; - xor eax, eax - ret -endp - -;;================================================================================================;; -proc img.from_rgb _rgb_data ;/////////////////////////////////////////////////////////////////////;; -;;------------------------------------------------------------------------------------------------;; -;? --- TBD --- ;; -;;------------------------------------------------------------------------------------------------;; -;> --- TBD --- ;; -;;------------------------------------------------------------------------------------------------;; -;< eax = 0 / pointer to image ;; -;;================================================================================================;; - xor eax, eax - ret -endp - -;;================================================================================================;; -proc img.to_rgb2 _img, _out ;/////////////////////////////////////////////////////////////////////;; -;;------------------------------------------------------------------------------------------------;; -;? decodes image data into RGB triplets and stores them where [_out] points to ;; -;;------------------------------------------------------------------------------------------------;; -;> [_img] = pointer to source image ;; -;> [_out] = where to store RGB triplets ;; -;;------------------------------------------------------------------------------------------------;; -;< none ;; -;;================================================================================================;; - push esi edi - mov esi, [_img] - stdcall img._.validate, esi - or eax, eax - jnz .ret - mov edi, [_out] - call img._.do_rgb -.ret: - pop edi esi - ret -endp - -;;================================================================================================;; -proc img.to_rgb _img ;////////////////////////////////////////////////////////////////////////////;; -;;------------------------------------------------------------------------------------------------;; -;? decodes image data into RGB triplets and returns pointer to memory area containing them ;; -;;------------------------------------------------------------------------------------------------;; -;> [_img] = pointer to source image ;; -;;------------------------------------------------------------------------------------------------;; -;< eax = 0 / pointer to rgb_data (array of [rgb] triplets) ;; -;;================================================================================================;; - push esi edi - mov esi, [_img] - stdcall img._.validate, esi - or eax, eax - jnz .error - - mov esi, [_img] - mov ecx, [esi + Image.Width] - imul ecx, [esi + Image.Height] - lea eax, [ecx * 3 + 4 * 3] - invoke mem.alloc, eax - or eax, eax - jz .error - - mov edi, eax - push eax - mov eax, [esi + Image.Width] - stosd - mov eax, [esi + Image.Height] - stosd - call img._.do_rgb - pop eax - pop edi esi - ret - - .error: - xor eax, eax - pop edi esi - ret -endp - -;;================================================================================================;; -proc img._.do_rgb ;///////////////////////////////////////////////////////////////////////////////;; -;;------------------------------------------------------------------------------------------------;; -;? decodes [esi + Image.Data] data into RGB triplets and stores them at [edi] ;; -;;------------------------------------------------------------------------------------------------;; -;> esi = pointer to source image ;; -;> edi = pointer to memory to store RGB triplets ;; -;;------------------------------------------------------------------------------------------------;; -;< none ;; -;;================================================================================================;; - mov ecx, [esi + Image.Width] - imul ecx, [esi + Image.Height] - mov eax, [esi + Image.Type] - jmp dword [.handlers + (eax-1)*4] - -align 16 -.bpp8i: -; 8 BPP WITH PALETTE -> 24 BPP - push ebx - mov ebx, [esi + Image.Palette] - mov esi, [esi + Image.Data] - sub ecx, 1 - jz .bpp8i.last -@@: - movzx eax, byte [esi] - add esi, 1 - mov eax, [ebx + eax*4] - mov [edi], eax - add edi, 3 - sub ecx, 1 - jnz @b -.bpp8i.last: - movzx eax, byte [esi] - mov eax, [ebx + eax*4] - mov [edi], ax - shr eax, 16 - mov [edi+2], al - pop ebx - ret - -align 16 -.bpp8g: -; 8 BPP GRAYSCALE -> 24 BPP - mov esi, [esi + Image.Data] -@@: - lodsb - mov ah, al - stosb - stosw - dec ecx - jnz @b - ret -; -;align 16 -;.bpp8a: ; considered application layer, may be changed in the future -;; 8a BPP -> 24 BPP -; mov esi, [esi + Image.Data] -;@@: -; lodsw -; mov ah, al -; stosb -; stosw -; dec ecx -; jnz @b -; 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] - - @@: - mov eax, [esi] - mov [edi], ax - shr eax, 16 - mov [edi+2], al - add esi, 4 - add edi, 3 - sub ecx, 1 - jnz @b - - @@: - ret - -align 16 -.bpp1: - push ebx ebp - mov ebp, [esi + Image.Width] - mov edx, [esi + Image.Height] - shl edx, 16 - mov ebx, [esi + Image.Palette] - mov esi, [esi + Image.Data] - .bpp1.pre: - mov dx, bp - mov ecx, 7 - .bpp1.begin: - xor eax, eax - bt [esi], ecx - adc eax, 0 - mov eax, [ebx + eax*4] - mov [edi], ax - shr eax, 16 - mov [edi + 2], al - add edi, 3 - dec dx - jz .bpp1.end_line - dec ecx - jns .bpp1.begin - mov ecx, 7 - inc esi - jmp .bpp1.begin - .bpp1.end_line: - sub edx, 0x10000 - jz .bpp1.quit - inc esi - jmp .bpp1.pre - .bpp1.quit: - pop ebp ebx - ret - -align 16 -.bpp2i: - push ebx ebp - mov ebp, [esi + Image.Width] - mov edx, [esi + Image.Height] - shl edx, 16 - mov ebx, [esi + Image.Palette] - mov esi, [esi + Image.Data] - .bpp2i.pre: - mov dx, bp - mov ecx, 3 - .bpp2i.begin: - mov eax, 3 - shl ecx, 1 - shl eax, cl - and al, [esi] - shr eax, cl - shr ecx, 1 - mov eax, [ebx + eax*4] - mov [edi], ax - shr eax, 16 - mov [edi + 2], al - add edi, 3 - dec dx - jz .bpp2i.end_line - dec ecx - jns .bpp2i.begin - mov ecx, 3 - inc esi - jmp .bpp2i.begin - .bpp2i.end_line: - sub edx, 0x10000 - jz .bpp2i.quit - inc esi - jmp .bpp2i.pre - .bpp2i.quit: - pop ebp ebx - ret - -align 16 -.bpp4i: - push ebx ebp - mov ebp, [esi + Image.Width] - mov edx, [esi + Image.Height] - shl edx, 16 - mov ebx, [esi + Image.Palette] - mov esi, [esi + Image.Data] - .bpp4i.pre: - mov dx, bp - mov ecx, 1 - .bpp4i.begin: - mov eax, 15 - shl ecx, 2 - shl eax, cl - and al, [esi] - shr eax, cl - shr ecx, 2 - mov eax, [ebx + eax*4] - mov [edi], ax - shr eax, 16 - mov [edi + 2], al - add edi, 3 - dec dx - jz .bpp4i.end_line - dec ecx - jns .bpp4i.begin - mov ecx, 1 - inc esi - jmp .bpp4i.begin - .bpp4i.end_line: - sub edx, 0x10000 - jz .bpp4i.quit - inc esi - jmp .bpp4i.pre - .bpp4i.quit: - pop ebp ebx - ret - -endp - -;;================================================================================================;; -proc img.decode _data, _length, _options ;////////////////////////////////////////////////////////;; -;;------------------------------------------------------------------------------------------------;; -;? decodes loaded into memory graphic file ;; -;;------------------------------------------------------------------------------------------------;; -;> [_data] = pointer to file in memory ;; -;> [_length] = size in bytes of memory area pointed to by [_data] ;; -;> [_options] = 0 / pointer to the structure of additional options ;; -;;------------------------------------------------------------------------------------------------;; -;< eax = 0 / pointer to image ;; -;;================================================================================================;; - push ebx - mov ebx, img.formats_table - @@: stdcall [ebx + FormatsTableEntry.Is], [_data], [_length] - or eax, eax - jnz @f - add ebx, sizeof.FormatsTableEntry - cmp dword[ebx], eax ;0 - jnz @b - pop ebx - ret - @@: mov eax, [ebx + FormatsTableEntry.Decode] - pop ebx - leave - jmp eax -endp - -;;================================================================================================;; -proc img.encode _img, _common, _specific ;////////////////////////////////////////////////////////;; -;;------------------------------------------------------------------------------------------------;; -;? encode image to some format ;; -;;------------------------------------------------------------------------------------------------;; -;> [_img] = pointer to input image ;; -;> [_common] = some most important options ;; -; 0x00 : byte : format id (defined in libimg.inc) ;; -; 0x01 : byte : fast encoding (0) / best compression ratio (255) ;; -; 0 : store uncompressed data (if supported both by the format and libimg) ;; -; 1 - 255 : use compression, if supported ;; -; this option may be ignored if any format specific options are defined ;; -; i.e. the 0 here will be ignored if some compression algorithm is specified ;; -; 0x02 : byte : flags (bitfield) ;; -; 0x01 : return an error if format specific conditions cannot be met ;; -; 0x02 : preserve current bit depth. means 8bpp/16bpp/24bpp and so on ;; -; 0x04 : delete alpha channel, if any ;; -; 0x08 : flush alpha channel with 0xff, if any; add it if none ;; -; 0x03 : byte : reserved, must be 0 ;; -;> [_specific] = 0 / pointer to the structure of format specific options ;; -; see .inc for description ;; -;;------------------------------------------------------------------------------------------------;; -;< eax = 0 / pointer to encoded data ;; -;< ecx = error code / the size of encoded data ;; -; 1 : out of memory ;; -; 2 : format is not supported ;; -; 3 : specific conditions cannot be satisfied ;; -; 4 : bit depth cannot be preserved ;; -;;================================================================================================;; - mov ebx, [_img] - - movzx eax, byte[_common] - dec eax - imul eax, sizeof.FormatsTableEntry - add eax, FormatsTableEntry.Capabilities - add eax, img.formats_table - mov eax, [eax] - test eax, 1 ; is encoding to this format supported at all? - jnz @f - mov ecx, LIBIMG_ERROR_FORMAT - jmp .error - @@: - mov ecx, [ebx + Image.Type] - mov edx, 1 - shl edx, cl - test eax, edx - jnz .bit_depth_ok - test byte[_common+2], LIBIMG_ENCODE_STRICT_BIT_DEPTH - jz @f - mov ecx, LIBIMG_ERROR_BIT_DEPTH - jmp .error - @@: - mov edx, 1 SHL Image.bpp24 - test eax, edx - jnz @f - mov ecx, LIBIMG_ERROR_BIT_DEPTH - jmp .error - @@: - stdcall img.create, [ebx + Image.Width], [ebx + Image.Height], Image.bpp24 - test eax, eax - jnz @f - mov ecx, LIBIMG_ERROR_OUT_OF_MEMORY - jmp .error - @@: - push eax - stdcall img.to_rgb2, ebx, [eax + Image.Data] - pop ebx - - .bit_depth_ok: - movzx eax, byte[_common] - dec eax - imul eax, sizeof.FormatsTableEntry - add eax, FormatsTableEntry.Encode - add eax, img.formats_table - mov eax, [eax] - stdcall eax, [_img], [_common], [_specific] - push eax ecx - cmp ebx, [_img] - je @f - stdcall img.destroy, ebx - @@: - pop ecx eax - jmp .quit - - .error: - xor eax, eax - .quit: - ret -endp - -;;================================================================================================;; -proc img.create _width, _height, _type ;//////////////////////////////////////////////////////////;; -;;------------------------------------------------------------------------------------------------;; -;? creates an Image structure and initializes some its fields ;; -;;------------------------------------------------------------------------------------------------;; -;> [_width] = width of an image in pixels ;; -;> [_height] = height of an image in pixels ;; -;> [_type] = one of the Image.bppN constants from libimg.inc ;; -;;------------------------------------------------------------------------------------------------;; -;< eax = 0 / pointer to image ;; -;;================================================================================================;; - push ecx - - stdcall img._.new - or eax, eax - jz .error - - mov ecx, [_type] - mov [eax + Image.Type], ecx - - push eax - - stdcall img._.resize_data, eax, [_width], [_height] - or eax, eax - jz .error.2 - - pop eax - jmp .ret - - .error.2: -; pop eax - stdcall img._.delete; eax - xor eax, eax - - .error: - .ret: - pop ecx - ret -endp - -;;================================================================================================;; -proc img.destroy.layer _img ;/////////////////////////////////////////////////////////////////////;; -;;------------------------------------------------------------------------------------------------;; -;? frees memory occupied by an image and all the memory regions its fields point to ;; -;? for image sequences deletes only one frame and fixes Previous/Next pointers ;; -;;------------------------------------------------------------------------------------------------;; -;> [_img] = pointer to image ;; -;;------------------------------------------------------------------------------------------------;; -;< eax = 0 (fail) / 1 (success) ;; -;;================================================================================================;; - 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 ;///////////////////////////////////////////////////////////////////////////;; -;;------------------------------------------------------------------------------------------------;; -;? frees memory occupied by an image and all the memory regions its fields point to ;; -;? follows Previous/Next pointers and deletes all the images in sequence ;; -;;------------------------------------------------------------------------------------------------;; -;> [_img] = pointer to image ;; -;;------------------------------------------------------------------------------------------------;; -;< eax = 0 (fail) / 1 (success) ;; -;;================================================================================================;; - 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 - -;;================================================================================================;; -proc img.count _img ;/////////////////////////////////////////////////////////////////////////////;; -;;------------------------------------------------------------------------------------------------;; -;? Get number of images in the list (e.g. in animated GIF file) ;; -;;------------------------------------------------------------------------------------------------;; -;> _img = pointer to image ;; -;;------------------------------------------------------------------------------------------------;; -;< eax = -1 (fail) / >0 (ok) ;; -;;================================================================================================;; - push ecx edx - mov edx, [_img] - stdcall img._.validate, edx - or eax, eax - jnz .error - - @@: mov eax, [edx + Image.Previous] - or eax, eax - jz @f - mov edx, eax - jmp @b - - @@: xor ecx, ecx - @@: inc ecx - mov eax, [edx + Image.Next] - or eax, eax - jz .exit - mov edx, eax - jmp @b - - .exit: - mov eax, ecx - pop edx ecx - ret - - .error: - or eax, -1 - pop edx ecx - ret -endp - -;;//// image processing //////////////////////////////////////////////////////////////////////////;; - -;;================================================================================================;; -proc img.lock_bits _img, _start_line, _end_line ;/////////////////////////////////////////////////;; -;;------------------------------------------------------------------------------------------------;; -;? --- TBD --- ;; -;;------------------------------------------------------------------------------------------------;; -;> --- TBD --- ;; -;;------------------------------------------------------------------------------------------------;; -;< eax = 0 / pointer to bits ;; -;;================================================================================================;; - xor eax, eax - ret -endp - -;;================================================================================================;; -proc img.unlock_bits _img, _lock ;////////////////////////////////////////////////////////////////;; -;;------------------------------------------------------------------------------------------------;; -;? --- TBD --- ;; -;;------------------------------------------------------------------------------------------------;; -;> --- TBD --- ;; -;;------------------------------------------------------------------------------------------------;; -;< eax = false / true ;; -;;================================================================================================;; - xor eax, eax - ret -endp - -;;================================================================================================;; -proc img.flip.layer _img, _flip_kind ;////////////////////////////////////////////////////////////;; -;;------------------------------------------------------------------------------------------------;; -;? Flip image layer ;; -;;------------------------------------------------------------------------------------------------;; -;> _img = pointer to image ;; -;> _flip_kind = one of FLIP_* constants ;; -;;------------------------------------------------------------------------------------------------;; -;< eax = false / true ;; -;;================================================================================================;; -locals - scanline_len dd ? -endl - - push ebx esi edi - mov ebx, [_img] - stdcall img._.validate, ebx - or eax, eax - jnz .error - - mov ecx, [ebx + Image.Height] - mov eax, [ebx + Image.Width] - call img._.get_scanline_len - mov [scanline_len], eax - - test [_flip_kind], FLIP_VERTICAL - jz .dont_flip_vert - - imul eax, ecx - sub eax, [scanline_len] - shr ecx, 1 - mov esi, [ebx + Image.Data] - lea edi, [esi + eax] - - .next_line_vert: - push ecx - - mov ecx, [scanline_len] - push ecx - shr ecx, 2 - @@: - dec ecx - js @f - mov eax, [esi] - xchg eax, [edi] - mov [esi], eax - add esi, 4 - add edi, 4 - jmp @b - @@: - - pop ecx - and ecx, 3 - jz .cont_line_vert - @@: - mov al, [esi] - xchg al, [edi] - mov [esi], al - add esi, 1 - add edi, 1 - dec ecx - jnz @b - .cont_line_vert: - - pop ecx - mov eax, [scanline_len] - shl eax, 1 - sub edi, eax - dec ecx - jnz .next_line_vert - - .dont_flip_vert: - - test [_flip_kind], FLIP_HORIZONTAL - jz .exit - - mov ecx, [ebx + Image.Height] - mov eax, [ebx + Image.Type] - mov esi, [ebx + Image.Data] - mov edi, [scanline_len] - add edi, esi - jmp dword [.handlers_horz + (eax-1)*4] - -.bpp32_horz: - sub edi, 4 - - .next_line_horz: - push ecx esi edi - - mov ecx, [scanline_len] - shr ecx, 3 - @@: mov eax, [esi] - xchg eax, [edi] - mov [esi], eax - add esi, 4 - add edi, -4 - sub ecx, 1 - jnz @b - - pop edi esi ecx - add esi, [scanline_len] - add edi, [scanline_len] - dec ecx - jnz .next_line_horz - jmp .exit - -.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 - -.bpp8ig_horz: - dec edi - .next_line_horz8ig: - push ecx esi edi - - mov ecx, [scanline_len] - shr ecx, 1 - @@: mov al, [esi] - mov dl, [edi] - mov [edi], al - mov [esi], dl - add esi, 1 - sub edi, 1 - sub ecx, 1 - jnz @b - - pop edi esi ecx - add esi, [scanline_len] - add edi, [scanline_len] - dec ecx - jnz .next_line_horz8ig - jmp .exit - -.bpp24_horz: - sub edi, 3 - .next_line_horz24: - push ecx esi edi - - mov ecx, [ebx + Image.Width] - @@: - mov al, [esi] - mov dl, [edi] - mov [edi], al - mov [esi], dl - mov al, [esi+1] - mov dl, [edi+1] - mov [edi+1], al - mov [esi+1], dl - mov al, [esi+2] - mov dl, [edi+2] - mov [edi+2], al - mov [esi+2], dl - add esi, 3 - sub edi, 3 - sub ecx, 2 - ja @b - - pop edi esi ecx - add esi, [scanline_len] - add edi, [scanline_len] - dec ecx - jnz .next_line_horz24 - jmp .exit - -.bpp1_horz: - mov edi, [scanline_len] - mov edx, [ebx + Image.Width] - and edx, 7 - neg edx - add edx, 8 - and edx, 7 -.bpp1_horz.begin: - push ebx edx esi - mov eax, 7 - add edi, esi - sub edi, 1 - mov ebx, [ebx + Image.Width] - shr ebx, 1 -.bpp1_horz.bit: - bt [edi], edx - jc @f - btr [esi], eax - jmp .bpp1_horz.right - @@: - bts [esi], eax - .bpp1_horz.right: - jnc @f - bts [edi], edx - jmp .bpp1_horz.bit_done - @@: - btr [edi], edx - .bpp1_horz.bit_done: - inc edx - and edx, 7 - jnz @f - dec edi - @@: - dec eax - jns @f - mov eax, 7 - inc esi - @@: - dec ebx - jnz .bpp1_horz.bit - - pop esi edx ebx - add esi, [scanline_len] - mov edi, [scanline_len] - dec ecx - jnz .bpp1_horz.begin - jmp .exit - - -.bpp2i_horz: - mov edi, [scanline_len] - mov edx, [ebx + Image.Width] - and edx, 3 - neg edx - add edx, 4 - and edx, 3 -.bpp2i_horz.begin: - push ebx edx esi - mov eax, 3 - add edi, esi - sub edi, 1 - mov ebx, [ebx + Image.Width] - shr ebx, 1 -.bpp2i_horz.pixel: - push ebx ecx - mov ebx, 3 - mov ecx, edx - shl ebx, cl - shl ebx, cl - and bl, [edi] - shr ebx, cl - shr ebx, cl - mov bh, 3 - mov ecx, eax - shl ebx, cl - shl ebx, cl - not bh - and bh, [esi] - or bl, bh - mov bh, [esi] - mov [esi], bl - shr ebx, 8 - shr ebx, cl - shr ebx, cl - and ebx, 3 - mov bh, 3 - mov ecx, edx - shl ebx, cl - shl ebx, cl - not bh - and bh, [edi] - or bl, bh - mov [edi], bl - pop ecx ebx - .bpp2i_horz.pixel_done: - inc edx - and edx, 3 - jnz @f - dec edi - @@: - dec eax - jns @f - mov eax, 3 - inc esi - @@: - dec ebx - jnz .bpp2i_horz.pixel - - pop esi edx ebx - add esi, [scanline_len] - mov edi, [scanline_len] - dec ecx - jnz .bpp2i_horz.begin - jmp .exit - - -.bpp4i_horz: - mov edi, [scanline_len] - mov edx, [ebx + Image.Width] - and edx, 1 - neg edx - add edx, 2 - and edx, 1 -.bpp4i_horz.begin: - push ebx edx esi - mov eax, 1 - add edi, esi - sub edi, 1 - mov ebx, [ebx + Image.Width] - shr ebx, 1 -.bpp4i_horz.pixel: - push ebx ecx - mov ebx, 15 - mov ecx, edx - shl ecx, 2 - shl ebx, cl - and bl, [edi] - shr ebx, cl - mov bh, 15 - mov ecx, eax - shl ecx, 2 - shl ebx, cl - not bh - and bh, [esi] - or bl, bh - mov bh, [esi] - mov [esi], bl - shr ebx, 8 - shr ebx, cl - and ebx, 15 - mov bh, 15 - mov ecx, edx - shl ecx, 2 - shl ebx, cl - not bh - and bh, [edi] - or bl, bh - mov [edi], bl - pop ecx ebx - .bpp4i_horz.pixel_done: - inc edx - and edx, 1 - jnz @f - dec edi - @@: - dec eax - jns @f - mov eax, 1 - inc esi - @@: - dec ebx - jnz .bpp4i_horz.pixel - - pop esi edx ebx - add esi, [scanline_len] - mov edi, [scanline_len] - dec ecx - jnz .bpp4i_horz.begin - jmp .exit - - - .exit: - xor eax, eax - inc eax - pop edi esi ebx - ret - - .error: - xor eax, eax - pop edi esi ebx - ret -endp - -;;================================================================================================;; -proc img.flip _img, _flip_kind ;//////////////////////////////////////////////////////////////////;; -;;------------------------------------------------------------------------------------------------;; -;? 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 ;; -;;================================================================================================;; -locals - scanline_len_old dd ? - scanline_len_new dd ? - scanline_pixels_new dd ? - line_buffer dd ? - pixels_ptr dd ? -endl - - mov [line_buffer], 0 - - push ebx esi edi - mov ebx, [_img] - stdcall img._.validate, ebx - or eax, eax - jnz .error - - cmp [_rotate_kind], ROTATE_90_CCW - je .rotate_ccw_low - cmp [_rotate_kind], ROTATE_90_CW - je .rotate_cw_low - cmp [_rotate_kind], ROTATE_180 - je .flip - jmp .exit - - .rotate_ccw_low: - mov eax, [ebx + Image.Height] - mov [scanline_pixels_new], eax - call img._.get_scanline_len - mov [scanline_len_new], eax - - invoke mem.alloc, eax - or eax, eax - jz .error - mov [line_buffer], eax - - mov eax, [ebx + Image.Width] - mov ecx, eax - call img._.get_scanline_len - mov [scanline_len_old], eax - - mov eax, [scanline_len_new] - imul eax, ecx - add eax, [ebx + Image.Data] - mov [pixels_ptr], eax - - cmp [ebx + Image.Type], Image.bpp1 - jz .rotate_ccw1 - cmp [ebx + Image.Type], Image.bpp2i - jz .rotate_ccw2i - cmp [ebx + Image.Type], Image.bpp4i - jz .rotate_ccw4i - cmp [ebx + Image.Type], Image.bpp8i - jz .rotate_ccw8ig - cmp [ebx + Image.Type], Image.bpp8g - jz .rotate_ccw8ig - 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 - push ecx - - mov edx, [scanline_len_old] - add [scanline_len_old], -4 - - mov ecx, [scanline_pixels_new] - mov esi, [ebx + Image.Data] - mov edi, [line_buffer] - @@: mov eax, [esi] - stosd - add esi, edx - dec ecx - jnz @b - - mov eax, [scanline_pixels_new] - mov edi, [ebx + Image.Data] - lea esi, [edi + 4] - mov edx, [scanline_len_old] - shr edx, 2 - @@: mov ecx, edx - rep movsd - add esi, 4 - dec eax - jnz @b - - mov eax, [scanline_len_new] - sub [pixels_ptr], eax - mov ecx, [scanline_pixels_new] - mov esi, [line_buffer] - mov edi, [pixels_ptr] - rep movsd - - pop ecx - jmp .next_column_ccw_low - -.rotate_ccw8ig: - .next_column_ccw_low8ig: - dec ecx - js .exchange_dims - push ecx - - mov edx, [scanline_len_old] - add [scanline_len_old], -1 - - mov ecx, [scanline_pixels_new] - mov esi, [ebx + Image.Data] - mov edi, [line_buffer] - @@: mov al, [esi] - mov [edi], al - add esi, edx - add edi, 1 - sub ecx, 1 - jnz @b - - mov eax, [scanline_pixels_new] - mov edi, [ebx + Image.Data] - lea esi, [edi + 1] - 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_low8ig - -.rotate_ccw24: - .next_column_ccw_low24: - dec ecx - js .exchange_dims - push ecx - - mov edx, [scanline_len_old] - add [scanline_len_old], -3 - - mov ecx, [scanline_pixels_new] - mov esi, [ebx + Image.Data] - mov edi, [line_buffer] - @@: mov al, [esi] - mov [edi], al - mov al, [esi+1] - mov [edi+1], al - mov al, [esi+2] - mov [edi+2], al - add esi, edx - add edi, 3 - sub ecx, 1 - jnz @b - - mov eax, [scanline_pixels_new] - mov edi, [ebx + Image.Data] - lea esi, [edi + 3] - 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_ccw_low24 - -.rotate_ccw1: - push ecx edx - - mov eax, [ebx + Image.Height] - add eax, 7 - shr eax, 3 - imul eax, [ebx + Image.Width] - push eax ; save new data size - - invoke mem.alloc, eax - or eax, eax - jz .error - push eax ; save pointer to new data - - mov ecx, [ebx + Image.Width] - and ecx, 7 - neg ecx - add ecx, 8 - and ecx, 7 - - mov edi, eax - mov esi, [ebx + Image.Data] - mov eax, 7 - mov edx, [scanline_len_old] - dec edx - add esi, edx - - .rotate_ccw1.begin: - bt [esi], ecx - jc .rotate_ccw1.one - .rotate_ccw1.zero: - btr [edi], eax - jmp @f - .rotate_ccw1.one: - bts [edi], eax - @@: - add esi, [scanline_len_old] - dec [scanline_pixels_new] - jz .rotate_ccw1.end_of_line - sub eax, 1 - adc edi, 0 - and eax, 7 - jmp .rotate_ccw1.begin - .rotate_ccw1.end_of_line: - inc edi - mov eax, [ebx + Image.Height] - mov [scanline_pixels_new], eax - mov eax, 7 - inc ecx - and ecx, 7 - jz @f - mov esi, [ebx + Image.Data] - add esi, edx - jmp .rotate_ccw1.begin - @@: - dec edx - js .rotate_ccw1.quit - mov esi, [ebx + Image.Data] - add esi, edx - jmp .rotate_ccw1.begin - .rotate_ccw1.quit: - pop esi ; get pointer to new data - mov edi, [ebx + Image.Data] - pop ecx ; get new data size - rep movsb - invoke mem.free, esi - pop edx ecx - jmp .exchange_dims - - -.rotate_ccw2i: - push ecx edx - - mov eax, [ebx + Image.Height] - add eax, 3 - shr eax, 2 - imul eax, [ebx + Image.Width] - push eax ; save new data size - - invoke mem.alloc, eax - or eax, eax - jz .error - push eax ; save pointer to new data - - mov ecx, [ebx + Image.Width] - and ecx, 3 - neg ecx - add ecx, 4 - and ecx, 3 - - mov edi, eax - mov esi, [ebx + Image.Data] - mov eax, 3 - mov edx, [scanline_len_old] - dec edx - add esi, edx - - .rotate_ccw2i.begin: - push ebx ecx - mov ebx, 3 - shl ebx, cl - shl ebx, cl - and bl, [esi] - shr ebx, cl - shr ebx, cl - mov bh, 3 - mov ecx, eax - shl ebx, cl - shl ebx, cl - not bh - and bh, [edi] - or bl, bh - mov [edi], bl - pop ecx ebx - - add esi, [scanline_len_old] - dec [scanline_pixels_new] - jz .rotate_ccw2i.end_of_line - sub eax, 1 - adc edi, 0 - and eax, 3 - jmp .rotate_ccw2i.begin - .rotate_ccw2i.end_of_line: - inc edi - mov eax, 3 - mov esi, [ebx + Image.Height] - mov [scanline_pixels_new], esi - inc ecx - and ecx, 3 - jz @f - mov esi, [ebx + Image.Data] - add esi, edx - jmp .rotate_ccw2i.begin - @@: - dec edx - js .rotate_ccw2i.quit - mov esi, [ebx + Image.Data] - add esi, edx - jmp .rotate_ccw2i.begin - .rotate_ccw2i.quit: - pop esi ; get pointer to new data - mov edi, [ebx + Image.Data] - pop ecx ; get new data size - rep movsb - invoke mem.free, esi - pop edx ecx - jmp .exchange_dims - - -.rotate_ccw4i: - push ecx edx - - mov eax, [ebx + Image.Height] - add eax, 1 - shr eax, 1 - imul eax, [ebx + Image.Width] - push eax ; save new data size - - invoke mem.alloc, eax - or eax, eax - jz .error - push eax ; save pointer to new data - - mov ecx, [ebx + Image.Width] - and ecx, 1 - neg ecx - add ecx, 2 - and ecx, 1 - - mov edi, eax - mov esi, [ebx + Image.Data] - mov eax, 1 - mov edx, [scanline_len_old] - dec edx - add esi, edx - - .rotate_ccw4i.begin: - push ebx ecx - mov ebx, 15 - shl ecx, 2 - shl ebx, cl - and bl, [esi] - shr ebx, cl - mov bh, 15 - mov ecx, eax - shl ecx, 2 - shl ebx, cl - not bh - and bh, [edi] - or bl, bh - mov [edi], bl - pop ecx ebx - - add esi, [scanline_len_old] - dec [scanline_pixels_new] - jz .rotate_ccw4i.end_of_line - sub eax, 1 - adc edi, 0 - and eax, 1 - jmp .rotate_ccw4i.begin - .rotate_ccw4i.end_of_line: - inc edi - mov eax, 1 - mov esi, [ebx + Image.Height] - mov [scanline_pixels_new], esi - inc ecx - and ecx, 1 - jz @f - mov esi, [ebx + Image.Data] - add esi, edx - jmp .rotate_ccw4i.begin - @@: - dec edx - js .rotate_ccw4i.quit - mov esi, [ebx + Image.Data] - add esi, edx - jmp .rotate_ccw4i.begin - .rotate_ccw4i.quit: - pop esi ; get pointer to new data - mov edi, [ebx + Image.Data] - pop ecx ; get new data size - rep movsb - invoke mem.free, esi - pop edx ecx - jmp .exchange_dims - - - - .rotate_cw_low: - mov eax, [ebx + Image.Height] - mov [scanline_pixels_new], eax - call img._.get_scanline_len - mov [scanline_len_new], eax - - invoke mem.alloc, eax - or eax, eax - jz .error - mov [line_buffer], eax - - mov eax, [ebx + Image.Width] - mov ecx, eax - call img._.get_scanline_len - mov [scanline_len_old], eax - - mov eax, [scanline_len_new] - imul eax, ecx - add eax, [ebx + Image.Data] - mov [pixels_ptr], eax - - cmp [ebx + Image.Type], Image.bpp1 - jz .rotate_cw1 - cmp [ebx + Image.Type], Image.bpp2i - jz .rotate_cw2i - cmp [ebx + Image.Type], Image.bpp4i - jz .rotate_cw4i - cmp [ebx + Image.Type], Image.bpp8i - jz .rotate_cw8ig - cmp [ebx + Image.Type], Image.bpp8g - jz .rotate_cw8ig - 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 - push ecx - - mov edx, [scanline_len_old] - add [scanline_len_old], -4 - - mov ecx, [scanline_pixels_new] - mov esi, [pixels_ptr] - add esi, -4 - mov edi, [line_buffer] - @@: mov eax, [esi] - stosd - sub esi, edx - dec ecx - jnz @b - - mov eax, [scanline_pixels_new] - dec eax - mov edi, [ebx + Image.Data] - add edi, [scanline_len_old] - lea esi, [edi + 4] - mov edx, [scanline_len_old] - shr edx, 2 - @@: mov ecx, edx - rep movsd - add esi, 4 - dec eax - jnz @b - - mov eax, [scanline_len_new] - sub [pixels_ptr], eax - mov ecx, [scanline_pixels_new] - mov esi, [line_buffer] - mov edi, [pixels_ptr] - rep movsd - - pop ecx - jmp .next_column_cw_low - -.rotate_cw8ig: - .next_column_cw_low8ig: - dec ecx - js .exchange_dims - push ecx - - mov edx, [scanline_len_old] - add [scanline_len_old], -1 - - mov ecx, [scanline_pixels_new] - mov esi, [pixels_ptr] - add esi, -1 - mov edi, [line_buffer] - @@: mov al, [esi] - mov [edi], al - sub esi, edx - add edi, 1 - 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 + 1] - 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, 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_low8ig - -.rotate_cw24: - .next_column_cw_low24: - dec ecx - js .exchange_dims - push ecx - - mov edx, [scanline_len_old] - add [scanline_len_old], -3 - - mov ecx, [scanline_pixels_new] - mov esi, [pixels_ptr] - add esi, -3 - mov edi, [line_buffer] - @@: mov al, [esi] - mov [edi], al - mov al, [esi+1] - mov [edi+1], al - mov al, [esi+2] - mov [edi+2], al - sub esi, edx - add edi, 3 - 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 + 3] - 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_low24 - - -.rotate_cw1: - push ecx edx - - mov eax, [ebx + Image.Height] - add eax, 7 - shr eax, 3 - imul [ebx + Image.Width] - push eax ; save new data size - - invoke mem.alloc, eax - or eax, eax - jz .error - push eax ; save pointer to new data - - mov edi, eax - mov esi, [ebx + Image.Data] - mov eax, [ebx + Image.Height] - dec eax - imul eax, [scanline_len_old] - add esi, eax - mov eax, 7 - mov ecx, 7 - mov edx, 0 - - .rotate_cw1.begin: - bt [esi], ecx - jc .rotate_cw1.one - .rotate_cw1.zero: - btr [edi], eax - jmp @f - .rotate_cw1.one: - bts [edi], eax - @@: - sub esi, [scanline_len_old] - dec [scanline_pixels_new] - jz .rotate_cw1.end_of_line - sub eax, 1 - adc edi, 0 - and eax, 7 - jmp .rotate_cw1.begin - .rotate_cw1.end_of_line: - inc edi - mov eax, [ebx + Image.Height] - mov [scanline_pixels_new], eax - mov eax, 7 - dec ecx - jns @f - mov ecx, 7 - inc edx - cmp edx, [scanline_len_old] - je .rotate_cw1.quit - @@: - mov esi, [ebx + Image.Height] - dec esi - imul esi, [scanline_len_old] - add esi, [ebx + Image.Data] - add esi, edx - jmp .rotate_cw1.begin - .rotate_cw1.quit: - pop eax ; get pointer to new data - mov esi, eax - mov edi, [ebx + Image.Data] - pop ecx ; get new data size - rep movsb - invoke mem.free, eax - pop edx ecx - jmp .exchange_dims - - -.rotate_cw2i: - push ecx edx - - mov eax, [ebx + Image.Height] - add eax, 3 - shr eax, 2 - imul [ebx + Image.Width] - push eax ; save new data size - - invoke mem.alloc, eax - or eax, eax - jz .error - push eax ; save pointer to new data - - mov edi, eax - mov esi, [ebx + Image.Data] - mov eax, [ebx + Image.Height] - dec eax - imul eax, [scanline_len_old] - add esi, eax - mov eax, 3 - mov ecx, 3 - mov edx, 0 - - .rotate_cw2i.begin: - push ebx ecx - mov ebx, 3 - shl ebx, cl - shl ebx, cl - and bl, [esi] - shr ebx, cl - shr ebx, cl - mov bh, 3 - mov ecx, eax - shl ebx, cl - shl ebx, cl - not bh - and bh, [edi] - or bl, bh - mov [edi], bl - pop ecx ebx - - sub esi, [scanline_len_old] - dec [scanline_pixels_new] - jz .rotate_cw2i.end_of_line - sub eax, 1 - adc edi, 0 - and eax, 3 - jmp .rotate_cw2i.begin - .rotate_cw2i.end_of_line: - inc edi - mov eax, [ebx + Image.Height] - mov [scanline_pixels_new], eax - mov eax, 3 - dec ecx - jns @f - mov ecx, 3 - inc edx - cmp edx, [scanline_len_old] - je .rotate_cw2i.quit - @@: - mov esi, [ebx + Image.Height] - dec esi - imul esi, [scanline_len_old] - add esi, [ebx + Image.Data] - add esi, edx - jmp .rotate_cw2i.begin - .rotate_cw2i.quit: - pop eax ; get pointer to new data - mov esi, eax - mov edi, [ebx + Image.Data] - pop ecx ; get new data size - rep movsb - invoke mem.free, eax - pop edx ecx - jmp .exchange_dims - - -.rotate_cw4i: - push ecx edx - - mov eax, [ebx + Image.Height] - add eax, 1 - shr eax, 1 - imul [ebx + Image.Width] - push eax ; save new data size - - invoke mem.alloc, eax - or eax, eax - jz .error - push eax ; save pointer to new data - - mov edi, eax - mov esi, [ebx + Image.Data] - mov eax, [ebx + Image.Height] - dec eax - imul eax, [scanline_len_old] - add esi, eax - mov eax, 1 - mov ecx, 1 - mov edx, 0 - - .rotate_cw4i.begin: - push ebx ecx - mov ebx, 15 - shl ecx, 2 - shl ebx, cl - and bl, [esi] - shr ebx, cl - mov bh, 15 - mov ecx, eax - shl ecx, 2 - shl ebx, cl - not bh - and bh, [edi] - or bl, bh - mov [edi], bl - pop ecx ebx - - sub esi, [scanline_len_old] - dec [scanline_pixels_new] - jz .rotate_cw4i.end_of_line - sub eax, 1 - adc edi, 0 - and eax, 1 - jmp .rotate_cw4i.begin - .rotate_cw4i.end_of_line: - inc edi - mov eax, [ebx + Image.Height] - mov [scanline_pixels_new], eax - mov eax, 1 - dec ecx - jns @f - mov ecx, 1 - inc edx - cmp edx, [scanline_len_old] - je .rotate_cw4i.quit - @@: - mov esi, [ebx + Image.Height] - dec esi - imul esi, [scanline_len_old] - add esi, [ebx + Image.Data] - add esi, edx - jmp .rotate_cw4i.begin - .rotate_cw4i.quit: - pop eax ; get pointer to new data - mov esi, eax - mov edi, [ebx + Image.Data] - pop ecx ; get new data size - rep movsb - invoke mem.free, eax - pop edx ecx - jmp .exchange_dims - - - .flip: - jmp .exit - - .exchange_dims: - push [ebx + Image.Width] [ebx + Image.Height] - pop [ebx + Image.Width] [ebx + Image.Height] - - .exit: - invoke mem.free, [line_buffer] - xor eax, eax - inc eax - pop edi esi ebx - ret - - .error: - invoke mem.free, [line_buffer] - xor eax, eax - pop edi esi ebx - 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 - push eax - mov eax, [ebx + Image.Width] - imul eax, [_ypos] - add eax, [_xpos] - call img._.get_scanline_len - add eax, [ebx + Image.Data] - mov edx, [_x - 2] - mov dx, word [_y] - mov esi, [ebx + Image.Type] - mov esi, [type2bpp + (esi-1)*4] - mov edi, [ebx + Image.Palette] - xchg eax, ebx - pop eax - push ebp - push 65 - pop ebp - xchg eax, ebp - int 40h - pop ebp -.done: - pop edi esi ebx - ret -endp - - -align 4 -img.formats_table: - .bmp dd LIBIMG_FORMAT_BMP, img.is.bmp, img.decode.bmp, img.encode.bmp, 1 + (1 SHL Image.bpp24) + (1 SHL Image.bpp32) - .ico dd LIBIMG_FORMAT_ICO, img.is.ico, img.decode.ico_cur, img.encode.ico, 0 - .cur dd LIBIMG_FORMAT_CUR, img.is.cur, img.decode.ico_cur, img.encode.cur, 0 - .gif dd LIBIMG_FORMAT_GIF, img.is.gif, img.decode.gif, img.encode.gif, 0 - .png dd LIBIMG_FORMAT_PNG, img.is.png, img.decode.png, img.encode.png, 1 + (1 SHL Image.bpp24) - .jpg dd LIBIMG_FORMAT_JPEG, img.is.jpg, img.decode.jpg, img.encode.jpg, 0 - .tga dd LIBIMG_FORMAT_TGA, img.is.tga, img.decode.tga, img.encode.tga, 0 - .pcx dd LIBIMG_FORMAT_PCX, img.is.pcx, img.decode.pcx, img.encode.pcx, 0 - .xcf dd LIBIMG_FORMAT_XCF, img.is.xcf, img.decode.xcf, img.encode.xcf, 0 - .tiff dd LIBIMG_FORMAT_TIFF, img.is.tiff, img.decode.tiff, img.encode.tiff,0 - .pnm dd LIBIMG_FORMAT_PNM, img.is.pnm, img.decode.pnm, img.encode.pnm, 1 + (1 SHL Image.bpp1) + (1 SHL Image.bpp8g) + (1 SHL Image.bpp24) - .wbmp dd LIBIMG_FORMAT_WBMP, img.is.wbmp, img.decode.wbmp, img.encode.wbmp,0 - .xbm dd LIBIMG_FORMAT_XBM, img.is.xbm, img.decode.xbm, img.encode.xbm, 0 - .z80 dd LIBIMG_FORMAT_Z80, img.is.z80, img.decode.z80, img.encode.z80, 0 ;this must be the last entry as there are no signatures in z80 screens at all - dd 0 - -align 4 -img.types_table: ; entries order must correspond to type defnitions in libimg.inc - dd 0 ; there is no Image.bpp* = 0 - .bpp8i dd (1 SHL Image.bpp24) - .bpp24 dd (1 SHL Image.bpp24) OR (1 SHL Image.bpp8g) - .bpp32 dd (1 SHL Image.bpp24) - .bpp15 dd (1 SHL Image.bpp24) - .bpp16 dd (1 SHL Image.bpp24) - .bpp1 dd (1 SHL Image.bpp24) - .bpp8g dd (1 SHL Image.bpp24) OR (1 SHL Image.bpp1 ) - .bpp8a dd (1 SHL Image.bpp24) - -;;================================================================================================;; -;;////////////////////////////////////////////////////////////////////////////////////////////////;; -;;================================================================================================;; -;! Below are private procs you should never call directly from your code ;; -;;================================================================================================;; -;;////////////////////////////////////////////////////////////////////////////////////////////////;; -;;================================================================================================;; - - -;;================================================================================================;; -proc img._.validate, _img ;///////////////////////////////////////////////////////////////////////;; -;;------------------------------------------------------------------------------------------------;; -;? --- TBD --- ;; -;;------------------------------------------------------------------------------------------------;; -;> --- TBD --- ;; -;;------------------------------------------------------------------------------------------------;; -;< --- TBD --- ;; -;;================================================================================================;; - xor eax, eax - ret -endp - -;;================================================================================================;; -proc img._.new ;//////////////////////////////////////////////////////////////////////////////////;; -;;------------------------------------------------------------------------------------------------;; -;? --- TBD --- ;; -;;------------------------------------------------------------------------------------------------;; -;> --- TBD --- ;; -;;------------------------------------------------------------------------------------------------;; -;< eax = 0 / pointer to image ;; -;;================================================================================================;; - invoke mem.alloc, sizeof.Image - test eax, eax - jz @f - push ecx - 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 - pop ecx -@@: - ret -endp - -;;================================================================================================;; -proc img._.delete _img ;//////////////////////////////////////////////////////////////////////////;; -;;------------------------------------------------------------------------------------------------;; -;? --- TBD --- ;; -;;------------------------------------------------------------------------------------------------;; -;> --- TBD --- ;; -;;------------------------------------------------------------------------------------------------;; -;< eax = false / true ;; -;;================================================================================================;; - push edx - mov edx, [_img] - cmp [edx + Image.Data], 0 - je @f - invoke mem.free, [edx + Image.Data] - @@: cmp [edx + Image.Extended], 0 - je @f - invoke mem.free, [edx + Image.Extended] - @@: invoke mem.free, edx - pop edx - ret -endp - -;;================================================================================================;; -proc img._.resize_data _img, _width, _height ;////////////////////////////////////////////////////;; -;;------------------------------------------------------------------------------------------------;; -;? --- TBD --- ;; -;;------------------------------------------------------------------------------------------------;; -;> --- TBD --- ;; -;;------------------------------------------------------------------------------------------------;; -;< --- TBD --- ;; -;;================================================================================================;; - push ebx esi - mov ebx, [_img] - mov eax, [_height] -; our memory is limited, [_width]*[_height] must not overflow -; image with width or height greater than 65535 is most likely bogus - cmp word [_width+2], 0 - jnz .error - cmp word [_height+2], 0 - jnz .error - imul eax, [_width] - test eax, eax - jz .error - cmp [ebx + Image.Type], Image.bpp1 - jz .bpp1 - cmp [ebx + Image.Type], Image.bpp2i - jz .bpp2i - cmp [ebx + Image.Type], Image.bpp4i - jz .bpp4i - cmp [ebx + Image.Type], Image.bpp8i - jz .bpp8i - cmp [ebx + Image.Type], Image.bpp8g - jz .bpp8g - cmp [ebx + Image.Type], Image.bpp8a - jz .bpp8a - cmp [ebx + Image.Type], Image.bpp24 - jz .bpp24 -.bpp32: - shl eax, 2 - jmp @f -.bpp24: - lea eax, [eax*3] - jmp @f -.bpp8i: - add eax, 256*4 ; for palette -.bpp8g: - jmp @f -.bpp8a: - shl eax, 1 - jmp @f -.bpp4i: - mov eax, [_width] - add eax, 1 - shr eax, 1 - imul eax, [_height] - mov ecx, eax - mov eax, [_height] - add eax, 1 - shr eax, 1 - imul eax, [_width] - cmp eax, ecx - jge .bpp4i.skip - mov eax, ecx - .bpp4i.skip: - add eax, 16*4 ; for palette - jmp @f -.bpp2i: - mov eax, [_width] - add eax, 3 - shr eax, 2 - imul eax, [_height] - mov ecx, eax - mov eax, [_height] - add eax, 3 - shr eax, 2 - imul eax, [_width] - cmp eax, ecx - jge .bpp2i.skip - mov eax, ecx - .bpp2i.skip: - add eax, 4*4 ; for palette - jmp @f -.bpp1: - mov eax, [_width] - add eax, 7 - shr eax, 3 - imul eax, [_height] - mov ecx, eax - mov eax, [_height] - add eax, 7 - shr eax, 3 - imul eax, [_width] - cmp eax, ecx - jge .bpp1.skip - mov eax, ecx - .bpp1.skip: - - add eax, 2*4 ; for palette -@@: - mov esi, eax - invoke mem.realloc, [ebx + Image.Data], eax - or eax, eax - jz .error - - mov [ebx + Image.Data], eax - push [_width] - pop [ebx + Image.Width] - push [_height] - pop [ebx + Image.Height] - cmp [ebx + Image.Type], Image.bpp8i - jnz @f - lea esi, [eax + esi - 256*4] - mov [ebx + Image.Palette], esi - jmp .ret -@@: - cmp [ebx + Image.Type], Image.bpp1 - jnz @f - lea esi, [eax + esi - 2*4] - mov [ebx + Image.Palette], esi - jmp .ret -@@: - cmp [ebx + Image.Type], Image.bpp2i - jnz @f - lea esi, [eax + esi - 4*4] - mov [ebx + Image.Palette], esi - jmp .ret -@@: - cmp [ebx + Image.Type], Image.bpp4i - jnz .ret - lea esi, [eax + esi - 16*4] - mov [ebx + Image.Palette], esi - jmp .ret - - .error: - xor eax, eax - .ret: - pop esi ebx - ret -endp - -;;================================================================================================;; -img._.get_scanline_len: ;/////////////////////////////////////////////////////////////////////////;; -;;------------------------------------------------------------------------------------------------;; -;? --- TBD --- ;; -;;------------------------------------------------------------------------------------------------;; -;> --- TBD --- ;; -;;------------------------------------------------------------------------------------------------;; -;< --- TBD --- ;; -;;================================================================================================;; - cmp [ebx + Image.Type], Image.bpp1 - jz .bpp1.1 - cmp [ebx + Image.Type], Image.bpp2i - jz .bpp2i.1 - cmp [ebx + Image.Type], Image.bpp4i - jz .bpp4i.1 - cmp [ebx + Image.Type], Image.bpp8i - jz .bpp8.1 - cmp [ebx + Image.Type], Image.bpp8g - jz .bpp8.1 - cmp [ebx + Image.Type], Image.bpp8a - jz .bpp8a.1 - cmp [ebx + Image.Type], Image.bpp24 - jz .bpp24.1 - add eax, eax - cmp [ebx + Image.Type], Image.bpp32 - jnz .quit - add eax, eax - jmp .quit -.bpp24.1: - lea eax, [eax*3] - jmp .quit -.bpp1.1: - add eax, 7 - shr eax, 3 - jmp .quit -.bpp2i.1: - add eax, 3 - shr eax, 2 - jmp .quit -.bpp4i.1: - add eax, 1 - shr eax, 1 - jmp .quit -.bpp8a.1: - shl eax, 1 -.bpp8.1: -.quit: - ret - - -;;================================================================================================;; -;;////////////////////////////////////////////////////////////////////////////////////////////////;; -;;================================================================================================;; -;! Below is private data you should never use directly from your code ;; -;;================================================================================================;; -;;////////////////////////////////////////////////////////////////////////////////////////////////;; -;;================================================================================================;; - -align 4 -type2bpp dd 8, 24, 32, 15, 16, 1, 9, 2, 4 -img._.do_rgb.handlers: - dd img._.do_rgb.bpp8i - 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 - dd img._.do_rgb.bpp1 - dd img._.do_rgb.bpp8g - dd img._.do_rgb.bpp2i - dd img._.do_rgb.bpp4i - -img.flip.layer.handlers_horz: - dd img.flip.layer.bpp8ig_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 - dd img.flip.layer.bpp1_horz - dd img.flip.layer.bpp8ig_horz - dd img.flip.layer.bpp2i_horz - dd img.flip.layer.bpp4i_horz - -;;================================================================================================;; -;;////////////////////////////////////////////////////////////////////////////////////////////////;; -;;================================================================================================;; -;! Exported functions section ;; -;;================================================================================================;; -;;////////////////////////////////////////////////////////////////////////////////////////////////;; -;;================================================================================================;; - - -align 4 -@EXPORT: - -export \ - lib_init , 'lib_init' , \ - 0x00050007 , '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.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.flip.layer , 'img_flip_layer' , \ - img.rotate , 'img_rotate' , \ - img.rotate.layer , 'img_rotate_layer' , \ - img.draw , 'img_draw' , \ - img.scale , 'img_scale' , \ - img.convert , 'img_convert' , \ - img.formats_table, 'img_formats_table' - -; import from deflate unpacker -; is initialized only when PNG loading is requested -align 16 -@IMPORT: - -library archiver, 'archiver.obj' -import archiver, \ - deflate_unpack2, 'deflate_unpack2',\ - deflateInit2, 'deflateInit2',\ - deflateReset, 'deflateReset',\ - deflate, 'deflate',\ - deflateEnd, 'deflateEnd',\ - calc_crc32, 'calc_crc32' - -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 -color_table_2 rd 256 -color_table_3 rd 256 -color_table_4 rd 256 +;;================================================================================================;; +;;//// libimg.asm //// (c) mike.dld, 2007-2008, (c) diamond, 2009, (c) dunkaist, 2011-2013 ///////;; +;;================================================================================================;; +;; ;; +;; 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 . ;; +;; ;; +;;================================================================================================;; + + +format MS COFF + +public @EXPORT as 'EXPORTS' + +include '../../../../struct.inc' +include '../../../../proc32.inc' +include '../../../../macros.inc' +include '../../../../config.inc' +;include '../../../../debug.inc' +purge section,mov,add,sub + +include 'libimg.inc' + +section '.flat' code readable align 16 + +include 'bmp/bmp.asm' +include 'gif/gif.asm' +include 'jpeg/jpeg.asm' +include 'png/png.asm' +include 'tga/tga.asm' +include 'z80/z80.asm' +include 'ico_cur/ico_cur.asm' +include 'pcx/pcx.asm' +include 'xcf/xcf.asm' +include 'tiff/tiff.asm' +include 'pnm/pnm.asm' +include 'wbmp/wbmp.asm' +include 'xbm/xbm.asm' + +include 'scale.asm' +include 'convert.asm' + +;;================================================================================================;; +proc lib_init ;///////////////////////////////////////////////////////////////////////////////////;; +;;------------------------------------------------------------------------------------------------;; +;? Library entry point (called after library load) ;; +;;------------------------------------------------------------------------------------------------;; +;> eax = pointer to memory allocation routine ;; +;> ebx = pointer to memory freeing routine ;; +;> ecx = pointer to memory reallocation routine ;; +;> edx = pointer to library loading routine ;; +;;------------------------------------------------------------------------------------------------;; +;< eax = 1 (fail) / 0 (ok) (library initialization result) ;; +;;================================================================================================;; + mov [mem.alloc], eax + mov [mem.free], ebx + mov [mem.realloc], ecx + mov [dll.load], edx + + or edx,edx + jz @f + invoke dll.load, @IMPORT + @@: + + 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 + +;;================================================================================================;; +proc img.is_img _data, _length ;//////////////////////////////////////////////////////////////////;; +;;------------------------------------------------------------------------------------------------;; +;? --- TBD --- ;; +;;------------------------------------------------------------------------------------------------;; +;> --- TBD --- ;; +;;------------------------------------------------------------------------------------------------;; +;< --- TBD --- ;; +;;================================================================================================;; + push ebx + mov ebx, img.formats_table + @@: stdcall [ebx + FormatsTableEntry.Is], [_data], [_length] + or eax, eax + jnz @f + add ebx, sizeof.FormatsTableEntry + cmp dword[ebx], 0 + jnz @b + xor eax, eax + @@: pop ebx + ret +endp + +;;================================================================================================;; +proc img.info _data, _length ;////////////////////////////////////////////////////////////////////;; +;;------------------------------------------------------------------------------------------------;; +;? --- TBD --- ;; +;;------------------------------------------------------------------------------------------------;; +;> --- TBD --- ;; +;;------------------------------------------------------------------------------------------------;; +;< --- TBD --- ;; +;;================================================================================================;; + xor eax, eax + ret +endp + +;;================================================================================================;; +proc img.from_file _filename ;////////////////////////////////////////////////////////////////////;; +;;------------------------------------------------------------------------------------------------;; +;? --- TBD --- ;; +;;------------------------------------------------------------------------------------------------;; +;> --- TBD --- ;; +;;------------------------------------------------------------------------------------------------;; +;< eax = 0 / pointer to image ;; +;;================================================================================================;; + xor eax, eax + ret +endp + +;;================================================================================================;; +proc img.to_file _img, _filename ;////////////////////////////////////////////////////////////////;; +;;------------------------------------------------------------------------------------------------;; +;? --- TBD --- ;; +;;------------------------------------------------------------------------------------------------;; +;> --- TBD --- ;; +;;------------------------------------------------------------------------------------------------;; +;< eax = false / true ;; +;;================================================================================================;; + xor eax, eax + ret +endp + +;;================================================================================================;; +proc img.from_rgb _rgb_data ;/////////////////////////////////////////////////////////////////////;; +;;------------------------------------------------------------------------------------------------;; +;? --- TBD --- ;; +;;------------------------------------------------------------------------------------------------;; +;> --- TBD --- ;; +;;------------------------------------------------------------------------------------------------;; +;< eax = 0 / pointer to image ;; +;;================================================================================================;; + xor eax, eax + ret +endp + +;;================================================================================================;; +proc img.to_rgb2 _img, _out ;/////////////////////////////////////////////////////////////////////;; +;;------------------------------------------------------------------------------------------------;; +;? decodes image data into RGB triplets and stores them where [_out] points to ;; +;;------------------------------------------------------------------------------------------------;; +;> [_img] = pointer to source image ;; +;> [_out] = where to store RGB triplets ;; +;;------------------------------------------------------------------------------------------------;; +;< none ;; +;;================================================================================================;; + push esi edi + mov esi, [_img] + stdcall img._.validate, esi + or eax, eax + jnz .ret + mov edi, [_out] + call img._.do_rgb +.ret: + pop edi esi + ret +endp + +;;================================================================================================;; +proc img.to_rgb _img ;////////////////////////////////////////////////////////////////////////////;; +;;------------------------------------------------------------------------------------------------;; +;? decodes image data into RGB triplets and returns pointer to memory area of following structure:;; +;? width dd ? ;; +;? height dd ? ;; +;? rgb triplets ;; +;;------------------------------------------------------------------------------------------------;; +;> [_img] = pointer to source image ;; +;;------------------------------------------------------------------------------------------------;; +;< eax = 0 / pointer to rgb_data (array of [rgb] triplets) ;; +;;================================================================================================;; + push esi edi + mov esi, [_img] + stdcall img._.validate, esi + or eax, eax + jnz .error + + mov esi, [_img] + mov ecx, [esi + Image.Width] + imul ecx, [esi + Image.Height] + lea eax, [ecx * 3 + 4 * 3] + invoke mem.alloc, eax + or eax, eax + jz .error + + mov edi, eax + push eax + mov eax, [esi + Image.Width] + stosd + mov eax, [esi + Image.Height] + stosd + call img._.do_rgb + pop eax + pop edi esi + ret + + .error: + xor eax, eax + pop edi esi + ret +endp + +;;================================================================================================;; +proc img._.do_rgb ;///////////////////////////////////////////////////////////////////////////////;; +;;------------------------------------------------------------------------------------------------;; +;? decodes [esi + Image.Data] data into RGB triplets and stores them at [edi] ;; +;;------------------------------------------------------------------------------------------------;; +;> esi = pointer to source image ;; +;> edi = pointer to memory to store RGB triplets ;; +;;------------------------------------------------------------------------------------------------;; +;< none ;; +;;================================================================================================;; + mov ecx, [esi + Image.Width] + imul ecx, [esi + Image.Height] + mov eax, [esi + Image.Type] + jmp dword [.handlers + (eax-1)*4] + +align 16 +.bpp8i: +; 8 BPP WITH PALETTE -> 24 BPP + push ebx + mov ebx, [esi + Image.Palette] + mov esi, [esi + Image.Data] + sub ecx, 1 + jz .bpp8i.last +@@: + movzx eax, byte [esi] + add esi, 1 + mov eax, [ebx + eax*4] + mov [edi], eax + add edi, 3 + sub ecx, 1 + jnz @b +.bpp8i.last: + movzx eax, byte [esi] + mov eax, [ebx + eax*4] + mov [edi], ax + shr eax, 16 + mov [edi+2], al + pop ebx + ret + +align 16 +.bpp8g: +; 8 BPP GRAYSCALE -> 24 BPP + mov esi, [esi + Image.Data] +@@: + lodsb + mov ah, al + stosb + stosw + dec ecx + jnz @b + ret +; +;align 16 +;.bpp8a: ; considered application layer, may be changed in the future +;; 8a BPP -> 24 BPP +; mov esi, [esi + Image.Data] +;@@: +; lodsw +; mov ah, al +; stosb +; stosw +; dec ecx +; jnz @b +; 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] + + @@: + mov eax, [esi] + mov [edi], ax + shr eax, 16 + mov [edi+2], al + add esi, 4 + add edi, 3 + sub ecx, 1 + jnz @b + + @@: + ret + +align 16 +.bpp1: + push ebx ebp + mov ebp, [esi + Image.Width] + mov edx, [esi + Image.Height] + shl edx, 16 + mov ebx, [esi + Image.Palette] + mov esi, [esi + Image.Data] + .bpp1.pre: + mov dx, bp + mov ecx, 7 + .bpp1.begin: + xor eax, eax + bt [esi], ecx + adc eax, 0 + mov eax, [ebx + eax*4] + mov [edi], ax + shr eax, 16 + mov [edi + 2], al + add edi, 3 + dec dx + jz .bpp1.end_line + dec ecx + jns .bpp1.begin + mov ecx, 7 + inc esi + jmp .bpp1.begin + .bpp1.end_line: + sub edx, 0x10000 + jz .bpp1.quit + inc esi + jmp .bpp1.pre + .bpp1.quit: + pop ebp ebx + ret + +align 16 +.bpp2i: + push ebx ebp + mov ebp, [esi + Image.Width] + mov edx, [esi + Image.Height] + shl edx, 16 + mov ebx, [esi + Image.Palette] + mov esi, [esi + Image.Data] + .bpp2i.pre: + mov dx, bp + mov ecx, 3 + .bpp2i.begin: + mov eax, 3 + shl ecx, 1 + shl eax, cl + and al, [esi] + shr eax, cl + shr ecx, 1 + mov eax, [ebx + eax*4] + mov [edi], ax + shr eax, 16 + mov [edi + 2], al + add edi, 3 + dec dx + jz .bpp2i.end_line + dec ecx + jns .bpp2i.begin + mov ecx, 3 + inc esi + jmp .bpp2i.begin + .bpp2i.end_line: + sub edx, 0x10000 + jz .bpp2i.quit + inc esi + jmp .bpp2i.pre + .bpp2i.quit: + pop ebp ebx + ret + +align 16 +.bpp4i: + push ebx ebp + mov ebp, [esi + Image.Width] + mov edx, [esi + Image.Height] + shl edx, 16 + mov ebx, [esi + Image.Palette] + mov esi, [esi + Image.Data] + .bpp4i.pre: + mov dx, bp + mov ecx, 1 + .bpp4i.begin: + mov eax, 15 + shl ecx, 2 + shl eax, cl + and al, [esi] + shr eax, cl + shr ecx, 2 + mov eax, [ebx + eax*4] + mov [edi], ax + shr eax, 16 + mov [edi + 2], al + add edi, 3 + dec dx + jz .bpp4i.end_line + dec ecx + jns .bpp4i.begin + mov ecx, 1 + inc esi + jmp .bpp4i.begin + .bpp4i.end_line: + sub edx, 0x10000 + jz .bpp4i.quit + inc esi + jmp .bpp4i.pre + .bpp4i.quit: + pop ebp ebx + ret + +endp + +;;================================================================================================;; +proc img.decode _data, _length, _options ;////////////////////////////////////////////////////////;; +;;------------------------------------------------------------------------------------------------;; +;? decodes loaded into memory graphic file ;; +;;------------------------------------------------------------------------------------------------;; +;> [_data] = pointer to file in memory ;; +;> [_length] = size in bytes of memory area pointed to by [_data] ;; +;> [_options] = 0 / pointer to the structure of additional options ;; +;;------------------------------------------------------------------------------------------------;; +;< eax = 0 / pointer to image ;; +;;================================================================================================;; + push ebx + mov ebx, img.formats_table + @@: stdcall [ebx + FormatsTableEntry.Is], [_data], [_length] + or eax, eax + jnz @f + add ebx, sizeof.FormatsTableEntry + cmp dword[ebx], eax ;0 + jnz @b + pop ebx + ret + @@: mov eax, [ebx + FormatsTableEntry.Decode] + pop ebx + leave + jmp eax +endp + +;;================================================================================================;; +proc img.encode _img, _common, _specific ;////////////////////////////////////////////////////////;; +;;------------------------------------------------------------------------------------------------;; +;? encode image to some format ;; +;;------------------------------------------------------------------------------------------------;; +;> [_img] = pointer to input image ;; +;> [_common] = some most important/common options ;; +; 0x00 : byte : format id (defined in libimg.inc) ;; +; 0x01 : byte : fast encoding (0) / best compression ratio (255) ;; +; 0 : store uncompressed data (if supported both by the format and libimg) ;; +; 1 - 255 : use compression, if supported ;; +; this option may be ignored if any format specific options are defined ;; +; i.e. 0 here will be ignored if particular compression algorithm is specified ;; +; 0x02 : byte : flags (bitfield) ;; +; 0x01 : return an error if format specific conditions cannot be met ;; +; 0x02 : preserve current bit depth. means 8bpp/16bpp/24bpp and so on ;; +; 0x04 : delete alpha channel, if any ;; +; 0x08 : flush alpha channel with 0xff, if any; add it if none ;; +; 0x03 : byte : reserved, must be 0 ;; +;> [_specific] = 0 / pointer to the structure of format specific options ;; +; see .inc for description ;; +;;------------------------------------------------------------------------------------------------;; +;< eax = 0 / pointer to encoded data ;; +;< ecx = error code / the size of encoded data ;; +; 1 : out of memory ;; +; 2 : format is not supported ;; +; 3 : specific conditions cannot be satisfied ;; +; 4 : bit depth cannot be preserved ;; +;;================================================================================================;; + mov ebx, [_img] + + movzx eax, byte[_common] + dec eax + imul eax, sizeof.FormatsTableEntry + add eax, FormatsTableEntry.Capabilities + add eax, img.formats_table + mov eax, [eax] + test eax, 1 ; is encoding to this format supported at all? + jnz @f + mov ecx, LIBIMG_ERROR_FORMAT + jmp .error + @@: + mov ecx, [ebx + Image.Type] + mov edx, 1 + shl edx, cl + test eax, edx + jnz .bit_depth_ok + test byte[_common+2], LIBIMG_ENCODE_STRICT_BIT_DEPTH + jz @f + mov ecx, LIBIMG_ERROR_BIT_DEPTH + jmp .error + @@: + mov edx, 1 SHL Image.bpp24 + test eax, edx + jnz @f + mov ecx, LIBIMG_ERROR_BIT_DEPTH + jmp .error + @@: + stdcall img.create, [ebx + Image.Width], [ebx + Image.Height], Image.bpp24 + test eax, eax + jnz @f + mov ecx, LIBIMG_ERROR_OUT_OF_MEMORY + jmp .error + @@: + push eax + stdcall img.to_rgb2, ebx, [eax + Image.Data] + pop ebx + + .bit_depth_ok: + movzx eax, byte[_common] + dec eax + imul eax, sizeof.FormatsTableEntry + add eax, FormatsTableEntry.Encode + add eax, img.formats_table + mov eax, [eax] + stdcall eax, [_img], [_common], [_specific] + push eax ecx + cmp ebx, [_img] + je @f + stdcall img.destroy, ebx + @@: + pop ecx eax + jmp .quit + + .error: + xor eax, eax + .quit: + ret +endp + +;;================================================================================================;; +proc img.create _width, _height, _type ;//////////////////////////////////////////////////////////;; +;;------------------------------------------------------------------------------------------------;; +;? creates an Image structure and initializes some its fields ;; +;;------------------------------------------------------------------------------------------------;; +;> [_width] = width of an image in pixels ;; +;> [_height] = height of an image in pixels ;; +;> [_type] = one of the Image.bppN constants from libimg.inc ;; +;;------------------------------------------------------------------------------------------------;; +;< eax = 0 / pointer to image ;; +;;================================================================================================;; + push ecx + + stdcall img._.new + or eax, eax + jz .error + + mov ecx, [_type] + mov [eax + Image.Type], ecx + + push eax + + stdcall img._.resize_data, eax, [_width], [_height] + or eax, eax + jz .error.2 + + pop eax + jmp .ret + + .error.2: +; pop eax + stdcall img._.delete; eax + xor eax, eax + + .error: + .ret: + pop ecx + ret +endp + +;;================================================================================================;; +proc img.destroy.layer _img ;/////////////////////////////////////////////////////////////////////;; +;;------------------------------------------------------------------------------------------------;; +;? frees memory occupied by an image and all the memory regions its fields point to ;; +;? for image sequences deletes only one frame and fixes Previous/Next pointers ;; +;;------------------------------------------------------------------------------------------------;; +;> [_img] = pointer to image ;; +;;------------------------------------------------------------------------------------------------;; +;< eax = 0 (fail) / 1 (success) ;; +;;================================================================================================;; + 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 ;///////////////////////////////////////////////////////////////////////////;; +;;------------------------------------------------------------------------------------------------;; +;? frees memory occupied by an image and all the memory regions its fields point to ;; +;? follows Previous/Next pointers and deletes all the images in sequence ;; +;;------------------------------------------------------------------------------------------------;; +;> [_img] = pointer to image ;; +;;------------------------------------------------------------------------------------------------;; +;< eax = 0 (fail) / 1 (success) ;; +;;================================================================================================;; + 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 + +;;================================================================================================;; +proc img.count _img ;/////////////////////////////////////////////////////////////////////////////;; +;;------------------------------------------------------------------------------------------------;; +;? Get number of images in the list (e.g. in animated GIF file) ;; +;;------------------------------------------------------------------------------------------------;; +;> _img = pointer to image ;; +;;------------------------------------------------------------------------------------------------;; +;< eax = -1 (fail) / >0 (ok) ;; +;;================================================================================================;; + push ecx edx + mov edx, [_img] + stdcall img._.validate, edx + or eax, eax + jnz .error + + @@: mov eax, [edx + Image.Previous] + or eax, eax + jz @f + mov edx, eax + jmp @b + + @@: xor ecx, ecx + @@: inc ecx + mov eax, [edx + Image.Next] + or eax, eax + jz .exit + mov edx, eax + jmp @b + + .exit: + mov eax, ecx + pop edx ecx + ret + + .error: + or eax, -1 + pop edx ecx + ret +endp + +;;//// image processing //////////////////////////////////////////////////////////////////////////;; + +;;================================================================================================;; +proc img.lock_bits _img, _start_line, _end_line ;/////////////////////////////////////////////////;; +;;------------------------------------------------------------------------------------------------;; +;? --- TBD --- ;; +;;------------------------------------------------------------------------------------------------;; +;> --- TBD --- ;; +;;------------------------------------------------------------------------------------------------;; +;< eax = 0 / pointer to bits ;; +;;================================================================================================;; + xor eax, eax + ret +endp + +;;================================================================================================;; +proc img.unlock_bits _img, _lock ;////////////////////////////////////////////////////////////////;; +;;------------------------------------------------------------------------------------------------;; +;? --- TBD --- ;; +;;------------------------------------------------------------------------------------------------;; +;> --- TBD --- ;; +;;------------------------------------------------------------------------------------------------;; +;< eax = false / true ;; +;;================================================================================================;; + xor eax, eax + ret +endp + +;;================================================================================================;; +proc img.flip.layer _img, _flip_kind ;////////////////////////////////////////////////////////////;; +;;------------------------------------------------------------------------------------------------;; +;? Flip image layer ;; +;;------------------------------------------------------------------------------------------------;; +;> _img = pointer to image ;; +;> _flip_kind = one of FLIP_* constants ;; +;;------------------------------------------------------------------------------------------------;; +;< eax = false / true ;; +;;================================================================================================;; +locals + scanline_len dd ? +endl + + push ebx esi edi + mov ebx, [_img] + stdcall img._.validate, ebx + or eax, eax + jnz .error + + mov ecx, [ebx + Image.Height] + mov eax, [ebx + Image.Width] + call img._.get_scanline_len + mov [scanline_len], eax + + test [_flip_kind], FLIP_VERTICAL + jz .dont_flip_vert + + imul eax, ecx + sub eax, [scanline_len] + shr ecx, 1 + mov esi, [ebx + Image.Data] + lea edi, [esi + eax] + + .next_line_vert: + push ecx + + mov ecx, [scanline_len] + push ecx + shr ecx, 2 + @@: + dec ecx + js @f + mov eax, [esi] + xchg eax, [edi] + mov [esi], eax + add esi, 4 + add edi, 4 + jmp @b + @@: + + pop ecx + and ecx, 3 + jz .cont_line_vert + @@: + mov al, [esi] + xchg al, [edi] + mov [esi], al + add esi, 1 + add edi, 1 + dec ecx + jnz @b + .cont_line_vert: + + pop ecx + mov eax, [scanline_len] + shl eax, 1 + sub edi, eax + dec ecx + jnz .next_line_vert + + .dont_flip_vert: + + test [_flip_kind], FLIP_HORIZONTAL + jz .exit + + mov ecx, [ebx + Image.Height] + mov eax, [ebx + Image.Type] + mov esi, [ebx + Image.Data] + mov edi, [scanline_len] + add edi, esi + jmp dword [.handlers_horz + (eax-1)*4] + +.bpp32_horz: + sub edi, 4 + + .next_line_horz: + push ecx esi edi + + mov ecx, [scanline_len] + shr ecx, 3 + @@: mov eax, [esi] + xchg eax, [edi] + mov [esi], eax + add esi, 4 + add edi, -4 + sub ecx, 1 + jnz @b + + pop edi esi ecx + add esi, [scanline_len] + add edi, [scanline_len] + dec ecx + jnz .next_line_horz + jmp .exit + +.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 + +.bpp8ig_horz: + dec edi + .next_line_horz8ig: + push ecx esi edi + + mov ecx, [scanline_len] + shr ecx, 1 + @@: mov al, [esi] + mov dl, [edi] + mov [edi], al + mov [esi], dl + add esi, 1 + sub edi, 1 + sub ecx, 1 + jnz @b + + pop edi esi ecx + add esi, [scanline_len] + add edi, [scanline_len] + dec ecx + jnz .next_line_horz8ig + jmp .exit + +.bpp24_horz: + sub edi, 3 + .next_line_horz24: + push ecx esi edi + + mov ecx, [ebx + Image.Width] + @@: + mov al, [esi] + mov dl, [edi] + mov [edi], al + mov [esi], dl + mov al, [esi+1] + mov dl, [edi+1] + mov [edi+1], al + mov [esi+1], dl + mov al, [esi+2] + mov dl, [edi+2] + mov [edi+2], al + mov [esi+2], dl + add esi, 3 + sub edi, 3 + sub ecx, 2 + ja @b + + pop edi esi ecx + add esi, [scanline_len] + add edi, [scanline_len] + dec ecx + jnz .next_line_horz24 + jmp .exit + +.bpp1_horz: + mov edi, [scanline_len] + mov edx, [ebx + Image.Width] + and edx, 7 + neg edx + add edx, 8 + and edx, 7 +.bpp1_horz.begin: + push ebx edx esi + mov eax, 7 + add edi, esi + sub edi, 1 + mov ebx, [ebx + Image.Width] + shr ebx, 1 +.bpp1_horz.bit: + bt [edi], edx + jc @f + btr [esi], eax + jmp .bpp1_horz.right + @@: + bts [esi], eax + .bpp1_horz.right: + jnc @f + bts [edi], edx + jmp .bpp1_horz.bit_done + @@: + btr [edi], edx + .bpp1_horz.bit_done: + inc edx + and edx, 7 + jnz @f + dec edi + @@: + dec eax + jns @f + mov eax, 7 + inc esi + @@: + dec ebx + jnz .bpp1_horz.bit + + pop esi edx ebx + add esi, [scanline_len] + mov edi, [scanline_len] + dec ecx + jnz .bpp1_horz.begin + jmp .exit + + +.bpp2i_horz: + mov edi, [scanline_len] + mov edx, [ebx + Image.Width] + and edx, 3 + neg edx + add edx, 4 + and edx, 3 +.bpp2i_horz.begin: + push ebx edx esi + mov eax, 3 + add edi, esi + sub edi, 1 + mov ebx, [ebx + Image.Width] + shr ebx, 1 +.bpp2i_horz.pixel: + push ebx ecx + mov ebx, 3 + mov ecx, edx + shl ebx, cl + shl ebx, cl + and bl, [edi] + shr ebx, cl + shr ebx, cl + mov bh, 3 + mov ecx, eax + shl ebx, cl + shl ebx, cl + not bh + and bh, [esi] + or bl, bh + mov bh, [esi] + mov [esi], bl + shr ebx, 8 + shr ebx, cl + shr ebx, cl + and ebx, 3 + mov bh, 3 + mov ecx, edx + shl ebx, cl + shl ebx, cl + not bh + and bh, [edi] + or bl, bh + mov [edi], bl + pop ecx ebx + .bpp2i_horz.pixel_done: + inc edx + and edx, 3 + jnz @f + dec edi + @@: + dec eax + jns @f + mov eax, 3 + inc esi + @@: + dec ebx + jnz .bpp2i_horz.pixel + + pop esi edx ebx + add esi, [scanline_len] + mov edi, [scanline_len] + dec ecx + jnz .bpp2i_horz.begin + jmp .exit + + +.bpp4i_horz: + mov edi, [scanline_len] + mov edx, [ebx + Image.Width] + and edx, 1 + neg edx + add edx, 2 + and edx, 1 +.bpp4i_horz.begin: + push ebx edx esi + mov eax, 1 + add edi, esi + sub edi, 1 + mov ebx, [ebx + Image.Width] + shr ebx, 1 +.bpp4i_horz.pixel: + push ebx ecx + mov ebx, 15 + mov ecx, edx + shl ecx, 2 + shl ebx, cl + and bl, [edi] + shr ebx, cl + mov bh, 15 + mov ecx, eax + shl ecx, 2 + shl ebx, cl + not bh + and bh, [esi] + or bl, bh + mov bh, [esi] + mov [esi], bl + shr ebx, 8 + shr ebx, cl + and ebx, 15 + mov bh, 15 + mov ecx, edx + shl ecx, 2 + shl ebx, cl + not bh + and bh, [edi] + or bl, bh + mov [edi], bl + pop ecx ebx + .bpp4i_horz.pixel_done: + inc edx + and edx, 1 + jnz @f + dec edi + @@: + dec eax + jns @f + mov eax, 1 + inc esi + @@: + dec ebx + jnz .bpp4i_horz.pixel + + pop esi edx ebx + add esi, [scanline_len] + mov edi, [scanline_len] + dec ecx + jnz .bpp4i_horz.begin + jmp .exit + + + .exit: + xor eax, eax + inc eax + pop edi esi ebx + ret + + .error: + xor eax, eax + pop edi esi ebx + ret +endp + +;;================================================================================================;; +proc img.flip _img, _flip_kind ;//////////////////////////////////////////////////////////////////;; +;;------------------------------------------------------------------------------------------------;; +;? 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 ;; +;;================================================================================================;; +locals + scanline_len_old dd ? + scanline_len_new dd ? + scanline_pixels_new dd ? + line_buffer dd ? + pixels_ptr dd ? +endl + + mov [line_buffer], 0 + + push ebx esi edi + mov ebx, [_img] + stdcall img._.validate, ebx + or eax, eax + jnz .error + + cmp [_rotate_kind], ROTATE_90_CCW + je .rotate_ccw_low + cmp [_rotate_kind], ROTATE_90_CW + je .rotate_cw_low + cmp [_rotate_kind], ROTATE_180 + je .flip + jmp .exit + + .rotate_ccw_low: + mov eax, [ebx + Image.Height] + mov [scanline_pixels_new], eax + call img._.get_scanline_len + mov [scanline_len_new], eax + + invoke mem.alloc, eax + or eax, eax + jz .error + mov [line_buffer], eax + + mov eax, [ebx + Image.Width] + mov ecx, eax + call img._.get_scanline_len + mov [scanline_len_old], eax + + mov eax, [scanline_len_new] + imul eax, ecx + add eax, [ebx + Image.Data] + mov [pixels_ptr], eax + + cmp [ebx + Image.Type], Image.bpp1 + jz .rotate_ccw1 + cmp [ebx + Image.Type], Image.bpp2i + jz .rotate_ccw2i + cmp [ebx + Image.Type], Image.bpp4i + jz .rotate_ccw4i + cmp [ebx + Image.Type], Image.bpp8i + jz .rotate_ccw8ig + cmp [ebx + Image.Type], Image.bpp8g + jz .rotate_ccw8ig + 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 + push ecx + + mov edx, [scanline_len_old] + add [scanline_len_old], -4 + + mov ecx, [scanline_pixels_new] + mov esi, [ebx + Image.Data] + mov edi, [line_buffer] + @@: mov eax, [esi] + stosd + add esi, edx + dec ecx + jnz @b + + mov eax, [scanline_pixels_new] + mov edi, [ebx + Image.Data] + lea esi, [edi + 4] + mov edx, [scanline_len_old] + shr edx, 2 + @@: mov ecx, edx + rep movsd + add esi, 4 + dec eax + jnz @b + + mov eax, [scanline_len_new] + sub [pixels_ptr], eax + mov ecx, [scanline_pixels_new] + mov esi, [line_buffer] + mov edi, [pixels_ptr] + rep movsd + + pop ecx + jmp .next_column_ccw_low + +.rotate_ccw8ig: + .next_column_ccw_low8ig: + dec ecx + js .exchange_dims + push ecx + + mov edx, [scanline_len_old] + add [scanline_len_old], -1 + + mov ecx, [scanline_pixels_new] + mov esi, [ebx + Image.Data] + mov edi, [line_buffer] + @@: mov al, [esi] + mov [edi], al + add esi, edx + add edi, 1 + sub ecx, 1 + jnz @b + + mov eax, [scanline_pixels_new] + mov edi, [ebx + Image.Data] + lea esi, [edi + 1] + 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_low8ig + +.rotate_ccw24: + .next_column_ccw_low24: + dec ecx + js .exchange_dims + push ecx + + mov edx, [scanline_len_old] + add [scanline_len_old], -3 + + mov ecx, [scanline_pixels_new] + mov esi, [ebx + Image.Data] + mov edi, [line_buffer] + @@: mov al, [esi] + mov [edi], al + mov al, [esi+1] + mov [edi+1], al + mov al, [esi+2] + mov [edi+2], al + add esi, edx + add edi, 3 + sub ecx, 1 + jnz @b + + mov eax, [scanline_pixels_new] + mov edi, [ebx + Image.Data] + lea esi, [edi + 3] + 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_ccw_low24 + +.rotate_ccw1: + push ecx edx + + mov eax, [ebx + Image.Height] + add eax, 7 + shr eax, 3 + imul eax, [ebx + Image.Width] + push eax ; save new data size + + invoke mem.alloc, eax + or eax, eax + jz .error + push eax ; save pointer to new data + + mov ecx, [ebx + Image.Width] + and ecx, 7 + neg ecx + add ecx, 8 + and ecx, 7 + + mov edi, eax + mov esi, [ebx + Image.Data] + mov eax, 7 + mov edx, [scanline_len_old] + dec edx + add esi, edx + + .rotate_ccw1.begin: + bt [esi], ecx + jc .rotate_ccw1.one + .rotate_ccw1.zero: + btr [edi], eax + jmp @f + .rotate_ccw1.one: + bts [edi], eax + @@: + add esi, [scanline_len_old] + dec [scanline_pixels_new] + jz .rotate_ccw1.end_of_line + sub eax, 1 + adc edi, 0 + and eax, 7 + jmp .rotate_ccw1.begin + .rotate_ccw1.end_of_line: + inc edi + mov eax, [ebx + Image.Height] + mov [scanline_pixels_new], eax + mov eax, 7 + inc ecx + and ecx, 7 + jz @f + mov esi, [ebx + Image.Data] + add esi, edx + jmp .rotate_ccw1.begin + @@: + dec edx + js .rotate_ccw1.quit + mov esi, [ebx + Image.Data] + add esi, edx + jmp .rotate_ccw1.begin + .rotate_ccw1.quit: + pop esi ; get pointer to new data + mov edi, [ebx + Image.Data] + pop ecx ; get new data size + rep movsb + invoke mem.free, esi + pop edx ecx + jmp .exchange_dims + + +.rotate_ccw2i: + push ecx edx + + mov eax, [ebx + Image.Height] + add eax, 3 + shr eax, 2 + imul eax, [ebx + Image.Width] + push eax ; save new data size + + invoke mem.alloc, eax + or eax, eax + jz .error + push eax ; save pointer to new data + + mov ecx, [ebx + Image.Width] + and ecx, 3 + neg ecx + add ecx, 4 + and ecx, 3 + + mov edi, eax + mov esi, [ebx + Image.Data] + mov eax, 3 + mov edx, [scanline_len_old] + dec edx + add esi, edx + + .rotate_ccw2i.begin: + push ebx ecx + mov ebx, 3 + shl ebx, cl + shl ebx, cl + and bl, [esi] + shr ebx, cl + shr ebx, cl + mov bh, 3 + mov ecx, eax + shl ebx, cl + shl ebx, cl + not bh + and bh, [edi] + or bl, bh + mov [edi], bl + pop ecx ebx + + add esi, [scanline_len_old] + dec [scanline_pixels_new] + jz .rotate_ccw2i.end_of_line + sub eax, 1 + adc edi, 0 + and eax, 3 + jmp .rotate_ccw2i.begin + .rotate_ccw2i.end_of_line: + inc edi + mov eax, 3 + mov esi, [ebx + Image.Height] + mov [scanline_pixels_new], esi + inc ecx + and ecx, 3 + jz @f + mov esi, [ebx + Image.Data] + add esi, edx + jmp .rotate_ccw2i.begin + @@: + dec edx + js .rotate_ccw2i.quit + mov esi, [ebx + Image.Data] + add esi, edx + jmp .rotate_ccw2i.begin + .rotate_ccw2i.quit: + pop esi ; get pointer to new data + mov edi, [ebx + Image.Data] + pop ecx ; get new data size + rep movsb + invoke mem.free, esi + pop edx ecx + jmp .exchange_dims + + +.rotate_ccw4i: + push ecx edx + + mov eax, [ebx + Image.Height] + add eax, 1 + shr eax, 1 + imul eax, [ebx + Image.Width] + push eax ; save new data size + + invoke mem.alloc, eax + or eax, eax + jz .error + push eax ; save pointer to new data + + mov ecx, [ebx + Image.Width] + and ecx, 1 + neg ecx + add ecx, 2 + and ecx, 1 + + mov edi, eax + mov esi, [ebx + Image.Data] + mov eax, 1 + mov edx, [scanline_len_old] + dec edx + add esi, edx + + .rotate_ccw4i.begin: + push ebx ecx + mov ebx, 15 + shl ecx, 2 + shl ebx, cl + and bl, [esi] + shr ebx, cl + mov bh, 15 + mov ecx, eax + shl ecx, 2 + shl ebx, cl + not bh + and bh, [edi] + or bl, bh + mov [edi], bl + pop ecx ebx + + add esi, [scanline_len_old] + dec [scanline_pixels_new] + jz .rotate_ccw4i.end_of_line + sub eax, 1 + adc edi, 0 + and eax, 1 + jmp .rotate_ccw4i.begin + .rotate_ccw4i.end_of_line: + inc edi + mov eax, 1 + mov esi, [ebx + Image.Height] + mov [scanline_pixels_new], esi + inc ecx + and ecx, 1 + jz @f + mov esi, [ebx + Image.Data] + add esi, edx + jmp .rotate_ccw4i.begin + @@: + dec edx + js .rotate_ccw4i.quit + mov esi, [ebx + Image.Data] + add esi, edx + jmp .rotate_ccw4i.begin + .rotate_ccw4i.quit: + pop esi ; get pointer to new data + mov edi, [ebx + Image.Data] + pop ecx ; get new data size + rep movsb + invoke mem.free, esi + pop edx ecx + jmp .exchange_dims + + + + .rotate_cw_low: + mov eax, [ebx + Image.Height] + mov [scanline_pixels_new], eax + call img._.get_scanline_len + mov [scanline_len_new], eax + + invoke mem.alloc, eax + or eax, eax + jz .error + mov [line_buffer], eax + + mov eax, [ebx + Image.Width] + mov ecx, eax + call img._.get_scanline_len + mov [scanline_len_old], eax + + mov eax, [scanline_len_new] + imul eax, ecx + add eax, [ebx + Image.Data] + mov [pixels_ptr], eax + + cmp [ebx + Image.Type], Image.bpp1 + jz .rotate_cw1 + cmp [ebx + Image.Type], Image.bpp2i + jz .rotate_cw2i + cmp [ebx + Image.Type], Image.bpp4i + jz .rotate_cw4i + cmp [ebx + Image.Type], Image.bpp8i + jz .rotate_cw8ig + cmp [ebx + Image.Type], Image.bpp8g + jz .rotate_cw8ig + 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 + push ecx + + mov edx, [scanline_len_old] + add [scanline_len_old], -4 + + mov ecx, [scanline_pixels_new] + mov esi, [pixels_ptr] + add esi, -4 + mov edi, [line_buffer] + @@: mov eax, [esi] + stosd + sub esi, edx + dec ecx + jnz @b + + mov eax, [scanline_pixels_new] + dec eax + mov edi, [ebx + Image.Data] + add edi, [scanline_len_old] + lea esi, [edi + 4] + mov edx, [scanline_len_old] + shr edx, 2 + @@: mov ecx, edx + rep movsd + add esi, 4 + dec eax + jnz @b + + mov eax, [scanline_len_new] + sub [pixels_ptr], eax + mov ecx, [scanline_pixels_new] + mov esi, [line_buffer] + mov edi, [pixels_ptr] + rep movsd + + pop ecx + jmp .next_column_cw_low + +.rotate_cw8ig: + .next_column_cw_low8ig: + dec ecx + js .exchange_dims + push ecx + + mov edx, [scanline_len_old] + add [scanline_len_old], -1 + + mov ecx, [scanline_pixels_new] + mov esi, [pixels_ptr] + add esi, -1 + mov edi, [line_buffer] + @@: mov al, [esi] + mov [edi], al + sub esi, edx + add edi, 1 + 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 + 1] + 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, 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_low8ig + +.rotate_cw24: + .next_column_cw_low24: + dec ecx + js .exchange_dims + push ecx + + mov edx, [scanline_len_old] + add [scanline_len_old], -3 + + mov ecx, [scanline_pixels_new] + mov esi, [pixels_ptr] + add esi, -3 + mov edi, [line_buffer] + @@: mov al, [esi] + mov [edi], al + mov al, [esi+1] + mov [edi+1], al + mov al, [esi+2] + mov [edi+2], al + sub esi, edx + add edi, 3 + 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 + 3] + 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_low24 + + +.rotate_cw1: + push ecx edx + + mov eax, [ebx + Image.Height] + add eax, 7 + shr eax, 3 + imul [ebx + Image.Width] + push eax ; save new data size + + invoke mem.alloc, eax + or eax, eax + jz .error + push eax ; save pointer to new data + + mov edi, eax + mov esi, [ebx + Image.Data] + mov eax, [ebx + Image.Height] + dec eax + imul eax, [scanline_len_old] + add esi, eax + mov eax, 7 + mov ecx, 7 + mov edx, 0 + + .rotate_cw1.begin: + bt [esi], ecx + jc .rotate_cw1.one + .rotate_cw1.zero: + btr [edi], eax + jmp @f + .rotate_cw1.one: + bts [edi], eax + @@: + sub esi, [scanline_len_old] + dec [scanline_pixels_new] + jz .rotate_cw1.end_of_line + sub eax, 1 + adc edi, 0 + and eax, 7 + jmp .rotate_cw1.begin + .rotate_cw1.end_of_line: + inc edi + mov eax, [ebx + Image.Height] + mov [scanline_pixels_new], eax + mov eax, 7 + dec ecx + jns @f + mov ecx, 7 + inc edx + cmp edx, [scanline_len_old] + je .rotate_cw1.quit + @@: + mov esi, [ebx + Image.Height] + dec esi + imul esi, [scanline_len_old] + add esi, [ebx + Image.Data] + add esi, edx + jmp .rotate_cw1.begin + .rotate_cw1.quit: + pop eax ; get pointer to new data + mov esi, eax + mov edi, [ebx + Image.Data] + pop ecx ; get new data size + rep movsb + invoke mem.free, eax + pop edx ecx + jmp .exchange_dims + + +.rotate_cw2i: + push ecx edx + + mov eax, [ebx + Image.Height] + add eax, 3 + shr eax, 2 + imul [ebx + Image.Width] + push eax ; save new data size + + invoke mem.alloc, eax + or eax, eax + jz .error + push eax ; save pointer to new data + + mov edi, eax + mov esi, [ebx + Image.Data] + mov eax, [ebx + Image.Height] + dec eax + imul eax, [scanline_len_old] + add esi, eax + mov eax, 3 + mov ecx, 3 + mov edx, 0 + + .rotate_cw2i.begin: + push ebx ecx + mov ebx, 3 + shl ebx, cl + shl ebx, cl + and bl, [esi] + shr ebx, cl + shr ebx, cl + mov bh, 3 + mov ecx, eax + shl ebx, cl + shl ebx, cl + not bh + and bh, [edi] + or bl, bh + mov [edi], bl + pop ecx ebx + + sub esi, [scanline_len_old] + dec [scanline_pixels_new] + jz .rotate_cw2i.end_of_line + sub eax, 1 + adc edi, 0 + and eax, 3 + jmp .rotate_cw2i.begin + .rotate_cw2i.end_of_line: + inc edi + mov eax, [ebx + Image.Height] + mov [scanline_pixels_new], eax + mov eax, 3 + dec ecx + jns @f + mov ecx, 3 + inc edx + cmp edx, [scanline_len_old] + je .rotate_cw2i.quit + @@: + mov esi, [ebx + Image.Height] + dec esi + imul esi, [scanline_len_old] + add esi, [ebx + Image.Data] + add esi, edx + jmp .rotate_cw2i.begin + .rotate_cw2i.quit: + pop eax ; get pointer to new data + mov esi, eax + mov edi, [ebx + Image.Data] + pop ecx ; get new data size + rep movsb + invoke mem.free, eax + pop edx ecx + jmp .exchange_dims + + +.rotate_cw4i: + push ecx edx + + mov eax, [ebx + Image.Height] + add eax, 1 + shr eax, 1 + imul [ebx + Image.Width] + push eax ; save new data size + + invoke mem.alloc, eax + or eax, eax + jz .error + push eax ; save pointer to new data + + mov edi, eax + mov esi, [ebx + Image.Data] + mov eax, [ebx + Image.Height] + dec eax + imul eax, [scanline_len_old] + add esi, eax + mov eax, 1 + mov ecx, 1 + mov edx, 0 + + .rotate_cw4i.begin: + push ebx ecx + mov ebx, 15 + shl ecx, 2 + shl ebx, cl + and bl, [esi] + shr ebx, cl + mov bh, 15 + mov ecx, eax + shl ecx, 2 + shl ebx, cl + not bh + and bh, [edi] + or bl, bh + mov [edi], bl + pop ecx ebx + + sub esi, [scanline_len_old] + dec [scanline_pixels_new] + jz .rotate_cw4i.end_of_line + sub eax, 1 + adc edi, 0 + and eax, 1 + jmp .rotate_cw4i.begin + .rotate_cw4i.end_of_line: + inc edi + mov eax, [ebx + Image.Height] + mov [scanline_pixels_new], eax + mov eax, 1 + dec ecx + jns @f + mov ecx, 1 + inc edx + cmp edx, [scanline_len_old] + je .rotate_cw4i.quit + @@: + mov esi, [ebx + Image.Height] + dec esi + imul esi, [scanline_len_old] + add esi, [ebx + Image.Data] + add esi, edx + jmp .rotate_cw4i.begin + .rotate_cw4i.quit: + pop eax ; get pointer to new data + mov esi, eax + mov edi, [ebx + Image.Data] + pop ecx ; get new data size + rep movsb + invoke mem.free, eax + pop edx ecx + jmp .exchange_dims + + + .flip: + stdcall img.flip.layer, [_img], FLIP_VERTICAL + test eax, eax + jz .error + jmp .exit + + .exchange_dims: + push [ebx + Image.Width] [ebx + Image.Height] + pop [ebx + Image.Width] [ebx + Image.Height] + + .exit: + invoke mem.free, [line_buffer] + xor eax, eax + inc eax + pop edi esi ebx + ret + + .error: + invoke mem.free, [line_buffer] + xor eax, eax + pop edi esi ebx + 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 + push eax + mov eax, [ebx + Image.Width] + imul eax, [_ypos] + add eax, [_xpos] + call img._.get_scanline_len + add eax, [ebx + Image.Data] + mov edx, [_x - 2] + mov dx, word [_y] + mov esi, [ebx + Image.Type] + mov esi, [type2bpp + (esi-1)*4] + mov edi, [ebx + Image.Palette] + xchg eax, ebx + pop eax + push ebp + push 65 + pop ebp + xchg eax, ebp + int 40h + pop ebp +.done: + pop edi esi ebx + ret +endp + + +align 4 +img.formats_table: + .bmp dd LIBIMG_FORMAT_BMP, img.is.bmp, img.decode.bmp, img.encode.bmp, 1 + (1 SHL Image.bpp24) + (1 SHL Image.bpp32) + .ico dd LIBIMG_FORMAT_ICO, img.is.ico, img.decode.ico_cur, img.encode.ico, 0 + .cur dd LIBIMG_FORMAT_CUR, img.is.cur, img.decode.ico_cur, img.encode.cur, 0 + .gif dd LIBIMG_FORMAT_GIF, img.is.gif, img.decode.gif, img.encode.gif, 0 + .png dd LIBIMG_FORMAT_PNG, img.is.png, img.decode.png, img.encode.png, 1 + (1 SHL Image.bpp24) + .jpg dd LIBIMG_FORMAT_JPEG, img.is.jpg, img.decode.jpg, img.encode.jpg, 0 + .tga dd LIBIMG_FORMAT_TGA, img.is.tga, img.decode.tga, img.encode.tga, 0 + .pcx dd LIBIMG_FORMAT_PCX, img.is.pcx, img.decode.pcx, img.encode.pcx, 0 + .xcf dd LIBIMG_FORMAT_XCF, img.is.xcf, img.decode.xcf, img.encode.xcf, 0 + .tiff dd LIBIMG_FORMAT_TIFF, img.is.tiff, img.decode.tiff, img.encode.tiff,0 + .pnm dd LIBIMG_FORMAT_PNM, img.is.pnm, img.decode.pnm, img.encode.pnm, 1 + (1 SHL Image.bpp1) + (1 SHL Image.bpp8g) + (1 SHL Image.bpp24) + .wbmp dd LIBIMG_FORMAT_WBMP, img.is.wbmp, img.decode.wbmp, img.encode.wbmp,0 + .xbm dd LIBIMG_FORMAT_XBM, img.is.xbm, img.decode.xbm, img.encode.xbm, 0 + .z80 dd LIBIMG_FORMAT_Z80, img.is.z80, img.decode.z80, img.encode.z80, 0 ;this must be the last entry as there are no signatures in z80 screens at all + dd 0 + +align 4 +img.types_table: ; entries order must correspond to type defnitions in libimg.inc + dd 0 ; there is no Image.bpp* = 0 + .bpp8i dd (1 SHL Image.bpp24) + .bpp24 dd (1 SHL Image.bpp24) OR (1 SHL Image.bpp8g) + .bpp32 dd (1 SHL Image.bpp24) + .bpp15 dd (1 SHL Image.bpp24) + .bpp16 dd (1 SHL Image.bpp24) + .bpp1 dd (1 SHL Image.bpp24) + .bpp8g dd (1 SHL Image.bpp24) OR (1 SHL Image.bpp1 ) OR (1 SHL Image.bpp8g) + .bpp8a dd (1 SHL Image.bpp24) + +;;================================================================================================;; +;;////////////////////////////////////////////////////////////////////////////////////////////////;; +;;================================================================================================;; +;! Below are private procs you should never call directly from your code ;; +;;================================================================================================;; +;;////////////////////////////////////////////////////////////////////////////////////////////////;; +;;================================================================================================;; + + +;;================================================================================================;; +proc img._.validate, _img ;///////////////////////////////////////////////////////////////////////;; +;;------------------------------------------------------------------------------------------------;; +;? --- TBD --- ;; +;;------------------------------------------------------------------------------------------------;; +;> --- TBD --- ;; +;;------------------------------------------------------------------------------------------------;; +;< --- TBD --- ;; +;;================================================================================================;; + xor eax, eax + ret +endp + +;;================================================================================================;; +proc img._.new ;//////////////////////////////////////////////////////////////////////////////////;; +;;------------------------------------------------------------------------------------------------;; +;? --- TBD --- ;; +;;------------------------------------------------------------------------------------------------;; +;> --- TBD --- ;; +;;------------------------------------------------------------------------------------------------;; +;< eax = 0 / pointer to image ;; +;;================================================================================================;; + invoke mem.alloc, sizeof.Image + test eax, eax + jz @f + push ecx + 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 + pop ecx +@@: + ret +endp + +;;================================================================================================;; +proc img._.delete _img ;//////////////////////////////////////////////////////////////////////////;; +;;------------------------------------------------------------------------------------------------;; +;? --- TBD --- ;; +;;------------------------------------------------------------------------------------------------;; +;> --- TBD --- ;; +;;------------------------------------------------------------------------------------------------;; +;< eax = false / true ;; +;;================================================================================================;; + push edx + mov edx, [_img] + cmp [edx + Image.Data], 0 + je @f + invoke mem.free, [edx + Image.Data] + @@: cmp [edx + Image.Extended], 0 + je @f + invoke mem.free, [edx + Image.Extended] + @@: invoke mem.free, edx + pop edx + ret +endp + +;;================================================================================================;; +proc img._.resize_data _img, _width, _height ;////////////////////////////////////////////////////;; +;;------------------------------------------------------------------------------------------------;; +;? --- TBD --- ;; +;;------------------------------------------------------------------------------------------------;; +;> --- TBD --- ;; +;;------------------------------------------------------------------------------------------------;; +;< --- TBD --- ;; +;;================================================================================================;; + push ebx esi + mov ebx, [_img] + mov eax, [_height] +; our memory is limited, [_width]*[_height] must not overflow +; image with width or height greater than 65535 is most likely bogus + cmp word [_width+2], 0 + jnz .error + cmp word [_height+2], 0 + jnz .error + imul eax, [_width] + test eax, eax + jz .error + cmp [ebx + Image.Type], Image.bpp1 + jz .bpp1 + cmp [ebx + Image.Type], Image.bpp2i + jz .bpp2i + cmp [ebx + Image.Type], Image.bpp4i + jz .bpp4i + cmp [ebx + Image.Type], Image.bpp8i + jz .bpp8i + cmp [ebx + Image.Type], Image.bpp8g + jz .bpp8g + cmp [ebx + Image.Type], Image.bpp8a + jz .bpp8a + cmp [ebx + Image.Type], Image.bpp24 + jz .bpp24 +.bpp32: + shl eax, 2 + jmp @f +.bpp24: + lea eax, [eax*3] + jmp @f +.bpp8i: + add eax, 256*4 ; for palette +.bpp8g: + jmp @f +.bpp8a: + shl eax, 1 + jmp @f +.bpp4i: + mov eax, [_width] + add eax, 1 + shr eax, 1 + imul eax, [_height] + mov ecx, eax + mov eax, [_height] + add eax, 1 + shr eax, 1 + imul eax, [_width] + cmp eax, ecx + jge .bpp4i.skip + mov eax, ecx + .bpp4i.skip: + add eax, 16*4 ; for palette + jmp @f +.bpp2i: + mov eax, [_width] + add eax, 3 + shr eax, 2 + imul eax, [_height] + mov ecx, eax + mov eax, [_height] + add eax, 3 + shr eax, 2 + imul eax, [_width] + cmp eax, ecx + jge .bpp2i.skip + mov eax, ecx + .bpp2i.skip: + add eax, 4*4 ; for palette + jmp @f +.bpp1: + mov eax, [_width] + add eax, 7 + shr eax, 3 + imul eax, [_height] + mov ecx, eax + mov eax, [_height] + add eax, 7 + shr eax, 3 + imul eax, [_width] + cmp eax, ecx + jge .bpp1.skip + mov eax, ecx + .bpp1.skip: + + add eax, 2*4 ; for palette +@@: + mov esi, eax + invoke mem.realloc, [ebx + Image.Data], eax + or eax, eax + jz .error + + mov [ebx + Image.Data], eax + push [_width] + pop [ebx + Image.Width] + push [_height] + pop [ebx + Image.Height] + cmp [ebx + Image.Type], Image.bpp8i + jnz @f + lea esi, [eax + esi - 256*4] + mov [ebx + Image.Palette], esi + jmp .ret +@@: + cmp [ebx + Image.Type], Image.bpp1 + jnz @f + lea esi, [eax + esi - 2*4] + mov [ebx + Image.Palette], esi + jmp .ret +@@: + cmp [ebx + Image.Type], Image.bpp2i + jnz @f + lea esi, [eax + esi - 4*4] + mov [ebx + Image.Palette], esi + jmp .ret +@@: + cmp [ebx + Image.Type], Image.bpp4i + jnz .ret + lea esi, [eax + esi - 16*4] + mov [ebx + Image.Palette], esi + jmp .ret + + .error: + xor eax, eax + .ret: + pop esi ebx + ret +endp + +;;================================================================================================;; +img._.get_scanline_len: ;/////////////////////////////////////////////////////////////////////////;; +;;------------------------------------------------------------------------------------------------;; +;? Get scanline length of image in bytes ;; +;;------------------------------------------------------------------------------------------------;; +;> eax = width of image in pixels ;; +;> ebx = image ;; +;;------------------------------------------------------------------------------------------------;; +;< eax = scanline length in bytes ;; +;;================================================================================================;; + cmp [ebx + Image.Type], Image.bpp1 + jz .bpp1.1 + cmp [ebx + Image.Type], Image.bpp2i + jz .bpp2i.1 + cmp [ebx + Image.Type], Image.bpp4i + jz .bpp4i.1 + cmp [ebx + Image.Type], Image.bpp8i + jz .bpp8.1 + cmp [ebx + Image.Type], Image.bpp8g + jz .bpp8.1 + cmp [ebx + Image.Type], Image.bpp8a + jz .bpp8a.1 + cmp [ebx + Image.Type], Image.bpp24 + jz .bpp24.1 + add eax, eax + cmp [ebx + Image.Type], Image.bpp32 + jnz .quit + add eax, eax + jmp .quit +.bpp24.1: + lea eax, [eax*3] + jmp .quit +.bpp1.1: + add eax, 7 + shr eax, 3 + jmp .quit +.bpp2i.1: + add eax, 3 + shr eax, 2 + jmp .quit +.bpp4i.1: + add eax, 1 + shr eax, 1 + jmp .quit +.bpp8a.1: + shl eax, 1 +.bpp8.1: +.quit: + ret + + +;;================================================================================================;; +;;////////////////////////////////////////////////////////////////////////////////////////////////;; +;;================================================================================================;; +;! Below is private data you should never use directly from your code ;; +;;================================================================================================;; +;;////////////////////////////////////////////////////////////////////////////////////////////////;; +;;================================================================================================;; + +align 4 +type2bpp dd 8, 24, 32, 15, 16, 1, 9, 2, 4 +img._.do_rgb.handlers: + dd img._.do_rgb.bpp8i + 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 + dd img._.do_rgb.bpp1 + dd img._.do_rgb.bpp8g + dd img._.do_rgb.bpp2i + dd img._.do_rgb.bpp4i + +img.flip.layer.handlers_horz: + dd img.flip.layer.bpp8ig_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 + dd img.flip.layer.bpp1_horz + dd img.flip.layer.bpp8ig_horz + dd img.flip.layer.bpp2i_horz + dd img.flip.layer.bpp4i_horz + +;;================================================================================================;; +;;////////////////////////////////////////////////////////////////////////////////////////////////;; +;;================================================================================================;; +;! Exported functions section ;; +;;================================================================================================;; +;;////////////////////////////////////////////////////////////////////////////////////////////////;; +;;================================================================================================;; + + +align 4 +@EXPORT: + +export \ + lib_init , 'lib_init' , \ + 0x00050007 , '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.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.flip.layer , 'img_flip_layer' , \ + img.rotate , 'img_rotate' , \ + img.rotate.layer , 'img_rotate_layer' , \ + img.draw , 'img_draw' , \ + img.scale , 'img_scale' , \ + img.get_scaled_size, 'img_get_scaled_size', \ + img.convert , 'img_convert' , \ + img.formats_table , 'img_formats_table' + +; import from deflate unpacker +; is initialized only when PNG loading is requested +align 16 +@IMPORT: + +library archiver, 'archiver.obj' +import archiver, \ + deflate_unpack2, 'deflate_unpack2',\ + deflateInit2, 'deflateInit2',\ + deflateReset, 'deflateReset',\ + deflate, 'deflate',\ + deflateEnd, 'deflateEnd',\ + calc_crc32, 'calc_crc32' + +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 +color_table_2 rd 256 +color_table_3 rd 256 +color_table_4 rd 256 diff --git a/programs/develop/libraries/libs-dev/libimg/libimg.inc b/programs/develop/libraries/libs-dev/libimg/libimg.inc index a617f8a171..23f92b4fff 100644 --- a/programs/develop/libraries/libs-dev/libimg/libimg.inc +++ b/programs/develop/libraries/libs-dev/libimg/libimg.inc @@ -1,124 +1,127 @@ -;;================================================================================================;; -;;//// libimg.inc //// (c) mike.dld, 2007-2008, (c) diamond, 2009, (c) dunkaist, 2011-2013 ///////;; -;;================================================================================================;; -;; ;; -;; 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 . ;; -;; ;; -;;================================================================================================;; - -; list of format id's -LIBIMG_FORMAT_BMP = 1 -LIBIMG_FORMAT_ICO = 2 -LIBIMG_FORMAT_CUR = 3 -LIBIMG_FORMAT_GIF = 4 -LIBIMG_FORMAT_PNG = 5 -LIBIMG_FORMAT_JPEG = 6 -LIBIMG_FORMAT_TGA = 7 -LIBIMG_FORMAT_PCX = 8 -LIBIMG_FORMAT_XCF = 9 -LIBIMG_FORMAT_TIFF = 10 -LIBIMG_FORMAT_PNM = 11 -LIBIMG_FORMAT_WBMP = 12 -LIBIMG_FORMAT_XBM = 13 -LIBIMG_FORMAT_Z80 = 14 - -; scale type ; corresponding img.scale params -LIBIMG_SCALE_INTEGER = 1 ; scale factor ; reserved 0 -LIBIMG_SCALE_TILE = 2 ; new width ; new height -LIBIMG_SCALE_STRETCH = 3 ; new width ; new height -LIBIMG_SCALE_FIT_RECT = 4 ; new width ; new height -LIBIMG_SCALE_FIT_WIDTH = 5 ; new width ; new height -LIBIMG_SCALE_FIT_HEIGHT = 6 ; new width ; new height -LIBIMG_SCALE_FIT_MAX = 7 ; new width ; new height - -; interpolation algorithm -LIBIMG_INTER_NONE = 0 ; use it with LIBIMG_SCALE_INTEGER, LIBIMG_SCALE_TILE, etc -LIBIMG_INTER_BILINEAR = 1 -;LIBIMG_INTER_BICUBIC = 2 -;LIBIMG_INTER_LANCZOS = 3 -LIBIMG_INTER_DEFAULT = LIBIMG_INTER_BILINEAR - -; error codes -LIBIMG_ERROR_OUT_OF_MEMORY = 1 -LIBIMG_ERROR_FORMAT = 2 -LIBIMG_ERROR_CONDITIONS = 3 -LIBIMG_ERROR_BIT_DEPTH = 4 -LIBIMG_ERROR_ENCODER = 5 -LIBIMG_ERROR_SRC_TYPE = 6 -LIBIMG_ERROR_SCALE = 7 -LIBIMG_ERROR_INTER = 8 -LIBIMG_ERROR_NOT_INPLEMENTED = 9 -LIBIMG_ERROR_INVALID_INPUT = 10 - -; encode flags (byte 0x02 of _common option) -LIBIMG_ENCODE_STRICT_SPECIFIC = 0x01 -LIBIMG_ENCODE_STRICT_BIT_DEPTH = 0x02 -LIBIMG_ENCODE_DELETE_ALPHA = 0x08 -LIBIMG_ENCODE_FLUSH_ALPHA = 0x10 - -; convert flags -; TBD - -struct FormatsTableEntry - Format_id dd ? - Is dd ? - Decode dd ? - Encode dd ? - Capabilities dd ? -ends - -struct Image - Checksum dd ? ; ((Width ROL 16) OR Height) XOR Data[0] ; ignored so far - Width dd ? - Height dd ? - Next dd ? - Previous dd ? - Type dd ? ; one of Image.bppN - Data dd ? - Palette dd ? ; used iff Type eq Image.bpp1, Image.bpp2, Image.bpp4 or Image.bpp8i - 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.bpp8i = 1 ; indexed -Image.bpp24 = 2 -Image.bpp32 = 3 -Image.bpp15 = 4 -Image.bpp16 = 5 -Image.bpp1 = 6 -Image.bpp8g = 7 ; grayscale -Image.bpp2i = 8 -Image.bpp4i = 9 -Image.bpp8a = 10 ; grayscale with alpha channel; application layer only!!! kernel doesn't handle this image type, libimg can only create and destroy such images - -; bits in Image.Flags -Image.IsAnimated = 1 - -struct ImageDecodeOptions - UsedSize dd ? ; if >=8, the field BackgroundColor is valid, and so on - BackgroundColor dd ? ; used for transparent images as background -ends - -FLIP_VERTICAL = 0x01 -FLIP_HORIZONTAL = 0x02 -FLIP_BOTH = FLIP_VERTICAL or FLIP_HORIZONTAL - -ROTATE_90_CW = 0x01 -ROTATE_180 = 0x02 -ROTATE_270_CW = 0x03 -ROTATE_90_CCW = ROTATE_270_CW -ROTATE_270_CCW = ROTATE_90_CW +;;================================================================================================;; +;;//// libimg.inc //// (c) mike.dld, 2007-2008, (c) diamond, 2009, (c) dunkaist, 2011-2013 ///////;; +;;================================================================================================;; +;; ;; +;; 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 . ;; +;; ;; +;;================================================================================================;; + +; list of format id's +LIBIMG_FORMAT_BMP = 1 +LIBIMG_FORMAT_ICO = 2 +LIBIMG_FORMAT_CUR = 3 +LIBIMG_FORMAT_GIF = 4 +LIBIMG_FORMAT_PNG = 5 +LIBIMG_FORMAT_JPEG = 6 +LIBIMG_FORMAT_TGA = 7 +LIBIMG_FORMAT_PCX = 8 +LIBIMG_FORMAT_XCF = 9 +LIBIMG_FORMAT_TIFF = 10 +LIBIMG_FORMAT_PNM = 11 +LIBIMG_FORMAT_WBMP = 12 +LIBIMG_FORMAT_XBM = 13 +LIBIMG_FORMAT_Z80 = 14 + +; scale type ; corresponding img.scale params +LIBIMG_SCALE_NONE = 0 ; do not scale +LIBIMG_SCALE_INTEGER = 1 ; scale factor ; reserved 0 +LIBIMG_SCALE_TILE = 2 ; new width ; new height +LIBIMG_SCALE_STRETCH = 3 ; new width ; new height +LIBIMG_SCALE_FIT_BOTH = LIBIMG_SCALE_STRETCH +LIBIMG_SCALE_FIT_MIN = 4 ; new width ; new height +LIBIMG_SCALE_FIT_RECT = LIBIMG_SCALE_FIT_MIN +LIBIMG_SCALE_FIT_WIDTH = 5 ; new width ; new height +LIBIMG_SCALE_FIT_HEIGHT = 6 ; new width ; new height +LIBIMG_SCALE_FIT_MAX = 7 ; new width ; new height + +; interpolation algorithm +LIBIMG_INTER_NONE = 0 ; use it with LIBIMG_SCALE_INTEGER, LIBIMG_SCALE_TILE, etc +LIBIMG_INTER_BILINEAR = 1 +;LIBIMG_INTER_BICUBIC = 2 +;LIBIMG_INTER_LANCZOS = 3 +LIBIMG_INTER_DEFAULT = LIBIMG_INTER_BILINEAR + +; error codes +LIBIMG_ERROR_OUT_OF_MEMORY = 1 +LIBIMG_ERROR_FORMAT = 2 +LIBIMG_ERROR_CONDITIONS = 3 +LIBIMG_ERROR_BIT_DEPTH = 4 +LIBIMG_ERROR_ENCODER = 5 +LIBIMG_ERROR_SRC_TYPE = 6 +LIBIMG_ERROR_SCALE = 7 +LIBIMG_ERROR_INTER = 8 +LIBIMG_ERROR_NOT_INPLEMENTED = 9 +LIBIMG_ERROR_INVALID_INPUT = 10 + +; encode flags (byte 0x02 of _common option) +;LIBIMG_ENCODE_STRICT_SPECIFIC = 0x01 +LIBIMG_ENCODE_STRICT_BIT_DEPTH = 0x02 +;LIBIMG_ENCODE_DELETE_ALPHA = 0x08 +;LIBIMG_ENCODE_FLUSH_ALPHA = 0x10 + +; convert flags +; none so far + +struct FormatsTableEntry + Format_id dd ? + Is dd ? + Decode dd ? + Encode dd ? + Capabilities dd ? +ends + +struct Image + Checksum dd ? ; ((Width ROL 16) OR Height) XOR Data[0] ; ignored so far + Width dd ? + Height dd ? + Next dd ? + Previous dd ? + Type dd ? ; one of Image.bppN + Data dd ? + Palette dd ? ; used iff Type eq Image.bpp1, Image.bpp2, Image.bpp4 or Image.bpp8i + 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.bpp8i = 1 ; indexed +Image.bpp24 = 2 +Image.bpp32 = 3 +Image.bpp15 = 4 +Image.bpp16 = 5 +Image.bpp1 = 6 +Image.bpp8g = 7 ; grayscale +Image.bpp2i = 8 +Image.bpp4i = 9 +Image.bpp8a = 10 ; grayscale with alpha channel; application layer only!!! kernel doesn't handle this image type, libimg can only create and destroy such images + +; bits in Image.Flags +Image.IsAnimated = 1 + +struct ImageDecodeOptions + UsedSize dd ? ; if >=8, the field BackgroundColor is valid, and so on + BackgroundColor dd ? ; used for transparent images as background +ends + +FLIP_VERTICAL = 0x01 +FLIP_HORIZONTAL = 0x02 +FLIP_BOTH = FLIP_VERTICAL or FLIP_HORIZONTAL + +ROTATE_90_CW = 0x01 +ROTATE_180 = 0x02 +ROTATE_270_CW = 0x03 +ROTATE_90_CCW = ROTATE_270_CW +ROTATE_270_CCW = ROTATE_90_CW diff --git a/programs/develop/libraries/libs-dev/libimg/scale.asm b/programs/develop/libraries/libs-dev/libimg/scale.asm index cc932e4c2a..f8f3fce470 100644 --- a/programs/develop/libraries/libs-dev/libimg/scale.asm +++ b/programs/develop/libraries/libs-dev/libimg/scale.asm @@ -17,6 +17,89 @@ ;; ;; ;;================================================================================================;; + +;;================================================================================================;; +proc img.get_scaled_size _width, _height, _scale_type, _param1, _param2 ;; +;;------------------------------------------------------------------------------------------------;; +;? calculate resulting width and height if image of _width and _height is scaled via _scale_type ;; +;;------------------------------------------------------------------------------------------------;; +;> [_width] = width of input image ;; +;> [_height] = height of input image ;; +;> [_scale_type] = see libimg.inc (LIBIMG_SCALE_*) ;; +;> [_param1] = depends on _scale_type, see libimg.inc ;; +;> [_param2] = depends on _scale_type, see libimg.inc ;; +;;------------------------------------------------------------------------------------------------;; +;< eax = width ;; +;< ecx = height ;; +;;================================================================================================;; + push ebx esi edi + mov eax, [_scale_type] + cmp eax, LIBIMG_SCALE_FIT_MIN + jz .fit_min + + .fit_min: + xor edx, edx + mov eax, [_width] + shl eax, 1 + mov ecx, [_param1] + add eax, ecx + shl eax, 15 + div ecx + mov ebx, eax + + xor edx, edx + mov eax, [_height] + shl eax, 1 + mov ecx, [_param2] + add eax, ecx + shl eax, 15 + div ecx + + cmp eax, ebx + ja .fit_height + jmp .fit_width + + jmp .quit + .fit_max: + jmp .quit + .fit_width: + xor edx, edx + mov eax, [_width] + shl eax, 16 + div [_param1] + mov ecx, eax + xor edx, edx + mov eax, [_height] + shl eax, 16 + mov ebx, ecx + shr ebx, 1 + add eax, ebx + div ecx + mov ecx, eax + mov eax, [_param1] + jmp .quit + .fit_height: + xor edx, edx + mov eax, [_height] + shl eax, 16 + div [_param2] + mov ecx, eax + xor edx, edx + mov eax, [_width] + shl eax, 16 + mov ebx, ecx + shr ebx, 1 + add eax, ebx + div ecx + mov ecx, [_param2] + jmp .quit + + .quit: + pop edi esi ebx + ret +endp + + ;;================================================================================================;; proc img.scale _src, _crop_x, _crop_y, _crop_width, _crop_height, _dst, _scale, _inter, _param1, _param2 ;; ;;------------------------------------------------------------------------------------------------;; @@ -27,685 +110,714 @@ proc img.scale _src, _crop_x, _crop_y, _crop_width, _crop_height, _dst, _scale, ;> [_crop_y] = top coord of cropping rect ;; ;> [_crop_width] = width of cropping rect ;; ;> [_crop_height] = height of cropping rect ;; -;> [_dst] = pointer to resulting image / 0 ;; -;> [_scale] = how to change width and height. see libimg.inc ;; -;> [_inter] = interpolation algorithm ;; -;> [_param1] = see libimg.inc ;; -;> [_param2] = see libimg.inc ;; +;> [_dst] = pointer to resulting image, 0 to create new one ;; +;> [_scale] = scaling method, see libimg.inc (LIBIMG_SCALE_*) ;; +;> [_inter] = interpolation algorithm, see libimg.inc (LIBIMG_INTER_*) ;; +;> [_param1] = depends on _scale, see libimg.inc ;; +;> [_param2] = depends on _scale, see libimg.inc ;; +;;------------------------------------------------------------------------------------------------;; +;< eax = 0 / pointer to scaled image ;; +;< ecx = error code / undefined ;; +;;================================================================================================;; + push ebx esi edi 0 0 + mov ebx, [_src] + @@: + mov eax, [ebx + Image.Previous] + test eax, eax + jz .loop + mov ebx, eax + jmp @b + .loop: + stdcall img.scale.layer, ebx, [_crop_x], [_crop_y], [_crop_width], [_crop_height], [_dst], [_scale], [_inter], [_param1], [_param2] + test eax, eax + jz .error + cmp dword[esp + 4], 0 + jnz @f + mov [esp + 4], eax + @@: + mov ecx, [esp] + jecxz @f + mov [ecx + Image.Next], eax + @@: + push [ebx + Image.Flags] + pop [eax + Image.Flags] + push [ebx + Image.Delay] + pop [eax + Image.Delay] + mov [eax + Image.Previous], ecx + mov [esp], eax + mov ebx, [ebx + Image.Next] + test ebx, ebx + jnz .loop + .quit: + pop eax eax edi esi ebx + ret + .error: + pop eax eax edi esi ebx + ret +endp + + +;;================================================================================================;; +proc img.scale.layer _src, _crop_x, _crop_y, _crop_width, _crop_height, _dst, _scale, _inter, _param1, _param2 ;; +;;------------------------------------------------------------------------------------------------;; +;? scale _image layer ;; +;;------------------------------------------------------------------------------------------------;; +;> [_src] = pointer to source image ;; +;> [_crop_x] = left coord of cropping rect ;; +;> [_crop_y] = top coord of cropping rect ;; +;> [_crop_width] = width of cropping rect ;; +;> [_crop_height] = height of cropping rect ;; +;> [_dst] = pointer to resulting image, 0 to create new one ;; +;> [_scale] = scaling method, see libimg.inc (LIBIMG_SCALE_*) ;; +;> [_inter] = interpolation algorithm, see libimg.inc (LIBIMG_INTER_*) ;; +;> [_param1] = depends on _scale, see libimg.inc ;; +;> [_param2] = depends on _scale, see libimg.inc ;; ;;------------------------------------------------------------------------------------------------;; ;< eax = 0 / pointer to scaled image ;; ;< ecx = error code / undefined ;; ;;================================================================================================;; locals - src_type rd 1 - src_data rd 1 - dst_data rd 1 + src_type rd 1 + src_data rd 1 + dst_data rd 1 - src_width_pixels rd 1 - src_width_bytes rd 1 - src_height_pixels rd 1 + src_width_pixels rd 1 + src_width_bytes rd 1 + src_height_pixels rd 1 - dst_width_pixels rd 1 - dst_width_pixels_inv rd 1 - dst_height_pixels rd 1 - dst_height_pixels_inv rd 1 - dst_width_bytes rd 1 - bytes_per_pixel rd 1 + dst_width_pixels rd 1 + dst_width_pixels_inv rd 1 + dst_height_pixels rd 1 + dst_height_pixels_inv rd 1 + dst_width_bytes rd 1 + bytes_per_pixel rd 1 - crop_width_pixels_m1 rd 1 - crop_height_pixels_m1 rd 1 + crop_width_pixels_m1 rd 1 + crop_height_pixels_m1 rd 1 ; bilinear - src_x rd 1 - src_y rd 1 - src_base rd 1 - dst_x rd 1 - dst_y rd 1 - rem_x rd 1 - rem_y rd 1 + src_x rd 1 + src_y rd 1 + src_base rd 1 + dst_x rd 1 + dst_y rd 1 + rem_x rd 1 + rem_y rd 1 endl - mov ebx, [_src] - push [ebx + Image.Width] - pop [src_width_pixels] - push [ebx + Image.Height] - pop [src_height_pixels] - push [ebx + Image.Type] - pop [src_type] - push [ebx + Image.Data] - pop [src_data] + push ebx esi edi + mov ebx, [_src] + push [ebx + Image.Width] + pop [src_width_pixels] + push [ebx + Image.Height] + pop [src_height_pixels] + push [ebx + Image.Type] + pop [src_type] + push [ebx + Image.Data] + pop [src_data] - mov eax, [src_type] - mov ecx, [src_width_pixels] - mov edx, [src_width_pixels] - imul edx, [_crop_y] - add edx, [_crop_x] - cmp eax, Image.bpp32 - jne @f - mov [bytes_per_pixel], 4 - shl ecx, 2 - shl edx, 2 - jmp .lab1 + mov eax, [src_type] + mov ecx, [src_width_pixels] + mov edx, [src_width_pixels] + imul edx, [_crop_y] + add edx, [_crop_x] + cmp eax, Image.bpp32 + jne @f + mov [bytes_per_pixel], 4 + shl ecx, 2 + shl edx, 2 + jmp .lab1 @@: - cmp eax, Image.bpp24 - jne @f - mov [bytes_per_pixel], 3 - lea ecx, [ecx*3] - lea edx, [edx*3] - jmp .lab1 + cmp eax, Image.bpp24 + jne @f + mov [bytes_per_pixel], 3 + lea ecx, [ecx*3] + lea edx, [edx*3] + jmp .lab1 @@: - cmp eax, Image.bpp8g - jne @f - mov [bytes_per_pixel], 1 - jmp .lab1 + cmp eax, Image.bpp8g + jne @f + mov [bytes_per_pixel], 1 + jmp .lab1 @@: - mov ecx, LIBIMG_ERROR_BIT_DEPTH - jmp .error + mov ecx, LIBIMG_ERROR_BIT_DEPTH + jmp .error .lab1: - mov [src_width_bytes], ecx - add [src_data], edx + mov [src_width_bytes], ecx + add [src_data], edx - mov eax, [_scale] - cmp eax, LIBIMG_SCALE_INTEGER - je .scale_type.integer - cmp eax, LIBIMG_SCALE_TILE - je .scale_type.tile - cmp eax, LIBIMG_SCALE_FIT_RECT - je .scale_type.fit_rect - cmp eax, LIBIMG_SCALE_FIT_WIDTH - je .scale_type.fit_width - cmp eax, LIBIMG_SCALE_FIT_HEIGHT - je .scale_type.fit_height - cmp eax, LIBIMG_SCALE_FIT_MAX - je .scale_type.fit_max - cmp eax, LIBIMG_SCALE_STRETCH - je .scale_type.stretch - mov ecx, LIBIMG_ERROR_SCALE - jmp .error + mov eax, [_scale] + cmp eax, LIBIMG_SCALE_INTEGER + je .scale_type.integer + cmp eax, LIBIMG_SCALE_TILE + je .scale_type.tile + cmp eax, LIBIMG_SCALE_FIT_RECT + je .scale_type.fit_rect + cmp eax, LIBIMG_SCALE_FIT_WIDTH + je .scale_type.fit_width + cmp eax, LIBIMG_SCALE_FIT_HEIGHT + je .scale_type.fit_height + cmp eax, LIBIMG_SCALE_FIT_MAX + je .scale_type.fit_max + cmp eax, LIBIMG_SCALE_STRETCH + je .scale_type.stretch + mov ecx, LIBIMG_ERROR_SCALE + jmp .error .scale_type.integer: - jmp .integer + jmp .integer .scale_type.tile: - jmp .tile + jmp .tile .scale_type.fit_rect: - mov eax, [_param1] - shl eax, 16 - add eax, 0x00008000 - xor edx, edx - div [src_width_pixels] - mov ebx, eax - mov eax, [_param2] - shl eax, 16 - add eax, 0x00008000 - xor edx, edx - div [src_height_pixels] - mov ecx, eax - cmp ebx, ecx - jb @f - mov ebx, ecx - @@: - jmp .scale_type.fit_common .scale_type.fit_max: - mov eax, [_param1] - shl eax, 16 - add eax, 0x00008000 - xor edx, edx - div [src_width_pixels] - mov ebx, eax - mov eax, [_param2] - shl eax, 16 - add eax, 0x00008000 - xor edx, edx - div [src_height_pixels] - mov ecx, eax - cmp ebx, ecx - ja @f - mov ebx, ecx - @@: - jmp .scale_type.fit_common .scale_type.fit_width: - mov eax, [_param1] - shl eax, 16 - add eax, 0x00008000 - xor edx, edx - div [src_width_pixels] - mov ebx, eax - jmp .scale_type.fit_common .scale_type.fit_height: - mov eax, [_param2] - shl eax, 16 - add eax, 0x00008000 - xor edx, edx - div [src_height_pixels] - mov ebx, eax - jmp .scale_type.fit_common - .scale_type.fit_common: - mov eax, [src_width_pixels] - mul ebx - shr eax, 16 - mov [dst_width_pixels], eax - imul eax, [bytes_per_pixel] - mov [dst_width_bytes], eax - mov eax, [src_height_pixels] - mul ebx - shr eax, 16 - mov [dst_height_pixels], eax - jmp .define_inter + mov eax, [_src] + stdcall img.get_scaled_size, [eax + Image.Width], [eax + Image.Height], [_scale], [_param1], [_param2] + mov [_param1], eax + mov [_param2], ecx .scale_type.stretch: - mov eax, [_param1] - mov [dst_width_pixels], eax - imul eax, [bytes_per_pixel] - mov [dst_width_bytes], eax - mov ecx, [_param2] - mov [dst_height_pixels], ecx - jmp .define_inter + mov eax, [_param1] + mov [dst_width_pixels], eax + imul eax, [bytes_per_pixel] + mov [dst_width_bytes], eax + mov ecx, [_param2] + mov [dst_height_pixels], ecx + jmp .define_inter .define_inter: - mov eax, [_inter] - cmp eax, LIBIMG_INTER_BILINEAR - je .bilinear - mov ecx, LIBIMG_ERROR_INTER - jmp .error + mov eax, [_inter] + cmp eax, LIBIMG_INTER_BILINEAR + je .bilinear + mov ecx, LIBIMG_ERROR_INTER + jmp .error .integer: - mov eax, [_param1] - mov ecx, [_crop_width] - imul ecx, eax - mov [dst_width_pixels], ecx - mov edx, [_crop_height] - imul edx, eax - mov [dst_height_pixels], edx + mov eax, [_param1] + mov ecx, [_crop_width] + imul ecx, eax + mov [dst_width_pixels], ecx + mov edx, [_crop_height] + imul edx, eax + mov [dst_height_pixels], edx - mov eax, [_dst] - test eax, eax - jnz @f - stdcall img.create, [dst_width_pixels], [dst_height_pixels], [src_type] - test eax, eax - jz .error - mov [_dst], eax + mov eax, [_dst] + test eax, eax + jnz @f + stdcall img.create, [dst_width_pixels], [dst_height_pixels], [src_type] + test eax, eax + jz .error + mov [_dst], eax + mov edi, [_src] + push [edi + Image.Flags] + pop [eax + Image.Flags] + push [edi + Image.Delay] + pop [eax + Image.Delay] + push [edi + Image.Previous] + pop [eax + Image.Previous] + push [edi + Image.Next] + pop [eax + Image.Next] @@: - mov edi, [eax + Image.Data] - mov [dst_data], edi + mov edi, [eax + Image.Data] + mov [dst_data], edi - mov esi, [src_data] - mov eax, [src_type] - cmp eax, Image.bpp8g - je .integer.bpp8g - cmp eax, Image.bpp24 - je .integer.bpp24 - cmp eax, Image.bpp32 - je .integer.bpp32 - mov ecx, LIBIMG_ERROR_BIT_DEPTH - jmp .error + mov esi, [src_data] + mov eax, [src_type] + cmp eax, Image.bpp8g + je .integer.bpp8g + cmp eax, Image.bpp24 + je .integer.bpp24 + cmp eax, Image.bpp32 + je .integer.bpp32 + mov ecx, LIBIMG_ERROR_BIT_DEPTH + jmp .error .integer.bpp8g: - push [dst_width_pixels] - pop [dst_width_bytes] - mov ecx, [_param1] -; cmp ecx, 1 -; je .error + push [dst_width_pixels] + pop [dst_width_bytes] + mov ecx, [_param1] +; cmp ecx, 1 +; je .error .integer.bpp8g.common: - mov edx, ecx - mov ebx, [_crop_height] + mov edx, ecx + mov ebx, [_crop_height] .integer.bpp8g.common.line: - push ebx - mov ebx, [_crop_width] - @@: - lodsb - mov ecx, edx - rep stosb - dec ebx - jnz @b - push esi - mov esi, edi - sub esi, [dst_width_bytes] - mov ecx, edx - dec ecx - imul ecx, [dst_width_bytes] - mov eax, ecx - shr ecx, 2 - and eax, 0x00000003 - rep movsd - mov ecx, eax - rep movsb - pop esi - mov eax, [src_width_pixels] - sub eax, [_crop_width] - add esi, eax - pop ebx - dec ebx - jnz .integer.bpp8g.common.line - mov eax, [_dst] - jmp .quit + push ebx + mov ebx, [_crop_width] + @@: + lodsb + mov ecx, edx + rep stosb + dec ebx + jnz @b + push esi + mov esi, edi + sub esi, [dst_width_bytes] + mov ecx, edx + dec ecx + imul ecx, [dst_width_bytes] + mov eax, ecx + shr ecx, 2 + and eax, 0x00000003 + rep movsd + mov ecx, eax + rep movsb + pop esi + mov eax, [src_width_pixels] + sub eax, [_crop_width] + add esi, eax + pop ebx + dec ebx + jnz .integer.bpp8g.common.line + mov eax, [_dst] + jmp .quit .integer.bpp24: - mov eax, [dst_width_pixels] - lea eax, [eax*3] - mov [dst_width_bytes], eax - mov ecx, [_param1] -; cmp ecx, 1 -; je .error + mov eax, [dst_width_pixels] + lea eax, [eax*3] + mov [dst_width_bytes], eax + mov ecx, [_param1] +; cmp ecx, 1 +; je .error .integer.bpp24.common: - mov edx, ecx - mov ebx, [_crop_height] + mov edx, ecx + mov ebx, [_crop_height] .integer.bpp24.common.line: - push ebx - mov ebx, [_crop_width] - @@: - movsw - movsb - mov ecx, edx - push esi - mov esi, edi - sub esi, 3 - dec ecx - lea ecx, [ecx*3] - rep movsb - pop esi - dec ebx - jnz @b - push esi - mov esi, edi - sub esi, [dst_width_bytes] - mov ecx, edx - dec ecx - imul ecx, [dst_width_bytes] - mov eax, ecx - shr ecx, 2 - and eax, 0x00000003 - rep movsd - mov ecx, eax - rep movsb - pop esi - mov eax, [src_width_pixels] - sub eax, [_crop_width] - lea eax, [eax*3] - add esi, eax - pop ebx - dec ebx - jnz .integer.bpp24.common.line - mov eax, [_dst] - jmp .quit + push ebx + mov ebx, [_crop_width] + @@: + movsw + movsb + mov ecx, edx + push esi + mov esi, edi + sub esi, 3 + dec ecx + lea ecx, [ecx*3] + rep movsb + pop esi + dec ebx + jnz @b + push esi + mov esi, edi + sub esi, [dst_width_bytes] + mov ecx, edx + dec ecx + imul ecx, [dst_width_bytes] + mov eax, ecx + shr ecx, 2 + and eax, 0x00000003 + rep movsd + mov ecx, eax + rep movsb + pop esi + mov eax, [src_width_pixels] + sub eax, [_crop_width] + lea eax, [eax*3] + add esi, eax + pop ebx + dec ebx + jnz .integer.bpp24.common.line + mov eax, [_dst] + jmp .quit .integer.bpp32: - mov eax, [dst_width_pixels] - shl eax, 2 - mov [dst_width_bytes], eax - mov ecx, [_param1] -; cmp ecx, 1 -; je .error + mov eax, [dst_width_pixels] + shl eax, 2 + mov [dst_width_bytes], eax + mov ecx, [_param1] +; cmp ecx, 1 +; je .error .integer.bpp32.common: - mov edx, ecx - mov ebx, [_crop_height] + mov edx, ecx + mov ebx, [_crop_height] .integer.bpp32.common.line: - push ebx - mov ebx, [_crop_width] - @@: - lodsd - mov ecx, edx - rep stosd - dec ebx - jnz @b - push esi - mov esi, edi - sub esi, [dst_width_bytes] - mov ecx, edx - dec ecx - imul ecx, [dst_width_bytes] - shr ecx, 2 - rep movsd - pop esi - mov eax, [src_width_pixels] - sub eax, [_crop_width] - shl eax, 2 - add esi, eax - pop ebx - dec ebx - jnz .integer.bpp32.common.line - mov eax, [_dst] - jmp .quit + push ebx + mov ebx, [_crop_width] + @@: + lodsd + mov ecx, edx + rep stosd + dec ebx + jnz @b + push esi + mov esi, edi + sub esi, [dst_width_bytes] + mov ecx, edx + dec ecx + imul ecx, [dst_width_bytes] + shr ecx, 2 + rep movsd + pop esi + mov eax, [src_width_pixels] + sub eax, [_crop_width] + shl eax, 2 + add esi, eax + pop ebx + dec ebx + jnz .integer.bpp32.common.line + mov eax, [_dst] + jmp .quit .tile: - mov eax, [_param1] - mov [dst_width_pixels], eax - imul eax, [bytes_per_pixel] - mov [dst_width_bytes], eax - mov eax, [_param2] - mov [dst_height_pixels], eax + mov eax, [_param1] + mov [dst_width_pixels], eax + imul eax, [bytes_per_pixel] + mov [dst_width_bytes], eax + mov eax, [_param2] + mov [dst_height_pixels], eax - mov eax, [_dst] - test eax, eax - jnz @f - stdcall img.create, [dst_width_pixels], [dst_height_pixels], [src_type] - test eax, eax - jz .error - mov [_dst], eax - @@: - mov edi, [eax + Image.Data] - mov [dst_data], edi + mov eax, [_dst] + test eax, eax + jnz @f + stdcall img.create, [dst_width_pixels], [dst_height_pixels], [src_type] + test eax, eax + jz .error + mov [_dst], eax + mov edi, [_src] + push [edi + Image.Flags] + pop [eax + Image.Flags] + push [edi + Image.Delay] + pop [eax + Image.Delay] + push [edi + Image.Previous] + pop [eax + Image.Previous] + push [edi + Image.Next] + pop [eax + Image.Next] + @@: + mov edi, [eax + Image.Data] + mov [dst_data], edi - mov esi, [src_data] - mov eax, [_crop_height] - cmp eax, [dst_height_pixels] - jna @f - mov eax, [dst_height_pixels] - @@: - push eax - mov ecx, [_crop_width] - cmp ecx, [dst_width_pixels] - jna @f - mov ecx, [dst_width_pixels] - @@: - imul ecx, [bytes_per_pixel] - mov edx, ecx - @@: - mov ecx, edx - rep movsb + mov esi, [src_data] + mov eax, [_crop_height] + cmp eax, [dst_height_pixels] + jna @f + mov eax, [dst_height_pixels] + @@: + push eax + mov ecx, [_crop_width] + cmp ecx, [dst_width_pixels] + jna @f + mov ecx, [dst_width_pixels] + @@: + imul ecx, [bytes_per_pixel] + mov edx, ecx + @@: + mov ecx, edx + rep movsb - push esi - mov esi, edi - sub esi, edx - mov ecx, [dst_width_bytes] - sub ecx, edx - rep movsb - pop esi + push esi + mov esi, edi + sub esi, edx + mov ecx, [dst_width_bytes] + sub ecx, edx + rep movsb + pop esi - mov ecx, [src_width_bytes] - sub ecx, edx - add esi, ecx - dec eax - jnz @b + mov ecx, [src_width_bytes] + sub ecx, edx + add esi, ecx + dec eax + jnz @b - pop eax - mov esi, [dst_data] - mov ecx, [dst_height_pixels] - sub ecx, eax - imul ecx, [dst_width_bytes] - rep movsb + pop eax + mov esi, [dst_data] + mov ecx, [dst_height_pixels] + sub ecx, eax + imul ecx, [dst_width_bytes] + rep movsb - mov eax, [_dst] - jmp .quit + mov eax, [_dst] + jmp .quit .bilinear: - mov eax, [_dst] - test eax, eax - jnz @f - stdcall img.create, [dst_width_pixels], [dst_height_pixels], [src_type] - test eax, eax - jz .error - mov [_dst], eax + mov eax, [_dst] + test eax, eax + jnz @f + stdcall img.create, [dst_width_pixels], [dst_height_pixels], [src_type] + test eax, eax + jz .error + mov [_dst], eax + mov edi, [_src] + push [edi + Image.Flags] + pop [eax + Image.Flags] + push [edi + Image.Delay] + pop [eax + Image.Delay] + push [edi + Image.Previous] + pop [eax + Image.Previous] + push [edi + Image.Next] + pop [eax + Image.Next] @@: - mov edi, [eax + Image.Data] - mov [dst_data], edi + mov edi, [eax + Image.Data] + mov [dst_data], edi - push [_crop_width] - pop [crop_width_pixels_m1] - sub [crop_width_pixels_m1], 1 - push [_crop_height] - pop [crop_height_pixels_m1] - sub [crop_height_pixels_m1], 1 + push [_crop_width] + pop [crop_width_pixels_m1] + sub [crop_width_pixels_m1], 1 + push [_crop_height] + pop [crop_height_pixels_m1] + sub [crop_height_pixels_m1], 1 - mov eax, 0xffffffff - xor edx, edx - div [dst_width_pixels] - mov [dst_width_pixels_inv], eax - mov eax, 0xffffffff - xor edx, edx - div [dst_height_pixels] - mov [dst_height_pixels_inv], eax + mov eax, 0xffffffff + xor edx, edx + div [dst_width_pixels] + mov [dst_width_pixels_inv], eax + mov eax, 0xffffffff + xor edx, edx + div [dst_height_pixels] + mov [dst_height_pixels_inv], eax - mov eax, [src_type] - cmp eax, Image.bpp8g - je .bilinear.bpp8g - cmp eax, Image.bpp24 - je .bilinear.bpp24 - cmp eax, Image.bpp32 - je .bilinear.bpp32 - mov ecx, LIBIMG_ERROR_BIT_DEPTH - jmp .error + mov eax, [src_type] + cmp eax, Image.bpp8g + je .bilinear.bpp8g + cmp eax, Image.bpp24 + je .bilinear.bpp24 + cmp eax, Image.bpp32 + je .bilinear.bpp32 + mov ecx, LIBIMG_ERROR_BIT_DEPTH + jmp .error .bilinear.bpp8g: - mov esi, [src_data] - mov [dst_y], 0 - mov eax, 0 ; mov eax, [dst_y] + mov esi, [src_data] + mov [dst_y], 0 + mov eax, 0 ; mov eax, [dst_y] .bilinear.bpp8g.line: - mov esi, [src_data] - mov [dst_x], 0 - imul eax, [crop_height_pixels_m1] - xor edx, edx - div [dst_height_pixels] - mov [rem_y], edx - imul eax, [src_width_bytes] - add esi, eax - mov [src_base], esi - mov eax, 0 ; mov eax, [dst_x] + mov esi, [src_data] + mov [dst_x], 0 + imul eax, [crop_height_pixels_m1] + xor edx, edx + div [dst_height_pixels] + mov [rem_y], edx + imul eax, [src_width_bytes] + add esi, eax + mov [src_base], esi + mov eax, 0 ; mov eax, [dst_x] .bilinear.bpp8g.pixel: - mov esi, [src_base] + mov esi, [src_base] - imul eax, [crop_width_pixels_m1] - xor edx, edx - div [dst_width_pixels] - add esi, eax + imul eax, [crop_width_pixels_m1] + xor edx, edx + div [dst_width_pixels] + add esi, eax - mov ax, word[esi] - add esi, [src_width_pixels] - mov bx, word[esi] - mov esi, edx - movzx edx, ah - and eax, 0x000000ff - movzx ecx, bh - and ebx, 0x000000ff + mov ax, word[esi] + add esi, [src_width_pixels] + mov bx, word[esi] + mov esi, edx + movzx edx, ah + and eax, 0x000000ff + movzx ecx, bh + and ebx, 0x000000ff - imul edx, esi - imul ecx, esi - neg esi - add esi, [dst_width_pixels] - imul eax, esi - imul ebx, esi - add eax, edx - add ebx, ecx - mov esi, [dst_width_pixels_inv] - mul esi - mov ecx, edx - mov eax, ebx - mul esi - mov eax, edx + imul edx, esi + imul ecx, esi + neg esi + add esi, [dst_width_pixels] + imul eax, esi + imul ebx, esi + add eax, edx + add ebx, ecx + mov esi, [dst_width_pixels_inv] + mul esi + mov ecx, edx + mov eax, ebx + mul esi + mov eax, edx - mov edx, [rem_y] - imul eax, edx - neg edx - add edx, [dst_height_pixels] - imul ecx, edx - add eax, ecx - mul [dst_height_pixels_inv] - mov byte[edi], dl - add edi, 1 + mov edx, [rem_y] + imul eax, edx + neg edx + add edx, [dst_height_pixels] + imul ecx, edx + add eax, ecx + mul [dst_height_pixels_inv] + mov byte[edi], dl + add edi, 1 - add [dst_x], 1 - mov eax, [dst_x] - cmp eax, [dst_width_pixels] - jne .bilinear.bpp8g.pixel + add [dst_x], 1 + mov eax, [dst_x] + cmp eax, [dst_width_pixels] + jne .bilinear.bpp8g.pixel - add [dst_y], 1 - mov eax, [dst_y] - cmp eax, [dst_height_pixels] - jne .bilinear.bpp8g.line + add [dst_y], 1 + mov eax, [dst_y] + cmp eax, [dst_height_pixels] + jne .bilinear.bpp8g.line - mov eax, [_dst] - jmp .quit + mov eax, [_dst] + jmp .quit .bilinear.bpp24: - mov esi, [src_data] - mov [dst_y], 0 - mov eax, 0 ; mov eax, [dst_y] + mov esi, [src_data] + mov [dst_y], 0 + mov eax, 0 ; mov eax, [dst_y] .bilinear.bpp24.line: - mov esi, [src_data] - mov [dst_x], 0 - imul eax, [crop_height_pixels_m1] - xor edx, edx - div [dst_height_pixels] - mov [rem_y], edx - imul eax, [src_width_bytes] - add esi, eax - mov [src_base], esi - mov eax, 0 ; mov eax, [dst_x] + mov esi, [src_data] + mov [dst_x], 0 + imul eax, [crop_height_pixels_m1] + xor edx, edx + div [dst_height_pixels] + mov [rem_y], edx + imul eax, [src_width_bytes] + add esi, eax + mov [src_base], esi + mov eax, 0 ; mov eax, [dst_x] .bilinear.bpp24.pixel: - mov esi, [src_base] + mov esi, [src_base] - imul eax, [crop_width_pixels_m1] - xor edx, edx - div [dst_width_pixels] - lea eax, [eax*3] - add esi, eax + imul eax, [crop_width_pixels_m1] + xor edx, edx + div [dst_width_pixels] + lea eax, [eax*3] + add esi, eax - mov [rem_x], edx - sub esi, 1 - mov [src_x], esi + mov [rem_x], edx + sub esi, 1 + mov [src_x], esi repeat 3 - mov edx, [rem_x] - add [src_x], 1 - mov esi, [src_x] + mov edx, [rem_x] + add [src_x], 1 + mov esi, [src_x] - mov al, byte[esi] - mov ah, byte[esi + 3] - add esi, [src_width_bytes] - movzx ebx, byte[esi] - movzx ecx, byte[esi + 3] - mov esi, edx - movzx edx, ah - and eax, 0x000000ff + mov al, byte[esi] + mov ah, byte[esi + 3] + add esi, [src_width_bytes] + movzx ebx, byte[esi] + movzx ecx, byte[esi + 3] + mov esi, edx + movzx edx, ah + and eax, 0x000000ff - imul edx, esi - imul ecx, esi - neg esi - add esi, [dst_width_pixels] - imul eax, esi - imul ebx, esi - add eax, edx - add ebx, ecx - mov esi, [dst_width_pixels_inv] - mul esi - mov ecx, edx - mov eax, ebx - mul esi - mov eax, edx + imul edx, esi + imul ecx, esi + neg esi + add esi, [dst_width_pixels] + imul eax, esi + imul ebx, esi + add eax, edx + add ebx, ecx + mov esi, [dst_width_pixels_inv] + mul esi + mov ecx, edx + mov eax, ebx + mul esi + mov eax, edx - mov edx, [rem_y] - imul eax, edx - neg edx - add edx, [dst_height_pixels] - imul ecx, edx - add eax, ecx - mul [dst_height_pixels_inv] - mov byte[edi], dl - add edi, 1 + mov edx, [rem_y] + imul eax, edx + neg edx + add edx, [dst_height_pixels] + imul ecx, edx + add eax, ecx + mul [dst_height_pixels_inv] + mov byte[edi], dl + add edi, 1 end repeat - add [dst_x], 1 - mov eax, [dst_x] - cmp eax, [dst_width_pixels] - jne .bilinear.bpp24.pixel + add [dst_x], 1 + mov eax, [dst_x] + cmp eax, [dst_width_pixels] + jne .bilinear.bpp24.pixel - add [dst_y], 1 - mov eax, [dst_y] - cmp eax, [dst_height_pixels] - jne .bilinear.bpp24.line + add [dst_y], 1 + mov eax, [dst_y] + cmp eax, [dst_height_pixels] + jne .bilinear.bpp24.line - mov eax, [_dst] - jmp .quit + mov eax, [_dst] + jmp .quit .bilinear.bpp32: - mov esi, [src_data] - mov [dst_y], 0 - mov eax, 0 ; mov eax, [dst_y] + mov esi, [src_data] + mov [dst_y], 0 + mov eax, 0 ; mov eax, [dst_y] .bilinear.bpp32.line: - mov esi, [src_data] - mov [dst_x], 0 - imul eax, [crop_height_pixels_m1] - xor edx, edx - div [dst_height_pixels] - mov [rem_y], edx - imul eax, [src_width_bytes] - add esi, eax - mov [src_base], esi - mov eax, 0 ; mov eax, [dst_x] + mov esi, [src_data] + mov [dst_x], 0 + imul eax, [crop_height_pixels_m1] + xor edx, edx + div [dst_height_pixels] + mov [rem_y], edx + imul eax, [src_width_bytes] + add esi, eax + mov [src_base], esi + mov eax, 0 ; mov eax, [dst_x] .bilinear.bpp32.pixel: - mov esi, [src_base] + mov esi, [src_base] - imul eax, [crop_width_pixels_m1] - xor edx, edx - div [dst_width_pixels] - shl eax, 2 - add esi, eax + imul eax, [crop_width_pixels_m1] + xor edx, edx + div [dst_width_pixels] + shl eax, 2 + add esi, eax - mov [rem_x], edx - sub esi, 1 - mov [src_x], esi + mov [rem_x], edx + sub esi, 1 + mov [src_x], esi repeat 4 - mov edx, [rem_x] - add [src_x], 1 - mov esi, [src_x] + mov edx, [rem_x] + add [src_x], 1 + mov esi, [src_x] - mov al, byte[esi] - mov ah, byte[esi + 4] - add esi, [src_width_bytes] - movzx ebx, byte[esi] - movzx ecx, byte[esi + 4] - mov esi, edx - movzx edx, ah - and eax, 0x000000ff + mov al, byte[esi] + mov ah, byte[esi + 4] + add esi, [src_width_bytes] + movzx ebx, byte[esi] + movzx ecx, byte[esi + 4] + mov esi, edx + movzx edx, ah + and eax, 0x000000ff - imul edx, esi - imul ecx, esi - neg esi - add esi, [dst_width_pixels] - imul eax, esi - imul ebx, esi - add eax, edx - add ebx, ecx - mov esi, [dst_width_pixels_inv] - mul esi - mov ecx, edx - mov eax, ebx - mul esi - mov eax, edx + imul edx, esi + imul ecx, esi + neg esi + add esi, [dst_width_pixels] + imul eax, esi + imul ebx, esi + add eax, edx + add ebx, ecx + mov esi, [dst_width_pixels_inv] + mul esi + mov ecx, edx + mov eax, ebx + mul esi + mov eax, edx - mov edx, [rem_y] - imul eax, edx - neg edx - add edx, [dst_height_pixels] - imul ecx, edx - add eax, ecx - mul [dst_height_pixels_inv] - mov byte[edi], dl - add edi, 1 + mov edx, [rem_y] + imul eax, edx + neg edx + add edx, [dst_height_pixels] + imul ecx, edx + add eax, ecx + mul [dst_height_pixels_inv] + mov byte[edi], dl + add edi, 1 end repeat - add [dst_x], 1 - mov eax, [dst_x] - cmp eax, [dst_width_pixels] - jne .bilinear.bpp32.pixel + add [dst_x], 1 + mov eax, [dst_x] + cmp eax, [dst_width_pixels] + jne .bilinear.bpp32.pixel - add [dst_y], 1 - mov eax, [dst_y] - cmp eax, [dst_height_pixels] - jne .bilinear.bpp32.line + add [dst_y], 1 + mov eax, [dst_y] + cmp eax, [dst_height_pixels] + jne .bilinear.bpp32.line - mov eax, [_dst] - jmp .quit + mov eax, [_dst] + jmp .quit .error: - xor eax, eax + xor eax, eax .quit: - ret - + pop edi esi ebx + ret endp