diff --git a/programs/develop/libraries/libs-dev/libimg/bmp/bmp.asm b/programs/develop/libraries/libs-dev/libimg/bmp/bmp.asm index 48788e74ed..0a6ee2e9e2 100644 --- a/programs/develop/libraries/libs-dev/libimg/bmp/bmp.asm +++ b/programs/develop/libraries/libs-dev/libimg/bmp/bmp.asm @@ -1,19 +1,19 @@ ;;================================================================================================;; -;;//// bmp.asm //// (c) mike.dld, 2007-2008 //////////////////////////////////////////////////////;; +;;//// bmp.asm //// (c) mike.dld, 2007-2008, (c) diamond, 2009 ///////////////////////////////////;; ;;================================================================================================;; ;; ;; ;; 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 ;; -;; General Public License as published by the Free Software Foundation, either version 3 of the ;; -;; License, or (at your option) any later version. ;; +;; 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 ;; -;; General Public License for more details. ;; +;; Lesser General Public License for more details. ;; ;; ;; -;; You should have received a copy of the GNU General Public License along with Libs-Dev. If not, ;; -;; see . ;; +;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;; +;; If not, see . ;; ;; ;; ;;================================================================================================;; ;; ;; @@ -28,7 +28,8 @@ include 'bmp.inc' ;;================================================================================================;; -proc img.is.bmp _data, _length ;//////////////////////////////////////////////////////////////////;; +;;proc img.is.bmp _data, _length ;////////////////////////////////////////////////////////////////;; +img.is.bmp: ;;------------------------------------------------------------------------------------------------;; ;? Determine if raw data could be decoded (is in BMP format) ;; ;;------------------------------------------------------------------------------------------------;; @@ -37,21 +38,23 @@ proc img.is.bmp _data, _length ;//////////////////////////////////////////////// ;;------------------------------------------------------------------------------------------------;; ;< eax = false / true ;; ;;================================================================================================;; - cmp [_length], 2 +; test 1 (length of data): data must contain FileHeader and required fields from InfoHeader + cmp dword [esp+8], sizeof.bmp.FileHeader + 12 jb .nope - mov eax, [_data] - cmp word[eax], 'BM' +; test 2: signature + mov eax, [esp+4] + cmp word [eax], 'BM' je .yep .nope: xor eax, eax - ret + ret 8 .yep: - xor eax,eax + xor eax, eax inc eax - ret -endp + ret 8 +;endp ;;================================================================================================;; proc img.decode.bmp _data, _length ;//////////////////////////////////////////////////////////////;; @@ -65,13 +68,15 @@ proc img.decode.bmp _data, _length ;//////////////////////////////////////////// ;;================================================================================================;; locals img dd ? + bTopDown db ? endl - push ebx + push ebx esi edi - stdcall img.is.bmp, [_data], [_length] - or eax, eax - jz .error +; img.is.bmp has been already called by img.decode +; stdcall img.is.bmp, [_data], [_length] +; or eax, eax +; jz .error mov ebx, [_data] ; cmp [ebx + bmp.Header.info.Compression], bmp.BI_RGB @@ -79,8 +84,60 @@ endl ; mov eax, [ebx + bmp.Header.file.Size] ; cmp eax, [_length] ; jne .error +; @@: + + mov eax, [ebx + bmp.Header.info.Size] +; sanity check: file length must be greater than size of headers + add eax, sizeof.bmp.FileHeader + cmp [_length], eax + jbe .error + + mov [bTopDown], 0 + + cmp eax, sizeof.bmp.FileHeader + 12 + jz .old1 + cmp eax, sizeof.bmp.FileHeader + 40 + jz .normal + cmp eax, sizeof.bmp.FileHeader + 56 + jnz .error +; convert images with <= 8 bpp to 8bpp, other - to 32 bpp +.normal: + xor eax, eax + inc eax ; Image.bpp8 + cmp [ebx + bmp.Header.info.BitCount], 8 + jbe @f + mov al, Image.bpp32 +@@: + push eax + mov eax, [ebx + bmp.Header.info.Height] + test eax, eax + jns @f + inc [bTopDown] + neg eax +@@: + pushd eax + pushd [ebx + bmp.Header.info.Width] + jmp .create +.old1: + xor eax, eax + inc eax ; Image.bpp8 + cmp [ebx + bmp.Header.info.OldBitCount], 8 + jbe @f + mov al, Image.bpp32 +@@: + push eax + movsx eax, [ebx + bmp.Header.info.OldHeight] + test eax, eax + jns @f + inc [bTopDown] + neg eax +@@: + push eax + movzx eax, [ebx + bmp.Header.info.OldWidth] + push eax +.create: + call img.create - @@: stdcall img.create, [ebx + bmp.Header.info.Width], [ebx + bmp.Header.info.Height] or eax, eax jz .error mov [img], eax @@ -88,52 +145,87 @@ endl invoke mem.alloc, sizeof.bmp.Image or eax, eax - jz .error + jz .error.free mov [edx + Image.Extended], eax - mov esi, ebx - add esi, sizeof.bmp.FileHeader + push eax mov edi, eax - mov ecx, sizeof.bmp.InfoHeader + mov ecx, sizeof.bmp.Image/4 + xor eax, eax + rep stosd + pop edi + lea esi, [ebx + sizeof.bmp.FileHeader] + pushd [ebx + bmp.FileHeader.OffBits] + mov ecx, [esi + bmp.InfoHeader.Size] + cmp ecx, 12 + jz .old2 rep movsb + jmp .decode +.old2: + movsd ; Size + movzx eax, word [esi] ; OldWidth -> Width + stosd + movsx eax, word [esi+2] ; OldHeight -> Height + stosd + lodsd ; skip OldWidth+OldHeight + movsd ; Planes+BitCount +.decode: - mov eax, [ebx + bmp.Header.info.Compression] + pop eax + mov esi, [_length] + sub esi, eax + jbe .error.free + + mov eax, [edx + Image.Extended] + mov eax, [eax + bmp.Image.info.Compression] cmp eax, bmp.BI_RGB jne @f stdcall ._.rgb jmp .decoded @@: cmp eax, bmp.BI_RLE8 jne @f + cmp [ebx + bmp.Header.info.BitCount], 8 + jnz .error.free stdcall ._.rle jmp .decoded @@: cmp eax, bmp.BI_RLE4 jne @f + cmp [ebx + bmp.Header.info.BitCount], 4 + jnz .error.free stdcall ._.rle jmp .decoded @@: cmp eax, bmp.BI_BITFIELDS - jne @f + jne .error.free stdcall ._.bitfields jmp .decoded - @@: cmp eax, bmp.BI_JPEG - jne @f - stdcall ._.jpeg - jmp .decoded - @@: cmp eax, bmp.BI_PNG - jne .error - stdcall ._.png +; BI_JPEG and BI_PNG constants are not valid values for BMP file, +; they are intended for WinAPI +; @@: cmp eax, bmp.BI_JPEG +; jne @f +; stdcall ._.jpeg +; jmp .decoded +; @@: cmp eax, bmp.BI_PNG +; jne .error +; stdcall ._.png .decoded: or eax, eax jz @f + .error.free: stdcall img.destroy, [img] jmp .error - - @@: stdcall img.flip, [img], FLIP_VERTICAL + + @@: + cmp [bTopDown], 0 + jnz @f + stdcall img.flip, [img], FLIP_VERTICAL + @@: mov eax, [img] + pop edi esi ebx ret .error: xor eax, eax - pop ebx + pop edi esi ebx ret endp @@ -175,7 +267,7 @@ proc img.decode.bmp._.rgb ;///////////////////////////////////////////////////// mov [ecx + bmp.Image.info.AlphaMask], 0 mov edi, [edx + Image.Data] - movzx eax, [ebx + bmp.Header.info.BitCount] + movzx eax, [ecx + bmp.Image.info.BitCount] cmp eax, 32 je .32bpp cmp eax, 24 @@ -202,13 +294,19 @@ img.decode.bmp._.rgb.32bpp: ;;------------------------------------------------------------------------------------------------;; img.decode.bmp._.rgb.24bpp: + mov eax, [edx + Image.Width] + lea eax, [eax*3 + 3] + and eax, not 3 + mov ecx, [edx + Image.Height] + imul eax, ecx + cmp esi, eax + jb img.decode.bmp._.rgb.error mov esi, ebx add esi, [ebx + bmp.Header.file.OffBits] - mov ecx, [ebx + bmp.Header.info.Height] .next_line: - push ecx - mov ecx, [ebx + bmp.Header.info.Width] + push ecx edx + mov ecx, [edx + Image.Width] xor edx, edx .next_line_pixel: @@ -220,7 +318,7 @@ img.decode.bmp._.rgb.24bpp: and edx, 0x03 add esi, edx - pop ecx + pop edx ecx dec ecx jnz .next_line @@ -238,22 +336,19 @@ img.decode.bmp._.rgb.16bpp: ;;------------------------------------------------------------------------------------------------;; img.decode.bmp._.rgb.8bpp: - mov esi, ebx - add esi, [ebx + bmp.Header.file.OffBits] - mov ecx, [ebx + bmp.Header.info.Height] + mov eax, [edx + Image.Width] + add eax, 3 + call img.decode.bmp._.rgb.prepare_palette + jc img.decode.bmp._.rgb.error .next_line: push ecx - mov ecx, [ebx + bmp.Header.info.Width] - - .next_line_dword: - lodsb - and eax, 0x000000FF - mov eax, [ebx + eax * 4 + bmp.Header.info.Palette] - stosd - dec ecx - jnz .next_line_dword - + mov ecx, [edx + Image.Width] + mov eax, ecx + neg eax + and eax, 3 + rep movsb + add esi, eax pop ecx dec ecx jnz .next_line @@ -263,13 +358,15 @@ img.decode.bmp._.rgb.8bpp: ;;------------------------------------------------------------------------------------------------;; img.decode.bmp._.rgb.4bpp: - mov esi, ebx - add esi, [ebx + bmp.Header.file.OffBits] - mov ecx, [ebx + bmp.Header.info.Height] + mov eax, [edx + Image.Width] + add eax, 7 + shr eax, 1 + call img.decode.bmp._.rgb.prepare_palette + jc img.decode.bmp._.rgb.error .next_line: - push ecx - mov ecx, [ebx + bmp.Header.info.Width] + push ecx edx + mov ecx, [edx + Image.Width] .next_line_dword: push ecx @@ -281,9 +378,8 @@ img.decode.bmp._.rgb.4bpp: .next_pixel: rol edx, 4 mov al, dl - and eax, 0x0000000F - mov eax, [ebx + eax * 4 + bmp.Header.info.Palette] - stosd + and al, 0x0000000F + stosb dec dword[esp] jz @f dec ecx @@ -293,7 +389,7 @@ img.decode.bmp._.rgb.4bpp: or ecx, ecx jnz .next_line_dword - pop ecx + pop edx ecx dec ecx jnz .next_line @@ -302,13 +398,15 @@ img.decode.bmp._.rgb.4bpp: ;;------------------------------------------------------------------------------------------------;; img.decode.bmp._.rgb.1bpp: - mov esi, ebx - add esi, [ebx + bmp.Header.file.OffBits] - mov ecx, [ebx + bmp.Header.info.Height] + mov eax, [edx + Image.Width] + add eax, 31 + shr eax, 3 + call img.decode.bmp._.rgb.prepare_palette + jc img.decode.bmp._.rgb.error .next_line: - push ecx - mov ecx, [ebx + bmp.Header.info.Width] + push ecx edx + mov ecx, [edx + Image.Width] .next_line_dword: push ecx @@ -320,9 +418,8 @@ img.decode.bmp._.rgb.1bpp: .next_pixel: rol edx, 1 mov al, dl - and eax, 0x00000001 - mov eax, [ebx + eax * 4 + bmp.Header.info.Palette] - stosd + and al, 0x00000001 + stosb dec dword[esp] jz @f dec ecx @@ -332,7 +429,7 @@ img.decode.bmp._.rgb.1bpp: or ecx, ecx jnz .next_line_dword - pop ecx + pop edx ecx dec ecx jnz .next_line @@ -347,6 +444,48 @@ img.decode.bmp._.rgb.1bpp: img.decode.bmp._.rgb.error: or eax, -1 ret + +img.decode.bmp._.rgb.prepare_palette: + and eax, not 3 + mov ecx, [edx + Image.Height] + imul eax, ecx + cmp esi, eax + jb .ret + mov esi, [ebx + bmp.Header.info.Size] + add esi, sizeof.bmp.FileHeader + jc .ret + mov eax, [ebx + bmp.Header.file.OffBits] + sub eax, esi + jc .ret + push edi + mov edi, [edx + Image.Palette] + push ecx + mov ecx, 256 + cmp esi, sizeof.bmp.FileHeader + 12 + jz .old + shr eax, 2 + add esi, ebx + cmp ecx, eax + jb @f + mov ecx, eax +@@: + rep movsd + jmp .common +.old: + movsd + dec esi + sub eax, 3 + jbe @f + sub ecx, 1 + jnz .old +@@: +.common: + pop ecx + pop edi + mov esi, ebx + add esi, [ebx + bmp.Header.file.OffBits] +.ret: + ret endp ;;================================================================================================;; @@ -365,27 +504,35 @@ locals marker_y dd ? abs_mode_addr dd ? enc_mode_addr dd ? + height dd ? endl - mov edi, [edx + Image.Data] - mov [abs_mode_addr], .absolute_mode.rle8 mov [enc_mode_addr], .encoded_mode.rle8 cmp [ebx + bmp.Header.info.Compression], bmp.BI_RLE4 jne @f mov [abs_mode_addr], .absolute_mode.rle4 mov [enc_mode_addr], .encoded_mode.rle4 + @@: + + push esi + xor eax, eax ; do not check file size in .prepare_palette + call img.decode.bmp._.rgb.prepare_palette + pop ecx ; ecx = rest bytes in file + jc .error - @@: mov esi, ebx - add esi, [ebx + bmp.Header.file.OffBits] mov eax, [edx + Image.Width] - shl eax, 2 mov [scanline_len], eax + mov eax, [edx + Image.Height] + mov [height], eax xor eax, eax mov [marker_x], eax mov [marker_y], eax + mov edi, [edx + Image.Data] .next_run: + sub ecx, 1 + jc .eof xor eax, eax lodsb or al, al @@ -393,6 +540,8 @@ endl jmp [enc_mode_addr] .escape_mode: + sub ecx, 1 + jc .eof lodsb cmp al, 0 je .end_of_scanline @@ -403,29 +552,30 @@ endl jmp [abs_mode_addr] .end_of_scanline: ; 0 - mov eax, [marker_x] - shl eax, 2 - neg eax - add eax, [scanline_len] - add edi, eax + sub edi, [marker_x] + add edi, [scanline_len] mov [marker_x], 0 - inc [marker_y] - jmp .next_run + mov eax, [marker_y] + inc eax + mov [marker_y], eax + cmp eax, [height] + jb .next_run + jmp .exit .offset_marker: ; 2: dx, dy + sub ecx, 2 + jc .eof lodsb mov edx, [marker_x] add edx, eax - cmp edx, [ebx + bmp.Header.info.Width] + cmp edx, [scanline_len] jae .exit mov [marker_x], edx - shl eax, 2 add edi, eax lodsb - and eax, 0x0FF mov edx, [marker_y] add edx, eax - cmp edx, [ebx + bmp.Header.info.Height] + cmp edx, [height] jae .exit mov [marker_y], edx imul eax, [scanline_len] @@ -433,90 +583,112 @@ endl jmp .next_run .encoded_mode.rle8: ; N: b1 * N - mov edx, eax + call .fix_marker + sub ecx, 1 + jc .eof lodsb - mov eax, [ebx + eax * 4 + bmp.Header.info.Palette] - @@: dec edx - js .fix_marker - stosd - inc [marker_x] - jmp @b + push ecx + mov ecx, edx + rep stosb + pop ecx + jmp .check_eoi .absolute_mode.rle8: ; N: b1 .. bN - mov edx, eax - push eax - @@: dec edx - js @f - lodsb - and eax, 0x0FF - mov eax, [ebx + eax * 4 + bmp.Header.info.Palette] - stosd - inc [marker_x] - jmp @b - @@: pop eax - test eax, 1 - jz .fix_marker + call .fix_marker + cmp ecx, edx + jae @f + mov edx, ecx + @@: + push ecx + mov ecx, edx + rep movsb + pop ecx + sub ecx, edx + jz .eof + test edx, 1 + jz .check_eoi + sub ecx, 1 + jc .eof inc esi - jmp .fix_marker + .check_eoi: + mov eax, [marker_y] + cmp eax, [height] + jb .next_run + jmp .exit .encoded_mode.rle4: ; N: b1 * N - mov edx, eax - lodsb + call .fix_marker + sub ecx, 1 + jc .eof + movzx eax, byte [esi] + inc esi + push ecx mov ecx, eax + and eax, 0xF shr ecx, 4 - mov ecx, [ebx + ecx * 4 + bmp.Header.info.Palette] - and eax, 0x00F - mov eax, [ebx + eax * 4 + bmp.Header.info.Palette] - @@: dec edx - js .fix_marker - test edx, 1 - jz .odd - mov [edi], ecx - add edi, 4 - inc [marker_x] - jmp @b - .odd: - stosd - inc [marker_x] - jmp @b - - .absolute_mode.rle4: ; N: b1 .. bN - mov edx, eax - push eax - @@: dec edx - js @f - lodsb - and eax, 0x0FF - mov ecx, eax - shr eax, 4 - mov eax, [ebx + eax * 4 + bmp.Header.info.Palette] - stosd - inc [marker_x] + @@: dec edx js @f - mov eax, ecx - and eax, 0x00F - mov eax, [ebx + eax * 4 + bmp.Header.info.Palette] - stosd - inc [marker_x] + mov [edi], cl + dec edx + js @f + mov [edi+1], al + add edi, 2 jmp @b - @@: pop eax + @@: + pop ecx + jmp .check_eoi + + .absolute_mode.rle4: ; N: b1 .. bN + call .fix_marker + lea eax, [edx+1] + shr eax, 1 + cmp ecx, eax + jbe @f + lea edx, [ecx*2] + @@: + push ecx edx + @@: dec edx + js @f + lodsb + mov cl, al + shr al, 4 + and cl, 0xF + stosb + dec edx + js @f + mov [edi], cl + inc edi + jmp @b + @@: pop eax ecx and eax, 0x03 - jz .fix_marker - cmp eax, 3 - je .fix_marker + jp .check_eoi + sub ecx, 1 + jc .eof inc esi - jmp .fix_marker + jmp .check_eoi .fix_marker: - mov eax, [marker_x] - @@: sub eax, [ebx + bmp.Header.info.Width] - jle .next_run + mov edx, eax + add eax, [marker_x] mov [marker_x], eax - inc [marker_y] - jmp @b + @@: + sub eax, [scanline_len] + jle @f + mov [marker_x], eax + push eax + mov eax, [marker_y] + inc eax + mov [marker_y], eax + cmp eax, [height] + pop eax + jb @b + sub edx, eax + @@: + retn .exit: + .eof: xor eax, eax ret @@ -542,8 +714,23 @@ locals delta dd ? endl - push esi edi - mov esi, [edx + Image.Extended] + push edi + + mov [delta], 4 + mov eax, [edx + Image.Extended] + cmp [eax + bmp.Image.info.BitCount], 32 + je @f + cmp [eax + bmp.Image.info.BitCount], 16 + jne .error + mov [delta], 2 + @@: + mov ecx, [edx + Image.Width] + imul ecx, [edx + Image.Height] + imul ecx, [delta] + cmp esi, ecx + jb .error + + mov esi, eax mov ecx, [esi + bmp.Image.info.RedMask] call .calc_shift @@ -577,17 +764,9 @@ endl mov esi, ebx add esi, [ebx + bmp.Header.file.OffBits] - mov [delta], 4 - movzx eax, [ebx + bmp.Header.info.BitCount] - cmp eax, 32 - je @f - cmp eax, 16 - jne .error - mov [delta], 2 - ;;------------------------------------------------------------------------------------------------;; - @@: mov ecx, [edx + Image.Height] + mov ecx, [edx + Image.Height] .next_line: push ecx @@ -642,12 +821,12 @@ endl .exit: xor eax, eax - pop edi esi + pop edi ret .error: or eax, -1 - pop edi esi + pop edi ret .calc_shift: @@ -678,6 +857,7 @@ endl retn endp +if 0 ;;================================================================================================;; proc img.decode.bmp._.jpeg ;//////////////////////////////////////////////////////////////////////;; ;;------------------------------------------------------------------------------------------------;; @@ -705,7 +885,7 @@ proc img.decode.bmp._.png ;///////////////////////////////////////////////////// xor eax, eax ret endp - +end if ;;================================================================================================;; ;;////////////////////////////////////////////////////////////////////////////////////////////////;; diff --git a/programs/develop/libraries/libs-dev/libimg/bmp/bmp.inc b/programs/develop/libraries/libs-dev/libimg/bmp/bmp.inc index ea31d6c6f4..8776208c9f 100644 --- a/programs/develop/libraries/libs-dev/libimg/bmp/bmp.inc +++ b/programs/develop/libraries/libs-dev/libimg/bmp/bmp.inc @@ -1,19 +1,19 @@ ;;================================================================================================;; -;;//// bmp.inc //// (c) mike.dld, 2007-2008 //////////////////////////////////////////////////////;; +;;//// bmp.inc //// (c) mike.dld, 2007-2008, (c) diamond, 2009 ///////////////////////////////////;; ;;================================================================================================;; ;; ;; ;; 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 ;; -;; General Public License as published by the Free Software Foundation, either version 3 of the ;; -;; License, or (at your option) any later version. ;; +;; 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 ;; -;; General Public License for more details. ;; +;; Lesser General Public License for more details. ;; ;; ;; -;; You should have received a copy of the GNU General Public License along with Libs-Dev. If not, ;; -;; see . ;; +;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;; +;; If not, see . ;; ;; ;; ;;================================================================================================;; @@ -28,10 +28,20 @@ ends struct bmp.InfoHeader ; v2 (Windows 2.x) Size dd ? ; Size of this header in bytes - Width dd ? ; Image width in pixels - Height dd ? ; Image height in pixels - Planes dw ? ; Number of color planes - BitCount dw ? ; Number of bits per pixel + union + struct ; new format + Width dd ? ; Image width in pixels + Height dd ? ; Image height in pixels + Planes dw ? ; Number of color planes + BitCount dw ? ; Number of bits per pixel + ends + struct ; old format + OldWidth dw ? ; Image width in pixels as word + OldHeight dw ? ; Image height in pixels as word + OldPlanes dw ? ; Number of color planes + OldBitCount dw ? ; Number of bits per pixel + ends + ends ; v3 (Windows 3.x) Compression dd ? ; Compression method used SizeImage dd ? ; Size of bitmap in bytes diff --git a/programs/develop/libraries/libs-dev/libimg/bmp/ico.asm b/programs/develop/libraries/libs-dev/libimg/bmp/ico.asm index cefc8f19ac..332d266310 100644 --- a/programs/develop/libraries/libs-dev/libimg/bmp/ico.asm +++ b/programs/develop/libraries/libs-dev/libimg/bmp/ico.asm @@ -5,15 +5,15 @@ ;; 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 ;; -;; General Public License as published by the Free Software Foundation, either version 3 of the ;; -;; License, or (at your option) any later version. ;; +;; 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 ;; -;; General Public License for more details. ;; +;; Lesser General Public License for more details. ;; ;; ;; -;; You should have received a copy of the GNU General Public License along with Libs-Dev. If not, ;; -;; see . ;; +;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;; +;; If not, see . ;; ;; ;; ;;================================================================================================;; ;; ;; diff --git a/programs/develop/libraries/libs-dev/libimg/gif/gif.asm b/programs/develop/libraries/libs-dev/libimg/gif/gif.asm index 41c231b987..845379764a 100644 --- a/programs/develop/libraries/libs-dev/libimg/gif/gif.asm +++ b/programs/develop/libraries/libs-dev/libimg/gif/gif.asm @@ -7,15 +7,15 @@ ;; 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 ;; -;; General Public License as published by the Free Software Foundation, either version 3 of the ;; -;; License, or (at your option) any later version. ;; +;; 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 ;; -;; General Public License for more details. ;; +;; Lesser General Public License for more details. ;; ;; ;; -;; You should have received a copy of the GNU General Public License along with Libs-Dev. If not, ;; -;; see . ;; +;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;; +;; If not, see . ;; ;; ;; ;;================================================================================================;; ;; ;; @@ -84,20 +84,18 @@ proc img.decode.gif _data, _length ;//////////////////////////////////////////// locals img dd ? global_color_table dd ? + global_color_table_size dd ? endl push ebx - stdcall img.is.gif, [_data], [_length] - or eax, eax - jz .error +; img.is.gif is called by caller (img.decode) +; stdcall img.is.gif, [_data], [_length] +; or eax, eax +; jz .error + mov [global_color_table_size], 0 mov ebx, [_data] -; cmp [ebx + bmp.Header.info.Compression], bmp.BI_RGB -; je @f -; mov eax, [ebx + bmp.Header.file.Size] -; cmp eax, [_length] -; jne .error test [ebx + gif.Header.lsd.Packed], gif.LSD.Packed.GlobalColorTableFlag jz @f @@ -106,9 +104,9 @@ endl mov cl, [ebx + gif.Header.lsd.Packed] and cl, gif.LSD.Packed.SizeOfGlobalColorTableMask shr cl, gif.LSD.Packed.SizeOfGlobalColorTableShift - inc cl - mov eax, 1 + mov eax, 2 shl eax, cl + mov [global_color_table_size], eax lea eax, [eax * 3] add ebx, eax @@: add ebx, sizeof.gif.Header @@ -130,11 +128,15 @@ endl jz .error mov edx, [img] mov [eax + Image.Previous], edx + test edx, edx + jz @f + mov [edx + Image.Next], eax +@@: mov [img], eax mov edx, eax + mov [eax + Image.Type], Image.bpp8 - mov ecx, sizeof.gif.Image - invoke mem.alloc, ecx + invoke mem.alloc, sizeof.gif.Image or eax, eax jz .error mov [edx + Image.Extended], eax @@ -149,33 +151,34 @@ endl or eax, eax jz .error - xor ecx, ecx - mov eax, [edx + Image.Extended] + mov esi, ebx + mov edi, [edx + Image.Extended] + mov ecx, sizeof.gif.ImageDescriptor + rep movsb + + mov edi, [edx + Image.Palette] + mov esi, [global_color_table] + mov ecx, [global_color_table_size] test [ebx + gif.ImageDescriptor.Packed], gif.ID.Packed.LocalColorTableFlag jz @f + lea esi, [ebx + sizeof.gif.ImageDescriptor] mov cl, [ebx + gif.ImageDescriptor.Packed] and cl, gif.ID.Packed.SizeOfLocalColorTableMask shr cl, gif.ID.Packed.SizeOfLocalColorTableShift - inc cl - mov eax, 1 + mov eax, 2 shl eax, cl - lea ecx, [eax * sizeof.gif.RgbTriplet] - lea eax, [ecx + sizeof.gif.Image] - invoke mem.realloc, [edx + Image.Extended], eax - or eax, eax - jz .error - mov [edx + Image.Extended], eax - @@: mov esi, ebx - lea edi, [eax + sizeof.gif.GraphicsControlExtension] - add ecx, sizeof.gif.ImageDescriptor - rep movsb - - mov eax, [global_color_table] - test [ebx + gif.ImageDescriptor.Packed], gif.ID.Packed.LocalColorTableFlag - jz @f - lea eax, [ebx + sizeof.gif.ImageDescriptor] - @@: mov ebx, esi - stdcall ._.process_image, eax + mov ecx, eax + lea eax, [eax*3] + add ebx, eax +@@: + lodsd + dec esi + bswap eax + shr eax, 8 + stosd + loop @b + add ebx, sizeof.gif.ImageDescriptor + stdcall ._.process_image .decoded: or eax, eax @@ -187,6 +190,11 @@ endl ret .error: + mov eax, [img] + test eax, eax + jz @f + stdcall img.destroy, eax +@@: xor eax, eax pop ebx ret @@ -309,7 +317,7 @@ proc img.decode.gif._.process_extensions ;////////////////////////////////////// endp ;;================================================================================================;; -proc img.decode.gif._.process_image _color_table ;////////////////////////////////////////////////;; +proc img.decode.gif._.process_image ;/////////////////////////////////////////////////////////////;; ;;------------------------------------------------------------------------------------------------;; ;? --- TBD --- ;; ;;------------------------------------------------------------------------------------------------;; @@ -342,8 +350,6 @@ endl mov [width], ecx mov eax, [edx + Image.Height] imul eax, ecx -; lea eax, [eax * 3] - shl eax, 2 mov [img_end], eax inc eax mov [row_end], eax @@ -351,8 +357,6 @@ endl mov eax, [edx + Image.Extended] test [eax + gif.Image.info.Packed], gif.ID.Packed.InterleaceFlag jz @f -; lea ecx, [ecx * 3] - shl ecx, 2 mov [row_end], ecx @@: mov esi, ebx @@ -502,21 +506,11 @@ img.decode.gif._.process_image.output: .loop2: pop ax - - lea esi, [eax * 3] - add esi, [_color_table] - - mov esi, [esi] - bswap esi - shr esi, 8 - mov [edi], esi - add edi, 4 + stosb cmp edi, [row_end] jb .norowend mov eax, [width] -; lea eax, [eax * 3] - shl eax, 2 push eax sub edi, eax add eax, eax diff --git a/programs/develop/libraries/libs-dev/libimg/gif/gif.inc b/programs/develop/libraries/libs-dev/libimg/gif/gif.inc index bc3a3928fc..264233eafc 100644 --- a/programs/develop/libraries/libs-dev/libimg/gif/gif.inc +++ b/programs/develop/libraries/libs-dev/libimg/gif/gif.inc @@ -5,15 +5,15 @@ ;; 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 ;; -;; General Public License as published by the Free Software Foundation, either version 3 of the ;; -;; License, or (at your option) any later version. ;; +;; 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 ;; -;; General Public License for more details. ;; +;; Lesser General Public License for more details. ;; ;; ;; -;; You should have received a copy of the GNU General Public License along with Libs-Dev. If not, ;; -;; see . ;; +;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;; +;; If not, see . ;; ;; ;; ;;================================================================================================;; diff --git a/programs/develop/libraries/libs-dev/libimg/jpeg/jpeg.asm b/programs/develop/libraries/libs-dev/libimg/jpeg/jpeg.asm new file mode 100644 index 0000000000..fe9d6a4b9d --- /dev/null +++ b/programs/develop/libraries/libs-dev/libimg/jpeg/jpeg.asm @@ -0,0 +1,2231 @@ +;;================================================================================================;; +;;//// jpeg.asm //// (c) diamond, 2008-2009 //////////////////////////////////////////////////////;; +;;================================================================================================;; +;; ;; +;; 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 . ;; +;; ;; +;;================================================================================================;; + +include 'jpeg.inc' + +img.is.jpg: + push esi ebp + mov esi, [esp+12] ; esi -> JPEG data + mov ebp, [esp+16] ; ebp = data size + call get_marker + jc .no + cmp al, 0xD8 ; SOI marker? + push 1 + pop eax + jz .ok +.no: + xor eax, eax +.ok: + pop ebp esi + ret 8 + +img.decode.jpg: + finit + pushad + mov esi, [esp+20h+4] ; esi -> JPEG data + mov ebp, [esp+20h+8] ; ebp = data size +@@: +; allocate area for JPEG processing + push sizeof.jpeg.work + call [mem.alloc] + test eax, eax + jz .ret + mov ebx, eax + xor ecx, ecx + mov [ebx + jpeg.work.image], ecx + mov [ebx + jpeg.work.dct_buffer], ecx + mov [ebx + jpeg.work._esp], esp +; check for SOI [Start-Of-Image] marker + call get_marker + jc .end + cmp al, 0xD8 ; SOI? + jz .soi_ok +.end: +; general exit from the function +; for progressive mode: convert loaded DCT coefficients to image + call handle_progressive +; convert full-color images to RGB + call convert_to_rgb + push [ebx + jpeg.work.image] + push ebx + call [mem.free] + pop eax +.ret: + mov [esp+28], eax + popad + ret 8 +.soi_ok: + mov [ebx + jpeg.work.restart_interval], ecx + mov [ebx + jpeg.work.adobe_ycck], cl +; loop until start of frame (real data), parse markers +.markers_loop: + call get_marker + jc .end +; markers RSTn do not have parameters +; N.B. They can not exist in this part of JPEG, but let's be liberal :) + cmp al, 0xD0 + jb @f + cmp al, 0xD8 + jb .markers_loop +@@: + cmp al, 0xD9 ; EOI? [invalid here] + jz .end +; ok, this is marker segment +; first word is length of the segment + cmp ebp, 2 + jb .end + xor edx, edx + mov dl, [esi+1] + mov dh, [esi] ; edx = marker length, al = marker value + sub ebp, edx + jb .end + cmp al, 0xDB ; DQT? + jz .dqt + cmp al, 0xC4 ; DHT? + jz .dht + cmp al, 0xCC ; DAC? [ignored - no arithmetic coding] + jz .next_marker + cmp al, 0xDD ; DRI? + jz .dri + cmp al, 0xDA ; SOS? + jz .sos + cmp al, 0xC0 + jb @f + cmp al, 0xD0 + jb .sofn +@@: + cmp al, 0xEE ; APP14? + jz .app14 +; unrecognized marker; let's skip it and hope for the best +.next_marker: + add esi, edx + jmp .markers_loop +.app14: +; check for special Adobe marker + cmp dx, 14 + jb .next_marker + cmp byte [esi+2], 'A' + jnz .next_marker + cmp dword [esi+3], 'dobe' + jnz .next_marker + cmp byte [esi+13], 2 + setz [ebx + jpeg.work.adobe_ycck] + jmp .next_marker +.dqt: +; DQT marker found +; length: 2 bytes for length field + 65 bytes per table + sub edx, 2 + jc .end + lodsw +.dqt_loop: + test edx, edx + jz .markers_loop + sub edx, 1+64 + jc .end + lodsb +; 8-bit DCT-based process shall not use a 16-bit precision quantization table. + test al, 0xF0 + jnz .end + and eax, 3 + mov [ebx+jpeg.work.quant_tables_defined+eax], 1 + shl eax, 8 + lea edi, [ebx+eax+jpeg.work.quant_tables] + xor ecx, ecx +@@: + xor eax, eax + lodsb + push eax + fild dword [esp] + pop eax + movzx eax, byte [zigzag+ecx] + add eax, eax + push eax + and eax, 7*4 + fmul dword [idct_pre_table+eax] + pop eax + push eax + shr eax, 3 + and eax, 7*4 + fmul dword [idct_pre_table+eax] + pop eax + fstp dword [edi+eax] + inc ecx + cmp ecx, 64 + jb @b + jmp .dqt_loop +.dri: +; DRI marker found + cmp edx, 4 ; length must be 4 + jnz .end2 + movzx eax, word [esi+2] + xchg al, ah + mov [ebx+jpeg.work.restart_interval], eax + jmp .next_marker +.dht: +; DHT marker found + sub edx, 2 + jc .end2 + lodsw +.dht_loop: + test edx, edx + jz .markers_loop + sub edx, 17 + jc .end2 +; next Huffman table; find place for it + lodsb + mov edi, eax + and eax, 0x10 + and edi, 3 + shr eax, 2 + or edi, eax + mov [ebx+jpeg.work.dc_huffman_defined+edi], 1 +; shl edi, 11 + imul edi, max_hufftable_size + lea edi, [ebx+edi+jpeg.work.dc_huffman] ; edi -> destination table +; get table size + xor eax, eax + push 16 + pop ecx +@@: + add al, [esi] + adc ah, 0 + inc esi + loop @b + cmp ax, 0x100 + ja .end2 + sub edx, eax + jc .end2 +; construct Huffman tree + push ebx edx + ; lea eax, [edi+256*8] + ; push eax + ; push 16 + ; mov edx, esi +; @@: + ; cmp byte [edx-1], 0 + ; jnz @f + ; dec edx + ; dec dword [esp] + ; jmp @b +; @@: + ; sub edx, [esp] + ; lea eax, [edi+8] + ; push 2 + ; pop ecx +; .lenloop: + ; mov bl, byte [edx] + ; test bl, bl + ; jz .len1done + ; push eax + ; xor eax, eax +; .len1loop: + ; dec ecx + ; js .dhterr + ; cmp edi, [esp+8] + ; jae .dhterr + ; lodsb + ; stosd + ; dec bl + ; jnz .len1loop + ; pop eax +; .len1done: + ; jecxz .len2done + ; push ecx +; .len2loop: + ; cmp eax, [esp+8] + ; jb @f + ; or eax, -1 +; @@: + ; cmp edi, [esp+8] + ; jae .dhterr + ; stosd + ; add eax, 8 + ; jnb @f + ; or eax, -1 +; @@: + ; loop .len2loop + ; pop ecx +; .len2done: + ; add ecx, ecx + ; inc edx + ; dec dword [esp] + ; jnz .lenloop + ; pop eax + ; pop eax + ; sub eax, edi + ; shr eax, 2 + ; cmp eax, ecx + ; ja @f + ; mov ecx, eax +; @@: + ; or eax, -1 + ; rep stosd + ; pop edx ebx + ; jmp .dht_loop +; .dhterr: + ; ;pop eax eax eax edx ebx + ; add esp, 5*4 + lea eax, [edi+256*2] + push eax + lea edx, [esi-16] + mov ah, 1 + mov ecx, 128 +.dht_l1: + movzx ebx, byte [edx] + inc edx + test ebx, ebx + jz .dht_l3 +.dht_l2: + cmp edi, [esp] + jae .dhterr1 + lodsb + xchg al, ah + push ecx + rep stosw + pop ecx + xchg al, ah + dec ebx + jnz .dht_l2 +.dht_l3: + inc ah + shr ecx, 1 + jnz .dht_l1 + push edi + mov edi, [esp+4] + push edi + mov eax, 0x00090100 + mov cl, 8 +.dht_l4: + movzx ebx, byte [edx] + inc edx + test ebx, ebx + jz .dht_l6 +.dht_l5: + cmp edi, [esp] + jb @f + mov edi, [esp+4] + rol eax, 16 + cmp edi, [esp+8] + jae .dhterr2 + stosw + inc ah + mov [esp+4], edi + pop edi + push edi + rol eax, 16 + add dword [esp], 16*2 +@@: + lodsb + xchg al, ah + push ecx + rep stosw + pop ecx + xchg al, ah + dec ebx + jnz .dht_l5 +.dht_l6: + inc ah + shr ecx, 1 + jnz .dht_l4 + push edi + movzx ebx, byte [edx] + add ebx, ebx + add bl, [edx+1] + adc bh, 0 + add ebx, ebx + add bl, [edx+2] + adc bh, 0 + add ebx, ebx + add bl, [edx+3] + adc bh, 0 + add ebx, 15 + shr ebx, 4 + mov cl, 8 + lea ebx, [edi+ebx*2] + sub ebx, [esp+12] + add ebx, 31 + shr ebx, 5 + mov edi, ebx + shl edi, 5 + add edi, [esp+12] + xor ebx, 9 + shl ebx, 16 + xor eax, ebx + push edi +.dht_l7: + movzx ebx, byte [edx] + inc edx + test ebx, ebx + jz .dht_l10 +.dht_l8: + cmp edi, [esp] + jb .dht_l9 + mov edi, [esp+4] + cmp edi, [esp+8] + jb @f + mov edi, [esp+12] + cmp edi, [esp+16] + jae .dhterr3 + mov al, 9 + stosb + rol eax, 8 + stosb + inc eax + ror eax, 8 + mov [esp+12], edi + mov edi, [esp+8] + add dword [esp+8], 16*2 +@@: + mov al, 9 + stosb + rol eax, 16 + stosb + inc eax + ror eax, 16 + mov [esp+4], edi + pop edi + push edi + add dword [esp], 16*2 +.dht_l9: + lodsb + xchg al, ah + push ecx + rep stosw + pop ecx + xchg al, ah + dec ebx + jnz .dht_l8 +.dht_l10: + inc ah + shr ecx, 1 + jnz .dht_l7 + push -1 + pop eax + pop ecx + sub ecx, edi + rep stosb + pop edi + pop ecx + sub ecx, edi + rep stosb + pop edi + pop ecx + sub ecx, edi + rep stosb + pop edx ebx + jmp .dht_loop +.dhterr3: + pop eax eax +.dhterr2: + pop eax eax +.dhterr1: + pop eax + pop edx ebx +.end2: + jmp .end +.sofn: +; SOFn marker found + cmp [ebx+jpeg.work.image], 0 + jnz .end2 ; only one frame is allowed +; only SOF0 [baseline sequential], SOF1 [extended sequential], SOF2 [progressive] +; nobody supports other compression methods + cmp al, 0xC2 + ja .end2 + setz [ebx+jpeg.work.progressive] +; Length must be at least 8 + sub edx, 8 + jb .end2 +; Sample precision in JFIF must be 8 bits + cmp byte [esi+2], 8 + jnz .end2 +; Color space in JFIF is either YCbCr (color images, 3 components) +; or Y (grey images, 1 component) + movzx eax, byte [esi+7] + cmp al, 1 + jz @f + cmp al, 3 + jz @f +; Adobe products sometimes use YCCK color space with 4 components + cmp al, 4 + jnz .end2 + cmp [ebx+jpeg.work.adobe_ycck], 0 + jz .end2 +@@: + mov edi, eax ; edi = number of components + lea eax, [eax*3] + sub edx, eax + jnz .end2 +; image type: 8 bpp for grayscale JPEGs, 24 bpp for normal, +; 32 bpp for Adobe YCCK + push Image.bpp8 + pop eax + cmp edi, 1 + jz @f + inc eax ; Image.bpp24 = 2 + cmp edi, 3 + jz @f + inc eax ; Image.bpp32 = 3 +@@: + push eax +; get width and height +; width must be nonzero +; height must be nonzero - nobody supports DNL markers + mov ah, [esi+3] + mov al, [esi+4] ; eax = height + xor ecx, ecx + mov ch, [esi+5] + mov cl, [esi+6] ; ecx = width +; allocate memory for image + stdcall img.create, ecx, eax + test eax, eax + jz .end2 + mov [ebx + jpeg.work.image], eax +; create grayscale palette if needed + cmp edi, 1 + jnz .no_create_palette + push ecx edi + mov edi, [eax + Image.Palette] + xor eax, eax + mov ecx, 256 +@@: + stosd + add eax, 0x010101 + loop @b + pop edi ecx +.no_create_palette: +; other image characteristics + mov eax, edi + shl eax, 3 + mov [ebx + jpeg.work.delta_x], eax + mov [ebx + jpeg.work.pixel_size], edi + ;mov eax, edi + imul eax, ecx + mov [ebx + jpeg.work.delta_y], eax + shr eax, 3 + mov [ebx + jpeg.work.line_size], eax + add esi, 8 + mov ecx, edi + lea edi, [ebx + jpeg.work.components] + xor eax, eax + xor edx, edx +.sof_parse_comp: + movsb ; db ComponentIdentifier + lodsb + mov ah, al + and al, 0xF + jz .end3 + shr ah, 4 + jz .end3 + stosd ; db V, db H, db ?, db ? (will be filled later) + cmp dl, al + ja @f + mov dl, al +@@: + cmp dh, ah + ja @f + mov dh, ah +@@: + movsb ; db QuantizationTableID + loop .sof_parse_comp + mov word [ebx + jpeg.work.max_v], dx + movzx eax, dh + movzx edx, dl + push eax edx + shl eax, 3 + shl edx, 3 + mov [ebx + jpeg.work.block_width], eax + mov [ebx + jpeg.work.block_height], edx + pop edx eax + push eax edx + imul eax, [ebx + jpeg.work.delta_x] + mov [ebx + jpeg.work.block_delta_x], eax + imul edx, [ebx + jpeg.work.delta_y] + mov [ebx + jpeg.work.block_delta_y], edx + mov ecx, [ebx + jpeg.work.image] + mov eax, [ecx + Image.Width] + add eax, [ebx + jpeg.work.block_width] + dec eax + xor edx, edx + div [ebx + jpeg.work.block_width] + mov [ebx + jpeg.work.x_num_blocks], eax + mov eax, [ecx + Image.Height] + add eax, [ebx + jpeg.work.block_height] + dec eax + xor edx, edx + div [ebx + jpeg.work.block_height] + mov [ebx + jpeg.work.y_num_blocks], eax + mov ecx, [ebx + jpeg.work.pixel_size] + pop edx + lea edi, [ebx + jpeg.work.components] +@@: + mov eax, edx + div byte [edi+1] ; VMax / V_i = VFactor_i + mov byte [edi+3], al ; db VFactor + pop eax + push eax + div byte [edi+2] ; HMax / H_i = HFactor_i + mov byte [edi+4], al ; db HFactor + add edi, 6 + loop @b + pop eax + cmp [ebx + jpeg.work.progressive], 0 + jz .sof_noprogressive + mov eax, [ebx + jpeg.work.x_num_blocks] + mul [ebx + jpeg.work.block_width] + mul [ebx + jpeg.work.y_num_blocks] + mul [ebx + jpeg.work.block_height] + add eax, eax + mov [ebx + jpeg.work.dct_buffer_size], eax + mul [ebx + jpeg.work.pixel_size] + push eax + call [mem.alloc] + test eax, eax + jnz @f + xchg eax, [ebx + jpeg.work.image] + push eax + call img.destroy + jmp .end +@@: + mov [ebx + jpeg.work.dct_buffer], eax +.sof_noprogressive: + jmp .markers_loop +.end3: + jmp .end +.sos: +; SOS marker found +; frame must be already opened + cmp [ebx + jpeg.work.image], 0 + jz .end3 + cmp edx, 6 + jb .end3 +; parse marker + movzx eax, byte [esi+2] ; number of components in this scan + test eax, eax + jz .end3 ; must be nonzero + cmp al, byte [ebx + jpeg.work.pixel_size] + ja .end3 ; must be <= total number of components +; mov [ns], eax + cmp al, 1 + setz [ebx + jpeg.work.not_interleaved] + lea ecx, [6+eax+eax] + cmp edx, ecx + jnz .end3 + mov ecx, eax + lea edi, [ebx + jpeg.work.cur_components] + add esi, 3 +.sos_find_comp: + lodsb ; got ComponentID, look for component info + push ecx esi + mov ecx, [ebx + jpeg.work.pixel_size] + lea esi, [ebx + jpeg.work.components] + and dword [edi+48], 0 + and dword [edi+52], 0 +@@: + cmp [esi], al + jz @f + inc dword [edi+52] + add esi, 6 + loop @b +@@: + mov eax, [esi+1] + mov dl, [esi+5] + pop esi ecx + jnz .end3 ; bad ComponentID + cmp [ebx + jpeg.work.not_interleaved], 0 + jz @f + mov ax, 0x0101 +@@: + stosd ; db V, db H, db VFactor, db HFactor + push ecx + xor eax, eax + mov al, byte [edi-1] ; get HFactor + mul byte [ebx+jpeg.work.pixel_size] ; number of components + stosd ; HIncrement_i = HFactor_i * sizeof(pixel) + mov al, byte [edi-4-2] ; get VFactor + mul byte [ebx+jpeg.work.pixel_size] ; number of components + mov ecx, [ebx+jpeg.work.image] + imul eax, [ecx+Image.Width] ; image width + stosd ; VIncrement_i = VFactor_i * sizeof(row) + xchg eax, edx + and eax, 3 + cmp [ebx+jpeg.work.quant_tables_defined+eax], 0 + jz .end3 + shl eax, 8 + lea eax, [ebx+eax+jpeg.work.quant_tables] + stosd ; dd QuantizationTable + lodsb + movzx eax, al + mov edx, eax + shr eax, 4 + and edx, 3 + and eax, 3 + cmp [ebx+jpeg.work.dc_huffman_defined+eax], 0 + jnz .dc_table_ok + cmp [ebx+jpeg.work.progressive], 0 + jz .end3 + xor eax, eax + jmp .dc_table_done +.dc_table_ok: +; shl eax, 11 + imul eax, max_hufftable_size + lea eax, [ebx+jpeg.work.dc_huffman+eax] +.dc_table_done: + cmp [ebx+jpeg.work.ac_huffman_defined+edx], 0 + jnz .ac_table_ok + cmp [ebx+jpeg.work.progressive], 0 + jz .end3 + xor edx, edx + jmp .ac_table_done +.ac_table_ok: +; shl edx, 11 + imul edx, max_hufftable_size + lea edx, [ebx+jpeg.work.ac_huffman+edx] +.ac_table_done: + stosd ; dd DCTable + xchg eax, edx + stosd ; dd ACTable + mov eax, [ecx+Image.Width] + movzx ecx, byte [edi-21] ; get HFactor + cdq ; edx:eax = width (width<0x10000, so as dword it is unsigned) + div ecx + stosd ; dd width / HFactor_i + stosd + xchg eax, ecx + inc eax + sub eax, edx + stosd ; dd HFactor_i+1 - (width % HFactor_i) + mov ecx, [ebx+jpeg.work.image] + mov eax, [ecx+Image.Height] + movzx ecx, byte [edi-34] ; get VFactor + cdq + div ecx + stosd ; dd height / VFactor_i + stosd + xchg eax, ecx + inc eax + sub eax, edx + stosd ; dd VFactor_i+1 - (height % VFactor_i) + pop ecx + scasd ; dd DCPrediction + cmp dword [edi], 0 + setnp al + ror al, 1 + mov byte [edi-1], al + scasd ; dd ComponentOffset + dec ecx + jnz .sos_find_comp + mov [ebx+jpeg.work.cur_components_end], edi + lea edi, [ebx+jpeg.work.ScanStart] + movsb + cmp byte [esi], 63 + ja .end3 + movsb + lodsb + push eax + and al, 0xF + stosb + pop eax + shr al, 4 + stosb +; now unpack data + call init_limits + and [ebx+jpeg.work.decoded_MCUs], 0 + mov [ebx+jpeg.work.cur_rst_marker], 7 + and [ebx+jpeg.work.huffman_bits], 0 + cmp [ebx+jpeg.work.progressive], 0 + jz .sos_noprogressive +; progressive mode - only decode DCT coefficients +; initialize pointers to coefficients data +; zero number of EOBs for AC coefficients +; redefine HIncrement and VIncrement + lea edi, [ebx+jpeg.work.cur_components] +.coeff_init: + mov eax, [ebx+jpeg.work.dct_buffer_size] + mul dword [edi+52] + add eax, [ebx+jpeg.work.dct_buffer] + mov [edi+12], eax + and dword [edi+52], 0 + cmp [ebx+jpeg.work.ScanStart], 0 + jz .scan_dc + cmp dword [edi+20], 0 + jz .end3 + jmp @f +.scan_dc: + cmp dword [edi+16], 0 + jz .end3 +@@: + movzx eax, byte [edi+1] + shl eax, 7 + mov [edi+4], eax + mov eax, [edi+28] + mov cl, [edi+3] + cmp cl, [edi+32] + sbb eax, -7-1 + shr eax, 3 + shl eax, 7 + mov [edi+8], eax + add edi, 56 + cmp edi, [ebx+jpeg.work.cur_components_end] + jb .coeff_init +; unpack coefficients +; N.B. Speed optimization has sense here. +.coeff_decode_loop: + lea edx, [ebx+jpeg.work.cur_components] +.coeff_components_loop: + mov edi, [edx+12] + movzx ecx, byte [edx] + push dword [edx+40] + push edi +.coeff_y_loop: + push ecx + movzx eax, byte [edx+1] + push dword [edx+28] + push edi +.coeff_x_loop: + cmp dword [edx+40], 0 + jl @f + cmp dword [edx+28], 0 + jge .realdata +@@: + cmp [ebx+jpeg.work.not_interleaved], 0 + jnz .norealdata + push eax edi + lea edi, [ebx+jpeg.work.dct_coeff] + call decode_progressive_coeff + pop edi eax + jmp .norealdata +.realdata: + push eax + call decode_progressive_coeff + add edi, 64*2 + pop eax +.norealdata: + sub dword [edx+28], 8 + sub eax, 1 + jnz .coeff_x_loop + pop edi + pop dword [edx+28] + add edi, [edx+8] + pop ecx + sub dword [edx+40], 8 + sub ecx, 1 + jnz .coeff_y_loop + movzx eax, byte [edx+1] + shl eax, 3 + pop edi + add edi, [edx+4] + pop dword [edx+40] + sub [edx+28], eax + mov [edx+12], edi + add edx, 56 + cmp edx, [ebx+jpeg.work.cur_components_end] + jnz .coeff_components_loop + call next_MCU + jc .norst + sub [ebx+jpeg.work.cur_x], 1 + jnz .coeff_decode_loop + call next_line + lea edx, [ebx+jpeg.work.cur_components] +@@: + mov eax, [ebx+jpeg.work.max_x] + imul eax, [edx+4] + sub [edx+12], eax + movzx eax, byte [edx] + imul eax, [edx+8] + add [edx+12], eax + add edx, 56 + cmp edx, [ebx+jpeg.work.cur_components_end] + jnz @b + sub [ebx+jpeg.work.cur_y], 1 + jnz .coeff_decode_loop + jmp .markers_loop +.norst: +.end4: + jmp .end3 +.sos_noprogressive: +; normal mode - unpack JPEG image + mov edi, [ebx+jpeg.work.image] + mov edi, [edi+Image.Data] + mov [ebx+jpeg.work.cur_out_ptr], edi +; N.B. Speed optimization has sense here. +.decode_loop: + call decode_MCU + call next_MCU + jc .end4 + sub [ebx+jpeg.work.cur_x], 1 + jnz .decode_loop + call next_line + sub [ebx+jpeg.work.cur_y], 1 + jnz .decode_loop + jmp .markers_loop + +get_marker: +; in: esi -> data +; out: CF=0, al=marker value - ok +; CF=1 - no marker + sub ebp, 1 + jc .ret + lodsb +if 1 + cmp al, 0xFF + jae @f +; Some stupid men, which do not read specifications and manuals, +; sometimes create markers with length field two less than true +; value (in JPEG length of marker = length of data INCLUDING +; length field itself). To open such files, allow 2 bytes +; before next marker. + cmp ebp, 2 + jb .ret + lodsb + lodsb +end if + cmp al, 0xFF + jb .ret +@@: + sub ebp, 1 + jc .ret + lodsb + cmp al, 0xFF + jz @b + clc +.ret: + ret + +align 16 +decode_MCU: + lea edx, [ebx+jpeg.work.cur_components] +.components_loop: +; decode each component + push [ebx+jpeg.work.cur_out_ptr] + movzx ecx, byte [edx] + push dword [edx+40] +; we have H_i * V_i blocks of packed data, decode them +.y_loop_1: + push [ebx+jpeg.work.cur_out_ptr] + push ecx + movzx eax, byte [edx+1] + push dword [edx+28] +.x_loop_1: + push eax + call decode_data_unit + cmp dword [edx+40], 0 + jl .nocopyloop + cmp dword [edx+28], 0 + jl .nocopyloop +; now we have decoded block 8*8 in decoded_data +; H_i * V_i packed blocks 8*8 make up one block (8*HMax) * (8*VMax) +; so each pixel in packed block corresponds to HFact * VFact pixels + movzx ecx, byte [edx+2] + push esi ebp + mov edi, [ebx+jpeg.work.cur_out_ptr] + add edi, [edx+52] +.y_loop_2: + push ecx edi + cmp ecx, [edx+44] + mov ecx, [edx+40] + sbb ecx, 8-1 + sbb eax, eax + and ecx, eax + add ecx, 8 + jz .skip_x_loop_2 + movzx eax, byte [edx+3] +.x_loop_2: + push eax ecx edi + cmp eax, [edx+32] + mov eax, [edx+28] + sbb eax, 8-1 + sbb ebp, ebp + and eax, ebp + mov ebp, .copyiter_all + lea esi, [ebx+jpeg.work.decoded_data] + sub ebp, eax + sub ebp, eax + sub ebp, eax + mov eax, [edx+4] + sub eax, 1 +.copyloop: + push esi edi + jmp ebp +.copyiter_all: + movsb +repeat 7 + add edi, eax + movsb +end repeat + nop + nop + pop edi esi + add edi, [edx+8] + add esi, 8 + sub ecx, 1 + jnz .copyloop + pop edi ecx eax + add edi, [ebx+jpeg.work.pixel_size] + sub eax, 1 + jnz .x_loop_2 +.skip_x_loop_2: + pop edi ecx + add edi, [ebx+jpeg.work.line_size] + sub ecx, 1 + jnz .y_loop_2 + pop ebp esi +.nocopyloop: + mov eax, [ebx+jpeg.work.delta_x] + add [ebx+jpeg.work.cur_out_ptr], eax + pop eax + sub dword [edx+28], 8 + sub eax, 1 + jnz .x_loop_1 + pop dword [edx+28] + pop ecx + pop eax + sub dword [edx+40], 8 + add eax, [ebx+jpeg.work.delta_y] + mov [ebx+jpeg.work.cur_out_ptr], eax + sub ecx, 1 + jnz .y_loop_1 + movzx eax, byte [edx+1] + pop dword [edx+40] + shl eax, 3 + pop [ebx+jpeg.work.cur_out_ptr] + sub dword [edx+28], eax + add edx, 56 + cmp edx, [ebx+jpeg.work.cur_components_end] + jb .components_loop + mov eax, [ebx+jpeg.work.cur_block_dx] + add [ebx+jpeg.work.cur_out_ptr], eax + ret + +align 16 +next_MCU: + add [ebx+jpeg.work.decoded_MCUs], 1 + mov eax, [ebx+jpeg.work.restart_interval] + test eax, eax + jz .no_restart + cmp [ebx+jpeg.work.decoded_MCUs], eax + jb .no_restart + and [ebx+jpeg.work.decoded_MCUs], 0 + and [ebx+jpeg.work.huffman_bits], 0 + cmp [ebx+jpeg.work.cur_x], 1 + jnz @f + cmp [ebx+jpeg.work.cur_y], 1 + jz .no_restart +@@: +; restart marker must be present + sub ebp, 2 + js .error + cmp byte [esi], 0xFF + jnz .error + mov al, [ebx+jpeg.work.cur_rst_marker] + inc eax + and al, 7 + mov [ebx+jpeg.work.cur_rst_marker], al + add al, 0xD0 + cmp [esi+1], al + jnz .error + add esi, 2 +; handle restart marker - zero all DC predictions + lea edx, [ebx+jpeg.work.cur_components] +@@: + and word [edx+48], 0 + add edx, 56 + cmp edx, [ebx+jpeg.work.cur_components_end] + jb @b +.no_restart: + clc + ret +.error: + stc + ret + +next_line: + mov eax, [ebx+jpeg.work.max_x] + mov [ebx+jpeg.work.cur_x], eax + mul [ebx+jpeg.work.cur_block_dx] + sub eax, [ebx+jpeg.work.cur_block_dy] + sub [ebx+jpeg.work.cur_out_ptr], eax + lea edx, [ebx+jpeg.work.cur_components] +@@: + mov eax, [edx+24] + mov [edx+28], eax + movzx eax, byte [edx] + shl eax, 3 + sub [edx+40], eax + add edx, 56 + cmp edx, [ebx+jpeg.work.cur_components_end] + jb @b + ret + +init_limits: + push [ebx+jpeg.work.x_num_blocks] + pop [ebx+jpeg.work.max_x] + push [ebx+jpeg.work.y_num_blocks] + pop [ebx+jpeg.work.max_y] + push [ebx+jpeg.work.block_delta_x] + pop [ebx+jpeg.work.cur_block_dx] + push [ebx+jpeg.work.block_delta_y] + pop [ebx+jpeg.work.cur_block_dy] + cmp [ebx+jpeg.work.not_interleaved], 0 + jz @f + mov eax, dword [ebx+jpeg.work.cur_components+28] + movzx ecx, byte [ebx+jpeg.work.cur_components+3] + cmp cl, [ebx+jpeg.work.cur_components+32] + sbb eax, -7-1 + shr eax, 3 + mov [ebx+jpeg.work.max_x], eax + mov eax, dword [ebx+jpeg.work.cur_components+40] + movzx edx, byte [ebx+jpeg.work.cur_components+2] + cmp dl, [ebx+jpeg.work.cur_components+44] + sbb eax, -7-1 + shr eax, 3 + mov [ebx+jpeg.work.max_y], eax + imul ecx, [ebx+jpeg.work.delta_x] + mov [ebx+jpeg.work.cur_block_dx], ecx + imul edx, [ebx+jpeg.work.delta_y] + mov [ebx+jpeg.work.cur_block_dy], edx +@@: + push [ebx+jpeg.work.max_x] + pop [ebx+jpeg.work.cur_x] + push [ebx+jpeg.work.max_y] + pop [ebx+jpeg.work.cur_y] + ret + +;macro get_bit +;{ +;local .l1,.l2,.marker +; add cl, cl +; jnz .l1 +; sub ebp, 1 +; js decode_data_unit.eof +; mov cl, [esi] +; cmp cl, 0xFF +; jnz .l2 +;.marker: +; add esi, 1 +; sub ebp, 1 +; js decode_data_unit.eof +; cmp byte [esi], 0xFF +; jz .marker +; cmp byte [esi], 0 +; jnz decode_data_unit.eof +;.l2: +; sub esi, -1 +; adc cl, cl +;.l1: +;} +macro get_bit stack_depth +{ +local .l1,.l2,.marker + sub cl, 1 + jns .l1 + sub ebp, 1 + js .eof_pop#stack_depth + mov ch, [esi] + cmp ch, 0xFF + jnz .l2 +.marker: + add esi, 1 + sub ebp, 1 + js .eof_pop#stack_depth + cmp byte [esi], 0xFF + jz .marker + cmp byte [esi], 0 + jnz .eof_pop#stack_depth +.l2: + add esi, 1 + mov cl, 7 +.l1: + add ch, ch +} +macro get_bits stack_depth,stack_depth_p1,restore_edx +{ +local .l1,.l2,.l3,.marker2 + movzx eax, ch + mov dl, cl + shl eax, 24 + neg cl + push ebx + add cl, 24 +.l1: + cmp bl, dl + jbe .l2 + sub bl, dl + sub ebp, 1 + js .eof_pop#stack_depth_p1 + mov ch, [esi] + cmp ch, 0xFF + jnz .l3 +.marker2: + add esi, 1 + sub ebp, 1 + js .eof_pop#stack_depth_p1 + cmp byte [esi], 0xFF + jz .marker2 + cmp byte [esi], 0 + jnz .eof_pop#stack_depth_p1 +.l3: + movzx edx, ch + add esi, 1 + shl edx, cl + sub cl, 8 + or eax, edx + mov dl, 8 + jmp .l1 +.l2: + mov cl, bl + sub dl, bl + shl ch, cl + pop ebx + cmp eax, 80000000h + rcr eax, 1 + mov cl, 31 + sub cl, bl + sar eax, cl + mov cl, dl +if restore_edx eq true + pop edx +end if + add eax, 80000000h + adc eax, 80000000h +} +; macro get_huffman_code +; { +; local .l1 + ; xor ebx, ebx +; .l1: + ; get_bit + ; adc ebx, ebx + ; mov eax, [eax+4*ebx] + ; xor ebx, ebx + ; cmp eax, -1 + ; jz .eof_pop + ; cmp eax, 0x1000 + ; jae .l1 + ; mov ebx, eax +; } +macro get_huffman_code stack_depth,stack_depth_p1 +{ +local .l1,.l2,.l3,.l4,.l5,.l6,.nomarker1,.marker1,.nomarker2,.marker2,.nomarker3,.marker3,.done +; 1. (First level in Huffman table) Does the current Huffman code fit in 8 bits +; and have we got enough bits? + movzx ebx, ch + cmp byte [eax+ebx*2], cl + jbe .l1 +; 2a. No; load next byte + sub ebp, 1 + js .eof_pop#stack_depth + mov ch, [esi] + movzx edx, ch + cmp ch, 0xFF + jnz .nomarker1 +.marker1: + add esi, 1 + sub ebp, 1 + js .eof_pop#stack_depth + cmp byte [esi], 0xFF + jz .marker1 + cmp byte [esi], 0 + jnz .eof_pop#stack_depth +.nomarker1: + shr edx, cl + add esi, 1 + or ebx, edx +; 3a. (First level in Huffman table, >=8 bits known) Does the current Huffman code fit in 8 bits? + cmp byte [eax+ebx*2], 8 + jbe .l2 + jl .eof_pop#stack_depth +; 4aa. No; go to next level + movzx ebx, byte [eax+ebx*2+1] + mov dl, ch + shl ebx, 5 + ror edx, cl + lea ebx, [eax+ebx+0x200] + shr edx, 24 + push edx + shr edx, 4 +; 5aa. (Second level in Huffman table) Does the current Huffman code fit in 12 bits +; and have we got enough bits? + cmp byte [ebx+edx*2], cl + jbe .l3 +; 6aaa. No; have we got 12 bits? + cmp cl, 4 + jae .l4 +; 7aaaa. No; load next byte + pop edx + sub ebp, 1 + js .eof_pop#stack_depth + mov ch, [esi] + cmp ch, 0xFF + jnz .nomarker2 +.marker2: + add esi, 1 + sub ebp, 1 + js .eof_pop#stack_depth + cmp byte [esi], 0xFF + jz .marker2 + cmp byte [esi], 0 + jnz .eof_pop#stack_depth +.nomarker2: + push ecx + shr ch, cl + add esi, 1 + or dl, ch + pop ecx + push edx + shr edx, 4 +; 8aaaa. (Second level in Huffman table) Does the current Huffman code fit in 12 bits? + cmp byte [ebx+edx*2], 4 + jbe .l5 + jl .eof_pop#stack_depth_p1 +; 9aaaaa. No; go to next level + movzx ebx, byte [ebx+edx*2+1] + pop edx + shl ebx, 5 + and edx, 0xF + lea ebx, [eax+ebx+0x200] +; 10aaaaa. Get current code length and value + sub cl, [ebx+edx*2] + movzx eax, byte [ebx+edx*2+1] + neg cl + shl ch, cl + neg cl + add cl, 8 + jmp .done +.l5: +; 9aaaab. Yes; get current code length and value + sub cl, [ebx+edx*2] + movzx eax, byte [ebx+edx*2+1] + neg cl + pop edx + shl ch, cl + neg cl + add cl, 8 + jmp .done +.l4: +; 7aaab. Yes; go to next level + movzx ebx, byte [ebx+edx*2+1] + pop edx + shl ebx, 5 + and edx, 0xF + lea ebx, [eax+ebx+0x200] +; 8aaab. (Third level in Huffman table) Have we got enough bits? + cmp [ebx+edx*2], cl + jbe .l6 +; 9aaaba. No; load next byte + sub ebp, 1 + js .eof_pop#stack_depth + mov ch, [esi] + cmp ch, 0xFF + jnz .nomarker3 +.marker3: + add esi, 1 + sub ebp, 1 + js .eof_pop#stack_depth + cmp byte [esi], 0xFF + jz .marker3 + cmp byte [esi], 0 + jnz .eof_pop#stack_depth +.nomarker3: + push ecx + shr ch, cl + add esi, 1 + or dl, ch + pop ecx +; 10aaaba. Get current code length and value + sub cl, [ebx+edx*2] + movzx eax, byte [ebx+edx*2+1] + neg cl + shl ch, cl + neg cl + add cl, 8 + jmp .done +.l3: +; 6aab. Yes; get current code length and value + pop eax +.l6: +; 9aaabb. Yes; get current code length and value + sub cl, [ebx+edx*2] + movzx eax, byte [ebx+edx*2+1] + xor cl, 7 + shl ch, cl + xor cl, 7 + add ch, ch + jmp .done +.l2: +; 3ab. Yes; get current code length and value + sub cl, [eax+ebx*2] + movzx eax, byte [eax+ebx*2+1] + neg cl + shl ch, cl + neg cl + add cl, 8 + jmp .done +.l1: +; 3b. Yes; get current code length and value + mov dl, [eax+ebx*2] + movzx eax, byte [eax+ebx*2+1] + xchg cl, dl + sub dl, cl + shl ch, cl + mov cl, dl +.done: + mov ebx, eax +} +; Decode DCT coefficients for one 8*8 block in progressive mode +; from input stream, given by pointer esi and length ebp +; N.B. Speed optimization has sense here. +align 16 +decode_progressive_coeff: + mov ecx, [ebx+jpeg.work.huffman_bits] + cmp [ebx+jpeg.work.ScanStart], 0 + jnz .ac +; DC coefficient + cmp [ebx+jpeg.work.ApproxPosHigh], 0 + jz .dc_first +; DC coefficient, subsequent passes + xor eax, eax + get_bit 0 + adc eax, eax + mov [ebx+jpeg.work.huffman_bits], ecx + mov cl, [ebx+jpeg.work.ApproxPosLow] + shl eax, cl + or [edi], ax + ret +.dc_first: +; DC coefficient, first pass + mov eax, [edx+16] + push ebx + push edx + get_huffman_code 2,3 + get_bits 2,3,true + pop ebx + add eax, [edx+48] + mov [edx+48], ax + mov [ebx+jpeg.work.huffman_bits], ecx + mov cl, [ebx+jpeg.work.ApproxPosLow] + shl eax, cl + mov [edi], ax + ret +.ac: +; AC coefficients + movzx eax, [ebx+jpeg.work.ScanStart] + cmp al, [ebx+jpeg.work.ScanEnd] + ja .ret + cmp dword [edx+52], 0 + jnz .was_eob + push ebx +.acloop: + push edx + push eax + mov eax, [edx+20] + get_huffman_code 3,4 + pop eax + test ebx, 15 + jz .band + push eax ebx + and ebx, 15 + get_bits 4,5,false + pop ebx + xchg eax, [esp] + shr ebx, 4 + mov edx, [esp+8] +.zeroloop1: + push eax ebx + movzx eax, byte [zigzag+eax] + xor ebx, ebx + cmp word [edi+eax], bx + jz .zeroloop2 + get_bit 5 + jnc @f + push ecx + mov cl, [edx+jpeg.work.ApproxPosLow] + xor ebx, ebx + cmp byte [edi+eax+1], 80h + adc ebx, 0 + add ebx, ebx + sub ebx, 1 + shl ebx, cl + pop ecx + add [edi+eax], bx +@@: + pop ebx eax +@@: + add eax, 1 + cmp al, [edx+jpeg.work.ScanEnd] + ja decode_data_unit.eof_pop3 + jmp .zeroloop1 +.zeroloop2: + pop ebx eax + sub ebx, 1 + jns @b +.nozero1: + pop ebx + test ebx, ebx + jz @f + push eax + movzx eax, byte [zigzag+eax] + push ecx + mov cl, [edx+jpeg.work.ApproxPosLow] + shl ebx, cl + pop ecx + mov [edi+eax], bx + pop eax +@@: + add eax, 1 + cmp al, [edx+jpeg.work.ScanEnd] + pop edx + jbe .acloop + pop ebx + mov [ebx+jpeg.work.huffman_bits], ecx +.ret: + ret +.eof_pop5: + pop ebx +.eof_pop4: + pop ebx +.eof_pop3: + pop ebx +.eof_pop2: + pop ebx +.eof_pop1: + pop ebx +.eof_pop0: + jmp decode_data_unit.eof_pop0 +.band: + shr ebx, 4 + cmp ebx, 15 + jnz .eob + mov edx, [esp+4] + push 0 + jmp .zeroloop1 +.eob: + pop edx + push eax + mov eax, 1 + test ebx, ebx + jz .eob0 +@@: + get_bit 2 + adc eax, eax + sub ebx, 1 + jnz @b +.eob0: + mov [edx+52], eax + pop eax + pop ebx +.was_eob: + sub dword [edx+52], 1 + cmp al, [ebx+jpeg.work.ScanEnd] + ja .ret2 + push edx +.zeroloop3: + push eax + movzx eax, byte [zigzag+eax] + xor edx, edx + cmp word [edi+eax], dx + jz @f + get_bit 2 + jnc @f + push ecx + mov cl, [ebx+jpeg.work.ApproxPosLow] + xor edx, edx + cmp byte [edi+eax+1], 80h + adc edx, 0 + add edx, edx + sub edx, 1 + shl edx, cl + pop ecx + add [edi+eax], dx +@@: + pop eax + add eax, 1 + cmp al, [ebx+jpeg.work.ScanEnd] + jbe .zeroloop3 + pop edx +.ret2: + mov [ebx+jpeg.work.huffman_bits], ecx + ret + +handle_progressive: + cmp [ebx+jpeg.work.dct_buffer], 0 + jnz @f + ret +@@: +; information for all components + lea esi, [ebx+jpeg.work.components] + xor ebp, ebp + mov ecx, [ebx+jpeg.work.pixel_size] +.next_component: + lea edi, [ebx+jpeg.work.cur_components] + lodsb ; ComponentID + lodsd + mov ax, 0x0101 + stosd ; db V, db H, db VFactor, db HFactor + xor eax, eax + mov al, byte [edi-1] ; get HFactor + mul byte [ebx+jpeg.work.pixel_size] ; number of components + stosd ; HIncrement_i = HFactor_i * sizeof(pixel) + movzx eax, byte [edi-4-2] ; get VFactor + mul [ebx+jpeg.work.line_size] ; number of components * image width + stosd ; VIncrement_i = VFactor_i * sizeof(row) + lodsb + and eax, 3 + cmp [ebx+jpeg.work.quant_tables_defined+eax], 0 + jz .error + shl eax, 8 + lea eax, [ebx+jpeg.work.quant_tables+eax] + stosd ; dd QuantizationTable + stosd ; dd DCTable - ignored + mov eax, ebp + mul [ebx+jpeg.work.dct_buffer_size] + add eax, [ebx+jpeg.work.dct_buffer] + stosd ; instead of dd ACTable - pointer to current DCT coefficients + push ecx + mov eax, [ebx+jpeg.work.image] + mov eax, [eax+Image.Width] + movzx ecx, byte [edi-21] ; get HFactor +; cdq ; edx = 0 as a result of previous mul + div ecx + stosd ; dd width / HFactor_i + stosd + xchg eax, ecx + inc eax + sub eax, edx + stosd ; dd HFactor_i+1 - (width % HFactor_i) + mov eax, [ebx+jpeg.work.image] + mov eax, [eax+Image.Height] + movzx ecx, byte [edi-34] ; get VFactor + cdq + div ecx + stosd ; dd height / VFactor_i + stosd + xchg eax, ecx + inc eax + sub eax, edx + stosd ; dd VFactor_i+1 - (height % VFactor_i) + pop ecx + xor eax, eax + cmp ebp, 1 + cmc + rcr eax, 1 + stosd ; dd DCPrediction + mov eax, ebp + stosd ; dd ComponentOffset + inc ebp + push ecx + mov [ebx+jpeg.work.cur_components_end], edi + lea edx, [edi-56] +; do IDCT and unpack + mov edi, [ebx+jpeg.work.image] + mov edi, [edi+Image.Data] + mov [ebx+jpeg.work.cur_out_ptr], edi + mov [ebx+jpeg.work.not_interleaved], 1 + call init_limits +.decode_loop: + call decode_MCU + sub [ebx+jpeg.work.cur_x], 1 + jnz .decode_loop + call next_line + sub [ebx+jpeg.work.cur_y], 1 + jnz .decode_loop + pop ecx + dec ecx + jnz .next_component +; image unpacked, return +.error: + push [ebx+jpeg.work.dct_buffer] + call [mem.free] + ret + +; Support for YCbCr -> RGB conversion +; R = Y + 1.402 * (Cr - 128) +; G = Y - 0.34414 * (Cb - 128) - 0.71414 * (Cr - 128) +; B = Y + 1.772 * (Cb - 128) +; When converting YCbCr -> RGB, we need to do some multiplications; +; to be faster, we precalculate the table for all 256 possible values +; Also we approximate fractions with N/65536, this gives sufficient precision +img.initialize.jpeg: +;initialize_color_table: +; 1.402 = 1 + 26345/65536, -0.71414 = -46802/65536 +; -0.34414 = -22554/65536, 1.772 = 1 + 50594/65536 + pushad + mov edi, color_table_1 + mov ecx, 128 +; 1. Cb -> 1.772*Cb + xor eax, eax + mov dx, 8000h +.l1: + push ecx +@@: + stosd + add dx, 50594 + adc eax, 1 + loop @b + neg dx + adc eax, -1 + neg eax + pop ecx + jnz .l1 +; 2. Cb -> -0.34414*Cb + mov ax, dx +.l2: + push ecx +@@: + stosd + sub eax, 22554 + loop @b + neg eax + pop ecx + cmp ax, dx + jnz .l2 + xor eax, eax +; 3. Cr -> -0.71414*Cr +.l3: + push ecx +@@: + stosd + sub eax, 46802 + loop @b + neg eax + pop ecx + jnz .l3 +; 4. Cr -> 1.402*Cr +.l4: + push ecx +@@: + stosd + add dx, 26345 + adc eax, 1 + loop @b + neg dx + adc eax, -1 + neg eax + pop ecx + jnz .l4 + popad + ret + +; this function is called in the end of image loading +convert_to_rgb: +; some checks + mov eax, [ebx+jpeg.work.image] + test eax, eax ; image exists? + jz .ret + cmp byte [ebx+jpeg.work.pixel_size], 3 ; full-color image? + jz .ycc2rgb + cmp byte [ebx+jpeg.work.pixel_size], 4 + jz .ycck2rgb +.ret: + ret +.ycc2rgb: +; conversion is needed + mov esi, [eax+Image.Width] + imul esi, [eax+Image.Height] + mov edi, [eax+Image.Data] + push ebx +; N.B. Speed optimization has sense here. +align 16 +.loop: +; mov ebx, [edi] +; mov edx, ebx +; mov ecx, ebx +; movzx ebx, bl ; ebx = Y +; shr edx, 16 +; mov eax, ebx +; movzx edx, dl ; edx = Cr +; movzx ecx, ch ; ecx = Cb + movzx ebx, byte [edi] + movzx ecx, byte [edi+1] + mov eax, ebx + movzx edx, byte [edi+2] +; B = Y + color_table_1[Cb] + add eax, [color_table_1+ecx*4] + mov ebp, [color_table_2+ecx*4] + cmp eax, 80000000h + sbb ecx, ecx + and eax, ecx + add ebp, [color_table_3+edx*4] + cmp eax, 0x100 + sbb ecx, ecx + not ecx + sar ebp, 16 + or eax, ecx + mov [edi], al +; G = Y + color_table_2[Cb] + color_table_3[Cr] + lea eax, [ebx+ebp] + cmp eax, 80000000h + sbb ecx, ecx + and eax, ecx + cmp eax, 0x100 + sbb ecx, ecx + not ecx + or eax, ecx + mov [edi+1], al +; R = Y + color_table_4[Cr] + mov eax, ebx + add eax, [color_table_4+edx*4] + cmp eax, 80000000h + sbb ecx, ecx + and eax, ecx + cmp eax, 0x100 + sbb ecx, ecx + not ecx + or eax, ecx + mov [edi+2], al + add edi, 3 + sub esi, 1 + jnz .loop + pop ebx + ret +.ycck2rgb: +; conversion is needed + mov esi, [eax+Image.Width] + imul esi, [eax+Image.Height] + push ebx + push esi + mov edi, [eax+Image.Data] + mov esi, edi +; N.B. Speed optimization has sense here. +align 16 +.kloop: +; mov ebx, [esi] +; mov edx, ebx +; mov ecx, ebx +; movzx ebx, bl ; ebx = Y +; shr edx, 16 +; mov eax, ebx +; movzx edx, dl ; edx = Cr +; movzx ecx, ch ; ecx = Cb + movzx ebx, byte [esi] + movzx ecx, byte [esi+1] + mov eax, ebx + movzx edx, byte [esi+2] +; B = Y + color_table_1[Cb] + add eax, [color_table_1+ecx*4] + mov ebp, [color_table_2+ecx*4] + cmp eax, 80000000h + sbb ecx, ecx + and eax, ecx + add ebp, [color_table_3+edx*4] + cmp eax, 0x100 + sbb ecx, ecx + not ecx + sar ebp, 16 + or eax, ecx + xor al, 0xFF + mul byte [esi+3] + add al, ah + adc ah, 0 + add al, 80h + adc ah, 0 + mov byte [edi], ah +; G = Y + color_table_2[Cb] + color_table_3[Cr] + lea eax, [ebx+ebp] + cmp eax, 80000000h + sbb ecx, ecx + and eax, ecx + cmp eax, 0x100 + sbb ecx, ecx + not ecx + or eax, ecx + xor al, 0xFF + mul byte [esi+3] + add al, ah + adc ah, 0 + add al, 80h + adc ah, 0 + mov byte [edi+1], ah +; R = Y + color_table_4[Cr] + mov eax, ebx + add eax, [color_table_4+edx*4] + cmp eax, 80000000h + sbb ecx, ecx + and eax, ecx + cmp eax, 0x100 + sbb ecx, ecx + not ecx + or eax, ecx + xor al, 0xFF + mul byte [esi+3] + add al, ah + adc ah, 0 + add al, 80h + adc ah, 0 + mov byte [edi+2], ah + add esi, 4 + add edi, 4 ;3 + sub dword [esp], 1 + jnz .kloop + pop eax + pop ebx +; release some memory - must succeed because we decrease size +; add ecx, 44+1 +; mov edx, ebx +; push 68 +; pop eax +; push 20 +; pop ebx +; int 0x40 +; mov ebx, eax + ret + +; Decodes one data unit, that is, 8*8 block, +; from input stream, given by pointer esi and length ebp +; N.B. Speed optimization has sense here. +align 16 +decode_data_unit: +; edx -> component data + cmp [ebx+jpeg.work.progressive], 0 + jz @f + mov edi, [edx+20] + add dword [edx+20], 64*2 + jmp .coeff_decoded +@@: + lea edi, [ebx+jpeg.work.dct_coeff] + mov ecx, 64*2/4 + xor eax, eax + rep stosd + mov edi, zigzag+1 + mov ecx, [ebx+jpeg.work.huffman_bits] +; read DC coefficient + push ebx + mov eax, [edx+16] + push edx + get_huffman_code 2,3 + get_bits 2,3,true + pop ebx + add eax, [edx+48] + mov [ebx+jpeg.work.dct_coeff], ax + mov [edx+48], ax +; read AC coefficients + push ebx +@@: + mov eax, [edx+20] + push edx + get_huffman_code 2,3 + shr eax, 4 + and ebx, 15 + jz .band + add edi, eax + cmp edi, zigzag+64 + jae .eof_pop2 + get_bits 2,3,true + movzx ebx, byte [edi] + add ebx, [esp] + mov [jpeg.work.dct_coeff+ebx], ax + add edi, 1 + cmp edi, zigzag+64 + jb @b + jmp .do_idct +.band: + pop edx + cmp al, 15 + jnz .do_idct + add edi, 16 + cmp edi, zigzag+64 + jb @b +; jmp .eof_pop1 +.do_idct: + pop ebx + lea edi, [ebx+jpeg.work.dct_coeff] + mov [ebx+jpeg.work.huffman_bits], ecx +; coefficients loaded, now IDCT +.coeff_decoded: + mov eax, [edx+12] + add ebx, jpeg.work.idct_tmp_area + push 8 +.idct_loop1: + mov cx, word [edi+1*16] +repeat 6 + or cx, word [edi+(%+1)*16] +end repeat + jnz .real_transform + fild word [edi] + fmul dword [eax] + fstp dword [ebx] + mov ecx, [ebx] +repeat 7 + mov [ebx+%*32], ecx +end repeat + jmp .idct_next1 +.real_transform: +; S0,...,S7 - transformed values, s0,...,s7 - sought-for values +; S0,...,S7 are dequantized; +; dequantization table elements were multiplied to [idct_pre_table], +; so S0,S1,... later denote S0/2\sqrt{2},S1*\cos{\pi/16}/2,... +; sqrt2 = \sqrt{2}, cos = 2\cos{\pi/8}, +; cos_sum = -2(\cos{\pi/8}+\cos{3\pi/8}), cos_diff = 2(\cos{\pi/8}-\cos{3\pi/8}) +; Now formulas: +; s0 = ((S0+S4)+(S2+S6)) + ((S1+S7)+(S3+S5)) +; s7 = ((S0+S4)+(S2+S6)) - ((S1+S7)+(S3+S5)) +; val0 = ((cos-1)S1-(cos+cos_sum+1)S3+(cos+cos_sum-1)S5-(cos+1)S7) +; s1 = ((S0-S4)+((sqrt2-1)S2-(sqrt2+1)S6)) + val0 +; s6 = ((S0-S4)+((sqrt2-1)S2-(sqrt2+1)S6)) - val0 +; val1 = (S1+S7-S3-S5)sqrt2 - val0 +; s2 = ((S0-S4)-((sqrt2-1)S2-(sqrt2+1)S6)) + val1 +; s5 = ((S0-S4)-((sqrt2-1)S2-(sqrt2+1)S6)) - val1 +; val2 = (S1-S7)cos_diff - (S1-S3+S5-S7)cos + val1 +; s3 = ((S0+S4)-(S2+S6)) - val2 +; s4 = ((S0+S4)-(S2+S6)) + val2 + fild word [edi+3*16] + fmul dword [eax+3*32] + fild word [edi+5*16] + fmul dword [eax+5*32] ; st0=S5,st1=S3 + fadd st1,st0 + fadd st0,st0 + fsub st0,st1 ; st0=S5-S3,st1=S5+S3 + fild word [edi+1*16] + fmul dword [eax+1*32] + fild word [edi+7*16] + fmul dword [eax+7*32] ; st0=S7,st1=S1 + fsub st1,st0 + fadd st0,st0 + fadd st0,st1 ; st0=S1+S7,st1=S1-S7,st2=S5-S3,st3=S5+S3 + fadd st3,st0 + fadd st0,st0 + fsub st0,st3 ; st0=S1-S3-S5+S7,st1=S1-S7,st2=S5-S3,st3=S1+S3+S5+S7 + fmul [idct_sqrt2] + fld st2 + fadd st0,st2 + fmul [idct_cos] ; st0=(S1-S3+S5-S7)cos,st1=(S1-S3-S5+S7)sqrt2, + ; st2=S1-S7,st3=S5-S3,st4=S1+S3+S5+S7 + fxch st2 + fmul [idct_cos_diff] + fsub st0,st2 ; st0=(S1-S7)cos_diff - (S1-S3+S5-S7)cos + fxch st3 + fmul [idct_cos_sum] + fadd st0,st2 ; st0=(S5-S3)cos_sum+(S1-S3+S5-S7)cos + fsub st0,st4 ; st0=val0 + fsub st1,st0 ; st0=val0,st1=val1,st2=(S1-S3+S5-S7)cos, + ; st3=(S1-S7)cos_diff-(S1-S3+S5-S7)cos,st4=S1+S3+S5+S7 + fxch st2 + fstp st0 + fadd st2,st0 ; st0=val1,st1=val0,st2=val2,st3=S1+S3+S5+S7 + + fild word [edi+0*16] + fmul dword [eax+0*32] + fild word [edi+4*16] + fmul dword [eax+4*32] ; st0=S4,st1=S0 + fsub st1,st0 + fadd st0,st0 + fadd st0,st1 ; st0=S0+S4,st1=S0-S4 + fild word [edi+6*16] + fmul dword [eax+6*32] + fild word [edi+2*16] + fmul dword [eax+2*32] ; st0=S2,st1=S6 + fadd st1,st0 + fadd st0,st0 + fsub st0,st1 ; st0=S2-S6,st1=S2+S6 + fmul [idct_sqrt2] + fsub st0,st1 + fsub st3,st0 + fadd st0,st0 + fadd st0,st3 ; st0=(S0-S4)+((S2-S6)sqrt2-(S2+S6)) + ; st3=(S0-S4)-((S2-S6)sqrt2-(S2+S6)) + fxch st1 + fsub st2,st0 + fadd st0,st0 + fadd st0,st2 ; st0=(S0+S4)+(S2+S6),st1=(S0-S4)+((S2-S6)sqrt2-(S2+S6)), + ; st2=(S0+S4)-(S2+S6),st3=(S0-S4)-((S2-S6)sqrt2-(S2+S6)) + ; st4=val1,st5=val0,st6=val2,st7=S1+S3+S5+S7 + fsubr st7,st0 + fadd st0,st0 + fsub st0,st7 + fstp dword [ebx+0*32] + fsubr st4,st0 + fadd st0,st0 + fsub st0,st4 + fstp dword [ebx+1*32] + fadd st4,st0 + fadd st0,st0 + fsub st0,st4 + fstp dword [ebx+3*32] + fsubr st1,st0 + fadd st0,st0 + fsub st0,st1 + fstp dword [ebx+2*32] + fstp dword [ebx+5*32] + fstp dword [ebx+6*32] + fstp dword [ebx+4*32] + fstp dword [ebx+7*32] +.idct_next1: + add ebx, 4 + add edi, 2 + add eax, 4 + sub dword [esp], 1 + jnz .idct_loop1 + pop ecx + sub ebx, 8*4 + mov ecx, 8 +.idct_loop2: + fld dword [ebx+3*4] + fld dword [ebx+5*4] + fadd st1,st0 + fadd st0,st0 + fsub st0,st1 ; st0=S5-S3,st1=S5+S3 + fld dword [ebx+1*4] + fld dword [ebx+7*4] + fsub st1,st0 + fadd st0,st0 + fadd st0,st1 ; st0=S1+S7,st1=S1-S7,st2=S5-S3,st3=S5+S3 + fadd st3,st0 + fadd st0,st0 + fsub st0,st3 ; st0=S1-S3-S5+S7,st1=S1-S7,st2=S5-S3,st3=S1+S3+S5+S7 + fmul [idct_sqrt2] + fld st2 + fadd st0,st2 + fmul [idct_cos] ; st0=(S1-S3+S5-S7)cos,st1=(S1-S3-S5+S7)sqrt2, + ; st2=S1-S7,st3=S5-S3,st4=S1+S3+S5+S7 + fxch st2 + fmul [idct_cos_diff] + fsub st0,st2 ; st0=(S1-S7)cos_diff - (S1-S3+S5-S7)cos + fxch st3 + fmul [idct_cos_sum] + fadd st0,st2 ; st0=(S5-S3)cos_sum+(S1-S3+S5-S7)cos + fsub st0,st4 ; st0=val0 + fsub st1,st0 ; st0=val0,st1=val1,st2=(S1-S3+S5-S7)cos, + ; st3=(S1-S7)cos_diff-(S1-S3+S5-S7)cos,st4=S1+S3+S5+S7 + fxch st2 + fstp st0 + fadd st2,st0 ; st0=val1,st1=val0,st2=val2,st3=S1+S3+S5+S7 + + fld dword [ebx+0*4] + fld dword [ebx+4*4] + fsub st1,st0 + fadd st0,st0 + fadd st0,st1 ; st0=S0+S4,st1=S0-S4 + fld dword [ebx+6*4] + fld dword [ebx+2*4] + fadd st1,st0 + fadd st0,st0 + fsub st0,st1 ; st0=S2-S6,st1=S2+S6 + fmul [idct_sqrt2] + fsub st0,st1 + fsub st3,st0 + fadd st0,st0 + fadd st0,st3 ; st0=(S0-S4)+((S2-S6)sqrt2-(S2+S6)) + ; st3=(S0-S4)-((S2-S6)sqrt2-(S2+S6)) + fxch st1 + fsub st2,st0 + fadd st0,st0 + fadd st0,st2 ; st0=(S0+S4)+(S2+S6),st1=(S0-S4)+((S2-S6)sqrt2-(S2+S6)), + ; st2=(S0+S4)-(S2+S6),st3=(S0-S4)-((S2-S6)sqrt2-(S2+S6)) + ; st4=val1,st5=val0,st6=val2,st7=S1+S3+S5+S7 + fsubr st7,st0 + fadd st0,st0 + fsub st0,st7 + fistp dword [ebx+0*4] + fsubr st4,st0 + fadd st0,st0 + fsub st0,st4 + fistp dword [ebx+1*4] + fadd st4,st0 + fadd st0,st0 + fsub st0,st4 + fistp dword [ebx+3*4] + fsubr st1,st0 + fadd st0,st0 + fsub st0,st1 + fistp dword [ebx+2*4] + fistp dword [ebx+5*4] + fistp dword [ebx+6*4] + fistp dword [ebx+4*4] + fistp dword [ebx+7*4] + + add ebx, 32 + sub ecx, 1 + jnz .idct_loop2 + + sub ebx, 32*8 + mov ecx, 64 + lea edi, [ebx - jpeg.work.idct_tmp_area + jpeg.work.decoded_data - 1] + push esi +.idct_loop3: + mov eax, [ebx] + add ebx, 4 + add eax, 80h + cmp eax, 80000000h + sbb esi, esi + add edi, 1 + and eax, esi + cmp eax, 100h + sbb esi, esi + not esi + or eax, esi + sub al, [edx+51] + sub ecx, 1 + mov [edi], al + jnz .idct_loop3 + pop esi + sub ebx, 64*4 + jpeg.work.idct_tmp_area +; done + ret + +.eof_pop3: + pop ebx +.eof_pop2: + pop ebx +.eof_pop1: + pop ebx +.eof_pop0: +; EOF or incorrect data during scanning + mov esp, [ebx + jpeg.work._esp] + jmp img.decode.jpg.end + +img.encode.jpg: + xor eax, eax + ret 8 + +zigzag: +; (x,y) -> 2*(x+y*8) +repeat 8 + .cur = % + if .cur and 1 + repeat % + db 2*((%-1) + (.cur-%)*8) + end repeat + else + repeat % + db 2*((.cur-%) + (%-1)*8) + end repeat + end if +end repeat +repeat 7 + .cur = % + if .cur and 1 + repeat 8-% + db 2*((%+.cur-1) + (8-%)*8) + end repeat + else + repeat 8-% + db 2*((8-%) + (%+.cur-1)*8) + end repeat + end if +end repeat + +align 4 +idct_pre_table: +; c_0 = 1/(2\sqrt{2}), c_i = cos(i*\pi/16)/2 + dd 0.35355339, 0.49039264, 0.461939766, 0.41573481 + dd 0.35355339, 0.27778512, 0.19134172, 0.09754516 +idct_sqrt2 dd 1.41421356 ; \sqrt{2} +idct_cos dd 1.847759065 ; 2\cos{\pi/8} +idct_cos_sum dd -2.61312593 ; -2(\cos{\pi/8} + \cos{3\pi/8}) +idct_cos_diff dd 1.08239220 ; 2(\cos{\pi/8} - \cos{3\pi/8}) +;--------------------------------------------------------------------- diff --git a/programs/develop/libraries/libs-dev/libimg/jpeg/jpeg.inc b/programs/develop/libraries/libs-dev/libimg/jpeg/jpeg.inc new file mode 100644 index 0000000000..8be95adce2 --- /dev/null +++ b/programs/develop/libraries/libs-dev/libimg/jpeg/jpeg.inc @@ -0,0 +1,96 @@ +;;================================================================================================;; +;;//// jpeg.inc //// (c) diamond, 2008-2009 //////////////////////////////////////////////////////;; +;;================================================================================================;; +;; ;; +;; This file is part of Common development libraries (Libs-Dev). ;; +;; ;; +;; Libs-Dev is free software: you can redistribute it and/or modify it under the terms of the GNU ;; +;; Lesser General Public License as published by the Free Software Foundation, either version 2.1 ;; +;; of the License, or (at your option) any later version. ;; +;; ;; +;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without ;; +;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;; +;; Lesser General Public License for more details. ;; +;; ;; +;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;; +;; If not, see . ;; +;; ;; +;;================================================================================================;; + +struct jpeg.work ; working area for JPEG handling +image dd ? +; progressive JPEG? +progressive db ? +; one component in the scan? +not_interleaved db ? +; Adobe YCCK file? +adobe_ycck db ? + rb 1 +; parameters for progressive scan +ScanStart db ? +ScanEnd db ? +ApproxPosLow db ? +ApproxPosHigh db ? +; restart interval +restart_interval dd ? +decoded_MCUs dd ? + +_esp dd ? + +; components information, up to 4 components +; db ComponentIdentifier, db V, db H, db VFactor, db HFactor, db QuantizationTable +components rb 4*6 +max_v db ? +max_h db ? +cur_rst_marker db ? + db ? +huffman_bits dd ? +block_width dd ? +block_height dd ? +block_delta_x dd ? +block_delta_y dd ? +cur_block_dx dd ? +cur_block_dy dd ? +x_num_blocks dd ? +y_num_blocks dd ? +delta_x dd ? +delta_y dd ? +pixel_size dd ? +line_size dd ? +cur_x dd ? +cur_y dd ? +max_x dd ? +max_y dd ? +cur_out_ptr dd ? +dct_buffer dd ? +dct_buffer_size dd ? +;ns dd ? +; +0: db V, db H, db VFactor, db HFactor, dd HIncrement, dd VIncrement, +; +12: dd QuantizationTable, dd DCTable, dd ACTable, +; +24: dd width/HFactor, dd width/HFactor-8k, dd HFactor+1-(width%HFactor), +; +36: dd height/VFactor, dd height/VFactor-8m, dd VFactor+1-(height%VFactor), +; +48: dw DCPrediction, db ?, db (0 for Y, 80h for Cb,Cr), dd ComponentOffset +cur_components rb 4*56 +cur_components_end dd ? +; Fourier coefficients +dct_coeff rw 64 +; Temporary space for IDCT +idct_tmp_area rd 64 +; decoded block 8*8 +decoded_data rb 8*8 +; up to 4 quantization tables +quant_tables rd 4*64 +quant_tables_defined rb 4 + +; Huffman tables +dc_huffman_defined rb 4 +ac_huffman_defined rb 4 +; up to 4 DC Huffman tables +;dc_huffman rd 4*256*2 +; up to 4 AC Huffman tables +;ac_huffman rd 4*256*2 +max_hufftable_size = (256 + (9+128)*16)*2 +dc_huffman rb 4*max_hufftable_size +ac_huffman rb 4*max_hufftable_size + +ends diff --git a/programs/develop/libraries/libs-dev/libimg/libimg.asm b/programs/develop/libraries/libs-dev/libimg/libimg.asm index 324dc1e3fb..27562315e3 100644 --- a/programs/develop/libraries/libs-dev/libimg/libimg.asm +++ b/programs/develop/libraries/libs-dev/libimg/libimg.asm @@ -1,19 +1,19 @@ ;;================================================================================================;; -;;//// libimg.asm //// (c) mike.dld, 2007-2008 ///////////////////////////////////////////////////;; +;;//// libimg.asm //// (c) mike.dld, 2007-2008, (c) diamond, 2009 ////////////////////////////////;; ;;================================================================================================;; ;; ;; ;; 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 ;; -;; General Public License as published by the Free Software Foundation, either version 3 of the ;; -;; License, or (at your option) any later version. ;; +;; 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 ;; -;; General Public License for more details. ;; +;; Lesser General Public License for more details. ;; ;; ;; -;; You should have received a copy of the GNU General Public License along with Libs-Dev. If not, ;; -;; see . ;; +;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;; +;; If not, see . ;; ;; ;; ;;================================================================================================;; @@ -25,7 +25,7 @@ public @EXPORT as 'EXPORTS' include '../../../../struct.inc' include '../../../../proc32.inc' include '../../../../macros.inc' -purge section,mov;add,sub +purge section,mov,add,sub include 'libimg.inc' @@ -33,6 +33,7 @@ section '.flat' code readable align 16 include 'bmp/bmp.asm' include 'gif/gif.asm' +include 'jpeg/jpeg.asm' mem.alloc dd ? mem.free dd ? @@ -56,6 +57,8 @@ proc lib_init ;///////////////////////////////////////////////////////////////// mov [mem.realloc], ecx mov [dll.load], edx + call img.initialize.jpeg + .ok: xor eax,eax ret endp @@ -162,6 +165,14 @@ proc img.to_rgb _img ;////////////////////////////////////////////////////////// stosd mov eax, [esi + Image.Height] stosd + mov eax, [esi + Image.Type] + dec eax + jz .bpp8 + dec eax + jz .bpp24 + dec eax + jnz .error_pop +; 32 BPP -> 24 BPP mov esi, [esi + Image.Data] @@: dec ecx @@ -174,6 +185,37 @@ proc img.to_rgb _img ;////////////////////////////////////////////////////////// pop edi esi ret +.bpp24: +; 24 BPP -> 24 BPP + lea ecx, [ecx*3 + 3] + mov esi, [esi + Image.Data] + shr ecx, 2 + rep movsd + pop eax + pop edi esi + ret + +.bpp8: +; 8 BPP -> 24 BPP + push ebx + mov ebx, [esi + Image.Palette] + mov esi, [esi + Image.Data] +@@: + movzx eax, byte [esi] + add esi, 1 + mov eax, [ebx + eax*4] + mov [edi], eax + add edi, 3 + sub ecx, 1 + jnz @b + pop ebx + pop eax + pop edi esi + ret + + .error_pop: + pop eax + .error: xor eax, eax pop edi esi @@ -196,7 +238,7 @@ proc img.decode _data, _length ;//////////////////////////////////////////////// jnz @f add ebx, sizeof.FormatsTableEntry cmp dword[ebx], 0 - jnz @f + jnz @b jmp .error @@: stdcall [ebx + FormatsTableEntry.Decode], [_data], [_length] @@ -219,7 +261,7 @@ proc img.encode _img, _p_length ;/////////////////////////////////////////////// endp ;;================================================================================================;; -proc img.create _width, _height ;/////////////////////////////////////////////////////////////////;; +proc img.create _width, _height, _type ;//////////////////////////////////////////////////////////;; ;;------------------------------------------------------------------------------------------------;; ;? --- TBD --- ;; ;;------------------------------------------------------------------------------------------------;; @@ -233,6 +275,9 @@ proc img.create _width, _height ;/////////////////////////////////////////////// or eax, eax jz .error + mov ecx, [_type] + mov [eax + Image.Type], ecx + push eax stdcall img._.resize_data, eax, [_width], [_height] @@ -240,7 +285,7 @@ proc img.create _width, _height ;/////////////////////////////////////////////// jz .error.2 pop eax - ret + jmp .ret .error.2: ; pop eax @@ -248,6 +293,7 @@ proc img.create _width, _height ;/////////////////////////////////////////////// xor eax, eax .error: + .ret: pop ecx ret endp @@ -348,39 +394,51 @@ locals scanline_len dd ? endl - push esi edi - stdcall img._.validate, [_img] + push ebx esi edi + mov ebx, [_img] + stdcall img._.validate, ebx or eax, eax jnz .error - mov esi, [_img] - mov ecx, [esi + Image.Height] - mov eax, [esi + Image.Width] - shl eax, 2 + mov ecx, [ebx + Image.Height] + mov eax, [ebx + Image.Width] + call img._.get_scanline_len mov [scanline_len], eax - push esi - test [_flip_kind], FLIP_VERTICAL jz .dont_flip_vert imul eax, ecx sub eax, [scanline_len] shr ecx, 1 - mov esi, [esi + Image.Data] + mov esi, [ebx + Image.Data] lea edi, [esi + eax] .next_line_vert: push ecx mov ecx, [scanline_len] + push ecx shr ecx, 2 - @@: lodsd + @@: mov eax, [esi] xchg eax, [edi] - mov [esi - 4], eax + mov [esi], eax + add esi, 4 add edi, 4 + sub ecx, 1 + jnz @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] @@ -391,15 +449,21 @@ endl .dont_flip_vert: - pop esi - test [_flip_kind], FLIP_HORIZONTAL jz .exit - mov ecx, [esi + Image.Height] - mov esi, [esi + Image.Data] - lea edi, [esi - 4] - add edi, [scanline_len] + mov ecx, [ebx + Image.Height] + mov eax, [ebx + Image.Type] + mov esi, [ebx + Image.Data] + mov edi, [scanline_len] + add edi, esi + + dec eax + jz .bpp8.2 + dec eax + jz .bpp24.2 + + sub edi, 4 .next_line_horz: push ecx esi edi @@ -411,7 +475,7 @@ endl mov [esi], eax add esi, 4 add edi, -4 - dec ecx + sub ecx, 1 jnz @b pop edi esi ecx @@ -419,16 +483,71 @@ endl add edi, [scanline_len] dec ecx jnz .next_line_horz + jmp .exit + +.bpp8.2: + dec edi + .next_line_horz8: + 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_horz8 + jmp .exit + +.bpp24.2: + sub edi, 3 + .next_line_horz32: + push ecx esi edi + + mov ecx, [ebx + Image.Width] + shr ecx, 1 + @@: + 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, 1 + jnz @b + + pop edi esi ecx + add esi, [scanline_len] + add edi, [scanline_len] + dec ecx + jnz .next_line_horz32 .exit: xor eax, eax inc eax - pop edi esi + pop edi esi ebx ret .error: xor eax, eax - pop edi esi + pop edi esi ebx ret endp @@ -453,7 +572,8 @@ endl mov [line_buffer], 0 push ebx esi edi - stdcall img._.validate, [_img] + mov ebx, [_img] + stdcall img._.validate, ebx or eax, eax jnz .error @@ -466,10 +586,9 @@ endl jmp .exit .rotate_ccw_low: - mov ebx, [_img] mov eax, [ebx + Image.Height] mov [scanline_pixels_new], eax - shl eax, 2 + call img._.get_scanline_len mov [scanline_len_new], eax invoke mem.alloc, eax @@ -477,8 +596,9 @@ endl jz .error mov [line_buffer], eax - mov ecx, [ebx + Image.Width] - lea eax, [ecx * 4] + mov eax, [ebx + Image.Width] + mov ecx, eax + call img._.get_scanline_len mov [scanline_len_old], eax mov eax, [scanline_len_new] @@ -486,9 +606,14 @@ endl add eax, [ebx + Image.Data] mov [pixels_ptr], eax + cmp [ebx + Image.Type], Image.bpp8 + jz .rotate_ccw8 + cmp [ebx + Image.Type], Image.bpp24 + jz .rotate_ccw24 + .next_column_ccw_low: dec ecx - jz .exchange_dims + js .exchange_dims push ecx mov edx, [scanline_len_old] @@ -524,11 +649,109 @@ endl pop ecx jmp .next_column_ccw_low +.rotate_ccw8: + .next_column_ccw_low8: + 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_low8 + +.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_cw_low: - mov ebx, [_img] mov eax, [ebx + Image.Height] mov [scanline_pixels_new], eax - shl eax, 2 + call img._.get_scanline_len mov [scanline_len_new], eax invoke mem.alloc, eax @@ -536,8 +759,9 @@ endl jz .error mov [line_buffer], eax - mov ecx, [ebx + Image.Width] - lea eax, [ecx * 4] + mov eax, [ebx + Image.Width] + mov ecx, eax + call img._.get_scanline_len mov [scanline_len_old], eax mov eax, [scanline_len_new] @@ -545,6 +769,11 @@ endl add eax, [ebx + Image.Data] mov [pixels_ptr], eax + cmp [ebx + Image.Type], Image.bpp8 + jz .rotate_cw8 + cmp [ebx + Image.Type], Image.bpp24 + jz .rotate_cw24 + .next_column_cw_low: dec ecx js .exchange_dims @@ -586,6 +815,110 @@ endl pop ecx jmp .next_column_cw_low +.rotate_cw8: + .next_column_cw_low8: + 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_low8 + +.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 + .flip: jmp .exit @@ -640,6 +973,17 @@ proc img._.new ;//////////////////////////////////////////////////////////////// ;< 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.Extended], ecx + mov [eax + Image.Previous], ecx + mov [eax + Image.Next], ecx + pop ecx +@@: ret endp @@ -674,11 +1018,35 @@ proc img._.resize_data _img, _width, _height ;////////////////////////////////// ;;------------------------------------------------------------------------------------------------;; ;< --- TBD --- ;; ;;================================================================================================;; - push ebx + 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 +; do not allow images which require too many memory + cmp eax, 4000000h + jae .error + cmp [ebx + Image.Type], Image.bpp8 + jz .bpp8 + cmp [ebx + Image.Type], Image.bpp24 + jz .bpp24 +.bpp32: shl eax, 2 + jmp @f +.bpp24: + lea eax, [eax*3] + jmp @f +.bpp8: + add eax, 256*4 ; for palette +@@: + mov esi, eax invoke mem.realloc, [ebx + Image.Data], eax or eax, eax jz .error @@ -688,12 +1056,40 @@ proc img._.resize_data _img, _width, _height ;////////////////////////////////// pop [ebx + Image.Width] push [_height] pop [ebx + Image.Height] + cmp [ebx + Image.Type], Image.bpp8 + jnz .ret + lea esi, [eax + esi - 256*4] + mov [ebx + Image.Palette], esi + jmp .ret .error: - pop ebx + xor eax, eax + .ret: + pop esi ebx ret endp +;;================================================================================================;; +img._.get_scanline_len: ;/////////////////////////////////////////////////////////////////////////;; +;;------------------------------------------------------------------------------------------------;; +;? --- TBD --- ;; +;;------------------------------------------------------------------------------------------------;; +;> --- TBD --- ;; +;;------------------------------------------------------------------------------------------------;; +;< --- TBD --- ;; +;;================================================================================================;; + cmp [ebx + Image.Type], Image.bpp8 + jz .bpp8.1 + cmp [ebx + Image.Type], Image.bpp24 + jz .bpp24.1 + shl eax, 2 + jmp @f +.bpp24.1: + lea eax, [eax*3] +.bpp8.1: +@@: + ret + ;;================================================================================================;; ;;////////////////////////////////////////////////////////////////////////////////////////////////;; @@ -710,7 +1106,7 @@ img._.formats_table: ; .cur dd img.is.cur, img.decode.cur, img.encode.cur .gif dd img.is.gif, img.decode.gif, img.encode.gif ; .png dd img.is.png, img.decode.png, img.encode.png -; .jpg dd img.is.jpg, img.decode.jpg, img.encode.jpg + .jpg dd img.is.jpg, img.decode.jpg, img.encode.jpg dd 0 @@ -723,7 +1119,7 @@ img._.formats_table: ;;================================================================================================;; -align 16 +align 4 @EXPORT: export \ @@ -744,3 +1140,12 @@ export \ img.unlock_bits , 'img.unlock_bits' , \ img.flip , 'img.flip' , \ img.rotate , 'img.rotate' + +section '.data' data readable writable align 16 +; uninitialized data - global constant tables + +; 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 aac8ab138b..aa28ea26bb 100644 --- a/programs/develop/libraries/libs-dev/libimg/libimg.inc +++ b/programs/develop/libraries/libs-dev/libimg/libimg.inc @@ -1,19 +1,19 @@ ;;================================================================================================;; -;;//// libimg.inc //// (c) mike.dld, 2007-2008 ///////////////////////////////////////////////////;; +;;//// libimg.inc //// (c) mike.dld, 2007-2008, (c) diamond, 2009 ////////////////////////////////;; ;;================================================================================================;; ;; ;; ;; 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 ;; -;; General Public License as published by the Free Software Foundation, either version 3 of the ;; -;; License, or (at your option) any later version. ;; +;; 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 ;; -;; General Public License for more details. ;; +;; Lesser General Public License for more details. ;; ;; ;; -;; You should have received a copy of the GNU General Public License along with Libs-Dev. If not, ;; -;; see . ;; +;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;; +;; If not, see . ;; ;; ;; ;;================================================================================================;; @@ -30,10 +30,16 @@ struct Image Height dd ? Next dd ? Previous dd ? + Type dd ? ; one of Image.bppN Data dd ? + Palette dd ? ; used iff Type eq Image.bpp8 Extended dd ? ends +Image.bpp8 = 1 +Image.bpp24 = 2 +Image.bpp32 = 3 + FLIP_VERTICAL = 0x01 FLIP_HORIZONTAL = 0x02 FLIP_BOTH = FLIP_VERTICAL or FLIP_HORIZONTAL