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