Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 998 → Rev 999

/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 <http://www.gnu.org/licenses/>. ;;
;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;;
;; If not, see <http://www.gnu.org/licenses/>. ;;
;; ;;
;;================================================================================================;;
;; ;;
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
;;------------------------------------------------------------------------------------------------;;
;< 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]
; test 2: signature
mov eax, [esp+4]
cmp word[eax], 'BM'
je .yep
 
.nope:
xor eax, eax
ret
ret 8
 
.yep:
xor eax,eax
inc eax
ret
endp
ret 8
;endp
 
;;================================================================================================;;
proc img.decode.bmp _data, _length ;//////////////////////////////////////////////////////////////;;
65,13 → 68,15
;;================================================================================================;;
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
; mov eax, [ebx + bmp.Header.file.Size]
; cmp eax, [_length]
; jne .error
; @@:
 
@@: stdcall img.create, [ebx + bmp.Header.info.Width], [ebx + bmp.Header.info.Height]
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
 
or eax, eax
jz .error
mov [img], eax
88,15 → 145,38
 
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
103,37 → 183,49
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
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.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
 
and edx, 0x03
add esi, edx
pop ecx
pop edx ecx
dec ecx
jnz .next_line
 
238,22 → 336,19
;;------------------------------------------------------------------------------------------------;;
 
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.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
.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
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.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
.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
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.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,10 → 504,9
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
375,17 → 513,26
jne @f
mov [abs_mode_addr], .absolute_mode.rle4
mov [enc_mode_addr], .encoded_mode.rle4
@@:
 
@@: mov esi, ebx
add esi, [ebx + bmp.Header.file.OffBits]
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 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
jmp [enc_mode_addr]
 
.escape_mode:
sub ecx, 1
jc .eof
lodsb
cmp al, 0
je .end_of_scanline
403,29 → 552,30
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
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]
@@:
dec edx
js @f
mov [edi], cl
dec edx
js @f
mov [edi+1], al
add edi, 2
jmp @b
.odd:
stosd
inc [marker_x]
jmp @b
@@:
pop ecx
jmp .check_eoi
 
.absolute_mode.rle4: ; N: b1 .. bN
mov edx, eax
push eax
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
and eax, 0x0FF
mov ecx, eax
shr eax, 4
mov eax, [ebx + eax * 4 + bmp.Header.info.Palette]
stosd
inc [marker_x]
mov cl, al
shr al, 4
and cl, 0xF
stosb
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
inc edi
jmp @b
@@: pop eax
@@: 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,9 → 714,24
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
mov [shift.Red], al
577,17 → 764,9
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
 
.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
retn
endp
 
if 0
;;================================================================================================;;
proc img.decode.bmp._.jpeg ;//////////////////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;;
705,8 → 885,8
xor eax, eax
ret
endp
end if
 
 
;;================================================================================================;;
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
;;================================================================================================;;
/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 <http://www.gnu.org/licenses/>. ;;
;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;;
;; If not, see <http://www.gnu.org/licenses/>. ;;
;; ;;
;;================================================================================================;;
 
28,10 → 28,20
struct bmp.InfoHeader
; v2 (Windows 2.x)
Size dd ? ; Size of this header in bytes
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
/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 <http://www.gnu.org/licenses/>. ;;
;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;;
;; If not, see <http://www.gnu.org/licenses/>. ;;
;; ;;
;;================================================================================================;;
;; ;;
/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 <http://www.gnu.org/licenses/>. ;;
;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;;
;; If not, see <http://www.gnu.org/licenses/>. ;;
;; ;;
;;================================================================================================;;
;; ;;
84,20 → 84,18
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
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
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,34 → 151,35
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 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
 
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
 
.decoded:
or eax, eax
jz @f
187,6 → 190,11
ret
 
.error:
mov eax, [img]
test eax, eax
jz @f
stdcall img.destroy, eax
@@:
xor eax, eax
pop ebx
ret
309,7 → 317,7
endp
 
;;================================================================================================;;
proc img.decode.gif._.process_image _color_table ;////////////////////////////////////////////////;;
proc img.decode.gif._.process_image ;/////////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;;
;? --- TBD --- ;;
;;------------------------------------------------------------------------------------------------;;
342,8 → 350,6
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
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
 
.loop2:
pop ax
stosb
 
lea esi, [eax * 3]
add esi, [_color_table]
 
mov esi, [esi]
bswap esi
shr esi, 8
mov [edi], esi
add edi, 4
 
cmp edi, [row_end]
jb .norowend
mov eax, [width]
; lea eax, [eax * 3]
shl eax, 2
push eax
sub edi, eax
add eax, eax
/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 <http://www.gnu.org/licenses/>. ;;
;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;;
;; If not, see <http://www.gnu.org/licenses/>. ;;
;; ;;
;;================================================================================================;;
 
/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 <http://www.gnu.org/licenses/>. ;;
;; ;;
;;================================================================================================;;
 
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})
;---------------------------------------------------------------------
/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 <http://www.gnu.org/licenses/>. ;;
;; ;;
;;================================================================================================;;
 
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
/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 <http://www.gnu.org/licenses/>. ;;
;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;;
;; If not, see <http://www.gnu.org/licenses/>. ;;
;; ;;
;;================================================================================================;;
 
25,7 → 25,7
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
 
include 'bmp/bmp.asm'
include 'gif/gif.asm'
include 'jpeg/jpeg.asm'
 
mem.alloc dd ?
mem.free dd ?
56,6 → 57,8
mov [mem.realloc], ecx
mov [dll.load], edx
 
call img.initialize.jpeg
 
.ok: xor eax,eax
ret
endp
162,6 → 165,14
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
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
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
endp
 
;;================================================================================================;;
proc img.create _width, _height ;/////////////////////////////////////////////////////////////////;;
proc img.create _width, _height, _type ;//////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;;
;? --- TBD --- ;;
;;------------------------------------------------------------------------------------------------;;
233,6 → 275,9
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
jz .error.2
 
pop eax
ret
jmp .ret
 
.error.2:
; pop eax
248,6 → 293,7
xor eax, eax
 
.error:
.ret:
pop ecx
ret
endp
348,19 → 394,17
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
 
367,7 → 411,7
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:
374,13 → 418,27
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,16 → 449,22
 
.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
mov [esi], eax
add esi, 4
add edi, -4
dec ecx
sub ecx, 1
jnz @b
 
pop edi esi ecx
419,16 → 483,71
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
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
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
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
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
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
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
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
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
;< 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
;;------------------------------------------------------------------------------------------------;;
;< --- 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,13 → 1056,41
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
; .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
;;================================================================================================;;
 
 
align 16
align 4
@EXPORT:
 
export \
744,3 → 1140,12
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
/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 <http://www.gnu.org/licenses/>. ;;
;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;;
;; If not, see <http://www.gnu.org/licenses/>. ;;
;; ;;
;;================================================================================================;;
 
30,10 → 30,16
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