diff --git a/programs/develop/libraries/libs-dev/libimg/Tupfile.lua b/programs/develop/libraries/libs-dev/libimg/Tupfile.lua
index a68bff973..69b6a65c5 100644
--- a/programs/develop/libraries/libs-dev/libimg/Tupfile.lua
+++ b/programs/develop/libraries/libs-dev/libimg/Tupfile.lua
@@ -1,2 +1,6 @@
if tup.getconfig("NO_FASM") ~= "" then return end
-tup.rule("libimg.asm", "fasm -m 32768 %f %o " .. tup.getconfig("KPACK_CMD"), "libimg.obj")
+HELPERDIR = (tup.getconfig("HELPERDIR") == "") and "../../../.." or tup.getconfig("HELPERDIR")
+tup.include(HELPERDIR .. "/use_fasm.lua")
+
+add_include(HELPERDIR .. "/develop/libraries/libs-dev/libio")
+tup.rule("libimg.asm", FASM .. " -m 32768 %f %o " .. tup.getconfig("KPACK_CMD"), "%B.obj")
diff --git a/programs/develop/libraries/libs-dev/libimg/blend.asm b/programs/develop/libraries/libs-dev/libimg/blend.asm
new file mode 100644
index 000000000..051ef1d5e
--- /dev/null
+++ b/programs/develop/libraries/libs-dev/libimg/blend.asm
@@ -0,0 +1,76 @@
+match =MMX, COMPOSITE_MODE {include 'blend_mmx.asm'}
+match =SSE, COMPOSITE_MODE {include 'blend_sse.asm'}
+
+;;============================================================================;;
+proc img.blend uses ebx esi edi, _bottom, _top, _xbottom, _ybottom, \ ;///////;;
+ _xtop, _ytop, _width, _height ;//////////////;;
+;;----------------------------------------------------------------------------;;
+;? Alpha blend _top image to _bottom one (both must be of type Image.bpp32) ;;
+;;----------------------------------------------------------------------------;;
+;> _bottom = pointer to bottom image (will be changed) ;;
+;> _top = pointer to top image (unchanged) ;;
+;> _xbottom = x coord inside _bottom image where to put _top image ;;
+;> _ybottom = y coord inside _bottom image where to put _top image ;;
+;> _xtop = x coord inside _top image to start from ;;
+;> _ytop = y coord inside _top image to start from ;;
+;> _width = width of _top image area to put to _bottom image ;;
+;> _height = height of _top image area to put to _bottom image ;;
+;;----------------------------------------------------------------------------;;
+;< eax = 0 (fail) / _bottom (ok) ;;
+;;============================================================================;;
+ mov esi, [_top]
+ mov edi, [_bottom]
+
+ mov eax, [esi+Image.Width]
+ sub eax, [_width]
+ shl eax, 2
+ push eax
+
+ mov eax, [edi+Image.Width]
+ sub eax, [_width]
+ shl eax, 2
+ push eax
+
+ mov eax, [_ytop]
+ imul eax, [esi+Image.Width]
+ add eax, [_xtop]
+ shl eax, 2
+ mov esi, [esi+Image.Data]
+ add esi, eax
+
+ mov eax, [_ybottom]
+ imul eax, [edi+Image.Width]
+ add eax, [_xbottom]
+ shl eax, 2
+ mov edi, [edi+Image.Data]
+ add edi, eax
+ stdcall xcf._.composite_rgb_00, [_width], [_height]
+ mov eax, [_bottom]
+ ret
+endp
+
+
+xcf._.composite_table.begin:
+ .p00 dd 00, xcf._.composite_rgb_00, xcf._.composite_gray_00, xcf._.composite_indexed_00 ; Normal
+ .p01 dd 01, xcf._.composite_rgb_01, xcf._.composite_gray_01, xcf._.composite_gray_01 ; Dissolve : random dithering to discrete alpha
+; .p02 dd 02, xcf._.composite_rgb_02, 0, xcf._.composite_indexed_02 ; Behind : not selectable in the GIMP UI. not implemented
+ .p03 dd 03, xcf._.composite_rgb_03, xcf._.composite_rgb_03, xcf._.composite_indexed_00 ; Multiply
+ .p04 dd 04, xcf._.composite_rgb_04, xcf._.composite_rgb_04, xcf._.composite_indexed_00 ; Screen
+ .p05 dd 05, xcf._.composite_rgb_05, xcf._.composite_rgb_05, xcf._.composite_indexed_00 ; Overlay
+ .p06 dd 06, xcf._.composite_rgb_06, xcf._.composite_rgb_06, xcf._.composite_indexed_00 ; Difference
+ .p07 dd 07, xcf._.composite_rgb_07, xcf._.composite_rgb_07, xcf._.composite_indexed_00 ; Addition
+ .p08 dd 08, xcf._.composite_rgb_08, xcf._.composite_rgb_08, xcf._.composite_indexed_00 ; Subtract
+ .p09 dd 09, xcf._.composite_rgb_09, xcf._.composite_rgb_09, xcf._.composite_indexed_00 ; Darken Only
+ .p10 dd 10, xcf._.composite_rgb_10, xcf._.composite_rgb_10, xcf._.composite_indexed_00 ; Lighten Only
+ .p11 dd 11, xcf._.composite_rgb_11, xcf._.composite_gray_00, xcf._.composite_indexed_00 ; Hue (H of HSV)
+ .p12 dd 12, xcf._.composite_rgb_12, xcf._.composite_gray_00, xcf._.composite_indexed_00 ; Saturation (S of HSV)
+ .p13 dd 13, xcf._.composite_rgb_13, xcf._.composite_gray_00, xcf._.composite_indexed_00 ; Color (H and S of HSL)
+ .p14 dd 14, xcf._.composite_rgb_14, xcf._.composite_gray_00, xcf._.composite_indexed_00 ; Value (V of HSV)
+ .p15 dd 15, xcf._.composite_rgb_15, xcf._.composite_rgb_15, xcf._.composite_indexed_00 ; Divide
+ .p16 dd 16, xcf._.composite_rgb_16, xcf._.composite_rgb_16, xcf._.composite_indexed_00 ; Dodge
+ .p17 dd 17, xcf._.composite_rgb_17, xcf._.composite_rgb_17, xcf._.composite_indexed_00 ; Burn
+ .p18 dd 18, xcf._.composite_rgb_18, xcf._.composite_rgb_18, xcf._.composite_indexed_00 ; Hard Light
+ .p19 dd 19, xcf._.composite_rgb_05, xcf._.composite_rgb_05, xcf._.composite_indexed_00 ; Soft Light : XCF >= 2 only ('soft light' == 'overlay')
+ .p20 dd 20, xcf._.composite_rgb_20, xcf._.composite_rgb_20, xcf._.composite_indexed_00 ; Grain Extract : XCF >= 2 only
+ .p21 dd 21, xcf._.composite_rgb_21, xcf._.composite_rgb_21, xcf._.composite_indexed_00 ; Grain Merge : XCF >= 2 only
+xcf._.composite_table.end:
diff --git a/programs/develop/libraries/libs-dev/libimg/xcf/composite_mmx.asm b/programs/develop/libraries/libs-dev/libimg/blend_mmx.asm
similarity index 85%
rename from programs/develop/libraries/libs-dev/libimg/xcf/composite_mmx.asm
rename to programs/develop/libraries/libs-dev/libimg/blend_mmx.asm
index 50bb01f2b..4f252eff3 100644
--- a/programs/develop/libraries/libs-dev/libimg/xcf/composite_mmx.asm
+++ b/programs/develop/libraries/libs-dev/libimg/blend_mmx.asm
@@ -1,3 +1,22 @@
+;;================================================================================================;;
+;;//// blend_mmx.asm //// (c) dunkaist, 2011-2012 ////////////////////////////////////////////////;;
+;;================================================================================================;;
+;; ;;
+;; 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 . ;;
+;; ;;
+;;================================================================================================;;
+
proc xcf._.blend_rgb
xchg al, bh
diff --git a/programs/develop/libraries/libs-dev/libimg/xcf/composite_sse.asm b/programs/develop/libraries/libs-dev/libimg/blend_sse.asm
similarity index 90%
rename from programs/develop/libraries/libs-dev/libimg/xcf/composite_sse.asm
rename to programs/develop/libraries/libs-dev/libimg/blend_sse.asm
index 010aa388e..2b1f673ae 100644
--- a/programs/develop/libraries/libs-dev/libimg/xcf/composite_sse.asm
+++ b/programs/develop/libraries/libs-dev/libimg/blend_sse.asm
@@ -1,3 +1,22 @@
+;;================================================================================================;;
+;;//// blend_sse.asm //// (c) dunkaist, 2011-2012 ////////////////////////////////////////////////;;
+;;================================================================================================;;
+;; ;;
+;; 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 . ;;
+;; ;;
+;;================================================================================================;;
+
proc xcf._.blend_rgb
push eax ebx
diff --git a/programs/develop/libraries/libs-dev/libimg/bmp/bmp.asm b/programs/develop/libraries/libs-dev/libimg/bmp/bmp.asm
index 0aadc75b8..39069a316 100644
--- a/programs/develop/libraries/libs-dev/libimg/bmp/bmp.asm
+++ b/programs/develop/libraries/libs-dev/libimg/bmp/bmp.asm
@@ -1,1161 +1,1161 @@
-;;================================================================================================;;
-;;//// 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 ;;
-;; Lesser General Public License as published by the Free Software Foundation, either version 2.1 ;;
-;; of the License, or (at your option) any later version. ;;
-;; ;;
-;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without ;;
-;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;
-;; Lesser General Public License for more details. ;;
-;; ;;
-;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;;
-;; If not, see . ;;
-;; ;;
-;;================================================================================================;;
-;; ;;
-;; References: ;;
-;; 1. "Microsoft Windows Bitmap File Format Summary" ;;
-;; from "Encyclopedia of Graphics File Formats" by O'Reilly ;;
-;; http://www.fileformat.info/format/bmp/ ;;
-;; ;;
-;;================================================================================================;;
-
-
-include 'bmp.inc'
-
-;;================================================================================================;;
-;;proc img.is.bmp _data, _length ;////////////////////////////////////////////////////////////////;;
-img.is.bmp:
-;;------------------------------------------------------------------------------------------------;;
-;? Determine if raw data could be decoded (is in BMP format) ;;
-;;------------------------------------------------------------------------------------------------;;
-;> _data = raw data as read from file/stream ;;
-;> _length = data length ;;
-;;------------------------------------------------------------------------------------------------;;
-;< eax = false / true ;;
-;;================================================================================================;;
-; test 1 (length of data): data must contain FileHeader and required fields from InfoHeader
- cmp dword [esp+8], sizeof.bmp.FileHeader + 12
- jb .nope
-; test 2: signature
- mov eax, [esp+4]
- cmp word [eax], 'BM'
- je .yep
-
- .nope:
- xor eax, eax
- ret 8
-
- .yep:
- xor eax, eax
- inc eax
- ret 8
-;endp
-
-;;================================================================================================;;
-proc img.decode.bmp _data, _length, _options ;////////////////////////////////////////////////////;;
-;;------------------------------------------------------------------------------------------------;;
-;? Decode data into image if it contains correctly formed raw data in BMP format ;;
-;;------------------------------------------------------------------------------------------------;;
-;> _data = raw data as read from file/stream ;;
-;> _length = data length ;;
-;;------------------------------------------------------------------------------------------------;;
-;< eax = 0 (error) or pointer to image ;;
-;;================================================================================================;;
-locals
- length_rest dd ?
- img dd ?
- bTopDown db ?
- bIsIco db ?
-endl
-img.decode.bmp.length_rest equ length_rest
- mov [bIsIco], 0
-.common: ; common place for BMP and ICO
-
- push ebx esi edi
-
- mov ebx, [_data]
- cmp [bIsIco], 0
- jnz @f
- add ebx, sizeof.bmp.FileHeader
- sub [_length], sizeof.bmp.FileHeader
- @@:
-
- mov eax, [ebx + bmp.InfoHeader.Size]
-; sanity check: file length must be greater than size of headers
- cmp [_length], eax
- jbe .error
-
- mov [bTopDown], 0
-
- cmp eax, 12 ; 0x0C
- jz .old1
- cmp eax, 40 ; 0x28
- jz .normal
- cmp eax, 56 ; 0x38
- je .normal
- cmp eax, 0x6C
- je .normal
- cmp eax, 0x7C
- jnz .error
-; convert images with <= 8 bpp to 8bpp, other - to 32 bpp
-.normal:
- m2m eax, Image.bpp8i
- cmp byte [ebx + 14], 8 ; bit count
- jbe @f
- mov al, Image.bpp32
-@@:
- push eax
- mov eax, [ebx + 8] ;[ebx + bmp.InfoHeader.Height]
- test eax, eax
- jns @f
- inc [bTopDown]
- neg eax
-@@:
- cmp [bIsIco], 0 ; for icons Height is two times larger than image height
- jz @f
- shr eax, 1
-@@:
- pushd eax
- pushd [ebx + 4] ;[ebx + bmp.InfoHeader.Width]
- jmp .create
-.old1:
- m2m eax, Image.bpp8i
- cmp byte [ebx + 10], 8 ; bit count
- jbe @f
- mov al, Image.bpp32
-@@:
- push eax
- movsx eax, word [ebx + 6] ;[ebx + bmp.InfoHeader.OldHeight]
- test eax, eax
- jns @f
- inc [bTopDown]
- neg eax
-@@:
- cmp [bIsIco], 0 ; for icons Height is two times larger than image height
- jz @f
- shr eax, 1
-@@:
- push eax
- movzx eax, word [ebx + 4] ;[ebx + bmp.InfoHeader.OldWidth]
- push eax
-.create:
- call img.create
-
- or eax, eax
- jz .error
- mov [img], eax
- mov edx, eax
-
- invoke mem.alloc, sizeof.bmp.Image
- or eax, eax
- jz .error.free
- mov [edx + Image.Extended], eax
- push eax
- mov edi, eax
- mov ecx, sizeof.bmp.Image/4
- xor eax, eax
- rep stosd
- pop edi
- push edi
- mov esi, ebx
- mov ecx, [ebx] ;[ebx + 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:
-
- pop edi
- cmp [bIsIco], 0
- jnz @f
- mov edi, [_length]
- add edi, sizeof.bmp.FileHeader
- mov esi, [ebx - sizeof.bmp.FileHeader + bmp.FileHeader.OffBits]
- jmp .offset_calculated
-@@:
- xor esi, esi
- mov cl, byte [edi + bmp.Image.info.BitCount]
- cmp cl, 8
- ja @f
- inc esi
- add cl, 2
- shl esi, cl
-@@:
- add esi, [edi + bmp.Image.info.Size]
- mov edi, [_length]
-.offset_calculated:
- sub edi, esi
- jbe .error.free
- add esi, [_data]
-
- 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 word [ebx + 14], 8 ;bmp.InfoHeader.BitCount
- jnz .error.free
- stdcall ._.rle
- jmp .decoded
- @@: cmp eax, bmp.BI_RLE4
- jne @f
- cmp word [ebx + 14], 4
- jnz .error.free
- stdcall ._.rle
- jmp .decoded
- @@: cmp eax, bmp.BI_BITFIELDS
- jne .error.free
- stdcall ._.bitfields
- jmp .decoded
-; 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
-
- @@:
- cmp [bTopDown], 0
- jnz @f
- stdcall img.flip, [img], FLIP_VERTICAL
- @@:
- mov eax, [img]
- mov ecx, [length_rest] ; return length for ICO code
- cmp [bIsIco], 0
- jz @f
- mov [esp + 4], esi ; return pointer to end-of-data for ICO code
- @@:
- pop edi esi ebx
- ret
-
- .error:
- xor eax, eax
- pop edi esi ebx
- ret
-endp
-
-;;================================================================================================;;
-proc img.encode.bmp _img, _common, _specific ;////////////////////////////////////////////////////;;
-;;------------------------------------------------------------------------------------------------;;
-;? Encode image into raw data in BMP format ;;
-;;------------------------------------------------------------------------------------------------;;
-;> [_img] = pointer to image ;;
-;> [_common] = format independent options ;;
-;> [_specific] = 0 / pointer to the structure of format specific options ;;
-;;------------------------------------------------------------------------------------------------;;
-;< eax = 0 / pointer to encoded data ;;
-;< ecx = error code / the size of encoded data ;;
-;;================================================================================================;;
-locals
- bytes_per_scanline rd 1
- encoded_file rd 1
- encoded_file_size rd 1
- encoded_data_size rd 1
-endl
- mov ebx, [_img]
- mov eax, [ebx + Image.Type]
- cmp eax, Image.bpp24
- je .bpp24
- cmp eax, Image.bpp32
- je .bpp32
- mov ecx, LIBIMG_ERROR_BIT_DEPTH
- jmp .error
-
- .bpp24:
- mov eax, [ebx + Image.Width]
- call img._.get_scanline_len
- test eax, 0x03
- jz @f
- and al, 0xfc
- add eax, 4
- @@:
- mov [bytes_per_scanline], eax
- imul eax, [ebx + Image.Height]
- mov [encoded_data_size], eax
- add eax, 108 + 14
- mov [encoded_file_size], eax
- stdcall [mem.alloc], eax
- test eax, eax
- jz .error
- mov [encoded_file], eax
- mov edi, eax
-
- mov word[edi], 'BM'
- add edi, 2
- mov eax, [encoded_file_size]
- stosd
- xor eax, eax
- stosd
- mov eax, 108 + 14
- stosd
- mov eax, 108
- stosd
- mov eax, [ebx + Image.Width]
- stosd
- mov eax, [ebx + Image.Height]
- stosd
- mov ax, 1 ; Planes
- stosw
- mov ax, 24 ; BitCount
- stosw
- mov eax, bmp.BI_RGB
- stosd
- mov eax, [encoded_data_size]
- stosd
- mov eax, 0x00000B13
- stosd
- stosd
- xor eax, eax
- stosd
- stosd
- mov eax, 'BGRs'
- stosd
- xor eax, eax
- stosd
- stosd
- stosd
- stosd
- stosd
- stosd
- stosd
- stosd
- stosd
- stosd
- stosd
- stosd
- mov eax, 2
- stosd
- xor eax, eax
- stosd
- stosd
- stosd
-
- mov esi, [ebx + Image.Data]
- mov ecx, [ebx + Image.Width]
- lea ecx, [ecx*3]
- mov eax, [ebx + Image.Height]
- mov edx, [bytes_per_scanline]
- sub edx, ecx
- mov dh, cl
- and dh, 3
- shr ecx, 2
- push ecx
- add edi, [encoded_data_size]
- sub edi, [bytes_per_scanline]
- @@:
- pop ecx
- push ecx
- rep movsd
- mov cl, dh
- rep movsb
- mov cl, dl
- add edi, ecx
- sub edi, [bytes_per_scanline]
- sub edi, [bytes_per_scanline]
- dec eax
- jnz @b
- pop ecx
- mov eax, [encoded_file]
- mov ecx, [encoded_file_size]
- jmp .quit
-
- .bpp32:
- mov eax, [ebx + Image.Width]
- call img._.get_scanline_len
- mov [bytes_per_scanline], eax
- imul eax, [ebx + Image.Height]
- mov [encoded_data_size], eax
- add eax, 0x7C + 14
- mov [encoded_file_size], eax
- stdcall [mem.alloc], eax
- test eax, eax
- jz .error
- mov [encoded_file], eax
- mov edi, eax
-
- mov word[edi], 'BM'
- add edi, 2
- mov eax, [encoded_file_size]
- stosd
- xor eax, eax
- stosd
- mov eax, 0x7C + 14
- stosd
- mov eax, 0x7C
- stosd
- mov eax, [ebx + Image.Width]
- stosd
- mov eax, [ebx + Image.Height]
- stosd
- mov ax, 1 ; Planes
- stosw
- mov ax, 32 ; BitCount
- stosw
- mov eax, 3 ; WTF? bmp.BI_RGB
- stosd
- mov eax, [encoded_data_size]
- stosd
- mov eax, 0x00000B13
- stosd
- stosd
- xor eax, eax
- stosd
- stosd
- mov eax, 0xFF000000
- stosd
- shr eax, 8
- stosd
- shr eax, 8
- stosd
-; shr eax, 8
- xor eax, eax
- stosd
- mov eax, 'BGRs'
- stosd
- xor eax, eax
- stosd
- stosd
- stosd
- stosd
- stosd
- stosd
- stosd
- stosd
- stosd
- stosd
- stosd
- stosd
- mov eax, 2
- stosd
- xor eax, eax
- stosd
- stosd
- stosd
-
- mov esi, [ebx + Image.Data]
- mov ecx, [ebx + Image.Width]
- mov eax, [ebx + Image.Height]
- add edi, [encoded_data_size]
- sub edi, [bytes_per_scanline]
- push ecx
- .next_line:
- pop ecx
- push ecx
- push eax
- @@:
- dec ecx
- js @f
- lodsd
- rol eax, 8
- stosd
- jmp @b
- @@:
- sub edi, [bytes_per_scanline]
- sub edi, [bytes_per_scanline]
- pop eax
- dec eax
- jnz .next_line
- pop ecx
- mov eax, [encoded_file]
- mov ecx, [encoded_file_size]
- jmp .quit
-
- .error:
- xor eax, eax
- .quit:
- ret
-endp
-
-
-;;================================================================================================;;
-;;////////////////////////////////////////////////////////////////////////////////////////////////;;
-;;================================================================================================;;
-;! Below are private procs you should never call directly from your code ;;
-;;================================================================================================;;
-;;////////////////////////////////////////////////////////////////////////////////////////////////;;
-;;================================================================================================;;
-
-
-;;================================================================================================;;
-proc img.decode.bmp._.rgb ;///////////////////////////////////////////////////////////////////////;;
-;;------------------------------------------------------------------------------------------------;;
-;? --- TBD --- ;;
-;;------------------------------------------------------------------------------------------------;;
-;> ebx = raw image data ;;
-;> edx = image data ;;
-;;------------------------------------------------------------------------------------------------;;
-;< --- TBD --- ;;
-;;================================================================================================;;
- mov ecx, [edx + Image.Extended]
- mov [ecx + bmp.Image.info.AlphaMask], 0
-
- movzx eax, [ecx + bmp.Image.info.BitCount]
- cmp eax, 32
- je .32bpp
- cmp eax, 24
- je .24bpp
- cmp eax, 16
- je .16bpp
- cmp eax, 8
- je .8bpp
- cmp eax, 4
- je .4bpp
- cmp eax, 1
- je .1bpp
- jmp .error
-
-;;------------------------------------------------------------------------------------------------;;
-
-img.decode.bmp._.rgb.32bpp:
- mov [ecx + bmp.Image.info.RedMask], 00000000111111110000000000000000b ; 8-0-0
- mov [ecx + bmp.Image.info.GreenMask], 00000000000000001111111100000000b ; 0-8-0
- mov [ecx + bmp.Image.info.BlueMask], 00000000000000000000000011111111b ; 0-0-8
- stdcall img.decode.bmp._.bitfields
- ret
-
-;;------------------------------------------------------------------------------------------------;;
-
-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
- sub edi, eax
- jb img.decode.bmp._.rgb.error
- mov [img.decode.bmp.length_rest], edi
- mov edi, [edx + Image.Data]
-
- .next_line:
- push ecx edx
- mov ecx, [edx + Image.Width]
- xor edx, edx
-
- .next_line_pixel:
- movsd
- dec esi
- inc edx
- dec ecx
- jnz .next_line_pixel
-
- and edx, 0x03
- add esi, edx
- pop edx ecx
- dec ecx
- jnz .next_line
-
- jmp img.decode.bmp._.rgb.exit
-
-;;------------------------------------------------------------------------------------------------;;
-
-img.decode.bmp._.rgb.16bpp:
- mov [ecx + bmp.Image.info.RedMask], 00000000000000000111110000000000b ; 5-0-0
- mov [ecx + bmp.Image.info.GreenMask], 00000000000000000000001111100000b ; 0-5-0
- mov [ecx + bmp.Image.info.BlueMask], 00000000000000000000000000011111b ; 0-0-5
- stdcall img.decode.bmp._.bitfields
- ret
-
-;;------------------------------------------------------------------------------------------------;;
-
-img.decode.bmp._.rgb.8bpp:
- 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, [edx + Image.Width]
- mov eax, ecx
- neg eax
- and eax, 3
- rep movsb
- add esi, eax
- pop ecx
- dec ecx
- jnz .next_line
-
- jmp img.decode.bmp._.rgb.exit
-
-;;------------------------------------------------------------------------------------------------;;
-
-img.decode.bmp._.rgb.4bpp:
- 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 edx
- mov ecx, [edx + Image.Width]
-
- .next_line_dword:
- push ecx
- lodsd
- bswap eax
- xchg edx, eax
- mov ecx, 32 / 4
-
- .next_pixel:
- rol edx, 4
- mov al, dl
- and al, 0x0000000F
- stosb
- dec dword[esp]
- jz @f
- dec ecx
- jnz .next_pixel
-
- @@: pop ecx
- or ecx, ecx
- jnz .next_line_dword
-
- pop edx ecx
- dec ecx
- jnz .next_line
-
- jmp img.decode.bmp._.rgb.exit
-
-;;------------------------------------------------------------------------------------------------;;
-
-img.decode.bmp._.rgb.1bpp:
- 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 edx
- mov ecx, [edx + Image.Width]
-
- .next_line_dword:
- push ecx
- lodsd
- bswap eax
- xchg edx, eax
- mov ecx, 32 / 1
-
- .next_pixel:
- rol edx, 1
- mov al, dl
- and al, 0x00000001
- stosb
- dec dword[esp]
- jz @f
- dec ecx
- jnz .next_pixel
-
- @@: pop ecx
- or ecx, ecx
- jnz .next_line_dword
-
- pop edx ecx
- dec ecx
- jnz .next_line
-
- jmp img.decode.bmp._.rgb.exit
-
-;;------------------------------------------------------------------------------------------------;;
-
- img.decode.bmp._.rgb.exit:
- xor eax, eax
- ret
-
- 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
- sub edi, eax
- jb .ret
- mov [img.decode.bmp.length_rest], edi
- push esi
- sub esi, ebx
- jc .ret.pop
- sub esi, [ebx + bmp.InfoHeader.Size]
- jc .ret.pop
- mov eax, esi
- mov edi, [edx + Image.Palette]
- push ecx
- mov ecx, 256
- mov esi, [ebx + bmp.InfoHeader.Size]
- cmp esi, 12
- jz .old
- shr eax, 2
- add esi, ebx
- cmp ecx, eax
- jb @f
- mov ecx, eax
-@@:
- rep movsd
- jmp .common
-.old:
- add esi, ebx
-@@:
- movsd
- dec esi
- sub eax, 3
- jbe @f
- sub ecx, 1
- jnz @b
-@@:
-.common:
- pop ecx
- mov edi, [edx + Image.Data]
- clc
-.ret.pop:
- pop esi
-.ret:
- ret
-endp
-
-;;================================================================================================;;
-proc img.decode.bmp._.rle ;///////////////////////////////////////////////////////////////////////;;
-;;------------------------------------------------------------------------------------------------;;
-;? --- TBD --- ;;
-;;------------------------------------------------------------------------------------------------;;
-;> ebx = raw image data ;;
-;> edx = image data ;;
-;;------------------------------------------------------------------------------------------------;;
-;< --- TBD --- ;;
-;;================================================================================================;;
-locals
- scanline_len dd ?
- marker_x dd ?
- marker_y dd ?
- abs_mode_addr dd ?
- enc_mode_addr dd ?
- height dd ?
-endl
-
- mov [abs_mode_addr], .absolute_mode.rle8
- mov [enc_mode_addr], .encoded_mode.rle8
- cmp [ebx + bmp.InfoHeader.Compression], bmp.BI_RLE4
- jne @f
- mov [abs_mode_addr], .absolute_mode.rle4
- mov [enc_mode_addr], .encoded_mode.rle4
- @@:
-
- push edi
- xor eax, eax ; do not check file size in .prepare_palette
- push ebp
- mov ebp, [ebp] ; set parent stack frame
- call img.decode.bmp._.rgb.prepare_palette
- pop ebp
- pop ecx ; ecx = rest bytes in file
- jc .error
-
- mov eax, [edx + Image.Width]
- 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
- jz .escape_mode
- jmp [enc_mode_addr]
-
- .escape_mode:
- sub ecx, 1
- jc .eof
- lodsb
- cmp al, 0
- je .end_of_scanline
- cmp al, 1
- je .exit
- cmp al, 2
- je .offset_marker
- jmp [abs_mode_addr]
-
- .end_of_scanline: ; 0
- sub edi, [marker_x]
- add edi, [scanline_len]
- mov [marker_x], 0
- 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, [scanline_len]
- jae .exit
- mov [marker_x], edx
- add edi, eax
- lodsb
- mov edx, [marker_y]
- add edx, eax
- cmp edx, [height]
- jae .exit
- mov [marker_y], edx
- imul eax, [scanline_len]
- add edi, eax
- jmp .next_run
-
- .encoded_mode.rle8: ; N: b1 * N
- call .fix_marker
- sub ecx, 1
- jc .eof
- lodsb
- push ecx
- mov ecx, edx
- rep stosb
- pop ecx
- jmp .check_eoi
-
- .absolute_mode.rle8: ; N: b1 .. bN
- 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
- .check_eoi:
- mov eax, [marker_y]
- cmp eax, [height]
- jb .next_run
- jmp .exit
-
- .encoded_mode.rle4: ; N: b1 * N
- 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
- @@:
- dec edx
- js @f
- mov [edi], cl
- dec edx
- js @f
- mov [edi+1], al
- add edi, 2
- jmp @b
- @@:
- 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
- jp .check_eoi
- sub ecx, 1
- jc .eof
- inc esi
- jmp .check_eoi
-
- .fix_marker:
- mov edx, eax
- add eax, [marker_x]
- mov [marker_x], eax
- @@:
- 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
-
- .error:
- or eax, -1
- ret
-endp
-
-;;================================================================================================;;
-proc img.decode.bmp._.bitfields ;/////////////////////////////////////////////////////////////////;;
-;;------------------------------------------------------------------------------------------------;;
-;? --- TBD --- ;;
-;;------------------------------------------------------------------------------------------------;;
-;> ebx = raw image data ;;
-;> edx = image data ;;
-;;------------------------------------------------------------------------------------------------;;
-;< --- TBD --- ;;
-;;================================================================================================;;
-locals
- shift bmp.RgbByteQuad
- unshift bmp.RgbByteQuad
- mask bmp.RgbQuad
- delta dd ?
- dataoff dd ? ; offset of encoded data
- ; row data are aligned on dword from data start, not file start
-endl
-
- 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]
- sub edi, ecx
- jb .error
- mov ecx, [ebp] ; use parent stack frame
- mov [ecx + img.decode.bmp.length_rest - ebp], edi ; !
-
- push esi
- mov esi, eax
-
- mov ecx, [esi + bmp.Image.info.RedMask]
- call .calc_shift
- mov [shift.Red], al
- mov [mask.Red], ecx
- call .calc_unshift
- mov [unshift.Red], al
- mov ecx, [esi + bmp.Image.info.GreenMask]
- call .calc_shift
- mov [shift.Green], al
- mov [unshift.Green], al
- mov [mask.Green], ecx
- call .calc_unshift
- mov [unshift.Green], al
- mov ecx, [esi + bmp.Image.info.BlueMask]
- call .calc_shift
- mov [shift.Blue], al
- mov [unshift.Blue], al
- mov [mask.Blue], ecx
- call .calc_unshift
- mov [unshift.Blue], al
- mov ecx, [esi + bmp.Image.info.AlphaMask]
- call .calc_shift
- mov [shift.Alpha], al
- mov [unshift.Alpha], al
- mov [mask.Alpha], ecx
- call .calc_unshift
- mov [unshift.Alpha], al
-
- mov edi, [edx + Image.Data]
- pop esi
- mov [dataoff], esi
-
-;;------------------------------------------------------------------------------------------------;;
-
- mov ecx, [edx + Image.Height]
-
- .next_line:
- push ecx
- mov ecx, [edx + Image.Width]
-
- .next_pixel:
- push ecx
-
- mov eax, [esi]
- mov cl, [shift.Blue]
- shr eax, cl
- and eax, [mask.Blue]
- mov cl, [unshift.Blue]
- shl eax, cl
- stosb
-
- mov eax, [esi]
- mov cl, [shift.Green]
- shr eax, cl
- and eax, [mask.Green]
- mov cl, [unshift.Green]
- shl eax, cl
- stosb
-
- mov eax, [esi]
- mov cl, [shift.Red]
- shr eax, cl
- and eax, [mask.Red]
- mov cl, [unshift.Red]
- shl eax, cl
- stosb
-
- mov eax, [esi]
- mov cl, [shift.Alpha]
- shr eax, cl
- and eax, [mask.Alpha]
- mov cl, [unshift.Alpha]
- shl eax, cl
- stosb
-
- add esi, [delta]
-
- pop ecx
- dec ecx
- jnz .next_pixel
-
- sub esi, [dataoff]
- add esi, 3
- and esi, not 3
- add esi, [dataoff]
- pop ecx
- dec ecx
- jnz .next_line
-
-;;------------------------------------------------------------------------------------------------;;
-
- .exit:
- xor eax, eax
- pop edi
- ret
-
- .error:
- or eax, -1
- pop edi
- ret
-
-.calc_shift:
- xor eax, eax
- or ecx, ecx
- jnz @f
- retn
- @@: test ecx, 1
- jnz @f
- .zz: shr ecx, 1
- inc eax
- jmp @b
- @@: test ecx, 0100000000b
- jnz .zz
- retn
-.calc_unshift:
- xor eax, eax
- or ecx, ecx
- jnz @f
- retn
- @@: test ecx, 1
- jz @f
- shr ecx, 1
- inc eax
- jmp @b
- @@: sub eax, 8
- neg eax
- retn
-endp
-
-if 0
-;;================================================================================================;;
-proc img.decode.bmp._.jpeg ;//////////////////////////////////////////////////////////////////////;;
-;;------------------------------------------------------------------------------------------------;;
-;? --- TBD --- ;;
-;;------------------------------------------------------------------------------------------------;;
-;> ebx = raw image data ;;
-;> edx = image data ;;
-;;------------------------------------------------------------------------------------------------;;
-;< --- TBD --- ;;
-;;================================================================================================;;
- xor eax, eax
- ret
-endp
-
-;;================================================================================================;;
-proc img.decode.bmp._.png ;///////////////////////////////////////////////////////////////////////;;
-;;------------------------------------------------------------------------------------------------;;
-;? --- TBD --- ;;
-;;------------------------------------------------------------------------------------------------;;
-;> ebx = raw image data ;;
-;> edx = image data ;;
-;;------------------------------------------------------------------------------------------------;;
-;< --- TBD --- ;;
-;;================================================================================================;;
- xor eax, eax
- ret
-endp
-end if
-
-;;================================================================================================;;
-;;////////////////////////////////////////////////////////////////////////////////////////////////;;
-;;================================================================================================;;
-;! Below is private data you should never use directly from your code ;;
-;;================================================================================================;;
-;;////////////////////////////////////////////////////////////////////////////////////////////////;;
-;;================================================================================================;;
-
-
-;
+;;================================================================================================;;
+;;//// 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 ;;
+;; Lesser General Public License as published by the Free Software Foundation, either version 2.1 ;;
+;; of the License, or (at your option) any later version. ;;
+;; ;;
+;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without ;;
+;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;
+;; Lesser General Public License for more details. ;;
+;; ;;
+;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;;
+;; If not, see . ;;
+;; ;;
+;;================================================================================================;;
+;; ;;
+;; References: ;;
+;; 1. "Microsoft Windows Bitmap File Format Summary" ;;
+;; from "Encyclopedia of Graphics File Formats" by O'Reilly ;;
+;; http://www.fileformat.info/format/bmp/ ;;
+;; ;;
+;;================================================================================================;;
+
+
+include 'bmp.inc'
+
+;;================================================================================================;;
+;;proc img.is.bmp _data, _length ;////////////////////////////////////////////////////////////////;;
+img.is.bmp:
+;;------------------------------------------------------------------------------------------------;;
+;? Determine if raw data could be decoded (is in BMP format) ;;
+;;------------------------------------------------------------------------------------------------;;
+;> _data = raw data as read from file/stream ;;
+;> _length = data length ;;
+;;------------------------------------------------------------------------------------------------;;
+;< eax = false / true ;;
+;;================================================================================================;;
+; test 1 (length of data): data must contain FileHeader and required fields from InfoHeader
+ cmp dword [esp+8], sizeof.bmp.FileHeader + 12
+ jb .nope
+; test 2: signature
+ mov eax, [esp+4]
+ cmp word [eax], 'BM'
+ je .yep
+
+ .nope:
+ xor eax, eax
+ ret 8
+
+ .yep:
+ xor eax, eax
+ inc eax
+ ret 8
+;endp
+
+;;================================================================================================;;
+proc img.decode.bmp _data, _length, _options ;////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? Decode data into image if it contains correctly formed raw data in BMP format ;;
+;;------------------------------------------------------------------------------------------------;;
+;> _data = raw data as read from file/stream ;;
+;> _length = data length ;;
+;;------------------------------------------------------------------------------------------------;;
+;< eax = 0 (error) or pointer to image ;;
+;;================================================================================================;;
+locals
+ length_rest dd ?
+ img dd ?
+ bTopDown db ?
+ bIsIco db ?
+endl
+img.decode.bmp.length_rest equ length_rest
+ mov [bIsIco], 0
+.common: ; common place for BMP and ICO
+
+ push ebx esi edi
+
+ mov ebx, [_data]
+ cmp [bIsIco], 0
+ jnz @f
+ add ebx, sizeof.bmp.FileHeader
+ sub [_length], sizeof.bmp.FileHeader
+ @@:
+
+ mov eax, [ebx + bmp.InfoHeader.Size]
+; sanity check: file length must be greater than size of headers
+ cmp [_length], eax
+ jbe .error
+
+ mov [bTopDown], 0
+
+ cmp eax, 12 ; 0x0C
+ jz .old1
+ cmp eax, 40 ; 0x28
+ jz .normal
+ cmp eax, 56 ; 0x38
+ je .normal
+ cmp eax, 0x6C
+ je .normal
+ cmp eax, 0x7C
+ jnz .error
+; convert images with <= 8 bpp to 8bpp, other - to 32 bpp
+.normal:
+ m2m eax, Image.bpp8i
+ cmp byte [ebx + 14], 8 ; bit count
+ jbe @f
+ mov al, Image.bpp32
+@@:
+ push eax
+ mov eax, [ebx + 8] ;[ebx + bmp.InfoHeader.Height]
+ test eax, eax
+ jns @f
+ inc [bTopDown]
+ neg eax
+@@:
+ cmp [bIsIco], 0 ; for icons Height is two times larger than image height
+ jz @f
+ shr eax, 1
+@@:
+ pushd eax
+ pushd [ebx + 4] ;[ebx + bmp.InfoHeader.Width]
+ jmp .create
+.old1:
+ m2m eax, Image.bpp8i
+ cmp byte [ebx + 10], 8 ; bit count
+ jbe @f
+ mov al, Image.bpp32
+@@:
+ push eax
+ movsx eax, word [ebx + 6] ;[ebx + bmp.InfoHeader.OldHeight]
+ test eax, eax
+ jns @f
+ inc [bTopDown]
+ neg eax
+@@:
+ cmp [bIsIco], 0 ; for icons Height is two times larger than image height
+ jz @f
+ shr eax, 1
+@@:
+ push eax
+ movzx eax, word [ebx + 4] ;[ebx + bmp.InfoHeader.OldWidth]
+ push eax
+.create:
+ call img.create
+
+ or eax, eax
+ jz .error
+ mov [img], eax
+ mov edx, eax
+
+ invoke mem.alloc, sizeof.bmp.Image
+ or eax, eax
+ jz .error.free
+ mov [edx + Image.Extended], eax
+ push eax
+ mov edi, eax
+ mov ecx, sizeof.bmp.Image/4
+ xor eax, eax
+ rep stosd
+ pop edi
+ push edi
+ mov esi, ebx
+ mov ecx, [ebx] ;[ebx + 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:
+
+ pop edi
+ cmp [bIsIco], 0
+ jnz @f
+ mov edi, [_length]
+ add edi, sizeof.bmp.FileHeader
+ mov esi, [ebx - sizeof.bmp.FileHeader + bmp.FileHeader.OffBits]
+ jmp .offset_calculated
+@@:
+ xor esi, esi
+ mov cl, byte [edi + bmp.Image.info.BitCount]
+ cmp cl, 8
+ ja @f
+ inc esi
+ add cl, 2
+ shl esi, cl
+@@:
+ add esi, [edi + bmp.Image.info.Size]
+ mov edi, [_length]
+.offset_calculated:
+ sub edi, esi
+ jbe .error.free
+ add esi, [_data]
+
+ 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 word [ebx + 14], 8 ;bmp.InfoHeader.BitCount
+ jnz .error.free
+ stdcall ._.rle
+ jmp .decoded
+ @@: cmp eax, bmp.BI_RLE4
+ jne @f
+ cmp word [ebx + 14], 4
+ jnz .error.free
+ stdcall ._.rle
+ jmp .decoded
+ @@: cmp eax, bmp.BI_BITFIELDS
+ jne .error.free
+ stdcall ._.bitfields
+ jmp .decoded
+; 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
+
+ @@:
+ cmp [bTopDown], 0
+ jnz @f
+ stdcall img.flip, [img], FLIP_VERTICAL
+ @@:
+ mov eax, [img]
+ mov ecx, [length_rest] ; return length for ICO code
+ cmp [bIsIco], 0
+ jz @f
+ mov [esp + 4], esi ; return pointer to end-of-data for ICO code
+ @@:
+ pop edi esi ebx
+ ret
+
+ .error:
+ xor eax, eax
+ pop edi esi ebx
+ ret
+endp
+
+;;================================================================================================;;
+proc img.encode.bmp _img, _common, _specific ;////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? Encode image into raw data in BMP format ;;
+;;------------------------------------------------------------------------------------------------;;
+;> [_img] = pointer to image ;;
+;> [_common] = format independent options ;;
+;> [_specific] = 0 / pointer to the structure of format specific options ;;
+;;------------------------------------------------------------------------------------------------;;
+;< eax = 0 / pointer to encoded data ;;
+;< ecx = error code / the size of encoded data ;;
+;;================================================================================================;;
+locals
+ bytes_per_scanline rd 1
+ encoded_file rd 1
+ encoded_file_size rd 1
+ encoded_data_size rd 1
+endl
+ mov ebx, [_img]
+ mov eax, [ebx + Image.Type]
+ cmp eax, Image.bpp24
+ je .bpp24
+ cmp eax, Image.bpp32
+ je .bpp32
+ mov ecx, LIBIMG_ERROR_BIT_DEPTH
+ jmp .error
+
+ .bpp24:
+ mov eax, [ebx + Image.Width]
+ call img._.get_scanline_len
+ test eax, 0x03
+ jz @f
+ and al, 0xfc
+ add eax, 4
+ @@:
+ mov [bytes_per_scanline], eax
+ imul eax, [ebx + Image.Height]
+ mov [encoded_data_size], eax
+ add eax, 108 + 14
+ mov [encoded_file_size], eax
+ stdcall [mem.alloc], eax
+ test eax, eax
+ jz .error
+ mov [encoded_file], eax
+ mov edi, eax
+
+ mov word[edi], 'BM'
+ add edi, 2
+ mov eax, [encoded_file_size]
+ stosd
+ xor eax, eax
+ stosd
+ mov eax, 108 + 14
+ stosd
+ mov eax, 108
+ stosd
+ mov eax, [ebx + Image.Width]
+ stosd
+ mov eax, [ebx + Image.Height]
+ stosd
+ mov ax, 1 ; Planes
+ stosw
+ mov ax, 24 ; BitCount
+ stosw
+ mov eax, bmp.BI_RGB
+ stosd
+ mov eax, [encoded_data_size]
+ stosd
+ mov eax, 0x00000B13
+ stosd
+ stosd
+ xor eax, eax
+ stosd
+ stosd
+ mov eax, 'BGRs'
+ stosd
+ xor eax, eax
+ stosd
+ stosd
+ stosd
+ stosd
+ stosd
+ stosd
+ stosd
+ stosd
+ stosd
+ stosd
+ stosd
+ stosd
+ mov eax, 2
+ stosd
+ xor eax, eax
+ stosd
+ stosd
+ stosd
+
+ mov esi, [ebx + Image.Data]
+ mov ecx, [ebx + Image.Width]
+ lea ecx, [ecx*3]
+ mov eax, [ebx + Image.Height]
+ mov edx, [bytes_per_scanline]
+ sub edx, ecx
+ mov dh, cl
+ and dh, 3
+ shr ecx, 2
+ push ecx
+ add edi, [encoded_data_size]
+ sub edi, [bytes_per_scanline]
+ @@:
+ pop ecx
+ push ecx
+ rep movsd
+ mov cl, dh
+ rep movsb
+ mov cl, dl
+ add edi, ecx
+ sub edi, [bytes_per_scanline]
+ sub edi, [bytes_per_scanline]
+ dec eax
+ jnz @b
+ pop ecx
+ mov eax, [encoded_file]
+ mov ecx, [encoded_file_size]
+ jmp .quit
+
+ .bpp32:
+ mov eax, [ebx + Image.Width]
+ call img._.get_scanline_len
+ mov [bytes_per_scanline], eax
+ imul eax, [ebx + Image.Height]
+ mov [encoded_data_size], eax
+ add eax, 0x7C + 14
+ mov [encoded_file_size], eax
+ stdcall [mem.alloc], eax
+ test eax, eax
+ jz .error
+ mov [encoded_file], eax
+ mov edi, eax
+
+ mov word[edi], 'BM'
+ add edi, 2
+ mov eax, [encoded_file_size]
+ stosd
+ xor eax, eax
+ stosd
+ mov eax, 0x7C + 14
+ stosd
+ mov eax, 0x7C
+ stosd
+ mov eax, [ebx + Image.Width]
+ stosd
+ mov eax, [ebx + Image.Height]
+ stosd
+ mov ax, 1 ; Planes
+ stosw
+ mov ax, 32 ; BitCount
+ stosw
+ mov eax, 3 ; WTF? bmp.BI_RGB
+ stosd
+ mov eax, [encoded_data_size]
+ stosd
+ mov eax, 0x00000B13
+ stosd
+ stosd
+ xor eax, eax
+ stosd
+ stosd
+ mov eax, 0xFF000000
+ stosd
+ shr eax, 8
+ stosd
+ shr eax, 8
+ stosd
+; shr eax, 8
+ xor eax, eax
+ stosd
+ mov eax, 'BGRs'
+ stosd
+ xor eax, eax
+ stosd
+ stosd
+ stosd
+ stosd
+ stosd
+ stosd
+ stosd
+ stosd
+ stosd
+ stosd
+ stosd
+ stosd
+ mov eax, 2
+ stosd
+ xor eax, eax
+ stosd
+ stosd
+ stosd
+
+ mov esi, [ebx + Image.Data]
+ mov ecx, [ebx + Image.Width]
+ mov eax, [ebx + Image.Height]
+ add edi, [encoded_data_size]
+ sub edi, [bytes_per_scanline]
+ push ecx
+ .next_line:
+ pop ecx
+ push ecx
+ push eax
+ @@:
+ dec ecx
+ js @f
+ lodsd
+ rol eax, 8
+ stosd
+ jmp @b
+ @@:
+ sub edi, [bytes_per_scanline]
+ sub edi, [bytes_per_scanline]
+ pop eax
+ dec eax
+ jnz .next_line
+ pop ecx
+ mov eax, [encoded_file]
+ mov ecx, [encoded_file_size]
+ jmp .quit
+
+ .error:
+ xor eax, eax
+ .quit:
+ ret
+endp
+
+
+;;================================================================================================;;
+;;////////////////////////////////////////////////////////////////////////////////////////////////;;
+;;================================================================================================;;
+;! Below are private procs you should never call directly from your code ;;
+;;================================================================================================;;
+;;////////////////////////////////////////////////////////////////////////////////////////////////;;
+;;================================================================================================;;
+
+
+;;================================================================================================;;
+proc img.decode.bmp._.rgb ;///////////////////////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? --- TBD --- ;;
+;;------------------------------------------------------------------------------------------------;;
+;> ebx = raw image data ;;
+;> edx = image data ;;
+;;------------------------------------------------------------------------------------------------;;
+;< --- TBD --- ;;
+;;================================================================================================;;
+ mov ecx, [edx + Image.Extended]
+ mov [ecx + bmp.Image.info.AlphaMask], 0
+
+ movzx eax, [ecx + bmp.Image.info.BitCount]
+ cmp eax, 32
+ je .32bpp
+ cmp eax, 24
+ je .24bpp
+ cmp eax, 16
+ je .16bpp
+ cmp eax, 8
+ je .8bpp
+ cmp eax, 4
+ je .4bpp
+ cmp eax, 1
+ je .1bpp
+ jmp .error
+
+;;------------------------------------------------------------------------------------------------;;
+
+img.decode.bmp._.rgb.32bpp:
+ mov [ecx + bmp.Image.info.RedMask], 00000000111111110000000000000000b ; 8-0-0
+ mov [ecx + bmp.Image.info.GreenMask], 00000000000000001111111100000000b ; 0-8-0
+ mov [ecx + bmp.Image.info.BlueMask], 00000000000000000000000011111111b ; 0-0-8
+ stdcall img.decode.bmp._.bitfields
+ ret
+
+;;------------------------------------------------------------------------------------------------;;
+
+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
+ sub edi, eax
+ jb img.decode.bmp._.rgb.error
+ mov [img.decode.bmp.length_rest], edi
+ mov edi, [edx + Image.Data]
+
+ .next_line:
+ push ecx edx
+ mov ecx, [edx + Image.Width]
+ xor edx, edx
+
+ .next_line_pixel:
+ movsd
+ dec esi
+ inc edx
+ dec ecx
+ jnz .next_line_pixel
+
+ and edx, 0x03
+ add esi, edx
+ pop edx ecx
+ dec ecx
+ jnz .next_line
+
+ jmp img.decode.bmp._.rgb.exit
+
+;;------------------------------------------------------------------------------------------------;;
+
+img.decode.bmp._.rgb.16bpp:
+ mov [ecx + bmp.Image.info.RedMask], 00000000000000000111110000000000b ; 5-0-0
+ mov [ecx + bmp.Image.info.GreenMask], 00000000000000000000001111100000b ; 0-5-0
+ mov [ecx + bmp.Image.info.BlueMask], 00000000000000000000000000011111b ; 0-0-5
+ stdcall img.decode.bmp._.bitfields
+ ret
+
+;;------------------------------------------------------------------------------------------------;;
+
+img.decode.bmp._.rgb.8bpp:
+ 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, [edx + Image.Width]
+ mov eax, ecx
+ neg eax
+ and eax, 3
+ rep movsb
+ add esi, eax
+ pop ecx
+ dec ecx
+ jnz .next_line
+
+ jmp img.decode.bmp._.rgb.exit
+
+;;------------------------------------------------------------------------------------------------;;
+
+img.decode.bmp._.rgb.4bpp:
+ 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 edx
+ mov ecx, [edx + Image.Width]
+
+ .next_line_dword:
+ push ecx
+ lodsd
+ bswap eax
+ xchg edx, eax
+ mov ecx, 32 / 4
+
+ .next_pixel:
+ rol edx, 4
+ mov al, dl
+ and al, 0x0000000F
+ stosb
+ dec dword[esp]
+ jz @f
+ dec ecx
+ jnz .next_pixel
+
+ @@: pop ecx
+ or ecx, ecx
+ jnz .next_line_dword
+
+ pop edx ecx
+ dec ecx
+ jnz .next_line
+
+ jmp img.decode.bmp._.rgb.exit
+
+;;------------------------------------------------------------------------------------------------;;
+
+img.decode.bmp._.rgb.1bpp:
+ 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 edx
+ mov ecx, [edx + Image.Width]
+
+ .next_line_dword:
+ push ecx
+ lodsd
+ bswap eax
+ xchg edx, eax
+ mov ecx, 32 / 1
+
+ .next_pixel:
+ rol edx, 1
+ mov al, dl
+ and al, 0x00000001
+ stosb
+ dec dword[esp]
+ jz @f
+ dec ecx
+ jnz .next_pixel
+
+ @@: pop ecx
+ or ecx, ecx
+ jnz .next_line_dword
+
+ pop edx ecx
+ dec ecx
+ jnz .next_line
+
+ jmp img.decode.bmp._.rgb.exit
+
+;;------------------------------------------------------------------------------------------------;;
+
+ img.decode.bmp._.rgb.exit:
+ xor eax, eax
+ ret
+
+ 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
+ sub edi, eax
+ jb .ret
+ mov [img.decode.bmp.length_rest], edi
+ push esi
+ sub esi, ebx
+ jc .ret.pop
+ sub esi, [ebx + bmp.InfoHeader.Size]
+ jc .ret.pop
+ mov eax, esi
+ mov edi, [edx + Image.Palette]
+ push ecx
+ mov ecx, 256
+ mov esi, [ebx + bmp.InfoHeader.Size]
+ cmp esi, 12
+ jz .old
+ shr eax, 2
+ add esi, ebx
+ cmp ecx, eax
+ jb @f
+ mov ecx, eax
+@@:
+ rep movsd
+ jmp .common
+.old:
+ add esi, ebx
+@@:
+ movsd
+ dec esi
+ sub eax, 3
+ jbe @f
+ sub ecx, 1
+ jnz @b
+@@:
+.common:
+ pop ecx
+ mov edi, [edx + Image.Data]
+ clc
+.ret.pop:
+ pop esi
+.ret:
+ ret
+endp
+
+;;================================================================================================;;
+proc img.decode.bmp._.rle ;///////////////////////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? --- TBD --- ;;
+;;------------------------------------------------------------------------------------------------;;
+;> ebx = raw image data ;;
+;> edx = image data ;;
+;;------------------------------------------------------------------------------------------------;;
+;< --- TBD --- ;;
+;;================================================================================================;;
+locals
+ scanline_len dd ?
+ marker_x dd ?
+ marker_y dd ?
+ abs_mode_addr dd ?
+ enc_mode_addr dd ?
+ height dd ?
+endl
+
+ mov [abs_mode_addr], .absolute_mode.rle8
+ mov [enc_mode_addr], .encoded_mode.rle8
+ cmp [ebx + bmp.InfoHeader.Compression], bmp.BI_RLE4
+ jne @f
+ mov [abs_mode_addr], .absolute_mode.rle4
+ mov [enc_mode_addr], .encoded_mode.rle4
+ @@:
+
+ push edi
+ xor eax, eax ; do not check file size in .prepare_palette
+ push ebp
+ mov ebp, [ebp] ; set parent stack frame
+ call img.decode.bmp._.rgb.prepare_palette
+ pop ebp
+ pop ecx ; ecx = rest bytes in file
+ jc .error
+
+ mov eax, [edx + Image.Width]
+ 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
+ jz .escape_mode
+ jmp [enc_mode_addr]
+
+ .escape_mode:
+ sub ecx, 1
+ jc .eof
+ lodsb
+ cmp al, 0
+ je .end_of_scanline
+ cmp al, 1
+ je .exit
+ cmp al, 2
+ je .offset_marker
+ jmp [abs_mode_addr]
+
+ .end_of_scanline: ; 0
+ sub edi, [marker_x]
+ add edi, [scanline_len]
+ mov [marker_x], 0
+ 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, [scanline_len]
+ jae .exit
+ mov [marker_x], edx
+ add edi, eax
+ lodsb
+ mov edx, [marker_y]
+ add edx, eax
+ cmp edx, [height]
+ jae .exit
+ mov [marker_y], edx
+ imul eax, [scanline_len]
+ add edi, eax
+ jmp .next_run
+
+ .encoded_mode.rle8: ; N: b1 * N
+ call .fix_marker
+ sub ecx, 1
+ jc .eof
+ lodsb
+ push ecx
+ mov ecx, edx
+ rep stosb
+ pop ecx
+ jmp .check_eoi
+
+ .absolute_mode.rle8: ; N: b1 .. bN
+ 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
+ .check_eoi:
+ mov eax, [marker_y]
+ cmp eax, [height]
+ jb .next_run
+ jmp .exit
+
+ .encoded_mode.rle4: ; N: b1 * N
+ 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
+ @@:
+ dec edx
+ js @f
+ mov [edi], cl
+ dec edx
+ js @f
+ mov [edi+1], al
+ add edi, 2
+ jmp @b
+ @@:
+ 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
+ jp .check_eoi
+ sub ecx, 1
+ jc .eof
+ inc esi
+ jmp .check_eoi
+
+ .fix_marker:
+ mov edx, eax
+ add eax, [marker_x]
+ mov [marker_x], eax
+ @@:
+ 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
+
+ .error:
+ or eax, -1
+ ret
+endp
+
+;;================================================================================================;;
+proc img.decode.bmp._.bitfields ;/////////////////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? --- TBD --- ;;
+;;------------------------------------------------------------------------------------------------;;
+;> ebx = raw image data ;;
+;> edx = image data ;;
+;;------------------------------------------------------------------------------------------------;;
+;< --- TBD --- ;;
+;;================================================================================================;;
+locals
+ shift bmp.RgbByteQuad
+ unshift bmp.RgbByteQuad
+ mask bmp.RgbQuad
+ delta dd ?
+ dataoff dd ? ; offset of encoded data
+ ; row data are aligned on dword from data start, not file start
+endl
+
+ 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]
+ sub edi, ecx
+ jb .error
+ mov ecx, [ebp] ; use parent stack frame
+ mov [ecx + img.decode.bmp.length_rest - ebp], edi ; !
+
+ push esi
+ mov esi, eax
+
+ mov ecx, [esi + bmp.Image.info.RedMask]
+ call .calc_shift
+ mov [shift.Red], al
+ mov [mask.Red], ecx
+ call .calc_unshift
+ mov [unshift.Red], al
+ mov ecx, [esi + bmp.Image.info.GreenMask]
+ call .calc_shift
+ mov [shift.Green], al
+ mov [unshift.Green], al
+ mov [mask.Green], ecx
+ call .calc_unshift
+ mov [unshift.Green], al
+ mov ecx, [esi + bmp.Image.info.BlueMask]
+ call .calc_shift
+ mov [shift.Blue], al
+ mov [unshift.Blue], al
+ mov [mask.Blue], ecx
+ call .calc_unshift
+ mov [unshift.Blue], al
+ mov ecx, [esi + bmp.Image.info.AlphaMask]
+ call .calc_shift
+ mov [shift.Alpha], al
+ mov [unshift.Alpha], al
+ mov [mask.Alpha], ecx
+ call .calc_unshift
+ mov [unshift.Alpha], al
+
+ mov edi, [edx + Image.Data]
+ pop esi
+ mov [dataoff], esi
+
+;;------------------------------------------------------------------------------------------------;;
+
+ mov ecx, [edx + Image.Height]
+
+ .next_line:
+ push ecx
+ mov ecx, [edx + Image.Width]
+
+ .next_pixel:
+ push ecx
+
+ mov eax, [esi]
+ mov cl, [shift.Blue]
+ shr eax, cl
+ and eax, [mask.Blue]
+ mov cl, [unshift.Blue]
+ shl eax, cl
+ stosb
+
+ mov eax, [esi]
+ mov cl, [shift.Green]
+ shr eax, cl
+ and eax, [mask.Green]
+ mov cl, [unshift.Green]
+ shl eax, cl
+ stosb
+
+ mov eax, [esi]
+ mov cl, [shift.Red]
+ shr eax, cl
+ and eax, [mask.Red]
+ mov cl, [unshift.Red]
+ shl eax, cl
+ stosb
+
+ mov eax, [esi]
+ mov cl, [shift.Alpha]
+ shr eax, cl
+ and eax, [mask.Alpha]
+ mov cl, [unshift.Alpha]
+ shl eax, cl
+ stosb
+
+ add esi, [delta]
+
+ pop ecx
+ dec ecx
+ jnz .next_pixel
+
+ sub esi, [dataoff]
+ add esi, 3
+ and esi, not 3
+ add esi, [dataoff]
+ pop ecx
+ dec ecx
+ jnz .next_line
+
+;;------------------------------------------------------------------------------------------------;;
+
+ .exit:
+ xor eax, eax
+ pop edi
+ ret
+
+ .error:
+ or eax, -1
+ pop edi
+ ret
+
+.calc_shift:
+ xor eax, eax
+ or ecx, ecx
+ jnz @f
+ retn
+ @@: test ecx, 1
+ jnz @f
+ .zz: shr ecx, 1
+ inc eax
+ jmp @b
+ @@: test ecx, 0100000000b
+ jnz .zz
+ retn
+.calc_unshift:
+ xor eax, eax
+ or ecx, ecx
+ jnz @f
+ retn
+ @@: test ecx, 1
+ jz @f
+ shr ecx, 1
+ inc eax
+ jmp @b
+ @@: sub eax, 8
+ neg eax
+ retn
+endp
+
+if 0
+;;================================================================================================;;
+proc img.decode.bmp._.jpeg ;//////////////////////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? --- TBD --- ;;
+;;------------------------------------------------------------------------------------------------;;
+;> ebx = raw image data ;;
+;> edx = image data ;;
+;;------------------------------------------------------------------------------------------------;;
+;< --- TBD --- ;;
+;;================================================================================================;;
+ xor eax, eax
+ ret
+endp
+
+;;================================================================================================;;
+proc img.decode.bmp._.png ;///////////////////////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? --- TBD --- ;;
+;;------------------------------------------------------------------------------------------------;;
+;> ebx = raw image data ;;
+;> edx = image data ;;
+;;------------------------------------------------------------------------------------------------;;
+;< --- TBD --- ;;
+;;================================================================================================;;
+ xor eax, eax
+ ret
+endp
+end if
+
+;;================================================================================================;;
+;;////////////////////////////////////////////////////////////////////////////////////////////////;;
+;;================================================================================================;;
+;! Below is private data you should never use directly from your code ;;
+;;================================================================================================;;
+;;////////////////////////////////////////////////////////////////////////////////////////////////;;
+;;================================================================================================;;
+
+
+;
diff --git a/programs/develop/libraries/libs-dev/libimg/bmp/bmp.inc b/programs/develop/libraries/libs-dev/libimg/bmp/bmp.inc
index 8776208c9..762e066df 100644
--- a/programs/develop/libraries/libs-dev/libimg/bmp/bmp.inc
+++ b/programs/develop/libraries/libs-dev/libimg/bmp/bmp.inc
@@ -1,107 +1,107 @@
-;;================================================================================================;;
-;;//// 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 ;;
-;; 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 bmp.FileHeader
- Type dw ? ; File type, always 4D42h ("BM")
- Size dd ? ; Size of the file in bytes
- dw 2 dup(?) ; Reserved; must be set to zero.
- OffBits dd ? ; Starting position of image data in bytes
-ends
-
-struct bmp.InfoHeader
-; v2 (Windows 2.x)
- Size dd ? ; Size of this header in bytes
- union
- struct ; new format
- Width dd ? ; Image width in pixels
- Height dd ? ; Image height in pixels
- Planes dw ? ; Number of color planes
- BitCount dw ? ; Number of bits per pixel
- ends
- struct ; old format
- OldWidth dw ? ; Image width in pixels as word
- OldHeight dw ? ; Image height in pixels as word
- OldPlanes dw ? ; Number of color planes
- OldBitCount dw ? ; Number of bits per pixel
- ends
- ends
-; v3 (Windows 3.x)
- Compression dd ? ; Compression method used
- SizeImage dd ? ; Size of bitmap in bytes
- XPelsPerMeter dd ? ; Horizontal resolution in pixels per meter
- YPelsPerMeter dd ? ; Vertical resolution in pixels per meter
- ClrUsed dd ? ; Number of colors in the image
- ClrImportant dd ? ; Minimum number of important colors
- union
- Palette dd ? ; Image palette if BitCount in [1,4,8]
-; v4 (Windows 95)
- struct
- RedMask dd ? ; Mask identifying bits of red component
- GreenMask dd ? ; Mask identifying bits of green component
- BlueMask dd ? ; Mask identifying bits of blue component
- AlphaMask dd ? ; Mask identifying bits of alpha component
- CSType dd ? ; Color space type
- RedX dd ? ; X coordinate of red endpoint
- RedY dd ? ; Y coordinate of red endpoint
- RedZ dd ? ; Z coordinate of red endpoint
- GreenX dd ? ; X coordinate of green endpoint
- GreenY dd ? ; Y coordinate of green endpoint
- GreenZ dd ? ; Z coordinate of green endpoint
- BlueX dd ? ; X coordinate of blue endpoint
- BlueY dd ? ; Y coordinate of blue endpoint
- BlueZ dd ? ; Z coordinate of blue endpoint
- GammaRed dd ? ; Gamma red coordinate scale value
- GammaGreen dd ? ; Gamma green coordinate scale value
- GammaBlue dd ? ; Gamma blue coordinate scale value
- ends
- ends
-ends
-
-define bmp.BI_RGB 0
-define bmp.BI_RLE8 1
-define bmp.BI_RLE4 2
-define bmp.BI_BITFIELDS 3
-define bmp.BI_JPEG 4
-define bmp.BI_PNG 5
-
-struct bmp.Header
- file bmp.FileHeader
- info bmp.InfoHeader
-ends
-
-struct bmp.RgbByteQuad
- Red db ?
- Green db ?
- Blue db ?
- Alpha db ?
-ends
-
-struct bmp.RgbQuad
- Red dd ?
- Green dd ?
- Blue dd ?
- Alpha dd ?
-ends
-
-;;------------------------------------------------------------------------------------------------;;
-
-struct bmp.Image
- info bmp.InfoHeader
-ends
+;;================================================================================================;;
+;;//// 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 ;;
+;; 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 bmp.FileHeader
+ Type dw ? ; File type, always 4D42h ("BM")
+ Size dd ? ; Size of the file in bytes
+ dw 2 dup(?) ; Reserved; must be set to zero.
+ OffBits dd ? ; Starting position of image data in bytes
+ends
+
+struct bmp.InfoHeader
+; v2 (Windows 2.x)
+ Size dd ? ; Size of this header in bytes
+ union
+ struct ; new format
+ Width dd ? ; Image width in pixels
+ Height dd ? ; Image height in pixels
+ Planes dw ? ; Number of color planes
+ BitCount dw ? ; Number of bits per pixel
+ ends
+ struct ; old format
+ OldWidth dw ? ; Image width in pixels as word
+ OldHeight dw ? ; Image height in pixels as word
+ OldPlanes dw ? ; Number of color planes
+ OldBitCount dw ? ; Number of bits per pixel
+ ends
+ ends
+; v3 (Windows 3.x)
+ Compression dd ? ; Compression method used
+ SizeImage dd ? ; Size of bitmap in bytes
+ XPelsPerMeter dd ? ; Horizontal resolution in pixels per meter
+ YPelsPerMeter dd ? ; Vertical resolution in pixels per meter
+ ClrUsed dd ? ; Number of colors in the image
+ ClrImportant dd ? ; Minimum number of important colors
+ union
+ Palette dd ? ; Image palette if BitCount in [1,4,8]
+; v4 (Windows 95)
+ struct
+ RedMask dd ? ; Mask identifying bits of red component
+ GreenMask dd ? ; Mask identifying bits of green component
+ BlueMask dd ? ; Mask identifying bits of blue component
+ AlphaMask dd ? ; Mask identifying bits of alpha component
+ CSType dd ? ; Color space type
+ RedX dd ? ; X coordinate of red endpoint
+ RedY dd ? ; Y coordinate of red endpoint
+ RedZ dd ? ; Z coordinate of red endpoint
+ GreenX dd ? ; X coordinate of green endpoint
+ GreenY dd ? ; Y coordinate of green endpoint
+ GreenZ dd ? ; Z coordinate of green endpoint
+ BlueX dd ? ; X coordinate of blue endpoint
+ BlueY dd ? ; Y coordinate of blue endpoint
+ BlueZ dd ? ; Z coordinate of blue endpoint
+ GammaRed dd ? ; Gamma red coordinate scale value
+ GammaGreen dd ? ; Gamma green coordinate scale value
+ GammaBlue dd ? ; Gamma blue coordinate scale value
+ ends
+ ends
+ends
+
+define bmp.BI_RGB 0
+define bmp.BI_RLE8 1
+define bmp.BI_RLE4 2
+define bmp.BI_BITFIELDS 3
+define bmp.BI_JPEG 4
+define bmp.BI_PNG 5
+
+struct bmp.Header
+ file bmp.FileHeader
+ info bmp.InfoHeader
+ends
+
+struct bmp.RgbByteQuad
+ Red db ?
+ Green db ?
+ Blue db ?
+ Alpha db ?
+ends
+
+struct bmp.RgbQuad
+ Red dd ?
+ Green dd ?
+ Blue dd ?
+ Alpha dd ?
+ends
+
+;;------------------------------------------------------------------------------------------------;;
+
+struct bmp.Image
+ info bmp.InfoHeader
+ends
diff --git a/programs/develop/libraries/libs-dev/libimg/gif/gif.asm b/programs/develop/libraries/libs-dev/libimg/gif/gif.asm
index dd01a68a6..7f868a43b 100644
--- a/programs/develop/libraries/libs-dev/libimg/gif/gif.asm
+++ b/programs/develop/libraries/libs-dev/libimg/gif/gif.asm
@@ -1,1583 +1,1583 @@
-;;================================================================================================;;
-;;//// gif.asm //// (c) mike.dld, 2007-2008 //////////////////////////////////////////////////////;;
-;;================================================================================================;;
-;;//// Partial (c) by Willow, Diamond and HidnPlayr //////////////////////////////////////////////;;
-;;================================================================================================;;
-;; ;;
-;; This file is part of Common development libraries (Libs-Dev). ;;
-;; ;;
-;; Libs-Dev is free software: you can redistribute it and/or modify it under the terms of the GNU ;;
-;; Lesser General Public License as published by the Free Software Foundation, either version 2.1 ;;
-;; of the License, or (at your option) any later version. ;;
-;; ;;
-;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without ;;
-;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;
-;; Lesser General Public License for more details. ;;
-;; ;;
-;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;;
-;; If not, see . ;;
-;; ;;
-;;================================================================================================;;
-;; ;;
-;; References: ;;
-;; 1. GIF LITE v3.0 (2004-2007) ;;
-;; by Willow and Diamond ;;
-;; svn://kolibrios.org/programs/media/gifview/trunk/gif_lite.inc ;;
-;; 2. "GIF File Format Summary" ;;
-;; from "Encyclopedia of Graphics File Formats" by O'Reilly ;;
-;; http://www.fileformat.info/format/gif/ ;;
-;; 3. "LZW and GIF explained" (1987) ;;
-;; by Steve Blackstock, IEEE ;;
-;; http://www.cis.udel.edu/~amer/CISC651/lzw.and.gif.explained.html ;;
-;; 4. "Graphics Interchange Format (tm)" (June 15, 1987) ;;
-;; by CompuServe Incorporated ;;
-;; http://examples.oreilly.de/english_examples/gff/CDROM/GFF/VENDSPEC/GIF/GIF87A.TXT ;;
-;; 5. "Graphics Interchange Format (sm)" (July 31, 1990) ;;
-;; by CompuServe Incorporated ;;
-;; http://examples.oreilly.de/english_examples/gff/CDROM/GFF/VENDSPEC/GIF/GIF89A.TXT ;;
-;; ;;
-;;================================================================================================;;
-
-
-include 'gif.inc'
-
-;;================================================================================================;;
-proc img.is.gif _data, _length ;//////////////////////////////////////////////////////////////////;;
-;;------------------------------------------------------------------------------------------------;;
-;? Determine if raw data could be decoded (is in GIF format) ;;
-;;------------------------------------------------------------------------------------------------;;
-;> _data = raw data as read from file/stream ;;
-;> _length = data length ;;
-;;------------------------------------------------------------------------------------------------;;
-;< eax = false / true ;;
-;;================================================================================================;;
- cmp [_length], sizeof.gif.Header
- jb .nope
- mov eax, [_data]
- cmp dword[eax], 'GIF8'
- jne .nope
- cmp word[eax + 4], '7a'
- je .yep
- cmp word[eax + 4], '9a'
- je .yep
-
- .nope:
- xor eax, eax
- ret
-
- .yep:
- xor eax, eax
- inc eax
- ret
-endp
-
-;;================================================================================================;;
-proc img.decode.gif _data, _length, _options ;////////////////////////////////////////////////////;;
-;;------------------------------------------------------------------------------------------------;;
-;? Decode data into image if it contains correctly formed raw data in GIF format ;;
-;;------------------------------------------------------------------------------------------------;;
-;> _data = raw data as read from file/stream ;;
-;> _length = data length ;;
-;;------------------------------------------------------------------------------------------------;;
-;< eax = 0 (error) or pointer to image ;;
-;;================================================================================================;;
-locals
- max_color dd ?
- cur_color_table_size dd ?
- transparent_color dd ?
- background_color dd ?
- options_bgr dd ?
- prev_palette dd ?
- aux_palette dd ?
- img dd ?
- prev_img_data dd ?
- aux_img_data dd ?
- aux_img_type dd ?
- prev_num_colors dd ?
- main_img dd ?
- global_color_table dd ?
- global_color_table_size dd ?
-endl
-
-img.decode.gif.main_img equ main_img
-img.decode.gif.prev_img_data equ prev_img_data
-img.decode.gif.transparent_color equ transparent_color
-img.decode.gif.background_color equ background_color
-img.decode.gif._length equ _length
-img.decode.gif.prev_num_colors equ prev_num_colors
-img.decode.gif.prev_palette equ prev_palette
-img.decode.gif.max_color equ max_color
-img.decode.gif._data equ _data
-img.decode.gif.aux_img_data equ aux_img_data
-img.decode.gif.aux_img_type equ aux_img_type
-img.decode.gif.aux_palette equ aux_palette
-img.decode.gif.options_bgr equ options_bgr
-; offset of _length parameter for child functions with ebp-based frame
-; child saved ebp, return address, 3 saved registers, 15 local variables
-img.decode.gif._length_child equ _length + 4 + 4 + 4*3 + 4*15
-img.decode.gif.max_color_child equ ebp + 4 + 4 + 4*3
-img.decode.gif.cur_color_table_size_child equ ebp + 4 + 4 + 4*3 + 4
-
- push ebx esi edi
- xor eax, eax
- mov [img], eax
- mov [main_img], eax
- mov [prev_img_data], eax
- mov [aux_img_data], eax
- mov [aux_img_type], eax
- mov [prev_palette], eax
- mov [aux_palette], eax
-; when no previous image is available, use background fill with 1-entry palette
- inc eax
- mov [prev_num_colors], eax
- lea eax, [background_color]
- mov [prev_palette], eax
-; value for bgr color in transparent images
- mov edx, 0xFFFFFF ; white bgr if no value given
- mov ecx, [_options]
- jecxz @f
- cmp [ecx + ImageDecodeOptions.UsedSize], ImageDecodeOptions.BackgroundColor + 4
- jb @f
- mov edx, [ecx + ImageDecodeOptions.BackgroundColor]
-@@:
- mov [options_bgr], edx
- mov dword [eax], edx
-; guard against incorrect gif files without any color tables
-; "If no color table is available at
-; all, the decoder is free to use a system color table or a table of its own. In
-; that case, the decoder may use a color table with as many colors as its
-; hardware is able to support; it is recommended that such a table have black and
-; white as its first two entries, so that monochrome images can be rendered
-; adequately." (c) official gif documentation
- mov [global_color_table], gif_default_palette
- mov [global_color_table_size], 2
-
-; img.is.gif is called by caller (img.decode)
-; stdcall img.is.gif, [_data], [_length]
-; or eax, eax
-; jz .error
-
- mov ebx, [_data]
- sub [_length], sizeof.gif.Header
-
- mov cl, [ebx + gif.Header.lsd.Packed]
- add ebx, sizeof.gif.Header
-; gif.LSD.Packed.GlobalColorTableFlag = 80h
-; test cl, gif.LSD.Packed.GlobalColorTableFlag
-; jz @f
- test cl, cl
- jns @f
- mov [global_color_table], ebx
- and cl, gif.LSD.Packed.SizeOfGlobalColorTableMask
-; shr cl, gif.LSD.Packed.SizeOfGlobalColorTableShift ; here Shift = 0
- push 2
- pop eax
- shl eax, cl
- mov [global_color_table_size], eax
- lea eax, [eax * 3]
- sub [_length], eax
- jbe .error ; there must be at least 1 additional byte after color table
- movzx ecx, byte [ebx - sizeof.gif.Header + gif.Header.lsd.BackgroundColor]
- lea ecx, [ecx*3]
- mov ecx, [ebx + ecx] ; eax = xxBBGGRR, convert to Kolibri color
- bswap ecx
- shr ecx, 8
- mov [background_color], ecx
- add ebx, eax
- @@:
-
-; @@: cmp byte[ebx + gif.Block.Introducer], gif.Block.Introducer.Extension
-; jne .next_image
-; cmp byte[ebx + gif.Extension.Label], gif.Extension.Label.Comment
-; jne .error
-; add ebx, sizeof.gif.Extension
-; stdcall ._.skip_data
-; mov ebx, eax
-; jmp @b
-
- .next_image:
- stdcall img._.new
- or eax, eax
- jz .error
- mov edx, [img]
- mov [eax + Image.Previous], edx
- push sizeof.gif.LogicalScreenDescriptor
- pop ecx
- test edx, edx
- jz @f
- mov [edx + Image.Next], eax
- xor ecx, ecx
- @@:
- push eax
- mov [eax + Image.Type], Image.bpp8i
-
- add ecx, sizeof.gif.Image
- invoke mem.alloc, ecx
- pop edx
- or eax, eax
- jz .error2
- mov [edx + Image.Extended], eax
- xor ecx, ecx
- cmp [img], ecx
- jnz @f
- mov esi, [_data]
- add esi, gif.Header.lsd
- lea edi, [eax + sizeof.gif.Image]
- mov cl, sizeof.gif.LogicalScreenDescriptor
- rep movsb
- mov [main_img], edx
- @@:
- mov [img], edx
-
- stdcall ._.process_extensions
-
- cmp al, gif.Block.Introducer.ImageDescriptor
- jne .error
- sub [_length], sizeof.gif.ImageDescriptor
- jc .error
- movzx eax, [ebx + gif.ImageDescriptor.Width]
- movzx ecx, [ebx + gif.ImageDescriptor.Height]
- push edx
- stdcall img._.resize_data, [img], eax, ecx
- pop edx
- or eax, eax
- jz .error
-
- 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
-; here Shift = 0
-; shr cl, gif.ID.Packed.SizeOfLocalColorTableShift
- push 2
- pop eax
- shl eax, cl
- mov ecx, eax
- lea eax, [eax*3]
- add ebx, eax
- sub [_length], eax
- jbe .error ; because we load additional byte, check is 'jbe', not 'jc'
-@@:
- mov [cur_color_table_size], ecx
- dec [cur_color_table_size]
-@@:
- lodsd
- dec esi
- bswap eax
- shr eax, 8
- stosd
- loop @b
- add ebx, sizeof.gif.ImageDescriptor
- stdcall ._.process_image
- push ebx
- mov edx, [img]
- push edx
- stdcall ._.superimpose
- pop edx
- push edx
- stdcall ._.dispose
- pop edx
- mov edx, [edx + Image.Previous]
- test edx, edx
- jz .nofreeprev
- mov ebx, [edx + Image.Extended]
- cmp [edx + Image.Delay], 0
- jnz .nofreeprev
- mov esi, [prev_palette]
- cmp esi, [edx + Image.Palette]
- jnz @f
- mov ecx, [prev_num_colors]
- stdcall ._.alloc_aux_palette
- test eax, eax
- jz .nofreeprev
- mov [prev_palette], eax
- @@:
- mov esi, [prev_img_data]
- cmp esi, [edx + Image.Data]
- jnz .noprevdata
- push 1
- pop eax
- cmp [edx + Image.Type], Image.bpp8i
- jz @f
- mov al, 3
- @@:
- cmp [aux_img_type], eax
- jb .resetaux
- mov edi, [aux_img_data]
- imul eax, [edx + Image.Width]
- imul eax, [edx + Image.Height]
- xchg eax, ecx
- rep movsb
- jmp .noprevdata
- .resetaux:
- mov [aux_img_type], eax
- mov eax, [aux_img_data]
- test eax, eax
- jz @f
- invoke mem.free, eax
- @@:
- xor eax, eax
- xchg eax, [edx + Image.Data]
- mov [aux_img_data], eax
- .noprevdata:
- cmp edx, [main_img]
- jnz @f
- mov eax, [edx + Image.Next]
- mov [main_img], eax
- mov esi, [eax + Image.Extended]
- mov edi, [edx + Image.Extended]
- mov [edx + Image.Extended], esi
- mov [eax + Image.Extended], edi
- push sizeof.gif.Image
- pop ecx
- rep movsb
- @@:
- stdcall img.destroy.layer, edx
- .nofreeprev:
- pop ebx
- test ebx, ebx
- jz .ret
- jmp .next_image
-
- .error2:
- mov [img], edx
-
- .error:
- mov eax, [img]
- test eax, eax
- jz .ret
- cmp [main_img], eax
- jnz @f
- and [main_img], 0
- @@:
- stdcall img.destroy.layer, eax
- .ret:
- mov eax, [aux_img_data]
- test eax, eax
- jz @f
- invoke mem.free, eax
- @@:
- mov eax, [aux_palette]
- test eax, eax
- jz @f
- invoke mem.free, eax
- @@:
- mov eax, [main_img]
- cmp [eax + Image.Next], 0
- jz @f
- or [eax + Image.Flags], Image.IsAnimated
- @@:
- pop edi esi ebx
- ret
-endp
-
-;;================================================================================================;;
-proc img.encode.gif _img, _p_length ;/////////////////////////////////////////////////////////////;;
-;;------------------------------------------------------------------------------------------------;;
-;? Encode image into raw data in GIF format ;;
-;;------------------------------------------------------------------------------------------------;;
-;> _img = pointer to image ;;
-;;------------------------------------------------------------------------------------------------;;
-;< eax = 0 (error) or pointer to encoded data ;;
-;< _p_length = encoded data length ;;
-;;================================================================================================;;
- xor eax, eax
- ret
-endp
-
-
-;;================================================================================================;;
-;;////////////////////////////////////////////////////////////////////////////////////////////////;;
-;;================================================================================================;;
-;! Below are private procs you should never call directly from your code ;;
-;;================================================================================================;;
-;;////////////////////////////////////////////////////////////////////////////////////////////////;;
-;;================================================================================================;;
-
-
-;;================================================================================================;;
-proc img.decode.gif._.process_extensions ;////////////////////////////////////////////////////////;;
-;;------------------------------------------------------------------------------------------------;;
-;? --- TBD --- ;;
-;;------------------------------------------------------------------------------------------------;;
-;> ebx = raw image data ;;
-;> edx = image data ;;
-;;------------------------------------------------------------------------------------------------;;
-;< --- TBD --- ;;
-;;================================================================================================;;
- mov esi, ebx
- xor eax, eax
- mov [edx + Image.Delay], eax
-
- .next_block:
- dec [img.decode.gif._length]
- js .exit_err
- lodsb ; load gif.Block.Introducer
- cmp al, gif.Block.Introducer.Extension
- jne .exit
-
- .ext_block:
- dec [img.decode.gif._length]
- js .exit_err
- lodsb ; load gif.Extension.Label
- cmp al, gif.Extension.Label.GraphicsControl
- je .graphics_control_ext
-; cmp al, gif.Extension.Label.PlainText
-; je .plain_text_ext
-; cmp al, gif.Extension.Label.Comment
-; je .comment_ext
-; cmp al, gif.Extension.Label.Application
-; je .application_ext
-; skip all other extensions
- .skip_ext:
- dec [img.decode.gif._length]
- js .exit_err
- lodsb ; load BlockSize
- .1:
- test al, al
- jz .next_block
- sub [img.decode.gif._length], eax
- jc .exit_err
- add esi, eax
- jmp .skip_ext
-
- .graphics_control_ext:
- dec [img.decode.gif._length]
- js .exit_err
- lodsb ; load BlockSize; must be sizeof.gif.GraphicsControlExtension
- cmp al, sizeof.gif.GraphicsControlExtension
- jnz .1
- sub [img.decode.gif._length], eax
- jc .exit_err
- push edi
- movzx edi, [esi + gif.GraphicsControlExtension.DelayTime]
- mov [edx + Image.Delay], edi
- mov edi, [edx + Image.Extended]
- add edi, gif.Image.gce
- mov ecx, eax
- rep movsb
- pop edi
- jmp .skip_ext
-
- .exit_err:
- xor eax, eax
-
- .exit:
- mov ebx, esi
- ret
-endp
-
-;;================================================================================================;;
-proc img.decode.gif._.process_image ;/////////////////////////////////////////////////////////////;;
-;;------------------------------------------------------------------------------------------------;;
-;? --- TBD --- ;;
-;;------------------------------------------------------------------------------------------------;;
-;> ebx = raw image data ;;
-;> edx = image data ;;
-;;------------------------------------------------------------------------------------------------;;
-;< --- TBD --- ;;
-;;================================================================================================;;
-locals
- width dd ?
- img_start dd ?
- img_end dd ?
- row_end dd ?
- pass dd ?
- codesize dd ?
- compsize dd ?
- workarea dd ?
- block_ofs dd ?
- bit_count dd ?
- CC dd ?
- EOI dd ?
-endl
-
- invoke mem.alloc, 16 * 1024
- mov [workarea], eax
- or eax, eax
- jz .error
-
- mov ecx, [edx + Image.Width]
- mov [width], ecx
- mov eax, [edx + Image.Height]
- imul eax, ecx
- mov [img_end], eax
- inc eax
- mov [row_end], eax
- and [pass], 0
- and dword [img.decode.gif.max_color_child], 0
- mov eax, [edx + Image.Extended]
- test [eax + gif.Image.info.Packed], gif.ID.Packed.InterleaceFlag
- jz @f
- mov [row_end], ecx
-
- @@: mov esi, ebx
- mov edi, [edx + Image.Data]
-
- sub dword [img.decode.gif._length_child], 2
- jc .error
- movzx ecx, byte[esi]
- inc esi
- cmp cl, 12
- jae .error
- mov [codesize], ecx
- inc [codesize]
- xor eax, eax
- lodsb ; eax - block_count
- sub [img.decode.gif._length_child], eax
- jc .error
- add eax, esi
- push edi
- mov edi, [workarea]
- mov [block_ofs], eax
- mov [bit_count], 8
- mov eax, 1
- shl eax, cl
- mov [CC], eax
- mov ecx, eax
- inc eax
- mov [EOI], eax
- mov eax, gif.Null shl 16
- .filltable:
- stosd
- inc eax
- loop .filltable
- pop edi
- mov [img_start], edi
- add [img_end], edi
- add [row_end], edi
- .reinit:
- mov edx, [EOI]
- inc edx
- push [codesize]
- pop [compsize]
- call .get_symbol
- cmp eax, [CC]
- je .reinit
- call .output
- .cycle:
- movzx ebx, ax
- call .get_symbol
- cmp eax, [EOI]
- je .end
- cmp eax, edx
- ja .error
- je .notintable
- cmp eax, [CC]
- je .reinit
- call .output
- .add:
- cmp edx, 0x00001000
- jae .cycle
- mov ecx, [workarea]
- mov [ecx + edx * 4], ebx
- inc edx
- cmp edx, 0x1000
- je .noinc
- bsr ebx, edx
- cmp ebx, [compsize]
- jne .noinc
- inc [compsize]
- .noinc:
- jmp .cycle
- .notintable:
- push eax
- mov eax, ebx
- call .output
- push ebx
- movzx eax, bx
- call .output
- pop ebx eax
- jmp .add
- .end:
- mov edi, [img_end]
- xor eax, eax
-
- .exit:
- cmp [workarea], 0
- je @f
- invoke mem.free, [workarea]
- @@:
- mov ebx, [block_ofs]
- @@:
- dec [img.decode.gif._length_child]
- js @f
- movzx eax, byte [ebx]
- inc ebx
- test eax, eax
- jz .ret
- sub [img.decode.gif._length_child], eax
- jc @f
- add ebx, eax
- jmp @b
-
- .error:
- cmp [workarea], 0
- je @f
- invoke mem.free, [workarea]
- @@: xor ebx, ebx
- .ret:
- ret
-
-;;------------------------------------------------------------------------------------------------;;
-
-img.decode.gif._.process_image.get_symbol:
- mov ecx, [compsize]
- push ecx
- xor eax, eax
-
- .shift:
- dec [bit_count]
- jns .loop1
- inc esi
- cmp esi, [block_ofs]
- jb .noblock
- push eax
- xor eax, eax
- sub [img.decode.gif._length_child], 1
- jc .error_eof
- lodsb
- test eax, eax
- jnz .nextbl
- .error_eof:
- add esp, 12
- jmp img.decode.gif._.process_image.error
-
- .nextbl:
- sub [img.decode.gif._length_child], eax
- jc .error_eof
- add eax, esi
- mov [block_ofs], eax
- pop eax
-
- .noblock:
- mov [bit_count], 7
-
- .loop1:
- ror byte[esi], 1
- rcr eax,1
- loop .shift
- pop ecx
- rol eax, cl
-
- .exit:
- xor ecx, ecx
- retn
-
-;;------------------------------------------------------------------------------------------------;;
-
-img.decode.gif._.process_image.output:
- push esi eax edx
- mov edx, [workarea]
-
- .next:
- pushw [edx + eax * 4]
- mov ax, [edx + eax * 4 + 2]
- inc ecx
- cmp ax, gif.Null
- jnz .next
- shl ebx, 16
- mov bx, [esp]
-
- .loop2:
- pop ax
- cmp al, byte [img.decode.gif.cur_color_table_size_child]
- jbe @f ; guard against incorrect GIFs
- mov al, 0
- @@: cmp al, byte [img.decode.gif.max_color_child]
- jbe @f
- mov [img.decode.gif.max_color_child], al
- @@: stosb
-
- cmp edi, [row_end]
- jb .norowend
- mov eax, [width]
- push eax
- sub edi, eax
- add eax, eax
- cmp [pass], 3
- je @f
- add eax, eax
- cmp [pass], 2
- je @f
- add eax, eax
- @@: add edi, eax
- pop eax
- cmp edi, [img_end]
- jb .nextrow
- mov edi, [img_start]
- inc [pass]
- cmp [pass], 4
- je .done
- add edi, eax
- cmp [pass], 3
- je @f
- add edi, eax
- cmp [pass], 2
- je @f
- add edi, eax
- add edi, eax
- @@:
-
- .nextrow:
- add eax, edi
- mov [row_end], eax
- xor eax, eax
-
- .norowend:
- cmp edi, [img_end]
- jz .done
- loop .loop2
- pop edx eax esi
- retn
-
- .done:
- lea esp, [esp+(ecx-1)*2]
- pop edx eax esi eax
- jmp img.decode.gif._.process_image.exit
-
-endp
-
-;;================================================================================================;;
-proc img.decode.gif._.is_logical_screen ;/////////////////////////////////////////////////////////;;
-;;------------------------------------------------------------------------------------------------;;
-;? Determines whether GIF image occupies the whole logical screen ;;
-;;------------------------------------------------------------------------------------------------;;
-;> eax = extended image data ;;
-;> ebx = main image ;;
-;;------------------------------------------------------------------------------------------------;;
-;< ZF set <=> image area equals logical screen ;;
-;;================================================================================================;;
- mov ebx, [ebx + Image.Extended]
- cmp [eax + gif.Image.info.Left], 0
- jnz @f
- cmp [eax + gif.Image.info.Top], 0
- jnz @f
- mov cx, [eax + gif.Image.info.Width]
- cmp cx, [ebx + sizeof.gif.Image + gif.LogicalScreenDescriptor.ScreenWidth]
- jnz @f
- mov cx, [eax + gif.Image.info.Height]
- cmp cx, [ebx + sizeof.gif.Image + gif.LogicalScreenDescriptor.ScreenHeight]
-@@: retn
-endp
-
-main_img equ img.decode.gif.main_img
-transparent_color equ img.decode.gif.transparent_color
-background_color equ img.decode.gif.background_color
-prev_num_colors equ img.decode.gif.prev_num_colors
-prev_palette equ img.decode.gif.prev_palette
-max_color equ img.decode.gif.max_color
-prev_img_data equ img.decode.gif.prev_img_data
-_data equ img.decode.gif._data
-aux_img_data equ img.decode.gif.aux_img_data
-aux_img_type equ img.decode.gif.aux_img_type
-aux_palette equ img.decode.gif.aux_palette
-
-;;================================================================================================;;
-proc img.decode.gif._.superimpose ;///////////////////////////////////////////////////////////////;;
-;;------------------------------------------------------------------------------------------------;;
-;? --- TBD --- ;;
-;;------------------------------------------------------------------------------------------------;;
-;> edx = image data ;;
-;;------------------------------------------------------------------------------------------------;;
-;< --- TBD --- ;;
-;;================================================================================================;;
- mov ebx, [main_img]
- mov eax, [edx + Image.Extended]
- or [transparent_color], -1 ; no transparent color
- test byte [eax + gif.Image.gce.Packed], 1
- jz @f
- movzx ecx, byte [eax + gif.Image.gce.ColorIndex]
- mov [transparent_color], ecx
- cmp edx, ebx
- jnz .has_transparency
- shl ecx, 2
- add ecx, [edx + Image.Palette]
- push eax
- mov eax, [img.decode.gif.options_bgr]
- mov dword [background_color], eax
- mov dword [ecx], eax
- pop eax
-@@:
- call img.decode.gif._.is_logical_screen
- jnz .has_transparency
-; image is not transparent, so keep it as is
- retn
-
-.has_transparency:
-; image has transparent areas, we must superimpose it on the previous
- mov ecx, [prev_num_colors]
- cmp ecx, 0x100
- ja .superimpose_on_rgb
-; create common palette
- sub esp, 3FCh
- push eax
- mov edi, esp
- push ecx
- mov esi, [prev_palette]
- rep movsd
- pop ecx
- mov esi, [edx + Image.Palette]
- xor ebx, ebx
- mov edi, esp
- sub esp, 100h
-.create_palette_loop:
- push ecx
- lodsd
- cmp ebx, [transparent_color]
- jz .nochange
- cmp ebx, ecx
- jae @f
- cmp eax, [edi+ebx*4]
- jz .nochange
-@@:
- push edi
- repnz scasd
- pop edi
- jnz .increase_palette
- sub ecx, [esp]
- not ecx ; cl = index of new color in current palette
- jmp .palette_common
-.increase_palette:
- mov ecx, [esp]
- test ch, ch
- jnz .output_to_rgb
- inc dword [esp]
- mov [edi+ecx*4], eax
- jmp .palette_common
-.nochange:
- mov ecx, ebx
-.palette_common:
- mov [ebx+esp+4], cl
- pop ecx
- inc ebx
- cmp ebx, [max_color]
- jbe .create_palette_loop
- mov [max_color], ecx
-; if image occupies only part of logical screen, allocate memory for full logical screen
- mov ebx, [main_img]
- mov eax, [edx + Image.Extended]
- mov esi, [edx + Image.Data]
- call img.decode.gif._.is_logical_screen
- jz @f
- and [edx + Image.Data], 0
- push edx
- movzx eax, [ebx + sizeof.gif.Image + gif.LogicalScreenDescriptor.ScreenHeight]
- push eax
- movzx eax, [ebx + sizeof.gif.Image + gif.LogicalScreenDescriptor.ScreenWidth]
- stdcall img._.resize_data, edx, eax
- pop edx
- test eax, eax
- jz .palette_nomem
-@@:
-; copy final palette to Image.Palette
- push esi esi
- mov esi, edi
- mov edi, [edx + Image.Palette]
- mov ecx, [max_color]
- dec [max_color]
- rep movsd
- mov esi, [prev_img_data]
- mov edi, [edx + Image.Data]
-; do superimpose, [esp] -> source data, esi -> prev image data
-; (NULL if previous image is filled with background color), esp+8 -> correspondence between
-; used palette and final palette, edi -> destination data
- mov ebx, [edx + Image.Extended]
-; first Top rows are copied from [prev_img_data] or filled with bgr
- movzx ecx, [ebx + gif.Image.info.Top]
- cmp ecx, [edx + Image.Height]
- jb @f
- mov ecx, [edx + Image.Height]
-@@:
- push ecx
- imul ecx, [edx + Image.Width]
- call .rep_movsb_or_stosb
- pop ecx
-; convert rows
- sub ecx, [edx + Image.Height]
- neg ecx
- push ecx
- cmp cx, [ebx + gif.Image.info.Height]
- jbe @f
- mov cx, [ebx + gif.Image.info.Height]
-@@:
- jecxz .norows
-.convert_rows:
- push ecx
- movzx ecx, [ebx + gif.Image.info.Left]
- cmp ecx, [edx + Image.Width]
- jb @f
- mov ecx, [edx + Image.Width]
-@@:
- push ecx
- call .rep_movsb_or_stosb
- pop ecx
- sub ecx, [edx + Image.Width]
- neg ecx
- push ecx edx
- mov edx, [esp+16] ; source data
- cmp cx, [ebx + gif.Image.info.Width]
- jbe @f
- mov cx, [ebx + gif.Image.info.Width]
-@@:
- jecxz .norowsi
-.rowsloop:
- movzx eax, byte [edx]
- inc edx
- cmp eax, [transparent_color]
- jz .rows_transparent
- mov al, [eax+esp+24]
- stosb
- call .lodsb
- jmp @f
-.rows_transparent:
- call .lodsb
- stosb
-@@:
- loop .rowsloop
-.norowsi:
- pop edx ecx
- sub cx, [ebx + gif.Image.info.Width]
- jbe @f
- call .rep_movsb_or_stosb
-@@:
- movzx eax, [ebx + gif.Image.info.Width]
- add [esp+8], eax
- pop ecx
- loop .convert_rows
-.norows:
- pop ecx
- sub cx, [ebx + gif.Image.info.Height]
- jbe @f
- imul ecx, [edx + Image.Width]
- call .rep_movsb_or_stosb
-@@:
-; free old image data if we have allocated new copy
- pop esi esi
- cmp esi, [edx + Image.Data]
- jz @f
- invoke mem.free, esi
-@@:
-; cleanup stack and return
- add esp, 500h
- retn
-.palette_nomem:
- mov [edx + Image.Data], esi
- jmp @b
-
-.output_to_rgb:
- pop ecx
- add esp, 500h
-; compose two palette-based images to one RGB image
- xor esi, esi
- xchg esi, [edx + Image.Data]
- push esi
- mov ebx, [_data]
- push [edx + Image.Palette]
- mov byte [edx + Image.Type], Image.bpp24
- push edx
- movzx eax, [ebx + gif.Header.lsd.ScreenHeight]
- push eax
- movzx eax, [ebx + gif.Header.lsd.ScreenWidth]
- stdcall img._.resize_data, edx, eax
- pop edx
- test eax, eax
- jz .convrgb_nomem
- push esi
- mov edi, [edx + Image.Data]
- mov esi, [prev_img_data]
- mov ebx, [edx + Image.Extended]
-; first Top rows are copied from [prev_img_data] or filled with bgr
- movzx ecx, [ebx + gif.Image.info.Top]
- cmp ecx, [edx + Image.Height]
- jb @f
- mov ecx, [edx + Image.Height]
-@@:
- push ecx
- imul ecx, [edx + Image.Width]
- call .convrgb_prev
- pop ecx
-; convert rows
- sub ecx, [edx + Image.Height]
- neg ecx
- push ecx
- cmp cx, [ebx + gif.Image.info.Height]
- jbe @f
- mov cx, [ebx + gif.Image.info.Height]
-@@:
- jecxz .convrgb_norows
-.convrgb_convert_rows:
- push ecx
- movzx ecx, [ebx + gif.Image.info.Left]
- cmp ecx, [edx + Image.Width]
- jb @f
- mov ecx, [edx + Image.Width]
-@@:
- push ecx
- call .convrgb_prev
- pop ecx
- sub ecx, [edx + Image.Width]
- neg ecx
- push ecx edx
- mov edx, [esp+16] ; source data
- cmp cx, [ebx + gif.Image.info.Width]
- jbe @f
- mov cx, [ebx + gif.Image.info.Width]
-@@:
- jecxz .convrgb_norowsi
-.convrgb_rowsloop:
- movzx eax, byte [edx]
- inc edx
- cmp eax, [transparent_color]
- jz .convrgb_rows_transparent
- shl eax, 2
- add eax, [esp+20] ; source palette
- mov eax, [eax]
- stosw
- shr eax, 16
- stosb
- call .convrgb_lodsb
- jmp @f
-.convrgb_rows_transparent:
- call .convrgb_lodsb
- stosw
- shr eax, 16
- stosb
-@@:
- loop .convrgb_rowsloop
-.convrgb_norowsi:
- pop edx ecx
- sub cx, [ebx + gif.Image.info.Width]
- jbe @f
- call .convrgb_prev
-@@:
- movzx eax, [ebx + gif.Image.info.Width]
- add [esp+8], eax
- pop ecx
- loop .convrgb_convert_rows
-.convrgb_norows:
- pop ecx
- sub cx, [ebx + gif.Image.info.Height]
- jbe @f
- imul ecx, [edx + Image.Width]
- call .convrgb_prev
-@@:
-; free old image data
- pop esi esi ;esi
- invoke mem.free;, esi
- retn
-.convrgb_nomem:
- pop esi esi
- retn
-
-.superimpose_on_rgb:
-; previous image is RGB, new image has transparent areas
- xor esi, esi
- xchg esi, [edx + Image.Data]
- push esi
- mov ebx, [_data]
- push [edx + Image.Palette]
- mov byte [edx + Image.Type], Image.bpp24
- push edx
- movzx eax, [ebx + gif.Header.lsd.ScreenHeight]
- push eax
- movzx eax, [ebx + gif.Header.lsd.ScreenWidth]
- stdcall img._.resize_data, edx, eax
- pop edx
- test eax, eax
- jz .rgb_nomem
- push esi
- mov edi, [edx + Image.Data]
- mov esi, [prev_img_data]
- mov ebx, [edx + Image.Extended]
-; first Top rows are copied from [prev_img_data] or filled with bgr
- movzx ecx, [ebx + gif.Image.info.Top]
- cmp ecx, [edx + Image.Height]
- jb @f
- mov ecx, [edx + Image.Height]
-@@:
- push ecx
- lea ecx, [ecx*3]
- imul ecx, [edx + Image.Width]
- rep movsb
- pop ecx
-; convert rows
- sub ecx, [edx + Image.Height]
- neg ecx
- push ecx
- cmp cx, [ebx + gif.Image.info.Height]
- jbe @f
- mov cx, [ebx + gif.Image.info.Height]
-@@:
- jecxz .rgb_norows
-.rgb_convert_rows:
- push ecx
- movzx ecx, [ebx + gif.Image.info.Left]
- cmp ecx, [edx + Image.Width]
- jb @f
- mov ecx, [edx + Image.Width]
-@@:
- push ecx
- lea ecx, [ecx*3]
- rep movsb
- pop ecx
- sub ecx, [edx + Image.Width]
- neg ecx
- push ecx edx
- mov edx, [esp+16] ; source data
- cmp cx, [ebx + gif.Image.info.Width]
- jbe @f
- mov cx, [ebx + gif.Image.info.Width]
-@@:
- jecxz .rgb_norowsi
-.rgb_rowsloop:
- movzx eax, byte [edx]
- inc edx
- cmp eax, [transparent_color]
- jz .rgb_rows_transparent
- shl eax, 2
- add eax, [esp+20] ; source palette
- mov eax, [eax]
- stosw
- shr eax, 16
- stosb
- add esi, 3
- jmp @f
-.rgb_rows_transparent:
- movsb
- movsb
- movsb
-@@:
- loop .rgb_rowsloop
-.rgb_norowsi:
- pop edx ecx
- sub cx, [ebx + gif.Image.info.Width]
- jbe @f
- lea ecx, [ecx*3]
- rep movsb
-@@:
- movzx eax, [ebx + gif.Image.info.Width]
- add [esp+8], eax
- pop ecx
- loop .rgb_convert_rows
-.rgb_norows:
- pop ecx
- sub cx, [ebx + gif.Image.info.Height]
- jbe @f
- imul ecx, [edx + Image.Width]
- lea ecx, [ecx*3]
- rep movsb
-@@:
-; free old image data
- pop esi esi ;esi
- invoke mem.free;, esi
- retn
-.rgb_nomem:
- pop esi esi
- retn
-
-.lodsb:
- xor eax, eax
- test esi, esi
- jz @f
- lodsb
-@@: retn
-
-.rep_movsb_or_stosb:
- test esi, esi
- jz .rmos1
- rep movsb
- jmp .rmos2
-.rmos1: xor eax, eax ; background index in final palette is 0 in bgr mode
- rep stosb
-.rmos2: retn
-
-.convrgb_prev:
- jecxz .convrgb_noprev
- test esi, esi
- jz .convrgb_prev_bgr
-@@:
- xor eax, eax
- lodsb
- shl eax, 2
- add eax, [prev_palette]
- mov eax, [eax]
- stosw
- shr eax, 16
- stosb
- loop @b
- retn
-.convrgb_prev_bgr:
-@@:
- mov eax, [background_color]
- stosw
- shr eax, 16
- stosb
- loop @b
-.convrgb_noprev:
- retn
-.convrgb_lodsb:
- xor eax, eax
- test esi, esi
- jz @f
- lodsb
- shl eax, 2
- add eax, [prev_palette]
- mov eax, [eax]
- retn
-@@: mov eax, [background_color]
- retn
-
-endp
-
-;;================================================================================================;;
-proc img.decode.gif._.dispose ;///////////////////////////////////////////////////////////////////;;
-;;------------------------------------------------------------------------------------------------;;
-;? --- TBD --- ;;
-;;------------------------------------------------------------------------------------------------;;
-;> edx = image data ;;
-;;------------------------------------------------------------------------------------------------;;
-;< --- TBD --- ;;
-;;================================================================================================;;
- mov ebx, [edx + Image.Extended]
- mov al, [ebx + gif.Image.gce.Packed]
- shr al, 2
- and al, 7
- cmp al, 2
- jz .background
- cmp al, 3
- jz .previous
-; don't dispose - set prev_img and related vars to current image
- mov eax, [edx + Image.Data]
- mov [prev_img_data], eax
- cmp [edx + Image.Type], Image.bpp8i
- jnz @f
- mov eax, [max_color]
- inc eax
- mov [prev_num_colors], eax
- mov eax, [edx + Image.Palette]
- mov [prev_palette], eax
- retn
-@@:
- or [prev_num_colors], -1
- and [prev_palette], 0
-.previous:
- retn
-.background:
- cmp [prev_img_data], 0
- jz .bgr_full
- mov ebx, [main_img]
- mov eax, [edx + Image.Extended]
- call img.decode.gif._.is_logical_screen
- jnz @f
-.bgr_full:
- xor eax, eax
- mov [prev_img_data], eax
- inc eax
- mov [prev_num_colors], eax
- lea eax, [background_color]
- mov [prev_palette], eax
- retn
-@@:
- cmp [prev_num_colors], 0x100
- ja .rgb
- mov eax, [background_color]
- mov edi, [prev_palette]
- mov ecx, [prev_num_colors]
- repnz scasd
- jz .palette_ok
- cmp [prev_num_colors], 0x100
- jz .convert_rgb
- push 1
- pop eax
- stdcall img.decode.gif._.alloc_aux_img
- test eax, eax
- jz .previous
- mov ecx, [prev_num_colors]
- mov esi, [prev_palette]
- call img.decode.gif._.alloc_aux_palette
- test eax, eax
- jz .previous
- mov [prev_palette], eax
- mov eax, [background_color]
- stosd
- mov eax, [prev_num_colors] ; eax = index of background color
- inc [prev_num_colors]
- jmp .bpp8_common
-.palette_ok:
- push 1
- pop eax
- stdcall img.decode.gif._.alloc_aux_img
- test eax, eax
- jz .previous
- sub edi, [prev_palette]
- shr edi, 2
- lea eax, [edi-1] ; eax = index of background color
-.bpp8_common:
- push eax
- mov ebx, [_data]
- mov esi, [prev_img_data]
- mov edi, [aux_img_data]
- mov [prev_img_data], edi
- cmp esi, edi
- jz @f
- movzx ecx, [ebx + gif.Header.lsd.ScreenWidth]
- movzx eax, [ebx + gif.Header.lsd.ScreenHeight]
- imul ecx, eax
- push edi
- rep movsb
- pop edi
-@@:
- movzx esi, [ebx + gif.Header.lsd.ScreenHeight]
- movzx eax, [ebx + gif.Header.lsd.ScreenWidth]
- mov edx, [edx + Image.Extended]
- movzx ecx, [edx + gif.Image.info.Top]
- sub esi, ecx
- jbe .bpp8_ret
- imul ecx, eax
- add edi, ecx
- cmp si, [edx + gif.Image.info.Height]
- jb @f
- mov si, [edx + gif.Image.info.Height]
-@@:
- movzx ecx, [edx + gif.Image.info.Left]
- sub eax, ecx
- jbe .bpp8_ret
- add edi, ecx
- cmp ax, [edx + gif.Image.info.Width]
- jb @f
- mov ax, [edx + gif.Image.info.Width]
-@@:
- xchg eax, ecx
- movzx edx, [ebx + gif.Header.lsd.ScreenWidth]
- sub edx, ecx
- pop eax
-@@:
- push ecx
- rep stosb
- pop ecx
- add edi, edx
- dec esi
- jnz @b
- push eax
-.bpp8_ret:
- pop eax
- retn
-.convert_rgb:
- push 3
- pop eax
- stdcall img.decode.gif._.alloc_aux_img
- test eax, eax
- jz .previous
- or [prev_num_colors], -1
- mov ebx, [_data]
- mov esi, [prev_img_data]
- mov edi, [aux_img_data]
- mov [prev_img_data], edi
- movzx ecx, [ebx + gif.Header.lsd.ScreenWidth]
- movzx eax, [ebx + gif.Header.lsd.ScreenHeight]
- imul ecx, eax
- push edx
- xor edx, edx
- xchg edx, [prev_palette]
- add edi, ecx
- add esi, ecx
- add edi, ecx
- add edi, ecx
-@@:
- dec esi
- movzx eax, byte [esi]
- mov eax, [eax*4+edx]
- sub edi, 3
- mov [edi], ax
- shr eax, 16
- mov [edi+2], al
- loop @b
- pop edx
- movzx esi, [ebx + gif.Header.lsd.ScreenHeight]
- movzx eax, [ebx + gif.Header.lsd.ScreenWidth]
- mov edx, [edx + Image.Extended]
- movzx ecx, [edx + gif.Image.info.Top]
- sub esi, ecx
- jbe .convert_rgb_ret
- imul ecx, eax
- lea ecx, [ecx*3]
- add edi, ecx
- cmp si, [edx + gif.Image.info.Height]
- jb @f
- mov si, [edx + gif.Image.info.Height]
-@@:
- movzx ecx, [edx + gif.Image.info.Left]
- sub eax, ecx
- jbe .convert_rgb_ret
- lea ecx, [ecx*3]
- add edi, ecx
- cmp ax, [edx + gif.Image.info.Width]
- jb @f
- mov ax, [edx + gif.Image.info.Width]
-@@:
- xchg eax, ecx
- movzx edx, [ebx + gif.Header.lsd.ScreenWidth]
- sub edx, ecx
- mov eax, [background_color]
- lea edx, [edx*3]
-.convert_rgb_loop:
- push ecx
-@@:
- stosw
- shr eax, 16
- stosb
- loop @b
- pop ecx
- add edi, edx
- dec esi
- jnz .convert_rgb_loop
-.convert_rgb_ret:
- retn
-.rgb:
- push 3
- pop eax
- stdcall img.decode.gif._.alloc_aux_img
- test eax, eax
- jz .previous
- or [prev_num_colors], -1
- and [prev_palette], 0
- mov ebx, [_data]
- mov esi, [prev_img_data]
- mov edi, [aux_img_data]
- mov [prev_img_data], edi
- cmp esi, edi
- jz @f
- movzx ecx, [ebx + gif.Header.lsd.ScreenHeight]
- push ecx
- movzx eax, [ebx + gif.Header.lsd.ScreenWidth]
- imul ecx, eax
- lea ecx, [ecx*3]
- push edi
- rep movsb
- pop edi
- pop esi
- mov edx, [edx + Image.Extended]
- movzx ecx, [edx + gif.Image.info.Top]
- sub esi, ecx
- jbe .rgb_ret
- imul ecx, eax
- lea ecx, [ecx*3]
- add edi, ecx
- cmp si, [edx + gif.Image.info.Height]
- jb @f
- mov si, [edx + gif.Image.info.Height]
-@@:
- movzx ecx, [edx + gif.Image.info.Left]
- sub eax, ecx
- jbe .rgb_ret
- lea ecx, [ecx*3]
- add edi, ecx
- cmp ax, [edx + gif.Image.info.Width]
- jb @f
- mov ax, [edx + gif.Image.info.Width]
-@@:
- xchg eax, ecx
- movzx edx, [ebx + gif.Header.lsd.ScreenWidth]
- sub edx, ecx
- mov eax, [background_color]
- lea edx, [edx*3]
-.rgb_loop:
- push ecx
-@@:
- stosw
- shr eax, 16
- stosb
- loop @b
- pop ecx
- add edi, edx
- dec esi
- jnz .rgb_loop
-.rgb_ret:
- retn
-
-endp
-
-;;================================================================================================;;
-proc img.decode.gif._.alloc_aux_img ;/////////////////////////////////////////////////////////////;;
-;;------------------------------------------------------------------------------------------------;;
-;? Allocate auxiliary memory for previous image ;;
-;;------------------------------------------------------------------------------------------------;;
-;> eax = image type: 1 = bpp8, 3 = bpp24 ;;
-;;------------------------------------------------------------------------------------------------;;
-;< eax = [aux_img_data] ;;
-;;================================================================================================;;
- cmp [aux_img_type], eax
- jae @f
- push edx eax
- movzx ecx, [ebx + sizeof.gif.Image + gif.LogicalScreenDescriptor.ScreenWidth]
- mul ecx
- movzx ecx, [ebx + sizeof.gif.Image + gif.LogicalScreenDescriptor.ScreenHeight]
- mul ecx
- invoke mem.realloc, [aux_img_data], eax
- pop ecx edx
- test eax, eax
- jz @f
- mov [aux_img_type], ecx
- mov [aux_img_data], eax
-@@: retn
-
-endp
-
-;;================================================================================================;;
-proc img.decode.gif._.alloc_aux_palette ;/////////////////////////////////////////////////////////;;
-;;------------------------------------------------------------------------------------------------;;
-;? Allocate and fill aux_palette ;;
-;;------------------------------------------------------------------------------------------------;;
-;> esi -> palette, ecx = palette size ;;
-;;------------------------------------------------------------------------------------------------;;
-;< [aux_palette] set ;;
-;;================================================================================================;;
- mov eax, [aux_palette]
- test eax, eax
- jnz @f
- push edx ecx
- invoke mem.alloc, 0x400
- pop ecx edx
- test eax, eax
- jz .ret
- mov [aux_palette], eax
-@@:
- mov edi, eax
- rep movsd
-.ret:
- retn
-
-endp
-
-restore main_img
-restore transparent_color
-restore background_color
-restore prev_num_colors
-restore prev_palette
-restore max_color
-restore prev_img_data
-restore _data
-restore aux_img_data
-restore aux_img_type
-restore aux_palette
-
-;;================================================================================================;;
-;;////////////////////////////////////////////////////////////////////////////////////////////////;;
-;;================================================================================================;;
-;! Below is private data you should never use directly from your code ;;
-;;================================================================================================;;
-;;////////////////////////////////////////////////////////////////////////////////////////////////;;
-;;================================================================================================;;
-
-
-;
+;;================================================================================================;;
+;;//// gif.asm //// (c) mike.dld, 2007-2008 //////////////////////////////////////////////////////;;
+;;================================================================================================;;
+;;//// Partial (c) by Willow, Diamond and HidnPlayr //////////////////////////////////////////////;;
+;;================================================================================================;;
+;; ;;
+;; This file is part of Common development libraries (Libs-Dev). ;;
+;; ;;
+;; Libs-Dev is free software: you can redistribute it and/or modify it under the terms of the GNU ;;
+;; Lesser General Public License as published by the Free Software Foundation, either version 2.1 ;;
+;; of the License, or (at your option) any later version. ;;
+;; ;;
+;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without ;;
+;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;
+;; Lesser General Public License for more details. ;;
+;; ;;
+;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;;
+;; If not, see . ;;
+;; ;;
+;;================================================================================================;;
+;; ;;
+;; References: ;;
+;; 1. GIF LITE v3.0 (2004-2007) ;;
+;; by Willow and Diamond ;;
+;; svn://kolibrios.org/programs/media/gifview/trunk/gif_lite.inc ;;
+;; 2. "GIF File Format Summary" ;;
+;; from "Encyclopedia of Graphics File Formats" by O'Reilly ;;
+;; http://www.fileformat.info/format/gif/ ;;
+;; 3. "LZW and GIF explained" (1987) ;;
+;; by Steve Blackstock, IEEE ;;
+;; http://www.cis.udel.edu/~amer/CISC651/lzw.and.gif.explained.html ;;
+;; 4. "Graphics Interchange Format (tm)" (June 15, 1987) ;;
+;; by CompuServe Incorporated ;;
+;; http://examples.oreilly.de/english_examples/gff/CDROM/GFF/VENDSPEC/GIF/GIF87A.TXT ;;
+;; 5. "Graphics Interchange Format (sm)" (July 31, 1990) ;;
+;; by CompuServe Incorporated ;;
+;; http://examples.oreilly.de/english_examples/gff/CDROM/GFF/VENDSPEC/GIF/GIF89A.TXT ;;
+;; ;;
+;;================================================================================================;;
+
+
+include 'gif.inc'
+
+;;================================================================================================;;
+proc img.is.gif _data, _length ;//////////////////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? Determine if raw data could be decoded (is in GIF format) ;;
+;;------------------------------------------------------------------------------------------------;;
+;> _data = raw data as read from file/stream ;;
+;> _length = data length ;;
+;;------------------------------------------------------------------------------------------------;;
+;< eax = false / true ;;
+;;================================================================================================;;
+ cmp [_length], sizeof.gif.Header
+ jb .nope
+ mov eax, [_data]
+ cmp dword[eax], 'GIF8'
+ jne .nope
+ cmp word[eax + 4], '7a'
+ je .yep
+ cmp word[eax + 4], '9a'
+ je .yep
+
+ .nope:
+ xor eax, eax
+ ret
+
+ .yep:
+ xor eax, eax
+ inc eax
+ ret
+endp
+
+;;================================================================================================;;
+proc img.decode.gif _data, _length, _options ;////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? Decode data into image if it contains correctly formed raw data in GIF format ;;
+;;------------------------------------------------------------------------------------------------;;
+;> _data = raw data as read from file/stream ;;
+;> _length = data length ;;
+;;------------------------------------------------------------------------------------------------;;
+;< eax = 0 (error) or pointer to image ;;
+;;================================================================================================;;
+locals
+ max_color dd ?
+ cur_color_table_size dd ?
+ transparent_color dd ?
+ background_color dd ?
+ options_bgr dd ?
+ prev_palette dd ?
+ aux_palette dd ?
+ img dd ?
+ prev_img_data dd ?
+ aux_img_data dd ?
+ aux_img_type dd ?
+ prev_num_colors dd ?
+ main_img dd ?
+ global_color_table dd ?
+ global_color_table_size dd ?
+endl
+
+img.decode.gif.main_img equ main_img
+img.decode.gif.prev_img_data equ prev_img_data
+img.decode.gif.transparent_color equ transparent_color
+img.decode.gif.background_color equ background_color
+img.decode.gif._length equ _length
+img.decode.gif.prev_num_colors equ prev_num_colors
+img.decode.gif.prev_palette equ prev_palette
+img.decode.gif.max_color equ max_color
+img.decode.gif._data equ _data
+img.decode.gif.aux_img_data equ aux_img_data
+img.decode.gif.aux_img_type equ aux_img_type
+img.decode.gif.aux_palette equ aux_palette
+img.decode.gif.options_bgr equ options_bgr
+; offset of _length parameter for child functions with ebp-based frame
+; child saved ebp, return address, 3 saved registers, 15 local variables
+img.decode.gif._length_child equ _length + 4 + 4 + 4*3 + 4*15
+img.decode.gif.max_color_child equ ebp + 4 + 4 + 4*3
+img.decode.gif.cur_color_table_size_child equ ebp + 4 + 4 + 4*3 + 4
+
+ push ebx esi edi
+ xor eax, eax
+ mov [img], eax
+ mov [main_img], eax
+ mov [prev_img_data], eax
+ mov [aux_img_data], eax
+ mov [aux_img_type], eax
+ mov [prev_palette], eax
+ mov [aux_palette], eax
+; when no previous image is available, use background fill with 1-entry palette
+ inc eax
+ mov [prev_num_colors], eax
+ lea eax, [background_color]
+ mov [prev_palette], eax
+; value for bgr color in transparent images
+ mov edx, 0xFFFFFF ; white bgr if no value given
+ mov ecx, [_options]
+ jecxz @f
+ cmp [ecx + ImageDecodeOptions.UsedSize], ImageDecodeOptions.BackgroundColor + 4
+ jb @f
+ mov edx, [ecx + ImageDecodeOptions.BackgroundColor]
+@@:
+ mov [options_bgr], edx
+ mov dword [eax], edx
+; guard against incorrect gif files without any color tables
+; "If no color table is available at
+; all, the decoder is free to use a system color table or a table of its own. In
+; that case, the decoder may use a color table with as many colors as its
+; hardware is able to support; it is recommended that such a table have black and
+; white as its first two entries, so that monochrome images can be rendered
+; adequately." (c) official gif documentation
+ mov [global_color_table], gif_default_palette
+ mov [global_color_table_size], 2
+
+; img.is.gif is called by caller (img.decode)
+; stdcall img.is.gif, [_data], [_length]
+; or eax, eax
+; jz .error
+
+ mov ebx, [_data]
+ sub [_length], sizeof.gif.Header
+
+ mov cl, [ebx + gif.Header.lsd.Packed]
+ add ebx, sizeof.gif.Header
+; gif.LSD.Packed.GlobalColorTableFlag = 80h
+; test cl, gif.LSD.Packed.GlobalColorTableFlag
+; jz @f
+ test cl, cl
+ jns @f
+ mov [global_color_table], ebx
+ and cl, gif.LSD.Packed.SizeOfGlobalColorTableMask
+; shr cl, gif.LSD.Packed.SizeOfGlobalColorTableShift ; here Shift = 0
+ push 2
+ pop eax
+ shl eax, cl
+ mov [global_color_table_size], eax
+ lea eax, [eax * 3]
+ sub [_length], eax
+ jbe .error ; there must be at least 1 additional byte after color table
+ movzx ecx, byte [ebx - sizeof.gif.Header + gif.Header.lsd.BackgroundColor]
+ lea ecx, [ecx*3]
+ mov ecx, [ebx + ecx] ; eax = xxBBGGRR, convert to Kolibri color
+ bswap ecx
+ shr ecx, 8
+ mov [background_color], ecx
+ add ebx, eax
+ @@:
+
+; @@: cmp byte[ebx + gif.Block.Introducer], gif.Block.Introducer.Extension
+; jne .next_image
+; cmp byte[ebx + gif.Extension.Label], gif.Extension.Label.Comment
+; jne .error
+; add ebx, sizeof.gif.Extension
+; stdcall ._.skip_data
+; mov ebx, eax
+; jmp @b
+
+ .next_image:
+ stdcall img._.new
+ or eax, eax
+ jz .error
+ mov edx, [img]
+ mov [eax + Image.Previous], edx
+ push sizeof.gif.LogicalScreenDescriptor
+ pop ecx
+ test edx, edx
+ jz @f
+ mov [edx + Image.Next], eax
+ xor ecx, ecx
+ @@:
+ push eax
+ mov [eax + Image.Type], Image.bpp8i
+
+ add ecx, sizeof.gif.Image
+ invoke mem.alloc, ecx
+ pop edx
+ or eax, eax
+ jz .error2
+ mov [edx + Image.Extended], eax
+ xor ecx, ecx
+ cmp [img], ecx
+ jnz @f
+ mov esi, [_data]
+ add esi, gif.Header.lsd
+ lea edi, [eax + sizeof.gif.Image]
+ mov cl, sizeof.gif.LogicalScreenDescriptor
+ rep movsb
+ mov [main_img], edx
+ @@:
+ mov [img], edx
+
+ stdcall ._.process_extensions
+
+ cmp al, gif.Block.Introducer.ImageDescriptor
+ jne .error
+ sub [_length], sizeof.gif.ImageDescriptor
+ jc .error
+ movzx eax, [ebx + gif.ImageDescriptor.Width]
+ movzx ecx, [ebx + gif.ImageDescriptor.Height]
+ push edx
+ stdcall img._.resize_data, [img], eax, ecx
+ pop edx
+ or eax, eax
+ jz .error
+
+ 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
+; here Shift = 0
+; shr cl, gif.ID.Packed.SizeOfLocalColorTableShift
+ push 2
+ pop eax
+ shl eax, cl
+ mov ecx, eax
+ lea eax, [eax*3]
+ add ebx, eax
+ sub [_length], eax
+ jbe .error ; because we load additional byte, check is 'jbe', not 'jc'
+@@:
+ mov [cur_color_table_size], ecx
+ dec [cur_color_table_size]
+@@:
+ lodsd
+ dec esi
+ bswap eax
+ shr eax, 8
+ stosd
+ loop @b
+ add ebx, sizeof.gif.ImageDescriptor
+ stdcall ._.process_image
+ push ebx
+ mov edx, [img]
+ push edx
+ stdcall ._.superimpose
+ pop edx
+ push edx
+ stdcall ._.dispose
+ pop edx
+ mov edx, [edx + Image.Previous]
+ test edx, edx
+ jz .nofreeprev
+ mov ebx, [edx + Image.Extended]
+ cmp [edx + Image.Delay], 0
+ jnz .nofreeprev
+ mov esi, [prev_palette]
+ cmp esi, [edx + Image.Palette]
+ jnz @f
+ mov ecx, [prev_num_colors]
+ stdcall ._.alloc_aux_palette
+ test eax, eax
+ jz .nofreeprev
+ mov [prev_palette], eax
+ @@:
+ mov esi, [prev_img_data]
+ cmp esi, [edx + Image.Data]
+ jnz .noprevdata
+ push 1
+ pop eax
+ cmp [edx + Image.Type], Image.bpp8i
+ jz @f
+ mov al, 3
+ @@:
+ cmp [aux_img_type], eax
+ jb .resetaux
+ mov edi, [aux_img_data]
+ imul eax, [edx + Image.Width]
+ imul eax, [edx + Image.Height]
+ xchg eax, ecx
+ rep movsb
+ jmp .noprevdata
+ .resetaux:
+ mov [aux_img_type], eax
+ mov eax, [aux_img_data]
+ test eax, eax
+ jz @f
+ invoke mem.free, eax
+ @@:
+ xor eax, eax
+ xchg eax, [edx + Image.Data]
+ mov [aux_img_data], eax
+ .noprevdata:
+ cmp edx, [main_img]
+ jnz @f
+ mov eax, [edx + Image.Next]
+ mov [main_img], eax
+ mov esi, [eax + Image.Extended]
+ mov edi, [edx + Image.Extended]
+ mov [edx + Image.Extended], esi
+ mov [eax + Image.Extended], edi
+ push sizeof.gif.Image
+ pop ecx
+ rep movsb
+ @@:
+ stdcall img.destroy.layer, edx
+ .nofreeprev:
+ pop ebx
+ test ebx, ebx
+ jz .ret
+ jmp .next_image
+
+ .error2:
+ mov [img], edx
+
+ .error:
+ mov eax, [img]
+ test eax, eax
+ jz .ret
+ cmp [main_img], eax
+ jnz @f
+ and [main_img], 0
+ @@:
+ stdcall img.destroy.layer, eax
+ .ret:
+ mov eax, [aux_img_data]
+ test eax, eax
+ jz @f
+ invoke mem.free, eax
+ @@:
+ mov eax, [aux_palette]
+ test eax, eax
+ jz @f
+ invoke mem.free, eax
+ @@:
+ mov eax, [main_img]
+ cmp [eax + Image.Next], 0
+ jz @f
+ or [eax + Image.Flags], Image.IsAnimated
+ @@:
+ pop edi esi ebx
+ ret
+endp
+
+;;================================================================================================;;
+proc img.encode.gif _img, _p_length ;/////////////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? Encode image into raw data in GIF format ;;
+;;------------------------------------------------------------------------------------------------;;
+;> _img = pointer to image ;;
+;;------------------------------------------------------------------------------------------------;;
+;< eax = 0 (error) or pointer to encoded data ;;
+;< _p_length = encoded data length ;;
+;;================================================================================================;;
+ xor eax, eax
+ ret
+endp
+
+
+;;================================================================================================;;
+;;////////////////////////////////////////////////////////////////////////////////////////////////;;
+;;================================================================================================;;
+;! Below are private procs you should never call directly from your code ;;
+;;================================================================================================;;
+;;////////////////////////////////////////////////////////////////////////////////////////////////;;
+;;================================================================================================;;
+
+
+;;================================================================================================;;
+proc img.decode.gif._.process_extensions ;////////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? --- TBD --- ;;
+;;------------------------------------------------------------------------------------------------;;
+;> ebx = raw image data ;;
+;> edx = image data ;;
+;;------------------------------------------------------------------------------------------------;;
+;< --- TBD --- ;;
+;;================================================================================================;;
+ mov esi, ebx
+ xor eax, eax
+ mov [edx + Image.Delay], eax
+
+ .next_block:
+ dec [img.decode.gif._length]
+ js .exit_err
+ lodsb ; load gif.Block.Introducer
+ cmp al, gif.Block.Introducer.Extension
+ jne .exit
+
+ .ext_block:
+ dec [img.decode.gif._length]
+ js .exit_err
+ lodsb ; load gif.Extension.Label
+ cmp al, gif.Extension.Label.GraphicsControl
+ je .graphics_control_ext
+; cmp al, gif.Extension.Label.PlainText
+; je .plain_text_ext
+; cmp al, gif.Extension.Label.Comment
+; je .comment_ext
+; cmp al, gif.Extension.Label.Application
+; je .application_ext
+; skip all other extensions
+ .skip_ext:
+ dec [img.decode.gif._length]
+ js .exit_err
+ lodsb ; load BlockSize
+ .1:
+ test al, al
+ jz .next_block
+ sub [img.decode.gif._length], eax
+ jc .exit_err
+ add esi, eax
+ jmp .skip_ext
+
+ .graphics_control_ext:
+ dec [img.decode.gif._length]
+ js .exit_err
+ lodsb ; load BlockSize; must be sizeof.gif.GraphicsControlExtension
+ cmp al, sizeof.gif.GraphicsControlExtension
+ jnz .1
+ sub [img.decode.gif._length], eax
+ jc .exit_err
+ push edi
+ movzx edi, [esi + gif.GraphicsControlExtension.DelayTime]
+ mov [edx + Image.Delay], edi
+ mov edi, [edx + Image.Extended]
+ add edi, gif.Image.gce
+ mov ecx, eax
+ rep movsb
+ pop edi
+ jmp .skip_ext
+
+ .exit_err:
+ xor eax, eax
+
+ .exit:
+ mov ebx, esi
+ ret
+endp
+
+;;================================================================================================;;
+proc img.decode.gif._.process_image ;/////////////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? --- TBD --- ;;
+;;------------------------------------------------------------------------------------------------;;
+;> ebx = raw image data ;;
+;> edx = image data ;;
+;;------------------------------------------------------------------------------------------------;;
+;< --- TBD --- ;;
+;;================================================================================================;;
+locals
+ width dd ?
+ img_start dd ?
+ img_end dd ?
+ row_end dd ?
+ pass dd ?
+ codesize dd ?
+ compsize dd ?
+ workarea dd ?
+ block_ofs dd ?
+ bit_count dd ?
+ CC dd ?
+ EOI dd ?
+endl
+
+ invoke mem.alloc, 16 * 1024
+ mov [workarea], eax
+ or eax, eax
+ jz .error
+
+ mov ecx, [edx + Image.Width]
+ mov [width], ecx
+ mov eax, [edx + Image.Height]
+ imul eax, ecx
+ mov [img_end], eax
+ inc eax
+ mov [row_end], eax
+ and [pass], 0
+ and dword [img.decode.gif.max_color_child], 0
+ mov eax, [edx + Image.Extended]
+ test [eax + gif.Image.info.Packed], gif.ID.Packed.InterleaceFlag
+ jz @f
+ mov [row_end], ecx
+
+ @@: mov esi, ebx
+ mov edi, [edx + Image.Data]
+
+ sub dword [img.decode.gif._length_child], 2
+ jc .error
+ movzx ecx, byte[esi]
+ inc esi
+ cmp cl, 12
+ jae .error
+ mov [codesize], ecx
+ inc [codesize]
+ xor eax, eax
+ lodsb ; eax - block_count
+ sub [img.decode.gif._length_child], eax
+ jc .error
+ add eax, esi
+ push edi
+ mov edi, [workarea]
+ mov [block_ofs], eax
+ mov [bit_count], 8
+ mov eax, 1
+ shl eax, cl
+ mov [CC], eax
+ mov ecx, eax
+ inc eax
+ mov [EOI], eax
+ mov eax, gif.Null shl 16
+ .filltable:
+ stosd
+ inc eax
+ loop .filltable
+ pop edi
+ mov [img_start], edi
+ add [img_end], edi
+ add [row_end], edi
+ .reinit:
+ mov edx, [EOI]
+ inc edx
+ push [codesize]
+ pop [compsize]
+ call .get_symbol
+ cmp eax, [CC]
+ je .reinit
+ call .output
+ .cycle:
+ movzx ebx, ax
+ call .get_symbol
+ cmp eax, [EOI]
+ je .end
+ cmp eax, edx
+ ja .error
+ je .notintable
+ cmp eax, [CC]
+ je .reinit
+ call .output
+ .add:
+ cmp edx, 0x00001000
+ jae .cycle
+ mov ecx, [workarea]
+ mov [ecx + edx * 4], ebx
+ inc edx
+ cmp edx, 0x1000
+ je .noinc
+ bsr ebx, edx
+ cmp ebx, [compsize]
+ jne .noinc
+ inc [compsize]
+ .noinc:
+ jmp .cycle
+ .notintable:
+ push eax
+ mov eax, ebx
+ call .output
+ push ebx
+ movzx eax, bx
+ call .output
+ pop ebx eax
+ jmp .add
+ .end:
+ mov edi, [img_end]
+ xor eax, eax
+
+ .exit:
+ cmp [workarea], 0
+ je @f
+ invoke mem.free, [workarea]
+ @@:
+ mov ebx, [block_ofs]
+ @@:
+ dec [img.decode.gif._length_child]
+ js @f
+ movzx eax, byte [ebx]
+ inc ebx
+ test eax, eax
+ jz .ret
+ sub [img.decode.gif._length_child], eax
+ jc @f
+ add ebx, eax
+ jmp @b
+
+ .error:
+ cmp [workarea], 0
+ je @f
+ invoke mem.free, [workarea]
+ @@: xor ebx, ebx
+ .ret:
+ ret
+
+;;------------------------------------------------------------------------------------------------;;
+
+img.decode.gif._.process_image.get_symbol:
+ mov ecx, [compsize]
+ push ecx
+ xor eax, eax
+
+ .shift:
+ dec [bit_count]
+ jns .loop1
+ inc esi
+ cmp esi, [block_ofs]
+ jb .noblock
+ push eax
+ xor eax, eax
+ sub [img.decode.gif._length_child], 1
+ jc .error_eof
+ lodsb
+ test eax, eax
+ jnz .nextbl
+ .error_eof:
+ add esp, 12
+ jmp img.decode.gif._.process_image.error
+
+ .nextbl:
+ sub [img.decode.gif._length_child], eax
+ jc .error_eof
+ add eax, esi
+ mov [block_ofs], eax
+ pop eax
+
+ .noblock:
+ mov [bit_count], 7
+
+ .loop1:
+ ror byte[esi], 1
+ rcr eax,1
+ loop .shift
+ pop ecx
+ rol eax, cl
+
+ .exit:
+ xor ecx, ecx
+ retn
+
+;;------------------------------------------------------------------------------------------------;;
+
+img.decode.gif._.process_image.output:
+ push esi eax edx
+ mov edx, [workarea]
+
+ .next:
+ pushw [edx + eax * 4]
+ mov ax, [edx + eax * 4 + 2]
+ inc ecx
+ cmp ax, gif.Null
+ jnz .next
+ shl ebx, 16
+ mov bx, [esp]
+
+ .loop2:
+ pop ax
+ cmp al, byte [img.decode.gif.cur_color_table_size_child]
+ jbe @f ; guard against incorrect GIFs
+ mov al, 0
+ @@: cmp al, byte [img.decode.gif.max_color_child]
+ jbe @f
+ mov [img.decode.gif.max_color_child], al
+ @@: stosb
+
+ cmp edi, [row_end]
+ jb .norowend
+ mov eax, [width]
+ push eax
+ sub edi, eax
+ add eax, eax
+ cmp [pass], 3
+ je @f
+ add eax, eax
+ cmp [pass], 2
+ je @f
+ add eax, eax
+ @@: add edi, eax
+ pop eax
+ cmp edi, [img_end]
+ jb .nextrow
+ mov edi, [img_start]
+ inc [pass]
+ cmp [pass], 4
+ je .done
+ add edi, eax
+ cmp [pass], 3
+ je @f
+ add edi, eax
+ cmp [pass], 2
+ je @f
+ add edi, eax
+ add edi, eax
+ @@:
+
+ .nextrow:
+ add eax, edi
+ mov [row_end], eax
+ xor eax, eax
+
+ .norowend:
+ cmp edi, [img_end]
+ jz .done
+ loop .loop2
+ pop edx eax esi
+ retn
+
+ .done:
+ lea esp, [esp+(ecx-1)*2]
+ pop edx eax esi eax
+ jmp img.decode.gif._.process_image.exit
+
+endp
+
+;;================================================================================================;;
+proc img.decode.gif._.is_logical_screen ;/////////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? Determines whether GIF image occupies the whole logical screen ;;
+;;------------------------------------------------------------------------------------------------;;
+;> eax = extended image data ;;
+;> ebx = main image ;;
+;;------------------------------------------------------------------------------------------------;;
+;< ZF set <=> image area equals logical screen ;;
+;;================================================================================================;;
+ mov ebx, [ebx + Image.Extended]
+ cmp [eax + gif.Image.info.Left], 0
+ jnz @f
+ cmp [eax + gif.Image.info.Top], 0
+ jnz @f
+ mov cx, [eax + gif.Image.info.Width]
+ cmp cx, [ebx + sizeof.gif.Image + gif.LogicalScreenDescriptor.ScreenWidth]
+ jnz @f
+ mov cx, [eax + gif.Image.info.Height]
+ cmp cx, [ebx + sizeof.gif.Image + gif.LogicalScreenDescriptor.ScreenHeight]
+@@: retn
+endp
+
+main_img equ img.decode.gif.main_img
+transparent_color equ img.decode.gif.transparent_color
+background_color equ img.decode.gif.background_color
+prev_num_colors equ img.decode.gif.prev_num_colors
+prev_palette equ img.decode.gif.prev_palette
+max_color equ img.decode.gif.max_color
+prev_img_data equ img.decode.gif.prev_img_data
+_data equ img.decode.gif._data
+aux_img_data equ img.decode.gif.aux_img_data
+aux_img_type equ img.decode.gif.aux_img_type
+aux_palette equ img.decode.gif.aux_palette
+
+;;================================================================================================;;
+proc img.decode.gif._.superimpose ;///////////////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? --- TBD --- ;;
+;;------------------------------------------------------------------------------------------------;;
+;> edx = image data ;;
+;;------------------------------------------------------------------------------------------------;;
+;< --- TBD --- ;;
+;;================================================================================================;;
+ mov ebx, [main_img]
+ mov eax, [edx + Image.Extended]
+ or [transparent_color], -1 ; no transparent color
+ test byte [eax + gif.Image.gce.Packed], 1
+ jz @f
+ movzx ecx, byte [eax + gif.Image.gce.ColorIndex]
+ mov [transparent_color], ecx
+ cmp edx, ebx
+ jnz .has_transparency
+ shl ecx, 2
+ add ecx, [edx + Image.Palette]
+ push eax
+ mov eax, [img.decode.gif.options_bgr]
+ mov dword [background_color], eax
+ mov dword [ecx], eax
+ pop eax
+@@:
+ call img.decode.gif._.is_logical_screen
+ jnz .has_transparency
+; image is not transparent, so keep it as is
+ retn
+
+.has_transparency:
+; image has transparent areas, we must superimpose it on the previous
+ mov ecx, [prev_num_colors]
+ cmp ecx, 0x100
+ ja .superimpose_on_rgb
+; create common palette
+ sub esp, 3FCh
+ push eax
+ mov edi, esp
+ push ecx
+ mov esi, [prev_palette]
+ rep movsd
+ pop ecx
+ mov esi, [edx + Image.Palette]
+ xor ebx, ebx
+ mov edi, esp
+ sub esp, 100h
+.create_palette_loop:
+ push ecx
+ lodsd
+ cmp ebx, [transparent_color]
+ jz .nochange
+ cmp ebx, ecx
+ jae @f
+ cmp eax, [edi+ebx*4]
+ jz .nochange
+@@:
+ push edi
+ repnz scasd
+ pop edi
+ jnz .increase_palette
+ sub ecx, [esp]
+ not ecx ; cl = index of new color in current palette
+ jmp .palette_common
+.increase_palette:
+ mov ecx, [esp]
+ test ch, ch
+ jnz .output_to_rgb
+ inc dword [esp]
+ mov [edi+ecx*4], eax
+ jmp .palette_common
+.nochange:
+ mov ecx, ebx
+.palette_common:
+ mov [ebx+esp+4], cl
+ pop ecx
+ inc ebx
+ cmp ebx, [max_color]
+ jbe .create_palette_loop
+ mov [max_color], ecx
+; if image occupies only part of logical screen, allocate memory for full logical screen
+ mov ebx, [main_img]
+ mov eax, [edx + Image.Extended]
+ mov esi, [edx + Image.Data]
+ call img.decode.gif._.is_logical_screen
+ jz @f
+ and [edx + Image.Data], 0
+ push edx
+ movzx eax, [ebx + sizeof.gif.Image + gif.LogicalScreenDescriptor.ScreenHeight]
+ push eax
+ movzx eax, [ebx + sizeof.gif.Image + gif.LogicalScreenDescriptor.ScreenWidth]
+ stdcall img._.resize_data, edx, eax
+ pop edx
+ test eax, eax
+ jz .palette_nomem
+@@:
+; copy final palette to Image.Palette
+ push esi esi
+ mov esi, edi
+ mov edi, [edx + Image.Palette]
+ mov ecx, [max_color]
+ dec [max_color]
+ rep movsd
+ mov esi, [prev_img_data]
+ mov edi, [edx + Image.Data]
+; do superimpose, [esp] -> source data, esi -> prev image data
+; (NULL if previous image is filled with background color), esp+8 -> correspondence between
+; used palette and final palette, edi -> destination data
+ mov ebx, [edx + Image.Extended]
+; first Top rows are copied from [prev_img_data] or filled with bgr
+ movzx ecx, [ebx + gif.Image.info.Top]
+ cmp ecx, [edx + Image.Height]
+ jb @f
+ mov ecx, [edx + Image.Height]
+@@:
+ push ecx
+ imul ecx, [edx + Image.Width]
+ call .rep_movsb_or_stosb
+ pop ecx
+; convert rows
+ sub ecx, [edx + Image.Height]
+ neg ecx
+ push ecx
+ cmp cx, [ebx + gif.Image.info.Height]
+ jbe @f
+ mov cx, [ebx + gif.Image.info.Height]
+@@:
+ jecxz .norows
+.convert_rows:
+ push ecx
+ movzx ecx, [ebx + gif.Image.info.Left]
+ cmp ecx, [edx + Image.Width]
+ jb @f
+ mov ecx, [edx + Image.Width]
+@@:
+ push ecx
+ call .rep_movsb_or_stosb
+ pop ecx
+ sub ecx, [edx + Image.Width]
+ neg ecx
+ push ecx edx
+ mov edx, [esp+16] ; source data
+ cmp cx, [ebx + gif.Image.info.Width]
+ jbe @f
+ mov cx, [ebx + gif.Image.info.Width]
+@@:
+ jecxz .norowsi
+.rowsloop:
+ movzx eax, byte [edx]
+ inc edx
+ cmp eax, [transparent_color]
+ jz .rows_transparent
+ mov al, [eax+esp+24]
+ stosb
+ call .lodsb
+ jmp @f
+.rows_transparent:
+ call .lodsb
+ stosb
+@@:
+ loop .rowsloop
+.norowsi:
+ pop edx ecx
+ sub cx, [ebx + gif.Image.info.Width]
+ jbe @f
+ call .rep_movsb_or_stosb
+@@:
+ movzx eax, [ebx + gif.Image.info.Width]
+ add [esp+8], eax
+ pop ecx
+ loop .convert_rows
+.norows:
+ pop ecx
+ sub cx, [ebx + gif.Image.info.Height]
+ jbe @f
+ imul ecx, [edx + Image.Width]
+ call .rep_movsb_or_stosb
+@@:
+; free old image data if we have allocated new copy
+ pop esi esi
+ cmp esi, [edx + Image.Data]
+ jz @f
+ invoke mem.free, esi
+@@:
+; cleanup stack and return
+ add esp, 500h
+ retn
+.palette_nomem:
+ mov [edx + Image.Data], esi
+ jmp @b
+
+.output_to_rgb:
+ pop ecx
+ add esp, 500h
+; compose two palette-based images to one RGB image
+ xor esi, esi
+ xchg esi, [edx + Image.Data]
+ push esi
+ mov ebx, [_data]
+ push [edx + Image.Palette]
+ mov byte [edx + Image.Type], Image.bpp24
+ push edx
+ movzx eax, [ebx + gif.Header.lsd.ScreenHeight]
+ push eax
+ movzx eax, [ebx + gif.Header.lsd.ScreenWidth]
+ stdcall img._.resize_data, edx, eax
+ pop edx
+ test eax, eax
+ jz .convrgb_nomem
+ push esi
+ mov edi, [edx + Image.Data]
+ mov esi, [prev_img_data]
+ mov ebx, [edx + Image.Extended]
+; first Top rows are copied from [prev_img_data] or filled with bgr
+ movzx ecx, [ebx + gif.Image.info.Top]
+ cmp ecx, [edx + Image.Height]
+ jb @f
+ mov ecx, [edx + Image.Height]
+@@:
+ push ecx
+ imul ecx, [edx + Image.Width]
+ call .convrgb_prev
+ pop ecx
+; convert rows
+ sub ecx, [edx + Image.Height]
+ neg ecx
+ push ecx
+ cmp cx, [ebx + gif.Image.info.Height]
+ jbe @f
+ mov cx, [ebx + gif.Image.info.Height]
+@@:
+ jecxz .convrgb_norows
+.convrgb_convert_rows:
+ push ecx
+ movzx ecx, [ebx + gif.Image.info.Left]
+ cmp ecx, [edx + Image.Width]
+ jb @f
+ mov ecx, [edx + Image.Width]
+@@:
+ push ecx
+ call .convrgb_prev
+ pop ecx
+ sub ecx, [edx + Image.Width]
+ neg ecx
+ push ecx edx
+ mov edx, [esp+16] ; source data
+ cmp cx, [ebx + gif.Image.info.Width]
+ jbe @f
+ mov cx, [ebx + gif.Image.info.Width]
+@@:
+ jecxz .convrgb_norowsi
+.convrgb_rowsloop:
+ movzx eax, byte [edx]
+ inc edx
+ cmp eax, [transparent_color]
+ jz .convrgb_rows_transparent
+ shl eax, 2
+ add eax, [esp+20] ; source palette
+ mov eax, [eax]
+ stosw
+ shr eax, 16
+ stosb
+ call .convrgb_lodsb
+ jmp @f
+.convrgb_rows_transparent:
+ call .convrgb_lodsb
+ stosw
+ shr eax, 16
+ stosb
+@@:
+ loop .convrgb_rowsloop
+.convrgb_norowsi:
+ pop edx ecx
+ sub cx, [ebx + gif.Image.info.Width]
+ jbe @f
+ call .convrgb_prev
+@@:
+ movzx eax, [ebx + gif.Image.info.Width]
+ add [esp+8], eax
+ pop ecx
+ loop .convrgb_convert_rows
+.convrgb_norows:
+ pop ecx
+ sub cx, [ebx + gif.Image.info.Height]
+ jbe @f
+ imul ecx, [edx + Image.Width]
+ call .convrgb_prev
+@@:
+; free old image data
+ pop esi esi ;esi
+ invoke mem.free;, esi
+ retn
+.convrgb_nomem:
+ pop esi esi
+ retn
+
+.superimpose_on_rgb:
+; previous image is RGB, new image has transparent areas
+ xor esi, esi
+ xchg esi, [edx + Image.Data]
+ push esi
+ mov ebx, [_data]
+ push [edx + Image.Palette]
+ mov byte [edx + Image.Type], Image.bpp24
+ push edx
+ movzx eax, [ebx + gif.Header.lsd.ScreenHeight]
+ push eax
+ movzx eax, [ebx + gif.Header.lsd.ScreenWidth]
+ stdcall img._.resize_data, edx, eax
+ pop edx
+ test eax, eax
+ jz .rgb_nomem
+ push esi
+ mov edi, [edx + Image.Data]
+ mov esi, [prev_img_data]
+ mov ebx, [edx + Image.Extended]
+; first Top rows are copied from [prev_img_data] or filled with bgr
+ movzx ecx, [ebx + gif.Image.info.Top]
+ cmp ecx, [edx + Image.Height]
+ jb @f
+ mov ecx, [edx + Image.Height]
+@@:
+ push ecx
+ lea ecx, [ecx*3]
+ imul ecx, [edx + Image.Width]
+ rep movsb
+ pop ecx
+; convert rows
+ sub ecx, [edx + Image.Height]
+ neg ecx
+ push ecx
+ cmp cx, [ebx + gif.Image.info.Height]
+ jbe @f
+ mov cx, [ebx + gif.Image.info.Height]
+@@:
+ jecxz .rgb_norows
+.rgb_convert_rows:
+ push ecx
+ movzx ecx, [ebx + gif.Image.info.Left]
+ cmp ecx, [edx + Image.Width]
+ jb @f
+ mov ecx, [edx + Image.Width]
+@@:
+ push ecx
+ lea ecx, [ecx*3]
+ rep movsb
+ pop ecx
+ sub ecx, [edx + Image.Width]
+ neg ecx
+ push ecx edx
+ mov edx, [esp+16] ; source data
+ cmp cx, [ebx + gif.Image.info.Width]
+ jbe @f
+ mov cx, [ebx + gif.Image.info.Width]
+@@:
+ jecxz .rgb_norowsi
+.rgb_rowsloop:
+ movzx eax, byte [edx]
+ inc edx
+ cmp eax, [transparent_color]
+ jz .rgb_rows_transparent
+ shl eax, 2
+ add eax, [esp+20] ; source palette
+ mov eax, [eax]
+ stosw
+ shr eax, 16
+ stosb
+ add esi, 3
+ jmp @f
+.rgb_rows_transparent:
+ movsb
+ movsb
+ movsb
+@@:
+ loop .rgb_rowsloop
+.rgb_norowsi:
+ pop edx ecx
+ sub cx, [ebx + gif.Image.info.Width]
+ jbe @f
+ lea ecx, [ecx*3]
+ rep movsb
+@@:
+ movzx eax, [ebx + gif.Image.info.Width]
+ add [esp+8], eax
+ pop ecx
+ loop .rgb_convert_rows
+.rgb_norows:
+ pop ecx
+ sub cx, [ebx + gif.Image.info.Height]
+ jbe @f
+ imul ecx, [edx + Image.Width]
+ lea ecx, [ecx*3]
+ rep movsb
+@@:
+; free old image data
+ pop esi esi ;esi
+ invoke mem.free;, esi
+ retn
+.rgb_nomem:
+ pop esi esi
+ retn
+
+.lodsb:
+ xor eax, eax
+ test esi, esi
+ jz @f
+ lodsb
+@@: retn
+
+.rep_movsb_or_stosb:
+ test esi, esi
+ jz .rmos1
+ rep movsb
+ jmp .rmos2
+.rmos1: xor eax, eax ; background index in final palette is 0 in bgr mode
+ rep stosb
+.rmos2: retn
+
+.convrgb_prev:
+ jecxz .convrgb_noprev
+ test esi, esi
+ jz .convrgb_prev_bgr
+@@:
+ xor eax, eax
+ lodsb
+ shl eax, 2
+ add eax, [prev_palette]
+ mov eax, [eax]
+ stosw
+ shr eax, 16
+ stosb
+ loop @b
+ retn
+.convrgb_prev_bgr:
+@@:
+ mov eax, [background_color]
+ stosw
+ shr eax, 16
+ stosb
+ loop @b
+.convrgb_noprev:
+ retn
+.convrgb_lodsb:
+ xor eax, eax
+ test esi, esi
+ jz @f
+ lodsb
+ shl eax, 2
+ add eax, [prev_palette]
+ mov eax, [eax]
+ retn
+@@: mov eax, [background_color]
+ retn
+
+endp
+
+;;================================================================================================;;
+proc img.decode.gif._.dispose ;///////////////////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? --- TBD --- ;;
+;;------------------------------------------------------------------------------------------------;;
+;> edx = image data ;;
+;;------------------------------------------------------------------------------------------------;;
+;< --- TBD --- ;;
+;;================================================================================================;;
+ mov ebx, [edx + Image.Extended]
+ mov al, [ebx + gif.Image.gce.Packed]
+ shr al, 2
+ and al, 7
+ cmp al, 2
+ jz .background
+ cmp al, 3
+ jz .previous
+; don't dispose - set prev_img and related vars to current image
+ mov eax, [edx + Image.Data]
+ mov [prev_img_data], eax
+ cmp [edx + Image.Type], Image.bpp8i
+ jnz @f
+ mov eax, [max_color]
+ inc eax
+ mov [prev_num_colors], eax
+ mov eax, [edx + Image.Palette]
+ mov [prev_palette], eax
+ retn
+@@:
+ or [prev_num_colors], -1
+ and [prev_palette], 0
+.previous:
+ retn
+.background:
+ cmp [prev_img_data], 0
+ jz .bgr_full
+ mov ebx, [main_img]
+ mov eax, [edx + Image.Extended]
+ call img.decode.gif._.is_logical_screen
+ jnz @f
+.bgr_full:
+ xor eax, eax
+ mov [prev_img_data], eax
+ inc eax
+ mov [prev_num_colors], eax
+ lea eax, [background_color]
+ mov [prev_palette], eax
+ retn
+@@:
+ cmp [prev_num_colors], 0x100
+ ja .rgb
+ mov eax, [background_color]
+ mov edi, [prev_palette]
+ mov ecx, [prev_num_colors]
+ repnz scasd
+ jz .palette_ok
+ cmp [prev_num_colors], 0x100
+ jz .convert_rgb
+ push 1
+ pop eax
+ stdcall img.decode.gif._.alloc_aux_img
+ test eax, eax
+ jz .previous
+ mov ecx, [prev_num_colors]
+ mov esi, [prev_palette]
+ call img.decode.gif._.alloc_aux_palette
+ test eax, eax
+ jz .previous
+ mov [prev_palette], eax
+ mov eax, [background_color]
+ stosd
+ mov eax, [prev_num_colors] ; eax = index of background color
+ inc [prev_num_colors]
+ jmp .bpp8_common
+.palette_ok:
+ push 1
+ pop eax
+ stdcall img.decode.gif._.alloc_aux_img
+ test eax, eax
+ jz .previous
+ sub edi, [prev_palette]
+ shr edi, 2
+ lea eax, [edi-1] ; eax = index of background color
+.bpp8_common:
+ push eax
+ mov ebx, [_data]
+ mov esi, [prev_img_data]
+ mov edi, [aux_img_data]
+ mov [prev_img_data], edi
+ cmp esi, edi
+ jz @f
+ movzx ecx, [ebx + gif.Header.lsd.ScreenWidth]
+ movzx eax, [ebx + gif.Header.lsd.ScreenHeight]
+ imul ecx, eax
+ push edi
+ rep movsb
+ pop edi
+@@:
+ movzx esi, [ebx + gif.Header.lsd.ScreenHeight]
+ movzx eax, [ebx + gif.Header.lsd.ScreenWidth]
+ mov edx, [edx + Image.Extended]
+ movzx ecx, [edx + gif.Image.info.Top]
+ sub esi, ecx
+ jbe .bpp8_ret
+ imul ecx, eax
+ add edi, ecx
+ cmp si, [edx + gif.Image.info.Height]
+ jb @f
+ mov si, [edx + gif.Image.info.Height]
+@@:
+ movzx ecx, [edx + gif.Image.info.Left]
+ sub eax, ecx
+ jbe .bpp8_ret
+ add edi, ecx
+ cmp ax, [edx + gif.Image.info.Width]
+ jb @f
+ mov ax, [edx + gif.Image.info.Width]
+@@:
+ xchg eax, ecx
+ movzx edx, [ebx + gif.Header.lsd.ScreenWidth]
+ sub edx, ecx
+ pop eax
+@@:
+ push ecx
+ rep stosb
+ pop ecx
+ add edi, edx
+ dec esi
+ jnz @b
+ push eax
+.bpp8_ret:
+ pop eax
+ retn
+.convert_rgb:
+ push 3
+ pop eax
+ stdcall img.decode.gif._.alloc_aux_img
+ test eax, eax
+ jz .previous
+ or [prev_num_colors], -1
+ mov ebx, [_data]
+ mov esi, [prev_img_data]
+ mov edi, [aux_img_data]
+ mov [prev_img_data], edi
+ movzx ecx, [ebx + gif.Header.lsd.ScreenWidth]
+ movzx eax, [ebx + gif.Header.lsd.ScreenHeight]
+ imul ecx, eax
+ push edx
+ xor edx, edx
+ xchg edx, [prev_palette]
+ add edi, ecx
+ add esi, ecx
+ add edi, ecx
+ add edi, ecx
+@@:
+ dec esi
+ movzx eax, byte [esi]
+ mov eax, [eax*4+edx]
+ sub edi, 3
+ mov [edi], ax
+ shr eax, 16
+ mov [edi+2], al
+ loop @b
+ pop edx
+ movzx esi, [ebx + gif.Header.lsd.ScreenHeight]
+ movzx eax, [ebx + gif.Header.lsd.ScreenWidth]
+ mov edx, [edx + Image.Extended]
+ movzx ecx, [edx + gif.Image.info.Top]
+ sub esi, ecx
+ jbe .convert_rgb_ret
+ imul ecx, eax
+ lea ecx, [ecx*3]
+ add edi, ecx
+ cmp si, [edx + gif.Image.info.Height]
+ jb @f
+ mov si, [edx + gif.Image.info.Height]
+@@:
+ movzx ecx, [edx + gif.Image.info.Left]
+ sub eax, ecx
+ jbe .convert_rgb_ret
+ lea ecx, [ecx*3]
+ add edi, ecx
+ cmp ax, [edx + gif.Image.info.Width]
+ jb @f
+ mov ax, [edx + gif.Image.info.Width]
+@@:
+ xchg eax, ecx
+ movzx edx, [ebx + gif.Header.lsd.ScreenWidth]
+ sub edx, ecx
+ mov eax, [background_color]
+ lea edx, [edx*3]
+.convert_rgb_loop:
+ push ecx
+@@:
+ stosw
+ shr eax, 16
+ stosb
+ loop @b
+ pop ecx
+ add edi, edx
+ dec esi
+ jnz .convert_rgb_loop
+.convert_rgb_ret:
+ retn
+.rgb:
+ push 3
+ pop eax
+ stdcall img.decode.gif._.alloc_aux_img
+ test eax, eax
+ jz .previous
+ or [prev_num_colors], -1
+ and [prev_palette], 0
+ mov ebx, [_data]
+ mov esi, [prev_img_data]
+ mov edi, [aux_img_data]
+ mov [prev_img_data], edi
+ cmp esi, edi
+ jz @f
+ movzx ecx, [ebx + gif.Header.lsd.ScreenHeight]
+ push ecx
+ movzx eax, [ebx + gif.Header.lsd.ScreenWidth]
+ imul ecx, eax
+ lea ecx, [ecx*3]
+ push edi
+ rep movsb
+ pop edi
+ pop esi
+ mov edx, [edx + Image.Extended]
+ movzx ecx, [edx + gif.Image.info.Top]
+ sub esi, ecx
+ jbe .rgb_ret
+ imul ecx, eax
+ lea ecx, [ecx*3]
+ add edi, ecx
+ cmp si, [edx + gif.Image.info.Height]
+ jb @f
+ mov si, [edx + gif.Image.info.Height]
+@@:
+ movzx ecx, [edx + gif.Image.info.Left]
+ sub eax, ecx
+ jbe .rgb_ret
+ lea ecx, [ecx*3]
+ add edi, ecx
+ cmp ax, [edx + gif.Image.info.Width]
+ jb @f
+ mov ax, [edx + gif.Image.info.Width]
+@@:
+ xchg eax, ecx
+ movzx edx, [ebx + gif.Header.lsd.ScreenWidth]
+ sub edx, ecx
+ mov eax, [background_color]
+ lea edx, [edx*3]
+.rgb_loop:
+ push ecx
+@@:
+ stosw
+ shr eax, 16
+ stosb
+ loop @b
+ pop ecx
+ add edi, edx
+ dec esi
+ jnz .rgb_loop
+.rgb_ret:
+ retn
+
+endp
+
+;;================================================================================================;;
+proc img.decode.gif._.alloc_aux_img ;/////////////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? Allocate auxiliary memory for previous image ;;
+;;------------------------------------------------------------------------------------------------;;
+;> eax = image type: 1 = bpp8, 3 = bpp24 ;;
+;;------------------------------------------------------------------------------------------------;;
+;< eax = [aux_img_data] ;;
+;;================================================================================================;;
+ cmp [aux_img_type], eax
+ jae @f
+ push edx eax
+ movzx ecx, [ebx + sizeof.gif.Image + gif.LogicalScreenDescriptor.ScreenWidth]
+ mul ecx
+ movzx ecx, [ebx + sizeof.gif.Image + gif.LogicalScreenDescriptor.ScreenHeight]
+ mul ecx
+ invoke mem.realloc, [aux_img_data], eax
+ pop ecx edx
+ test eax, eax
+ jz @f
+ mov [aux_img_type], ecx
+ mov [aux_img_data], eax
+@@: retn
+
+endp
+
+;;================================================================================================;;
+proc img.decode.gif._.alloc_aux_palette ;/////////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? Allocate and fill aux_palette ;;
+;;------------------------------------------------------------------------------------------------;;
+;> esi -> palette, ecx = palette size ;;
+;;------------------------------------------------------------------------------------------------;;
+;< [aux_palette] set ;;
+;;================================================================================================;;
+ mov eax, [aux_palette]
+ test eax, eax
+ jnz @f
+ push edx ecx
+ invoke mem.alloc, 0x400
+ pop ecx edx
+ test eax, eax
+ jz .ret
+ mov [aux_palette], eax
+@@:
+ mov edi, eax
+ rep movsd
+.ret:
+ retn
+
+endp
+
+restore main_img
+restore transparent_color
+restore background_color
+restore prev_num_colors
+restore prev_palette
+restore max_color
+restore prev_img_data
+restore _data
+restore aux_img_data
+restore aux_img_type
+restore aux_palette
+
+;;================================================================================================;;
+;;////////////////////////////////////////////////////////////////////////////////////////////////;;
+;;================================================================================================;;
+;! Below is private data you should never use directly from your code ;;
+;;================================================================================================;;
+;;////////////////////////////////////////////////////////////////////////////////////////////////;;
+;;================================================================================================;;
+
+
+;
diff --git a/programs/develop/libraries/libs-dev/libimg/gif/gif.inc b/programs/develop/libraries/libs-dev/libimg/gif/gif.inc
index d45a7ff31..72b738e5d 100644
--- a/programs/develop/libraries/libs-dev/libimg/gif/gif.inc
+++ b/programs/develop/libraries/libs-dev/libimg/gif/gif.inc
@@ -1,142 +1,142 @@
-;;================================================================================================;;
-;;//// gif.inc //// (c) mike.dld, 2007-2008 //////////////////////////////////////////////////////;;
-;;================================================================================================;;
-;; ;;
-;; This file is part of Common development libraries (Libs-Dev). ;;
-;; ;;
-;; Libs-Dev is free software: you can redistribute it and/or modify it under the terms of the GNU ;;
-;; Lesser General Public License as published by the Free Software Foundation, either version 2.1 ;;
-;; of the License, or (at your option) any later version. ;;
-;; ;;
-;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without ;;
-;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;
-;; Lesser General Public License for more details. ;;
-;; ;;
-;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;;
-;; If not, see . ;;
-;; ;;
-;;================================================================================================;;
-
-
-struct gif.FileHeader ; GIF87a
- Signature db 3 dup(?) ; Header Signature (always "GIF")
- Version db 3 dup(?) ; GIF format version("87a" or "89a")
-ends
-
-struct gif.LogicalScreenDescriptor ; GIF87a
- ScreenWidth dw ? ; Width of Display Screen in Pixels
- ScreenHeight dw ? ; Height of Display Screen in Pixels
- Packed db ? ; Screen and Color Map Information
- BackgroundColor db ? ; Background Color Index
- AspectRatio db ? ; Pixel Aspect Ratio
-ends
-
-gif.LSD.Packed.SizeOfGlobalColorTableMask = 000000111b
-gif.LSD.Packed.SizeOfGlobalColorTableShift = 0
-gif.LSD.Packed.ColorTableSortFlag = 000001000b
-gif.LSD.Packed.ColorTableSortShift = 3
-gif.LSD.Packed.ColorResolutionMask = 001110000b
-gif.LSD.Packed.ColorResolutionShift = 4
-gif.LSD.Packed.GlobalColorTableFlag = 010000000b
-gif.LSD.Packed.GlobalColorTableShift = 7
-
-struct gif.Header
- file gif.FileHeader
- lsd gif.LogicalScreenDescriptor
-ends
-
-struct gif.RgbTriplet ; GIF87a
- Red db ? ; Red Color Element
- Green db ? ; Green Color Element
- Blue db ? ; Blue Color Element
-ends
-
-struct gif.Block
- Introducer db ?
-ends
-
-gif.Block.Introducer.EndOfData = 0x00
-gif.Block.Introducer.Extension = 0x21
-gif.Block.Introducer.ImageDescriptor = 0x2C
-gif.Block.Introducer.EndOfFile = 0x3B
-
-struct gif.ImageDescriptor ; GIF87a
-; we read Introducer before parsing gif.ImageDescriptor,
-; so it is convenient to not include it in struct
-; b gif.Block ; Introducer = 2Ch (',')
- Left dw ? ; X position of image on the display
- Top dw ? ; Y position of image on the display
- Width dw ? ; Width of the image in pixels
- Height dw ? ; Height of the image in pixels
- Packed db ? ; Image and Color Table Data Information
-ends
-
-gif.ID.Packed.SizeOfLocalColorTableMask = 000000111b
-gif.ID.Packed.SizeOfLocalColorTableShift = 0
-gif.ID.Packed.SortFlag = 000100000b
-gif.ID.Packed.SortShift = 5
-gif.ID.Packed.InterleaceFlag = 001000000b
-gif.ID.Packed.InterleaceShift = 6
-gif.ID.Packed.LocalColorTableFlag = 010000000b
-gif.ID.Packed.LocalColorTableShift = 7
-
-struct gif.Extension
- b gif.Block ; Introducer = 21h ('|')
- Label db ? ; Extension label
-ends
-
-gif.Extension.Label.PlainText = 0x01
-gif.Extension.Label.GraphicsControl = 0xF9
-gif.Extension.Label.Comment = 0xFE
-gif.Extension.Label.Application = 0xFF
-
-struct gif.PlainTextExtension ; GIF89a
-; e gif.Extension ; Label = 01h
-; BlockSize db ? ; Size of Extension Block (always 0Ch)
- TextGridLeft dw ? ; X position of text grid in pixels
- TextGridTop dw ? ; Y position of text grid in pixels
- TextGridWidth dw ? ; Width of the text grid in pixels
- TextGridHeight dw ? ; Height of the text grid in pixels
- CellWidth db ? ; Width of a grid cell in pixels
- CellHeight db ? ; Height of a grid cell in pixels
- TextFgColorIndex db ? ; Text foreground color index value
- TextBgColorIndex db ? ; Text background color index value
- PlainTextData db ? ; The Plain Text data (*)
-; Terminator db ? ; Block Terminator (always 0)
-ends
-
-struct gif.GraphicsControlExtension ; GIF89a
-; e gif.Extension ; Label = F9h
-; BlockSize db ? ; Size of remaining fields (always 04h)
-; previous fields are not included in this structure for convenience
-; (they are parsed before this)
- Packed db ? ; Method of graphics disposal to use
- DelayTime dw ? ; Hundredths of seconds to wait
- ColorIndex db ? ; Transparent Color Index
-; Terminator db ? ; Block Terminator (always 0)
-ends
-
-struct gif.CommentExtension ; GIF89a
- e gif.Extension ; Label = FEh
- CommentData db ? ; Pointer to Comment Data sub-blocks (*)
-; Terminator db ? ; Block Terminator (always 0)
-ends
-
-struct gif.ApplicationExtension ; GIF89a
- e gif.Extension ; Label = FFh
- BlockSize db ? ; Size of Extension Block (always 0Bh)
- Identifier db 8 dup(?) ; Application Identifier
- AuthentCode db 3 dup(?) ; Application Authentication Code
- ApplicationData db ? ; Point to Application Data sub-blocks (*)
-; Terminator db ? ; Block Terminator (always 0)
-ends
-
-;;------------------------------------------------------------------------------------------------;;
-
-struct gif.Image
- info gif.ImageDescriptor
- gce gif.GraphicsControlExtension
-; lsd gif.LogicalScreenDescriptor ; saved only in first image
-ends
-
-gif.Null equ 0x1000
+;;================================================================================================;;
+;;//// gif.inc //// (c) mike.dld, 2007-2008 //////////////////////////////////////////////////////;;
+;;================================================================================================;;
+;; ;;
+;; This file is part of Common development libraries (Libs-Dev). ;;
+;; ;;
+;; Libs-Dev is free software: you can redistribute it and/or modify it under the terms of the GNU ;;
+;; Lesser General Public License as published by the Free Software Foundation, either version 2.1 ;;
+;; of the License, or (at your option) any later version. ;;
+;; ;;
+;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without ;;
+;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;
+;; Lesser General Public License for more details. ;;
+;; ;;
+;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;;
+;; If not, see . ;;
+;; ;;
+;;================================================================================================;;
+
+
+struct gif.FileHeader ; GIF87a
+ Signature db 3 dup(?) ; Header Signature (always "GIF")
+ Version db 3 dup(?) ; GIF format version("87a" or "89a")
+ends
+
+struct gif.LogicalScreenDescriptor ; GIF87a
+ ScreenWidth dw ? ; Width of Display Screen in Pixels
+ ScreenHeight dw ? ; Height of Display Screen in Pixels
+ Packed db ? ; Screen and Color Map Information
+ BackgroundColor db ? ; Background Color Index
+ AspectRatio db ? ; Pixel Aspect Ratio
+ends
+
+gif.LSD.Packed.SizeOfGlobalColorTableMask = 000000111b
+gif.LSD.Packed.SizeOfGlobalColorTableShift = 0
+gif.LSD.Packed.ColorTableSortFlag = 000001000b
+gif.LSD.Packed.ColorTableSortShift = 3
+gif.LSD.Packed.ColorResolutionMask = 001110000b
+gif.LSD.Packed.ColorResolutionShift = 4
+gif.LSD.Packed.GlobalColorTableFlag = 010000000b
+gif.LSD.Packed.GlobalColorTableShift = 7
+
+struct gif.Header
+ file gif.FileHeader
+ lsd gif.LogicalScreenDescriptor
+ends
+
+struct gif.RgbTriplet ; GIF87a
+ Red db ? ; Red Color Element
+ Green db ? ; Green Color Element
+ Blue db ? ; Blue Color Element
+ends
+
+struct gif.Block
+ Introducer db ?
+ends
+
+gif.Block.Introducer.EndOfData = 0x00
+gif.Block.Introducer.Extension = 0x21
+gif.Block.Introducer.ImageDescriptor = 0x2C
+gif.Block.Introducer.EndOfFile = 0x3B
+
+struct gif.ImageDescriptor ; GIF87a
+; we read Introducer before parsing gif.ImageDescriptor,
+; so it is convenient to not include it in struct
+; b gif.Block ; Introducer = 2Ch (',')
+ Left dw ? ; X position of image on the display
+ Top dw ? ; Y position of image on the display
+ Width dw ? ; Width of the image in pixels
+ Height dw ? ; Height of the image in pixels
+ Packed db ? ; Image and Color Table Data Information
+ends
+
+gif.ID.Packed.SizeOfLocalColorTableMask = 000000111b
+gif.ID.Packed.SizeOfLocalColorTableShift = 0
+gif.ID.Packed.SortFlag = 000100000b
+gif.ID.Packed.SortShift = 5
+gif.ID.Packed.InterleaceFlag = 001000000b
+gif.ID.Packed.InterleaceShift = 6
+gif.ID.Packed.LocalColorTableFlag = 010000000b
+gif.ID.Packed.LocalColorTableShift = 7
+
+struct gif.Extension
+ b gif.Block ; Introducer = 21h ('|')
+ Label db ? ; Extension label
+ends
+
+gif.Extension.Label.PlainText = 0x01
+gif.Extension.Label.GraphicsControl = 0xF9
+gif.Extension.Label.Comment = 0xFE
+gif.Extension.Label.Application = 0xFF
+
+struct gif.PlainTextExtension ; GIF89a
+; e gif.Extension ; Label = 01h
+; BlockSize db ? ; Size of Extension Block (always 0Ch)
+ TextGridLeft dw ? ; X position of text grid in pixels
+ TextGridTop dw ? ; Y position of text grid in pixels
+ TextGridWidth dw ? ; Width of the text grid in pixels
+ TextGridHeight dw ? ; Height of the text grid in pixels
+ CellWidth db ? ; Width of a grid cell in pixels
+ CellHeight db ? ; Height of a grid cell in pixels
+ TextFgColorIndex db ? ; Text foreground color index value
+ TextBgColorIndex db ? ; Text background color index value
+ PlainTextData db ? ; The Plain Text data (*)
+; Terminator db ? ; Block Terminator (always 0)
+ends
+
+struct gif.GraphicsControlExtension ; GIF89a
+; e gif.Extension ; Label = F9h
+; BlockSize db ? ; Size of remaining fields (always 04h)
+; previous fields are not included in this structure for convenience
+; (they are parsed before this)
+ Packed db ? ; Method of graphics disposal to use
+ DelayTime dw ? ; Hundredths of seconds to wait
+ ColorIndex db ? ; Transparent Color Index
+; Terminator db ? ; Block Terminator (always 0)
+ends
+
+struct gif.CommentExtension ; GIF89a
+ e gif.Extension ; Label = FEh
+ CommentData db ? ; Pointer to Comment Data sub-blocks (*)
+; Terminator db ? ; Block Terminator (always 0)
+ends
+
+struct gif.ApplicationExtension ; GIF89a
+ e gif.Extension ; Label = FFh
+ BlockSize db ? ; Size of Extension Block (always 0Bh)
+ Identifier db 8 dup(?) ; Application Identifier
+ AuthentCode db 3 dup(?) ; Application Authentication Code
+ ApplicationData db ? ; Point to Application Data sub-blocks (*)
+; Terminator db ? ; Block Terminator (always 0)
+ends
+
+;;------------------------------------------------------------------------------------------------;;
+
+struct gif.Image
+ info gif.ImageDescriptor
+ gce gif.GraphicsControlExtension
+; lsd gif.LogicalScreenDescriptor ; saved only in first image
+ends
+
+gif.Null equ 0x1000
diff --git a/programs/develop/libraries/libs-dev/libimg/ico_cur/ico_cur.asm b/programs/develop/libraries/libs-dev/libimg/ico_cur/ico_cur.asm
index 503f2f715..baef0d622 100644
--- a/programs/develop/libraries/libs-dev/libimg/ico_cur/ico_cur.asm
+++ b/programs/develop/libraries/libs-dev/libimg/ico_cur/ico_cur.asm
@@ -1,372 +1,372 @@
-;;================================================================================================;;
-;;//// ico.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 ;;
-;; Lesser General Public License as published by the Free Software Foundation, either version 2.1 ;;
-;; of the License, or (at your option) any later version. ;;
-;; ;;
-;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without ;;
-;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;
-;; Lesser General Public License for more details. ;;
-;; ;;
-;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;;
-;; If not, see . ;;
-;; ;;
-;;================================================================================================;;
-;; ;;
-;; References: ;;
-;; 1. "Icons in Win32" ;;
-;; by John Hornick, Microsoft Corporation ;;
-;; http://msdn2.microsoft.com/en-us/library/ms997538.aspx ;;
-;; ;;
-;;================================================================================================;;
-
-include 'ico_cur.inc'
-
-;;================================================================================================;;
-;;proc img.is.ico _data, _length ;////////////////////////////////////////////////////////////////;;
-img.is.ico:
- mov edx, 0x00010000 ; icon type = 1
- jmp @f
-img.is.cur:
- mov edx, 0x00020000 ; cursor type = 2
-@@:
-;;------------------------------------------------------------------------------------------------;;
-;? Determine if raw data could be decoded (is in ICO format) ;;
-;;------------------------------------------------------------------------------------------------;;
-;> _data = raw data as read from file/stream ;;
-;> _length = data length ;;
-;;------------------------------------------------------------------------------------------------;;
-;< eax = false / true ;;
-;;================================================================================================;;
-; test 1 (length of data): data must contain FileHeader
- mov ecx, [esp+8]
- sub ecx, sizeof.ico.FileHeader
- jb .nope
-; test 2: signature
- mov eax, [esp+4]
- cmp dword [eax], edx ; Reserved & Type
- jne .nope
-; test 3: count must be non-zero
- movzx eax, [eax + ico.FileHeader.Count]
- test eax, eax
- jz .nope
-; test 4 (length of data): data must containt Count dir entries
- shl eax, 4
- sub ecx, eax
- jae .yep
-
- .nope:
- xor eax, eax
- ret 8
-
- .yep:
- xor eax, eax
- inc eax
- ret 8
-;endp
-
-;;================================================================================================;;
-proc img.decode.ico_cur _data, _length, _options ;////////////////////////////////////////////////;;
-;;------------------------------------------------------------------------------------------------;;
-;? Decode data into image if it contains correctly formed raw data in ICO/CUR format ;;
-;;------------------------------------------------------------------------------------------------;;
-;> _data = raw data as read from file/stream ;;
-;> _length = data length ;;
-;> _options = options for decoding (e.g. background color) ;;
-;;------------------------------------------------------------------------------------------------;;
-;< eax = 0 (error) or pointer to image ;;
-;;================================================================================================;;
-locals
- count dd ?
- img dd ?
- main_img dd ?
-endl
-
- push ebx esi edi
-
-; img.is.ico has been already called by img.decode
-; stdcall img.is.ico, [_data], [_length]
-; or eax, eax
-; jz .error
-
- mov ebx, [_data]
- movzx eax, [ebx + ico.FileHeader.Count]
- mov [count], eax
- and [img], 0
- and [main_img], 0
-.loop:
- mov ecx, [ebx + sizeof.ico.FileHeader + ico.DirEntry.ByteSize]
- mov edx, [ebx + sizeof.ico.FileHeader + ico.DirEntry.ImageOffset]
- mov eax, [_length]
- sub eax, edx
- jb .skip
- cmp eax, ecx
- jb .skip
- cmp ecx, 12 ; length test, see img.is.bmp
- jb .skip
- add edx, [_data]
- push [_options]
- push ecx
- push edx
- call img.decode.ico._.decode_icon_data
- test eax, eax
- jz .skip
- push 0xFFFFFF ; set bgr to white if no given
- mov edx, [_options]
- test edx, edx
- jz @f
- cmp [edx + ImageDecodeOptions.UsedSize], ImageDecodeOptions.BackgroundColor + 4
- jb @f
- add esp, 4
- push [edx + ImageDecodeOptions.BackgroundColor]
-@@:
- call img.decode.ico._.decode_icon_mask
- test eax, eax
- jz .skip
- mov edx, [img]
- test edx, edx
- jz .first
- mov [edx + Image.Next], eax
- mov [eax + Image.Previous], edx
- jmp @f
-.first:
- mov [main_img], eax
-@@:
- mov [img], eax
-.skip:
- add ebx, sizeof.ico.DirEntry
- dec [count]
- jnz .loop
-
- mov eax, [main_img]
- pop edi esi ebx
- ret
-endp
-
-;;================================================================================================;;
-img.encode.cur:
-proc img.encode.ico _img, _p_length, _options ;///////////////////////////////////////////////////;;
-;;------------------------------------------------------------------------------------------------;;
-;? Encode image into raw data in ICO format ;;
-;;------------------------------------------------------------------------------------------------;;
-;> _img = pointer to image ;;
-;;------------------------------------------------------------------------------------------------;;
-;< eax = 0 (error) or pointer to encoded data ;;
-;< _p_length = encoded data length ;;
-;;================================================================================================;;
- xor eax, eax
- ret
-endp
-
-
-;;================================================================================================;;
-;;////////////////////////////////////////////////////////////////////////////////////////////////;;
-;;================================================================================================;;
-;! Below are private procs you should never call directly from your code ;;
-;;================================================================================================;;
-;;////////////////////////////////////////////////////////////////////////////////////////////////;;
-;;================================================================================================;;
-
-img.decode.ico._.decode_icon_data:
-; create stack frame and jump to common BMP+ICO code
- push ebp
- mov ebp, esp
- sub esp, 12
- mov byte [ebp - 3], 1 ; bIsIco
- jmp img.decode.bmp.common
-
-img.decode.ico._.decode_icon_mask:
- mov edx, [eax + Image.Width]
- add edx, 31
- shr edx, 3
- and edx, not 3
- push edx
- imul edx, [eax + Image.Height]
- cmp ecx, edx
- pop edx
- jb .error.free
- mov edi, [eax + Image.Data]
- push ebp ebx eax
- xor ebp, ebp
- mov ebx, [eax + Image.Extended]
- cmp [ebx + bmp.Image.info.Height], 0
- js @f
- push edx
- imul edx, [eax + Image.Height]
- add esi, edx
- pop edx
- lea ebp, [edx+edx]
- sub esi, edx
-@@:
- mov ebx, [eax + Image.Height]
- mov ecx, [eax + Image.Width]
-; for now, BMP code produces only 8 and 32 bpp images
- cmp [eax + Image.Type], Image.bpp8i
- jz .bpp8
-.bpp32:
- mov edx, [esp+16] ; get background color
-.bpp32.extloop:
- push ecx
-.bpp32.innloop:
- lodsd
- bswap eax
- push 32
-.bpp32.dwordloop:
- add eax, eax
- jnc @f
- mov [edi], edx
-@@:
- add edi, 4
- dec ecx
- jz @f
- dec dword [esp]
- jnz .bpp32.dwordloop
-@@:
- pop eax
- test ecx, ecx
- jnz .bpp32.innloop
- sub esi, ebp
- pop ecx
- dec ebx
- jnz .bpp32.extloop
- pop eax ebx ebp
- ret 4
-.bpp8:
- push edi
- mov edi, [eax + Image.Palette]
- mov eax, [esp+20] ; get background color
-; if palette already has index for bgr color, use it
- push ecx
- mov ecx, 256
- repnz scasd
- jnz .bpp8.notfound
- not cl ; cl = index
- pop edx
- pop edi
-.bpp8.extloop:
- push edx
-.bpp8.innloop:
- lodsd
- bswap eax
- push 32
-.bpp8.dwordloop:
- add eax, eax
- jnc @f
- mov [edi], cl
-@@:
- inc edi
- dec edx
- jz @f
- dec dword [esp]
- jnz .bpp8.dwordloop
-@@:
- pop eax
- test edx, edx
- jnz .bpp8.innloop
- sub esi, ebp
- pop edx
- dec ebx
- jnz .bpp8.extloop
- pop eax ebx ebp
- ret 4
-.bpp8.notfound:
-; get maximum used color; if index < 255, then we can add one color to palette
- pop ecx
- pop edi
- pop eax
- mov edx, [eax + Image.Width]
- imul edx, ebx
- mov edi, [eax + Image.Data]
- xor ecx, ecx
-.bpp8.scanloop:
- cmp [edi], cl
- jb @f
- mov cl, [edi]
-@@:
- inc edi
- dec edx
- jnz .bpp8.scanloop
- inc cl
- jz .bpp8.nospace
- mov edx, [esp+8]
- mov edi, [eax + Image.Palette]
- mov [edi+ecx*4], edx ; set palette color
- mov edi, [eax + Image.Data]
- mov edx, [eax + Image.Width]
- push eax
- jmp .bpp8.extloop
-.bpp8.nospace:
-; convert to 24 bpp
- mov edx, [eax + Image.Width]
- imul edx, ebx
- lea edx, [edx*3]
- push eax
- invoke mem.alloc, edx
- mov edi, eax
- pop eax
- test edi, edi
- jz .error.free2
- push eax esi edi
- mov esi, eax
- call img._.do_rgb
- pop edi esi eax
- xchg edi, [eax + Image.Data]
- mov byte [eax + Image.Type], Image.bpp24
- push eax
- invoke mem.free, edi
- pop eax
- push eax
- mov ecx, [eax + Image.Width]
- mov edi, [eax + Image.Data]
-.bpp24:
- mov edx, [esp+16] ; get background color
-.bpp24.extloop:
- push ecx
-.bpp24.innloop:
- lodsd
- bswap eax
- push 32
-.bpp24.dwordloop:
- add eax, eax
- jnc @f
- mov [edi], dx
- ror edx, 16
- mov [edi+2], dl
- ror edx, 16
-@@:
- add edi, 3
- dec ecx
- jz @f
- dec dword [esp]
- jnz .bpp24.dwordloop
-@@:
- pop eax
- test ecx, ecx
- jnz .bpp24.innloop
- sub esi, ebp
- pop ecx
- dec ebx
- jnz .bpp24.extloop
- pop eax ebx ebp
- ret 4
-.error.free2:
- pop ebx ebp
-.error.free:
- stdcall img._.delete, eax
- xor eax, eax
- ret 4
-
-;;================================================================================================;;
-;;////////////////////////////////////////////////////////////////////////////////////////////////;;
-;;================================================================================================;;
-;! Below is private data you should never use directly from your code ;;
-;;================================================================================================;;
-;;////////////////////////////////////////////////////////////////////////////////////////////////;;
-;;================================================================================================;;
-
-
-;
+;;================================================================================================;;
+;;//// ico.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 ;;
+;; Lesser General Public License as published by the Free Software Foundation, either version 2.1 ;;
+;; of the License, or (at your option) any later version. ;;
+;; ;;
+;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without ;;
+;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;
+;; Lesser General Public License for more details. ;;
+;; ;;
+;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;;
+;; If not, see . ;;
+;; ;;
+;;================================================================================================;;
+;; ;;
+;; References: ;;
+;; 1. "Icons in Win32" ;;
+;; by John Hornick, Microsoft Corporation ;;
+;; http://msdn2.microsoft.com/en-us/library/ms997538.aspx ;;
+;; ;;
+;;================================================================================================;;
+
+include 'ico_cur.inc'
+
+;;================================================================================================;;
+;;proc img.is.ico _data, _length ;////////////////////////////////////////////////////////////////;;
+img.is.ico:
+ mov edx, 0x00010000 ; icon type = 1
+ jmp @f
+img.is.cur:
+ mov edx, 0x00020000 ; cursor type = 2
+@@:
+;;------------------------------------------------------------------------------------------------;;
+;? Determine if raw data could be decoded (is in ICO format) ;;
+;;------------------------------------------------------------------------------------------------;;
+;> _data = raw data as read from file/stream ;;
+;> _length = data length ;;
+;;------------------------------------------------------------------------------------------------;;
+;< eax = false / true ;;
+;;================================================================================================;;
+; test 1 (length of data): data must contain FileHeader
+ mov ecx, [esp+8]
+ sub ecx, sizeof.ico.FileHeader
+ jb .nope
+; test 2: signature
+ mov eax, [esp+4]
+ cmp dword [eax], edx ; Reserved & Type
+ jne .nope
+; test 3: count must be non-zero
+ movzx eax, [eax + ico.FileHeader.Count]
+ test eax, eax
+ jz .nope
+; test 4 (length of data): data must containt Count dir entries
+ shl eax, 4
+ sub ecx, eax
+ jae .yep
+
+ .nope:
+ xor eax, eax
+ ret 8
+
+ .yep:
+ xor eax, eax
+ inc eax
+ ret 8
+;endp
+
+;;================================================================================================;;
+proc img.decode.ico_cur _data, _length, _options ;////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? Decode data into image if it contains correctly formed raw data in ICO/CUR format ;;
+;;------------------------------------------------------------------------------------------------;;
+;> _data = raw data as read from file/stream ;;
+;> _length = data length ;;
+;> _options = options for decoding (e.g. background color) ;;
+;;------------------------------------------------------------------------------------------------;;
+;< eax = 0 (error) or pointer to image ;;
+;;================================================================================================;;
+locals
+ count dd ?
+ img dd ?
+ main_img dd ?
+endl
+
+ push ebx esi edi
+
+; img.is.ico has been already called by img.decode
+; stdcall img.is.ico, [_data], [_length]
+; or eax, eax
+; jz .error
+
+ mov ebx, [_data]
+ movzx eax, [ebx + ico.FileHeader.Count]
+ mov [count], eax
+ and [img], 0
+ and [main_img], 0
+.loop:
+ mov ecx, [ebx + sizeof.ico.FileHeader + ico.DirEntry.ByteSize]
+ mov edx, [ebx + sizeof.ico.FileHeader + ico.DirEntry.ImageOffset]
+ mov eax, [_length]
+ sub eax, edx
+ jb .skip
+ cmp eax, ecx
+ jb .skip
+ cmp ecx, 12 ; length test, see img.is.bmp
+ jb .skip
+ add edx, [_data]
+ push [_options]
+ push ecx
+ push edx
+ call img.decode.ico._.decode_icon_data
+ test eax, eax
+ jz .skip
+ push 0xFFFFFF ; set bgr to white if no given
+ mov edx, [_options]
+ test edx, edx
+ jz @f
+ cmp [edx + ImageDecodeOptions.UsedSize], ImageDecodeOptions.BackgroundColor + 4
+ jb @f
+ add esp, 4
+ push [edx + ImageDecodeOptions.BackgroundColor]
+@@:
+ call img.decode.ico._.decode_icon_mask
+ test eax, eax
+ jz .skip
+ mov edx, [img]
+ test edx, edx
+ jz .first
+ mov [edx + Image.Next], eax
+ mov [eax + Image.Previous], edx
+ jmp @f
+.first:
+ mov [main_img], eax
+@@:
+ mov [img], eax
+.skip:
+ add ebx, sizeof.ico.DirEntry
+ dec [count]
+ jnz .loop
+
+ mov eax, [main_img]
+ pop edi esi ebx
+ ret
+endp
+
+;;================================================================================================;;
+img.encode.cur:
+proc img.encode.ico _img, _p_length, _options ;///////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? Encode image into raw data in ICO format ;;
+;;------------------------------------------------------------------------------------------------;;
+;> _img = pointer to image ;;
+;;------------------------------------------------------------------------------------------------;;
+;< eax = 0 (error) or pointer to encoded data ;;
+;< _p_length = encoded data length ;;
+;;================================================================================================;;
+ xor eax, eax
+ ret
+endp
+
+
+;;================================================================================================;;
+;;////////////////////////////////////////////////////////////////////////////////////////////////;;
+;;================================================================================================;;
+;! Below are private procs you should never call directly from your code ;;
+;;================================================================================================;;
+;;////////////////////////////////////////////////////////////////////////////////////////////////;;
+;;================================================================================================;;
+
+img.decode.ico._.decode_icon_data:
+; create stack frame and jump to common BMP+ICO code
+ push ebp
+ mov ebp, esp
+ sub esp, 12
+ mov byte [ebp - 3], 1 ; bIsIco
+ jmp img.decode.bmp.common
+
+img.decode.ico._.decode_icon_mask:
+ mov edx, [eax + Image.Width]
+ add edx, 31
+ shr edx, 3
+ and edx, not 3
+ push edx
+ imul edx, [eax + Image.Height]
+ cmp ecx, edx
+ pop edx
+ jb .error.free
+ mov edi, [eax + Image.Data]
+ push ebp ebx eax
+ xor ebp, ebp
+ mov ebx, [eax + Image.Extended]
+ cmp [ebx + bmp.Image.info.Height], 0
+ js @f
+ push edx
+ imul edx, [eax + Image.Height]
+ add esi, edx
+ pop edx
+ lea ebp, [edx+edx]
+ sub esi, edx
+@@:
+ mov ebx, [eax + Image.Height]
+ mov ecx, [eax + Image.Width]
+; for now, BMP code produces only 8 and 32 bpp images
+ cmp [eax + Image.Type], Image.bpp8i
+ jz .bpp8
+.bpp32:
+ mov edx, [esp+16] ; get background color
+.bpp32.extloop:
+ push ecx
+.bpp32.innloop:
+ lodsd
+ bswap eax
+ push 32
+.bpp32.dwordloop:
+ add eax, eax
+ jnc @f
+ mov [edi], edx
+@@:
+ add edi, 4
+ dec ecx
+ jz @f
+ dec dword [esp]
+ jnz .bpp32.dwordloop
+@@:
+ pop eax
+ test ecx, ecx
+ jnz .bpp32.innloop
+ sub esi, ebp
+ pop ecx
+ dec ebx
+ jnz .bpp32.extloop
+ pop eax ebx ebp
+ ret 4
+.bpp8:
+ push edi
+ mov edi, [eax + Image.Palette]
+ mov eax, [esp+20] ; get background color
+; if palette already has index for bgr color, use it
+ push ecx
+ mov ecx, 256
+ repnz scasd
+ jnz .bpp8.notfound
+ not cl ; cl = index
+ pop edx
+ pop edi
+.bpp8.extloop:
+ push edx
+.bpp8.innloop:
+ lodsd
+ bswap eax
+ push 32
+.bpp8.dwordloop:
+ add eax, eax
+ jnc @f
+ mov [edi], cl
+@@:
+ inc edi
+ dec edx
+ jz @f
+ dec dword [esp]
+ jnz .bpp8.dwordloop
+@@:
+ pop eax
+ test edx, edx
+ jnz .bpp8.innloop
+ sub esi, ebp
+ pop edx
+ dec ebx
+ jnz .bpp8.extloop
+ pop eax ebx ebp
+ ret 4
+.bpp8.notfound:
+; get maximum used color; if index < 255, then we can add one color to palette
+ pop ecx
+ pop edi
+ pop eax
+ mov edx, [eax + Image.Width]
+ imul edx, ebx
+ mov edi, [eax + Image.Data]
+ xor ecx, ecx
+.bpp8.scanloop:
+ cmp [edi], cl
+ jb @f
+ mov cl, [edi]
+@@:
+ inc edi
+ dec edx
+ jnz .bpp8.scanloop
+ inc cl
+ jz .bpp8.nospace
+ mov edx, [esp+8]
+ mov edi, [eax + Image.Palette]
+ mov [edi+ecx*4], edx ; set palette color
+ mov edi, [eax + Image.Data]
+ mov edx, [eax + Image.Width]
+ push eax
+ jmp .bpp8.extloop
+.bpp8.nospace:
+; convert to 24 bpp
+ mov edx, [eax + Image.Width]
+ imul edx, ebx
+ lea edx, [edx*3]
+ push eax
+ invoke mem.alloc, edx
+ mov edi, eax
+ pop eax
+ test edi, edi
+ jz .error.free2
+ push eax esi edi
+ mov esi, eax
+ call img._.do_rgb
+ pop edi esi eax
+ xchg edi, [eax + Image.Data]
+ mov byte [eax + Image.Type], Image.bpp24
+ push eax
+ invoke mem.free, edi
+ pop eax
+ push eax
+ mov ecx, [eax + Image.Width]
+ mov edi, [eax + Image.Data]
+.bpp24:
+ mov edx, [esp+16] ; get background color
+.bpp24.extloop:
+ push ecx
+.bpp24.innloop:
+ lodsd
+ bswap eax
+ push 32
+.bpp24.dwordloop:
+ add eax, eax
+ jnc @f
+ mov [edi], dx
+ ror edx, 16
+ mov [edi+2], dl
+ ror edx, 16
+@@:
+ add edi, 3
+ dec ecx
+ jz @f
+ dec dword [esp]
+ jnz .bpp24.dwordloop
+@@:
+ pop eax
+ test ecx, ecx
+ jnz .bpp24.innloop
+ sub esi, ebp
+ pop ecx
+ dec ebx
+ jnz .bpp24.extloop
+ pop eax ebx ebp
+ ret 4
+.error.free2:
+ pop ebx ebp
+.error.free:
+ stdcall img._.delete, eax
+ xor eax, eax
+ ret 4
+
+;;================================================================================================;;
+;;////////////////////////////////////////////////////////////////////////////////////////////////;;
+;;================================================================================================;;
+;! Below is private data you should never use directly from your code ;;
+;;================================================================================================;;
+;;////////////////////////////////////////////////////////////////////////////////////////////////;;
+;;================================================================================================;;
+
+
+;
diff --git a/programs/develop/libraries/libs-dev/libimg/ico_cur/ico_cur.inc b/programs/develop/libraries/libs-dev/libimg/ico_cur/ico_cur.inc
index 148c11e73..b2fabc906 100644
--- a/programs/develop/libraries/libs-dev/libimg/ico_cur/ico_cur.inc
+++ b/programs/develop/libraries/libs-dev/libimg/ico_cur/ico_cur.inc
@@ -1,46 +1,46 @@
-;;================================================================================================;;
-;;//// ico.inc //// (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 ;;
-;; 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 ico.FileHeader
- Reserved dw ? ; must be 0
- Type dw ? ; must be 1
- Count dw ?
-ends
-
-struct ico.DirEntry
- Width db ?
- Height db ?
- ColorCount db ?
- db ? ; reseved
- dw ? ; reserved
- dw ? ; reserved
- ByteSize dd ?
- ImageOffset dd ?
-ends
-
-struct cur.DirEntry
- Width db ?
- Height db ?
- ColorCount db ?
- db ? ; reserved
- XHotSpot dw ?
- YHotSpot dw ?
- ByteSize dd ?
- ImageOffset dd ?
-ends
+;;================================================================================================;;
+;;//// ico.inc //// (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 ;;
+;; 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 ico.FileHeader
+ Reserved dw ? ; must be 0
+ Type dw ? ; must be 1
+ Count dw ?
+ends
+
+struct ico.DirEntry
+ Width db ?
+ Height db ?
+ ColorCount db ?
+ db ? ; reseved
+ dw ? ; reserved
+ dw ? ; reserved
+ ByteSize dd ?
+ ImageOffset dd ?
+ends
+
+struct cur.DirEntry
+ Width db ?
+ Height db ?
+ ColorCount db ?
+ db ? ; reserved
+ XHotSpot dw ?
+ YHotSpot dw ?
+ ByteSize dd ?
+ ImageOffset dd ?
+ends
diff --git a/programs/develop/libraries/libs-dev/libimg/jpeg/jpeg.asm b/programs/develop/libraries/libs-dev/libimg/jpeg/jpeg.asm
index 9ad8750aa..921445da7 100644
--- a/programs/develop/libraries/libs-dev/libimg/jpeg/jpeg.asm
+++ b/programs/develop/libraries/libs-dev/libimg/jpeg/jpeg.asm
@@ -1,2231 +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 12
-.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.bpp8i
- pop eax ; Image.bpp8i = 1
- cmp edi, eax
- 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
- test ebp, ebp
- setnp al
- ror 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})
-;---------------------------------------------------------------------
+;;================================================================================================;;
+;;//// 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 12
+.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.bpp8i
+ pop eax ; Image.bpp8i = 1
+ cmp edi, eax
+ 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
+ test ebp, ebp
+ setnp al
+ ror 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
index 8be95adce..2cedfcc8d 100644
--- a/programs/develop/libraries/libs-dev/libimg/jpeg/jpeg.inc
+++ b/programs/develop/libraries/libs-dev/libimg/jpeg/jpeg.inc
@@ -1,96 +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
+;;================================================================================================;;
+;;//// 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 495e18af7..a77c5bb1a 100644
--- a/programs/develop/libraries/libs-dev/libimg/libimg.asm
+++ b/programs/develop/libraries/libs-dev/libimg/libimg.asm
@@ -22,14 +22,14 @@ format MS COFF
public @EXPORT as 'EXPORTS'
-include '../../../../struct.inc'
-include '../../../../proc32.inc'
-include '../../../../macros.inc'
-include '../../../../config.inc'
-include '../../../../debug-fdo.inc'
+include 'struct.inc'
+include 'proc32.inc'
+include 'macros.inc'
+include 'config.inc'
+include 'debug-fdo.inc'
__DEBUG__ = 0
__DEBUG_LEVEL__ = 1
-include '../../../../develop/libraries/libs-dev/libio/libio.inc'
+include 'libio.inc'
purge section,mov,add,sub
include 'libimg.inc'
@@ -53,6 +53,11 @@ include 'xbm/xbm.asm'
include 'scale.asm'
include 'convert.asm'
+COMPOSITE_MODE equ MMX
+; MMX | pretty fast and compatible
+; SSE | a bit faster, but may be unsupported by some CPUs
+include 'blend.asm'
+
;;================================================================================================;;
proc lib_init ;///////////////////////////////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;;
@@ -2743,6 +2748,7 @@ img._.get_scanline_len: ;///////////////////////////////////////////////////////
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
;;================================================================================================;;
+section '.data' data readable writable align 16
;include_debug_strings
align 4
@@ -2807,6 +2813,7 @@ export \
img.scale , 'img_scale' , \
img.get_scaled_size, 'img_get_scaled_size', \
img.convert , 'img_convert' , \
+ img.blend , 'img_blend' , \
img.formats_table , 'img_formats_table'
; import from deflate unpacker
@@ -2841,7 +2848,6 @@ gif_default_palette:
db 0, 0, 0
db 0xFF, 0xFF, 0xFF
-section '.data' data readable writable align 16
; uninitialized data - global constant tables
mem.alloc dd ?
mem.free dd ?
diff --git a/programs/develop/libraries/libs-dev/libimg/png/libpng/png.asm b/programs/develop/libraries/libs-dev/libimg/png/libpng/png.asm
index 869f19e6e..b933727d0 100644
--- a/programs/develop/libraries/libs-dev/libimg/png/libpng/png.asm
+++ b/programs/develop/libraries/libs-dev/libimg/png/libpng/png.asm
@@ -1,4726 +1,4726 @@
-
-; png.asm - location for general purpose libpng functions
-
-; Last changed in libpng 1.6.25 [September 1, 2016]
-; Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
-; (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
-; (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
-
-; This code is released under the libpng license.
-; For conditions of distribution and use, see the disclaimer
-; and license in png.inc
-
-DEBUG equ 0
-
-include '../../../../../../KOSfuncs.inc'
-include '../../../../../../fs/kfar/trunk/zlib/deflate.inc'
-include 'pngtokos.inc' ;integrate png to kos
-
-;files from libpng
-include 'pnglibconf.inc'
-include 'pngpriv.inc'
-include 'png.inc'
-include 'pngstruct.inc'
-include 'pnginfo.inc'
-include 'pngerror.asm'
-include 'pngtrans.asm'
-include 'pngget.asm'
-include 'pngwrite.asm'
-include 'pngmem.asm'
-include 'pngset.asm'
-include 'pngwutil.asm'
-include 'pngwio.asm'
-include 'pngwtran.asm'
-
-; Generate a compiler error if there is an old png.inc in the search path.
-;typedef png_libpng_version_1_6_25 Your_png_h_is_not_version_1_6_25;
-
-; Tells libpng that we have already handled the first "num_bytes" bytes
-; of the PNG file signature. If the PNG data is embedded into another
-; stream we can set num_bytes = 8 so that libpng will not attempt to read
-; or write any of the magic bytes before it starts on the IHDR.
-
-
-;if PNG_READ_SUPPORTED
-;void (png_structrp png_ptr, int num_bytes)
-align 4
-proc png_set_sig_bytes uses eax edi, png_ptr:dword, num_bytes:dword
- png_debug 1, 'in png_set_sig_bytes'
-
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f ;if (..==0) return
-
- mov eax,[num_bytes]
- cmp eax,0
- jge @f
- xor eax,eax
- @@:
- cmp eax,8
- jle @f ;if (..>8)
- png_error edi, 'Too many bytes for PNG signature'
- @@:
- mov byte[edi+png_struct.sig_bytes],al
-.end_f:
- ret
-endp
-
-; Checks whether the supplied bytes match the PNG signature. We allow
-; checking less than the full 8-byte signature so that those apps that
-; already read the first few bytes of a file to determine the file type
-; can simply check the remaining bytes for extra assurance. Returns
-; an integer less than, equal to, or greater than zero if sig is found,
-; respectively, to be less than, to match, or be greater than the correct
-; PNG signature (this is the same behavior as strcmp, memcmp, etc).
-
-;int (bytep sig, png_size_t start, png_size_t num_to_check)
-align 4
-proc png_sig_cmp, sig:dword, start:dword, num_to_check:dword
-; byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
-
-; if (num_to_check > 8)
-; num_to_check = 8;
-
-; else if (num_to_check < 1)
-; return (-1);
-
-; if (start > 7)
-; return (-1);
-
-; if (start + num_to_check > 8)
-; num_to_check = 8 - start;
-
-; return ((int)(memcmp(&sig[start], &png_signature[start], num_to_check)));
- ret
-endp
-
-;end if /* READ */
-
-; Function to allocate memory for zlib
-;voidpf (voidpf png_ptr, uInt items, uInt size)
-align 4
-proc png_zalloc uses edx ecx, png_ptr:dword, items:dword, size:dword
-
- cmp dword[png_ptr],0
- jne @f
- xor eax,eax
- jmp .end_f ;if (..==0) return 0
- @@:
-
- xor eax,eax
- not eax
- xor edx,edx
- mov ecx,[size]
- div ecx
- cmp [items],eax
- jl @f ;if (..>=..)
- png_warning [png_ptr], 'Potential overflow in png_zalloc()'
- xor eax,eax
- jmp .end_f
- @@:
-
- mov ecx,[size]
- imul ecx,[items]
- stdcall png_malloc_warn, [png_ptr], ecx
-.end_f:
- ret
-endp
-
-; Function to free memory for zlib
-;void (voidpf png_ptr, voidpf ptr)
-align 4
-proc png_zfree, png_ptr:dword, p2ptr:dword
- stdcall png_free, [png_ptr], [p2ptr]
- ret
-endp
-
-; Reset the CRC variable to 32 bits of 1's. Care must be taken
-; in case CRC is > 32 bits to leave the top bits 0.
-
-;void (png_structrp png_ptr)
-align 4
-proc png_reset_crc uses eax edi, png_ptr:dword
- ; The cast is safe because the crc is a 32-bit value.
- mov edi,[png_ptr]
- stdcall [calc_crc32], 0, Z_NULL, 0
- mov dword[edi+png_struct.crc],eax
- ret
-endp
-
-; Calculate the CRC over a section of data. We can only pass as
-; much data to this routine as the largest single buffer size. We
-; also check that this data will actually be used before going to the
-; trouble of calculating it.
-
-;void (png_structrp png_ptr, bytep ptr, png_size_t length)
-align 4
-proc png_calculate_crc uses eax ebx edi, png_ptr:dword, ptr:dword, length:dword
-locals
- need_crc dd 1
- safe_length dd ?
-endl
- mov edi,[png_ptr]
- PNG_CHUNK_ANCILLARY [edi+png_struct.chunk_name]
- cmp eax,0 ;if (..!=0)
- je @f
- mov eax,[edi+png_struct.flags]
- and eax,PNG_FLAG_CRC_ANCILLARY_MASK
- cmp eax,PNG_FLAG_CRC_ANCILLARY_USE or PNG_FLAG_CRC_ANCILLARY_NOWARN
- jne .end0 ;if (..==..)
- mov dword[need_crc],0
- jmp .end0
- @@: ;else ;critical
- mov eax,[edi+png_struct.flags]
- and eax,PNG_FLAG_CRC_CRITICAL_IGNORE
- jz .end0 ;if (..!=0)
- mov dword[need_crc],0
- .end0:
-
- ; 'uLong' is defined in zlib.inc as unsigned long; this means that on some
- ; systems it is a 64-bit value. crc32, however, returns 32 bits so the
- ; following cast is safe. 'uInt' may be no more than 16 bits, so it is
- ; necessary to perform a loop here.
-
- cmp dword[need_crc],0
- je .end_f
- cmp dword[length],0
- jle .end_f ;if (..!=0 && ..>0)
- mov eax,[edi+png_struct.crc] ;Should never issue a warning
-
- .cycle0: ;do
- mov ebx,[length]
- mov [safe_length],ebx
-;#ifndef __COVERITY__
-; if (safe_length == 0)
-; safe_length = (uInt)-1 ;evil, but safe
-;end if
- stdcall [calc_crc32], eax, [ptr], [safe_length]
-
- ; The following should never issue compiler warnings; if they do the
- ; target system has characteristics that will probably violate other
- ; assumptions within the libpng code.
-
- mov ebx,[safe_length]
- add [ptr],ebx
- sub [length],ebx
- cmp dword[length],0
- jg .cycle0 ;while (..>0)
-
- ; And the following is always safe because the crc is only 32 bits.
- mov [edi+png_struct.crc],eax
- .end_f:
- ret
-endp
-
-; Check a user supplied version number, called from both read and write
-; functions that create a png_struct.
-
-;int (png_structrp png_ptr, charp user_png_ver)
-align 4
-proc png_user_version_check, png_ptr:dword, user_png_ver:dword
- ; Libpng versions 1.0.0 and later are binary compatible if the version
- ; string matches through the second '.'; we must recompile any
- ; applications that use any older library version.
-
-; if (user_png_ver != NULL)
-; {
-; int i = -1;
-; int found_dots = 0;
-
-; do
-; {
-; i++;
-; if (user_png_ver[i] != PNG_LIBPNG_VER_STRING[i])
-; png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
-; if (user_png_ver[i] == '.')
-; found_dots++;
-; } while (found_dots < 2 && user_png_ver[i] != 0 &&
-; PNG_LIBPNG_VER_STRING[i] != 0);
-; }
-
-; else
-; png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
-
-; if ((png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) != 0)
-; {
-if PNG_WARNINGS_SUPPORTED eq 1
-; size_t pos = 0;
-; char m[128];
-
-; pos = png_safecat(m, (sizeof m), pos,
-; "Application built with libpng-");
-; pos = png_safecat(m, (sizeof m), pos, user_png_ver);
-; pos = png_safecat(m, (sizeof m), pos, " but running with ");
-; pos = png_safecat(m, (sizeof m), pos, PNG_LIBPNG_VER_STRING);
-
-; png_warning(png_ptr, m);
-end if
-
-if PNG_ERROR_NUMBERS_SUPPORTED eq 1
-; png_ptr->flags = 0;
-end if
-
-; return 0;
-; }
-
- ; Success return.
- xor eax,eax
- inc eax
-.end_f:
- ret
-endp
-
-; Generic function to create a png_struct for either read or write - this
-; contains the common initialization.
-
-;png_structp (charp user_png_ver, voidp error_ptr,
-; png_error_ptr error_fn, png_error_ptr warn_fn, voidp mem_ptr,
-; png_malloc_ptr malloc_fn, png_free_ptr free_fn)
-align 4
-proc png_create_png_struct uses ebx ecx edi esi, user_png_ver:dword, error_ptr:dword, error_fn:dword, warn_fn:dword, mem_ptr:dword, malloc_fn:dword, free_fn:dword
-locals
-if PNG_SETJMP_SUPPORTED eq 1
- create_jmp_buf dd ? ;jmp_buf
-end if
- create_struct png_struct
-endl
- ; This temporary stack-allocated structure is used to provide a place to
- ; build enough context to allow the user provided memory allocator (if any)
- ; to be called.
-
- xor eax,eax
- mov ecx,sizeof.png_struct
- mov edi,ebp
- sub edi,ecx
- mov ebx,edi
- rep stosb
-
- ; Added at libpng-1.2.6
-if PNG_USER_LIMITS_SUPPORTED eq 1
- mov dword[ebx+png_struct.user_width_max], PNG_USER_WIDTH_MAX
- mov dword[ebx+png_struct.user_height_max], PNG_USER_HEIGHT_MAX
-
- ; Added at libpng-1.2.43 and 1.4.0
- mov dword[ebx+png_struct.user_chunk_cache_max], PNG_USER_CHUNK_CACHE_MAX
-
- ; Added at libpng-1.2.43 and 1.4.1, required only for read but exists
- ; in png_struct regardless.
-
- mov dword[ebx+png_struct.user_chunk_malloc_max], PNG_USER_CHUNK_MALLOC_MAX
-end if
-
- ; The following two API calls simply set fields in png_struct, so it is safe
- ; to do them now even though error handling is not yet set up.
-
-if PNG_USER_MEM_SUPPORTED eq 1
- stdcall png_set_mem_fn, ebx, [mem_ptr], [malloc_fn], [free_fn]
-end if
-
- ; (*error_fn) can return control to the caller after the error_ptr is set,
- ; this will result in a memory leak unless the error_fn does something
- ; extremely sophisticated. The design lacks merit but is implicit in the
- ; API.
-
- stdcall png_set_error_fn, ebx, [error_ptr], [error_fn], [warn_fn]
-
-if PNG_SETJMP_SUPPORTED eq 1
- stdcall setjmp,... ;create_jmp_buf
- cmp eax,0
- j... .end0 ;if (!setjmp(create_jmp_buf))
-
- ; Temporarily fake out the longjmp information until we have
- ; successfully completed this function. This only works if we have
- ; setjmp() support compiled in, but it is safe - this stuff should
- ; never happen.
-
-; create_struct.jmp_buf_ptr = &create_jmp_buf;
- mov dword[ebx+png_struct.jmp_buf_size],0 ;stack allocation
-; create_struct.longjmp_fn = longjmp;
-end if
- ; Call the general version checker (shared with read and write code):
-
- stdcall png_user_version_check, ebx, [user_png_ver]
- cmp eax,0
- je .end0 ;if (..!=0)
- stdcall png_malloc_warn, ebx, sizeof.png_struct
- ;eax = png_ptr
- cmp eax,0
- je .end0 ;if (..!=0)
- ; png_ptr->zstream holds a back-pointer to the png_struct, so
- ; this can only be done now:
-
- mov [ebx+png_struct.zstream.zalloc], png_zalloc
- mov [ebx+png_struct.zstream.zfree], png_zfree
- mov [ebx+png_struct.zstream.opaque], eax
-
-if PNG_SETJMP_SUPPORTED eq 1
- ; Eliminate the local error handling:
- mov [ebx+png_struct.jmp_buf_ptr], 0
- mov [ebx+png_struct.jmp_buf_size], 0
- mov [ebx+png_struct.longjmp_fn], 0
-end if
- mov ecx,sizeof.png_struct
- mov edi,eax
- mov esi,ebx
- rep movsb ;*png_ptr = create_struct
-
- ; This is the successful return point
- jmp .end_f
- .end0:
-
- ; A longjmp because of a bug in the application storage allocator or a
- ; simple failure to allocate the png_struct.
-
- xor eax,eax
-.end_f:
- ret
-endp
-
-; Allocate the memory for an info_struct for the application.
-;png_infop (png_structrp png_ptr)
-align 4
-proc png_create_info_struct uses ebx ecx edi, png_ptr:dword
- png_debug 1, 'in png_create_info_struct'
- ;ebx - info_ptr dd ? ;png_inforp
-
- mov edi,[png_ptr]
- cmp edi,0
- jne @f ;if (..==0) return 0
- xor eax,eax
- jmp .end_f
- @@:
-
- ; Use the internal API that does not (or at least should not) error out, so
- ; that this call always returns ok. The application typically sets up the
- ; error handling *after* creating the info_struct because this is the way it
- ; has always been done in 'example.asm'.
-
- stdcall png_malloc_base, edi, sizeof.png_info_def
- mov ebx,eax
-
- cmp eax,0
- je @f
- mov edi,eax
- xor eax,eax
- mov ecx,sizeof.png_info_def
- rep stosb ;memset(...
- @@:
-
- mov eax,ebx
-.end_f:
- ret
-endp
-
-; This function frees the memory associated with a single info struct.
-; Normally, one would use either png_destroy_read_struct() or
-; png_destroy_write_struct() to free an info struct, but this may be
-; useful for some applications. From libpng 1.6.0 this function is also used
-; internally to implement the png_info release part of the 'struct' destroy
-; APIs. This ensures that all possible approaches free the same data (all of
-; it).
-
-;void (png_structrp png_ptr, png_infopp info_ptr_ptr)
-align 4
-proc png_destroy_info_struct uses eax ebx ecx edi, png_ptr:dword, info_ptr_ptr:dword
- png_debug 1, 'in png_destroy_info_struct'
-
- cmp dword[png_ptr],0
- je .end_f ;if (..==0) return
-
- mov edi,[info_ptr_ptr]
- cmp edi,0 ;if (..!=0)
- je .end_f
- ; Do this first in case of an error below; if the app implements its own
- ; memory management this can lead to png_free calling png_error, which
- ; will abort this routine and return control to the app error handler.
- ; An infinite loop may result if it then tries to free the same info
- ; ptr.
-
- mov dword[edi],0
-
- stdcall png_free_data, [png_ptr], edi, PNG_FREE_ALL, -1
- mov ebx,edi
- xor eax,eax
- mov ecx,sizeof.png_info_def
- rep stosb
- stdcall png_free, [png_ptr], ebx
- .end_f:
- ret
-endp
-
-; Initialize the info structure. This is now an internal function (0.89)
-; and applications using it are urged to use png_create_info_struct()
-; instead. Use deprecated in 1.6.0, internal use removed (used internally it
-; is just a memset).
-
-; NOTE: it is almost inconceivable that this API is used because it bypasses
-; the user-memory mechanism and the user error handling/warning mechanisms in
-; those cases where it does anything other than a memset.
-
-;void (png_infopp ptr_ptr, png_size_t png_info_struct_size)
-align 4
-proc png_info_init_3, ptr_ptr:dword, png_info_struct_size:dword
-; png_inforp info_ptr = *ptr_ptr;
-
- png_debug 1, 'in png_info_init_3'
-
-; if (info_ptr == NULL)
-; return;
-
-; if ((sizeof (png_info)) > png_info_struct_size)
-; {
-; *ptr_ptr = NULL;
- ; The following line is why this API should not be used:
-; free(info_ptr);
-; info_ptr = png_malloc_base(NULL, (sizeof *info_ptr));
-; if (info_ptr == NULL)
-; return;
-; *ptr_ptr = info_ptr;
-; }
-
- ; Set everything to 0
-; memset(info_ptr, 0, (sizeof *info_ptr));
- ret
-endp
-
-; The following API is not called internally
-;void (png_structrp png_ptr, png_inforp info_ptr, int freer, uint_32 mask)
-align 4
-proc png_data_freer uses edi esi, png_ptr:dword, info_ptr:dword, freer:dword, mask:dword
- png_debug 1, 'in png_data_freer'
-
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f
- mov esi,[info_ptr]
- cmp esi,0
- je .end_f ;if (..==0 || ..==0) return
-
-; if (freer == PNG_DESTROY_WILL_FREE_DATA)
-; info_ptr->free_me |= mask;
-
-; else if (freer == PNG_USER_WILL_FREE_DATA)
-; info_ptr->free_me &= ~mask;
-
-; else
-; png_error(png_ptr, "Unknown freer parameter in png_data_freer");
-.end_f
- ret
-endp
-
-;void (png_structrp png_ptr, png_inforp info_ptr, uint_32 mask, int num)
-align 4
-proc png_free_data uses eax edi esi, png_ptr:dword, info_ptr:dword, mask:dword, num:dword
- png_debug 1, 'in png_free_data'
-
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f
- mov esi,[info_ptr]
- cmp esi,0
- je .end_f ;if (..==0 || ..==0) return
-
-if PNG_TEXT_SUPPORTED eq 1
- ; Free text item num or (if num == -1) all text items
-; if (info_ptr->text != 0 &&
-; ((mask & PNG_FREE_TEXT) & info_ptr->free_me) != 0)
-; {
-; if (num != -1)
-; {
-; png_free(png_ptr, info_ptr->text[num].key);
-; info_ptr->text[num].key = NULL;
-; }
-
-; else
-; {
-; int i;
-
-; for (i = 0; i < info_ptr->num_text; i++)
-; png_free(png_ptr, info_ptr->text[i].key);
-
-; png_free(png_ptr, info_ptr->text);
-; info_ptr->text = NULL;
-; info_ptr->num_text = 0;
-; }
-; }
-end if
-
-if PNG_tRNS_SUPPORTED eq 1
- ; Free any tRNS entry
- mov eax,[mask]
- and eax,PNG_FREE_TRNS
- and eax,[esi+png_info_def.free_me]
- jz @f ;if (..!=0)
- and dword[esi+png_info_def.valid], not PNG_INFO_tRNS
- stdcall png_free, edi, [esi+png_info_def.trans_alpha]
- mov dword[esi+png_info_def.trans_alpha],0
- mov word[esi+png_info_def.num_trans],0
- @@:
-end if
-
-if PNG_sCAL_SUPPORTED eq 1
- ; Free any sCAL entry
- mov eax,[mask]
- and eax,PNG_FREE_SCAL
- and eax,[esi+png_info_def.free_me]
- jz @f ;if (..!=0)
- stdcall png_free, edi, [esi+png_info_def.scal_s_width]
- stdcall png_free, edi, [esi+png_info_def.scal_s_height]
- mov dword[esi+png_info_def.scal_s_width],0
- mov dword[esi+png_info_def.scal_s_height],0
- and dword[esi+png_info_def.valid], not PNG_INFO_sCAL
- @@:
-end if
-
-if PNG_pCAL_SUPPORTED eq 1
- ; Free any pCAL entry
-; if (((mask & PNG_FREE_PCAL) & info_ptr->free_me) != 0)
-; {
-; png_free(png_ptr, info_ptr->pcal_purpose);
-; png_free(png_ptr, info_ptr->pcal_units);
-; info_ptr->pcal_purpose = NULL;
-; info_ptr->pcal_units = NULL;
-
-; if (info_ptr->pcal_params != NULL)
-; {
-; int i;
-
-; for (i = 0; i < info_ptr->pcal_nparams; i++)
-; png_free(png_ptr, info_ptr->pcal_params[i]);
-;
-; png_free(png_ptr, info_ptr->pcal_params);
-; info_ptr->pcal_params = NULL;
-; }
-; info_ptr->valid &= ~PNG_INFO_pCAL;
-; }
-end if
-
-if PNG_iCCP_SUPPORTED eq 1
- ; Free any profile entry
- mov eax,[mask]
- and eax,PNG_FREE_ICCP
- and eax,[esi+png_info_def.free_me]
- jz @f ;if (..!=0)
- stdcall png_free, edi, [esi+png_info_def.iccp_name]
- stdcall png_free, edi, [esi+png_info_def.iccp_profile]
- mov dword[esi+png_info_def.iccp_name],0
- mov dword[esi+png_info_def.iccp_profile],0
- and dword[esi+png_info_def.valid], not PNG_INFO_iCCP
- @@:
-end if
-
-if PNG_sPLT_SUPPORTED eq 1
- ; Free a given sPLT entry, or (if num == -1) all sPLT entries
-; if (info_ptr->splt_palettes != 0 &&
-; ((mask & PNG_FREE_SPLT) & info_ptr->free_me) != 0)
-; {
-; if (num != -1)
-; {
-; png_free(png_ptr, info_ptr->splt_palettes[num].name);
-; png_free(png_ptr, info_ptr->splt_palettes[num].entries);
-; info_ptr->splt_palettes[num].name = NULL;
-; info_ptr->splt_palettes[num].entries = NULL;
-; }
-
-; else
-; {
-; int i;
-
-; for (i = 0; i < info_ptr->splt_palettes_num; i++)
-; {
-; png_free(png_ptr, info_ptr->splt_palettes[i].name);
-; png_free(png_ptr, info_ptr->splt_palettes[i].entries);
-; }
-
-; png_free(png_ptr, info_ptr->splt_palettes);
-; info_ptr->splt_palettes = NULL;
-; info_ptr->splt_palettes_num = 0;
-; info_ptr->valid &= ~PNG_INFO_sPLT;
-; }
-; }
-end if
-
-if PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED eq 1
-; if (info_ptr->unknown_chunks != 0 &&
-; ((mask & PNG_FREE_UNKN) & info_ptr->free_me) != 0)
-; {
-; if (num != -1)
-; {
-; png_free(png_ptr, info_ptr->unknown_chunks[num].data);
-; info_ptr->unknown_chunks[num].data = NULL;
-; }
-
-; else
-; {
-; int i;
-
-; for (i = 0; i < info_ptr->unknown_chunks_num; i++)
-; png_free(png_ptr, info_ptr->unknown_chunks[i].data);
-
-; png_free(png_ptr, info_ptr->unknown_chunks);
-; info_ptr->unknown_chunks = NULL;
-; info_ptr->unknown_chunks_num = 0;
-; }
-; }
-end if
-
-if PNG_hIST_SUPPORTED eq 1
- ; Free any hIST entry
- mov eax,[mask]
- and eax,PNG_FREE_HIST
- and eax,[esi+png_info_def.free_me]
- jz @f ;if (..!=0)
- stdcall png_free, edi, [esi+png_info_def.hist]
- mov dword[esi+png_info_def.hist],0
- and dword[esi+png_info_def.valid], not PNG_INFO_hIST
- @@:
-end if
-
- ; Free any PLTE entry that was internally allocated
- mov eax,[mask]
- and eax,PNG_FREE_PLTE
- and eax,[esi+png_info_def.free_me]
- jz @f ;if (..!=0)
- stdcall png_free, edi, [esi+png_info_def.palette]
- mov dword[esi+png_info_def.palette],0
- and dword[esi+png_info_def.valid],not PNG_INFO_PLTE
- mov dword[esi+png_info_def.num_palette],0
- @@:
-
-if PNG_INFO_IMAGE_SUPPORTED eq 1
- ; Free any image bits attached to the info structure
-; if (((mask & PNG_FREE_ROWS) & info_ptr->free_me) != 0)
-; {
-; if (info_ptr->row_pointers != 0)
-; {
-; uint_32 row;
-; for (row = 0; row < info_ptr->height; row++)
-; png_free(png_ptr, info_ptr->row_pointers[row]);
-
-; png_free(png_ptr, info_ptr->row_pointers);
-; info_ptr->row_pointers = NULL;
-; }
-; info_ptr->valid &= ~PNG_INFO_IDAT;
-; }
-end if
-
-; if (num != -1)
-; mask &= ~PNG_FREE_MUL;
-
- mov eax,[mask]
- not eax
- and [esi+png_info_def.free_me],eax
-.end_f:
- ret
-endp
-
-; This function returns a pointer to the io_ptr associated with the user
-; functions. The application should free any memory associated with this
-; pointer before png_write_destroy() or png_read_destroy() are called.
-
-;voidp (png_structrp png_ptr)
-align 4
-proc png_get_io_ptr, png_ptr:dword
- mov eax,[png_ptr]
- cmp eax,0
- je @f ;if (..==0) return 0
- mov eax,[eax+png_struct.io_ptr]
- @@:
- ret
-endp
-
-;#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
-; Initialize the default input/output functions for the PNG file. If you
-; use your own read or write routines, you can call either png_set_read_fn()
-; or png_set_write_fn() instead of png_init_io(). If you have defined
-; PNG_NO_STDIO or otherwise disabled PNG_STDIO_SUPPORTED, you must use a
-; function of your own because "FILE *" isn't necessarily available.
-
-;void (png_structrp png_ptr, png_FILE_p fp)
-align 4
-proc png_init_io uses eax edi, png_ptr:dword, fp:dword
- png_debug 1, 'in png_init_io'
-
- mov edi,[png_ptr]
- cmp edi,0
- je @f ;if (..==0) return
- mov eax,[fp]
- mov [edi+png_struct.io_ptr],eax
- @@:
- ret
-endp
-
-; PNG signed integers are saved in 32-bit 2's complement format. ANSI C-90
-; defines a cast of a signed integer to an unsigned integer either to preserve
-; the value, if it is positive, or to calculate:
-
-; (UNSIGNED_MAX+1) + integer
-
-; Where UNSIGNED_MAX is the appropriate maximum unsigned value, so when the
-; negative integral value is added the result will be an unsigned value
-; correspnding to the 2's complement representation.
-
-;void (bytep buf, int_32 i)
-align 4
-proc png_save_int_32, buf:dword, i:dword
- stdcall png_save_uint_32, [buf], [i]
- ret
-endp
-
-;# ifdef PNG_TIME_RFC1123_SUPPORTED
-; Convert the supplied time into an RFC 1123 string suitable for use in
-; a "Creation Time" or other text-based time string.
-
-;int (char out[29], const_timep ptime)
-align 4
-short_months db 'Jan',0, 'Feb',0, 'Mar',0, 'Apr',0, 'May',0, 'Jun',0,\
- 'Jul',0, 'Aug',0, 'Sep',0, 'Oct',0, 'Nov',0, 'Dec',0
-
-align 4
-proc png_convert_to_rfc1123_buffer, out_29:dword, ptime:dword
- cmp dword[out_29],0
- jne @f
- xor eax,eax
- jmp .end_f ;if (..==0) return 0
- @@:
-
-; if (ptime->year > 9999 /* RFC1123 limitation */ ||
-; ptime->month == 0 || ptime->month > 12 ||
-; ptime->day == 0 || ptime->day > 31 ||
-; ptime->hour > 23 || ptime->minute > 59 ||
-; ptime->second > 60)
-; return 0;
-
-; {
-; size_t pos = 0;
-; char number_buf[5]; /* enough for a four-digit year */
-
-;# define APPEND_STRING(string) pos = png_safecat(out_29, 29, pos, (string))
-;# define APPEND_NUMBER(format, value)\
-; APPEND_STRING(PNG_FORMAT_NUMBER(number_buf, format, (value)))
-;# define APPEND(ch) if (pos < 28) out_29[pos++] = (ch)
-
-; APPEND_NUMBER(PNG_NUMBER_FORMAT_u, (unsigned)ptime->day);
-; APPEND(' ');
-; APPEND_STRING(short_months[(ptime->month - 1)]);
-; APPEND(' ');
-; APPEND_NUMBER(PNG_NUMBER_FORMAT_u, ptime->year);
-; APPEND(' ');
-; APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->hour);
-; APPEND(':');
-; APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->minute);
-; APPEND(':');
-; APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->second);
-; APPEND_STRING(" +0000"); /* This reliably terminates the buffer */
-
-;# undef APPEND
-;# undef APPEND_NUMBER
-;# undef APPEND_STRING
-; }
-
- xor eax,eax
- inc eax
-.end_f:
- ret
-endp
-
-;# if PNG_LIBPNG_VER < 10700
-; To do: remove the following from libpng-1.7
-; Original API that uses a private buffer in png_struct.
-; Deprecated because it causes png_struct to carry a spurious temporary
-; buffer (png_struct::time_buffer), better to have the caller pass this in.
-
-;charp (png_structrp png_ptr, const_timep ptime)
-align 4
-proc png_convert_to_rfc1123, png_ptr:dword, ptime:dword
-; if (png_ptr != NULL)
-; {
- ; The only failure above if png_ptr != NULL is from an invalid ptime
-; if (png_convert_to_rfc1123_buffer(png_ptr->time_buffer, ptime) == 0)
-; png_warning(png_ptr, "Ignoring invalid time value");
-
-; else
-; return png_ptr->time_buffer;
-; }
-
-; return NULL;
- ret
-endp
-;# endif /* LIBPNG_VER < 10700 */
-;# endif /* TIME_RFC1123 */
-
-;end if /* READ || WRITE */
-
-;charp (png_structrp png_ptr)
-align 4
-proc png_get_copyright, png_ptr:dword
-jmp .end_0
-@@: db 'libpng version 1.6.25 - September 1, 2016',13,10,\
- ' Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson',13,10,\
- ' Copyright (c) 1996-1997 Andreas Dilger',13,10,\
- ' Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.',0
-.end_0:
- mov eax,@b
- ret
-endp
-
-; The following return the library version as a short string in the
-; format 1.0.0 through 99.99.99zz. To get the version of *.inc files
-; used with your application, print out PNG_LIBPNG_VER_STRING, which
-; is defined in png.inc.
-; Note: now there is no difference between png_get_libpng_ver() and
-; png_get_header_ver(). Due to the version_nn_nn_nn typedef guard,
-; it is guaranteed that png.asm uses the correct version of png.inc.
-
-;charp (png_structrp png_ptr)
-align 4
-proc png_get_libpng_ver, png_ptr:dword
- ; Version of *.asm files used when building libpng
-; return png_get_header_ver(png_ptr);
- ret
-endp
-
-;charp (png_structrp png_ptr)
-align 4
-proc png_get_header_ver, png_ptr:dword
- ; Version of *.inc files used when building libpng
-; return PNG_LIBPNG_VER_STRING;
- ret
-endp
-
-;charp (png_structrp png_ptr)
-align 4
-proc png_get_header_version, png_ptr:dword
- ; Returns longer string containing both version and date
-;if __STDC__
-; return PNG_HEADER_VERSION_STRING
-;# ifndef PNG_READ_SUPPORTED
-; " (NO READ SUPPORT)"
-;# endif
-; PNG_STRING_NEWLINE;
-;#else
-; return PNG_HEADER_VERSION_STRING;
-;end if
- ret
-endp
-
-; NOTE: this routine is not used internally!
-; Build a grayscale palette. Palette is assumed to be 1 << bit_depth
-; large of png_color. This lets grayscale images be treated as
-; paletted. Most useful for gamma correction and simplification
-; of code. This API is not used internally.
-
-;void (int bit_depth, png_colorp palette)
-align 4
-proc png_build_grayscale_palette, bit_depth:dword, palette:dword
-; int num_palette;
-; int color_inc;
-; int i;
-; int v;
-
- png_debug 1, 'in png_do_build_grayscale_palette'
-
-; if (palette == NULL)
-; return;
-
-; switch (bit_depth)
-; {
-; case 1:
-; num_palette = 2;
-; color_inc = 0xff;
-; break;
-;
-; case 2:
-; num_palette = 4;
-; color_inc = 0x55;
-; break;
-;
-; case 4:
-; num_palette = 16;
-; color_inc = 0x11;
-; break;
-;
-; case 8:
-; num_palette = 256;
-; color_inc = 1;
-; break;
-;
-; default:
-; num_palette = 0;
-; color_inc = 0;
-; break;
-; }
-;
-; for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
-; {
-; palette[i].red = (byte)(v & 0xff);
-; palette[i].green = (byte)(v & 0xff);
-; palette[i].blue = (byte)(v & 0xff);
-; }
- ret
-endp
-
-;int (png_structrp png_ptr, bytep chunk_name)
-align 4
-proc png_handle_as_unknown uses ecx edi esi, png_ptr:dword, chunk_name:dword
- ; Check chunk_name and return "keep" value if it's on the list, else 0
-; bytep p, p_end;
-
- mov edi,[png_ptr]
- cmp edi,0
- je .end0
- cmp dword[chunk_name],0
- je .end0
- cmp dword[edi+png_struct.num_chunk_list],0
- je .end0
- jmp @f
- .end0: ;if (..==0 || ..==0 || ..==0)
- mov eax,PNG_HANDLE_CHUNK_AS_DEFAULT
- jmp .end_f
- @@:
-
-; p_end = png_ptr->chunk_list;
-; p = p_end + png_ptr->num_chunk_list*5; /* beyond end */
-
- ; The code is the fifth byte after each four byte string. Historically this
- ; code was always searched from the end of the list, this is no longer
- ; necessary because the 'set' routine handles duplicate entries correcty.
-
-; do /* num_chunk_list > 0, so at least one */
-; {
-; p -= 5;
-
-; if (memcmp(chunk_name, p, 4) == 0)
-; return p[4];
-; }
-; while (p > p_end);
-
- ; This means that known chunks should be processed and unknown chunks should
- ; be handled according to the value of png_ptr->unknown_default; this can be
- ; confusing because, as a result, there are two levels of defaulting for
- ; unknown chunks.
-
- mov eax,PNG_HANDLE_CHUNK_AS_DEFAULT
-.end_f:
- ret
-endp
-
-;int (png_structrp png_ptr, uint_32 chunk_name)
-align 4
-proc png_chunk_unknown_handling, png_ptr:dword, chunk_name:dword
-; byte chunk_string[5];
-
-; PNG_CSTRING_FROM_CHUNK(chunk_string, chunk_name);
-; return png_handle_as_unknown(png_ptr, chunk_string);
- ret
-endp
-
-; This function, added to libpng-1.0.6g, is untested.
-;int (png_structrp png_ptr)
-align 4
-proc png_reset_zstream, png_ptr:dword
- mov eax,[png_ptr]
- cmp eax,0
- jne @f ;if (..==0)
- mov eax,Z_STREAM_ERROR
- jmp .end_f
- @@:
- ; WARNING: this resets the window bits to the maximum!
- add eax,png_struct.zstream
- stdcall inflateReset,eax
-.end_f:
- ret
-endp
-
-; This function was added to libpng-1.0.7
-;uint_32 png_access_version_number(void)
-align 4
-png_access_version_number:
- ; Version of *.asm files used when building libpng
- mov eax,PNG_LIBPNG_VER
- ret
-
-;#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
-; Ensure that png_ptr->zstream.msg holds some appropriate error message string.
-; If it doesn't 'ret' is used to set it to something appropriate, even in cases
-; like Z_OK or Z_STREAM_END where the error code is apparently a success code.
-
-;void (png_structrp png_ptr, int ret)
-align 4
-proc png_zstream_error uses eax edi, png_ptr:dword, p2ret:dword
- ; Translate 'p2ret' into an appropriate error string, priority is given to the
- ; one in zstream if set. This always returns a string, even in cases like
- ; Z_OK or Z_STREAM_END where the error code is a success code.
-
- mov edi,[png_ptr]
- cmp dword[edi+png_struct.zstream.msg],0
- jne .end_f ;if (..==0) switch (p2ret)
- mov eax,[p2ret]
-; default:
- cmp eax,Z_OK
- jne @f
- cStr dword[edi+png_struct.zstream.msg],'unexpected zlib return code'
- jmp .end_f
- @@:
- cmp eax,Z_STREAM_END
- jne @f
- ; Normal exit
- cStr dword[edi+png_struct.zstream.msg],'unexpected end of LZ stream'
- jmp .end_f
- @@:
- cmp eax,Z_NEED_DICT
- jne @f
- ; This means the deflate stream did not have a dictionary; this
- ; indicates a bogus PNG.
-
- cStr dword[edi+png_struct.zstream.msg],'missing LZ dictionary'
- jmp .end_f
- @@:
- cmp eax,Z_ERRNO
- jne @f
- ; gz APIs only: should not happen
- cStr dword[edi+png_struct.zstream.msg],'zlib IO error'
- jmp .end_f
- @@:
- cmp eax,Z_STREAM_ERROR
- jne @f
- ; internal libpng error
- cStr dword[edi+png_struct.zstream.msg],'bad parameters to zlib'
- jmp .end_f
- @@:
- cmp eax,Z_DATA_ERROR
- jne @f
- cStr dword[edi+png_struct.zstream.msg],'damaged LZ stream'
- jmp .end_f
- @@:
- cmp eax,Z_MEM_ERROR
- jne @f
- cStr dword[edi+png_struct.zstream.msg],'insufficient memory'
- jmp .end_f
- @@:
- cmp eax,Z_BUF_ERROR
- jne @f
- ; End of input or output; not a problem if the caller is doing
- ; incremental read or write.
-
- cStr dword[edi+png_struct.zstream.msg],'truncated'
- jmp .end_f
- @@:
- cmp eax,Z_VERSION_ERROR
- jne @f
- cStr dword[edi+png_struct.zstream.msg],'unsupported zlib version'
- jmp .end_f
- @@:
- cmp eax,PNG_UNEXPECTED_ZLIB_RETURN
- jne .end_f
- ; Compile errors here mean that zlib now uses the value co-opted in
- ; pngpriv.inc for PNG_UNEXPECTED_ZLIB_RETURN; update the switch above
- ; and change pngpriv.inc. Note that this message is "... return",
- ; whereas the default/Z_OK one is "... return code".
-
- cStr dword[edi+png_struct.zstream.msg],'unexpected zlib return'
-; break;
-.end_f:
- ret
-endp
-
-; png_convert_size: a PNGAPI but no longer in png.inc, so deleted
-; at libpng 1.5.5!
-
-
-; Added at libpng version 1.2.34 and 1.4.0 (moved from pngset.asm)
-;if PNG_GAMMA_SUPPORTED /* always set if COLORSPACE */
-;int (png_structrp png_ptr,
-; png_colorspacerp colorspace, png_fixed_point gAMA, int from)
- ; This is called to check a new gamma value against an existing one. The
- ; routine returns false if the new gamma value should not be written.
- ;
- ; 'from' says where the new gamma value comes from:
- ;
- ; 0: the new gamma value is the libpng estimate for an ICC profile
- ; 1: the new gamma value comes from a gAMA chunk
- ; 2: the new gamma value comes from an sRGB chunk
-
-align 4
-proc png_colorspace_check_gamma, png_ptr:dword, colorspace:dword, gAMA:dword, from:dword
-; png_fixed_point gtest;
-;
-; if ((colorspace->flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 &&
-; (png_muldiv(>est, colorspace->gamma, PNG_FP_1, gAMA) == 0 ||
-; png_gamma_significant(gtest) != 0))
-; {
- ; Either this is an sRGB image, in which case the calculated gamma
- ; approximation should match, or this is an image with a profile and the
- ; value libpng calculates for the gamma of the profile does not match the
- ; value recorded in the file. The former, sRGB, case is an error, the
- ; latter is just a warning.
-
-; if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0 || from == 2)
-; {
-; png_chunk_report(png_ptr, "gamma value does not match sRGB",
-; PNG_CHUNK_ERROR);
-; /* Do not overwrite an sRGB value */
-; return from == 2;
-; }
-
-; else /* sRGB tag not involved */
-; {
-; png_chunk_report(png_ptr, "gamma value does not match libpng estimate",
-; PNG_CHUNK_WARNING);
-; return from == 1;
-; }
-; }
-
-; return 1;
- ret
-endp
-
-;void (png_structrp png_ptr, png_colorspacerp colorspace, png_fixed_point gAMA)
-align 4
-proc png_colorspace_set_gamma, png_ptr:dword, colorspace:dword, gAMA:dword
- ; Changed in libpng-1.5.4 to limit the values to ensure overflow can't
- ; occur. Since the fixed point representation is asymetrical it is
- ; possible for 1/gamma to overflow the limit of 21474 and this means the
- ; gamma value must be at least 5/100000 and hence at most 20000.0. For
- ; safety the limits here are a little narrower. The values are 0.00016 to
- ; 6250.0, which are truly ridiculous gamma values (and will produce
- ; displays that are all black or all white.)
-
- ; In 1.6.0 this test replaces the ones in pngrutil.c, in the gAMA chunk
- ; handling code, which only required the value to be >0.
-
-; charp errmsg;
-
-; if (gAMA < 16 || gAMA > 625000000)
-; errmsg = "gamma value out of range";
-
-;# ifdef PNG_READ_gAMA_SUPPORTED
- ; Allow the application to set the gamma value more than once
-; else if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
-; (colorspace->flags & PNG_COLORSPACE_FROM_gAMA) != 0)
-; errmsg = "duplicate";
-;# endif
-
- ; Do nothing if the colorspace is already invalid
-; else if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
-; return;
-
-; else
-; {
-; if (png_colorspace_check_gamma(png_ptr, colorspace, gAMA,
-; 1/*from gAMA*/) != 0)
-; {
-; /* Store this gamma value. */
-; colorspace->gamma = gAMA;
-; colorspace->flags |=
-; (PNG_COLORSPACE_HAVE_GAMMA | PNG_COLORSPACE_FROM_gAMA);
-; }
-
- ; At present if the check_gamma test fails the gamma of the colorspace is
- ; not updated however the colorspace is not invalidated. This
- ; corresponds to the case where the existing gamma comes from an sRGB
- ; chunk or profile. An error message has already been output.
-
-; return;
-; }
-
- ; Error exit - errmsg has been set.
-; colorspace->flags |= PNG_COLORSPACE_INVALID;
-; png_chunk_report(png_ptr, errmsg, PNG_CHUNK_WRITE_ERROR);
-.end_f:
- ret
-endp
-
-;void (png_structrp png_ptr, png_inforp info_ptr)
-align 4
-proc png_colorspace_sync_info uses eax esi, png_ptr:dword, info_ptr:dword
- mov esi,[info_ptr]
- mov ax,[esi+png_info_def.colorspace.flags]
- and ax,PNG_COLORSPACE_INVALID
- cmp ax,0
- je @f ;if (..!=0)
- ; Everything is invalid
- and dword[esi+png_info_def.valid], not (PNG_INFO_gAMA or PNG_INFO_cHRM or PNG_INFO_sRGB or PNG_INFO_iCCP)
-
-if PNG_COLORSPACE_SUPPORTED eq 1
- ; Clean up the iCCP profile now if it won't be used.
- stdcall png_free_data, [png_ptr], esi, PNG_FREE_ICCP, -1 ;not used
-end if
- jmp .end0
- @@: ;else
-if PNG_COLORSPACE_SUPPORTED eq 1
- ; Leave the INFO_iCCP flag set if the pngset.c code has already set
- ; it; this allows a PNG to contain a profile which matches sRGB and
- ; yet still have that profile retrievable by the application.
-
- mov ax,[esi+png_info_def.colorspace.flags]
- and ax,PNG_COLORSPACE_MATCHES_sRGB
- cmp ax,0
- je @f ;if (..!=0)
- or dword[esi+png_info_def.valid], PNG_INFO_sRGB
- jmp .end1
- @@: ;else
- and dword[esi+png_info_def.valid], not PNG_INFO_sRGB
- .end1:
- mov ax,[esi+png_info_def.colorspace.flags]
- and ax,PNG_COLORSPACE_HAVE_ENDPOINTS
- cmp ax,0
- je @f ;if (..!=0)
- or dword[esi+png_info_def.valid], PNG_INFO_cHRM
- jmp .end2
- @@: ;else
- and dword[esi+png_info_def.valid], not PNG_INFO_cHRM
- .end2:
-end if
-
- mov ax,[esi+png_info_def.colorspace.flags]
- and ax,PNG_COLORSPACE_HAVE_GAMMA
- cmp ax,0
- je @f ;if (..!=0)
- or dword[esi+png_info_def.valid], PNG_INFO_gAMA
- jmp .end0
- @@: ;else
- and dword[esi+png_info_def.valid], not PNG_INFO_gAMA
- .end0:
- ret
-endp
-
-;void (png_structrp png_ptr, png_inforp info_ptr)
-align 4
-proc png_colorspace_sync uses ecx edi esi, png_ptr:dword, info_ptr:dword
- mov edi,[info_ptr]
- cmp edi,0
- je @f ;if (..==0) ;reduce code size; check here not in the caller
- mov ecx,sizeof.png_colorspace
- mov esi,[png_ptr]
- add esi,png_struct.colorspace
- add edi,png_info_def.colorspace
- rep movsb
- stdcall png_colorspace_sync_info, [png_ptr], [info_ptr]
- @@:
- ret
-endp
-
-;end if /* GAMMA */
-
-;if PNG_COLORSPACE_SUPPORTED
-; Added at libpng-1.5.5 to support read and write of true CIEXYZ values for
-; cHRM, as opposed to using chromaticities. These internal APIs return
-; non-zero on a parameter error. The X, Y and Z values are required to be
-; positive and less than 1.0.
-
-;int (png_xy *xy, const png_XYZ *XYZ)
-align 4
-proc png_xy_from_XYZ, xy:dword, XYZ:dword
-; int_32 d, dwhite, whiteX, whiteY;
-
-; d = XYZ->red_X + XYZ->red_Y + XYZ->red_Z;
-; if (png_muldiv(&xy->redx, XYZ->red_X, PNG_FP_1, d) == 0)
-; return 1;
-; if (png_muldiv(&xy->redy, XYZ->red_Y, PNG_FP_1, d) == 0)
-; return 1;
-; dwhite = d;
-; whiteX = XYZ->red_X;
-; whiteY = XYZ->red_Y;
-
-; d = XYZ->green_X + XYZ->green_Y + XYZ->green_Z;
-; if (png_muldiv(&xy->greenx, XYZ->green_X, PNG_FP_1, d) == 0)
-; return 1;
-; if (png_muldiv(&xy->greeny, XYZ->green_Y, PNG_FP_1, d) == 0)
-; return 1;
-; dwhite += d;
-; whiteX += XYZ->green_X;
-; whiteY += XYZ->green_Y;
-
-; d = XYZ->blue_X + XYZ->blue_Y + XYZ->blue_Z;
-; if (png_muldiv(&xy->bluex, XYZ->blue_X, PNG_FP_1, d) == 0)
-; return 1;
-; if (png_muldiv(&xy->bluey, XYZ->blue_Y, PNG_FP_1, d) == 0)
-; return 1;
-; dwhite += d;
-; whiteX += XYZ->blue_X;
-; whiteY += XYZ->blue_Y;
-
- ; The reference white is simply the sum of the end-point (X,Y,Z) vectors,
- ; thus:
-
-; if (png_muldiv(&xy->whitex, whiteX, PNG_FP_1, dwhite) == 0)
-; return 1;
-; if (png_muldiv(&xy->whitey, whiteY, PNG_FP_1, dwhite) == 0)
-; return 1;
-
-; return 0;
- ret
-endp
-
-;int (png_XYZ *XYZ, const png_xy *xy)
-align 4
-proc png_XYZ_from_xy, XYZ:dword, xy:dword
-; png_fixed_point red_inverse, green_inverse, blue_scale;
-; png_fixed_point left, right, denominator;
-
- ; Check xy and, implicitly, z. Note that wide gamut color spaces typically
- ; have end points with 0 tristimulus values (these are impossible end
- ; points, but they are used to cover the possible colors). We check
- ; xy->whitey against 5, not 0, to avoid a possible integer overflow.
-
-; if (xy->redx < 0 || xy->redx > PNG_FP_1) return 1;
-; if (xy->redy < 0 || xy->redy > PNG_FP_1-xy->redx) return 1;
-; if (xy->greenx < 0 || xy->greenx > PNG_FP_1) return 1;
-; if (xy->greeny < 0 || xy->greeny > PNG_FP_1-xy->greenx) return 1;
-; if (xy->bluex < 0 || xy->bluex > PNG_FP_1) return 1;
-; if (xy->bluey < 0 || xy->bluey > PNG_FP_1-xy->bluex) return 1;
-; if (xy->whitex < 0 || xy->whitex > PNG_FP_1) return 1;
-; if (xy->whitey < 5 || xy->whitey > PNG_FP_1-xy->whitex) return 1;
-
- ; The reverse calculation is more difficult because the original tristimulus
- ; value had 9 independent values (red,green,blue)x(X,Y,Z) however only 8
- ; derived values were recorded in the cHRM chunk;
- ; (red,green,blue,white)x(x,y). This loses one degree of freedom and
- ; therefore an arbitrary ninth value has to be introduced to undo the
- ; original transformations.
-
- ; Think of the original end-points as points in (X,Y,Z) space. The
- ; chromaticity values (c) have the property:
-
- ; C
- ; c = ---------
- ; X + Y + Z
-
- ; For each c (x,y,z) from the corresponding original C (X,Y,Z). Thus the
- ; three chromaticity values (x,y,z) for each end-point obey the
- ; relationship:
-
- ; x + y + z = 1
-
- ; This describes the plane in (X,Y,Z) space that intersects each axis at the
- ; value 1.0; call this the chromaticity plane. Thus the chromaticity
- ; calculation has scaled each end-point so that it is on the x+y+z=1 plane
- ; and chromaticity is the intersection of the vector from the origin to the
- ; (X,Y,Z) value with the chromaticity plane.
-
- ; To fully invert the chromaticity calculation we would need the three
- ; end-point scale factors, (red-scale, green-scale, blue-scale), but these
- ; were not recorded. Instead we calculated the reference white (X,Y,Z) and
- ; recorded the chromaticity of this. The reference white (X,Y,Z) would have
- ; given all three of the scale factors since:
-
- ; color-C = color-c * color-scale
- ; white-C = red-C + green-C + blue-C
- ; = red-c*red-scale + green-c*green-scale + blue-c*blue-scale
-
- ; But cHRM records only white-x and white-y, so we have lost the white scale
- ; factor:
-
- ; white-C = white-c*white-scale
-
- ; To handle this the inverse transformation makes an arbitrary assumption
- ; about white-scale:
-
- ; Assume: white-Y = 1.0
- ; Hence: white-scale = 1/white-y
- ; Or: red-Y + green-Y + blue-Y = 1.0
-
- ; Notice the last statement of the assumption gives an equation in three of
- ; the nine values we want to calculate. 8 more equations come from the
- ; above routine as summarised at the top above (the chromaticity
- ; calculation):
-
- ; Given: color-x = color-X / (color-X + color-Y + color-Z)
- ; Hence: (color-x - 1)*color-X + color.x*color-Y + color.x*color-Z = 0
-
- ; This is 9 simultaneous equations in the 9 variables "color-C" and can be
- ; solved by Cramer's rule. Cramer's rule requires calculating 10 9x9 matrix
- ; determinants, however this is not as bad as it seems because only 28 of
- ; the total of 90 terms in the various matrices are non-zero. Nevertheless
- ; Cramer's rule is notoriously numerically unstable because the determinant
- ; calculation involves the difference of large, but similar, numbers. It is
- ; difficult to be sure that the calculation is stable for real world values
- ; and it is certain that it becomes unstable where the end points are close
- ; together.
-
- ; So this code uses the perhaps slightly less optimal but more
- ; understandable and totally obvious approach of calculating color-scale.
-
- ; This algorithm depends on the precision in white-scale and that is
- ; (1/white-y), so we can immediately see that as white-y approaches 0 the
- ; accuracy inherent in the cHRM chunk drops off substantially.
-
- ; libpng arithmetic: a simple inversion of the above equations
- ; ------------------------------------------------------------
-
- ; white_scale = 1/white-y
- ; white-X = white-x * white-scale
- ; white-Y = 1.0
- ; white-Z = (1 - white-x - white-y) * white_scale
-
- ; white-C = red-C + green-C + blue-C
- ; = red-c*red-scale + green-c*green-scale + blue-c*blue-scale
-
- ; This gives us three equations in (red-scale,green-scale,blue-scale) where
- ; all the coefficients are now known:
-
- ; red-x*red-scale + green-x*green-scale + blue-x*blue-scale
- ; = white-x/white-y
- ; red-y*red-scale + green-y*green-scale + blue-y*blue-scale = 1
- ; red-z*red-scale + green-z*green-scale + blue-z*blue-scale
- ; = (1 - white-x - white-y)/white-y
-
- ; In the last equation color-z is (1 - color-x - color-y) so we can add all
- ; three equations together to get an alternative third:
-
- ; red-scale + green-scale + blue-scale = 1/white-y = white-scale
-
- ; So now we have a Cramer's rule solution where the determinants are just
- ; 3x3 - far more tractible. Unfortunately 3x3 determinants still involve
- ; multiplication of three coefficients so we can't guarantee to avoid
- ; overflow in the libpng fixed point representation. Using Cramer's rule in
- ; floating point is probably a good choice here, but it's not an option for
- ; fixed point. Instead proceed to simplify the first two equations by
- ; eliminating what is likely to be the largest value, blue-scale:
-
- ; blue-scale = white-scale - red-scale - green-scale
-
- ; Hence:
-
- ; (red-x - blue-x)*red-scale + (green-x - blue-x)*green-scale =
- ; (white-x - blue-x)*white-scale
-
- ; (red-y - blue-y)*red-scale + (green-y - blue-y)*green-scale =
- ; 1 - blue-y*white-scale
-
- ; And now we can trivially solve for (red-scale,green-scale):
-
- ; green-scale =
- ; (white-x - blue-x)*white-scale - (red-x - blue-x)*red-scale
- ; -----------------------------------------------------------
- ; green-x - blue-x
-
- ; red-scale =
- ; 1 - blue-y*white-scale - (green-y - blue-y) * green-scale
- ; ---------------------------------------------------------
- ; red-y - blue-y
-
- ; Hence:
-
- ; red-scale =
- ; ( (green-x - blue-x) * (white-y - blue-y) -
- ; (green-y - blue-y) * (white-x - blue-x) ) / white-y
- ; -------------------------------------------------------------------------
- ; (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x)
-
- ; green-scale =
- ; ( (red-y - blue-y) * (white-x - blue-x) -
- ; (red-x - blue-x) * (white-y - blue-y) ) / white-y
- ; -------------------------------------------------------------------------
- ; (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x)
-
- ; Accuracy:
- ; The input values have 5 decimal digits of accuracy. The values are all in
- ; the range 0 < value < 1, so simple products are in the same range but may
- ; need up to 10 decimal digits to preserve the original precision and avoid
- ; underflow. Because we are using a 32-bit signed representation we cannot
- ; match this; the best is a little over 9 decimal digits, less than 10.
-
- ; The approach used here is to preserve the maximum precision within the
- ; signed representation. Because the red-scale calculation above uses the
- ; difference between two products of values that must be in the range -1..+1
- ; it is sufficient to divide the product by 7; ceil(100,000/32767*2). The
- ; factor is irrelevant in the calculation because it is applied to both
- ; numerator and denominator.
-
- ; Note that the values of the differences of the products of the
- ; chromaticities in the above equations tend to be small, for example for
- ; the sRGB chromaticities they are:
-
- ; red numerator: -0.04751
- ; green numerator: -0.08788
- ; denominator: -0.2241 (without white-y multiplication)
-
- ; The resultant Y coefficients from the chromaticities of some widely used
- ; color space definitions are (to 15 decimal places):
-
- ; sRGB
- ; 0.212639005871510 0.715168678767756 0.072192315360734
- ; Kodak ProPhoto
- ; 0.288071128229293 0.711843217810102 0.000085653960605
- ; Adobe RGB
- ; 0.297344975250536 0.627363566255466 0.075291458493998
- ; Adobe Wide Gamut RGB
- ; 0.258728243040113 0.724682314948566 0.016589442011321
-
- ; By the argument, above overflow should be impossible here. The return
- ; value of 2 indicates an internal error to the caller.
-
-; if (png_muldiv(&left, xy->greenx-xy->bluex, xy->redy - xy->bluey, 7) == 0)
-; return 2;
-; if (png_muldiv(&right, xy->greeny-xy->bluey, xy->redx - xy->bluex, 7) == 0)
-; return 2;
-; denominator = left - right;
-
- ; Now find the red numerator.
-; if (png_muldiv(&left, xy->greenx-xy->bluex, xy->whitey-xy->bluey, 7) == 0)
-; return 2;
-; if (png_muldiv(&right, xy->greeny-xy->bluey, xy->whitex-xy->bluex, 7) == 0)
-; return 2;
-
- ; Overflow is possible here and it indicates an extreme set of PNG cHRM
- ; chunk values. This calculation actually returns the reciprocal of the
- ; scale value because this allows us to delay the multiplication of white-y
- ; into the denominator, which tends to produce a small number.
-
-; if (png_muldiv(&red_inverse, xy->whitey, denominator, left-right) == 0 ||
-; red_inverse <= xy->whitey /* r+g+b scales = white scale */)
-; return 1;
-
- ; Similarly for green_inverse:
-; if (png_muldiv(&left, xy->redy-xy->bluey, xy->whitex-xy->bluex, 7) == 0)
-; return 2;
-; if (png_muldiv(&right, xy->redx-xy->bluex, xy->whitey-xy->bluey, 7) == 0)
-; return 2;
-; if (png_muldiv(&green_inverse, xy->whitey, denominator, left-right) == 0 ||
-; green_inverse <= xy->whitey)
-; return 1;
-
- ; And the blue scale, the checks above guarantee this can't overflow but it
- ; can still produce 0 for extreme cHRM values.
-
-; blue_scale = png_reciprocal(xy->whitey) - png_reciprocal(red_inverse) -
-; png_reciprocal(green_inverse);
-; if (blue_scale <= 0)
-; return 1;
-
-
- ; And fill in the png_XYZ:
-; if (png_muldiv(&XYZ->red_X, xy->redx, PNG_FP_1, red_inverse) == 0)
-; return 1;
-; if (png_muldiv(&XYZ->red_Y, xy->redy, PNG_FP_1, red_inverse) == 0)
-; return 1;
-; if (png_muldiv(&XYZ->red_Z, PNG_FP_1 - xy->redx - xy->redy, PNG_FP_1,
-; red_inverse) == 0)
-; return 1;
-
-; if (png_muldiv(&XYZ->green_X, xy->greenx, PNG_FP_1, green_inverse) == 0)
-; return 1;
-; if (png_muldiv(&XYZ->green_Y, xy->greeny, PNG_FP_1, green_inverse) == 0)
-; return 1;
-; if (png_muldiv(&XYZ->green_Z, PNG_FP_1 - xy->greenx - xy->greeny, PNG_FP_1,
-; green_inverse) == 0)
-; return 1;
-
-; if (png_muldiv(&XYZ->blue_X, xy->bluex, blue_scale, PNG_FP_1) == 0)
-; return 1;
-; if (png_muldiv(&XYZ->blue_Y, xy->bluey, blue_scale, PNG_FP_1) == 0)
-; return 1;
-; if (png_muldiv(&XYZ->blue_Z, PNG_FP_1 - xy->bluex - xy->bluey, blue_scale,
-; PNG_FP_1) == 0)
-; return 1;
-
-; return 0; /*success*/
- ret
-endp
-
-;int (png_XYZ *XYZ)
-align 4
-proc png_XYZ_normalize, XYZ:dword
-; int_32 Y;
-
-; if (XYZ->red_Y < 0 || XYZ->green_Y < 0 || XYZ->blue_Y < 0 ||
-; XYZ->red_X < 0 || XYZ->green_X < 0 || XYZ->blue_X < 0 ||
-; XYZ->red_Z < 0 || XYZ->green_Z < 0 || XYZ->blue_Z < 0)
-; return 1;
-
- ; Normalize by scaling so the sum of the end-point Y values is PNG_FP_1.
- ; IMPLEMENTATION NOTE: ANSI requires signed overflow not to occur, therefore
- ; relying on addition of two positive values producing a negative one is not
- ; safe.
-
-; Y = XYZ->red_Y;
-; if (0x7fffffff - Y < XYZ->green_X)
-; return 1;
-; Y += XYZ->green_Y;
-; if (0x7fffffff - Y < XYZ->blue_X)
-; return 1;
-; Y += XYZ->blue_Y;
-
-; if (Y != PNG_FP_1)
-; {
-; if (png_muldiv(&XYZ->red_X, XYZ->red_X, PNG_FP_1, Y) == 0)
-; return 1;
-; if (png_muldiv(&XYZ->red_Y, XYZ->red_Y, PNG_FP_1, Y) == 0)
-; return 1;
-; if (png_muldiv(&XYZ->red_Z, XYZ->red_Z, PNG_FP_1, Y) == 0)
-; return 1;
-
-; if (png_muldiv(&XYZ->green_X, XYZ->green_X, PNG_FP_1, Y) == 0)
-; return 1;
-; if (png_muldiv(&XYZ->green_Y, XYZ->green_Y, PNG_FP_1, Y) == 0)
-; return 1;
-; if (png_muldiv(&XYZ->green_Z, XYZ->green_Z, PNG_FP_1, Y) == 0)
-; return 1;
-
-; if (png_muldiv(&XYZ->blue_X, XYZ->blue_X, PNG_FP_1, Y) == 0)
-; return 1;
-; if (png_muldiv(&XYZ->blue_Y, XYZ->blue_Y, PNG_FP_1, Y) == 0)
-; return 1;
-; if (png_muldiv(&XYZ->blue_Z, XYZ->blue_Z, PNG_FP_1, Y) == 0)
-; return 1;
-; }
-
-; return 0;
- ret
-endp
-
-;int (const png_xy *xy1, const png_xy *xy2, int delta)
-align 4
-proc png_colorspace_endpoints_match, xy1:dword, xy2:dword, delta:dword
- ; Allow an error of +/-0.01 (absolute value) on each chromaticity
-; if (PNG_OUT_OF_RANGE(xy1->whitex, xy2->whitex,delta) ||
-; PNG_OUT_OF_RANGE(xy1->whitey, xy2->whitey,delta) ||
-; PNG_OUT_OF_RANGE(xy1->redx, xy2->redx, delta) ||
-; PNG_OUT_OF_RANGE(xy1->redy, xy2->redy, delta) ||
-; PNG_OUT_OF_RANGE(xy1->greenx, xy2->greenx,delta) ||
-; PNG_OUT_OF_RANGE(xy1->greeny, xy2->greeny,delta) ||
-; PNG_OUT_OF_RANGE(xy1->bluex, xy2->bluex, delta) ||
-; PNG_OUT_OF_RANGE(xy1->bluey, xy2->bluey, delta))
-; return 0;
-; return 1;
- ret
-endp
-
-; Added in libpng-1.6.0, a different check for the validity of a set of cHRM
-; chunk chromaticities. Earlier checks used to simply look for the overflow
-; condition (where the determinant of the matrix to solve for XYZ ends up zero
-; because the chromaticity values are not all distinct.) Despite this it is
-; theoretically possible to produce chromaticities that are apparently valid
-; but that rapidly degrade to invalid, potentially crashing, sets because of
-; arithmetic inaccuracies when calculations are performed on them. The new
-; check is to round-trip xy -> XYZ -> xy and then check that the result is
-; within a small percentage of the original.
-
-;int (png_XYZ *XYZ, const png_xy *xy)
-align 4
-proc png_colorspace_check_xy, XYZ:dword, xy:dword
-; int result;
-; png_xy xy_test;
-
- ; As a side-effect this routine also returns the XYZ endpoints.
-; result = png_XYZ_from_xy(XYZ, xy);
-; if (result != 0)
-; return result;
-
-; result = png_xy_from_XYZ(&xy_test, XYZ);
-; if (result != 0)
-; return result;
-
-; if (png_colorspace_endpoints_match(xy, &xy_test,
-; 5/*actually, the math is pretty accurate*/) != 0)
-; return 0;
-
- ; Too much slip
-; return 1;
- ret
-endp
-
-; This is the check going the other way. The XYZ is modified to normalize it
-; (another side-effect) and the xy chromaticities are returned.
-
-;int (png_xy *xy, png_XYZ *XYZ)
-align 4
-proc png_colorspace_check_XYZ, xy:dword, XYZ:dword
-; int result;
-; png_XYZ XYZtemp;
-
-; result = png_XYZ_normalize(XYZ);
-; if (result != 0)
-; return result;
-
-; result = png_xy_from_XYZ(xy, XYZ);
-; if (result != 0)
-; return result;
-
-; XYZtemp = *XYZ;
-; return png_colorspace_check_xy(&XYZtemp, xy);
- ret
-endp
-
-; Used to check for an endpoint match against sRGB
-;const png_xy sRGB_xy = /* From ITU-R BT.709-3 */
-; /* color x y */
-; /* red */ 64000, 33000,
-; /* green */ 30000, 60000,
-; /* blue */ 15000, 6000,
-; /* white */ 31270, 32900
-
-;int (png_structrp png_ptr,
-; png_colorspacerp colorspace, const png_xy *xy, const png_XYZ *XYZ,
-; int preferred)
-align 4
-proc png_colorspace_set_xy_and_XYZ, png_ptr:dword, colorspace:dword, xy:dword, XYZ:dword, preferred:dword
-; if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
-; return 0;
-
- ; The consistency check is performed on the chromaticities; this factors out
- ; variations because of the normalization (or not) of the end point Y
- ; values.
-
-; if (preferred < 2 &&
-; (colorspace->flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
-; {
- ; The end points must be reasonably close to any we already have. The
- ; following allows an error of up to +/-.001
-
-; if (png_colorspace_endpoints_match(xy, &colorspace->end_points_xy,
-; 100) == 0)
-; {
-; colorspace->flags |= PNG_COLORSPACE_INVALID;
-; png_benign_error(png_ptr, "inconsistent chromaticities");
-; return 0; /* failed */
-; }
-
- ; Only overwrite with preferred values
-; if (preferred == 0)
-; return 1; /* ok, but no change */
-; }
-
-; colorspace->end_points_xy = *xy;
-; colorspace->end_points_XYZ = *XYZ;
-; colorspace->flags |= PNG_COLORSPACE_HAVE_ENDPOINTS;
-
-; /* The end points are normally quoted to two decimal digits, so allow +/-0.01
- ; on this test.
-
-; if (png_colorspace_endpoints_match(xy, &sRGB_xy, 1000) != 0)
-; colorspace->flags |= PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB;
-;
-; else
-; colorspace->flags &= PNG_COLORSPACE_CANCEL(
-; PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB);
-
-; return 2; /* ok and changed */
- ret
-endp
-
-;int (png_structrp png_ptr,
-; png_colorspacerp colorspace, const png_xy *xy, int preferred)
-align 4
-proc png_colorspace_set_chromaticities, png_ptr:dword, colorspace:dword, xy:dword, preferred:dword
- ; We must check the end points to ensure they are reasonable - in the past
- ; color management systems have crashed as a result of getting bogus
- ; colorant values, while this isn't the fault of libpng it is the
- ; responsibility of libpng because PNG carries the bomb and libpng is in a
- ; position to protect against it.
-
-; png_XYZ XYZ;
-
-; switch (png_colorspace_check_xy(&XYZ, xy))
-; {
-; case 0: /* success */
-; return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, xy, &XYZ,
-; preferred);
-
-; case 1:
- ; We can't invert the chromaticities so we can't produce value XYZ
- ; values. Likely as not a color management system will fail too.
-
-; colorspace->flags |= PNG_COLORSPACE_INVALID;
-; png_benign_error(png_ptr, "invalid chromaticities");
-; break;
-;
-; default:
- ; libpng is broken; this should be a warning but if it happens we
- ; want error reports so for the moment it is an error.
-
-; colorspace->flags |= PNG_COLORSPACE_INVALID;
-; png_error(png_ptr, "internal error checking chromaticities");
-; }
-
- xor eax,eax
-.end_f:
- ret
-endp
-
-;int (png_structrp png_ptr,
-; png_colorspacerp colorspace, const png_XYZ *XYZ_in, int preferred)
-align 4
-proc png_colorspace_set_endpoints, png_ptr:dword, colorspace:dword, XYZ_in:dword, preferred:dword
-; png_XYZ XYZ = *XYZ_in;
-; png_xy xy;
-
-; switch (png_colorspace_check_XYZ(&xy, &XYZ))
-; {
-; case 0:
-; return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, &xy, &XYZ,
-; preferred);
-
-; case 1:
- ; End points are invalid.
-; colorspace->flags |= PNG_COLORSPACE_INVALID;
-; png_benign_error(png_ptr, "invalid end points");
-; break;
-
-; default:
-; colorspace->flags |= PNG_COLORSPACE_INVALID;
-; png_error(png_ptr, "internal error checking chromaticities");
-; }
-
- xor eax,eax
-.end_f:
- ret
-endp
-
-; Error message generation
-;char (uint_32 byte)
-align 4
-proc png_icc_tag_char, p1byte:dword
- mov eax,[p1byte]
- cmp al,32
- jl @f
- cmp al,126
- jg @f ;if (..>=.. && ..<=..) return
- mov al,'?'
- @@:
- and eax,0xff
- ret
-endp
-
-;void (char *name, uint_32 tag)
-align 4
-proc png_icc_tag_name uses eax edi, name:dword, tag:dword
- mov edi,[name]
- mov byte[edi],39
- mov byte[edi+5],39
- inc edi
- mov eax,[tag]
- shr eax,24
- stdcall png_icc_tag_char,eax
- stosb
- mov eax,[tag]
- shr eax,16
- stdcall png_icc_tag_char,eax
- stosb
- mov eax,[tag]
- shr eax,8
- stdcall png_icc_tag_char,eax
- stosb
- stdcall png_icc_tag_char,[tag]
- stosb
- ret
-endp
-
-;int (png_alloc_size_t it)
-align 4
-proc is_ICC_signature_char, it:dword
-; return it == 32 || (it >= 48 && it <= 57) || (it >= 65 && it <= 90) ||
-; (it >= 97 && it <= 122);
- ret
-endp
-
-;int (png_alloc_size_t it)
-align 4
-proc is_ICC_signature, it:dword
-; return is_ICC_signature_char(it >> 24) /* checks all the top bits */ &&
-; is_ICC_signature_char((it >> 16) & 0xff) &&
-; is_ICC_signature_char((it >> 8) & 0xff) &&
-; is_ICC_signature_char(it & 0xff);
- ret
-endp
-
-;int (png_structrp png_ptr, png_colorspacerp colorspace,
-; charp name, png_alloc_size_t value, charp reason)
-align 4
-proc png_icc_profile_error, png_ptr:dword, colorspace:dword, name:dword, value:dword, reason:dword
-locals
- pos dd ? ;size_t
- message rb 196 ;char[] ;see below for calculation
-endl
- mov eax,[colorspace]
- cmp eax,0
- je @f ;if (..!=0)
- or word[eax+png_colorspace.flags], PNG_COLORSPACE_INVALID
- @@:
-
-; pos = png_safecat(message, (sizeof message), 0, "profile '"); /* 9 chars */
-; pos = png_safecat(message, pos+79, pos, name); /* Truncate to 79 chars */
-; pos = png_safecat(message, (sizeof message), pos, "': "); /* +2 = 90 */
-; if (is_ICC_signature(value) != 0)
-; {
- ; So 'value' is at most 4 bytes and the following cast is safe
-; png_icc_tag_name(message+pos, (uint_32)value);
-; pos += 6; /* total +8; less than the else clause */
-; message[pos++] = ':';
-; message[pos++] = ' ';
-; }
-if PNG_WARNINGS_SUPPORTED eq 1
-; else
-; {
-; char number[PNG_NUMBER_BUFFER_SIZE]; /* +24 = 114*/
-
-; pos = png_safecat(message, (sizeof message), pos,
-; png_format_number(number, number+(sizeof number),
-; PNG_NUMBER_FORMAT_x, value));
-; pos = png_safecat(message, (sizeof message), pos, "h: "); /*+2 = 116*/
-; }
-end if
- ; The 'reason' is an arbitrary message, allow +79 maximum 195
-; pos = png_safecat(message, (sizeof message), pos, reason);
-
- ; This is recoverable, but make it unconditionally an app_error on write to
- ; avoid writing invalid ICC profiles into PNG files (i.e., we handle them
- ; on read, with a warning, but on write unless the app turns off
- ; application errors the PNG won't be written.)
-
-; png_chunk_report(png_ptr, message,
-; (colorspace != NULL) ? PNG_CHUNK_ERROR : PNG_CHUNK_WRITE_ERROR);
-
- xor eax,eax
- ret
-endp
-
-if PNG_sRGB_SUPPORTED eq 1
-;color X Y Z
-sRGB_XYZ dd 41239, 21264, 1933,\ ;red
- 35758, 71517, 11919,\ ;green
- 18048, 7219, 95053 ;blue
-end if
-
-;int (png_structrp png_ptr, png_colorspacerp colorspace, int intent)
-align 4
-proc png_colorspace_set_sRGB uses ebx ecx edi esi, png_ptr:dword, colorspace:dword, intent:dword
- ; sRGB sets known gamma, end points and (from the chunk) intent.
- ; IMPORTANT: these are not necessarily the values found in an ICC profile
- ; because ICC profiles store values adapted to a D50 environment; it is
- ; expected that the ICC profile mediaWhitePointTag will be D50; see the
- ; checks and code elsewhere to understand this better.
-
- ; These XYZ values, which are accurate to 5dp, produce rgb to gray
- ; coefficients of (6968,23435,2366), which are reduced (because they add up
- ; to 32769 not 32768) to (6968,23434,2366). These are the values that
- ; libpng has traditionally used (and are the best values given the 15bit
- ; algorithm used by the rgb to gray code.)
-
- ; Do nothing if the colorspace is already invalidated.
- mov ebx,[colorspace]
- mov ax,[ebx+png_colorspace.flags]
- and ax,PNG_COLORSPACE_INVALID
- cmp ax,0
- je @f ;if (..!=0)
- xor eax,eax
- jmp .end_f
- @@:
-
- ; Check the intent, then check for existing settings. It is valid for the
- ; PNG file to have cHRM or gAMA chunks along with sRGB, but the values must
- ; be consistent with the correct values. If, however, this function is
- ; called below because an iCCP chunk matches sRGB then it is quite
- ; conceivable that an older app recorded incorrect gAMA and cHRM because of
- ; an incorrect calculation based on the values in the profile - this does
- ; *not* invalidate the profile (though it still produces an error, which can
- ; be ignored.)
-
- mov edi,[png_ptr]
- cmp dword[intent],0
- jl @f
- cmp dword[intent],PNG_sRGB_INTENT_LAST
- jge @f
- jmp .end0
- @@: ;if (..<0 || ..>=..)
- cStr ,'sRGB'
- cStr ecx,'invalid sRGB rendering intent'
- stdcall png_icc_profile_error, edi, ebx, eax, [intent], ecx
- jmp .end_f
- .end0:
-
- mov ax,[ebx+png_colorspace.flags]
- and ax,PNG_COLORSPACE_HAVE_INTENT
- cmp ax,0
- je @f
- movzx eax,word[ebx+png_colorspace.rendering_intent]
- cmp eax,[intent]
- je @f ;if (..!=0 && ..!=..)
- cStr ,'sRGB'
- cStr ecx,'inconsistent rendering intents'
- stdcall png_icc_profile_error, edi, ebx, eax, [intent], ecx
- jmp .end_f
- @@:
-
- mov ax,[ebx+png_colorspace.flags]
- and ax,PNG_COLORSPACE_FROM_sRGB
- cmp ax,0
- je @f ;if (..!=0)
- png_benign_error edi, 'duplicate sRGB information ignored'
- xor eax,eax
- jmp .end_f
- @@:
-
- ; If the standard sRGB cHRM chunk does not match the one from the PNG file
- ; warn but overwrite the value with the correct one.
-
- mov ax,[ebx+png_colorspace.flags]
- and ax,PNG_COLORSPACE_HAVE_ENDPOINTS
- cmp ax,0
- je @f ;if (..!=0 &&
-; !png_colorspace_endpoints_match(&sRGB_xy, &colorspace->end_points_xy,
-; 100))
- cStr ,'cHRM chunk does not match sRGB'
- stdcall png_chunk_report, edi, eax, PNG_CHUNK_ERROR
- @@:
-
- ; This check is just done for the error reporting - the routine always
- ; returns true when the 'from' argument corresponds to sRGB (2).
-
- stdcall png_colorspace_check_gamma, edi, ebx, PNG_GAMMA_sRGB_INVERSE, 2 ;from sRGB
-
- ; intent: bugs in GCC force 'int' to be used as the parameter type.
- mov eax,[intent]
- mov [ebx+png_colorspace.rendering_intent],ax
- or word[ebx+png_colorspace.flags], PNG_COLORSPACE_HAVE_INTENT
-
- ; endpoints
-; colorspace->end_points_xy = sRGB_xy;
-; colorspace->end_points_XYZ = sRGB_XYZ;
- or word[ebx+png_colorspace.flags], (PNG_COLORSPACE_HAVE_ENDPOINTS or PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB)
-
- ; gamma
- mov dword[ebx+png_colorspace.gamma], PNG_GAMMA_sRGB_INVERSE
- or word[ebx+png_colorspace.flags], PNG_COLORSPACE_HAVE_GAMMA
-
- ; Finally record that we have an sRGB profile
- or word[ebx+png_colorspace.flags], (PNG_COLORSPACE_MATCHES_sRGB or PNG_COLORSPACE_FROM_sRGB)
-
- xor eax,eax
- inc eax ;set
-.end_f:
- ret
-endp
-
-;if PNG_iCCP_SUPPORTED
-; Encoded value of D50 as an ICC XYZNumber. From the ICC 2010 spec the value
-; is XYZ(0.9642,1.0,0.8249), which scales to:
-
-; (63189.8112, 65536, 54060.6464)
-
-D50_nCIEXYZ db \ ;byte[12]
- 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d
-
-;int /* bool */
-;(png_structrp png_ptr, png_colorspacerp colorspace, charp name, uint_32 profile_length)
-align 4
-proc icc_check_length, png_ptr:dword, colorspace:dword, name:dword, profile_length:dword
- cmp dword[profile_length],132
- jge @f ;if (..<..)
-; return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
-; "too short");
- jmp .end_f
- @@:
- xor eax,eax
- inc eax
-.end_f:
- ret
-endp
-
-;int (png_structrp png_ptr, png_colorspacerp colorspace,
-; charp name, uint_32 profile_length)
-align 4
-proc png_icc_check_length, png_ptr:dword, colorspace:dword, name:dword, profile_length:dword
-; if (!icc_check_length(png_ptr, colorspace, name, profile_length))
-; return 0;
-
- ; This needs to be here because the 'normal' check is in
- ; png_decompress_chunk, yet this happens after the attempt to
- ; png_malloc_base the required data. We only need this on read; on write
- ; the caller supplies the profile buffer so libpng doesn't allocate it. See
- ; the call to icc_check_length below (the write case).
-
-if PNG_SET_USER_LIMITS_SUPPORTED eq 1
-; else if (png_ptr->user_chunk_malloc_max > 0 &&
-; png_ptr->user_chunk_malloc_max < profile_length)
-; return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
-; "exceeds application limits");
-elseif PNG_USER_CHUNK_MALLOC_MAX > 0
-; else if (PNG_USER_CHUNK_MALLOC_MAX < profile_length)
-; return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
-; "exceeds libpng limits");
-else ;!SET_USER_LIMITS
- ; This will get compiled out on all 32-bit and better systems.
-; else if (PNG_SIZE_MAX < profile_length)
-; return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
-; "exceeds system limits");
-end if ;!SET_USER_LIMITS
- xor eax,eax
- inc eax
-.end_f:
- ret
-endp
-
-;int (png_structrp png_ptr, png_colorspacerp colorspace,
-; charp name, uint_32 profile_length,
-; bytep profile/* first 132 bytes only */, int color_type)
-align 4
-proc png_icc_check_header, png_ptr:dword, colorspace:dword, name:dword, profile_length:dword, profile:dword, color_type:dword
-; uint_32 temp;
-
- ; Length check; this cannot be ignored in this code because profile_length
- ; is used later to check the tag table, so even if the profile seems over
- ; long profile_length from the caller must be correct. The caller can fix
- ; this up on read or write by just passing in the profile header length.
-
-; temp = png_get_uint_32(profile);
-; if (temp != profile_length)
-; return png_icc_profile_error(png_ptr, colorspace, name, temp,
-; "length does not match profile");
-
-; temp = (uint_32) (*(profile+8));
-; if (temp > 3 && (profile_length & 3))
-; return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
-; "invalid length");
-
-; temp = png_get_uint_32(profile+128); /* tag count: 12 bytes/tag */
-; if (temp > 357913930 || /* (2^32-4-132)/12: maximum possible tag count */
-; profile_length < 132+12*temp) /* truncated tag table */
-; return png_icc_profile_error(png_ptr, colorspace, name, temp,
-; "tag count too large");
-
- ; The 'intent' must be valid or we can't store it, ICC limits the intent to
- ; 16 bits.
-
-; temp = png_get_uint_32(profile+64);
-; if (temp >= 0xffff) /* The ICC limit */
-; return png_icc_profile_error(png_ptr, colorspace, name, temp,
-; "invalid rendering intent");
-
- ; This is just a warning because the profile may be valid in future
- ; versions.
-
-; if (temp >= PNG_sRGB_INTENT_LAST)
-; (void)png_icc_profile_error(png_ptr, NULL, name, temp,
-; "intent outside defined range");
-
- ; At this point the tag table can't be checked because it hasn't necessarily
- ; been loaded; however, various header fields can be checked. These checks
- ; are for values permitted by the PNG spec in an ICC profile; the PNG spec
- ; restricts the profiles that can be passed in an iCCP chunk (they must be
- ; appropriate to processing PNG data!)
-
- ; Data checks (could be skipped). These checks must be independent of the
- ; version number; however, the version number doesn't accomodate changes in
- ; the header fields (just the known tags and the interpretation of the
- ; data.)
-
-; temp = png_get_uint_32(profile+36); /* signature 'ascp' */
-; if (temp != 0x61637370)
-; return png_icc_profile_error(png_ptr, colorspace, name, temp,
-; "invalid signature");
-
- ; Currently the PCS illuminant/adopted white point (the computational
- ; white point) are required to be D50,
- ; however the profile contains a record of the illuminant so perhaps ICC
- ; expects to be able to change this in the future (despite the rationale in
- ; the introduction for using a fixed PCS adopted white.) Consequently the
- ; following is just a warning.
-
-; if (memcmp(profile+68, D50_nCIEXYZ, 12) != 0)
-; (void)png_icc_profile_error(png_ptr, NULL, name, 0/*no tag value*/,
-; "PCS illuminant is not D50");
-
- ; The PNG spec requires this:
- ; "If the iCCP chunk is present, the image samples conform to the colour
- ; space represented by the embedded ICC profile as defined by the
- ; International Color Consortium [ICC]. The colour space of the ICC profile
- ; shall be an RGB colour space for colour images (PNG colour types 2, 3, and
- ; 6), or a greyscale colour space for greyscale images (PNG colour types 0
- ; and 4)."
-
- ; This checking code ensures the embedded profile (on either read or write)
- ; conforms to the specification requirements. Notice that an ICC 'gray'
- ; color-space profile contains the information to transform the monochrome
- ; data to XYZ or L*a*b (according to which PCS the profile uses) and this
- ; should be used in preference to the standard libpng K channel replication
- ; into R, G and B channels.
-
- ; Previously it was suggested that an RGB profile on grayscale data could be
- ; handled. However it it is clear that using an RGB profile in this context
- ; must be an error - there is no specification of what it means. Thus it is
- ; almost certainly more correct to ignore the profile.
-
-; temp = png_get_uint_32(profile+16); /* data colour space field */
-; switch (temp)
-; {
-; case 0x52474220: /* 'RGB ' */
-; if ((color_type & PNG_COLOR_MASK_COLOR) == 0)
-; return png_icc_profile_error(png_ptr, colorspace, name, temp,
-; "RGB color space not permitted on grayscale PNG");
-; break;
-
-; case 0x47524159: /* 'GRAY' */
-; if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
-; return png_icc_profile_error(png_ptr, colorspace, name, temp,
-; "Gray color space not permitted on RGB PNG");
-; break;
-
-; default:
-; return png_icc_profile_error(png_ptr, colorspace, name, temp,
-; "invalid ICC profile color space");
-; }
-
- ; It is up to the application to check that the profile class matches the
- ; application requirements; the spec provides no guidance, but it's pretty
- ; weird if the profile is not scanner ('scnr'), monitor ('mntr'), printer
- ; ('prtr') or 'spac' (for generic color spaces). Issue a warning in these
- ; cases. Issue an error for device link or abstract profiles - these don't
- ; contain the records necessary to transform the color-space to anything
- ; other than the target device (and not even that for an abstract profile).
- ; Profiles of these classes may not be embedded in images.
-
-; temp = png_get_uint_32(profile+12); /* profile/device class */
-; switch (temp)
-; {
-; case 0x73636e72: /* 'scnr' */
-; case 0x6d6e7472: /* 'mntr' */
-; case 0x70727472: /* 'prtr' */
-; case 0x73706163: /* 'spac' */
-; /* All supported */
-; break;
-
-; case 0x61627374: /* 'abst' */
-; /* May not be embedded in an image */
-; return png_icc_profile_error(png_ptr, colorspace, name, temp,
-; "invalid embedded Abstract ICC profile");
-
-; case 0x6c696e6b: /* 'link' */
-; /* DeviceLink profiles cannot be interpreted in a non-device specific
- ; fashion, if an app uses the AToB0Tag in the profile the results are
- ; undefined unless the result is sent to the intended device,
- ; therefore a DeviceLink profile should not be found embedded in a
- ; PNG.
-
-; return png_icc_profile_error(png_ptr, colorspace, name, temp,
-; "unexpected DeviceLink ICC profile class");
-
-; case 0x6e6d636c: /* 'nmcl' */
-; /* A NamedColor profile is also device specific, however it doesn't
- ; contain an AToB0 tag that is open to misinterpretation. Almost
- ; certainly it will fail the tests below.
-
-; (void)png_icc_profile_error(png_ptr, NULL, name, temp,
-; "unexpected NamedColor ICC profile class");
-; break;
-
-; default:
-; /* To allow for future enhancements to the profile accept unrecognized
- ; profile classes with a warning, these then hit the test below on the
- ; tag content to ensure they are backward compatible with one of the
- ; understood profiles.
-
-; (void)png_icc_profile_error(png_ptr, NULL, name, temp,
-; "unrecognized ICC profile class");
-; break;
-; }
-
- ; For any profile other than a device link one the PCS must be encoded
- ; either in XYZ or Lab.
-
-; temp = png_get_uint_32(profile+20);
-; switch (temp)
-; {
-; case 0x58595a20: /* 'XYZ ' */
-; case 0x4c616220: /* 'Lab ' */
-; break;
-
-; default:
-; return png_icc_profile_error(png_ptr, colorspace, name, temp,
-; "unexpected ICC PCS encoding");
-; }
-
-; return 1;
- ret
-endp
-
-;int (png_structrp png_ptr, png_colorspacerp colorspace,
-; charp name, uint_32 profile_length,
-; bytep profile /* header plus whole tag table */)
-align 4
-proc png_icc_check_tag_table, png_ptr:dword, colorspace:dword, name:dword, profile_length:dword, profile:dword
-; uint_32 tag_count = png_get_uint_32(profile+128);
-; uint_32 itag;
-; bytep tag = profile+132; /* The first tag */
-
- ; First scan all the tags in the table and add bits to the icc_info value
- ; (temporarily in 'tags').
-
-; for (itag=0; itag < tag_count; ++itag, tag += 12)
-; {
-; uint_32 tag_id = png_get_uint_32(tag+0);
-; uint_32 tag_start = png_get_uint_32(tag+4); /* must be aligned */
-; uint_32 tag_length = png_get_uint_32(tag+8);/* not padded */
-
- ; The ICC specification does not exclude zero length tags, therefore the
- ; start might actually be anywhere if there is no data, but this would be
- ; a clear abuse of the intent of the standard so the start is checked for
- ; being in range. All defined tag types have an 8 byte header - a 4 byte
- ; type signature then 0.
-
-; if ((tag_start & 3) != 0)
-; {
- ; CNHP730S.icc shipped with Microsoft Windows 64 violates this, it is
- ; only a warning here because libpng does not care about the
- ; alignment.
-
-; (void)png_icc_profile_error(png_ptr, NULL, name, tag_id,
-; "ICC profile tag start not a multiple of 4");
-; }
-
- ; This is a hard error; potentially it can cause read outside the
- ; profile.
-
-; if (tag_start > profile_length || tag_length > profile_length - tag_start)
-; return png_icc_profile_error(png_ptr, colorspace, name, tag_id,
-; "ICC profile tag outside profile");
-; }
- xor eax,eax
- inc eax ;success, maybe with warnings
-.end_f:
- ret
-endp
-
-;if PNG_sRGB_SUPPORTED
-;#if PNG_sRGB_PROFILE_CHECKS >= 0
-; Information about the known ICC sRGB profiles
-struct png_sRGB_checks
- adler dd ? ;uint_32
- crc dd ?
- length dd ?
- md5 rd 4 ;uint_32[4]
- have_md5 db ? ;byte
- is_broken db ? ;byte
- intent dw ? ;uint_16
-ends
-;# define PNG_MD5(a,b,c,d) { a, b, c, d }, (a!=0)||(b!=0)||(c!=0)||(d!=0)
-;# define PNG_ICC_CHECKSUM(adler, crc, md5, intent, broke, date, length, fname)\
-; { adler, crc, length, md5, broke, intent },
-
-;[] =
- ; This data comes from contrib/tools/checksum-icc run on downloads of
- ; all four ICC sRGB profiles from www.color.org.
-
- ; adler32, crc32, MD5[4], intent, date, length, file-name
-; PNG_ICC_CHECKSUM(0x0a3fd9f6, 0x3b8772b9,
-; PNG_MD5(0x29f83dde, 0xaff255ae, 0x7842fae4, 0xca83390d), 0, 0,
-; "2009/03/27 21:36:31", 3048, "sRGB_IEC61966-2-1_black_scaled.icc")
-
- ; ICC sRGB v2 perceptual no black-compensation:
-; PNG_ICC_CHECKSUM(0x4909e5e1, 0x427ebb21,
-; PNG_MD5(0xc95bd637, 0xe95d8a3b, 0x0df38f99, 0xc1320389), 1, 0,
-; "2009/03/27 21:37:45", 3052, "sRGB_IEC61966-2-1_no_black_scaling.icc")
-
-; PNG_ICC_CHECKSUM(0xfd2144a1, 0x306fd8ae,
-; PNG_MD5(0xfc663378, 0x37e2886b, 0xfd72e983, 0x8228f1b8), 0, 0,
-; "2009/08/10 17:28:01", 60988, "sRGB_v4_ICC_preference_displayclass.icc")
-
- ; ICC sRGB v4 perceptual
-; PNG_ICC_CHECKSUM(0x209c35d2, 0xbbef7812,
-; PNG_MD5(0x34562abf, 0x994ccd06, 0x6d2c5721, 0xd0d68c5d), 0, 0,
-; "2007/07/25 00:05:37", 60960, "sRGB_v4_ICC_preference.icc")
-
- ; The following profiles have no known MD5 checksum. If there is a match
- ; on the (empty) MD5 the other fields are used to attempt a match and
- ; a warning is produced. The first two of these profiles have a 'cprt' tag
- ; which suggests that they were also made by Hewlett Packard.
-
-; PNG_ICC_CHECKSUM(0xa054d762, 0x5d5129ce,
-; PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 0,
-; "2004/07/21 18:57:42", 3024, "sRGB_IEC61966-2-1_noBPC.icc")
-
- ; This is a 'mntr' (display) profile with a mediaWhitePointTag that does not
- ; match the D50 PCS illuminant in the header (it is in fact the D65 values,
- ; so the white point is recorded as the un-adapted value.) The profiles
- ; below only differ in one byte - the intent - and are basically the same as
- ; the previous profile except for the mediaWhitePointTag error and a missing
- ; chromaticAdaptationTag.
-
-; PNG_ICC_CHECKSUM(0xf784f3fb, 0x182ea552,
-; PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 0, 1/*broken*/,
-; "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 perceptual")
-
-; PNG_ICC_CHECKSUM(0x0398f3fc, 0xf29e526d,
-; PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 1/*broken*/,
-; "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 media-relative")
-;
-
-;int (png_structrp png_ptr, bytep profile, uLong adler)
-align 4
-proc png_compare_ICC_profile_with_sRGB, png_ptr:dword, profile:dword, adler:dword
- ; The quick check is to verify just the MD5 signature and trust the
- ; rest of the data. Because the profile has already been verified for
- ; correctness this is safe. png_colorspace_set_sRGB will check the 'intent'
- ; field too, so if the profile has been edited with an intent not defined
- ; by sRGB (but maybe defined by a later ICC specification) the read of
- ; the profile will fail at that point.
-
-; uint_32 length = 0;
-; uint_32 intent = 0x10000; /* invalid */
-if PNG_sRGB_PROFILE_CHECKS > 1
-; uLong crc = 0; /* the value for 0 length data */
-end if
-; uint i;
-
-if PNG_SET_OPTION_SUPPORTED eq 1
- ; First see if PNG_SKIP_sRGB_CHECK_PROFILE has been set to "on"
-; if (((png_ptr->options >> PNG_SKIP_sRGB_CHECK_PROFILE) & 3) ==
-; PNG_OPTION_ON)
-; return 0;
-end if
-
-; for (i=0; i < (sizeof png_sRGB_checks) / (sizeof png_sRGB_checks[0]); ++i)
-; {
-; if (png_get_uint_32(profile+84) == png_sRGB_checks[i].md5[0] &&
-; png_get_uint_32(profile+88) == png_sRGB_checks[i].md5[1] &&
-; png_get_uint_32(profile+92) == png_sRGB_checks[i].md5[2] &&
-; png_get_uint_32(profile+96) == png_sRGB_checks[i].md5[3])
-; {
- ; This may be one of the old HP profiles without an MD5, in that
- ; case we can only use the length and Adler32 (note that these
- ; are not used by default if there is an MD5!)
-
-;# if PNG_sRGB_PROFILE_CHECKS == 0
-; if (png_sRGB_checks[i].have_md5 != 0)
-; return 1+png_sRGB_checks[i].is_broken;
-;# endif
-
- ; Profile is unsigned or more checks have been configured in.
-; if (length == 0)
-; {
-; length = png_get_uint_32(profile);
-; intent = png_get_uint_32(profile+64);
-; }
-
- ; Length *and* intent must match
-; if (length == (uint_32) png_sRGB_checks[i].length &&
-; intent == (uint_32) png_sRGB_checks[i].intent)
-; {
- ; Now calculate the adler32 if not done already.
-; if (adler == 0)
-; {
-; adler = adler32(0, NULL, 0);
-; adler = adler32(adler, profile, length);
-; }
-
-; if (adler == png_sRGB_checks[i].adler)
-; {
- ; These basic checks suggest that the data has not been
- ; modified, but if the check level is more than 1 perform
- ; our own crc32 checksum on the data.
-
-;# if PNG_sRGB_PROFILE_CHECKS > 1
-; if (crc == 0)
-; {
-; crc = calc_crc32(0, NULL, 0);
-; crc = calc_crc32(crc, profile, length);
-; }
-
-; /* So this check must pass for the 'return' below to happen.
-
-; if (crc == png_sRGB_checks[i].crc)
-;# endif
-; {
-; if (png_sRGB_checks[i].is_broken != 0)
-; {
- ; These profiles are known to have bad data that may cause
- ; problems if they are used, therefore attempt to
- ; discourage their use, skip the 'have_md5' warning below,
- ; which is made irrelevant by this error.
-
-; png_chunk_report(png_ptr, "known incorrect sRGB profile",
-; PNG_CHUNK_ERROR);
-; }
-
- ; Warn that this being done; this isn't even an error since
- ; the profile is perfectly valid, but it would be nice if
- ; people used the up-to-date ones.
-
-; else if (png_sRGB_checks[i].have_md5 == 0)
-; {
-; png_chunk_report(png_ptr,
-; "out-of-date sRGB profile with no signature",
-; PNG_CHUNK_WARNING);
-; }
-
-; return 1+png_sRGB_checks[i].is_broken;
-; }
-; }
-
-;# if PNG_sRGB_PROFILE_CHECKS > 0
- ; The signature matched, but the profile had been changed in some
- ; way. This probably indicates a data error or uninformed hacking.
- ; Fall through to "no match".
-
-; png_chunk_report(png_ptr,
-; "Not recognizing known sRGB profile that has been edited",
-; PNG_CHUNK_WARNING);
-; break;
-;# endif
-; }
-; }
-; }
-
-; return 0; /* no match */
- ret
-endp
-
-;void (png_structrp png_ptr,
-; png_colorspacerp colorspace, bytep profile, uLong adler)
-align 4
-proc png_icc_set_sRGB uses eax, png_ptr:dword, colorspace:dword, profile:dword, adler:dword
- ; Is this profile one of the known ICC sRGB profiles? If it is, just set
- ; the sRGB information.
-
-; if (png_compare_ICC_profile_with_sRGB(png_ptr, profile, adler) != 0)
-; (void)png_colorspace_set_sRGB(png_ptr, colorspace,
-; (int)/*already checked*/png_get_uint_32(profile+64));
- ret
-endp
-;end if /* PNG_sRGB_PROFILE_CHECKS >= 0 */
-;end if /* sRGB */
-
-;int (png_structrp png_ptr, png_colorspacerp colorspace,
-; charp name, uint_32 profile_length, bytep profile,
-; int color_type)
-align 4
-proc png_colorspace_set_ICC, png_ptr:dword, colorspace:dword, name:dword, profile_length:dword, profile:dword, color_type:dword
-; if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
-; return 0;
-
-; if (icc_check_length(png_ptr, colorspace, name, profile_length) != 0 &&
-; png_icc_check_header(png_ptr, colorspace, name, profile_length, profile,
-; color_type) != 0 &&
-; png_icc_check_tag_table(png_ptr, colorspace, name, profile_length,
-; profile) != 0)
-; {
-;# if defined(PNG_sRGB_SUPPORTED) && PNG_sRGB_PROFILE_CHECKS >= 0
- ; If no sRGB support, don't try storing sRGB information
-; png_icc_set_sRGB(png_ptr, colorspace, profile, 0);
-;# endif
-; return 1;
-; }
-
- ; Failure case
- xor eax,eax
-.end_f:
- ret
-endp
-;end if /* iCCP */
-
-;void (png_structrp png_ptr)
-align 4
-proc png_colorspace_set_rgb_coefficients, png_ptr:dword
- ; Set the rgb_to_gray coefficients from the colorspace.
-; if (png_ptr->rgb_to_gray_coefficients_set == 0 &&
-; (png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
-; {
- ; png_set_background has not been called, get the coefficients from the Y
- ; values of the colorspace colorants.
-
-; png_fixed_point r = png_ptr->colorspace.end_points_XYZ.red_Y;
-; png_fixed_point g = png_ptr->colorspace.end_points_XYZ.green_Y;
-; png_fixed_point b = png_ptr->colorspace.end_points_XYZ.blue_Y;
-; png_fixed_point total = r+g+b;
-
-; if (total > 0 &&
-; r >= 0 && png_muldiv(&r, r, 32768, total) && r >= 0 && r <= 32768 &&
-; g >= 0 && png_muldiv(&g, g, 32768, total) && g >= 0 && g <= 32768 &&
-; b >= 0 && png_muldiv(&b, b, 32768, total) && b >= 0 && b <= 32768 &&
-; r+g+b <= 32769)
-; {
- ; We allow 0 coefficients here. r+g+b may be 32769 if two or
- ; all of the coefficients were rounded up. Handle this by
- ; reducing the *largest* coefficient by 1; this matches the
- ; approach used for the default coefficients in pngrtran.c
-
-; int add = 0;
-;
-; if (r+g+b > 32768)
-; add = -1;
-; else if (r+g+b < 32768)
-; add = 1;
-
-; if (add != 0)
-; {
-; if (g >= r && g >= b)
-; g += add;
-; else if (r >= g && r >= b)
-; r += add;
-; else
-; b += add;
-; }
-
-; /* Check for an internal error. */
-; if (r+g+b != 32768)
-; png_error(png_ptr,
-; "internal error handling cHRM coefficients");
-
-; else
-; {
-; png_ptr->rgb_to_gray_red_coeff = (uint_16)r;
-; png_ptr->rgb_to_gray_green_coeff = (uint_16)g;
-; }
-; }
-
- ; This is a png_error at present even though it could be ignored -
- ; it should never happen, but it is important that if it does, the
- ; bug is fixed.
-
-; else
-; png_error(png_ptr, "internal error handling cHRM->XYZ");
-; }
- ret
-endp
-
-;end if /* COLORSPACE */
-
-;void (png_structrp png_ptr,
-; uint_32 width, uint_32 height, int bit_depth,
-; int color_type, int interlace_type, int compression_type, int filter_type)
-align 4
-proc png_check_IHDR uses eax ebx edi, png_ptr:dword, width:dword, height:dword, bit_depth:dword, color_type:dword, interlace_type:dword, compression_type:dword, filter_type:dword
- mov edi,[png_ptr]
- xor ebx,ebx
-
- ; Check for width and height valid values
- cmp dword[width],0
- jne @f ;if (..==0)
- png_warning edi, 'Image width is zero in IHDR'
- inc ebx
- @@:
-
- cmp dword[width],PNG_UINT_31_MAX
- jle @f ;if (..>..)
- png_warning edi, 'Invalid image width in IHDR'
- inc ebx
- @@:
-
- ; 48 - big_row_buf hack
- ; 1 - filter byte
- ; 8 - 8-byte RGBA pixels
- ; 1 - extra max_pixel_depth pad
- mov eax,[width]
- add eax,7
- and eax,not 7
- cmp eax,((PNG_SIZE_MAX -48 -1) / 8) -1
- jle @f ;if (..>..)
- ; The size of the row must be within the limits of this architecture.
- ; Because the read code can perform arbitrary transformations the
- ; maximum size is checked here. Because the code in png_read_start_row
- ; adds extra space "for safety's sake" in several places a conservative
- ; limit is used here.
-
- ; NOTE: it would be far better to check the size that is actually used,
- ; but the effect in the real world is minor and the changes are more
- ; extensive, therefore much more dangerous and much more difficult to
- ; write in a way that avoids compiler warnings.
-
- png_warning edi, 'Image width is too large for this architecture'
- inc ebx
- @@:
-
-if PNG_SET_USER_LIMITS_SUPPORTED eq 1
- mov eax,[edi+png_struct.user_width_max]
- cmp dword[width],eax
-else
- cmp dword[width],PNG_USER_WIDTH_MAX
-end if
- jle @f ;if (..>..)
- png_warning edi, 'Image width exceeds user limit in IHDR'
- inc ebx
- @@:
-
- cmp dword[height],0
- jne @f ;if (..==0)
- png_warning edi, 'Image height is zero in IHDR'
- inc ebx
- @@:
-
- cmp dword[height],PNG_UINT_31_MAX
- jle @f ;if (..>..)
- png_warning edi, 'Invalid image height in IHDR'
- inc ebx
- @@:
-
-if PNG_SET_USER_LIMITS_SUPPORTED eq 1
- mov eax,[edi+png_struct.user_height_max]
- cmp dword[height],eax
-else
- cmp dword[height],PNG_USER_HEIGHT_MAX
-end if
- jle @f ;if (..>..)
- png_warning edi, 'Image height exceeds user limit in IHDR'
- inc ebx
- @@:
-
- ; Check other values
- cmp dword[bit_depth],1
- je @f
- cmp dword[bit_depth],2
- je @f
- cmp dword[bit_depth],4
- je @f
- cmp dword[bit_depth],8
- je @f
- cmp dword[bit_depth],16
- je @f ;if (..!=.. && ...)
- png_warning edi, 'Invalid bit depth in IHDR'
- inc ebx
- @@:
-
- cmp dword[color_type],0
- jl @f
- cmp dword[color_type],1
- je @f
- cmp dword[color_type],5
- je @f
- cmp dword[color_type],6
- jg @f
- jmp .end0
- @@: ;if (..<0 || ..==1 || ..==5 || ..>6)
- png_warning edi, 'Invalid color type in IHDR'
- inc ebx
- .end0:
-
- cmp dword[color_type],PNG_COLOR_TYPE_PALETTE
- jne @f
- cmp dword[bit_depth],8
- jg .beg1
- @@:
- cmp dword[color_type],PNG_COLOR_TYPE_RGB
- je @f
- cmp dword[color_type],PNG_COLOR_TYPE_GRAY_ALPHA
- je @f
- cmp dword[color_type],PNG_COLOR_TYPE_RGB_ALPHA
- jne .end1
- @@:
- cmp dword[bit_depth],8
- jge .end1
- .beg1: ;if (((..==..) && ..>..) || ((..==.. || ..==.. || ..==..) && ..<..))
- png_warning edi, 'Invalid color type/bit depth combination in IHDR'
- inc ebx
- .end1:
-
- cmp dword[interlace_type],PNG_INTERLACE_LAST
- jl @f ;if (..>=..)
- png_warning edi, 'Unknown interlace method in IHDR'
- inc ebx
- @@:
-
- cmp dword[compression_type],PNG_COMPRESSION_TYPE_BASE
- je @f ;if (..!=..)
- png_warning edi, 'Unknown compression method in IHDR'
- inc ebx
- @@:
-
-if PNG_MNG_FEATURES_SUPPORTED eq 1
- ; Accept filter_method 64 (intrapixel differencing) only if
- ; 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
- ; 2. Libpng did not read a PNG signature (this filter_method is only
- ; used in PNG datastreams that are embedded in MNG datastreams) and
- ; 3. The application called png_permit_mng_features with a mask that
- ; included PNG_FLAG_MNG_FILTER_64 and
- ; 4. The filter_method is 64 and
- ; 5. The color_type is RGB or RGBA
-
-; if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) != 0 &&
-; png_ptr->mng_features_permitted != 0)
- png_warning edi, 'MNG features are not allowed in a PNG datastream'
-
-; if (filter_type != PNG_FILTER_TYPE_BASE)
-; {
-; if (!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
-; (filter_type == PNG_INTRAPIXEL_DIFFERENCING) &&
-; ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) == 0) &&
-; (color_type == PNG_COLOR_TYPE_RGB ||
-; color_type == PNG_COLOR_TYPE_RGB_ALPHA)))
-; {
- png_warning edi, 'Unknown filter method in IHDR'
- inc ebx
-; }
-
-; if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) != 0)
-; {
- png_warning edi, 'Invalid filter method in IHDR'
- inc ebx
-; }
-; }
-
-else
- cmp dword[filter_type],PNG_FILTER_TYPE_BASE
- je @f ;if (..!=..)
- png_warning edi, 'Unknown filter method in IHDR'
- inc ebx
- @@:
-end if
-
- cmp ebx,0
- je @f
- png_error edi, 'Invalid IHDR data'
- @@:
- ret
-endp
-
-;#if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED)
-; ASCII to fp functions
-; Check an ASCII formated floating point value, see the more detailed
-; comments in pngpriv.inc
-
-; The following is used internally to preserve the sticky flags */
-;#define png_fp_add(state, flags) ((state) |= (flags))
-;#define png_fp_set(state, value) ((state) = (value) | ((state) & PNG_FP_STICKY))
-
-;int (charp string, png_size_t size, int *statep, png_size_tp whereami)
-align 4
-proc png_check_fp_number, string:dword, size:dword, statep:dword, whereami:dword
-; int state = *statep;
-; png_size_t i = *whereami;
-
-; while (i < size)
-; {
-; int type;
- ; First find the type of the next character
-; switch (string[i])
-; {
-; case 43: type = PNG_FP_SAW_SIGN; break;
-; case 45: type = PNG_FP_SAW_SIGN + PNG_FP_NEGATIVE; break;
-; case 46: type = PNG_FP_SAW_DOT; break;
-; case 48: type = PNG_FP_SAW_DIGIT; break;
-; case 49: case 50: case 51: case 52:
-; case 53: case 54: case 55: case 56:
-; case 57: type = PNG_FP_SAW_DIGIT + PNG_FP_NONZERO; break;
-; case 69:
-; case 101: type = PNG_FP_SAW_E; break;
-; default: goto PNG_FP_End;
-; }
-
- ; Now deal with this type according to the current
- ; state, the type is arranged to not overlap the
- ; bits of the PNG_FP_STATE.
-
-; switch ((state & PNG_FP_STATE) + (type & PNG_FP_SAW_ANY))
-; {
-; case PNG_FP_INTEGER + PNG_FP_SAW_SIGN:
-; if ((state & PNG_FP_SAW_ANY) != 0)
-; goto PNG_FP_End; /* not a part of the number */
-
-; png_fp_add(state, type);
-; break;
-
-; case PNG_FP_INTEGER + PNG_FP_SAW_DOT:
- ; Ok as trailer, ok as lead of fraction.
-; if ((state & PNG_FP_SAW_DOT) != 0) /* two dots */
-; goto PNG_FP_End;
-
-; else if ((state & PNG_FP_SAW_DIGIT) != 0) /* trailing dot? */
-; png_fp_add(state, type);
-
-; else
-; png_fp_set(state, PNG_FP_FRACTION | type);
-
-; break;
-
-; case PNG_FP_INTEGER + PNG_FP_SAW_DIGIT:
-; if ((state & PNG_FP_SAW_DOT) != 0) /* delayed fraction */
-; png_fp_set(state, PNG_FP_FRACTION | PNG_FP_SAW_DOT);
-
-; png_fp_add(state, type | PNG_FP_WAS_VALID);
-
-; break;
-
-; case PNG_FP_INTEGER + PNG_FP_SAW_E:
-; if ((state & PNG_FP_SAW_DIGIT) == 0)
-; goto PNG_FP_End;
-
-; png_fp_set(state, PNG_FP_EXPONENT);
-
-; break;
-
-; /* case PNG_FP_FRACTION + PNG_FP_SAW_SIGN: goto PNG_FP_End; ** no sign in fraction */
-
-; /* case PNG_FP_FRACTION + PNG_FP_SAW_DOT: goto PNG_FP_End; ** Because SAW_DOT is always set */
-
-; case PNG_FP_FRACTION + PNG_FP_SAW_DIGIT:
-; png_fp_add(state, type | PNG_FP_WAS_VALID);
-; break;
-
-; case PNG_FP_FRACTION + PNG_FP_SAW_E:
- ; This is correct because the trailing '.' on an
- ; integer is handled above - so we can only get here
- ; with the sequence ".E" (with no preceding digits).
-
-; if ((state & PNG_FP_SAW_DIGIT) == 0)
-; goto PNG_FP_End;
-
-; png_fp_set(state, PNG_FP_EXPONENT);
-
-; break;
-
-; case PNG_FP_EXPONENT + PNG_FP_SAW_SIGN:
-; if ((state & PNG_FP_SAW_ANY) != 0)
-; goto PNG_FP_End; /* not a part of the number */
-
-; png_fp_add(state, PNG_FP_SAW_SIGN);
-
-; break;
-
-; /* case PNG_FP_EXPONENT + PNG_FP_SAW_DOT: goto PNG_FP_End; */
-
-; case PNG_FP_EXPONENT + PNG_FP_SAW_DIGIT:
-; png_fp_add(state, PNG_FP_SAW_DIGIT | PNG_FP_WAS_VALID);
-
-; break;
-
-; /* case PNG_FP_EXPONEXT + PNG_FP_SAW_E: goto PNG_FP_End; */
-
-; default: goto PNG_FP_End; /* I.e. break 2 */
-; }
-
- ; The character seems ok, continue.
-; ++i;
-; }
-;
-;PNG_FP_End:
- ; Here at the end, update the state and return the correct
- ; return code.
-
-; *statep = state;
-; *whereami = i;
-
-; return (state & PNG_FP_SAW_DIGIT) != 0;
- ret
-endp
-
-
-; The same but for a complete string.
-;int (charp string, png_size_t size)
-align 4
-proc png_check_fp_string, string:dword, size:dword
-; int state=0;
-; png_size_t char_index=0;
-;
-; if (png_check_fp_number(string, size, &state, &char_index) != 0 &&
-; (char_index == size || string[char_index] == 0))
-; return state /* must be non-zero - see above */;
-
-; return 0; /* i.e. fail */
- ret
-endp
-;end if /* pCAL || sCAL */
-
-;if PNG_sCAL_SUPPORTED
-;# ifdef PNG_FLOATING_POINT_SUPPORTED
-; Utility used below - a simple accurate power of ten from an integral
-; exponent.
-
-;double (int power)
-align 4
-proc png_pow10, power:dword
-; int recip = 0;
-; double d = 1;
-
- ; Handle negative exponent with a reciprocal at the end because
- ; 10 is exact whereas .1 is inexact in base 2
-
-; if (power < 0)
-; {
-; if (power < DBL_MIN_10_EXP) return 0;
-; recip = 1, power = -power;
-; }
-
-; if (power > 0)
-; {
- ; Decompose power bitwise.
-; double mult = 10;
-; do
-; {
-; if (power & 1) d *= mult;
-; mult *= mult;
-; power >>= 1;
-; }
-; while (power > 0);
-
-; if (recip != 0) d = 1/d;
-; }
- ; else power is 0 and d is 1
-
-; return d;
- ret
-endp
-
-; Function to format a floating point value in ASCII with a given
-; precision.
-
-;void (png_structrp png_ptr, charp ascii, png_size_t size,
-; double fp, uint precision)
-align 4
-proc png_ascii_from_fp, png_ptr:dword, ascii:dword, size:dword, fp:dword, precision:dword
- ; We use standard functions from math.h, but not printf because
- ; that would require stdio. The caller must supply a buffer of
- ; sufficient size or we will png_error. The tests on size and
- ; the space in ascii[] consumed are indicated below.
-
-; if (precision < 1)
-; precision = DBL_DIG;
-
- ; Enforce the limit of the implementation precision too.
-; if (precision > DBL_DIG+1)
-; precision = DBL_DIG+1;
-
- ; Basic sanity checks
-; if (size >= precision+5) /* See the requirements below. */
-; {
-; if (fp < 0)
-; {
-; fp = -fp;
-; *ascii++ = 45; /* '-' PLUS 1 TOTAL 1 */
-; --size;
-; }
-
-; if (fp >= DBL_MIN && fp <= DBL_MAX)
-; {
-; int exp_b10; /* A base 10 exponent */
-; double base; /* 10^exp_b10 */
-
- ; First extract a base 10 exponent of the number,
- ; the calculation below rounds down when converting
- ; from base 2 to base 10 (multiply by log10(2) -
- ; 0.3010, but 77/256 is 0.3008, so exp_b10 needs to
- ; be increased. Note that the arithmetic shift
- ; performs a floor() unlike C arithmetic - using a
- ; C multiply would break the following for negative
- ; exponents.
-
-; (void)frexp(fp, &exp_b10); /* exponent to base 2 */
-
-; exp_b10 = (exp_b10 * 77) >> 8; /* <= exponent to base 10 */
-
-; /* Avoid underflow here. */
-; base = png_pow10(exp_b10); /* May underflow */
-
-; while (base < DBL_MIN || base < fp)
-; {
-; /* And this may overflow. */
-; double test = png_pow10(exp_b10+1);
-
-; if (test <= DBL_MAX)
-; ++exp_b10, base = test;
-
-; else
-; break;
-; }
-
- ; Normalize fp and correct exp_b10, after this fp is in the
- ; range [.1,1) and exp_b10 is both the exponent and the digit
- ; *before* which the decimal point should be inserted
- ; (starting with 0 for the first digit). Note that this
- ; works even if 10^exp_b10 is out of range because of the
- ; test on DBL_MAX above.
-
-; fp /= base;
-; while (fp >= 1) fp /= 10, ++exp_b10;
-
- ; Because of the code above fp may, at this point, be
- ; less than .1, this is ok because the code below can
- ; handle the leading zeros this generates, so no attempt
- ; is made to correct that here.
-
-; {
-; uint czero, clead, cdigits;
-; char exponent[10];
-
- ; Allow up to two leading zeros - this will not lengthen
- ; the number compared to using E-n.
-
-; if (exp_b10 < 0 && exp_b10 > -3) /* PLUS 3 TOTAL 4 */
-; {
-; czero = -exp_b10; /* PLUS 2 digits: TOTAL 3 */
-; exp_b10 = 0; /* Dot added below before first output. */
-; }
-; else
-; czero = 0; /* No zeros to add */
-
- ; Generate the digit list, stripping trailing zeros and
- ; inserting a '.' before a digit if the exponent is 0.
-
-; clead = czero; /* Count of leading zeros */
-; cdigits = 0; /* Count of digits in list. */
-
-; do
-; {
-; double d;
-
-; fp *= 10;
- ; Use modf here, not floor and subtract, so that
- ; the separation is done in one step. At the end
- ; of the loop don't break the number into parts so
- ; that the final digit is rounded.
-
-; if (cdigits+czero+1 < precision+clead)
-; fp = modf(fp, &d);
-
-; else
-; {
-; d = floor(fp + .5);
-
-; if (d > 9)
-; {
-; /* Rounding up to 10, handle that here. */
-; if (czero > 0)
-; {
-; --czero, d = 1;
-; if (cdigits == 0) --clead;
-; }
-; else
-; {
-; while (cdigits > 0 && d > 9)
-; {
-; int ch = *--ascii;
-
-; if (exp_b10 != (-1))
-; ++exp_b10;
-
-; else if (ch == 46)
-; {
-; ch = *--ascii, ++size;
-; /* Advance exp_b10 to '1', so that the
-; * decimal point happens after the
-; * previous digit.
-
-; exp_b10 = 1;
-; }
-
-; --cdigits;
-; d = ch - 47; /* I.e. 1+(ch-48) */
-; }
-
-; /* Did we reach the beginning? If so adjust the
-; * exponent but take into account the leading
-; * decimal point.
-
-; if (d > 9) /* cdigits == 0 */
-; {
-; if (exp_b10 == (-1))
-; {
- ; Leading decimal point (plus zeros?), if
- ; we lose the decimal point here it must
- ; be reentered below.
-
-; int ch = *--ascii;
-
-; if (ch == 46)
-; ++size, exp_b10 = 1;
-
-; /* Else lost a leading zero, so 'exp_b10' is
-; * still ok at (-1)
-
-; }
-; else
-; ++exp_b10;
-
-; /* In all cases we output a '1' */
-; d = 1;
-; }
-; }
-; }
-; fp = 0; /* Guarantees termination below. */
-; }
-
-; if (d == 0)
-; {
-; ++czero;
-; if (cdigits == 0) ++clead;
-; }
-; else
-; {
-; /* Included embedded zeros in the digit count. */
-; cdigits += czero - clead;
-; clead = 0;
-
-; while (czero > 0)
-; {
- ; exp_b10 == (-1) means we just output the decimal
- ; place - after the DP don't adjust 'exp_b10' any
- ; more!
-
-; if (exp_b10 != (-1))
-; {
-; if (exp_b10 == 0) *ascii++ = 46, --size;
-; /* PLUS 1: TOTAL 4 */
-; --exp_b10;
-; }
-; *ascii++ = 48, --czero;
-; }
-
-; if (exp_b10 != (-1))
-; {
-; if (exp_b10 == 0)
-; *ascii++ = 46, --size; /* counted above */
-
-; --exp_b10;
-; }
-; *ascii++ = (char)(48 + (int)d), ++cdigits;
-; }
-; }
-; while (cdigits+czero < precision+clead && fp > DBL_MIN);
-
-; /* The total output count (max) is now 4+precision */
-
- ; Check for an exponent, if we don't need one we are
- ; done and just need to terminate the string. At
- ; this point exp_b10==(-1) is effectively if flag - it got
- ; to '-1' because of the decrement after outputting
- ; the decimal point above (the exponent required is
- ; *not* -1!)
-
-; if (exp_b10 >= (-1) && exp_b10 <= 2)
-; {
- ; The following only happens if we didn't output the
- ; leading zeros above for negative exponent, so this
- ; doesn't add to the digit requirement. Note that the
- ; two zeros here can only be output if the two leading
- ; zeros were *not* output, so this doesn't increase
- ; the output count.
-
-; while (--exp_b10 >= 0) *ascii++ = 48;
-
-; *ascii = 0;
-
-; /* Total buffer requirement (including the '\0') is
- ; 5+precision - see check at the start.
-
-; return;
-; }
-
- ; Here if an exponent is required, adjust size for
- ; the digits we output but did not count. The total
- ; digit output here so far is at most 1+precision - no
- ; decimal point and no leading or trailing zeros have
- ; been output.
-
-; size -= cdigits;
-;
-; *ascii++ = 69, --size; /* 'E': PLUS 1 TOTAL 2+precision */
-
- ; The following use of an unsigned temporary avoids ambiguities in
- ; the signed arithmetic on exp_b10 and permits GCC at least to do
- ; better optimization.
-
-; {
-; uint uexp_b10;
-
-; if (exp_b10 < 0)
-; {
-; *ascii++ = 45, --size; /* '-': PLUS 1 TOTAL 3+precision */
-; uexp_b10 = -exp_b10;
-; }
-
-; else
-; uexp_b10 = exp_b10;
-
-; cdigits = 0;
-
-; while (uexp_b10 > 0)
-; {
-; exponent[cdigits++] = (char)(48 + uexp_b10 % 10);
-; uexp_b10 /= 10;
-; }
-; }
-
- ; Need another size check here for the exponent digits, so
- ; this need not be considered above.
-
-; if (size > cdigits)
-; {
-; while (cdigits > 0) *ascii++ = exponent[--cdigits];
-
-; *ascii = 0;
-
-; return;
-; }
-; }
-; }
-; else if (!(fp >= DBL_MIN))
-; {
-; *ascii++ = 48; /* '0' */
-; *ascii = 0;
-; return;
-; }
-; else
-; {
-; *ascii++ = 105; /* 'i' */
-; *ascii++ = 110; /* 'n' */
-; *ascii++ = 102; /* 'f' */
-; *ascii = 0;
-; return;
-; }
-; }
-
- ; Here on buffer too small.
-; png_error(png_ptr, "ASCII conversion buffer too small");
- ret
-endp
-
-;# endif /* FLOATING_POINT */
-
-; Function to format a fixed point value in ASCII.
-
-;void (png_structrp png_ptr, charp ascii, png_size_t size, png_fixed_point fp)
-align 4
-proc png_ascii_from_fixed, png_ptr:dword, ascii:dword, size:dword, fp:dword
- ; Require space for 10 decimal digits, a decimal point, a minus sign and a
- ; trailing \0, 13 characters:
-
- cmp dword[size],12
- jle .end0 ;if (..>..)
-; uint_32 num;
-
- ; Avoid overflow here on the minimum integer.
-; if (fp < 0)
-; *ascii++ = 45, num = -fp;
-; else
-; num = fp;
-
-; if (num <= 0x80000000) /* else overflowed */
-; {
-; uint ndigits = 0, first = 16 /* flag value */;
-; char digits[10];
-
-; while (num)
-; {
- ; Split the low digit off num:
-; uint tmp = num/10;
-; num -= tmp*10;
-; digits[ndigits++] = (char)(48 + num);
- ; Record the first non-zero digit, note that this is a number
- ; starting at 1, it's not actually the array index.
-
-; if (first == 16 && num > 0)
-; first = ndigits;
-; num = tmp;
-; }
-
-; if (ndigits > 0)
-; {
-; while (ndigits > 5) *ascii++ = digits[--ndigits];
- ; The remaining digits are fractional digits, ndigits is '5' or
- ; smaller at this point. It is certainly not zero. Check for a
- ; non-zero fractional digit:
-
-; if (first <= 5)
-; {
-; uint i;
-; *ascii++ = 46; /* decimal point */
- ; ndigits may be <5 for small numbers, output leading zeros
- ; then ndigits digits to first:
-
-; i = 5;
-; while (ndigits < i) *ascii++ = 48, --i;
-; while (ndigits >= first) *ascii++ = digits[--ndigits];
- ; Don't output the trailing zeros!
-; }
-; }
-; else
-; *ascii++ = 48;
-
- ; And null terminate the string:
-; *ascii = 0;
-; return;
-; }
- .end0:
-
- ; Here on buffer too small.
- png_error [png_ptr], 'ASCII conversion buffer too small'
- ret
-endp
-;end if /* SCAL */
-
-;png_fixed_point (png_structrp png_ptr, double fp, charp text)
-align 4
-proc png_fixed, png_ptr:dword, fp:dword, text:dword
-; double r = floor(100000 * fp + .5);
-
-; if (r > 2147483647. || r < -2147483648.)
-; png_fixed_error(png_ptr, text);
-
-; return (png_fixed_point)r;
- ret
-endp
-
-; muldiv functions
-; This API takes signed arguments and rounds the result to the nearest
-; integer (or, for a fixed point number - the standard argument - to
-; the nearest .00001). Overflow and divide by zero are signalled in
-; the result, a boolean - true on success, false on overflow.
-
-;int (png_fixed_point_p res, png_fixed_point a, int_32 times, int_32 divisor)
-align 4
-proc png_muldiv, res:dword, a:dword, p3times:dword, divisor:dword
- ; Return a * times / divisor, rounded.
-; if (divisor != 0)
-; {
-; if (a == 0 || p3times == 0)
-; {
-; *res = 0;
-; return 1;
-; }
-; else
-; {
-if PNG_FLOATING_ARITHMETIC_SUPPORTED eq 1
-; double r = a;
-; r *= p3times;
-; r /= divisor;
-; r = floor(r+.5);
-
-; /* A png_fixed_point is a 32-bit integer. */
-; if (r <= 2147483647. && r >= -2147483648.)
-; {
-; *res = (png_fixed_point)r;
-; return 1;
-; }
-else
-; int negative = 0;
-; uint_32 A, T, D;
-; uint_32 s16, s32, s00;
-
-; if (a < 0)
-; negative = 1, A = -a;
-; else
-; A = a;
-
-; if (p3times < 0)
-; negative = !negative, T = -p3times;
-; else
-; T = p3times;
-
-; if (divisor < 0)
-; negative = !negative, D = -divisor;
-; else
-; D = divisor;
-
- ; Following can't overflow because the arguments only
- ; have 31 bits each, however the result may be 32 bits.
-
-; s16 = (A >> 16) * (T & 0xffff) +
-; (A & 0xffff) * (T >> 16);
- ; Can't overflow because the a*times bit is only 30
- ; bits at most.
-
-; s32 = (A >> 16) * (T >> 16) + (s16 >> 16);
-; s00 = (A & 0xffff) * (T & 0xffff);
-
-; s16 = (s16 & 0xffff) << 16;
-; s00 += s16;
-
-; if (s00 < s16)
-; ++s32; /* carry */
-
-; if (s32 < D) /* else overflow */
-; {
- ; s32.s00 is now the 64-bit product, do a standard
- ; division, we know that s32 < D, so the maximum
- ; required shift is 31.
-
-; int bitshift = 32;
-; png_fixed_point result = 0; /* NOTE: signed */
-
-; while (--bitshift >= 0)
-; {
-; uint_32 d32, d00;
-
-; if (bitshift > 0)
-; d32 = D >> (32-bitshift), d00 = D << bitshift;
-
-; else
-; d32 = 0, d00 = D;
-
-; if (s32 > d32)
-; {
-; if (s00 < d00) --s32; /* carry */
-; s32 -= d32, s00 -= d00, result += 1<= d00)
-; s32 = 0, s00 -= d00, result += 1<= (D >> 1))
-; ++result;
-
-; if (negative != 0)
-; result = -result;
-
-; /* Check for overflow. */
-; if ((negative != 0 && result <= 0) ||
-; (negative == 0 && result >= 0))
-; {
-; *res = result;
-; return 1;
-; }
-; }
-end if
-; }
-; }
-
- xor eax,eax
- ret
-endp
-
-; The following is for when the caller doesn't much care about the
-; result.
-
-;png_fixed_point (png_structrp png_ptr, png_fixed_point a, int_32 times,
-; int_32 divisor)
-align 4
-proc png_muldiv_warn, png_ptr:dword, a:dword, p3times:dword, divisor:dword
-; png_fixed_point result;
-
-; if (png_muldiv(&result, a, p3times, divisor) != 0)
-; return result;
-
- png_warning [png_ptr], 'fixed point overflow ignored'
- xor eax,eax
- ret
-endp
-
-; Calculate a reciprocal, return 0 on div-by-zero or overflow.
-;png_fixed_point (png_fixed_point a)
-align 4
-proc png_reciprocal, a:dword
-if PNG_FLOATING_ARITHMETIC_SUPPORTED eq 1
-; double r = floor(1E10/a+.5);
-
-; if (r <= 2147483647. && r >= -2147483648.)
-; return (png_fixed_point)r;
-else
-; png_fixed_point res;
-
-; if (png_muldiv(&res, 100000, 100000, a) != 0)
-; return res;
-end if
-
-; return 0; /* error/overflow */
- ret
-endp
-
-; This is the shared test on whether a gamma value is 'significant' - whether
-; it is worth doing gamma correction.
-
-;int (png_fixed_point gamma_val)
-align 4
-proc png_gamma_significant, gamma_val:dword
-; return gamma_val < PNG_FP_1 - PNG_GAMMA_THRESHOLD_FIXED ||
-; gamma_val > PNG_FP_1 + PNG_GAMMA_THRESHOLD_FIXED;
- ret
-endp
-
-;if PNG_READ_GAMMA_SUPPORTED
-; A local convenience routine.
-;png_fixed_point (png_fixed_point a, png_fixed_point b)
-align 4
-proc png_product2, a:dword, b:dword
- ; The required result is 1/a * 1/b; the following preserves accuracy.
-if PNG_FLOATING_ARITHMETIC_SUPPORTED eq 1
-; double r = a * 1E-5;
-; r *= b;
-; r = floor(r+.5);
-
-; if (r <= 2147483647. && r >= -2147483648.)
-; return (png_fixed_point)r;
-else
-; png_fixed_point res;
-
-; if (png_muldiv(&res, a, b, 100000) != 0)
-; return res;
-end if
-
-; return 0; /* overflow */
- ret
-endp
-
-; The inverse of the above.
-;png_fixed_point (png_fixed_point a, png_fixed_point b)
-align 4
-proc png_reciprocal2, a:dword, b:dword
- ; The required result is 1/a * 1/b; the following preserves accuracy.
-if PNG_FLOATING_ARITHMETIC_SUPPORTED eq 1
-; if (a != 0 && b != 0)
-; {
-; double r = 1E15/a;
-; r /= b;
-; r = floor(r+.5);
-;
-; if (r <= 2147483647. && r >= -2147483648.)
-; return (png_fixed_point)r;
-; }
-else
- ; This may overflow because the range of png_fixed_point isn't symmetric,
- ; but this API is only used for the product of file and screen gamma so it
- ; doesn't matter that the smallest number it can produce is 1/21474, not
- ; 1/100000
-
-; png_fixed_point res = png_product2(a, b);
-
-; if (res != 0)
-; return png_reciprocal(res);
-end if
-
-; return 0; /* overflow */
- ret
-endp
-;end if /* READ_GAMMA */
-
-;if PNG_READ_GAMMA_SUPPORTED /* gamma table code */
-;#ifndef PNG_FLOATING_ARITHMETIC_SUPPORTED
-; Fixed point gamma.
-
-; The code to calculate the tables used below can be found in the shell script
-; contrib/tools/intgamma.sh
-
-; To calculate gamma this code implements fast log() and exp() calls using only
-; fixed point arithmetic. This code has sufficient precision for either 8-bit
-; or 16-bit sample values.
-
-; The tables used here were calculated using simple 'bc' programs, but C double
-; precision floating point arithmetic would work fine.
-
-; 8-bit log table
-; This is a table of -log(value/255)/log(2) for 'value' in the range 128 to
-; 255, so it's the base 2 logarithm of a normalized 8-bit floating point
-; mantissa. The numbers are 32-bit fractions.
-
-;const uint_32
-;png_8bit_l2[128] =
-; 4270715492U, 4222494797U, 4174646467U, 4127164793U, 4080044201U, 4033279239U,
-; 3986864580U, 3940795015U, 3895065449U, 3849670902U, 3804606499U, 3759867474U,
-; 3715449162U, 3671346997U, 3627556511U, 3584073329U, 3540893168U, 3498011834U,
-; 3455425220U, 3413129301U, 3371120137U, 3329393864U, 3287946700U, 3246774933U,
-; 3205874930U, 3165243125U, 3124876025U, 3084770202U, 3044922296U, 3005329011U,
-; 2965987113U, 2926893432U, 2888044853U, 2849438323U, 2811070844U, 2772939474U,
-; 2735041326U, 2697373562U, 2659933400U, 2622718104U, 2585724991U, 2548951424U,
-; 2512394810U, 2476052606U, 2439922311U, 2404001468U, 2368287663U, 2332778523U,
-; 2297471715U, 2262364947U, 2227455964U, 2192742551U, 2158222529U, 2123893754U,
-; 2089754119U, 2055801552U, 2022034013U, 1988449497U, 1955046031U, 1921821672U,
-; 1888774511U, 1855902668U, 1823204291U, 1790677560U, 1758320682U, 1726131893U,
-; 1694109454U, 1662251657U, 1630556815U, 1599023271U, 1567649391U, 1536433567U,
-; 1505374214U, 1474469770U, 1443718700U, 1413119487U, 1382670639U, 1352370686U,
-; 1322218179U, 1292211689U, 1262349810U, 1232631153U, 1203054352U, 1173618059U,
-; 1144320946U, 1115161701U, 1086139034U, 1057251672U, 1028498358U, 999877854U,
-; 971388940U, 943030410U, 914801076U, 886699767U, 858725327U, 830876614U,
-; 803152505U, 775551890U, 748073672U, 720716771U, 693480120U, 666362667U,
-; 639363374U, 612481215U, 585715177U, 559064263U, 532527486U, 506103872U,
-; 479792461U, 453592303U, 427502463U, 401522014U, 375650043U, 349885648U,
-; 324227938U, 298676034U, 273229066U, 247886176U, 222646516U, 197509248U,
-; 172473545U, 147538590U, 122703574U, 97967701U, 73330182U, 48790236U,
-; 24347096U, 0U
-
-if 0
- ; The following are the values for 16-bit tables - these work fine for the
- ; 8-bit conversions but produce very slightly larger errors in the 16-bit
- ; log (about 1.2 as opposed to 0.7 absolute error in the final value). To
- ; use these all the shifts below must be adjusted appropriately.
-
-; 65166, 64430, 63700, 62976, 62257, 61543, 60835, 60132, 59434, 58741, 58054,
-; 57371, 56693, 56020, 55352, 54689, 54030, 53375, 52726, 52080, 51439, 50803,
-; 50170, 49542, 48918, 48298, 47682, 47070, 46462, 45858, 45257, 44661, 44068,
-; 43479, 42894, 42312, 41733, 41159, 40587, 40020, 39455, 38894, 38336, 37782,
-; 37230, 36682, 36137, 35595, 35057, 34521, 33988, 33459, 32932, 32408, 31887,
-; 31369, 30854, 30341, 29832, 29325, 28820, 28319, 27820, 27324, 26830, 26339,
-; 25850, 25364, 24880, 24399, 23920, 23444, 22970, 22499, 22029, 21562, 21098,
-; 20636, 20175, 19718, 19262, 18808, 18357, 17908, 17461, 17016, 16573, 16132,
-; 15694, 15257, 14822, 14390, 13959, 13530, 13103, 12678, 12255, 11834, 11415,
-; 10997, 10582, 10168, 9756, 9346, 8937, 8531, 8126, 7723, 7321, 6921, 6523,
-; 6127, 5732, 5339, 4947, 4557, 4169, 3782, 3397, 3014, 2632, 2251, 1872, 1495,
-; 1119, 744, 372
-end if
-
-;int_32 (uint x)
-align 4
-proc png_log8bit, x:dword
-; uint lg2 = 0;
- ; Each time 'x' is multiplied by 2, 1 must be subtracted off the final log,
- ; because the log is actually negate that means adding 1. The final
- ; returned value thus has the range 0 (for 255 input) to 7.994 (for 1
- ; input), return -1 for the overflow (log 0) case, - so the result is
- ; always at most 19 bits.
-
-; if ((x &= 0xff) == 0)
-; return -1;
-
-; if ((x & 0xf0) == 0)
-; lg2 = 4, x <<= 4;
-
-; if ((x & 0xc0) == 0)
-; lg2 += 2, x <<= 2;
-
-; if ((x & 0x80) == 0)
-; lg2 += 1, x <<= 1;
-
- ; result is at most 19 bits, so this cast is safe:
-; return (int_32)((lg2 << 16) + ((png_8bit_l2[x-128]+32768)>>16));
- ret
-endp
-
-; The above gives exact (to 16 binary places) log2 values for 8-bit images,
-; for 16-bit images we use the most significant 8 bits of the 16-bit value to
-; get an approximation then multiply the approximation by a correction factor
-; determined by the remaining up to 8 bits. This requires an additional step
-; in the 16-bit case.
-
-; We want log2(value/65535), we have log2(v'/255), where:
-
-; value = v' * 256 + v''
-; = v' * f
-
-; So f is value/v', which is equal to (256+v''/v') since v' is in the range 128
-; to 255 and v'' is in the range 0 to 255 f will be in the range 256 to less
-; than 258. The final factor also needs to correct for the fact that our 8-bit
-; value is scaled by 255, whereas the 16-bit values must be scaled by 65535.
-
-; This gives a final formula using a calculated value 'x' which is value/v' and
-; scaling by 65536 to match the above table:
-
-; log2(x/257) * 65536
-
-; Since these numbers are so close to '1' we can use simple linear
-; interpolation between the two end values 256/257 (result -368.61) and 258/257
-; (result 367.179). The values used below are scaled by a further 64 to give
-; 16-bit precision in the interpolation:
-
-; Start (256): -23591
-; Zero (257): 0
-; End (258): 23499
-
-;int_32 (uint_32 x)
-align 4
-proc png_log16bit, x:dword
-; uint lg2 = 0;
-
- ; As above, but now the input has 16 bits.
-; if ((x &= 0xffff) == 0)
-; return -1;
-
-; if ((x & 0xff00) == 0)
-; lg2 = 8, x <<= 8;
-
-; if ((x & 0xf000) == 0)
-; lg2 += 4, x <<= 4;
-
-; if ((x & 0xc000) == 0)
-; lg2 += 2, x <<= 2;
-
-; if ((x & 0x8000) == 0)
-; lg2 += 1, x <<= 1;
-
- ; Calculate the base logarithm from the top 8 bits as a 28-bit fractional
- ; value.
-
-; lg2 <<= 28;
-; lg2 += (png_8bit_l2[(x>>8)-128]+8) >> 4;
-
- ; Now we need to interpolate the factor, this requires a division by the top
- ; 8 bits. Do this with maximum precision.
-
-; x = ((x << 16) + (x >> 9)) / (x >> 8);
-
- ; Since we divided by the top 8 bits of 'x' there will be a '1' at 1<<24,
- ; the value at 1<<16 (ignoring this) will be 0 or 1; this gives us exactly
- ; 16 bits to interpolate to get the low bits of the result. Round the
- ; answer. Note that the end point values are scaled by 64 to retain overall
- ; precision and that 'lg2' is current scaled by an extra 12 bits, so adjust
- ; the overall scaling by 6-12. Round at every step.
-
-; x -= 1U << 24;
-
-; if (x <= 65536U) /* <= '257' */
-; lg2 += ((23591U * (65536U-x)) + (1U << (16+6-12-1))) >> (16+6-12);
-
-; else
-; lg2 -= ((23499U * (x-65536U)) + (1U << (16+6-12-1))) >> (16+6-12);
-
- ; Safe, because the result can't have more than 20 bits:
-; return (int_32)((lg2 + 2048) >> 12);
- ret
-endp
-
-; The 'exp()' case must invert the above, taking a 20-bit fixed point
-; logarithmic value and returning a 16 or 8-bit number as appropriate. In
-; each case only the low 16 bits are relevant - the fraction - since the
-; integer bits (the top 4) simply determine a shift.
-
-; The worst case is the 16-bit distinction between 65535 and 65534. This
-; requires perhaps spurious accuracy in the decoding of the logarithm to
-; distinguish log2(65535/65534.5) - 10^-5 or 17 bits. There is little chance
-; of getting this accuracy in practice.
-
-; To deal with this the following exp() function works out the exponent of the
-; frational part of the logarithm by using an accurate 32-bit value from the
-; top four fractional bits then multiplying in the remaining bits.
-
-; NOTE: the first entry is deliberately set to the maximum 32-bit value.
-align 4
-png_32bit_exp dd 4294967295, 4112874773, 3938502376, 3771522796, 3611622603, 3458501653,\
- 3311872529, 3171459999, 3037000500, 2908241642, 2784941738, 2666869345,\
- 2553802834, 2445529972, 2341847524, 2242560872
-
-; Adjustment table; provided to explain the numbers in the code below.
-;#if 0
-;for (i=11;i>=0;--i){ print i, " ", (1 - e(-(2^i)/65536*l(2))) * 2^(32-i), "\n"}
-; 11 44937.64284865548751208448
-; 10 45180.98734845585101160448
-; 9 45303.31936980687359311872
-; 8 45364.65110595323018870784
-; 7 45395.35850361789624614912
-; 6 45410.72259715102037508096
-; 5 45418.40724413220722311168
-; 4 45422.25021786898173001728
-; 3 45424.17186732298419044352
-; 2 45425.13273269940811464704
-; 1 45425.61317555035558641664
-; 0 45425.85339951654943850496
-;end if
-
-;uint_32 (png_fixed_point x)
-align 4
-proc png_exp, x:dword
-; if (x > 0 && x <= 0xfffff) /* Else overflow or zero (underflow) */
-; {
- ; Obtain a 4-bit approximation
-; uint_32 e = png_32bit_exp[(x >> 12) & 0x0f];
-
- ; Incorporate the low 12 bits - these decrease the returned value by
- ; multiplying by a number less than 1 if the bit is set. The multiplier
- ; is determined by the above table and the shift. Notice that the values
- ; converge on 45426 and this is used to allow linear interpolation of the
- ; low bits.
-
-; if (x & 0x800)
-; e -= (((e >> 16) * 44938U) + 16U) >> 5;
-
-; if (x & 0x400)
-; e -= (((e >> 16) * 45181U) + 32U) >> 6;
-
-; if (x & 0x200)
-; e -= (((e >> 16) * 45303U) + 64U) >> 7;
-
-; if (x & 0x100)
-; e -= (((e >> 16) * 45365U) + 128U) >> 8;
-
-; if (x & 0x080)
-; e -= (((e >> 16) * 45395U) + 256U) >> 9;
-
-; if (x & 0x040)
-; e -= (((e >> 16) * 45410U) + 512U) >> 10;
-
- ; And handle the low 6 bits in a single block.
-; e -= (((e >> 16) * 355U * (x & 0x3fU)) + 256U) >> 9;
-
- ; Handle the upper bits of x.
-; e >>= x >> 16;
-; return e;
-; }
-
- ; Check for overflow
-; if (x <= 0)
-; return png_32bit_exp[0];
-
- ; Else underflow
-; return 0;
- ret
-endp
-
-;byte (png_fixed_point lg2)
-align 4
-proc png_exp8bit, lg2:dword
- ; Get a 32-bit value:
-; uint_32 x = png_exp(lg2);
-
- ; Convert the 32-bit value to 0..255 by multiplying by 256-1. Note that the
- ; second, rounding, step can't overflow because of the first, subtraction,
- ; step.
-
-; x -= x >> 8;
-; return (byte)(((x + 0x7fffffU) >> 24) & 0xff);
- ret
-endp
-
-;uint_16 (png_fixed_point lg2)
-align 4
-proc png_exp16bit, lg2:dword
- ; Get a 32-bit value:
-; uint_32 x = png_exp(lg2);
-
- ; Convert the 32-bit value to 0..65535 by multiplying by 65536-1:
-; x -= x >> 16;
-; return (uint_16)((x + 32767U) >> 16);
- ret
-endp
-;end if /* FLOATING_ARITHMETIC */
-
-;byte (uint value, png_fixed_point gamma_val)
-align 4
-proc png_gamma_8bit_correct, value:dword, gamma_val:dword
-; if (value > 0 && value < 255)
-; {
-if PNG_FLOATING_ARITHMETIC_SUPPORTED eq 1
- ; 'value' is unsigned, ANSI-C90 requires the compiler to correctly
- ; convert this to a floating point value. This includes values that
- ; would overflow if 'value' were to be converted to 'int'.
-
- ; Apparently GCC, however, does an intermediate conversion to (int)
- ; on some (ARM) but not all (x86) platforms, possibly because of
- ; hardware FP limitations. (E.g. if the hardware conversion always
- ; assumes the integer register contains a signed value.) This results
- ; in ANSI-C undefined behavior for large values.
-
- ; Other implementations on the same machine might actually be ANSI-C90
- ; conformant and therefore compile spurious extra code for the large
- ; values.
-
- ; We can be reasonably sure that an unsigned to float conversion
- ; won't be faster than an int to float one. Therefore this code
- ; assumes responsibility for the undefined behavior, which it knows
- ; can't happen because of the check above.
-
- ; Note the argument to this routine is an (uint) because, on
- ; 16-bit platforms, it is assigned a value which might be out of
- ; range for an (int); that would result in undefined behavior in the
- ; caller if the *argument* ('value') were to be declared (int).
-
-; double r = floor(255*pow((int)/*SAFE*/value/255.,gamma_val*.00001)+.5);
-; return (byte)r;
-else
-; int_32 lg2 = png_log8bit(value);
-; png_fixed_point res;
-
-; if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1) != 0)
-; return png_exp8bit(res);
-
- ; Overflow.
-; value = 0;
-end if
-; }
-
-; return (byte)(value & 0xff);
- ret
-endp
-
-;uint_16 (uint value, png_fixed_point gamma_val)
-align 4
-proc png_gamma_16bit_correct, value:dword, gamma_val:dword
-; if (value > 0 && value < 65535)
-; {
-if PNG_FLOATING_ARITHMETIC_SUPPORTED eq 1
- ; The same (uint)->(double) constraints apply here as above,
- ; however in this case the (uint) to (int) conversion can
- ; overflow on an ANSI-C90 compliant system so the cast needs to ensure
- ; that this is not possible.
-
-; double r = floor(65535*pow((int_32)value/65535.,
-; gamma_val*.00001)+.5);
-; return (uint_16)r;
-else
-; int_32 lg2 = png_log16bit(value);
-; png_fixed_point res;
-
-; if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1) != 0)
-; return png_exp16bit(res);
-
- ; Overflow.
-; value = 0;
-end if
-; }
-
-; return (uint_16)value;
- ret
-endp
-
-; This does the right thing based on the bit_depth field of the
-; png_struct, interpreting values as 8-bit or 16-bit. While the result
-; is nominally a 16-bit value if bit depth is 8 then the result is
-; 8-bit (as are the arguments.)
-
-;uint_16 (png_structrp png_ptr, uint value, png_fixed_point gamma_val)
-align 4
-proc png_gamma_correct, png_ptr:dword, value:dword, gamma_val:dword
-; if (png_ptr->bit_depth == 8)
-; return png_gamma_8bit_correct(value, gamma_val);
-;
-if PNG_16BIT_SUPPORTED eq 1
-; else
-; return png_gamma_16bit_correct(value, gamma_val);
-else
- ; should not reach this
- xor eax,eax
-end if ;16BIT
-.end_f:
- ret
-endp
-
-;if PNG_16BIT_SUPPORTED
-; Internal function to build a single 16-bit table - the table consists of
-; 'num' 256 entry subtables, where 'num' is determined by 'shift' - the amount
-; to shift the input values right (or 16-number_of_signifiant_bits).
-
-; The caller is responsible for ensuring that the table gets cleaned up on
-; png_error (i.e. if one of the mallocs below fails) - i.e. the *table argument
-; should be somewhere that will be cleaned.
-
-;void (png_structrp png_ptr, uint_16pp *ptable, uint shift, png_fixed_point gamma_val)
-align 4
-proc png_build_16bit_table, png_ptr:dword, ptable:dword, shift:dword, gamma_val:dword
- ; Various values derived from 'shift':
-; uint num = 1U << (8U - shift);
-if PNG_FLOATING_ARITHMETIC_SUPPORTED eq 1
- ; CSE the division and work round wacky GCC warnings (see the comments
- ; in png_gamma_8bit_correct for where these come from.)
-
-; double fmax = 1./(((int_32)1 << (16U - shift))-1);
-end if
-; uint max = (1U << (16U - shift))-1U;
-; uint max_by_2 = 1U << (15U-shift);
-; uint i;
-
-; uint_16pp table = *ptable =
-; (uint_16pp)png_calloc(png_ptr, num * (sizeof (uint_16p)));
-
-; for (i = 0; i < num; i++)
-; {
-; uint_16p sub_table = table[i] =
-; (uint_16p)png_malloc(png_ptr, 256 * (sizeof (uint_16)));
-
- ; The 'threshold' test is repeated here because it can arise for one of
- ; the 16-bit tables even if the others don't hit it.
-
-; if (png_gamma_significant(gamma_val) != 0)
-; {
- ; The old code would overflow at the end and this would cause the
- ; 'pow' function to return a result >1, resulting in an
- ; arithmetic error. This code follows the spec exactly; ig is
- ; the recovered input sample, it always has 8-16 bits.
-
- ; We want input * 65535/max, rounded, the arithmetic fits in 32
- ; bits (unsigned) so long as max <= 32767.
-
-; uint j;
-; for (j = 0; j < 256; j++)
-; {
-; uint_32 ig = (j << (8-shift)) + i;
-if PNG_FLOATING_ARITHMETIC_SUPPORTED eq 1
- ; Inline the 'max' scaling operation:
- ; See png_gamma_8bit_correct for why the cast to (int) is
- ; required here.
-
-; double d = floor(65535.*pow(ig*fmax, gamma_val*.00001)+.5);
-; sub_table[j] = (uint_16)d;
-else
-; if (shift != 0)
-; ig = (ig * 65535U + max_by_2)/max;
-;
-; sub_table[j] = png_gamma_16bit_correct(ig, gamma_val);
-end if
-; }
-; }
-; else
-; {
- ; We must still build a table, but do it the fast way.
-; uint j;
-;
-; for (j = 0; j < 256; j++)
-; {
-; uint_32 ig = (j << (8-shift)) + i;
-;
-; if (shift != 0)
-; ig = (ig * 65535U + max_by_2)/max;
-;
-; sub_table[j] = (uint_16)ig;
-; }
-; }
-; }
- ret
-endp
-
-; NOTE: this function expects the *inverse* of the overall gamma transformation
-; required.
-
-;void (png_structrp png_ptr, uint_16pp *ptable, uint shift, png_fixed_point gamma_val)
-align 4
-proc png_build_16to8_table, png_ptr:dword, ptable:dword, shift:dword, gamma_val:dword
-; uint num = 1U << (8U - shift);
-; uint max = (1U << (16U - shift))-1U;
-; uint i;
-; uint_32 last;
-
-; uint_16pp table = *ptable =
-; (uint_16pp)png_calloc(png_ptr, num * (sizeof (uint_16p)));
-
- ; 'num' is the number of tables and also the number of low bits of low
- ; bits of the input 16-bit value used to select a table. Each table is
- ; itself indexed by the high 8 bits of the value.
-
-; for (i = 0; i < num; i++)
-; table[i] = (uint_16p)png_malloc(png_ptr,
-; 256 * (sizeof (uint_16)));
-
- ; 'gamma_val' is set to the reciprocal of the value calculated above, so
- ; pow(out,g) is an *input* value. 'last' is the last input value set.
- ;
- ; In the loop 'i' is used to find output values. Since the output is
- ; 8-bit there are only 256 possible values. The tables are set up to
- ; select the closest possible output value for each input by finding
- ; the input value at the boundary between each pair of output values
- ; and filling the table up to that boundary with the lower output
- ; value.
-
- ; The boundary values are 0.5,1.5..253.5,254.5. Since these are 9-bit
- ; values the code below uses a 16-bit value in i; the values start at
- ; 128.5 (for 0.5) and step by 257, for a total of 254 values (the last
- ; entries are filled with 255). Start i at 128 and fill all 'last'
- ; table entries <= 'max'
-
-; last = 0;
-; for (i = 0; i < 255; ++i) /* 8-bit output value */
-; {
- ; Find the corresponding maximum input value
-; uint_16 out = (uint_16)(i * 257U); /* 16-bit output value */
-
- ; Find the boundary value in 16 bits:
-; uint_32 bound = png_gamma_16bit_correct(out+128U, gamma_val);
-
- ; Adjust (round) to (16-shift) bits:
-; bound = (bound * max + 32768U)/65535U + 1U;
-;
-; while (last < bound)
-; {
-; table[last & (0xffU >> shift)][last >> (8U - shift)] = out;
-; last++;
-; }
-; }
-
- ; And fill in the final entries.
-; while (last < (num << 8))
-; {
-; table[last & (0xff >> shift)][last >> (8U - shift)] = 65535U;
-; last++;
-; }
- ret
-endp
-;end if /* 16BIT */
-
-; Build a single 8-bit table: same as the 16-bit case but much simpler (and
-; typically much faster). Note that libpng currently does no sBIT processing
-; (apparently contrary to the spec) so a 256-entry table is always generated.
-
-;void (png_structrp png_ptr, bytepp ptable, png_fixed_point gamma_val)
-align 4
-proc png_build_8bit_table, png_ptr:dword, ptable:dword, gamma_val:dword
-; uint i;
-; bytep table = *ptable = (bytep)png_malloc(png_ptr, 256);
-
-; if (png_gamma_significant(gamma_val) != 0)
-; for (i=0; i<256; i++)
-; table[i] = png_gamma_8bit_correct(i, gamma_val);
-
-; else
-; for (i=0; i<256; ++i)
-; table[i] = (byte)(i & 0xff);
- ret
-endp
-
-; Used from png_read_destroy and below to release the memory used by the gamma
-; tables.
-
-;void (png_structrp png_ptr)
-align 4
-proc png_destroy_gamma_table, png_ptr:dword
-; png_free(png_ptr, png_ptr->gamma_table);
-; png_ptr->gamma_table = NULL;
-
-if PNG_16BIT_SUPPORTED eq 1
-; if (png_ptr->gamma_16_table != NULL)
-; {
-; int i;
-; int istop = (1 << (8 - png_ptr->gamma_shift));
-; for (i = 0; i < istop; i++)
-; {
-; png_free(png_ptr, png_ptr->gamma_16_table[i]);
-; }
-; png_free(png_ptr, png_ptr->gamma_16_table);
-; png_ptr->gamma_16_table = NULL;
-; }
-end if ;16BIT
-
-;#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
-; defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
-; defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
-; png_free(png_ptr, png_ptr->gamma_from_1);
-; png_ptr->gamma_from_1 = NULL;
-; png_free(png_ptr, png_ptr->gamma_to_1);
-; png_ptr->gamma_to_1 = NULL;
-
-if PNG_16BIT_SUPPORTED eq 1
-; if (png_ptr->gamma_16_from_1 != NULL)
-; {
-; int i;
-; int istop = (1 << (8 - png_ptr->gamma_shift));
-; for (i = 0; i < istop; i++)
-; {
-; png_free(png_ptr, png_ptr->gamma_16_from_1[i]);
-; }
-; png_free(png_ptr, png_ptr->gamma_16_from_1);
-; png_ptr->gamma_16_from_1 = NULL;
-; }
-; if (png_ptr->gamma_16_to_1 != NULL)
-; {
-; int i;
-; int istop = (1 << (8 - png_ptr->gamma_shift));
-; for (i = 0; i < istop; i++)
-; {
-; png_free(png_ptr, png_ptr->gamma_16_to_1[i]);
-; }
-; png_free(png_ptr, png_ptr->gamma_16_to_1);
-; png_ptr->gamma_16_to_1 = NULL;
-; }
-end if ;16BIT
-;end if /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
- ret
-endp
-
-; We build the 8- or 16-bit gamma tables here. Note that for 16-bit
-; tables, we don't make a full table if we are reducing to 8-bit in
-; the future. Note also how the gamma_16 tables are segmented so that
-; we don't need to allocate > 64K chunks for a full 16-bit table.
-
-;void (png_structrp png_ptr, int bit_depth)
-align 4
-proc png_build_gamma_table, png_ptr:dword, bit_depth:dword
- png_debug 1, 'in png_build_gamma_table'
-
- ; Remove any existing table; this copes with multiple calls to
- ; png_read_update_info. The warning is because building the gamma tables
- ; multiple times is a performance hit - it's harmless but the ability to
- ; call png_read_update_info() multiple times is new in 1.5.6 so it seems
- ; sensible to warn if the app introduces such a hit.
-
-; if (png_ptr->gamma_table != NULL || png_ptr->gamma_16_table != NULL)
-; {
-; png_warning(png_ptr, "gamma table being rebuilt");
-; png_destroy_gamma_table(png_ptr);
-; }
-
-; if (bit_depth <= 8)
-; {
-; png_build_8bit_table(png_ptr, &png_ptr->gamma_table,
-; png_ptr->screen_gamma > 0 ?
-; png_reciprocal2(png_ptr->colorspace.gamma,
-; png_ptr->screen_gamma) : PNG_FP_1);
-;
-if (PNG_READ_BACKGROUND_SUPPORTED eq 1) | (PNG_READ_ALPHA_MODE_SUPPORTED eq 1) | (PNG_READ_RGB_TO_GRAY_SUPPORTED eq 1)
-; if ((png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) != 0)
-; {
-; png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1,
-; png_reciprocal(png_ptr->colorspace.gamma));
-;
-; png_build_8bit_table(png_ptr, &png_ptr->gamma_from_1,
-; png_ptr->screen_gamma > 0 ?
-; png_reciprocal(png_ptr->screen_gamma) :
-; png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */);
-; }
-end if ;READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY
-; }
-if PNG_16BIT_SUPPORTED eq 1
-; else
-; {
-; byte shift, sig_bit;
-;
-; if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
-; {
-; sig_bit = png_ptr->sig_bit.red;
-;
-; if (png_ptr->sig_bit.green > sig_bit)
-; sig_bit = png_ptr->sig_bit.green;
-;
-; if (png_ptr->sig_bit.blue > sig_bit)
-; sig_bit = png_ptr->sig_bit.blue;
-; }
-; else
-; sig_bit = png_ptr->sig_bit.gray;
-
- ; 16-bit gamma code uses this equation:
-
- ; ov = table[(iv & 0xff) >> gamma_shift][iv >> 8]
-
- ; Where 'iv' is the input color value and 'ov' is the output value -
- ; pow(iv, gamma).
-
- ; Thus the gamma table consists of up to 256 256-entry tables. The table
- ; is selected by the (8-gamma_shift) most significant of the low 8 bits
- ; of the color value then indexed by the upper 8 bits:
- ;
- ; table[low bits][high 8 bits]
-
- ; So the table 'n' corresponds to all those 'iv' of:
-
- ; ..<(n+1 << gamma_shift)-1>
-
-
-; if (sig_bit > 0 && sig_bit < 16U)
-; /* shift == insignificant bits */
-; shift = (byte)((16U - sig_bit) & 0xff);
-
-; else
-; shift = 0; /* keep all 16 bits */
-
-; if ((png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) != 0)
-; {
- ; PNG_MAX_GAMMA_8 is the number of bits to keep - effectively
- ; the significant bits in the *input* when the output will
- ; eventually be 8 bits. By default it is 11.
-
-; if (shift < (16U - PNG_MAX_GAMMA_8))
-; shift = (16U - PNG_MAX_GAMMA_8);
-; }
-
-; if (shift > 8U)
-; shift = 8U; /* Guarantees at least one table! */
-
-; png_ptr->gamma_shift = shift;
-
- ; NOTE: prior to 1.5.4 this test used to include PNG_BACKGROUND (now
- ; PNG_COMPOSE). This effectively smashed the background calculation for
- ; 16-bit output because the 8-bit table assumes the result will be
- ; reduced to 8 bits.
-
-; if ((png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) != 0)
-; png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift,
-; png_ptr->screen_gamma > 0 ? png_product2(png_ptr->colorspace.gamma,
-; png_ptr->screen_gamma) : PNG_FP_1);
-;
-; else
-; png_build_16bit_table(png_ptr, &png_ptr->gamma_16_table, shift,
-; png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->colorspace.gamma,
-; png_ptr->screen_gamma) : PNG_FP_1);
-;
-if (PNG_READ_BACKGROUND_SUPPORTED eq 1) | (PNG_READ_ALPHA_MODE_SUPPORTED eq 1) | (PNG_READ_RGB_TO_GRAY_SUPPORTED eq 1)
-; if ((png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) != 0)
-; {
-; png_build_16bit_table(png_ptr, &png_ptr->gamma_16_to_1, shift,
-; png_reciprocal(png_ptr->colorspace.gamma));
-
- ; Notice that the '16 from 1' table should be full precision, however
- ; the lookup on this table still uses gamma_shift, so it can't be.
- ; TODO: fix this.
-
-; png_build_16bit_table(png_ptr, &png_ptr->gamma_16_from_1, shift,
-; png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) :
-; png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */);
-; }
-end if ;READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY
-; }
-end if ;16BIT
- ret
-endp
-;end if /* READ_GAMMA */
-
-; HARDWARE OR SOFTWARE OPTION SUPPORT
-;int (png_structrp png_ptr, int option, int onoff)
-align 4
-proc png_set_option uses ecx, png_ptr:dword, option:dword, onoff:dword
- mov eax,[png_ptr]
- cmp eax,0
- je @f
- mov ecx,[option]
- cmp ecx,0
- jl @f
- cmp ecx,PNG_OPTION_NEXT
- jge @f
- bt ecx,0 ;cmp (ecx & 1), 0
- jc @f ;if (..!=0 && ..>=0 && ..<.. && ..==0)
-; int mask = 3 << option;
-; int setting = (2 + (onoff != 0)) << option;
-; int current = png_ptr->options;
-
-; png_ptr->options = (byte)(((current & ~mask) | setting) & 0xff);
-
-; return (current & mask) >> option;
- jmp .end_f
- @@:
- mov eax,PNG_OPTION_INVALID
-.end_f:
- ret
-endp
-
-; sRGB support
-if (PNG_SIMPLIFIED_READ_SUPPORTED eq 1) | (PNG_SIMPLIFIED_WRITE_SUPPORTED eq 1)
-; sRGB conversion tables; these are machine generated with the code in
-; contrib/tools/makesRGB.c. The actual sRGB transfer curve defined in the
-; specification (see the article at http://en.wikipedia.org/wiki/SRGB)
-; is used, not the gamma=1/2.2 approximation use elsewhere in libpng.
-; The sRGB to linear table is exact (to the nearest 16-bit linear fraction).
-; The inverse (linear to sRGB) table has accuracies as follows:
-
-; For all possible (255*65535+1) input values:
-; error: -0.515566 - 0.625971, 79441 (0.475369%) of readings inexact
-
-; For the input values corresponding to the 65536 16-bit values:
-; error: -0.513727 - 0.607759, 308 (0.469978%) of readings inexact
-
-; In all cases the inexact readings are only off by one.
-
-
-if PNG_SIMPLIFIED_READ_SUPPORTED eq 1
-; The convert-to-sRGB table is only currently required for read.
-align 4
-png_sRGB_table dw 0,20,40,60,80,99,119,139,\
- 159,179,199,219,241,264,288,313,\
- 340,367,396,427,458,491,526,562,\
- 599,637,677,718,761,805,851,898,\
- 947,997,1048,1101,1156,1212,1270,1330,\
- 1391,1453,1517,1583,1651,1720,1790,1863,\
- 1937,2013,2090,2170,2250,2333,2418,2504,\
- 2592,2681,2773,2866,2961,3058,3157,3258,\
- 3360,3464,3570,3678,3788,3900,4014,4129,\
- 4247,4366,4488,4611,4736,4864,4993,5124,\
- 5257,5392,5530,5669,5810,5953,6099,6246,\
- 6395,6547,6700,6856,7014,7174,7335,7500,\
- 7666,7834,8004,8177,8352,8528,8708,8889,\
- 9072,9258,9445,9635,9828,10022,10219,10417,\
- 10619,10822,11028,11235,11446,11658,11873,12090,\
- 12309,12530,12754,12980,13209,13440,13673,13909,\
- 14146,14387,14629,14874,15122,15371,15623,15878,\
- 16135,16394,16656,16920,17187,17456,17727,18001,\
- 18277,18556,18837,19121,19407,19696,19987,20281,\
- 20577,20876,21177,21481,21787,22096,22407,22721,\
- 23038,23357,23678,24002,24329,24658,24990,25325,\
- 25662,26001,26344,26688,27036,27386,27739,28094,\
- 28452,28813,29176,29542,29911,30282,30656,31033,\
- 31412,31794,32179,32567,32957,33350,33745,34143,\
- 34544,34948,35355,35764,36176,36591,37008,37429,\
- 37852,38278,38706,39138,39572,40009,40449,40891,\
- 41337,41785,42236,42690,43147,43606,44069,44534,\
- 45002,45473,45947,46423,46903,47385,47871,48359,\
- 48850,49344,49841,50341,50844,51349,51858,52369,\
- 52884,53401,53921,54445,54971,55500,56032,56567,\
- 57105,57646,58190,58737,59287,59840,60396,60955,\
- 61517,62082,62650,63221,63795,64372,64952,65535
-end if ;SIMPLIFIED_READ
-
-; The base/delta tables are required for both read and write (but currently
-; only the simplified versions.)
-align 4
-png_sRGB_base dw 128,1782,3383,4644,5675,6564,7357,8074,\
- 8732,9346,9921,10463,10977,11466,11935,12384,\
- 12816,13233,13634,14024,14402,14769,15125,15473,\
- 15812,16142,16466,16781,17090,17393,17690,17981,\
- 18266,18546,18822,19093,19359,19621,19879,20133,\
- 20383,20630,20873,21113,21349,21583,21813,22041,\
- 22265,22487,22707,22923,23138,23350,23559,23767,\
- 23972,24175,24376,24575,24772,24967,25160,25352,\
- 25542,25730,25916,26101,26284,26465,26645,26823,\
- 27000,27176,27350,27523,27695,27865,28034,28201,\
- 28368,28533,28697,28860,29021,29182,29341,29500,\
- 29657,29813,29969,30123,30276,30429,30580,30730,\
- 30880,31028,31176,31323,31469,31614,31758,31902,\
- 32045,32186,32327,32468,32607,32746,32884,33021,\
- 33158,33294,33429,33564,33697,33831,33963,34095,\
- 34226,34357,34486,34616,34744,34873,35000,35127,\
- 35253,35379,35504,35629,35753,35876,35999,36122,\
- 36244,36365,36486,36606,36726,36845,36964,37083,\
- 37201,37318,37435,37551,37668,37783,37898,38013,\
- 38127,38241,38354,38467,38580,38692,38803,38915,\
- 39026,39136,39246,39356,39465,39574,39682,39790,\
- 39898,40005,40112,40219,40325,40431,40537,40642,\
- 40747,40851,40955,41059,41163,41266,41369,41471,\
- 41573,41675,41777,41878,41979,42079,42179,42279,\
- 42379,42478,42577,42676,42775,42873,42971,43068,\
- 43165,43262,43359,43456,43552,43648,43743,43839,\
- 43934,44028,44123,44217,44311,44405,44499,44592,\
- 44685,44778,44870,44962,45054,45146,45238,45329,\
- 45420,45511,45601,45692,45782,45872,45961,46051,\
- 46140,46229,46318,46406,46494,46583,46670,46758,\
- 46846,46933,47020,47107,47193,47280,47366,47452,\
- 47538,47623,47709,47794,47879,47964,48048,48133,\
- 48217,48301,48385,48468,48552,48635,48718,48801,\
- 48884,48966,49048,49131,49213,49294,49376,49458,\
- 49539,49620,49701,49782,49862,49943,50023,50103,\
- 50183,50263,50342,50422,50501,50580,50659,50738,\
- 50816,50895,50973,51051,51129,51207,51285,51362,\
- 51439,51517,51594,51671,51747,51824,51900,51977,\
- 52053,52129,52205,52280,52356,52432,52507,52582,\
- 52657,52732,52807,52881,52956,53030,53104,53178,\
- 53252,53326,53400,53473,53546,53620,53693,53766,\
- 53839,53911,53984,54056,54129,54201,54273,54345,\
- 54417,54489,54560,54632,54703,54774,54845,54916,\
- 54987,55058,55129,55199,55269,55340,55410,55480,\
- 55550,55620,55689,55759,55828,55898,55967,56036,\
- 56105,56174,56243,56311,56380,56448,56517,56585,\
- 56653,56721,56789,56857,56924,56992,57059,57127,\
- 57194,57261,57328,57395,57462,57529,57595,57662,\
- 57728,57795,57861,57927,57993,58059,58125,58191,\
- 58256,58322,58387,58453,58518,58583,58648,58713,\
- 58778,58843,58908,58972,59037,59101,59165,59230,\
- 59294,59358,59422,59486,59549,59613,59677,59740,\
- 59804,59867,59930,59993,60056,60119,60182,60245,\
- 60308,60370,60433,60495,60558,60620,60682,60744,\
- 60806,60868,60930,60992,61054,61115,61177,61238,\
- 61300,61361,61422,61483,61544,61605,61666,61727,\
- 61788,61848,61909,61969,62030,62090,62150,62211,\
- 62271,62331,62391,62450,62510,62570,62630,62689,\
- 62749,62808,62867,62927,62986,63045,63104,63163,\
- 63222,63281,63340,63398,63457,63515,63574,63632,\
- 63691,63749,63807,63865,63923,63981,64039,64097,\
- 64155,64212,64270,64328,64385,64443,64500,64557,\
- 64614,64672,64729,64786,64843,64900,64956,65013,\
- 65070,65126,65183,65239,65296,65352,65409,65465
-align 4
-png_sRGB_delta db 207,201,158,129,113,100,90,82,77,72,68,64,61,59,56,54,\
- 52,50,49,47,46,45,43,42,41,40,39,39,38,37,36,36,\
- 35,34,34,33,33,32,32,31,31,30,30,30,29,29,28,28,\
- 28,27,27,27,27,26,26,26,25,25,25,25,24,24,24,24,\
- 23,23,23,23,23,22,22,22,22,22,22,21,21,21,21,21,\
- 21,20,20,20,20,20,20,20,20,19,19,19,19,19,19,19,\
- 19,18,18,18,18,18,18,18,18,18,18,17,17,17,17,17,\
- 17,17,17,17,17,17,16,16,16,16,16,16,16,16,16,16,\
- 16,16,16,16,15,15,15,15,15,15,15,15,15,15,15,15,\
- 15,15,15,15,14,14,14,14,14,14,14,14,14,14,14,14,\
- 14,14,14,14,14,14,14,13,13,13,13,13,13,13,13,13,\
- 13,13,13,13,13,13,13,13,13,13,13,13,13,13,12,12,\
- 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,\
- 12,12,12,12,12,12,12,12,12,12,12,12,11,11,11,11,\
- 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,\
- 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,\
- 11,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,\
- 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,\
- 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,\
- 10,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,\
- 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,\
- 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,\
- 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,\
- 9,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,\
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,\
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,\
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,\
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,\
- 8,8,8,8,8,8,8,8,8,7,7,7,7,7,7,7,\
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
-
-end if ;SIMPLIFIED READ/WRITE sRGB support
-
-; SIMPLIFIED READ/WRITE SUPPORT
-;int (voidp argument)
-align 4
-proc png_image_free_function uses ebx ecx edi esi, argument:dword
-locals
-; png_imagep image = argument;
-; png_controlp cp = image->opaque;
- c png_control
-endl
- ; Double check that we have a png_ptr - it should be impossible to get here
- ; without one.
-
- mov ebx,[argument]
- mov esi,[ebx+png_image.opaque] ;esi = cp
- cmp dword[esi+png_control.png_ptr],0
- jne @f ;if (..==0)
- xor eax,eax
- jmp .end_f
- @@:
-
- ; First free any data held in the control structure.
-if PNG_STDIO_SUPPORTED eq 1
-; if (cp->owned_file != 0)
-; {
-; FILE *fp = cp->png_ptr->io_ptr;
-; cp->owned_file = 0;
-
- ; Ignore errors here.
-; if (fp != NULL)
-; {
-; cp->png_ptr->io_ptr = NULL;
-; (void)fclose(fp);
-; }
-; }
-end if
-
- ; Copy the control structure so that the original, allocated, version can be
- ; safely freed. Notice that a png_error here stops the remainder of the
- ; cleanup, but this is probably fine because that would indicate bad memory
- ; problems anyway.
-
- mov ecx,sizeof.png_control
- mov edi,ebp
- sub edi,ecx ;edi = &c
- rep movsb
- sub edi,sizeof.png_control
- sub esi,sizeof.png_control
- mov dword[ebx+png_image.opaque],edi
- stdcall png_free, [edi+png_control.png_ptr], esi
-
- ; Then the structures, calling the correct API.
-; if (c.for_write != 0)
-; {
-if PNG_SIMPLIFIED_WRITE_SUPPORTED eq 1
-; png_destroy_write_struct(&c.png_ptr, &c.info_ptr);
-else
-; png_error(c.png_ptr, "simplified write not supported");
-end if
- jmp .end2
- .end1: ;else
-if PNG_SIMPLIFIED_READ_SUPPORTED eq 1
-; png_destroy_read_struct(&c.png_ptr, &c.info_ptr, NULL);
-else
-; png_error(c.png_ptr, "simplified read not supported");
-end if
- .end2:
-
- ; Success.
- xor eax,eax
- inc eax
-.end_f:
- ret
-endp
-
-;void (png_imagep image)
-align 4
-proc png_image_free uses eax ebx, image:dword
- ; Safely call the real function, but only if doing so is safe at this point
- ; (if not inside an error handling context). Otherwise assume
- ; png_safe_execute will call this API after the return.
-
- mov ebx,[image]
- cmp ebx,0
- je @f
- cmp dword[ebx+png_image.opaque],0
- je @f
- mov eax,[ebx+png_image.opaque]
- cmp dword[eax+png_control.error_buf],0
- jne @f ;if (..!=0 && ..!=0 && ..==0)
- ; Ignore errors here:
- stdcall png_safe_execute, ebx, png_image_free_function, ebx
- mov dword[ebx+png_image.opaque],0
- @@:
- ret
-endp
-
-;int (png_imagep image, charp error_message)
-align 4
-proc png_image_error uses ebx, image:dword, error_message:dword
- ; Utility to log an error.
- mov ebx,[image]
- mov eax,ebx
- add eax,png_image.message
- stdcall png_safecat, eax, sizeof.png_image.message, 0, [error_message]
- or dword[ebx+png_image.warning_or_error], PNG_IMAGE_ERROR
- stdcall png_image_free, ebx
- xor eax,eax
- ret
-endp
-
-;end if /* READ || WRITE */
+
+; png.asm - location for general purpose libpng functions
+
+; Last changed in libpng 1.6.25 [September 1, 2016]
+; Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
+; (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+; (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+
+; This code is released under the libpng license.
+; For conditions of distribution and use, see the disclaimer
+; and license in png.inc
+
+DEBUG equ 0
+
+include '../../../../../../KOSfuncs.inc'
+include '../../../../../../fs/kfar/trunk/zlib/deflate.inc'
+include 'pngtokos.inc' ;integrate png to kos
+
+;files from libpng
+include 'pnglibconf.inc'
+include 'pngpriv.inc'
+include 'png.inc'
+include 'pngstruct.inc'
+include 'pnginfo.inc'
+include 'pngerror.asm'
+include 'pngtrans.asm'
+include 'pngget.asm'
+include 'pngwrite.asm'
+include 'pngmem.asm'
+include 'pngset.asm'
+include 'pngwutil.asm'
+include 'pngwio.asm'
+include 'pngwtran.asm'
+
+; Generate a compiler error if there is an old png.inc in the search path.
+;typedef png_libpng_version_1_6_25 Your_png_h_is_not_version_1_6_25;
+
+; Tells libpng that we have already handled the first "num_bytes" bytes
+; of the PNG file signature. If the PNG data is embedded into another
+; stream we can set num_bytes = 8 so that libpng will not attempt to read
+; or write any of the magic bytes before it starts on the IHDR.
+
+
+;if PNG_READ_SUPPORTED
+;void (png_structrp png_ptr, int num_bytes)
+align 4
+proc png_set_sig_bytes uses eax edi, png_ptr:dword, num_bytes:dword
+ png_debug 1, 'in png_set_sig_bytes'
+
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f ;if (..==0) return
+
+ mov eax,[num_bytes]
+ cmp eax,0
+ jge @f
+ xor eax,eax
+ @@:
+ cmp eax,8
+ jle @f ;if (..>8)
+ png_error edi, 'Too many bytes for PNG signature'
+ @@:
+ mov byte[edi+png_struct.sig_bytes],al
+.end_f:
+ ret
+endp
+
+; Checks whether the supplied bytes match the PNG signature. We allow
+; checking less than the full 8-byte signature so that those apps that
+; already read the first few bytes of a file to determine the file type
+; can simply check the remaining bytes for extra assurance. Returns
+; an integer less than, equal to, or greater than zero if sig is found,
+; respectively, to be less than, to match, or be greater than the correct
+; PNG signature (this is the same behavior as strcmp, memcmp, etc).
+
+;int (bytep sig, png_size_t start, png_size_t num_to_check)
+align 4
+proc png_sig_cmp, sig:dword, start:dword, num_to_check:dword
+; byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
+
+; if (num_to_check > 8)
+; num_to_check = 8;
+
+; else if (num_to_check < 1)
+; return (-1);
+
+; if (start > 7)
+; return (-1);
+
+; if (start + num_to_check > 8)
+; num_to_check = 8 - start;
+
+; return ((int)(memcmp(&sig[start], &png_signature[start], num_to_check)));
+ ret
+endp
+
+;end if /* READ */
+
+; Function to allocate memory for zlib
+;voidpf (voidpf png_ptr, uInt items, uInt size)
+align 4
+proc png_zalloc uses edx ecx, png_ptr:dword, items:dword, size:dword
+
+ cmp dword[png_ptr],0
+ jne @f
+ xor eax,eax
+ jmp .end_f ;if (..==0) return 0
+ @@:
+
+ xor eax,eax
+ not eax
+ xor edx,edx
+ mov ecx,[size]
+ div ecx
+ cmp [items],eax
+ jl @f ;if (..>=..)
+ png_warning [png_ptr], 'Potential overflow in png_zalloc()'
+ xor eax,eax
+ jmp .end_f
+ @@:
+
+ mov ecx,[size]
+ imul ecx,[items]
+ stdcall png_malloc_warn, [png_ptr], ecx
+.end_f:
+ ret
+endp
+
+; Function to free memory for zlib
+;void (voidpf png_ptr, voidpf ptr)
+align 4
+proc png_zfree, png_ptr:dword, p2ptr:dword
+ stdcall png_free, [png_ptr], [p2ptr]
+ ret
+endp
+
+; Reset the CRC variable to 32 bits of 1's. Care must be taken
+; in case CRC is > 32 bits to leave the top bits 0.
+
+;void (png_structrp png_ptr)
+align 4
+proc png_reset_crc uses eax edi, png_ptr:dword
+ ; The cast is safe because the crc is a 32-bit value.
+ mov edi,[png_ptr]
+ stdcall [calc_crc32], 0, Z_NULL, 0
+ mov dword[edi+png_struct.crc],eax
+ ret
+endp
+
+; Calculate the CRC over a section of data. We can only pass as
+; much data to this routine as the largest single buffer size. We
+; also check that this data will actually be used before going to the
+; trouble of calculating it.
+
+;void (png_structrp png_ptr, bytep ptr, png_size_t length)
+align 4
+proc png_calculate_crc uses eax ebx edi, png_ptr:dword, ptr:dword, length:dword
+locals
+ need_crc dd 1
+ safe_length dd ?
+endl
+ mov edi,[png_ptr]
+ PNG_CHUNK_ANCILLARY [edi+png_struct.chunk_name]
+ cmp eax,0 ;if (..!=0)
+ je @f
+ mov eax,[edi+png_struct.flags]
+ and eax,PNG_FLAG_CRC_ANCILLARY_MASK
+ cmp eax,PNG_FLAG_CRC_ANCILLARY_USE or PNG_FLAG_CRC_ANCILLARY_NOWARN
+ jne .end0 ;if (..==..)
+ mov dword[need_crc],0
+ jmp .end0
+ @@: ;else ;critical
+ mov eax,[edi+png_struct.flags]
+ and eax,PNG_FLAG_CRC_CRITICAL_IGNORE
+ jz .end0 ;if (..!=0)
+ mov dword[need_crc],0
+ .end0:
+
+ ; 'uLong' is defined in zlib.inc as unsigned long; this means that on some
+ ; systems it is a 64-bit value. crc32, however, returns 32 bits so the
+ ; following cast is safe. 'uInt' may be no more than 16 bits, so it is
+ ; necessary to perform a loop here.
+
+ cmp dword[need_crc],0
+ je .end_f
+ cmp dword[length],0
+ jle .end_f ;if (..!=0 && ..>0)
+ mov eax,[edi+png_struct.crc] ;Should never issue a warning
+
+ .cycle0: ;do
+ mov ebx,[length]
+ mov [safe_length],ebx
+;#ifndef __COVERITY__
+; if (safe_length == 0)
+; safe_length = (uInt)-1 ;evil, but safe
+;end if
+ stdcall [calc_crc32], eax, [ptr], [safe_length]
+
+ ; The following should never issue compiler warnings; if they do the
+ ; target system has characteristics that will probably violate other
+ ; assumptions within the libpng code.
+
+ mov ebx,[safe_length]
+ add [ptr],ebx
+ sub [length],ebx
+ cmp dword[length],0
+ jg .cycle0 ;while (..>0)
+
+ ; And the following is always safe because the crc is only 32 bits.
+ mov [edi+png_struct.crc],eax
+ .end_f:
+ ret
+endp
+
+; Check a user supplied version number, called from both read and write
+; functions that create a png_struct.
+
+;int (png_structrp png_ptr, charp user_png_ver)
+align 4
+proc png_user_version_check, png_ptr:dword, user_png_ver:dword
+ ; Libpng versions 1.0.0 and later are binary compatible if the version
+ ; string matches through the second '.'; we must recompile any
+ ; applications that use any older library version.
+
+; if (user_png_ver != NULL)
+; {
+; int i = -1;
+; int found_dots = 0;
+
+; do
+; {
+; i++;
+; if (user_png_ver[i] != PNG_LIBPNG_VER_STRING[i])
+; png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
+; if (user_png_ver[i] == '.')
+; found_dots++;
+; } while (found_dots < 2 && user_png_ver[i] != 0 &&
+; PNG_LIBPNG_VER_STRING[i] != 0);
+; }
+
+; else
+; png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
+
+; if ((png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) != 0)
+; {
+if PNG_WARNINGS_SUPPORTED eq 1
+; size_t pos = 0;
+; char m[128];
+
+; pos = png_safecat(m, (sizeof m), pos,
+; "Application built with libpng-");
+; pos = png_safecat(m, (sizeof m), pos, user_png_ver);
+; pos = png_safecat(m, (sizeof m), pos, " but running with ");
+; pos = png_safecat(m, (sizeof m), pos, PNG_LIBPNG_VER_STRING);
+
+; png_warning(png_ptr, m);
+end if
+
+if PNG_ERROR_NUMBERS_SUPPORTED eq 1
+; png_ptr->flags = 0;
+end if
+
+; return 0;
+; }
+
+ ; Success return.
+ xor eax,eax
+ inc eax
+.end_f:
+ ret
+endp
+
+; Generic function to create a png_struct for either read or write - this
+; contains the common initialization.
+
+;png_structp (charp user_png_ver, voidp error_ptr,
+; png_error_ptr error_fn, png_error_ptr warn_fn, voidp mem_ptr,
+; png_malloc_ptr malloc_fn, png_free_ptr free_fn)
+align 4
+proc png_create_png_struct uses ebx ecx edi esi, user_png_ver:dword, error_ptr:dword, error_fn:dword, warn_fn:dword, mem_ptr:dword, malloc_fn:dword, free_fn:dword
+locals
+if PNG_SETJMP_SUPPORTED eq 1
+ create_jmp_buf dd ? ;jmp_buf
+end if
+ create_struct png_struct
+endl
+ ; This temporary stack-allocated structure is used to provide a place to
+ ; build enough context to allow the user provided memory allocator (if any)
+ ; to be called.
+
+ xor eax,eax
+ mov ecx,sizeof.png_struct
+ mov edi,ebp
+ sub edi,ecx
+ mov ebx,edi
+ rep stosb
+
+ ; Added at libpng-1.2.6
+if PNG_USER_LIMITS_SUPPORTED eq 1
+ mov dword[ebx+png_struct.user_width_max], PNG_USER_WIDTH_MAX
+ mov dword[ebx+png_struct.user_height_max], PNG_USER_HEIGHT_MAX
+
+ ; Added at libpng-1.2.43 and 1.4.0
+ mov dword[ebx+png_struct.user_chunk_cache_max], PNG_USER_CHUNK_CACHE_MAX
+
+ ; Added at libpng-1.2.43 and 1.4.1, required only for read but exists
+ ; in png_struct regardless.
+
+ mov dword[ebx+png_struct.user_chunk_malloc_max], PNG_USER_CHUNK_MALLOC_MAX
+end if
+
+ ; The following two API calls simply set fields in png_struct, so it is safe
+ ; to do them now even though error handling is not yet set up.
+
+if PNG_USER_MEM_SUPPORTED eq 1
+ stdcall png_set_mem_fn, ebx, [mem_ptr], [malloc_fn], [free_fn]
+end if
+
+ ; (*error_fn) can return control to the caller after the error_ptr is set,
+ ; this will result in a memory leak unless the error_fn does something
+ ; extremely sophisticated. The design lacks merit but is implicit in the
+ ; API.
+
+ stdcall png_set_error_fn, ebx, [error_ptr], [error_fn], [warn_fn]
+
+if PNG_SETJMP_SUPPORTED eq 1
+ stdcall setjmp,... ;create_jmp_buf
+ cmp eax,0
+ j... .end0 ;if (!setjmp(create_jmp_buf))
+
+ ; Temporarily fake out the longjmp information until we have
+ ; successfully completed this function. This only works if we have
+ ; setjmp() support compiled in, but it is safe - this stuff should
+ ; never happen.
+
+; create_struct.jmp_buf_ptr = &create_jmp_buf;
+ mov dword[ebx+png_struct.jmp_buf_size],0 ;stack allocation
+; create_struct.longjmp_fn = longjmp;
+end if
+ ; Call the general version checker (shared with read and write code):
+
+ stdcall png_user_version_check, ebx, [user_png_ver]
+ cmp eax,0
+ je .end0 ;if (..!=0)
+ stdcall png_malloc_warn, ebx, sizeof.png_struct
+ ;eax = png_ptr
+ cmp eax,0
+ je .end0 ;if (..!=0)
+ ; png_ptr->zstream holds a back-pointer to the png_struct, so
+ ; this can only be done now:
+
+ mov [ebx+png_struct.zstream.zalloc], png_zalloc
+ mov [ebx+png_struct.zstream.zfree], png_zfree
+ mov [ebx+png_struct.zstream.opaque], eax
+
+if PNG_SETJMP_SUPPORTED eq 1
+ ; Eliminate the local error handling:
+ mov [ebx+png_struct.jmp_buf_ptr], 0
+ mov [ebx+png_struct.jmp_buf_size], 0
+ mov [ebx+png_struct.longjmp_fn], 0
+end if
+ mov ecx,sizeof.png_struct
+ mov edi,eax
+ mov esi,ebx
+ rep movsb ;*png_ptr = create_struct
+
+ ; This is the successful return point
+ jmp .end_f
+ .end0:
+
+ ; A longjmp because of a bug in the application storage allocator or a
+ ; simple failure to allocate the png_struct.
+
+ xor eax,eax
+.end_f:
+ ret
+endp
+
+; Allocate the memory for an info_struct for the application.
+;png_infop (png_structrp png_ptr)
+align 4
+proc png_create_info_struct uses ebx ecx edi, png_ptr:dword
+ png_debug 1, 'in png_create_info_struct'
+ ;ebx - info_ptr dd ? ;png_inforp
+
+ mov edi,[png_ptr]
+ cmp edi,0
+ jne @f ;if (..==0) return 0
+ xor eax,eax
+ jmp .end_f
+ @@:
+
+ ; Use the internal API that does not (or at least should not) error out, so
+ ; that this call always returns ok. The application typically sets up the
+ ; error handling *after* creating the info_struct because this is the way it
+ ; has always been done in 'example.asm'.
+
+ stdcall png_malloc_base, edi, sizeof.png_info_def
+ mov ebx,eax
+
+ cmp eax,0
+ je @f
+ mov edi,eax
+ xor eax,eax
+ mov ecx,sizeof.png_info_def
+ rep stosb ;memset(...
+ @@:
+
+ mov eax,ebx
+.end_f:
+ ret
+endp
+
+; This function frees the memory associated with a single info struct.
+; Normally, one would use either png_destroy_read_struct() or
+; png_destroy_write_struct() to free an info struct, but this may be
+; useful for some applications. From libpng 1.6.0 this function is also used
+; internally to implement the png_info release part of the 'struct' destroy
+; APIs. This ensures that all possible approaches free the same data (all of
+; it).
+
+;void (png_structrp png_ptr, png_infopp info_ptr_ptr)
+align 4
+proc png_destroy_info_struct uses eax ebx ecx edi, png_ptr:dword, info_ptr_ptr:dword
+ png_debug 1, 'in png_destroy_info_struct'
+
+ cmp dword[png_ptr],0
+ je .end_f ;if (..==0) return
+
+ mov edi,[info_ptr_ptr]
+ cmp edi,0 ;if (..!=0)
+ je .end_f
+ ; Do this first in case of an error below; if the app implements its own
+ ; memory management this can lead to png_free calling png_error, which
+ ; will abort this routine and return control to the app error handler.
+ ; An infinite loop may result if it then tries to free the same info
+ ; ptr.
+
+ mov dword[edi],0
+
+ stdcall png_free_data, [png_ptr], edi, PNG_FREE_ALL, -1
+ mov ebx,edi
+ xor eax,eax
+ mov ecx,sizeof.png_info_def
+ rep stosb
+ stdcall png_free, [png_ptr], ebx
+ .end_f:
+ ret
+endp
+
+; Initialize the info structure. This is now an internal function (0.89)
+; and applications using it are urged to use png_create_info_struct()
+; instead. Use deprecated in 1.6.0, internal use removed (used internally it
+; is just a memset).
+
+; NOTE: it is almost inconceivable that this API is used because it bypasses
+; the user-memory mechanism and the user error handling/warning mechanisms in
+; those cases where it does anything other than a memset.
+
+;void (png_infopp ptr_ptr, png_size_t png_info_struct_size)
+align 4
+proc png_info_init_3, ptr_ptr:dword, png_info_struct_size:dword
+; png_inforp info_ptr = *ptr_ptr;
+
+ png_debug 1, 'in png_info_init_3'
+
+; if (info_ptr == NULL)
+; return;
+
+; if ((sizeof (png_info)) > png_info_struct_size)
+; {
+; *ptr_ptr = NULL;
+ ; The following line is why this API should not be used:
+; free(info_ptr);
+; info_ptr = png_malloc_base(NULL, (sizeof *info_ptr));
+; if (info_ptr == NULL)
+; return;
+; *ptr_ptr = info_ptr;
+; }
+
+ ; Set everything to 0
+; memset(info_ptr, 0, (sizeof *info_ptr));
+ ret
+endp
+
+; The following API is not called internally
+;void (png_structrp png_ptr, png_inforp info_ptr, int freer, uint_32 mask)
+align 4
+proc png_data_freer uses edi esi, png_ptr:dword, info_ptr:dword, freer:dword, mask:dword
+ png_debug 1, 'in png_data_freer'
+
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f
+ mov esi,[info_ptr]
+ cmp esi,0
+ je .end_f ;if (..==0 || ..==0) return
+
+; if (freer == PNG_DESTROY_WILL_FREE_DATA)
+; info_ptr->free_me |= mask;
+
+; else if (freer == PNG_USER_WILL_FREE_DATA)
+; info_ptr->free_me &= ~mask;
+
+; else
+; png_error(png_ptr, "Unknown freer parameter in png_data_freer");
+.end_f
+ ret
+endp
+
+;void (png_structrp png_ptr, png_inforp info_ptr, uint_32 mask, int num)
+align 4
+proc png_free_data uses eax edi esi, png_ptr:dword, info_ptr:dword, mask:dword, num:dword
+ png_debug 1, 'in png_free_data'
+
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f
+ mov esi,[info_ptr]
+ cmp esi,0
+ je .end_f ;if (..==0 || ..==0) return
+
+if PNG_TEXT_SUPPORTED eq 1
+ ; Free text item num or (if num == -1) all text items
+; if (info_ptr->text != 0 &&
+; ((mask & PNG_FREE_TEXT) & info_ptr->free_me) != 0)
+; {
+; if (num != -1)
+; {
+; png_free(png_ptr, info_ptr->text[num].key);
+; info_ptr->text[num].key = NULL;
+; }
+
+; else
+; {
+; int i;
+
+; for (i = 0; i < info_ptr->num_text; i++)
+; png_free(png_ptr, info_ptr->text[i].key);
+
+; png_free(png_ptr, info_ptr->text);
+; info_ptr->text = NULL;
+; info_ptr->num_text = 0;
+; }
+; }
+end if
+
+if PNG_tRNS_SUPPORTED eq 1
+ ; Free any tRNS entry
+ mov eax,[mask]
+ and eax,PNG_FREE_TRNS
+ and eax,[esi+png_info_def.free_me]
+ jz @f ;if (..!=0)
+ and dword[esi+png_info_def.valid], not PNG_INFO_tRNS
+ stdcall png_free, edi, [esi+png_info_def.trans_alpha]
+ mov dword[esi+png_info_def.trans_alpha],0
+ mov word[esi+png_info_def.num_trans],0
+ @@:
+end if
+
+if PNG_sCAL_SUPPORTED eq 1
+ ; Free any sCAL entry
+ mov eax,[mask]
+ and eax,PNG_FREE_SCAL
+ and eax,[esi+png_info_def.free_me]
+ jz @f ;if (..!=0)
+ stdcall png_free, edi, [esi+png_info_def.scal_s_width]
+ stdcall png_free, edi, [esi+png_info_def.scal_s_height]
+ mov dword[esi+png_info_def.scal_s_width],0
+ mov dword[esi+png_info_def.scal_s_height],0
+ and dword[esi+png_info_def.valid], not PNG_INFO_sCAL
+ @@:
+end if
+
+if PNG_pCAL_SUPPORTED eq 1
+ ; Free any pCAL entry
+; if (((mask & PNG_FREE_PCAL) & info_ptr->free_me) != 0)
+; {
+; png_free(png_ptr, info_ptr->pcal_purpose);
+; png_free(png_ptr, info_ptr->pcal_units);
+; info_ptr->pcal_purpose = NULL;
+; info_ptr->pcal_units = NULL;
+
+; if (info_ptr->pcal_params != NULL)
+; {
+; int i;
+
+; for (i = 0; i < info_ptr->pcal_nparams; i++)
+; png_free(png_ptr, info_ptr->pcal_params[i]);
+;
+; png_free(png_ptr, info_ptr->pcal_params);
+; info_ptr->pcal_params = NULL;
+; }
+; info_ptr->valid &= ~PNG_INFO_pCAL;
+; }
+end if
+
+if PNG_iCCP_SUPPORTED eq 1
+ ; Free any profile entry
+ mov eax,[mask]
+ and eax,PNG_FREE_ICCP
+ and eax,[esi+png_info_def.free_me]
+ jz @f ;if (..!=0)
+ stdcall png_free, edi, [esi+png_info_def.iccp_name]
+ stdcall png_free, edi, [esi+png_info_def.iccp_profile]
+ mov dword[esi+png_info_def.iccp_name],0
+ mov dword[esi+png_info_def.iccp_profile],0
+ and dword[esi+png_info_def.valid], not PNG_INFO_iCCP
+ @@:
+end if
+
+if PNG_sPLT_SUPPORTED eq 1
+ ; Free a given sPLT entry, or (if num == -1) all sPLT entries
+; if (info_ptr->splt_palettes != 0 &&
+; ((mask & PNG_FREE_SPLT) & info_ptr->free_me) != 0)
+; {
+; if (num != -1)
+; {
+; png_free(png_ptr, info_ptr->splt_palettes[num].name);
+; png_free(png_ptr, info_ptr->splt_palettes[num].entries);
+; info_ptr->splt_palettes[num].name = NULL;
+; info_ptr->splt_palettes[num].entries = NULL;
+; }
+
+; else
+; {
+; int i;
+
+; for (i = 0; i < info_ptr->splt_palettes_num; i++)
+; {
+; png_free(png_ptr, info_ptr->splt_palettes[i].name);
+; png_free(png_ptr, info_ptr->splt_palettes[i].entries);
+; }
+
+; png_free(png_ptr, info_ptr->splt_palettes);
+; info_ptr->splt_palettes = NULL;
+; info_ptr->splt_palettes_num = 0;
+; info_ptr->valid &= ~PNG_INFO_sPLT;
+; }
+; }
+end if
+
+if PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED eq 1
+; if (info_ptr->unknown_chunks != 0 &&
+; ((mask & PNG_FREE_UNKN) & info_ptr->free_me) != 0)
+; {
+; if (num != -1)
+; {
+; png_free(png_ptr, info_ptr->unknown_chunks[num].data);
+; info_ptr->unknown_chunks[num].data = NULL;
+; }
+
+; else
+; {
+; int i;
+
+; for (i = 0; i < info_ptr->unknown_chunks_num; i++)
+; png_free(png_ptr, info_ptr->unknown_chunks[i].data);
+
+; png_free(png_ptr, info_ptr->unknown_chunks);
+; info_ptr->unknown_chunks = NULL;
+; info_ptr->unknown_chunks_num = 0;
+; }
+; }
+end if
+
+if PNG_hIST_SUPPORTED eq 1
+ ; Free any hIST entry
+ mov eax,[mask]
+ and eax,PNG_FREE_HIST
+ and eax,[esi+png_info_def.free_me]
+ jz @f ;if (..!=0)
+ stdcall png_free, edi, [esi+png_info_def.hist]
+ mov dword[esi+png_info_def.hist],0
+ and dword[esi+png_info_def.valid], not PNG_INFO_hIST
+ @@:
+end if
+
+ ; Free any PLTE entry that was internally allocated
+ mov eax,[mask]
+ and eax,PNG_FREE_PLTE
+ and eax,[esi+png_info_def.free_me]
+ jz @f ;if (..!=0)
+ stdcall png_free, edi, [esi+png_info_def.palette]
+ mov dword[esi+png_info_def.palette],0
+ and dword[esi+png_info_def.valid],not PNG_INFO_PLTE
+ mov dword[esi+png_info_def.num_palette],0
+ @@:
+
+if PNG_INFO_IMAGE_SUPPORTED eq 1
+ ; Free any image bits attached to the info structure
+; if (((mask & PNG_FREE_ROWS) & info_ptr->free_me) != 0)
+; {
+; if (info_ptr->row_pointers != 0)
+; {
+; uint_32 row;
+; for (row = 0; row < info_ptr->height; row++)
+; png_free(png_ptr, info_ptr->row_pointers[row]);
+
+; png_free(png_ptr, info_ptr->row_pointers);
+; info_ptr->row_pointers = NULL;
+; }
+; info_ptr->valid &= ~PNG_INFO_IDAT;
+; }
+end if
+
+; if (num != -1)
+; mask &= ~PNG_FREE_MUL;
+
+ mov eax,[mask]
+ not eax
+ and [esi+png_info_def.free_me],eax
+.end_f:
+ ret
+endp
+
+; This function returns a pointer to the io_ptr associated with the user
+; functions. The application should free any memory associated with this
+; pointer before png_write_destroy() or png_read_destroy() are called.
+
+;voidp (png_structrp png_ptr)
+align 4
+proc png_get_io_ptr, png_ptr:dword
+ mov eax,[png_ptr]
+ cmp eax,0
+ je @f ;if (..==0) return 0
+ mov eax,[eax+png_struct.io_ptr]
+ @@:
+ ret
+endp
+
+;#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
+; Initialize the default input/output functions for the PNG file. If you
+; use your own read or write routines, you can call either png_set_read_fn()
+; or png_set_write_fn() instead of png_init_io(). If you have defined
+; PNG_NO_STDIO or otherwise disabled PNG_STDIO_SUPPORTED, you must use a
+; function of your own because "FILE *" isn't necessarily available.
+
+;void (png_structrp png_ptr, png_FILE_p fp)
+align 4
+proc png_init_io uses eax edi, png_ptr:dword, fp:dword
+ png_debug 1, 'in png_init_io'
+
+ mov edi,[png_ptr]
+ cmp edi,0
+ je @f ;if (..==0) return
+ mov eax,[fp]
+ mov [edi+png_struct.io_ptr],eax
+ @@:
+ ret
+endp
+
+; PNG signed integers are saved in 32-bit 2's complement format. ANSI C-90
+; defines a cast of a signed integer to an unsigned integer either to preserve
+; the value, if it is positive, or to calculate:
+
+; (UNSIGNED_MAX+1) + integer
+
+; Where UNSIGNED_MAX is the appropriate maximum unsigned value, so when the
+; negative integral value is added the result will be an unsigned value
+; correspnding to the 2's complement representation.
+
+;void (bytep buf, int_32 i)
+align 4
+proc png_save_int_32, buf:dword, i:dword
+ stdcall png_save_uint_32, [buf], [i]
+ ret
+endp
+
+;# ifdef PNG_TIME_RFC1123_SUPPORTED
+; Convert the supplied time into an RFC 1123 string suitable for use in
+; a "Creation Time" or other text-based time string.
+
+;int (char out[29], const_timep ptime)
+align 4
+short_months db 'Jan',0, 'Feb',0, 'Mar',0, 'Apr',0, 'May',0, 'Jun',0,\
+ 'Jul',0, 'Aug',0, 'Sep',0, 'Oct',0, 'Nov',0, 'Dec',0
+
+align 4
+proc png_convert_to_rfc1123_buffer, out_29:dword, ptime:dword
+ cmp dword[out_29],0
+ jne @f
+ xor eax,eax
+ jmp .end_f ;if (..==0) return 0
+ @@:
+
+; if (ptime->year > 9999 /* RFC1123 limitation */ ||
+; ptime->month == 0 || ptime->month > 12 ||
+; ptime->day == 0 || ptime->day > 31 ||
+; ptime->hour > 23 || ptime->minute > 59 ||
+; ptime->second > 60)
+; return 0;
+
+; {
+; size_t pos = 0;
+; char number_buf[5]; /* enough for a four-digit year */
+
+;# define APPEND_STRING(string) pos = png_safecat(out_29, 29, pos, (string))
+;# define APPEND_NUMBER(format, value)\
+; APPEND_STRING(PNG_FORMAT_NUMBER(number_buf, format, (value)))
+;# define APPEND(ch) if (pos < 28) out_29[pos++] = (ch)
+
+; APPEND_NUMBER(PNG_NUMBER_FORMAT_u, (unsigned)ptime->day);
+; APPEND(' ');
+; APPEND_STRING(short_months[(ptime->month - 1)]);
+; APPEND(' ');
+; APPEND_NUMBER(PNG_NUMBER_FORMAT_u, ptime->year);
+; APPEND(' ');
+; APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->hour);
+; APPEND(':');
+; APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->minute);
+; APPEND(':');
+; APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->second);
+; APPEND_STRING(" +0000"); /* This reliably terminates the buffer */
+
+;# undef APPEND
+;# undef APPEND_NUMBER
+;# undef APPEND_STRING
+; }
+
+ xor eax,eax
+ inc eax
+.end_f:
+ ret
+endp
+
+;# if PNG_LIBPNG_VER < 10700
+; To do: remove the following from libpng-1.7
+; Original API that uses a private buffer in png_struct.
+; Deprecated because it causes png_struct to carry a spurious temporary
+; buffer (png_struct::time_buffer), better to have the caller pass this in.
+
+;charp (png_structrp png_ptr, const_timep ptime)
+align 4
+proc png_convert_to_rfc1123, png_ptr:dword, ptime:dword
+; if (png_ptr != NULL)
+; {
+ ; The only failure above if png_ptr != NULL is from an invalid ptime
+; if (png_convert_to_rfc1123_buffer(png_ptr->time_buffer, ptime) == 0)
+; png_warning(png_ptr, "Ignoring invalid time value");
+
+; else
+; return png_ptr->time_buffer;
+; }
+
+; return NULL;
+ ret
+endp
+;# endif /* LIBPNG_VER < 10700 */
+;# endif /* TIME_RFC1123 */
+
+;end if /* READ || WRITE */
+
+;charp (png_structrp png_ptr)
+align 4
+proc png_get_copyright, png_ptr:dword
+jmp .end_0
+@@: db 'libpng version 1.6.25 - September 1, 2016',13,10,\
+ ' Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson',13,10,\
+ ' Copyright (c) 1996-1997 Andreas Dilger',13,10,\
+ ' Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.',0
+.end_0:
+ mov eax,@b
+ ret
+endp
+
+; The following return the library version as a short string in the
+; format 1.0.0 through 99.99.99zz. To get the version of *.inc files
+; used with your application, print out PNG_LIBPNG_VER_STRING, which
+; is defined in png.inc.
+; Note: now there is no difference between png_get_libpng_ver() and
+; png_get_header_ver(). Due to the version_nn_nn_nn typedef guard,
+; it is guaranteed that png.asm uses the correct version of png.inc.
+
+;charp (png_structrp png_ptr)
+align 4
+proc png_get_libpng_ver, png_ptr:dword
+ ; Version of *.asm files used when building libpng
+; return png_get_header_ver(png_ptr);
+ ret
+endp
+
+;charp (png_structrp png_ptr)
+align 4
+proc png_get_header_ver, png_ptr:dword
+ ; Version of *.inc files used when building libpng
+; return PNG_LIBPNG_VER_STRING;
+ ret
+endp
+
+;charp (png_structrp png_ptr)
+align 4
+proc png_get_header_version, png_ptr:dword
+ ; Returns longer string containing both version and date
+;if __STDC__
+; return PNG_HEADER_VERSION_STRING
+;# ifndef PNG_READ_SUPPORTED
+; " (NO READ SUPPORT)"
+;# endif
+; PNG_STRING_NEWLINE;
+;#else
+; return PNG_HEADER_VERSION_STRING;
+;end if
+ ret
+endp
+
+; NOTE: this routine is not used internally!
+; Build a grayscale palette. Palette is assumed to be 1 << bit_depth
+; large of png_color. This lets grayscale images be treated as
+; paletted. Most useful for gamma correction and simplification
+; of code. This API is not used internally.
+
+;void (int bit_depth, png_colorp palette)
+align 4
+proc png_build_grayscale_palette, bit_depth:dword, palette:dword
+; int num_palette;
+; int color_inc;
+; int i;
+; int v;
+
+ png_debug 1, 'in png_do_build_grayscale_palette'
+
+; if (palette == NULL)
+; return;
+
+; switch (bit_depth)
+; {
+; case 1:
+; num_palette = 2;
+; color_inc = 0xff;
+; break;
+;
+; case 2:
+; num_palette = 4;
+; color_inc = 0x55;
+; break;
+;
+; case 4:
+; num_palette = 16;
+; color_inc = 0x11;
+; break;
+;
+; case 8:
+; num_palette = 256;
+; color_inc = 1;
+; break;
+;
+; default:
+; num_palette = 0;
+; color_inc = 0;
+; break;
+; }
+;
+; for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
+; {
+; palette[i].red = (byte)(v & 0xff);
+; palette[i].green = (byte)(v & 0xff);
+; palette[i].blue = (byte)(v & 0xff);
+; }
+ ret
+endp
+
+;int (png_structrp png_ptr, bytep chunk_name)
+align 4
+proc png_handle_as_unknown uses ecx edi esi, png_ptr:dword, chunk_name:dword
+ ; Check chunk_name and return "keep" value if it's on the list, else 0
+; bytep p, p_end;
+
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end0
+ cmp dword[chunk_name],0
+ je .end0
+ cmp dword[edi+png_struct.num_chunk_list],0
+ je .end0
+ jmp @f
+ .end0: ;if (..==0 || ..==0 || ..==0)
+ mov eax,PNG_HANDLE_CHUNK_AS_DEFAULT
+ jmp .end_f
+ @@:
+
+; p_end = png_ptr->chunk_list;
+; p = p_end + png_ptr->num_chunk_list*5; /* beyond end */
+
+ ; The code is the fifth byte after each four byte string. Historically this
+ ; code was always searched from the end of the list, this is no longer
+ ; necessary because the 'set' routine handles duplicate entries correcty.
+
+; do /* num_chunk_list > 0, so at least one */
+; {
+; p -= 5;
+
+; if (memcmp(chunk_name, p, 4) == 0)
+; return p[4];
+; }
+; while (p > p_end);
+
+ ; This means that known chunks should be processed and unknown chunks should
+ ; be handled according to the value of png_ptr->unknown_default; this can be
+ ; confusing because, as a result, there are two levels of defaulting for
+ ; unknown chunks.
+
+ mov eax,PNG_HANDLE_CHUNK_AS_DEFAULT
+.end_f:
+ ret
+endp
+
+;int (png_structrp png_ptr, uint_32 chunk_name)
+align 4
+proc png_chunk_unknown_handling, png_ptr:dword, chunk_name:dword
+; byte chunk_string[5];
+
+; PNG_CSTRING_FROM_CHUNK(chunk_string, chunk_name);
+; return png_handle_as_unknown(png_ptr, chunk_string);
+ ret
+endp
+
+; This function, added to libpng-1.0.6g, is untested.
+;int (png_structrp png_ptr)
+align 4
+proc png_reset_zstream, png_ptr:dword
+ mov eax,[png_ptr]
+ cmp eax,0
+ jne @f ;if (..==0)
+ mov eax,Z_STREAM_ERROR
+ jmp .end_f
+ @@:
+ ; WARNING: this resets the window bits to the maximum!
+ add eax,png_struct.zstream
+ stdcall inflateReset,eax
+.end_f:
+ ret
+endp
+
+; This function was added to libpng-1.0.7
+;uint_32 png_access_version_number(void)
+align 4
+png_access_version_number:
+ ; Version of *.asm files used when building libpng
+ mov eax,PNG_LIBPNG_VER
+ ret
+
+;#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
+; Ensure that png_ptr->zstream.msg holds some appropriate error message string.
+; If it doesn't 'ret' is used to set it to something appropriate, even in cases
+; like Z_OK or Z_STREAM_END where the error code is apparently a success code.
+
+;void (png_structrp png_ptr, int ret)
+align 4
+proc png_zstream_error uses eax edi, png_ptr:dword, p2ret:dword
+ ; Translate 'p2ret' into an appropriate error string, priority is given to the
+ ; one in zstream if set. This always returns a string, even in cases like
+ ; Z_OK or Z_STREAM_END where the error code is a success code.
+
+ mov edi,[png_ptr]
+ cmp dword[edi+png_struct.zstream.msg],0
+ jne .end_f ;if (..==0) switch (p2ret)
+ mov eax,[p2ret]
+; default:
+ cmp eax,Z_OK
+ jne @f
+ cStr dword[edi+png_struct.zstream.msg],'unexpected zlib return code'
+ jmp .end_f
+ @@:
+ cmp eax,Z_STREAM_END
+ jne @f
+ ; Normal exit
+ cStr dword[edi+png_struct.zstream.msg],'unexpected end of LZ stream'
+ jmp .end_f
+ @@:
+ cmp eax,Z_NEED_DICT
+ jne @f
+ ; This means the deflate stream did not have a dictionary; this
+ ; indicates a bogus PNG.
+
+ cStr dword[edi+png_struct.zstream.msg],'missing LZ dictionary'
+ jmp .end_f
+ @@:
+ cmp eax,Z_ERRNO
+ jne @f
+ ; gz APIs only: should not happen
+ cStr dword[edi+png_struct.zstream.msg],'zlib IO error'
+ jmp .end_f
+ @@:
+ cmp eax,Z_STREAM_ERROR
+ jne @f
+ ; internal libpng error
+ cStr dword[edi+png_struct.zstream.msg],'bad parameters to zlib'
+ jmp .end_f
+ @@:
+ cmp eax,Z_DATA_ERROR
+ jne @f
+ cStr dword[edi+png_struct.zstream.msg],'damaged LZ stream'
+ jmp .end_f
+ @@:
+ cmp eax,Z_MEM_ERROR
+ jne @f
+ cStr dword[edi+png_struct.zstream.msg],'insufficient memory'
+ jmp .end_f
+ @@:
+ cmp eax,Z_BUF_ERROR
+ jne @f
+ ; End of input or output; not a problem if the caller is doing
+ ; incremental read or write.
+
+ cStr dword[edi+png_struct.zstream.msg],'truncated'
+ jmp .end_f
+ @@:
+ cmp eax,Z_VERSION_ERROR
+ jne @f
+ cStr dword[edi+png_struct.zstream.msg],'unsupported zlib version'
+ jmp .end_f
+ @@:
+ cmp eax,PNG_UNEXPECTED_ZLIB_RETURN
+ jne .end_f
+ ; Compile errors here mean that zlib now uses the value co-opted in
+ ; pngpriv.inc for PNG_UNEXPECTED_ZLIB_RETURN; update the switch above
+ ; and change pngpriv.inc. Note that this message is "... return",
+ ; whereas the default/Z_OK one is "... return code".
+
+ cStr dword[edi+png_struct.zstream.msg],'unexpected zlib return'
+; break;
+.end_f:
+ ret
+endp
+
+; png_convert_size: a PNGAPI but no longer in png.inc, so deleted
+; at libpng 1.5.5!
+
+
+; Added at libpng version 1.2.34 and 1.4.0 (moved from pngset.asm)
+;if PNG_GAMMA_SUPPORTED /* always set if COLORSPACE */
+;int (png_structrp png_ptr,
+; png_colorspacerp colorspace, png_fixed_point gAMA, int from)
+ ; This is called to check a new gamma value against an existing one. The
+ ; routine returns false if the new gamma value should not be written.
+ ;
+ ; 'from' says where the new gamma value comes from:
+ ;
+ ; 0: the new gamma value is the libpng estimate for an ICC profile
+ ; 1: the new gamma value comes from a gAMA chunk
+ ; 2: the new gamma value comes from an sRGB chunk
+
+align 4
+proc png_colorspace_check_gamma, png_ptr:dword, colorspace:dword, gAMA:dword, from:dword
+; png_fixed_point gtest;
+;
+; if ((colorspace->flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 &&
+; (png_muldiv(>est, colorspace->gamma, PNG_FP_1, gAMA) == 0 ||
+; png_gamma_significant(gtest) != 0))
+; {
+ ; Either this is an sRGB image, in which case the calculated gamma
+ ; approximation should match, or this is an image with a profile and the
+ ; value libpng calculates for the gamma of the profile does not match the
+ ; value recorded in the file. The former, sRGB, case is an error, the
+ ; latter is just a warning.
+
+; if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0 || from == 2)
+; {
+; png_chunk_report(png_ptr, "gamma value does not match sRGB",
+; PNG_CHUNK_ERROR);
+; /* Do not overwrite an sRGB value */
+; return from == 2;
+; }
+
+; else /* sRGB tag not involved */
+; {
+; png_chunk_report(png_ptr, "gamma value does not match libpng estimate",
+; PNG_CHUNK_WARNING);
+; return from == 1;
+; }
+; }
+
+; return 1;
+ ret
+endp
+
+;void (png_structrp png_ptr, png_colorspacerp colorspace, png_fixed_point gAMA)
+align 4
+proc png_colorspace_set_gamma, png_ptr:dword, colorspace:dword, gAMA:dword
+ ; Changed in libpng-1.5.4 to limit the values to ensure overflow can't
+ ; occur. Since the fixed point representation is asymetrical it is
+ ; possible for 1/gamma to overflow the limit of 21474 and this means the
+ ; gamma value must be at least 5/100000 and hence at most 20000.0. For
+ ; safety the limits here are a little narrower. The values are 0.00016 to
+ ; 6250.0, which are truly ridiculous gamma values (and will produce
+ ; displays that are all black or all white.)
+
+ ; In 1.6.0 this test replaces the ones in pngrutil.c, in the gAMA chunk
+ ; handling code, which only required the value to be >0.
+
+; charp errmsg;
+
+; if (gAMA < 16 || gAMA > 625000000)
+; errmsg = "gamma value out of range";
+
+;# ifdef PNG_READ_gAMA_SUPPORTED
+ ; Allow the application to set the gamma value more than once
+; else if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
+; (colorspace->flags & PNG_COLORSPACE_FROM_gAMA) != 0)
+; errmsg = "duplicate";
+;# endif
+
+ ; Do nothing if the colorspace is already invalid
+; else if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
+; return;
+
+; else
+; {
+; if (png_colorspace_check_gamma(png_ptr, colorspace, gAMA,
+; 1/*from gAMA*/) != 0)
+; {
+; /* Store this gamma value. */
+; colorspace->gamma = gAMA;
+; colorspace->flags |=
+; (PNG_COLORSPACE_HAVE_GAMMA | PNG_COLORSPACE_FROM_gAMA);
+; }
+
+ ; At present if the check_gamma test fails the gamma of the colorspace is
+ ; not updated however the colorspace is not invalidated. This
+ ; corresponds to the case where the existing gamma comes from an sRGB
+ ; chunk or profile. An error message has already been output.
+
+; return;
+; }
+
+ ; Error exit - errmsg has been set.
+; colorspace->flags |= PNG_COLORSPACE_INVALID;
+; png_chunk_report(png_ptr, errmsg, PNG_CHUNK_WRITE_ERROR);
+.end_f:
+ ret
+endp
+
+;void (png_structrp png_ptr, png_inforp info_ptr)
+align 4
+proc png_colorspace_sync_info uses eax esi, png_ptr:dword, info_ptr:dword
+ mov esi,[info_ptr]
+ mov ax,[esi+png_info_def.colorspace.flags]
+ and ax,PNG_COLORSPACE_INVALID
+ cmp ax,0
+ je @f ;if (..!=0)
+ ; Everything is invalid
+ and dword[esi+png_info_def.valid], not (PNG_INFO_gAMA or PNG_INFO_cHRM or PNG_INFO_sRGB or PNG_INFO_iCCP)
+
+if PNG_COLORSPACE_SUPPORTED eq 1
+ ; Clean up the iCCP profile now if it won't be used.
+ stdcall png_free_data, [png_ptr], esi, PNG_FREE_ICCP, -1 ;not used
+end if
+ jmp .end0
+ @@: ;else
+if PNG_COLORSPACE_SUPPORTED eq 1
+ ; Leave the INFO_iCCP flag set if the pngset.c code has already set
+ ; it; this allows a PNG to contain a profile which matches sRGB and
+ ; yet still have that profile retrievable by the application.
+
+ mov ax,[esi+png_info_def.colorspace.flags]
+ and ax,PNG_COLORSPACE_MATCHES_sRGB
+ cmp ax,0
+ je @f ;if (..!=0)
+ or dword[esi+png_info_def.valid], PNG_INFO_sRGB
+ jmp .end1
+ @@: ;else
+ and dword[esi+png_info_def.valid], not PNG_INFO_sRGB
+ .end1:
+ mov ax,[esi+png_info_def.colorspace.flags]
+ and ax,PNG_COLORSPACE_HAVE_ENDPOINTS
+ cmp ax,0
+ je @f ;if (..!=0)
+ or dword[esi+png_info_def.valid], PNG_INFO_cHRM
+ jmp .end2
+ @@: ;else
+ and dword[esi+png_info_def.valid], not PNG_INFO_cHRM
+ .end2:
+end if
+
+ mov ax,[esi+png_info_def.colorspace.flags]
+ and ax,PNG_COLORSPACE_HAVE_GAMMA
+ cmp ax,0
+ je @f ;if (..!=0)
+ or dword[esi+png_info_def.valid], PNG_INFO_gAMA
+ jmp .end0
+ @@: ;else
+ and dword[esi+png_info_def.valid], not PNG_INFO_gAMA
+ .end0:
+ ret
+endp
+
+;void (png_structrp png_ptr, png_inforp info_ptr)
+align 4
+proc png_colorspace_sync uses ecx edi esi, png_ptr:dword, info_ptr:dword
+ mov edi,[info_ptr]
+ cmp edi,0
+ je @f ;if (..==0) ;reduce code size; check here not in the caller
+ mov ecx,sizeof.png_colorspace
+ mov esi,[png_ptr]
+ add esi,png_struct.colorspace
+ add edi,png_info_def.colorspace
+ rep movsb
+ stdcall png_colorspace_sync_info, [png_ptr], [info_ptr]
+ @@:
+ ret
+endp
+
+;end if /* GAMMA */
+
+;if PNG_COLORSPACE_SUPPORTED
+; Added at libpng-1.5.5 to support read and write of true CIEXYZ values for
+; cHRM, as opposed to using chromaticities. These internal APIs return
+; non-zero on a parameter error. The X, Y and Z values are required to be
+; positive and less than 1.0.
+
+;int (png_xy *xy, const png_XYZ *XYZ)
+align 4
+proc png_xy_from_XYZ, xy:dword, XYZ:dword
+; int_32 d, dwhite, whiteX, whiteY;
+
+; d = XYZ->red_X + XYZ->red_Y + XYZ->red_Z;
+; if (png_muldiv(&xy->redx, XYZ->red_X, PNG_FP_1, d) == 0)
+; return 1;
+; if (png_muldiv(&xy->redy, XYZ->red_Y, PNG_FP_1, d) == 0)
+; return 1;
+; dwhite = d;
+; whiteX = XYZ->red_X;
+; whiteY = XYZ->red_Y;
+
+; d = XYZ->green_X + XYZ->green_Y + XYZ->green_Z;
+; if (png_muldiv(&xy->greenx, XYZ->green_X, PNG_FP_1, d) == 0)
+; return 1;
+; if (png_muldiv(&xy->greeny, XYZ->green_Y, PNG_FP_1, d) == 0)
+; return 1;
+; dwhite += d;
+; whiteX += XYZ->green_X;
+; whiteY += XYZ->green_Y;
+
+; d = XYZ->blue_X + XYZ->blue_Y + XYZ->blue_Z;
+; if (png_muldiv(&xy->bluex, XYZ->blue_X, PNG_FP_1, d) == 0)
+; return 1;
+; if (png_muldiv(&xy->bluey, XYZ->blue_Y, PNG_FP_1, d) == 0)
+; return 1;
+; dwhite += d;
+; whiteX += XYZ->blue_X;
+; whiteY += XYZ->blue_Y;
+
+ ; The reference white is simply the sum of the end-point (X,Y,Z) vectors,
+ ; thus:
+
+; if (png_muldiv(&xy->whitex, whiteX, PNG_FP_1, dwhite) == 0)
+; return 1;
+; if (png_muldiv(&xy->whitey, whiteY, PNG_FP_1, dwhite) == 0)
+; return 1;
+
+; return 0;
+ ret
+endp
+
+;int (png_XYZ *XYZ, const png_xy *xy)
+align 4
+proc png_XYZ_from_xy, XYZ:dword, xy:dword
+; png_fixed_point red_inverse, green_inverse, blue_scale;
+; png_fixed_point left, right, denominator;
+
+ ; Check xy and, implicitly, z. Note that wide gamut color spaces typically
+ ; have end points with 0 tristimulus values (these are impossible end
+ ; points, but they are used to cover the possible colors). We check
+ ; xy->whitey against 5, not 0, to avoid a possible integer overflow.
+
+; if (xy->redx < 0 || xy->redx > PNG_FP_1) return 1;
+; if (xy->redy < 0 || xy->redy > PNG_FP_1-xy->redx) return 1;
+; if (xy->greenx < 0 || xy->greenx > PNG_FP_1) return 1;
+; if (xy->greeny < 0 || xy->greeny > PNG_FP_1-xy->greenx) return 1;
+; if (xy->bluex < 0 || xy->bluex > PNG_FP_1) return 1;
+; if (xy->bluey < 0 || xy->bluey > PNG_FP_1-xy->bluex) return 1;
+; if (xy->whitex < 0 || xy->whitex > PNG_FP_1) return 1;
+; if (xy->whitey < 5 || xy->whitey > PNG_FP_1-xy->whitex) return 1;
+
+ ; The reverse calculation is more difficult because the original tristimulus
+ ; value had 9 independent values (red,green,blue)x(X,Y,Z) however only 8
+ ; derived values were recorded in the cHRM chunk;
+ ; (red,green,blue,white)x(x,y). This loses one degree of freedom and
+ ; therefore an arbitrary ninth value has to be introduced to undo the
+ ; original transformations.
+
+ ; Think of the original end-points as points in (X,Y,Z) space. The
+ ; chromaticity values (c) have the property:
+
+ ; C
+ ; c = ---------
+ ; X + Y + Z
+
+ ; For each c (x,y,z) from the corresponding original C (X,Y,Z). Thus the
+ ; three chromaticity values (x,y,z) for each end-point obey the
+ ; relationship:
+
+ ; x + y + z = 1
+
+ ; This describes the plane in (X,Y,Z) space that intersects each axis at the
+ ; value 1.0; call this the chromaticity plane. Thus the chromaticity
+ ; calculation has scaled each end-point so that it is on the x+y+z=1 plane
+ ; and chromaticity is the intersection of the vector from the origin to the
+ ; (X,Y,Z) value with the chromaticity plane.
+
+ ; To fully invert the chromaticity calculation we would need the three
+ ; end-point scale factors, (red-scale, green-scale, blue-scale), but these
+ ; were not recorded. Instead we calculated the reference white (X,Y,Z) and
+ ; recorded the chromaticity of this. The reference white (X,Y,Z) would have
+ ; given all three of the scale factors since:
+
+ ; color-C = color-c * color-scale
+ ; white-C = red-C + green-C + blue-C
+ ; = red-c*red-scale + green-c*green-scale + blue-c*blue-scale
+
+ ; But cHRM records only white-x and white-y, so we have lost the white scale
+ ; factor:
+
+ ; white-C = white-c*white-scale
+
+ ; To handle this the inverse transformation makes an arbitrary assumption
+ ; about white-scale:
+
+ ; Assume: white-Y = 1.0
+ ; Hence: white-scale = 1/white-y
+ ; Or: red-Y + green-Y + blue-Y = 1.0
+
+ ; Notice the last statement of the assumption gives an equation in three of
+ ; the nine values we want to calculate. 8 more equations come from the
+ ; above routine as summarised at the top above (the chromaticity
+ ; calculation):
+
+ ; Given: color-x = color-X / (color-X + color-Y + color-Z)
+ ; Hence: (color-x - 1)*color-X + color.x*color-Y + color.x*color-Z = 0
+
+ ; This is 9 simultaneous equations in the 9 variables "color-C" and can be
+ ; solved by Cramer's rule. Cramer's rule requires calculating 10 9x9 matrix
+ ; determinants, however this is not as bad as it seems because only 28 of
+ ; the total of 90 terms in the various matrices are non-zero. Nevertheless
+ ; Cramer's rule is notoriously numerically unstable because the determinant
+ ; calculation involves the difference of large, but similar, numbers. It is
+ ; difficult to be sure that the calculation is stable for real world values
+ ; and it is certain that it becomes unstable where the end points are close
+ ; together.
+
+ ; So this code uses the perhaps slightly less optimal but more
+ ; understandable and totally obvious approach of calculating color-scale.
+
+ ; This algorithm depends on the precision in white-scale and that is
+ ; (1/white-y), so we can immediately see that as white-y approaches 0 the
+ ; accuracy inherent in the cHRM chunk drops off substantially.
+
+ ; libpng arithmetic: a simple inversion of the above equations
+ ; ------------------------------------------------------------
+
+ ; white_scale = 1/white-y
+ ; white-X = white-x * white-scale
+ ; white-Y = 1.0
+ ; white-Z = (1 - white-x - white-y) * white_scale
+
+ ; white-C = red-C + green-C + blue-C
+ ; = red-c*red-scale + green-c*green-scale + blue-c*blue-scale
+
+ ; This gives us three equations in (red-scale,green-scale,blue-scale) where
+ ; all the coefficients are now known:
+
+ ; red-x*red-scale + green-x*green-scale + blue-x*blue-scale
+ ; = white-x/white-y
+ ; red-y*red-scale + green-y*green-scale + blue-y*blue-scale = 1
+ ; red-z*red-scale + green-z*green-scale + blue-z*blue-scale
+ ; = (1 - white-x - white-y)/white-y
+
+ ; In the last equation color-z is (1 - color-x - color-y) so we can add all
+ ; three equations together to get an alternative third:
+
+ ; red-scale + green-scale + blue-scale = 1/white-y = white-scale
+
+ ; So now we have a Cramer's rule solution where the determinants are just
+ ; 3x3 - far more tractible. Unfortunately 3x3 determinants still involve
+ ; multiplication of three coefficients so we can't guarantee to avoid
+ ; overflow in the libpng fixed point representation. Using Cramer's rule in
+ ; floating point is probably a good choice here, but it's not an option for
+ ; fixed point. Instead proceed to simplify the first two equations by
+ ; eliminating what is likely to be the largest value, blue-scale:
+
+ ; blue-scale = white-scale - red-scale - green-scale
+
+ ; Hence:
+
+ ; (red-x - blue-x)*red-scale + (green-x - blue-x)*green-scale =
+ ; (white-x - blue-x)*white-scale
+
+ ; (red-y - blue-y)*red-scale + (green-y - blue-y)*green-scale =
+ ; 1 - blue-y*white-scale
+
+ ; And now we can trivially solve for (red-scale,green-scale):
+
+ ; green-scale =
+ ; (white-x - blue-x)*white-scale - (red-x - blue-x)*red-scale
+ ; -----------------------------------------------------------
+ ; green-x - blue-x
+
+ ; red-scale =
+ ; 1 - blue-y*white-scale - (green-y - blue-y) * green-scale
+ ; ---------------------------------------------------------
+ ; red-y - blue-y
+
+ ; Hence:
+
+ ; red-scale =
+ ; ( (green-x - blue-x) * (white-y - blue-y) -
+ ; (green-y - blue-y) * (white-x - blue-x) ) / white-y
+ ; -------------------------------------------------------------------------
+ ; (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x)
+
+ ; green-scale =
+ ; ( (red-y - blue-y) * (white-x - blue-x) -
+ ; (red-x - blue-x) * (white-y - blue-y) ) / white-y
+ ; -------------------------------------------------------------------------
+ ; (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x)
+
+ ; Accuracy:
+ ; The input values have 5 decimal digits of accuracy. The values are all in
+ ; the range 0 < value < 1, so simple products are in the same range but may
+ ; need up to 10 decimal digits to preserve the original precision and avoid
+ ; underflow. Because we are using a 32-bit signed representation we cannot
+ ; match this; the best is a little over 9 decimal digits, less than 10.
+
+ ; The approach used here is to preserve the maximum precision within the
+ ; signed representation. Because the red-scale calculation above uses the
+ ; difference between two products of values that must be in the range -1..+1
+ ; it is sufficient to divide the product by 7; ceil(100,000/32767*2). The
+ ; factor is irrelevant in the calculation because it is applied to both
+ ; numerator and denominator.
+
+ ; Note that the values of the differences of the products of the
+ ; chromaticities in the above equations tend to be small, for example for
+ ; the sRGB chromaticities they are:
+
+ ; red numerator: -0.04751
+ ; green numerator: -0.08788
+ ; denominator: -0.2241 (without white-y multiplication)
+
+ ; The resultant Y coefficients from the chromaticities of some widely used
+ ; color space definitions are (to 15 decimal places):
+
+ ; sRGB
+ ; 0.212639005871510 0.715168678767756 0.072192315360734
+ ; Kodak ProPhoto
+ ; 0.288071128229293 0.711843217810102 0.000085653960605
+ ; Adobe RGB
+ ; 0.297344975250536 0.627363566255466 0.075291458493998
+ ; Adobe Wide Gamut RGB
+ ; 0.258728243040113 0.724682314948566 0.016589442011321
+
+ ; By the argument, above overflow should be impossible here. The return
+ ; value of 2 indicates an internal error to the caller.
+
+; if (png_muldiv(&left, xy->greenx-xy->bluex, xy->redy - xy->bluey, 7) == 0)
+; return 2;
+; if (png_muldiv(&right, xy->greeny-xy->bluey, xy->redx - xy->bluex, 7) == 0)
+; return 2;
+; denominator = left - right;
+
+ ; Now find the red numerator.
+; if (png_muldiv(&left, xy->greenx-xy->bluex, xy->whitey-xy->bluey, 7) == 0)
+; return 2;
+; if (png_muldiv(&right, xy->greeny-xy->bluey, xy->whitex-xy->bluex, 7) == 0)
+; return 2;
+
+ ; Overflow is possible here and it indicates an extreme set of PNG cHRM
+ ; chunk values. This calculation actually returns the reciprocal of the
+ ; scale value because this allows us to delay the multiplication of white-y
+ ; into the denominator, which tends to produce a small number.
+
+; if (png_muldiv(&red_inverse, xy->whitey, denominator, left-right) == 0 ||
+; red_inverse <= xy->whitey /* r+g+b scales = white scale */)
+; return 1;
+
+ ; Similarly for green_inverse:
+; if (png_muldiv(&left, xy->redy-xy->bluey, xy->whitex-xy->bluex, 7) == 0)
+; return 2;
+; if (png_muldiv(&right, xy->redx-xy->bluex, xy->whitey-xy->bluey, 7) == 0)
+; return 2;
+; if (png_muldiv(&green_inverse, xy->whitey, denominator, left-right) == 0 ||
+; green_inverse <= xy->whitey)
+; return 1;
+
+ ; And the blue scale, the checks above guarantee this can't overflow but it
+ ; can still produce 0 for extreme cHRM values.
+
+; blue_scale = png_reciprocal(xy->whitey) - png_reciprocal(red_inverse) -
+; png_reciprocal(green_inverse);
+; if (blue_scale <= 0)
+; return 1;
+
+
+ ; And fill in the png_XYZ:
+; if (png_muldiv(&XYZ->red_X, xy->redx, PNG_FP_1, red_inverse) == 0)
+; return 1;
+; if (png_muldiv(&XYZ->red_Y, xy->redy, PNG_FP_1, red_inverse) == 0)
+; return 1;
+; if (png_muldiv(&XYZ->red_Z, PNG_FP_1 - xy->redx - xy->redy, PNG_FP_1,
+; red_inverse) == 0)
+; return 1;
+
+; if (png_muldiv(&XYZ->green_X, xy->greenx, PNG_FP_1, green_inverse) == 0)
+; return 1;
+; if (png_muldiv(&XYZ->green_Y, xy->greeny, PNG_FP_1, green_inverse) == 0)
+; return 1;
+; if (png_muldiv(&XYZ->green_Z, PNG_FP_1 - xy->greenx - xy->greeny, PNG_FP_1,
+; green_inverse) == 0)
+; return 1;
+
+; if (png_muldiv(&XYZ->blue_X, xy->bluex, blue_scale, PNG_FP_1) == 0)
+; return 1;
+; if (png_muldiv(&XYZ->blue_Y, xy->bluey, blue_scale, PNG_FP_1) == 0)
+; return 1;
+; if (png_muldiv(&XYZ->blue_Z, PNG_FP_1 - xy->bluex - xy->bluey, blue_scale,
+; PNG_FP_1) == 0)
+; return 1;
+
+; return 0; /*success*/
+ ret
+endp
+
+;int (png_XYZ *XYZ)
+align 4
+proc png_XYZ_normalize, XYZ:dword
+; int_32 Y;
+
+; if (XYZ->red_Y < 0 || XYZ->green_Y < 0 || XYZ->blue_Y < 0 ||
+; XYZ->red_X < 0 || XYZ->green_X < 0 || XYZ->blue_X < 0 ||
+; XYZ->red_Z < 0 || XYZ->green_Z < 0 || XYZ->blue_Z < 0)
+; return 1;
+
+ ; Normalize by scaling so the sum of the end-point Y values is PNG_FP_1.
+ ; IMPLEMENTATION NOTE: ANSI requires signed overflow not to occur, therefore
+ ; relying on addition of two positive values producing a negative one is not
+ ; safe.
+
+; Y = XYZ->red_Y;
+; if (0x7fffffff - Y < XYZ->green_X)
+; return 1;
+; Y += XYZ->green_Y;
+; if (0x7fffffff - Y < XYZ->blue_X)
+; return 1;
+; Y += XYZ->blue_Y;
+
+; if (Y != PNG_FP_1)
+; {
+; if (png_muldiv(&XYZ->red_X, XYZ->red_X, PNG_FP_1, Y) == 0)
+; return 1;
+; if (png_muldiv(&XYZ->red_Y, XYZ->red_Y, PNG_FP_1, Y) == 0)
+; return 1;
+; if (png_muldiv(&XYZ->red_Z, XYZ->red_Z, PNG_FP_1, Y) == 0)
+; return 1;
+
+; if (png_muldiv(&XYZ->green_X, XYZ->green_X, PNG_FP_1, Y) == 0)
+; return 1;
+; if (png_muldiv(&XYZ->green_Y, XYZ->green_Y, PNG_FP_1, Y) == 0)
+; return 1;
+; if (png_muldiv(&XYZ->green_Z, XYZ->green_Z, PNG_FP_1, Y) == 0)
+; return 1;
+
+; if (png_muldiv(&XYZ->blue_X, XYZ->blue_X, PNG_FP_1, Y) == 0)
+; return 1;
+; if (png_muldiv(&XYZ->blue_Y, XYZ->blue_Y, PNG_FP_1, Y) == 0)
+; return 1;
+; if (png_muldiv(&XYZ->blue_Z, XYZ->blue_Z, PNG_FP_1, Y) == 0)
+; return 1;
+; }
+
+; return 0;
+ ret
+endp
+
+;int (const png_xy *xy1, const png_xy *xy2, int delta)
+align 4
+proc png_colorspace_endpoints_match, xy1:dword, xy2:dword, delta:dword
+ ; Allow an error of +/-0.01 (absolute value) on each chromaticity
+; if (PNG_OUT_OF_RANGE(xy1->whitex, xy2->whitex,delta) ||
+; PNG_OUT_OF_RANGE(xy1->whitey, xy2->whitey,delta) ||
+; PNG_OUT_OF_RANGE(xy1->redx, xy2->redx, delta) ||
+; PNG_OUT_OF_RANGE(xy1->redy, xy2->redy, delta) ||
+; PNG_OUT_OF_RANGE(xy1->greenx, xy2->greenx,delta) ||
+; PNG_OUT_OF_RANGE(xy1->greeny, xy2->greeny,delta) ||
+; PNG_OUT_OF_RANGE(xy1->bluex, xy2->bluex, delta) ||
+; PNG_OUT_OF_RANGE(xy1->bluey, xy2->bluey, delta))
+; return 0;
+; return 1;
+ ret
+endp
+
+; Added in libpng-1.6.0, a different check for the validity of a set of cHRM
+; chunk chromaticities. Earlier checks used to simply look for the overflow
+; condition (where the determinant of the matrix to solve for XYZ ends up zero
+; because the chromaticity values are not all distinct.) Despite this it is
+; theoretically possible to produce chromaticities that are apparently valid
+; but that rapidly degrade to invalid, potentially crashing, sets because of
+; arithmetic inaccuracies when calculations are performed on them. The new
+; check is to round-trip xy -> XYZ -> xy and then check that the result is
+; within a small percentage of the original.
+
+;int (png_XYZ *XYZ, const png_xy *xy)
+align 4
+proc png_colorspace_check_xy, XYZ:dword, xy:dword
+; int result;
+; png_xy xy_test;
+
+ ; As a side-effect this routine also returns the XYZ endpoints.
+; result = png_XYZ_from_xy(XYZ, xy);
+; if (result != 0)
+; return result;
+
+; result = png_xy_from_XYZ(&xy_test, XYZ);
+; if (result != 0)
+; return result;
+
+; if (png_colorspace_endpoints_match(xy, &xy_test,
+; 5/*actually, the math is pretty accurate*/) != 0)
+; return 0;
+
+ ; Too much slip
+; return 1;
+ ret
+endp
+
+; This is the check going the other way. The XYZ is modified to normalize it
+; (another side-effect) and the xy chromaticities are returned.
+
+;int (png_xy *xy, png_XYZ *XYZ)
+align 4
+proc png_colorspace_check_XYZ, xy:dword, XYZ:dword
+; int result;
+; png_XYZ XYZtemp;
+
+; result = png_XYZ_normalize(XYZ);
+; if (result != 0)
+; return result;
+
+; result = png_xy_from_XYZ(xy, XYZ);
+; if (result != 0)
+; return result;
+
+; XYZtemp = *XYZ;
+; return png_colorspace_check_xy(&XYZtemp, xy);
+ ret
+endp
+
+; Used to check for an endpoint match against sRGB
+;const png_xy sRGB_xy = /* From ITU-R BT.709-3 */
+; /* color x y */
+; /* red */ 64000, 33000,
+; /* green */ 30000, 60000,
+; /* blue */ 15000, 6000,
+; /* white */ 31270, 32900
+
+;int (png_structrp png_ptr,
+; png_colorspacerp colorspace, const png_xy *xy, const png_XYZ *XYZ,
+; int preferred)
+align 4
+proc png_colorspace_set_xy_and_XYZ, png_ptr:dword, colorspace:dword, xy:dword, XYZ:dword, preferred:dword
+; if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
+; return 0;
+
+ ; The consistency check is performed on the chromaticities; this factors out
+ ; variations because of the normalization (or not) of the end point Y
+ ; values.
+
+; if (preferred < 2 &&
+; (colorspace->flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
+; {
+ ; The end points must be reasonably close to any we already have. The
+ ; following allows an error of up to +/-.001
+
+; if (png_colorspace_endpoints_match(xy, &colorspace->end_points_xy,
+; 100) == 0)
+; {
+; colorspace->flags |= PNG_COLORSPACE_INVALID;
+; png_benign_error(png_ptr, "inconsistent chromaticities");
+; return 0; /* failed */
+; }
+
+ ; Only overwrite with preferred values
+; if (preferred == 0)
+; return 1; /* ok, but no change */
+; }
+
+; colorspace->end_points_xy = *xy;
+; colorspace->end_points_XYZ = *XYZ;
+; colorspace->flags |= PNG_COLORSPACE_HAVE_ENDPOINTS;
+
+; /* The end points are normally quoted to two decimal digits, so allow +/-0.01
+ ; on this test.
+
+; if (png_colorspace_endpoints_match(xy, &sRGB_xy, 1000) != 0)
+; colorspace->flags |= PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB;
+;
+; else
+; colorspace->flags &= PNG_COLORSPACE_CANCEL(
+; PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB);
+
+; return 2; /* ok and changed */
+ ret
+endp
+
+;int (png_structrp png_ptr,
+; png_colorspacerp colorspace, const png_xy *xy, int preferred)
+align 4
+proc png_colorspace_set_chromaticities, png_ptr:dword, colorspace:dword, xy:dword, preferred:dword
+ ; We must check the end points to ensure they are reasonable - in the past
+ ; color management systems have crashed as a result of getting bogus
+ ; colorant values, while this isn't the fault of libpng it is the
+ ; responsibility of libpng because PNG carries the bomb and libpng is in a
+ ; position to protect against it.
+
+; png_XYZ XYZ;
+
+; switch (png_colorspace_check_xy(&XYZ, xy))
+; {
+; case 0: /* success */
+; return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, xy, &XYZ,
+; preferred);
+
+; case 1:
+ ; We can't invert the chromaticities so we can't produce value XYZ
+ ; values. Likely as not a color management system will fail too.
+
+; colorspace->flags |= PNG_COLORSPACE_INVALID;
+; png_benign_error(png_ptr, "invalid chromaticities");
+; break;
+;
+; default:
+ ; libpng is broken; this should be a warning but if it happens we
+ ; want error reports so for the moment it is an error.
+
+; colorspace->flags |= PNG_COLORSPACE_INVALID;
+; png_error(png_ptr, "internal error checking chromaticities");
+; }
+
+ xor eax,eax
+.end_f:
+ ret
+endp
+
+;int (png_structrp png_ptr,
+; png_colorspacerp colorspace, const png_XYZ *XYZ_in, int preferred)
+align 4
+proc png_colorspace_set_endpoints, png_ptr:dword, colorspace:dword, XYZ_in:dword, preferred:dword
+; png_XYZ XYZ = *XYZ_in;
+; png_xy xy;
+
+; switch (png_colorspace_check_XYZ(&xy, &XYZ))
+; {
+; case 0:
+; return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, &xy, &XYZ,
+; preferred);
+
+; case 1:
+ ; End points are invalid.
+; colorspace->flags |= PNG_COLORSPACE_INVALID;
+; png_benign_error(png_ptr, "invalid end points");
+; break;
+
+; default:
+; colorspace->flags |= PNG_COLORSPACE_INVALID;
+; png_error(png_ptr, "internal error checking chromaticities");
+; }
+
+ xor eax,eax
+.end_f:
+ ret
+endp
+
+; Error message generation
+;char (uint_32 byte)
+align 4
+proc png_icc_tag_char, p1byte:dword
+ mov eax,[p1byte]
+ cmp al,32
+ jl @f
+ cmp al,126
+ jg @f ;if (..>=.. && ..<=..) return
+ mov al,'?'
+ @@:
+ and eax,0xff
+ ret
+endp
+
+;void (char *name, uint_32 tag)
+align 4
+proc png_icc_tag_name uses eax edi, name:dword, tag:dword
+ mov edi,[name]
+ mov byte[edi],39
+ mov byte[edi+5],39
+ inc edi
+ mov eax,[tag]
+ shr eax,24
+ stdcall png_icc_tag_char,eax
+ stosb
+ mov eax,[tag]
+ shr eax,16
+ stdcall png_icc_tag_char,eax
+ stosb
+ mov eax,[tag]
+ shr eax,8
+ stdcall png_icc_tag_char,eax
+ stosb
+ stdcall png_icc_tag_char,[tag]
+ stosb
+ ret
+endp
+
+;int (png_alloc_size_t it)
+align 4
+proc is_ICC_signature_char, it:dword
+; return it == 32 || (it >= 48 && it <= 57) || (it >= 65 && it <= 90) ||
+; (it >= 97 && it <= 122);
+ ret
+endp
+
+;int (png_alloc_size_t it)
+align 4
+proc is_ICC_signature, it:dword
+; return is_ICC_signature_char(it >> 24) /* checks all the top bits */ &&
+; is_ICC_signature_char((it >> 16) & 0xff) &&
+; is_ICC_signature_char((it >> 8) & 0xff) &&
+; is_ICC_signature_char(it & 0xff);
+ ret
+endp
+
+;int (png_structrp png_ptr, png_colorspacerp colorspace,
+; charp name, png_alloc_size_t value, charp reason)
+align 4
+proc png_icc_profile_error, png_ptr:dword, colorspace:dword, name:dword, value:dword, reason:dword
+locals
+ pos dd ? ;size_t
+ message rb 196 ;char[] ;see below for calculation
+endl
+ mov eax,[colorspace]
+ cmp eax,0
+ je @f ;if (..!=0)
+ or word[eax+png_colorspace.flags], PNG_COLORSPACE_INVALID
+ @@:
+
+; pos = png_safecat(message, (sizeof message), 0, "profile '"); /* 9 chars */
+; pos = png_safecat(message, pos+79, pos, name); /* Truncate to 79 chars */
+; pos = png_safecat(message, (sizeof message), pos, "': "); /* +2 = 90 */
+; if (is_ICC_signature(value) != 0)
+; {
+ ; So 'value' is at most 4 bytes and the following cast is safe
+; png_icc_tag_name(message+pos, (uint_32)value);
+; pos += 6; /* total +8; less than the else clause */
+; message[pos++] = ':';
+; message[pos++] = ' ';
+; }
+if PNG_WARNINGS_SUPPORTED eq 1
+; else
+; {
+; char number[PNG_NUMBER_BUFFER_SIZE]; /* +24 = 114*/
+
+; pos = png_safecat(message, (sizeof message), pos,
+; png_format_number(number, number+(sizeof number),
+; PNG_NUMBER_FORMAT_x, value));
+; pos = png_safecat(message, (sizeof message), pos, "h: "); /*+2 = 116*/
+; }
+end if
+ ; The 'reason' is an arbitrary message, allow +79 maximum 195
+; pos = png_safecat(message, (sizeof message), pos, reason);
+
+ ; This is recoverable, but make it unconditionally an app_error on write to
+ ; avoid writing invalid ICC profiles into PNG files (i.e., we handle them
+ ; on read, with a warning, but on write unless the app turns off
+ ; application errors the PNG won't be written.)
+
+; png_chunk_report(png_ptr, message,
+; (colorspace != NULL) ? PNG_CHUNK_ERROR : PNG_CHUNK_WRITE_ERROR);
+
+ xor eax,eax
+ ret
+endp
+
+if PNG_sRGB_SUPPORTED eq 1
+;color X Y Z
+sRGB_XYZ dd 41239, 21264, 1933,\ ;red
+ 35758, 71517, 11919,\ ;green
+ 18048, 7219, 95053 ;blue
+end if
+
+;int (png_structrp png_ptr, png_colorspacerp colorspace, int intent)
+align 4
+proc png_colorspace_set_sRGB uses ebx ecx edi esi, png_ptr:dword, colorspace:dword, intent:dword
+ ; sRGB sets known gamma, end points and (from the chunk) intent.
+ ; IMPORTANT: these are not necessarily the values found in an ICC profile
+ ; because ICC profiles store values adapted to a D50 environment; it is
+ ; expected that the ICC profile mediaWhitePointTag will be D50; see the
+ ; checks and code elsewhere to understand this better.
+
+ ; These XYZ values, which are accurate to 5dp, produce rgb to gray
+ ; coefficients of (6968,23435,2366), which are reduced (because they add up
+ ; to 32769 not 32768) to (6968,23434,2366). These are the values that
+ ; libpng has traditionally used (and are the best values given the 15bit
+ ; algorithm used by the rgb to gray code.)
+
+ ; Do nothing if the colorspace is already invalidated.
+ mov ebx,[colorspace]
+ mov ax,[ebx+png_colorspace.flags]
+ and ax,PNG_COLORSPACE_INVALID
+ cmp ax,0
+ je @f ;if (..!=0)
+ xor eax,eax
+ jmp .end_f
+ @@:
+
+ ; Check the intent, then check for existing settings. It is valid for the
+ ; PNG file to have cHRM or gAMA chunks along with sRGB, but the values must
+ ; be consistent with the correct values. If, however, this function is
+ ; called below because an iCCP chunk matches sRGB then it is quite
+ ; conceivable that an older app recorded incorrect gAMA and cHRM because of
+ ; an incorrect calculation based on the values in the profile - this does
+ ; *not* invalidate the profile (though it still produces an error, which can
+ ; be ignored.)
+
+ mov edi,[png_ptr]
+ cmp dword[intent],0
+ jl @f
+ cmp dword[intent],PNG_sRGB_INTENT_LAST
+ jge @f
+ jmp .end0
+ @@: ;if (..<0 || ..>=..)
+ cStr ,'sRGB'
+ cStr ecx,'invalid sRGB rendering intent'
+ stdcall png_icc_profile_error, edi, ebx, eax, [intent], ecx
+ jmp .end_f
+ .end0:
+
+ mov ax,[ebx+png_colorspace.flags]
+ and ax,PNG_COLORSPACE_HAVE_INTENT
+ cmp ax,0
+ je @f
+ movzx eax,word[ebx+png_colorspace.rendering_intent]
+ cmp eax,[intent]
+ je @f ;if (..!=0 && ..!=..)
+ cStr ,'sRGB'
+ cStr ecx,'inconsistent rendering intents'
+ stdcall png_icc_profile_error, edi, ebx, eax, [intent], ecx
+ jmp .end_f
+ @@:
+
+ mov ax,[ebx+png_colorspace.flags]
+ and ax,PNG_COLORSPACE_FROM_sRGB
+ cmp ax,0
+ je @f ;if (..!=0)
+ png_benign_error edi, 'duplicate sRGB information ignored'
+ xor eax,eax
+ jmp .end_f
+ @@:
+
+ ; If the standard sRGB cHRM chunk does not match the one from the PNG file
+ ; warn but overwrite the value with the correct one.
+
+ mov ax,[ebx+png_colorspace.flags]
+ and ax,PNG_COLORSPACE_HAVE_ENDPOINTS
+ cmp ax,0
+ je @f ;if (..!=0 &&
+; !png_colorspace_endpoints_match(&sRGB_xy, &colorspace->end_points_xy,
+; 100))
+ cStr ,'cHRM chunk does not match sRGB'
+ stdcall png_chunk_report, edi, eax, PNG_CHUNK_ERROR
+ @@:
+
+ ; This check is just done for the error reporting - the routine always
+ ; returns true when the 'from' argument corresponds to sRGB (2).
+
+ stdcall png_colorspace_check_gamma, edi, ebx, PNG_GAMMA_sRGB_INVERSE, 2 ;from sRGB
+
+ ; intent: bugs in GCC force 'int' to be used as the parameter type.
+ mov eax,[intent]
+ mov [ebx+png_colorspace.rendering_intent],ax
+ or word[ebx+png_colorspace.flags], PNG_COLORSPACE_HAVE_INTENT
+
+ ; endpoints
+; colorspace->end_points_xy = sRGB_xy;
+; colorspace->end_points_XYZ = sRGB_XYZ;
+ or word[ebx+png_colorspace.flags], (PNG_COLORSPACE_HAVE_ENDPOINTS or PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB)
+
+ ; gamma
+ mov dword[ebx+png_colorspace.gamma], PNG_GAMMA_sRGB_INVERSE
+ or word[ebx+png_colorspace.flags], PNG_COLORSPACE_HAVE_GAMMA
+
+ ; Finally record that we have an sRGB profile
+ or word[ebx+png_colorspace.flags], (PNG_COLORSPACE_MATCHES_sRGB or PNG_COLORSPACE_FROM_sRGB)
+
+ xor eax,eax
+ inc eax ;set
+.end_f:
+ ret
+endp
+
+;if PNG_iCCP_SUPPORTED
+; Encoded value of D50 as an ICC XYZNumber. From the ICC 2010 spec the value
+; is XYZ(0.9642,1.0,0.8249), which scales to:
+
+; (63189.8112, 65536, 54060.6464)
+
+D50_nCIEXYZ db \ ;byte[12]
+ 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d
+
+;int /* bool */
+;(png_structrp png_ptr, png_colorspacerp colorspace, charp name, uint_32 profile_length)
+align 4
+proc icc_check_length, png_ptr:dword, colorspace:dword, name:dword, profile_length:dword
+ cmp dword[profile_length],132
+ jge @f ;if (..<..)
+; return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
+; "too short");
+ jmp .end_f
+ @@:
+ xor eax,eax
+ inc eax
+.end_f:
+ ret
+endp
+
+;int (png_structrp png_ptr, png_colorspacerp colorspace,
+; charp name, uint_32 profile_length)
+align 4
+proc png_icc_check_length, png_ptr:dword, colorspace:dword, name:dword, profile_length:dword
+; if (!icc_check_length(png_ptr, colorspace, name, profile_length))
+; return 0;
+
+ ; This needs to be here because the 'normal' check is in
+ ; png_decompress_chunk, yet this happens after the attempt to
+ ; png_malloc_base the required data. We only need this on read; on write
+ ; the caller supplies the profile buffer so libpng doesn't allocate it. See
+ ; the call to icc_check_length below (the write case).
+
+if PNG_SET_USER_LIMITS_SUPPORTED eq 1
+; else if (png_ptr->user_chunk_malloc_max > 0 &&
+; png_ptr->user_chunk_malloc_max < profile_length)
+; return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
+; "exceeds application limits");
+elseif PNG_USER_CHUNK_MALLOC_MAX > 0
+; else if (PNG_USER_CHUNK_MALLOC_MAX < profile_length)
+; return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
+; "exceeds libpng limits");
+else ;!SET_USER_LIMITS
+ ; This will get compiled out on all 32-bit and better systems.
+; else if (PNG_SIZE_MAX < profile_length)
+; return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
+; "exceeds system limits");
+end if ;!SET_USER_LIMITS
+ xor eax,eax
+ inc eax
+.end_f:
+ ret
+endp
+
+;int (png_structrp png_ptr, png_colorspacerp colorspace,
+; charp name, uint_32 profile_length,
+; bytep profile/* first 132 bytes only */, int color_type)
+align 4
+proc png_icc_check_header, png_ptr:dword, colorspace:dword, name:dword, profile_length:dword, profile:dword, color_type:dword
+; uint_32 temp;
+
+ ; Length check; this cannot be ignored in this code because profile_length
+ ; is used later to check the tag table, so even if the profile seems over
+ ; long profile_length from the caller must be correct. The caller can fix
+ ; this up on read or write by just passing in the profile header length.
+
+; temp = png_get_uint_32(profile);
+; if (temp != profile_length)
+; return png_icc_profile_error(png_ptr, colorspace, name, temp,
+; "length does not match profile");
+
+; temp = (uint_32) (*(profile+8));
+; if (temp > 3 && (profile_length & 3))
+; return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
+; "invalid length");
+
+; temp = png_get_uint_32(profile+128); /* tag count: 12 bytes/tag */
+; if (temp > 357913930 || /* (2^32-4-132)/12: maximum possible tag count */
+; profile_length < 132+12*temp) /* truncated tag table */
+; return png_icc_profile_error(png_ptr, colorspace, name, temp,
+; "tag count too large");
+
+ ; The 'intent' must be valid or we can't store it, ICC limits the intent to
+ ; 16 bits.
+
+; temp = png_get_uint_32(profile+64);
+; if (temp >= 0xffff) /* The ICC limit */
+; return png_icc_profile_error(png_ptr, colorspace, name, temp,
+; "invalid rendering intent");
+
+ ; This is just a warning because the profile may be valid in future
+ ; versions.
+
+; if (temp >= PNG_sRGB_INTENT_LAST)
+; (void)png_icc_profile_error(png_ptr, NULL, name, temp,
+; "intent outside defined range");
+
+ ; At this point the tag table can't be checked because it hasn't necessarily
+ ; been loaded; however, various header fields can be checked. These checks
+ ; are for values permitted by the PNG spec in an ICC profile; the PNG spec
+ ; restricts the profiles that can be passed in an iCCP chunk (they must be
+ ; appropriate to processing PNG data!)
+
+ ; Data checks (could be skipped). These checks must be independent of the
+ ; version number; however, the version number doesn't accomodate changes in
+ ; the header fields (just the known tags and the interpretation of the
+ ; data.)
+
+; temp = png_get_uint_32(profile+36); /* signature 'ascp' */
+; if (temp != 0x61637370)
+; return png_icc_profile_error(png_ptr, colorspace, name, temp,
+; "invalid signature");
+
+ ; Currently the PCS illuminant/adopted white point (the computational
+ ; white point) are required to be D50,
+ ; however the profile contains a record of the illuminant so perhaps ICC
+ ; expects to be able to change this in the future (despite the rationale in
+ ; the introduction for using a fixed PCS adopted white.) Consequently the
+ ; following is just a warning.
+
+; if (memcmp(profile+68, D50_nCIEXYZ, 12) != 0)
+; (void)png_icc_profile_error(png_ptr, NULL, name, 0/*no tag value*/,
+; "PCS illuminant is not D50");
+
+ ; The PNG spec requires this:
+ ; "If the iCCP chunk is present, the image samples conform to the colour
+ ; space represented by the embedded ICC profile as defined by the
+ ; International Color Consortium [ICC]. The colour space of the ICC profile
+ ; shall be an RGB colour space for colour images (PNG colour types 2, 3, and
+ ; 6), or a greyscale colour space for greyscale images (PNG colour types 0
+ ; and 4)."
+
+ ; This checking code ensures the embedded profile (on either read or write)
+ ; conforms to the specification requirements. Notice that an ICC 'gray'
+ ; color-space profile contains the information to transform the monochrome
+ ; data to XYZ or L*a*b (according to which PCS the profile uses) and this
+ ; should be used in preference to the standard libpng K channel replication
+ ; into R, G and B channels.
+
+ ; Previously it was suggested that an RGB profile on grayscale data could be
+ ; handled. However it it is clear that using an RGB profile in this context
+ ; must be an error - there is no specification of what it means. Thus it is
+ ; almost certainly more correct to ignore the profile.
+
+; temp = png_get_uint_32(profile+16); /* data colour space field */
+; switch (temp)
+; {
+; case 0x52474220: /* 'RGB ' */
+; if ((color_type & PNG_COLOR_MASK_COLOR) == 0)
+; return png_icc_profile_error(png_ptr, colorspace, name, temp,
+; "RGB color space not permitted on grayscale PNG");
+; break;
+
+; case 0x47524159: /* 'GRAY' */
+; if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
+; return png_icc_profile_error(png_ptr, colorspace, name, temp,
+; "Gray color space not permitted on RGB PNG");
+; break;
+
+; default:
+; return png_icc_profile_error(png_ptr, colorspace, name, temp,
+; "invalid ICC profile color space");
+; }
+
+ ; It is up to the application to check that the profile class matches the
+ ; application requirements; the spec provides no guidance, but it's pretty
+ ; weird if the profile is not scanner ('scnr'), monitor ('mntr'), printer
+ ; ('prtr') or 'spac' (for generic color spaces). Issue a warning in these
+ ; cases. Issue an error for device link or abstract profiles - these don't
+ ; contain the records necessary to transform the color-space to anything
+ ; other than the target device (and not even that for an abstract profile).
+ ; Profiles of these classes may not be embedded in images.
+
+; temp = png_get_uint_32(profile+12); /* profile/device class */
+; switch (temp)
+; {
+; case 0x73636e72: /* 'scnr' */
+; case 0x6d6e7472: /* 'mntr' */
+; case 0x70727472: /* 'prtr' */
+; case 0x73706163: /* 'spac' */
+; /* All supported */
+; break;
+
+; case 0x61627374: /* 'abst' */
+; /* May not be embedded in an image */
+; return png_icc_profile_error(png_ptr, colorspace, name, temp,
+; "invalid embedded Abstract ICC profile");
+
+; case 0x6c696e6b: /* 'link' */
+; /* DeviceLink profiles cannot be interpreted in a non-device specific
+ ; fashion, if an app uses the AToB0Tag in the profile the results are
+ ; undefined unless the result is sent to the intended device,
+ ; therefore a DeviceLink profile should not be found embedded in a
+ ; PNG.
+
+; return png_icc_profile_error(png_ptr, colorspace, name, temp,
+; "unexpected DeviceLink ICC profile class");
+
+; case 0x6e6d636c: /* 'nmcl' */
+; /* A NamedColor profile is also device specific, however it doesn't
+ ; contain an AToB0 tag that is open to misinterpretation. Almost
+ ; certainly it will fail the tests below.
+
+; (void)png_icc_profile_error(png_ptr, NULL, name, temp,
+; "unexpected NamedColor ICC profile class");
+; break;
+
+; default:
+; /* To allow for future enhancements to the profile accept unrecognized
+ ; profile classes with a warning, these then hit the test below on the
+ ; tag content to ensure they are backward compatible with one of the
+ ; understood profiles.
+
+; (void)png_icc_profile_error(png_ptr, NULL, name, temp,
+; "unrecognized ICC profile class");
+; break;
+; }
+
+ ; For any profile other than a device link one the PCS must be encoded
+ ; either in XYZ or Lab.
+
+; temp = png_get_uint_32(profile+20);
+; switch (temp)
+; {
+; case 0x58595a20: /* 'XYZ ' */
+; case 0x4c616220: /* 'Lab ' */
+; break;
+
+; default:
+; return png_icc_profile_error(png_ptr, colorspace, name, temp,
+; "unexpected ICC PCS encoding");
+; }
+
+; return 1;
+ ret
+endp
+
+;int (png_structrp png_ptr, png_colorspacerp colorspace,
+; charp name, uint_32 profile_length,
+; bytep profile /* header plus whole tag table */)
+align 4
+proc png_icc_check_tag_table, png_ptr:dword, colorspace:dword, name:dword, profile_length:dword, profile:dword
+; uint_32 tag_count = png_get_uint_32(profile+128);
+; uint_32 itag;
+; bytep tag = profile+132; /* The first tag */
+
+ ; First scan all the tags in the table and add bits to the icc_info value
+ ; (temporarily in 'tags').
+
+; for (itag=0; itag < tag_count; ++itag, tag += 12)
+; {
+; uint_32 tag_id = png_get_uint_32(tag+0);
+; uint_32 tag_start = png_get_uint_32(tag+4); /* must be aligned */
+; uint_32 tag_length = png_get_uint_32(tag+8);/* not padded */
+
+ ; The ICC specification does not exclude zero length tags, therefore the
+ ; start might actually be anywhere if there is no data, but this would be
+ ; a clear abuse of the intent of the standard so the start is checked for
+ ; being in range. All defined tag types have an 8 byte header - a 4 byte
+ ; type signature then 0.
+
+; if ((tag_start & 3) != 0)
+; {
+ ; CNHP730S.icc shipped with Microsoft Windows 64 violates this, it is
+ ; only a warning here because libpng does not care about the
+ ; alignment.
+
+; (void)png_icc_profile_error(png_ptr, NULL, name, tag_id,
+; "ICC profile tag start not a multiple of 4");
+; }
+
+ ; This is a hard error; potentially it can cause read outside the
+ ; profile.
+
+; if (tag_start > profile_length || tag_length > profile_length - tag_start)
+; return png_icc_profile_error(png_ptr, colorspace, name, tag_id,
+; "ICC profile tag outside profile");
+; }
+ xor eax,eax
+ inc eax ;success, maybe with warnings
+.end_f:
+ ret
+endp
+
+;if PNG_sRGB_SUPPORTED
+;#if PNG_sRGB_PROFILE_CHECKS >= 0
+; Information about the known ICC sRGB profiles
+struct png_sRGB_checks
+ adler dd ? ;uint_32
+ crc dd ?
+ length dd ?
+ md5 rd 4 ;uint_32[4]
+ have_md5 db ? ;byte
+ is_broken db ? ;byte
+ intent dw ? ;uint_16
+ends
+;# define PNG_MD5(a,b,c,d) { a, b, c, d }, (a!=0)||(b!=0)||(c!=0)||(d!=0)
+;# define PNG_ICC_CHECKSUM(adler, crc, md5, intent, broke, date, length, fname)\
+; { adler, crc, length, md5, broke, intent },
+
+;[] =
+ ; This data comes from contrib/tools/checksum-icc run on downloads of
+ ; all four ICC sRGB profiles from www.color.org.
+
+ ; adler32, crc32, MD5[4], intent, date, length, file-name
+; PNG_ICC_CHECKSUM(0x0a3fd9f6, 0x3b8772b9,
+; PNG_MD5(0x29f83dde, 0xaff255ae, 0x7842fae4, 0xca83390d), 0, 0,
+; "2009/03/27 21:36:31", 3048, "sRGB_IEC61966-2-1_black_scaled.icc")
+
+ ; ICC sRGB v2 perceptual no black-compensation:
+; PNG_ICC_CHECKSUM(0x4909e5e1, 0x427ebb21,
+; PNG_MD5(0xc95bd637, 0xe95d8a3b, 0x0df38f99, 0xc1320389), 1, 0,
+; "2009/03/27 21:37:45", 3052, "sRGB_IEC61966-2-1_no_black_scaling.icc")
+
+; PNG_ICC_CHECKSUM(0xfd2144a1, 0x306fd8ae,
+; PNG_MD5(0xfc663378, 0x37e2886b, 0xfd72e983, 0x8228f1b8), 0, 0,
+; "2009/08/10 17:28:01", 60988, "sRGB_v4_ICC_preference_displayclass.icc")
+
+ ; ICC sRGB v4 perceptual
+; PNG_ICC_CHECKSUM(0x209c35d2, 0xbbef7812,
+; PNG_MD5(0x34562abf, 0x994ccd06, 0x6d2c5721, 0xd0d68c5d), 0, 0,
+; "2007/07/25 00:05:37", 60960, "sRGB_v4_ICC_preference.icc")
+
+ ; The following profiles have no known MD5 checksum. If there is a match
+ ; on the (empty) MD5 the other fields are used to attempt a match and
+ ; a warning is produced. The first two of these profiles have a 'cprt' tag
+ ; which suggests that they were also made by Hewlett Packard.
+
+; PNG_ICC_CHECKSUM(0xa054d762, 0x5d5129ce,
+; PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 0,
+; "2004/07/21 18:57:42", 3024, "sRGB_IEC61966-2-1_noBPC.icc")
+
+ ; This is a 'mntr' (display) profile with a mediaWhitePointTag that does not
+ ; match the D50 PCS illuminant in the header (it is in fact the D65 values,
+ ; so the white point is recorded as the un-adapted value.) The profiles
+ ; below only differ in one byte - the intent - and are basically the same as
+ ; the previous profile except for the mediaWhitePointTag error and a missing
+ ; chromaticAdaptationTag.
+
+; PNG_ICC_CHECKSUM(0xf784f3fb, 0x182ea552,
+; PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 0, 1/*broken*/,
+; "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 perceptual")
+
+; PNG_ICC_CHECKSUM(0x0398f3fc, 0xf29e526d,
+; PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 1/*broken*/,
+; "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 media-relative")
+;
+
+;int (png_structrp png_ptr, bytep profile, uLong adler)
+align 4
+proc png_compare_ICC_profile_with_sRGB, png_ptr:dword, profile:dword, adler:dword
+ ; The quick check is to verify just the MD5 signature and trust the
+ ; rest of the data. Because the profile has already been verified for
+ ; correctness this is safe. png_colorspace_set_sRGB will check the 'intent'
+ ; field too, so if the profile has been edited with an intent not defined
+ ; by sRGB (but maybe defined by a later ICC specification) the read of
+ ; the profile will fail at that point.
+
+; uint_32 length = 0;
+; uint_32 intent = 0x10000; /* invalid */
+if PNG_sRGB_PROFILE_CHECKS > 1
+; uLong crc = 0; /* the value for 0 length data */
+end if
+; uint i;
+
+if PNG_SET_OPTION_SUPPORTED eq 1
+ ; First see if PNG_SKIP_sRGB_CHECK_PROFILE has been set to "on"
+; if (((png_ptr->options >> PNG_SKIP_sRGB_CHECK_PROFILE) & 3) ==
+; PNG_OPTION_ON)
+; return 0;
+end if
+
+; for (i=0; i < (sizeof png_sRGB_checks) / (sizeof png_sRGB_checks[0]); ++i)
+; {
+; if (png_get_uint_32(profile+84) == png_sRGB_checks[i].md5[0] &&
+; png_get_uint_32(profile+88) == png_sRGB_checks[i].md5[1] &&
+; png_get_uint_32(profile+92) == png_sRGB_checks[i].md5[2] &&
+; png_get_uint_32(profile+96) == png_sRGB_checks[i].md5[3])
+; {
+ ; This may be one of the old HP profiles without an MD5, in that
+ ; case we can only use the length and Adler32 (note that these
+ ; are not used by default if there is an MD5!)
+
+;# if PNG_sRGB_PROFILE_CHECKS == 0
+; if (png_sRGB_checks[i].have_md5 != 0)
+; return 1+png_sRGB_checks[i].is_broken;
+;# endif
+
+ ; Profile is unsigned or more checks have been configured in.
+; if (length == 0)
+; {
+; length = png_get_uint_32(profile);
+; intent = png_get_uint_32(profile+64);
+; }
+
+ ; Length *and* intent must match
+; if (length == (uint_32) png_sRGB_checks[i].length &&
+; intent == (uint_32) png_sRGB_checks[i].intent)
+; {
+ ; Now calculate the adler32 if not done already.
+; if (adler == 0)
+; {
+; adler = adler32(0, NULL, 0);
+; adler = adler32(adler, profile, length);
+; }
+
+; if (adler == png_sRGB_checks[i].adler)
+; {
+ ; These basic checks suggest that the data has not been
+ ; modified, but if the check level is more than 1 perform
+ ; our own crc32 checksum on the data.
+
+;# if PNG_sRGB_PROFILE_CHECKS > 1
+; if (crc == 0)
+; {
+; crc = calc_crc32(0, NULL, 0);
+; crc = calc_crc32(crc, profile, length);
+; }
+
+; /* So this check must pass for the 'return' below to happen.
+
+; if (crc == png_sRGB_checks[i].crc)
+;# endif
+; {
+; if (png_sRGB_checks[i].is_broken != 0)
+; {
+ ; These profiles are known to have bad data that may cause
+ ; problems if they are used, therefore attempt to
+ ; discourage their use, skip the 'have_md5' warning below,
+ ; which is made irrelevant by this error.
+
+; png_chunk_report(png_ptr, "known incorrect sRGB profile",
+; PNG_CHUNK_ERROR);
+; }
+
+ ; Warn that this being done; this isn't even an error since
+ ; the profile is perfectly valid, but it would be nice if
+ ; people used the up-to-date ones.
+
+; else if (png_sRGB_checks[i].have_md5 == 0)
+; {
+; png_chunk_report(png_ptr,
+; "out-of-date sRGB profile with no signature",
+; PNG_CHUNK_WARNING);
+; }
+
+; return 1+png_sRGB_checks[i].is_broken;
+; }
+; }
+
+;# if PNG_sRGB_PROFILE_CHECKS > 0
+ ; The signature matched, but the profile had been changed in some
+ ; way. This probably indicates a data error or uninformed hacking.
+ ; Fall through to "no match".
+
+; png_chunk_report(png_ptr,
+; "Not recognizing known sRGB profile that has been edited",
+; PNG_CHUNK_WARNING);
+; break;
+;# endif
+; }
+; }
+; }
+
+; return 0; /* no match */
+ ret
+endp
+
+;void (png_structrp png_ptr,
+; png_colorspacerp colorspace, bytep profile, uLong adler)
+align 4
+proc png_icc_set_sRGB uses eax, png_ptr:dword, colorspace:dword, profile:dword, adler:dword
+ ; Is this profile one of the known ICC sRGB profiles? If it is, just set
+ ; the sRGB information.
+
+; if (png_compare_ICC_profile_with_sRGB(png_ptr, profile, adler) != 0)
+; (void)png_colorspace_set_sRGB(png_ptr, colorspace,
+; (int)/*already checked*/png_get_uint_32(profile+64));
+ ret
+endp
+;end if /* PNG_sRGB_PROFILE_CHECKS >= 0 */
+;end if /* sRGB */
+
+;int (png_structrp png_ptr, png_colorspacerp colorspace,
+; charp name, uint_32 profile_length, bytep profile,
+; int color_type)
+align 4
+proc png_colorspace_set_ICC, png_ptr:dword, colorspace:dword, name:dword, profile_length:dword, profile:dword, color_type:dword
+; if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
+; return 0;
+
+; if (icc_check_length(png_ptr, colorspace, name, profile_length) != 0 &&
+; png_icc_check_header(png_ptr, colorspace, name, profile_length, profile,
+; color_type) != 0 &&
+; png_icc_check_tag_table(png_ptr, colorspace, name, profile_length,
+; profile) != 0)
+; {
+;# if defined(PNG_sRGB_SUPPORTED) && PNG_sRGB_PROFILE_CHECKS >= 0
+ ; If no sRGB support, don't try storing sRGB information
+; png_icc_set_sRGB(png_ptr, colorspace, profile, 0);
+;# endif
+; return 1;
+; }
+
+ ; Failure case
+ xor eax,eax
+.end_f:
+ ret
+endp
+;end if /* iCCP */
+
+;void (png_structrp png_ptr)
+align 4
+proc png_colorspace_set_rgb_coefficients, png_ptr:dword
+ ; Set the rgb_to_gray coefficients from the colorspace.
+; if (png_ptr->rgb_to_gray_coefficients_set == 0 &&
+; (png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
+; {
+ ; png_set_background has not been called, get the coefficients from the Y
+ ; values of the colorspace colorants.
+
+; png_fixed_point r = png_ptr->colorspace.end_points_XYZ.red_Y;
+; png_fixed_point g = png_ptr->colorspace.end_points_XYZ.green_Y;
+; png_fixed_point b = png_ptr->colorspace.end_points_XYZ.blue_Y;
+; png_fixed_point total = r+g+b;
+
+; if (total > 0 &&
+; r >= 0 && png_muldiv(&r, r, 32768, total) && r >= 0 && r <= 32768 &&
+; g >= 0 && png_muldiv(&g, g, 32768, total) && g >= 0 && g <= 32768 &&
+; b >= 0 && png_muldiv(&b, b, 32768, total) && b >= 0 && b <= 32768 &&
+; r+g+b <= 32769)
+; {
+ ; We allow 0 coefficients here. r+g+b may be 32769 if two or
+ ; all of the coefficients were rounded up. Handle this by
+ ; reducing the *largest* coefficient by 1; this matches the
+ ; approach used for the default coefficients in pngrtran.c
+
+; int add = 0;
+;
+; if (r+g+b > 32768)
+; add = -1;
+; else if (r+g+b < 32768)
+; add = 1;
+
+; if (add != 0)
+; {
+; if (g >= r && g >= b)
+; g += add;
+; else if (r >= g && r >= b)
+; r += add;
+; else
+; b += add;
+; }
+
+; /* Check for an internal error. */
+; if (r+g+b != 32768)
+; png_error(png_ptr,
+; "internal error handling cHRM coefficients");
+
+; else
+; {
+; png_ptr->rgb_to_gray_red_coeff = (uint_16)r;
+; png_ptr->rgb_to_gray_green_coeff = (uint_16)g;
+; }
+; }
+
+ ; This is a png_error at present even though it could be ignored -
+ ; it should never happen, but it is important that if it does, the
+ ; bug is fixed.
+
+; else
+; png_error(png_ptr, "internal error handling cHRM->XYZ");
+; }
+ ret
+endp
+
+;end if /* COLORSPACE */
+
+;void (png_structrp png_ptr,
+; uint_32 width, uint_32 height, int bit_depth,
+; int color_type, int interlace_type, int compression_type, int filter_type)
+align 4
+proc png_check_IHDR uses eax ebx edi, png_ptr:dword, width:dword, height:dword, bit_depth:dword, color_type:dword, interlace_type:dword, compression_type:dword, filter_type:dword
+ mov edi,[png_ptr]
+ xor ebx,ebx
+
+ ; Check for width and height valid values
+ cmp dword[width],0
+ jne @f ;if (..==0)
+ png_warning edi, 'Image width is zero in IHDR'
+ inc ebx
+ @@:
+
+ cmp dword[width],PNG_UINT_31_MAX
+ jle @f ;if (..>..)
+ png_warning edi, 'Invalid image width in IHDR'
+ inc ebx
+ @@:
+
+ ; 48 - big_row_buf hack
+ ; 1 - filter byte
+ ; 8 - 8-byte RGBA pixels
+ ; 1 - extra max_pixel_depth pad
+ mov eax,[width]
+ add eax,7
+ and eax,not 7
+ cmp eax,((PNG_SIZE_MAX -48 -1) / 8) -1
+ jle @f ;if (..>..)
+ ; The size of the row must be within the limits of this architecture.
+ ; Because the read code can perform arbitrary transformations the
+ ; maximum size is checked here. Because the code in png_read_start_row
+ ; adds extra space "for safety's sake" in several places a conservative
+ ; limit is used here.
+
+ ; NOTE: it would be far better to check the size that is actually used,
+ ; but the effect in the real world is minor and the changes are more
+ ; extensive, therefore much more dangerous and much more difficult to
+ ; write in a way that avoids compiler warnings.
+
+ png_warning edi, 'Image width is too large for this architecture'
+ inc ebx
+ @@:
+
+if PNG_SET_USER_LIMITS_SUPPORTED eq 1
+ mov eax,[edi+png_struct.user_width_max]
+ cmp dword[width],eax
+else
+ cmp dword[width],PNG_USER_WIDTH_MAX
+end if
+ jle @f ;if (..>..)
+ png_warning edi, 'Image width exceeds user limit in IHDR'
+ inc ebx
+ @@:
+
+ cmp dword[height],0
+ jne @f ;if (..==0)
+ png_warning edi, 'Image height is zero in IHDR'
+ inc ebx
+ @@:
+
+ cmp dword[height],PNG_UINT_31_MAX
+ jle @f ;if (..>..)
+ png_warning edi, 'Invalid image height in IHDR'
+ inc ebx
+ @@:
+
+if PNG_SET_USER_LIMITS_SUPPORTED eq 1
+ mov eax,[edi+png_struct.user_height_max]
+ cmp dword[height],eax
+else
+ cmp dword[height],PNG_USER_HEIGHT_MAX
+end if
+ jle @f ;if (..>..)
+ png_warning edi, 'Image height exceeds user limit in IHDR'
+ inc ebx
+ @@:
+
+ ; Check other values
+ cmp dword[bit_depth],1
+ je @f
+ cmp dword[bit_depth],2
+ je @f
+ cmp dword[bit_depth],4
+ je @f
+ cmp dword[bit_depth],8
+ je @f
+ cmp dword[bit_depth],16
+ je @f ;if (..!=.. && ...)
+ png_warning edi, 'Invalid bit depth in IHDR'
+ inc ebx
+ @@:
+
+ cmp dword[color_type],0
+ jl @f
+ cmp dword[color_type],1
+ je @f
+ cmp dword[color_type],5
+ je @f
+ cmp dword[color_type],6
+ jg @f
+ jmp .end0
+ @@: ;if (..<0 || ..==1 || ..==5 || ..>6)
+ png_warning edi, 'Invalid color type in IHDR'
+ inc ebx
+ .end0:
+
+ cmp dword[color_type],PNG_COLOR_TYPE_PALETTE
+ jne @f
+ cmp dword[bit_depth],8
+ jg .beg1
+ @@:
+ cmp dword[color_type],PNG_COLOR_TYPE_RGB
+ je @f
+ cmp dword[color_type],PNG_COLOR_TYPE_GRAY_ALPHA
+ je @f
+ cmp dword[color_type],PNG_COLOR_TYPE_RGB_ALPHA
+ jne .end1
+ @@:
+ cmp dword[bit_depth],8
+ jge .end1
+ .beg1: ;if (((..==..) && ..>..) || ((..==.. || ..==.. || ..==..) && ..<..))
+ png_warning edi, 'Invalid color type/bit depth combination in IHDR'
+ inc ebx
+ .end1:
+
+ cmp dword[interlace_type],PNG_INTERLACE_LAST
+ jl @f ;if (..>=..)
+ png_warning edi, 'Unknown interlace method in IHDR'
+ inc ebx
+ @@:
+
+ cmp dword[compression_type],PNG_COMPRESSION_TYPE_BASE
+ je @f ;if (..!=..)
+ png_warning edi, 'Unknown compression method in IHDR'
+ inc ebx
+ @@:
+
+if PNG_MNG_FEATURES_SUPPORTED eq 1
+ ; Accept filter_method 64 (intrapixel differencing) only if
+ ; 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
+ ; 2. Libpng did not read a PNG signature (this filter_method is only
+ ; used in PNG datastreams that are embedded in MNG datastreams) and
+ ; 3. The application called png_permit_mng_features with a mask that
+ ; included PNG_FLAG_MNG_FILTER_64 and
+ ; 4. The filter_method is 64 and
+ ; 5. The color_type is RGB or RGBA
+
+; if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) != 0 &&
+; png_ptr->mng_features_permitted != 0)
+ png_warning edi, 'MNG features are not allowed in a PNG datastream'
+
+; if (filter_type != PNG_FILTER_TYPE_BASE)
+; {
+; if (!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
+; (filter_type == PNG_INTRAPIXEL_DIFFERENCING) &&
+; ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) == 0) &&
+; (color_type == PNG_COLOR_TYPE_RGB ||
+; color_type == PNG_COLOR_TYPE_RGB_ALPHA)))
+; {
+ png_warning edi, 'Unknown filter method in IHDR'
+ inc ebx
+; }
+
+; if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) != 0)
+; {
+ png_warning edi, 'Invalid filter method in IHDR'
+ inc ebx
+; }
+; }
+
+else
+ cmp dword[filter_type],PNG_FILTER_TYPE_BASE
+ je @f ;if (..!=..)
+ png_warning edi, 'Unknown filter method in IHDR'
+ inc ebx
+ @@:
+end if
+
+ cmp ebx,0
+ je @f
+ png_error edi, 'Invalid IHDR data'
+ @@:
+ ret
+endp
+
+;#if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED)
+; ASCII to fp functions
+; Check an ASCII formated floating point value, see the more detailed
+; comments in pngpriv.inc
+
+; The following is used internally to preserve the sticky flags */
+;#define png_fp_add(state, flags) ((state) |= (flags))
+;#define png_fp_set(state, value) ((state) = (value) | ((state) & PNG_FP_STICKY))
+
+;int (charp string, png_size_t size, int *statep, png_size_tp whereami)
+align 4
+proc png_check_fp_number, string:dword, size:dword, statep:dword, whereami:dword
+; int state = *statep;
+; png_size_t i = *whereami;
+
+; while (i < size)
+; {
+; int type;
+ ; First find the type of the next character
+; switch (string[i])
+; {
+; case 43: type = PNG_FP_SAW_SIGN; break;
+; case 45: type = PNG_FP_SAW_SIGN + PNG_FP_NEGATIVE; break;
+; case 46: type = PNG_FP_SAW_DOT; break;
+; case 48: type = PNG_FP_SAW_DIGIT; break;
+; case 49: case 50: case 51: case 52:
+; case 53: case 54: case 55: case 56:
+; case 57: type = PNG_FP_SAW_DIGIT + PNG_FP_NONZERO; break;
+; case 69:
+; case 101: type = PNG_FP_SAW_E; break;
+; default: goto PNG_FP_End;
+; }
+
+ ; Now deal with this type according to the current
+ ; state, the type is arranged to not overlap the
+ ; bits of the PNG_FP_STATE.
+
+; switch ((state & PNG_FP_STATE) + (type & PNG_FP_SAW_ANY))
+; {
+; case PNG_FP_INTEGER + PNG_FP_SAW_SIGN:
+; if ((state & PNG_FP_SAW_ANY) != 0)
+; goto PNG_FP_End; /* not a part of the number */
+
+; png_fp_add(state, type);
+; break;
+
+; case PNG_FP_INTEGER + PNG_FP_SAW_DOT:
+ ; Ok as trailer, ok as lead of fraction.
+; if ((state & PNG_FP_SAW_DOT) != 0) /* two dots */
+; goto PNG_FP_End;
+
+; else if ((state & PNG_FP_SAW_DIGIT) != 0) /* trailing dot? */
+; png_fp_add(state, type);
+
+; else
+; png_fp_set(state, PNG_FP_FRACTION | type);
+
+; break;
+
+; case PNG_FP_INTEGER + PNG_FP_SAW_DIGIT:
+; if ((state & PNG_FP_SAW_DOT) != 0) /* delayed fraction */
+; png_fp_set(state, PNG_FP_FRACTION | PNG_FP_SAW_DOT);
+
+; png_fp_add(state, type | PNG_FP_WAS_VALID);
+
+; break;
+
+; case PNG_FP_INTEGER + PNG_FP_SAW_E:
+; if ((state & PNG_FP_SAW_DIGIT) == 0)
+; goto PNG_FP_End;
+
+; png_fp_set(state, PNG_FP_EXPONENT);
+
+; break;
+
+; /* case PNG_FP_FRACTION + PNG_FP_SAW_SIGN: goto PNG_FP_End; ** no sign in fraction */
+
+; /* case PNG_FP_FRACTION + PNG_FP_SAW_DOT: goto PNG_FP_End; ** Because SAW_DOT is always set */
+
+; case PNG_FP_FRACTION + PNG_FP_SAW_DIGIT:
+; png_fp_add(state, type | PNG_FP_WAS_VALID);
+; break;
+
+; case PNG_FP_FRACTION + PNG_FP_SAW_E:
+ ; This is correct because the trailing '.' on an
+ ; integer is handled above - so we can only get here
+ ; with the sequence ".E" (with no preceding digits).
+
+; if ((state & PNG_FP_SAW_DIGIT) == 0)
+; goto PNG_FP_End;
+
+; png_fp_set(state, PNG_FP_EXPONENT);
+
+; break;
+
+; case PNG_FP_EXPONENT + PNG_FP_SAW_SIGN:
+; if ((state & PNG_FP_SAW_ANY) != 0)
+; goto PNG_FP_End; /* not a part of the number */
+
+; png_fp_add(state, PNG_FP_SAW_SIGN);
+
+; break;
+
+; /* case PNG_FP_EXPONENT + PNG_FP_SAW_DOT: goto PNG_FP_End; */
+
+; case PNG_FP_EXPONENT + PNG_FP_SAW_DIGIT:
+; png_fp_add(state, PNG_FP_SAW_DIGIT | PNG_FP_WAS_VALID);
+
+; break;
+
+; /* case PNG_FP_EXPONEXT + PNG_FP_SAW_E: goto PNG_FP_End; */
+
+; default: goto PNG_FP_End; /* I.e. break 2 */
+; }
+
+ ; The character seems ok, continue.
+; ++i;
+; }
+;
+;PNG_FP_End:
+ ; Here at the end, update the state and return the correct
+ ; return code.
+
+; *statep = state;
+; *whereami = i;
+
+; return (state & PNG_FP_SAW_DIGIT) != 0;
+ ret
+endp
+
+
+; The same but for a complete string.
+;int (charp string, png_size_t size)
+align 4
+proc png_check_fp_string, string:dword, size:dword
+; int state=0;
+; png_size_t char_index=0;
+;
+; if (png_check_fp_number(string, size, &state, &char_index) != 0 &&
+; (char_index == size || string[char_index] == 0))
+; return state /* must be non-zero - see above */;
+
+; return 0; /* i.e. fail */
+ ret
+endp
+;end if /* pCAL || sCAL */
+
+;if PNG_sCAL_SUPPORTED
+;# ifdef PNG_FLOATING_POINT_SUPPORTED
+; Utility used below - a simple accurate power of ten from an integral
+; exponent.
+
+;double (int power)
+align 4
+proc png_pow10, power:dword
+; int recip = 0;
+; double d = 1;
+
+ ; Handle negative exponent with a reciprocal at the end because
+ ; 10 is exact whereas .1 is inexact in base 2
+
+; if (power < 0)
+; {
+; if (power < DBL_MIN_10_EXP) return 0;
+; recip = 1, power = -power;
+; }
+
+; if (power > 0)
+; {
+ ; Decompose power bitwise.
+; double mult = 10;
+; do
+; {
+; if (power & 1) d *= mult;
+; mult *= mult;
+; power >>= 1;
+; }
+; while (power > 0);
+
+; if (recip != 0) d = 1/d;
+; }
+ ; else power is 0 and d is 1
+
+; return d;
+ ret
+endp
+
+; Function to format a floating point value in ASCII with a given
+; precision.
+
+;void (png_structrp png_ptr, charp ascii, png_size_t size,
+; double fp, uint precision)
+align 4
+proc png_ascii_from_fp, png_ptr:dword, ascii:dword, size:dword, fp:dword, precision:dword
+ ; We use standard functions from math.h, but not printf because
+ ; that would require stdio. The caller must supply a buffer of
+ ; sufficient size or we will png_error. The tests on size and
+ ; the space in ascii[] consumed are indicated below.
+
+; if (precision < 1)
+; precision = DBL_DIG;
+
+ ; Enforce the limit of the implementation precision too.
+; if (precision > DBL_DIG+1)
+; precision = DBL_DIG+1;
+
+ ; Basic sanity checks
+; if (size >= precision+5) /* See the requirements below. */
+; {
+; if (fp < 0)
+; {
+; fp = -fp;
+; *ascii++ = 45; /* '-' PLUS 1 TOTAL 1 */
+; --size;
+; }
+
+; if (fp >= DBL_MIN && fp <= DBL_MAX)
+; {
+; int exp_b10; /* A base 10 exponent */
+; double base; /* 10^exp_b10 */
+
+ ; First extract a base 10 exponent of the number,
+ ; the calculation below rounds down when converting
+ ; from base 2 to base 10 (multiply by log10(2) -
+ ; 0.3010, but 77/256 is 0.3008, so exp_b10 needs to
+ ; be increased. Note that the arithmetic shift
+ ; performs a floor() unlike C arithmetic - using a
+ ; C multiply would break the following for negative
+ ; exponents.
+
+; (void)frexp(fp, &exp_b10); /* exponent to base 2 */
+
+; exp_b10 = (exp_b10 * 77) >> 8; /* <= exponent to base 10 */
+
+; /* Avoid underflow here. */
+; base = png_pow10(exp_b10); /* May underflow */
+
+; while (base < DBL_MIN || base < fp)
+; {
+; /* And this may overflow. */
+; double test = png_pow10(exp_b10+1);
+
+; if (test <= DBL_MAX)
+; ++exp_b10, base = test;
+
+; else
+; break;
+; }
+
+ ; Normalize fp and correct exp_b10, after this fp is in the
+ ; range [.1,1) and exp_b10 is both the exponent and the digit
+ ; *before* which the decimal point should be inserted
+ ; (starting with 0 for the first digit). Note that this
+ ; works even if 10^exp_b10 is out of range because of the
+ ; test on DBL_MAX above.
+
+; fp /= base;
+; while (fp >= 1) fp /= 10, ++exp_b10;
+
+ ; Because of the code above fp may, at this point, be
+ ; less than .1, this is ok because the code below can
+ ; handle the leading zeros this generates, so no attempt
+ ; is made to correct that here.
+
+; {
+; uint czero, clead, cdigits;
+; char exponent[10];
+
+ ; Allow up to two leading zeros - this will not lengthen
+ ; the number compared to using E-n.
+
+; if (exp_b10 < 0 && exp_b10 > -3) /* PLUS 3 TOTAL 4 */
+; {
+; czero = -exp_b10; /* PLUS 2 digits: TOTAL 3 */
+; exp_b10 = 0; /* Dot added below before first output. */
+; }
+; else
+; czero = 0; /* No zeros to add */
+
+ ; Generate the digit list, stripping trailing zeros and
+ ; inserting a '.' before a digit if the exponent is 0.
+
+; clead = czero; /* Count of leading zeros */
+; cdigits = 0; /* Count of digits in list. */
+
+; do
+; {
+; double d;
+
+; fp *= 10;
+ ; Use modf here, not floor and subtract, so that
+ ; the separation is done in one step. At the end
+ ; of the loop don't break the number into parts so
+ ; that the final digit is rounded.
+
+; if (cdigits+czero+1 < precision+clead)
+; fp = modf(fp, &d);
+
+; else
+; {
+; d = floor(fp + .5);
+
+; if (d > 9)
+; {
+; /* Rounding up to 10, handle that here. */
+; if (czero > 0)
+; {
+; --czero, d = 1;
+; if (cdigits == 0) --clead;
+; }
+; else
+; {
+; while (cdigits > 0 && d > 9)
+; {
+; int ch = *--ascii;
+
+; if (exp_b10 != (-1))
+; ++exp_b10;
+
+; else if (ch == 46)
+; {
+; ch = *--ascii, ++size;
+; /* Advance exp_b10 to '1', so that the
+; * decimal point happens after the
+; * previous digit.
+
+; exp_b10 = 1;
+; }
+
+; --cdigits;
+; d = ch - 47; /* I.e. 1+(ch-48) */
+; }
+
+; /* Did we reach the beginning? If so adjust the
+; * exponent but take into account the leading
+; * decimal point.
+
+; if (d > 9) /* cdigits == 0 */
+; {
+; if (exp_b10 == (-1))
+; {
+ ; Leading decimal point (plus zeros?), if
+ ; we lose the decimal point here it must
+ ; be reentered below.
+
+; int ch = *--ascii;
+
+; if (ch == 46)
+; ++size, exp_b10 = 1;
+
+; /* Else lost a leading zero, so 'exp_b10' is
+; * still ok at (-1)
+
+; }
+; else
+; ++exp_b10;
+
+; /* In all cases we output a '1' */
+; d = 1;
+; }
+; }
+; }
+; fp = 0; /* Guarantees termination below. */
+; }
+
+; if (d == 0)
+; {
+; ++czero;
+; if (cdigits == 0) ++clead;
+; }
+; else
+; {
+; /* Included embedded zeros in the digit count. */
+; cdigits += czero - clead;
+; clead = 0;
+
+; while (czero > 0)
+; {
+ ; exp_b10 == (-1) means we just output the decimal
+ ; place - after the DP don't adjust 'exp_b10' any
+ ; more!
+
+; if (exp_b10 != (-1))
+; {
+; if (exp_b10 == 0) *ascii++ = 46, --size;
+; /* PLUS 1: TOTAL 4 */
+; --exp_b10;
+; }
+; *ascii++ = 48, --czero;
+; }
+
+; if (exp_b10 != (-1))
+; {
+; if (exp_b10 == 0)
+; *ascii++ = 46, --size; /* counted above */
+
+; --exp_b10;
+; }
+; *ascii++ = (char)(48 + (int)d), ++cdigits;
+; }
+; }
+; while (cdigits+czero < precision+clead && fp > DBL_MIN);
+
+; /* The total output count (max) is now 4+precision */
+
+ ; Check for an exponent, if we don't need one we are
+ ; done and just need to terminate the string. At
+ ; this point exp_b10==(-1) is effectively if flag - it got
+ ; to '-1' because of the decrement after outputting
+ ; the decimal point above (the exponent required is
+ ; *not* -1!)
+
+; if (exp_b10 >= (-1) && exp_b10 <= 2)
+; {
+ ; The following only happens if we didn't output the
+ ; leading zeros above for negative exponent, so this
+ ; doesn't add to the digit requirement. Note that the
+ ; two zeros here can only be output if the two leading
+ ; zeros were *not* output, so this doesn't increase
+ ; the output count.
+
+; while (--exp_b10 >= 0) *ascii++ = 48;
+
+; *ascii = 0;
+
+; /* Total buffer requirement (including the '\0') is
+ ; 5+precision - see check at the start.
+
+; return;
+; }
+
+ ; Here if an exponent is required, adjust size for
+ ; the digits we output but did not count. The total
+ ; digit output here so far is at most 1+precision - no
+ ; decimal point and no leading or trailing zeros have
+ ; been output.
+
+; size -= cdigits;
+;
+; *ascii++ = 69, --size; /* 'E': PLUS 1 TOTAL 2+precision */
+
+ ; The following use of an unsigned temporary avoids ambiguities in
+ ; the signed arithmetic on exp_b10 and permits GCC at least to do
+ ; better optimization.
+
+; {
+; uint uexp_b10;
+
+; if (exp_b10 < 0)
+; {
+; *ascii++ = 45, --size; /* '-': PLUS 1 TOTAL 3+precision */
+; uexp_b10 = -exp_b10;
+; }
+
+; else
+; uexp_b10 = exp_b10;
+
+; cdigits = 0;
+
+; while (uexp_b10 > 0)
+; {
+; exponent[cdigits++] = (char)(48 + uexp_b10 % 10);
+; uexp_b10 /= 10;
+; }
+; }
+
+ ; Need another size check here for the exponent digits, so
+ ; this need not be considered above.
+
+; if (size > cdigits)
+; {
+; while (cdigits > 0) *ascii++ = exponent[--cdigits];
+
+; *ascii = 0;
+
+; return;
+; }
+; }
+; }
+; else if (!(fp >= DBL_MIN))
+; {
+; *ascii++ = 48; /* '0' */
+; *ascii = 0;
+; return;
+; }
+; else
+; {
+; *ascii++ = 105; /* 'i' */
+; *ascii++ = 110; /* 'n' */
+; *ascii++ = 102; /* 'f' */
+; *ascii = 0;
+; return;
+; }
+; }
+
+ ; Here on buffer too small.
+; png_error(png_ptr, "ASCII conversion buffer too small");
+ ret
+endp
+
+;# endif /* FLOATING_POINT */
+
+; Function to format a fixed point value in ASCII.
+
+;void (png_structrp png_ptr, charp ascii, png_size_t size, png_fixed_point fp)
+align 4
+proc png_ascii_from_fixed, png_ptr:dword, ascii:dword, size:dword, fp:dword
+ ; Require space for 10 decimal digits, a decimal point, a minus sign and a
+ ; trailing \0, 13 characters:
+
+ cmp dword[size],12
+ jle .end0 ;if (..>..)
+; uint_32 num;
+
+ ; Avoid overflow here on the minimum integer.
+; if (fp < 0)
+; *ascii++ = 45, num = -fp;
+; else
+; num = fp;
+
+; if (num <= 0x80000000) /* else overflowed */
+; {
+; uint ndigits = 0, first = 16 /* flag value */;
+; char digits[10];
+
+; while (num)
+; {
+ ; Split the low digit off num:
+; uint tmp = num/10;
+; num -= tmp*10;
+; digits[ndigits++] = (char)(48 + num);
+ ; Record the first non-zero digit, note that this is a number
+ ; starting at 1, it's not actually the array index.
+
+; if (first == 16 && num > 0)
+; first = ndigits;
+; num = tmp;
+; }
+
+; if (ndigits > 0)
+; {
+; while (ndigits > 5) *ascii++ = digits[--ndigits];
+ ; The remaining digits are fractional digits, ndigits is '5' or
+ ; smaller at this point. It is certainly not zero. Check for a
+ ; non-zero fractional digit:
+
+; if (first <= 5)
+; {
+; uint i;
+; *ascii++ = 46; /* decimal point */
+ ; ndigits may be <5 for small numbers, output leading zeros
+ ; then ndigits digits to first:
+
+; i = 5;
+; while (ndigits < i) *ascii++ = 48, --i;
+; while (ndigits >= first) *ascii++ = digits[--ndigits];
+ ; Don't output the trailing zeros!
+; }
+; }
+; else
+; *ascii++ = 48;
+
+ ; And null terminate the string:
+; *ascii = 0;
+; return;
+; }
+ .end0:
+
+ ; Here on buffer too small.
+ png_error [png_ptr], 'ASCII conversion buffer too small'
+ ret
+endp
+;end if /* SCAL */
+
+;png_fixed_point (png_structrp png_ptr, double fp, charp text)
+align 4
+proc png_fixed, png_ptr:dword, fp:dword, text:dword
+; double r = floor(100000 * fp + .5);
+
+; if (r > 2147483647. || r < -2147483648.)
+; png_fixed_error(png_ptr, text);
+
+; return (png_fixed_point)r;
+ ret
+endp
+
+; muldiv functions
+; This API takes signed arguments and rounds the result to the nearest
+; integer (or, for a fixed point number - the standard argument - to
+; the nearest .00001). Overflow and divide by zero are signalled in
+; the result, a boolean - true on success, false on overflow.
+
+;int (png_fixed_point_p res, png_fixed_point a, int_32 times, int_32 divisor)
+align 4
+proc png_muldiv, res:dword, a:dword, p3times:dword, divisor:dword
+ ; Return a * times / divisor, rounded.
+; if (divisor != 0)
+; {
+; if (a == 0 || p3times == 0)
+; {
+; *res = 0;
+; return 1;
+; }
+; else
+; {
+if PNG_FLOATING_ARITHMETIC_SUPPORTED eq 1
+; double r = a;
+; r *= p3times;
+; r /= divisor;
+; r = floor(r+.5);
+
+; /* A png_fixed_point is a 32-bit integer. */
+; if (r <= 2147483647. && r >= -2147483648.)
+; {
+; *res = (png_fixed_point)r;
+; return 1;
+; }
+else
+; int negative = 0;
+; uint_32 A, T, D;
+; uint_32 s16, s32, s00;
+
+; if (a < 0)
+; negative = 1, A = -a;
+; else
+; A = a;
+
+; if (p3times < 0)
+; negative = !negative, T = -p3times;
+; else
+; T = p3times;
+
+; if (divisor < 0)
+; negative = !negative, D = -divisor;
+; else
+; D = divisor;
+
+ ; Following can't overflow because the arguments only
+ ; have 31 bits each, however the result may be 32 bits.
+
+; s16 = (A >> 16) * (T & 0xffff) +
+; (A & 0xffff) * (T >> 16);
+ ; Can't overflow because the a*times bit is only 30
+ ; bits at most.
+
+; s32 = (A >> 16) * (T >> 16) + (s16 >> 16);
+; s00 = (A & 0xffff) * (T & 0xffff);
+
+; s16 = (s16 & 0xffff) << 16;
+; s00 += s16;
+
+; if (s00 < s16)
+; ++s32; /* carry */
+
+; if (s32 < D) /* else overflow */
+; {
+ ; s32.s00 is now the 64-bit product, do a standard
+ ; division, we know that s32 < D, so the maximum
+ ; required shift is 31.
+
+; int bitshift = 32;
+; png_fixed_point result = 0; /* NOTE: signed */
+
+; while (--bitshift >= 0)
+; {
+; uint_32 d32, d00;
+
+; if (bitshift > 0)
+; d32 = D >> (32-bitshift), d00 = D << bitshift;
+
+; else
+; d32 = 0, d00 = D;
+
+; if (s32 > d32)
+; {
+; if (s00 < d00) --s32; /* carry */
+; s32 -= d32, s00 -= d00, result += 1<= d00)
+; s32 = 0, s00 -= d00, result += 1<= (D >> 1))
+; ++result;
+
+; if (negative != 0)
+; result = -result;
+
+; /* Check for overflow. */
+; if ((negative != 0 && result <= 0) ||
+; (negative == 0 && result >= 0))
+; {
+; *res = result;
+; return 1;
+; }
+; }
+end if
+; }
+; }
+
+ xor eax,eax
+ ret
+endp
+
+; The following is for when the caller doesn't much care about the
+; result.
+
+;png_fixed_point (png_structrp png_ptr, png_fixed_point a, int_32 times,
+; int_32 divisor)
+align 4
+proc png_muldiv_warn, png_ptr:dword, a:dword, p3times:dword, divisor:dword
+; png_fixed_point result;
+
+; if (png_muldiv(&result, a, p3times, divisor) != 0)
+; return result;
+
+ png_warning [png_ptr], 'fixed point overflow ignored'
+ xor eax,eax
+ ret
+endp
+
+; Calculate a reciprocal, return 0 on div-by-zero or overflow.
+;png_fixed_point (png_fixed_point a)
+align 4
+proc png_reciprocal, a:dword
+if PNG_FLOATING_ARITHMETIC_SUPPORTED eq 1
+; double r = floor(1E10/a+.5);
+
+; if (r <= 2147483647. && r >= -2147483648.)
+; return (png_fixed_point)r;
+else
+; png_fixed_point res;
+
+; if (png_muldiv(&res, 100000, 100000, a) != 0)
+; return res;
+end if
+
+; return 0; /* error/overflow */
+ ret
+endp
+
+; This is the shared test on whether a gamma value is 'significant' - whether
+; it is worth doing gamma correction.
+
+;int (png_fixed_point gamma_val)
+align 4
+proc png_gamma_significant, gamma_val:dword
+; return gamma_val < PNG_FP_1 - PNG_GAMMA_THRESHOLD_FIXED ||
+; gamma_val > PNG_FP_1 + PNG_GAMMA_THRESHOLD_FIXED;
+ ret
+endp
+
+;if PNG_READ_GAMMA_SUPPORTED
+; A local convenience routine.
+;png_fixed_point (png_fixed_point a, png_fixed_point b)
+align 4
+proc png_product2, a:dword, b:dword
+ ; The required result is 1/a * 1/b; the following preserves accuracy.
+if PNG_FLOATING_ARITHMETIC_SUPPORTED eq 1
+; double r = a * 1E-5;
+; r *= b;
+; r = floor(r+.5);
+
+; if (r <= 2147483647. && r >= -2147483648.)
+; return (png_fixed_point)r;
+else
+; png_fixed_point res;
+
+; if (png_muldiv(&res, a, b, 100000) != 0)
+; return res;
+end if
+
+; return 0; /* overflow */
+ ret
+endp
+
+; The inverse of the above.
+;png_fixed_point (png_fixed_point a, png_fixed_point b)
+align 4
+proc png_reciprocal2, a:dword, b:dword
+ ; The required result is 1/a * 1/b; the following preserves accuracy.
+if PNG_FLOATING_ARITHMETIC_SUPPORTED eq 1
+; if (a != 0 && b != 0)
+; {
+; double r = 1E15/a;
+; r /= b;
+; r = floor(r+.5);
+;
+; if (r <= 2147483647. && r >= -2147483648.)
+; return (png_fixed_point)r;
+; }
+else
+ ; This may overflow because the range of png_fixed_point isn't symmetric,
+ ; but this API is only used for the product of file and screen gamma so it
+ ; doesn't matter that the smallest number it can produce is 1/21474, not
+ ; 1/100000
+
+; png_fixed_point res = png_product2(a, b);
+
+; if (res != 0)
+; return png_reciprocal(res);
+end if
+
+; return 0; /* overflow */
+ ret
+endp
+;end if /* READ_GAMMA */
+
+;if PNG_READ_GAMMA_SUPPORTED /* gamma table code */
+;#ifndef PNG_FLOATING_ARITHMETIC_SUPPORTED
+; Fixed point gamma.
+
+; The code to calculate the tables used below can be found in the shell script
+; contrib/tools/intgamma.sh
+
+; To calculate gamma this code implements fast log() and exp() calls using only
+; fixed point arithmetic. This code has sufficient precision for either 8-bit
+; or 16-bit sample values.
+
+; The tables used here were calculated using simple 'bc' programs, but C double
+; precision floating point arithmetic would work fine.
+
+; 8-bit log table
+; This is a table of -log(value/255)/log(2) for 'value' in the range 128 to
+; 255, so it's the base 2 logarithm of a normalized 8-bit floating point
+; mantissa. The numbers are 32-bit fractions.
+
+;const uint_32
+;png_8bit_l2[128] =
+; 4270715492U, 4222494797U, 4174646467U, 4127164793U, 4080044201U, 4033279239U,
+; 3986864580U, 3940795015U, 3895065449U, 3849670902U, 3804606499U, 3759867474U,
+; 3715449162U, 3671346997U, 3627556511U, 3584073329U, 3540893168U, 3498011834U,
+; 3455425220U, 3413129301U, 3371120137U, 3329393864U, 3287946700U, 3246774933U,
+; 3205874930U, 3165243125U, 3124876025U, 3084770202U, 3044922296U, 3005329011U,
+; 2965987113U, 2926893432U, 2888044853U, 2849438323U, 2811070844U, 2772939474U,
+; 2735041326U, 2697373562U, 2659933400U, 2622718104U, 2585724991U, 2548951424U,
+; 2512394810U, 2476052606U, 2439922311U, 2404001468U, 2368287663U, 2332778523U,
+; 2297471715U, 2262364947U, 2227455964U, 2192742551U, 2158222529U, 2123893754U,
+; 2089754119U, 2055801552U, 2022034013U, 1988449497U, 1955046031U, 1921821672U,
+; 1888774511U, 1855902668U, 1823204291U, 1790677560U, 1758320682U, 1726131893U,
+; 1694109454U, 1662251657U, 1630556815U, 1599023271U, 1567649391U, 1536433567U,
+; 1505374214U, 1474469770U, 1443718700U, 1413119487U, 1382670639U, 1352370686U,
+; 1322218179U, 1292211689U, 1262349810U, 1232631153U, 1203054352U, 1173618059U,
+; 1144320946U, 1115161701U, 1086139034U, 1057251672U, 1028498358U, 999877854U,
+; 971388940U, 943030410U, 914801076U, 886699767U, 858725327U, 830876614U,
+; 803152505U, 775551890U, 748073672U, 720716771U, 693480120U, 666362667U,
+; 639363374U, 612481215U, 585715177U, 559064263U, 532527486U, 506103872U,
+; 479792461U, 453592303U, 427502463U, 401522014U, 375650043U, 349885648U,
+; 324227938U, 298676034U, 273229066U, 247886176U, 222646516U, 197509248U,
+; 172473545U, 147538590U, 122703574U, 97967701U, 73330182U, 48790236U,
+; 24347096U, 0U
+
+if 0
+ ; The following are the values for 16-bit tables - these work fine for the
+ ; 8-bit conversions but produce very slightly larger errors in the 16-bit
+ ; log (about 1.2 as opposed to 0.7 absolute error in the final value). To
+ ; use these all the shifts below must be adjusted appropriately.
+
+; 65166, 64430, 63700, 62976, 62257, 61543, 60835, 60132, 59434, 58741, 58054,
+; 57371, 56693, 56020, 55352, 54689, 54030, 53375, 52726, 52080, 51439, 50803,
+; 50170, 49542, 48918, 48298, 47682, 47070, 46462, 45858, 45257, 44661, 44068,
+; 43479, 42894, 42312, 41733, 41159, 40587, 40020, 39455, 38894, 38336, 37782,
+; 37230, 36682, 36137, 35595, 35057, 34521, 33988, 33459, 32932, 32408, 31887,
+; 31369, 30854, 30341, 29832, 29325, 28820, 28319, 27820, 27324, 26830, 26339,
+; 25850, 25364, 24880, 24399, 23920, 23444, 22970, 22499, 22029, 21562, 21098,
+; 20636, 20175, 19718, 19262, 18808, 18357, 17908, 17461, 17016, 16573, 16132,
+; 15694, 15257, 14822, 14390, 13959, 13530, 13103, 12678, 12255, 11834, 11415,
+; 10997, 10582, 10168, 9756, 9346, 8937, 8531, 8126, 7723, 7321, 6921, 6523,
+; 6127, 5732, 5339, 4947, 4557, 4169, 3782, 3397, 3014, 2632, 2251, 1872, 1495,
+; 1119, 744, 372
+end if
+
+;int_32 (uint x)
+align 4
+proc png_log8bit, x:dword
+; uint lg2 = 0;
+ ; Each time 'x' is multiplied by 2, 1 must be subtracted off the final log,
+ ; because the log is actually negate that means adding 1. The final
+ ; returned value thus has the range 0 (for 255 input) to 7.994 (for 1
+ ; input), return -1 for the overflow (log 0) case, - so the result is
+ ; always at most 19 bits.
+
+; if ((x &= 0xff) == 0)
+; return -1;
+
+; if ((x & 0xf0) == 0)
+; lg2 = 4, x <<= 4;
+
+; if ((x & 0xc0) == 0)
+; lg2 += 2, x <<= 2;
+
+; if ((x & 0x80) == 0)
+; lg2 += 1, x <<= 1;
+
+ ; result is at most 19 bits, so this cast is safe:
+; return (int_32)((lg2 << 16) + ((png_8bit_l2[x-128]+32768)>>16));
+ ret
+endp
+
+; The above gives exact (to 16 binary places) log2 values for 8-bit images,
+; for 16-bit images we use the most significant 8 bits of the 16-bit value to
+; get an approximation then multiply the approximation by a correction factor
+; determined by the remaining up to 8 bits. This requires an additional step
+; in the 16-bit case.
+
+; We want log2(value/65535), we have log2(v'/255), where:
+
+; value = v' * 256 + v''
+; = v' * f
+
+; So f is value/v', which is equal to (256+v''/v') since v' is in the range 128
+; to 255 and v'' is in the range 0 to 255 f will be in the range 256 to less
+; than 258. The final factor also needs to correct for the fact that our 8-bit
+; value is scaled by 255, whereas the 16-bit values must be scaled by 65535.
+
+; This gives a final formula using a calculated value 'x' which is value/v' and
+; scaling by 65536 to match the above table:
+
+; log2(x/257) * 65536
+
+; Since these numbers are so close to '1' we can use simple linear
+; interpolation between the two end values 256/257 (result -368.61) and 258/257
+; (result 367.179). The values used below are scaled by a further 64 to give
+; 16-bit precision in the interpolation:
+
+; Start (256): -23591
+; Zero (257): 0
+; End (258): 23499
+
+;int_32 (uint_32 x)
+align 4
+proc png_log16bit, x:dword
+; uint lg2 = 0;
+
+ ; As above, but now the input has 16 bits.
+; if ((x &= 0xffff) == 0)
+; return -1;
+
+; if ((x & 0xff00) == 0)
+; lg2 = 8, x <<= 8;
+
+; if ((x & 0xf000) == 0)
+; lg2 += 4, x <<= 4;
+
+; if ((x & 0xc000) == 0)
+; lg2 += 2, x <<= 2;
+
+; if ((x & 0x8000) == 0)
+; lg2 += 1, x <<= 1;
+
+ ; Calculate the base logarithm from the top 8 bits as a 28-bit fractional
+ ; value.
+
+; lg2 <<= 28;
+; lg2 += (png_8bit_l2[(x>>8)-128]+8) >> 4;
+
+ ; Now we need to interpolate the factor, this requires a division by the top
+ ; 8 bits. Do this with maximum precision.
+
+; x = ((x << 16) + (x >> 9)) / (x >> 8);
+
+ ; Since we divided by the top 8 bits of 'x' there will be a '1' at 1<<24,
+ ; the value at 1<<16 (ignoring this) will be 0 or 1; this gives us exactly
+ ; 16 bits to interpolate to get the low bits of the result. Round the
+ ; answer. Note that the end point values are scaled by 64 to retain overall
+ ; precision and that 'lg2' is current scaled by an extra 12 bits, so adjust
+ ; the overall scaling by 6-12. Round at every step.
+
+; x -= 1U << 24;
+
+; if (x <= 65536U) /* <= '257' */
+; lg2 += ((23591U * (65536U-x)) + (1U << (16+6-12-1))) >> (16+6-12);
+
+; else
+; lg2 -= ((23499U * (x-65536U)) + (1U << (16+6-12-1))) >> (16+6-12);
+
+ ; Safe, because the result can't have more than 20 bits:
+; return (int_32)((lg2 + 2048) >> 12);
+ ret
+endp
+
+; The 'exp()' case must invert the above, taking a 20-bit fixed point
+; logarithmic value and returning a 16 or 8-bit number as appropriate. In
+; each case only the low 16 bits are relevant - the fraction - since the
+; integer bits (the top 4) simply determine a shift.
+
+; The worst case is the 16-bit distinction between 65535 and 65534. This
+; requires perhaps spurious accuracy in the decoding of the logarithm to
+; distinguish log2(65535/65534.5) - 10^-5 or 17 bits. There is little chance
+; of getting this accuracy in practice.
+
+; To deal with this the following exp() function works out the exponent of the
+; frational part of the logarithm by using an accurate 32-bit value from the
+; top four fractional bits then multiplying in the remaining bits.
+
+; NOTE: the first entry is deliberately set to the maximum 32-bit value.
+align 4
+png_32bit_exp dd 4294967295, 4112874773, 3938502376, 3771522796, 3611622603, 3458501653,\
+ 3311872529, 3171459999, 3037000500, 2908241642, 2784941738, 2666869345,\
+ 2553802834, 2445529972, 2341847524, 2242560872
+
+; Adjustment table; provided to explain the numbers in the code below.
+;#if 0
+;for (i=11;i>=0;--i){ print i, " ", (1 - e(-(2^i)/65536*l(2))) * 2^(32-i), "\n"}
+; 11 44937.64284865548751208448
+; 10 45180.98734845585101160448
+; 9 45303.31936980687359311872
+; 8 45364.65110595323018870784
+; 7 45395.35850361789624614912
+; 6 45410.72259715102037508096
+; 5 45418.40724413220722311168
+; 4 45422.25021786898173001728
+; 3 45424.17186732298419044352
+; 2 45425.13273269940811464704
+; 1 45425.61317555035558641664
+; 0 45425.85339951654943850496
+;end if
+
+;uint_32 (png_fixed_point x)
+align 4
+proc png_exp, x:dword
+; if (x > 0 && x <= 0xfffff) /* Else overflow or zero (underflow) */
+; {
+ ; Obtain a 4-bit approximation
+; uint_32 e = png_32bit_exp[(x >> 12) & 0x0f];
+
+ ; Incorporate the low 12 bits - these decrease the returned value by
+ ; multiplying by a number less than 1 if the bit is set. The multiplier
+ ; is determined by the above table and the shift. Notice that the values
+ ; converge on 45426 and this is used to allow linear interpolation of the
+ ; low bits.
+
+; if (x & 0x800)
+; e -= (((e >> 16) * 44938U) + 16U) >> 5;
+
+; if (x & 0x400)
+; e -= (((e >> 16) * 45181U) + 32U) >> 6;
+
+; if (x & 0x200)
+; e -= (((e >> 16) * 45303U) + 64U) >> 7;
+
+; if (x & 0x100)
+; e -= (((e >> 16) * 45365U) + 128U) >> 8;
+
+; if (x & 0x080)
+; e -= (((e >> 16) * 45395U) + 256U) >> 9;
+
+; if (x & 0x040)
+; e -= (((e >> 16) * 45410U) + 512U) >> 10;
+
+ ; And handle the low 6 bits in a single block.
+; e -= (((e >> 16) * 355U * (x & 0x3fU)) + 256U) >> 9;
+
+ ; Handle the upper bits of x.
+; e >>= x >> 16;
+; return e;
+; }
+
+ ; Check for overflow
+; if (x <= 0)
+; return png_32bit_exp[0];
+
+ ; Else underflow
+; return 0;
+ ret
+endp
+
+;byte (png_fixed_point lg2)
+align 4
+proc png_exp8bit, lg2:dword
+ ; Get a 32-bit value:
+; uint_32 x = png_exp(lg2);
+
+ ; Convert the 32-bit value to 0..255 by multiplying by 256-1. Note that the
+ ; second, rounding, step can't overflow because of the first, subtraction,
+ ; step.
+
+; x -= x >> 8;
+; return (byte)(((x + 0x7fffffU) >> 24) & 0xff);
+ ret
+endp
+
+;uint_16 (png_fixed_point lg2)
+align 4
+proc png_exp16bit, lg2:dword
+ ; Get a 32-bit value:
+; uint_32 x = png_exp(lg2);
+
+ ; Convert the 32-bit value to 0..65535 by multiplying by 65536-1:
+; x -= x >> 16;
+; return (uint_16)((x + 32767U) >> 16);
+ ret
+endp
+;end if /* FLOATING_ARITHMETIC */
+
+;byte (uint value, png_fixed_point gamma_val)
+align 4
+proc png_gamma_8bit_correct, value:dword, gamma_val:dword
+; if (value > 0 && value < 255)
+; {
+if PNG_FLOATING_ARITHMETIC_SUPPORTED eq 1
+ ; 'value' is unsigned, ANSI-C90 requires the compiler to correctly
+ ; convert this to a floating point value. This includes values that
+ ; would overflow if 'value' were to be converted to 'int'.
+
+ ; Apparently GCC, however, does an intermediate conversion to (int)
+ ; on some (ARM) but not all (x86) platforms, possibly because of
+ ; hardware FP limitations. (E.g. if the hardware conversion always
+ ; assumes the integer register contains a signed value.) This results
+ ; in ANSI-C undefined behavior for large values.
+
+ ; Other implementations on the same machine might actually be ANSI-C90
+ ; conformant and therefore compile spurious extra code for the large
+ ; values.
+
+ ; We can be reasonably sure that an unsigned to float conversion
+ ; won't be faster than an int to float one. Therefore this code
+ ; assumes responsibility for the undefined behavior, which it knows
+ ; can't happen because of the check above.
+
+ ; Note the argument to this routine is an (uint) because, on
+ ; 16-bit platforms, it is assigned a value which might be out of
+ ; range for an (int); that would result in undefined behavior in the
+ ; caller if the *argument* ('value') were to be declared (int).
+
+; double r = floor(255*pow((int)/*SAFE*/value/255.,gamma_val*.00001)+.5);
+; return (byte)r;
+else
+; int_32 lg2 = png_log8bit(value);
+; png_fixed_point res;
+
+; if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1) != 0)
+; return png_exp8bit(res);
+
+ ; Overflow.
+; value = 0;
+end if
+; }
+
+; return (byte)(value & 0xff);
+ ret
+endp
+
+;uint_16 (uint value, png_fixed_point gamma_val)
+align 4
+proc png_gamma_16bit_correct, value:dword, gamma_val:dword
+; if (value > 0 && value < 65535)
+; {
+if PNG_FLOATING_ARITHMETIC_SUPPORTED eq 1
+ ; The same (uint)->(double) constraints apply here as above,
+ ; however in this case the (uint) to (int) conversion can
+ ; overflow on an ANSI-C90 compliant system so the cast needs to ensure
+ ; that this is not possible.
+
+; double r = floor(65535*pow((int_32)value/65535.,
+; gamma_val*.00001)+.5);
+; return (uint_16)r;
+else
+; int_32 lg2 = png_log16bit(value);
+; png_fixed_point res;
+
+; if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1) != 0)
+; return png_exp16bit(res);
+
+ ; Overflow.
+; value = 0;
+end if
+; }
+
+; return (uint_16)value;
+ ret
+endp
+
+; This does the right thing based on the bit_depth field of the
+; png_struct, interpreting values as 8-bit or 16-bit. While the result
+; is nominally a 16-bit value if bit depth is 8 then the result is
+; 8-bit (as are the arguments.)
+
+;uint_16 (png_structrp png_ptr, uint value, png_fixed_point gamma_val)
+align 4
+proc png_gamma_correct, png_ptr:dword, value:dword, gamma_val:dword
+; if (png_ptr->bit_depth == 8)
+; return png_gamma_8bit_correct(value, gamma_val);
+;
+if PNG_16BIT_SUPPORTED eq 1
+; else
+; return png_gamma_16bit_correct(value, gamma_val);
+else
+ ; should not reach this
+ xor eax,eax
+end if ;16BIT
+.end_f:
+ ret
+endp
+
+;if PNG_16BIT_SUPPORTED
+; Internal function to build a single 16-bit table - the table consists of
+; 'num' 256 entry subtables, where 'num' is determined by 'shift' - the amount
+; to shift the input values right (or 16-number_of_signifiant_bits).
+
+; The caller is responsible for ensuring that the table gets cleaned up on
+; png_error (i.e. if one of the mallocs below fails) - i.e. the *table argument
+; should be somewhere that will be cleaned.
+
+;void (png_structrp png_ptr, uint_16pp *ptable, uint shift, png_fixed_point gamma_val)
+align 4
+proc png_build_16bit_table, png_ptr:dword, ptable:dword, shift:dword, gamma_val:dword
+ ; Various values derived from 'shift':
+; uint num = 1U << (8U - shift);
+if PNG_FLOATING_ARITHMETIC_SUPPORTED eq 1
+ ; CSE the division and work round wacky GCC warnings (see the comments
+ ; in png_gamma_8bit_correct for where these come from.)
+
+; double fmax = 1./(((int_32)1 << (16U - shift))-1);
+end if
+; uint max = (1U << (16U - shift))-1U;
+; uint max_by_2 = 1U << (15U-shift);
+; uint i;
+
+; uint_16pp table = *ptable =
+; (uint_16pp)png_calloc(png_ptr, num * (sizeof (uint_16p)));
+
+; for (i = 0; i < num; i++)
+; {
+; uint_16p sub_table = table[i] =
+; (uint_16p)png_malloc(png_ptr, 256 * (sizeof (uint_16)));
+
+ ; The 'threshold' test is repeated here because it can arise for one of
+ ; the 16-bit tables even if the others don't hit it.
+
+; if (png_gamma_significant(gamma_val) != 0)
+; {
+ ; The old code would overflow at the end and this would cause the
+ ; 'pow' function to return a result >1, resulting in an
+ ; arithmetic error. This code follows the spec exactly; ig is
+ ; the recovered input sample, it always has 8-16 bits.
+
+ ; We want input * 65535/max, rounded, the arithmetic fits in 32
+ ; bits (unsigned) so long as max <= 32767.
+
+; uint j;
+; for (j = 0; j < 256; j++)
+; {
+; uint_32 ig = (j << (8-shift)) + i;
+if PNG_FLOATING_ARITHMETIC_SUPPORTED eq 1
+ ; Inline the 'max' scaling operation:
+ ; See png_gamma_8bit_correct for why the cast to (int) is
+ ; required here.
+
+; double d = floor(65535.*pow(ig*fmax, gamma_val*.00001)+.5);
+; sub_table[j] = (uint_16)d;
+else
+; if (shift != 0)
+; ig = (ig * 65535U + max_by_2)/max;
+;
+; sub_table[j] = png_gamma_16bit_correct(ig, gamma_val);
+end if
+; }
+; }
+; else
+; {
+ ; We must still build a table, but do it the fast way.
+; uint j;
+;
+; for (j = 0; j < 256; j++)
+; {
+; uint_32 ig = (j << (8-shift)) + i;
+;
+; if (shift != 0)
+; ig = (ig * 65535U + max_by_2)/max;
+;
+; sub_table[j] = (uint_16)ig;
+; }
+; }
+; }
+ ret
+endp
+
+; NOTE: this function expects the *inverse* of the overall gamma transformation
+; required.
+
+;void (png_structrp png_ptr, uint_16pp *ptable, uint shift, png_fixed_point gamma_val)
+align 4
+proc png_build_16to8_table, png_ptr:dword, ptable:dword, shift:dword, gamma_val:dword
+; uint num = 1U << (8U - shift);
+; uint max = (1U << (16U - shift))-1U;
+; uint i;
+; uint_32 last;
+
+; uint_16pp table = *ptable =
+; (uint_16pp)png_calloc(png_ptr, num * (sizeof (uint_16p)));
+
+ ; 'num' is the number of tables and also the number of low bits of low
+ ; bits of the input 16-bit value used to select a table. Each table is
+ ; itself indexed by the high 8 bits of the value.
+
+; for (i = 0; i < num; i++)
+; table[i] = (uint_16p)png_malloc(png_ptr,
+; 256 * (sizeof (uint_16)));
+
+ ; 'gamma_val' is set to the reciprocal of the value calculated above, so
+ ; pow(out,g) is an *input* value. 'last' is the last input value set.
+ ;
+ ; In the loop 'i' is used to find output values. Since the output is
+ ; 8-bit there are only 256 possible values. The tables are set up to
+ ; select the closest possible output value for each input by finding
+ ; the input value at the boundary between each pair of output values
+ ; and filling the table up to that boundary with the lower output
+ ; value.
+
+ ; The boundary values are 0.5,1.5..253.5,254.5. Since these are 9-bit
+ ; values the code below uses a 16-bit value in i; the values start at
+ ; 128.5 (for 0.5) and step by 257, for a total of 254 values (the last
+ ; entries are filled with 255). Start i at 128 and fill all 'last'
+ ; table entries <= 'max'
+
+; last = 0;
+; for (i = 0; i < 255; ++i) /* 8-bit output value */
+; {
+ ; Find the corresponding maximum input value
+; uint_16 out = (uint_16)(i * 257U); /* 16-bit output value */
+
+ ; Find the boundary value in 16 bits:
+; uint_32 bound = png_gamma_16bit_correct(out+128U, gamma_val);
+
+ ; Adjust (round) to (16-shift) bits:
+; bound = (bound * max + 32768U)/65535U + 1U;
+;
+; while (last < bound)
+; {
+; table[last & (0xffU >> shift)][last >> (8U - shift)] = out;
+; last++;
+; }
+; }
+
+ ; And fill in the final entries.
+; while (last < (num << 8))
+; {
+; table[last & (0xff >> shift)][last >> (8U - shift)] = 65535U;
+; last++;
+; }
+ ret
+endp
+;end if /* 16BIT */
+
+; Build a single 8-bit table: same as the 16-bit case but much simpler (and
+; typically much faster). Note that libpng currently does no sBIT processing
+; (apparently contrary to the spec) so a 256-entry table is always generated.
+
+;void (png_structrp png_ptr, bytepp ptable, png_fixed_point gamma_val)
+align 4
+proc png_build_8bit_table, png_ptr:dword, ptable:dword, gamma_val:dword
+; uint i;
+; bytep table = *ptable = (bytep)png_malloc(png_ptr, 256);
+
+; if (png_gamma_significant(gamma_val) != 0)
+; for (i=0; i<256; i++)
+; table[i] = png_gamma_8bit_correct(i, gamma_val);
+
+; else
+; for (i=0; i<256; ++i)
+; table[i] = (byte)(i & 0xff);
+ ret
+endp
+
+; Used from png_read_destroy and below to release the memory used by the gamma
+; tables.
+
+;void (png_structrp png_ptr)
+align 4
+proc png_destroy_gamma_table, png_ptr:dword
+; png_free(png_ptr, png_ptr->gamma_table);
+; png_ptr->gamma_table = NULL;
+
+if PNG_16BIT_SUPPORTED eq 1
+; if (png_ptr->gamma_16_table != NULL)
+; {
+; int i;
+; int istop = (1 << (8 - png_ptr->gamma_shift));
+; for (i = 0; i < istop; i++)
+; {
+; png_free(png_ptr, png_ptr->gamma_16_table[i]);
+; }
+; png_free(png_ptr, png_ptr->gamma_16_table);
+; png_ptr->gamma_16_table = NULL;
+; }
+end if ;16BIT
+
+;#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
+; defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
+; defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+; png_free(png_ptr, png_ptr->gamma_from_1);
+; png_ptr->gamma_from_1 = NULL;
+; png_free(png_ptr, png_ptr->gamma_to_1);
+; png_ptr->gamma_to_1 = NULL;
+
+if PNG_16BIT_SUPPORTED eq 1
+; if (png_ptr->gamma_16_from_1 != NULL)
+; {
+; int i;
+; int istop = (1 << (8 - png_ptr->gamma_shift));
+; for (i = 0; i < istop; i++)
+; {
+; png_free(png_ptr, png_ptr->gamma_16_from_1[i]);
+; }
+; png_free(png_ptr, png_ptr->gamma_16_from_1);
+; png_ptr->gamma_16_from_1 = NULL;
+; }
+; if (png_ptr->gamma_16_to_1 != NULL)
+; {
+; int i;
+; int istop = (1 << (8 - png_ptr->gamma_shift));
+; for (i = 0; i < istop; i++)
+; {
+; png_free(png_ptr, png_ptr->gamma_16_to_1[i]);
+; }
+; png_free(png_ptr, png_ptr->gamma_16_to_1);
+; png_ptr->gamma_16_to_1 = NULL;
+; }
+end if ;16BIT
+;end if /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
+ ret
+endp
+
+; We build the 8- or 16-bit gamma tables here. Note that for 16-bit
+; tables, we don't make a full table if we are reducing to 8-bit in
+; the future. Note also how the gamma_16 tables are segmented so that
+; we don't need to allocate > 64K chunks for a full 16-bit table.
+
+;void (png_structrp png_ptr, int bit_depth)
+align 4
+proc png_build_gamma_table, png_ptr:dword, bit_depth:dword
+ png_debug 1, 'in png_build_gamma_table'
+
+ ; Remove any existing table; this copes with multiple calls to
+ ; png_read_update_info. The warning is because building the gamma tables
+ ; multiple times is a performance hit - it's harmless but the ability to
+ ; call png_read_update_info() multiple times is new in 1.5.6 so it seems
+ ; sensible to warn if the app introduces such a hit.
+
+; if (png_ptr->gamma_table != NULL || png_ptr->gamma_16_table != NULL)
+; {
+; png_warning(png_ptr, "gamma table being rebuilt");
+; png_destroy_gamma_table(png_ptr);
+; }
+
+; if (bit_depth <= 8)
+; {
+; png_build_8bit_table(png_ptr, &png_ptr->gamma_table,
+; png_ptr->screen_gamma > 0 ?
+; png_reciprocal2(png_ptr->colorspace.gamma,
+; png_ptr->screen_gamma) : PNG_FP_1);
+;
+if (PNG_READ_BACKGROUND_SUPPORTED eq 1) | (PNG_READ_ALPHA_MODE_SUPPORTED eq 1) | (PNG_READ_RGB_TO_GRAY_SUPPORTED eq 1)
+; if ((png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) != 0)
+; {
+; png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1,
+; png_reciprocal(png_ptr->colorspace.gamma));
+;
+; png_build_8bit_table(png_ptr, &png_ptr->gamma_from_1,
+; png_ptr->screen_gamma > 0 ?
+; png_reciprocal(png_ptr->screen_gamma) :
+; png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */);
+; }
+end if ;READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY
+; }
+if PNG_16BIT_SUPPORTED eq 1
+; else
+; {
+; byte shift, sig_bit;
+;
+; if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
+; {
+; sig_bit = png_ptr->sig_bit.red;
+;
+; if (png_ptr->sig_bit.green > sig_bit)
+; sig_bit = png_ptr->sig_bit.green;
+;
+; if (png_ptr->sig_bit.blue > sig_bit)
+; sig_bit = png_ptr->sig_bit.blue;
+; }
+; else
+; sig_bit = png_ptr->sig_bit.gray;
+
+ ; 16-bit gamma code uses this equation:
+
+ ; ov = table[(iv & 0xff) >> gamma_shift][iv >> 8]
+
+ ; Where 'iv' is the input color value and 'ov' is the output value -
+ ; pow(iv, gamma).
+
+ ; Thus the gamma table consists of up to 256 256-entry tables. The table
+ ; is selected by the (8-gamma_shift) most significant of the low 8 bits
+ ; of the color value then indexed by the upper 8 bits:
+ ;
+ ; table[low bits][high 8 bits]
+
+ ; So the table 'n' corresponds to all those 'iv' of:
+
+ ; ..<(n+1 << gamma_shift)-1>
+
+
+; if (sig_bit > 0 && sig_bit < 16U)
+; /* shift == insignificant bits */
+; shift = (byte)((16U - sig_bit) & 0xff);
+
+; else
+; shift = 0; /* keep all 16 bits */
+
+; if ((png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) != 0)
+; {
+ ; PNG_MAX_GAMMA_8 is the number of bits to keep - effectively
+ ; the significant bits in the *input* when the output will
+ ; eventually be 8 bits. By default it is 11.
+
+; if (shift < (16U - PNG_MAX_GAMMA_8))
+; shift = (16U - PNG_MAX_GAMMA_8);
+; }
+
+; if (shift > 8U)
+; shift = 8U; /* Guarantees at least one table! */
+
+; png_ptr->gamma_shift = shift;
+
+ ; NOTE: prior to 1.5.4 this test used to include PNG_BACKGROUND (now
+ ; PNG_COMPOSE). This effectively smashed the background calculation for
+ ; 16-bit output because the 8-bit table assumes the result will be
+ ; reduced to 8 bits.
+
+; if ((png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) != 0)
+; png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift,
+; png_ptr->screen_gamma > 0 ? png_product2(png_ptr->colorspace.gamma,
+; png_ptr->screen_gamma) : PNG_FP_1);
+;
+; else
+; png_build_16bit_table(png_ptr, &png_ptr->gamma_16_table, shift,
+; png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->colorspace.gamma,
+; png_ptr->screen_gamma) : PNG_FP_1);
+;
+if (PNG_READ_BACKGROUND_SUPPORTED eq 1) | (PNG_READ_ALPHA_MODE_SUPPORTED eq 1) | (PNG_READ_RGB_TO_GRAY_SUPPORTED eq 1)
+; if ((png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) != 0)
+; {
+; png_build_16bit_table(png_ptr, &png_ptr->gamma_16_to_1, shift,
+; png_reciprocal(png_ptr->colorspace.gamma));
+
+ ; Notice that the '16 from 1' table should be full precision, however
+ ; the lookup on this table still uses gamma_shift, so it can't be.
+ ; TODO: fix this.
+
+; png_build_16bit_table(png_ptr, &png_ptr->gamma_16_from_1, shift,
+; png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) :
+; png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */);
+; }
+end if ;READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY
+; }
+end if ;16BIT
+ ret
+endp
+;end if /* READ_GAMMA */
+
+; HARDWARE OR SOFTWARE OPTION SUPPORT
+;int (png_structrp png_ptr, int option, int onoff)
+align 4
+proc png_set_option uses ecx, png_ptr:dword, option:dword, onoff:dword
+ mov eax,[png_ptr]
+ cmp eax,0
+ je @f
+ mov ecx,[option]
+ cmp ecx,0
+ jl @f
+ cmp ecx,PNG_OPTION_NEXT
+ jge @f
+ bt ecx,0 ;cmp (ecx & 1), 0
+ jc @f ;if (..!=0 && ..>=0 && ..<.. && ..==0)
+; int mask = 3 << option;
+; int setting = (2 + (onoff != 0)) << option;
+; int current = png_ptr->options;
+
+; png_ptr->options = (byte)(((current & ~mask) | setting) & 0xff);
+
+; return (current & mask) >> option;
+ jmp .end_f
+ @@:
+ mov eax,PNG_OPTION_INVALID
+.end_f:
+ ret
+endp
+
+; sRGB support
+if (PNG_SIMPLIFIED_READ_SUPPORTED eq 1) | (PNG_SIMPLIFIED_WRITE_SUPPORTED eq 1)
+; sRGB conversion tables; these are machine generated with the code in
+; contrib/tools/makesRGB.c. The actual sRGB transfer curve defined in the
+; specification (see the article at http://en.wikipedia.org/wiki/SRGB)
+; is used, not the gamma=1/2.2 approximation use elsewhere in libpng.
+; The sRGB to linear table is exact (to the nearest 16-bit linear fraction).
+; The inverse (linear to sRGB) table has accuracies as follows:
+
+; For all possible (255*65535+1) input values:
+; error: -0.515566 - 0.625971, 79441 (0.475369%) of readings inexact
+
+; For the input values corresponding to the 65536 16-bit values:
+; error: -0.513727 - 0.607759, 308 (0.469978%) of readings inexact
+
+; In all cases the inexact readings are only off by one.
+
+
+if PNG_SIMPLIFIED_READ_SUPPORTED eq 1
+; The convert-to-sRGB table is only currently required for read.
+align 4
+png_sRGB_table dw 0,20,40,60,80,99,119,139,\
+ 159,179,199,219,241,264,288,313,\
+ 340,367,396,427,458,491,526,562,\
+ 599,637,677,718,761,805,851,898,\
+ 947,997,1048,1101,1156,1212,1270,1330,\
+ 1391,1453,1517,1583,1651,1720,1790,1863,\
+ 1937,2013,2090,2170,2250,2333,2418,2504,\
+ 2592,2681,2773,2866,2961,3058,3157,3258,\
+ 3360,3464,3570,3678,3788,3900,4014,4129,\
+ 4247,4366,4488,4611,4736,4864,4993,5124,\
+ 5257,5392,5530,5669,5810,5953,6099,6246,\
+ 6395,6547,6700,6856,7014,7174,7335,7500,\
+ 7666,7834,8004,8177,8352,8528,8708,8889,\
+ 9072,9258,9445,9635,9828,10022,10219,10417,\
+ 10619,10822,11028,11235,11446,11658,11873,12090,\
+ 12309,12530,12754,12980,13209,13440,13673,13909,\
+ 14146,14387,14629,14874,15122,15371,15623,15878,\
+ 16135,16394,16656,16920,17187,17456,17727,18001,\
+ 18277,18556,18837,19121,19407,19696,19987,20281,\
+ 20577,20876,21177,21481,21787,22096,22407,22721,\
+ 23038,23357,23678,24002,24329,24658,24990,25325,\
+ 25662,26001,26344,26688,27036,27386,27739,28094,\
+ 28452,28813,29176,29542,29911,30282,30656,31033,\
+ 31412,31794,32179,32567,32957,33350,33745,34143,\
+ 34544,34948,35355,35764,36176,36591,37008,37429,\
+ 37852,38278,38706,39138,39572,40009,40449,40891,\
+ 41337,41785,42236,42690,43147,43606,44069,44534,\
+ 45002,45473,45947,46423,46903,47385,47871,48359,\
+ 48850,49344,49841,50341,50844,51349,51858,52369,\
+ 52884,53401,53921,54445,54971,55500,56032,56567,\
+ 57105,57646,58190,58737,59287,59840,60396,60955,\
+ 61517,62082,62650,63221,63795,64372,64952,65535
+end if ;SIMPLIFIED_READ
+
+; The base/delta tables are required for both read and write (but currently
+; only the simplified versions.)
+align 4
+png_sRGB_base dw 128,1782,3383,4644,5675,6564,7357,8074,\
+ 8732,9346,9921,10463,10977,11466,11935,12384,\
+ 12816,13233,13634,14024,14402,14769,15125,15473,\
+ 15812,16142,16466,16781,17090,17393,17690,17981,\
+ 18266,18546,18822,19093,19359,19621,19879,20133,\
+ 20383,20630,20873,21113,21349,21583,21813,22041,\
+ 22265,22487,22707,22923,23138,23350,23559,23767,\
+ 23972,24175,24376,24575,24772,24967,25160,25352,\
+ 25542,25730,25916,26101,26284,26465,26645,26823,\
+ 27000,27176,27350,27523,27695,27865,28034,28201,\
+ 28368,28533,28697,28860,29021,29182,29341,29500,\
+ 29657,29813,29969,30123,30276,30429,30580,30730,\
+ 30880,31028,31176,31323,31469,31614,31758,31902,\
+ 32045,32186,32327,32468,32607,32746,32884,33021,\
+ 33158,33294,33429,33564,33697,33831,33963,34095,\
+ 34226,34357,34486,34616,34744,34873,35000,35127,\
+ 35253,35379,35504,35629,35753,35876,35999,36122,\
+ 36244,36365,36486,36606,36726,36845,36964,37083,\
+ 37201,37318,37435,37551,37668,37783,37898,38013,\
+ 38127,38241,38354,38467,38580,38692,38803,38915,\
+ 39026,39136,39246,39356,39465,39574,39682,39790,\
+ 39898,40005,40112,40219,40325,40431,40537,40642,\
+ 40747,40851,40955,41059,41163,41266,41369,41471,\
+ 41573,41675,41777,41878,41979,42079,42179,42279,\
+ 42379,42478,42577,42676,42775,42873,42971,43068,\
+ 43165,43262,43359,43456,43552,43648,43743,43839,\
+ 43934,44028,44123,44217,44311,44405,44499,44592,\
+ 44685,44778,44870,44962,45054,45146,45238,45329,\
+ 45420,45511,45601,45692,45782,45872,45961,46051,\
+ 46140,46229,46318,46406,46494,46583,46670,46758,\
+ 46846,46933,47020,47107,47193,47280,47366,47452,\
+ 47538,47623,47709,47794,47879,47964,48048,48133,\
+ 48217,48301,48385,48468,48552,48635,48718,48801,\
+ 48884,48966,49048,49131,49213,49294,49376,49458,\
+ 49539,49620,49701,49782,49862,49943,50023,50103,\
+ 50183,50263,50342,50422,50501,50580,50659,50738,\
+ 50816,50895,50973,51051,51129,51207,51285,51362,\
+ 51439,51517,51594,51671,51747,51824,51900,51977,\
+ 52053,52129,52205,52280,52356,52432,52507,52582,\
+ 52657,52732,52807,52881,52956,53030,53104,53178,\
+ 53252,53326,53400,53473,53546,53620,53693,53766,\
+ 53839,53911,53984,54056,54129,54201,54273,54345,\
+ 54417,54489,54560,54632,54703,54774,54845,54916,\
+ 54987,55058,55129,55199,55269,55340,55410,55480,\
+ 55550,55620,55689,55759,55828,55898,55967,56036,\
+ 56105,56174,56243,56311,56380,56448,56517,56585,\
+ 56653,56721,56789,56857,56924,56992,57059,57127,\
+ 57194,57261,57328,57395,57462,57529,57595,57662,\
+ 57728,57795,57861,57927,57993,58059,58125,58191,\
+ 58256,58322,58387,58453,58518,58583,58648,58713,\
+ 58778,58843,58908,58972,59037,59101,59165,59230,\
+ 59294,59358,59422,59486,59549,59613,59677,59740,\
+ 59804,59867,59930,59993,60056,60119,60182,60245,\
+ 60308,60370,60433,60495,60558,60620,60682,60744,\
+ 60806,60868,60930,60992,61054,61115,61177,61238,\
+ 61300,61361,61422,61483,61544,61605,61666,61727,\
+ 61788,61848,61909,61969,62030,62090,62150,62211,\
+ 62271,62331,62391,62450,62510,62570,62630,62689,\
+ 62749,62808,62867,62927,62986,63045,63104,63163,\
+ 63222,63281,63340,63398,63457,63515,63574,63632,\
+ 63691,63749,63807,63865,63923,63981,64039,64097,\
+ 64155,64212,64270,64328,64385,64443,64500,64557,\
+ 64614,64672,64729,64786,64843,64900,64956,65013,\
+ 65070,65126,65183,65239,65296,65352,65409,65465
+align 4
+png_sRGB_delta db 207,201,158,129,113,100,90,82,77,72,68,64,61,59,56,54,\
+ 52,50,49,47,46,45,43,42,41,40,39,39,38,37,36,36,\
+ 35,34,34,33,33,32,32,31,31,30,30,30,29,29,28,28,\
+ 28,27,27,27,27,26,26,26,25,25,25,25,24,24,24,24,\
+ 23,23,23,23,23,22,22,22,22,22,22,21,21,21,21,21,\
+ 21,20,20,20,20,20,20,20,20,19,19,19,19,19,19,19,\
+ 19,18,18,18,18,18,18,18,18,18,18,17,17,17,17,17,\
+ 17,17,17,17,17,17,16,16,16,16,16,16,16,16,16,16,\
+ 16,16,16,16,15,15,15,15,15,15,15,15,15,15,15,15,\
+ 15,15,15,15,14,14,14,14,14,14,14,14,14,14,14,14,\
+ 14,14,14,14,14,14,14,13,13,13,13,13,13,13,13,13,\
+ 13,13,13,13,13,13,13,13,13,13,13,13,13,13,12,12,\
+ 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,\
+ 12,12,12,12,12,12,12,12,12,12,12,12,11,11,11,11,\
+ 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,\
+ 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,\
+ 11,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,\
+ 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,\
+ 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,\
+ 10,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,\
+ 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,\
+ 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,\
+ 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,\
+ 9,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,\
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,\
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,\
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,\
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,\
+ 8,8,8,8,8,8,8,8,8,7,7,7,7,7,7,7,\
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
+
+end if ;SIMPLIFIED READ/WRITE sRGB support
+
+; SIMPLIFIED READ/WRITE SUPPORT
+;int (voidp argument)
+align 4
+proc png_image_free_function uses ebx ecx edi esi, argument:dword
+locals
+; png_imagep image = argument;
+; png_controlp cp = image->opaque;
+ c png_control
+endl
+ ; Double check that we have a png_ptr - it should be impossible to get here
+ ; without one.
+
+ mov ebx,[argument]
+ mov esi,[ebx+png_image.opaque] ;esi = cp
+ cmp dword[esi+png_control.png_ptr],0
+ jne @f ;if (..==0)
+ xor eax,eax
+ jmp .end_f
+ @@:
+
+ ; First free any data held in the control structure.
+if PNG_STDIO_SUPPORTED eq 1
+; if (cp->owned_file != 0)
+; {
+; FILE *fp = cp->png_ptr->io_ptr;
+; cp->owned_file = 0;
+
+ ; Ignore errors here.
+; if (fp != NULL)
+; {
+; cp->png_ptr->io_ptr = NULL;
+; (void)fclose(fp);
+; }
+; }
+end if
+
+ ; Copy the control structure so that the original, allocated, version can be
+ ; safely freed. Notice that a png_error here stops the remainder of the
+ ; cleanup, but this is probably fine because that would indicate bad memory
+ ; problems anyway.
+
+ mov ecx,sizeof.png_control
+ mov edi,ebp
+ sub edi,ecx ;edi = &c
+ rep movsb
+ sub edi,sizeof.png_control
+ sub esi,sizeof.png_control
+ mov dword[ebx+png_image.opaque],edi
+ stdcall png_free, [edi+png_control.png_ptr], esi
+
+ ; Then the structures, calling the correct API.
+; if (c.for_write != 0)
+; {
+if PNG_SIMPLIFIED_WRITE_SUPPORTED eq 1
+; png_destroy_write_struct(&c.png_ptr, &c.info_ptr);
+else
+; png_error(c.png_ptr, "simplified write not supported");
+end if
+ jmp .end2
+ .end1: ;else
+if PNG_SIMPLIFIED_READ_SUPPORTED eq 1
+; png_destroy_read_struct(&c.png_ptr, &c.info_ptr, NULL);
+else
+; png_error(c.png_ptr, "simplified read not supported");
+end if
+ .end2:
+
+ ; Success.
+ xor eax,eax
+ inc eax
+.end_f:
+ ret
+endp
+
+;void (png_imagep image)
+align 4
+proc png_image_free uses eax ebx, image:dword
+ ; Safely call the real function, but only if doing so is safe at this point
+ ; (if not inside an error handling context). Otherwise assume
+ ; png_safe_execute will call this API after the return.
+
+ mov ebx,[image]
+ cmp ebx,0
+ je @f
+ cmp dword[ebx+png_image.opaque],0
+ je @f
+ mov eax,[ebx+png_image.opaque]
+ cmp dword[eax+png_control.error_buf],0
+ jne @f ;if (..!=0 && ..!=0 && ..==0)
+ ; Ignore errors here:
+ stdcall png_safe_execute, ebx, png_image_free_function, ebx
+ mov dword[ebx+png_image.opaque],0
+ @@:
+ ret
+endp
+
+;int (png_imagep image, charp error_message)
+align 4
+proc png_image_error uses ebx, image:dword, error_message:dword
+ ; Utility to log an error.
+ mov ebx,[image]
+ mov eax,ebx
+ add eax,png_image.message
+ stdcall png_safecat, eax, sizeof.png_image.message, 0, [error_message]
+ or dword[ebx+png_image.warning_or_error], PNG_IMAGE_ERROR
+ stdcall png_image_free, ebx
+ xor eax,eax
+ ret
+endp
+
+;end if /* READ || WRITE */
diff --git a/programs/develop/libraries/libs-dev/libimg/png/libpng/png.inc b/programs/develop/libraries/libs-dev/libimg/png/libpng/png.inc
index 35fcb638e..d93a75a01 100644
--- a/programs/develop/libraries/libs-dev/libimg/png/libpng/png.inc
+++ b/programs/develop/libraries/libs-dev/libimg/png/libpng/png.inc
@@ -1,1814 +1,1814 @@
-
-; png.inc - header file for PNG reference library
-
-; libpng version 1.6.25, September 1, 2016
-
-; Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
-; (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
-; (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
-
-; This code is released under the libpng license (See LICENSE, below)
-
-; Authors and maintainers:
-; libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
-; libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger
-; libpng versions 0.97, January 1998, through 1.6.25, September 1, 2016:
-; Glenn Randers-Pehrson.
-; See also "Contributing Authors", below.
-
-
-
-; COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:
-
-; If you modify libpng you may insert additional notices immediately following
-; this sentence.
-
-; This code is released under the libpng license.
-
-; Some files in the "contrib" directory and some configure-generated
-; files that are distributed with libpng have other copyright owners and
-; are released under other open source licenses.
-
-; libpng versions 1.0.7, July 1, 2000 through 1.6.25, September 1, 2016 are
-; Copyright (c) 2000-2002, 2004, 2006-2016 Glenn Randers-Pehrson, are
-; derived from libpng-1.0.6, and are distributed according to the same
-; disclaimer and license as libpng-1.0.6 with the following individuals
-; added to the list of Contributing Authors:
-
-; Simon-Pierre Cadieux
-; Eric S. Raymond
-; Mans Rullgard
-; Cosmin Truta
-; Gilles Vollant
-; James Yu
-; Mandar Sahastrabuddhe
-
-; and with the following additions to the disclaimer:
-
-; There is no warranty against interference with your enjoyment of the
-; library or against infringement. There is no warranty that our
-; efforts or the library will fulfill any of your particular purposes
-; or needs. This library is provided with all faults, and the entire
-; risk of satisfactory quality, performance, accuracy, and effort is with
-; the user.
-
-; Some files in the "contrib" directory have other copyright owners and
-; are released under other open source licenses.
-
-
-; libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
-; Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
-; libpng-0.96, and are distributed according to the same disclaimer and
-; license as libpng-0.96, with the following individuals added to the list
-; of Contributing Authors:
-
-; Tom Lane
-; Glenn Randers-Pehrson
-; Willem van Schaik
-
-; Some files in the "scripts" directory have different copyright owners
-; but are also released under this license.
-
-; libpng versions 0.89, June 1996, through 0.96, May 1997, are
-; Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88,
-; and are distributed according to the same disclaimer and license as
-; libpng-0.88, with the following individuals added to the list of
-; Contributing Authors:
-
-; John Bowler
-; Kevin Bracey
-; Sam Bushell
-; Magnus Holmgren
-; Greg Roelofs
-; Tom Tanner
-
-; Some files in the "scripts" directory have other copyright owners
-; but are released under this license.
-
-; libpng versions 0.5, May 1995, through 0.88, January 1996, are
-; Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
-
-; For the purposes of this copyright and license, "Contributing Authors"
-; is defined as the following set of individuals:
-
-; Andreas Dilger
-; Dave Martindale
-; Guy Eric Schalnat
-; Paul Schmidt
-; Tim Wegner
-
-; The PNG Reference Library is supplied "AS IS". The Contributing Authors
-; and Group 42, Inc. disclaim all warranties, expressed or implied,
-; including, without limitation, the warranties of merchantability and of
-; fitness for any purpose. The Contributing Authors and Group 42, Inc.
-; assume no liability for direct, indirect, incidental, special, exemplary,
-; or consequential damages, which may result from the use of the PNG
-; Reference Library, even if advised of the possibility of such damage.
-
-; Permission is hereby granted to use, copy, modify, and distribute this
-; source code, or portions hereof, for any purpose, without fee, subject
-; to the following restrictions:
-
-; 1. The origin of this source code must not be misrepresented.
-
-; 2. Altered versions must be plainly marked as such and must not
-; be misrepresented as being the original source.
-
-; 3. This Copyright notice may not be removed or altered from any
-; source or altered source distribution.
-
-; The Contributing Authors and Group 42, Inc. specifically permit, without
-; fee, and encourage the use of this source code as a component to
-; supporting the PNG file format in commercial products. If you use this
-; source code in a product, acknowledgment is not required but would be
-; appreciated.
-
-; END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE.
-
-; TRADEMARK:
-
-; The name "libpng" has not been registered by the Copyright owner
-; as a trademark in any jurisdiction. However, because libpng has
-; been distributed and maintained world-wide, continually since 1995,
-; the Copyright owner claims "common-law trademark protection" in any
-; jurisdiction where common-law trademark is recognized.
-
-; OSI CERTIFICATION:
-
-; Libpng is OSI Certified Open Source Software. OSI Certified Open Source is
-; a certification mark of the Open Source Initiative. OSI has not addressed
-; the additional disclaimers inserted at version 1.0.7.
-
-; EXPORT CONTROL:
-
-; The Copyright owner believes that the Export Control Classification
-; Number (ECCN) for libpng is EAR99, which means not subject to export
-; controls or International Traffic in Arms Regulations (ITAR) because
-; it is open source, publicly available software, that does not contain
-; any encryption software. See the EAR, paragraphs 734.3(b)(3) and
-; 734.7(b).
-
-
-
-; A "png_get_copyright" function is available, for convenient use in "about"
-; boxes and the like:
-
-; printf("%s", png_get_copyright(NULL));
-
-; Also, the PNG logo (in PNG format, of course) is supplied in the
-; files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31).
-
-
-
-; The contributing authors would like to thank all those who helped
-; with testing, bug fixes, and patience. This wouldn't have been
-; possible without all of you.
-
-; Thanks to Frank J. T. Wojcik for helping with the documentation.
-
-;
-; Note about libpng version numbers:
-;
-; Due to various miscommunications, unforeseen code incompatibilities
-; and occasional factors outside the authors' control, version numbering
-; on the library has not always been consistent and straightforward.
-; The following table summarizes matters since version 0.89c, which was
-; the first widely used release:
-;
-; source png.h png.h shared-lib
-; version string int version
-; ------- ------ ----- ----------
-; ...
-; 1.2.56 13 10256 12.so.0.56[.0]
-; ...
-; 1.5.27 15 10527 15.so.15.27[.0]
-; ...
-; 1.6.25 16 10625 16.so.16.25[.0]
-
-; Henceforth the source version will match the shared-library major
-; and minor numbers; the shared-library major version number will be
-; used for changes in backward compatibility, as it is intended. The
-; PNG_LIBPNG_VER macro, which is not used within libpng but is available
-; for applications, is an unsigned integer of the form xyyzz corresponding
-; to the source version x.y.z (leading zeros in y and z). Beta versions
-; were given the previous public release number plus a letter, until
-; version 1.0.6j; from then on they were given the upcoming public
-; release number plus "betaNN" or "rcNN".
-
-; Binary incompatibility exists only when applications make direct access
-; to the info_ptr or png_ptr members through png.h, and the compiled
-; application is loaded with a different version of the library.
-
-; DLLNUM will change each time there are forward or backward changes
-; in binary compatibility (e.g., when a new feature is added).
-
-; See libpng.txt or libpng.3 for more information. The PNG specification
-; is available as a W3C Recommendation and as an ISO Specification,
-;
-
-; If you just need to read a PNG file and don't want to read the documentation
-; skip to the end of this file and read the section entitled 'simplified API'.
-
-
-; Version information for png.h - this should match the version in png.asm
-PNG_LIBPNG_VER_STRING db '1.6.25',0
-PNG_HEADER_VERSION_STRING db ' libpng version 1.6.25 - September 1, 2016',13,10,0
-
-PNG_LIBPNG_VER_SONUM equ 16
-PNG_LIBPNG_VER_DLLNUM equ 16
-
-; These should match the first 3 components of PNG_LIBPNG_VER_STRING:
-PNG_LIBPNG_VER_MAJOR equ 1
-PNG_LIBPNG_VER_MINOR equ 6
-PNG_LIBPNG_VER_RELEASE equ 25
-
-; This should match the numeric part of the final component of
-; PNG_LIBPNG_VER_STRING, omitting any leading zero:
-
-
-PNG_LIBPNG_VER_BUILD equ 0
-
-; Release Status
-PNG_LIBPNG_BUILD_ALPHA equ 1
-PNG_LIBPNG_BUILD_BETA equ 2
-PNG_LIBPNG_BUILD_RC equ 3
-PNG_LIBPNG_BUILD_STABLE equ 4
-PNG_LIBPNG_BUILD_RELEASE_STATUS_MASK equ 7
-
-; Release-Specific Flags
-PNG_LIBPNG_BUILD_PATCH equ 8 ;Can be OR'ed with PNG_LIBPNG_BUILD_STABLE only
-PNG_LIBPNG_BUILD_PRIVATE equ 16 ;Cannot be OR'ed with PNG_LIBPNG_BUILD_SPECIAL
-PNG_LIBPNG_BUILD_SPECIAL equ 32 ;Cannot be OR'ed with PNG_LIBPNG_BUILD_PRIVATE
-
-PNG_LIBPNG_BUILD_BASE_TYPE equ PNG_LIBPNG_BUILD_STABLE
-
-; Careful here. At one time, Guy wanted to use 082, but that would be octal.
-; We must not include leading zeros.
-; Versions 0.7 through 1.0.0 were in the range 0 to 100 here (only
-; version 1.0.0 was mis-numbered 100 instead of 10000). From
-; version 1.0.1 it's xxyyzz, where x=major, y=minor, z=release
-
-PNG_LIBPNG_VER equ 10625 ;1.6.25
-
-; Library configuration: these options cannot be changed after
-; the library has been built.
-
-
-; Added at libpng-1.2.8
-
-; Ref MSDN: Private as priority over Special
-; VS_FF_PRIVATEBUILD File *was not* built using standard release
-; procedures. If this value is given, the StringFileInfo block must
-; contain a PrivateBuild string.
-
-; VS_FF_SPECIALBUILD File *was* built by the original company using
-; standard release procedures but is a variation of the standard
-; file of the same version number. If this value is given, the
-; StringFileInfo block must contain a SpecialBuild string.
-
-;if PNG_USER_PRIVATEBUILD /* From pnglibconf.h */
-;# define PNG_LIBPNG_BUILD_TYPE \
-; (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_PRIVATE)
-;#else
-;# ifdef PNG_LIBPNG_SPECIALBUILD
-;# define PNG_LIBPNG_BUILD_TYPE \
-; (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_SPECIAL)
-;# else
-;# define PNG_LIBPNG_BUILD_TYPE (PNG_LIBPNG_BUILD_BASE_TYPE)
-;# endif
-;end if
-
-;#ifndef PNG_VERSION_INFO_ONLY
-
-; Version information for C files, stored in png.asm. This had better match
-; the version above.
-
-;#define png_libpng_ver png_get_header_ver(NULL)
-
-; This file is arranged in several sections:
-
-; 1. [omitted]
-; 2. Any configuration options that can be specified by for the application
-; code when it is built. (Build time configuration is in pnglibconf.h)
-; 3. Type definitions (base types are defined in pngconf.h), structure
-; definitions.
-; 4. Exported library functions.
-; 5. Simplified API.
-; 6. Implementation options.
-
-; The library source code has additional files (principally pngpriv.h) that
-; allow configuration of the library.
-
-
-; Section 1: [omitted]
-
-; Section 2: run time configuration
-; See pnglibconf.h for build time configuration
-
-; Run time configuration allows the application to choose between
-; implementations of certain arithmetic APIs. The default is set
-; at build time and recorded in pnglibconf.h, but it is safe to
-; override these (and only these) settings. Note that this won't
-; change what the library does, only application code, and the
-; settings can (and probably should) be made on a per-file basis
-; by setting the #defines before including png.h
-
-; Use macros to read integers from PNG data or use the exported
-; functions?
-; PNG_USE_READ_MACROS: use the macros (see below) Note that
-; the macros evaluate their argument multiple times.
-; PNG_NO_USE_READ_MACROS: call the relevant library function.
-
-; Use the alternative algorithm for compositing alpha samples that
-; does not use division?
-; PNG_READ_COMPOSITE_NODIV_SUPPORTED: use the 'no division'
-; algorithm.
-; PNG_NO_READ_COMPOSITE_NODIV: use the 'division' algorithm.
-
-; How to handle benign errors if PNG_ALLOW_BENIGN_ERRORS is
-; false?
-; PNG_ALLOW_BENIGN_ERRORS: map calls to the benign error
-; APIs to png_warning.
-; Otherwise the calls are mapped to png_error.
-
-
-; Section 3: type definitions, including structures and compile time
-; constants.
-; See pngconf.h for base types that vary by machine/system
-
-
-; This triggers a compiler error in png.c, if png.c and png.h
-; do not agree upon the version number.
-
-;typedef char* png_libpng_version_1_6_25;
-
-; Basic control structions. Read libpng-manual.txt or libpng.3 for more info.
-
-; png_struct is the cache of information used while reading or writing a single
-; PNG file. One of these is always required, although the simplified API
-; (below) hides the creation and destruction of it.
-
-; png_info contains information read from or to be written to a PNG file. One
-; or more of these must exist while reading or creating a PNG file. The
-; information is not used by libpng during read but is used to control what
-; gets written when a PNG file is created. "png_get_" function calls read
-; information during read and "png_set_" functions calls write information
-; when creating a PNG.
-; been moved into a separate header file that is not accessible to
-; applications. Read libpng-manual.txt or libpng.3 for more info.
-
-; Types with names ending 'p' are pointer types. The corresponding types with
-; names ending 'rp' are identical pointer types except that the pointer is
-; marked 'restrict', which means that it is the only pointer to the object
-; passed to the function. Applications should not use the 'restrict' types;
-; it is always valid to pass 'p' to a pointer with a function argument of the
-; corresponding 'rp' type. Different compilers have different rules with
-; regard to type matching in the presence of 'restrict'. For backward
-; compatibility libpng callbacks never have 'restrict' in their parameters and,
-; consequentially, writing portable application code is extremely difficult if
-; an attempt is made to use 'restrict'.
-
-; Three color definitions. The order of the red, green, and blue, (and the
-; exact size) is not important, although the size of the fields need to
-; be byte or uint_16 (as defined below).
-
-struct png_color
- red db ? ;byte
- green db ? ;byte
- blue db ? ;byte
-ends
-
-struct png_color_16
- index db ? ;byte ;used for palette files
- red dw ? ;uint_16 ;for use in red green blue files
- green dw ? ;uint_16
- blue dw ? ;uint_16
- gray dw ? ;uint_16 ;for use in grayscale files
-ends
-
-struct png_color_8
- red db ? ;byte ;for use in red green blue files
- green db ? ;byte
- blue db ? ;byte
- gray db ? ;byte ;for use in grayscale files
- alpha db ? ;byte ;for alpha channel files
-ends
-
-
-; The following two structures are used for the in-core representation
-; of sPLT chunks.
-
-struct png_sPLT_entry
- red dw ? ;uint_16
- green dw ? ;uint_16
- blue dw ? ;uint_16
- alpha dw ? ;uint_16
- frequency dw ? ;uint_16
-ends
-
-; When the depth of the sPLT palette is 8 bits, the color and alpha samples
-; occupy the LSB of their respective members, and the MSB of each member
-; is zero-filled. The frequency member always occupies the full 16 bits.
-
-
-struct png_sPLT_t
- name dd ? ;charp ;palette name
- depth db ? ;byte ;depth of palette samples
- entries dd ? ;png_sPLT_entryp ;palette entries
- nentries dd ? ;int_32 ;number of palette entries
-ends
-
-if PNG_TEXT_SUPPORTED eq 1
-; png_text holds the contents of a text/ztxt/itxt chunk in a PNG file,
-; and whether that contents is compressed or not. The "key" field
-; points to a regular zero-terminated C string. The "text" fields can be a
-; regular C string, an empty string, or a NULL pointer.
-; However, the structure returned by png_get_text() will always contain
-; the "text" field as a regular zero-terminated C string (possibly
-; empty), never a NULL pointer, so it can be safely used in printf() and
-; other string-handling functions. Note that the "itxt_length", "lang", and
-; "lang_key" members of the structure only exist when the library is built
-; with iTXt chunk support. Prior to libpng-1.4.0 the library was built by
-; default without iTXt support. Also note that when iTXt *is* supported,
-; the "lang" and "lang_key" fields contain NULL pointers when the
-; "compression" field contains * PNG_TEXT_COMPRESSION_NONE or
-; PNG_TEXT_COMPRESSION_zTXt. Note that the "compression value" is not the
-; same as what appears in the PNG tEXt/zTXt/iTXt chunk's "compression flag"
-; which is always 0 or 1, or its "compression method" which is always 0.
-
-struct png_text
- compression dd ? ;int ;compression value:
- ;-1: tEXt, none
- ; 0: zTXt, deflate
- ; 1: iTXt, none
- ; 2: iTXt, deflate
- key dd ? ;charp ;keyword, 1-79 character description of "text"
- text dd ? ;charp ;comment, may be an empty string (ie "")
- ; or a NULL pointer
- text_length dd ? ;png_size_t ;length of the text string
- itxt_length dd ? ;png_size_t ;length of the itxt string
- lang dd ? ;charp ;language code, 0-79 characters
- ; or a NULL pointer
- lang_key dd ? ;charp ;keyword translated UTF-8 string, 0 or more
- ; chars or a NULL pointer
-ends
-end if
-
-; Supported compression types for text in PNG files (tEXt, and zTXt).
-; The values of the PNG_TEXT_COMPRESSION_ defines should NOT be changed.
-PNG_TEXT_COMPRESSION_NONE_WR equ -3
-PNG_TEXT_COMPRESSION_zTXt_WR equ -2
-PNG_TEXT_COMPRESSION_NONE equ -1
-PNG_TEXT_COMPRESSION_zTXt equ 0
-PNG_ITXT_COMPRESSION_NONE equ 1
-PNG_ITXT_COMPRESSION_zTXt equ 2
-PNG_TEXT_COMPRESSION_LAST equ 3 ;Not a valid value
-
-; png_time is a way to hold the time in an machine independent way.
-; Two conversions are provided, both from time_t and struct tm. There
-; is no portable way to convert to either of these structures, as far
-; as I know. If you know of a portable way, send it to me. As a side
-; note - PNG has always been Year 2000 compliant!
-
-struct png_time
- year dw ? ;uint_16 ;full year, as in, 1995
- month db ? ;byte ;month of year, 1 - 12
- day db ? ;byte ;day of month, 1 - 31
- hour db ? ;byte ;hour of day, 0 - 23
- minute db ? ;byte ;minute of hour, 0 - 59
- second db ? ;byte ;second of minute, 0 - 60 (for leap seconds)
-ends
-
-if (PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED eq 1) | (PNG_USER_CHUNKS_SUPPORTED eq 1)
-; png_unknown_chunk is a structure to hold queued chunks for which there is
-; no specific support. The idea is that we can use this to queue
-; up private chunks for output even though the library doesn't actually
-; know about their semantics.
-
-; The data in the structure is set by libpng on read and used on write.
-
-struct png_unknown_chunk
- name rb 5 ;byte[5] ;Textual chunk name with '\0' terminator
- rb 3 ;align
- podata dd ? ;byte* ;Data, should not be modified on read!
- size dd ? ;png_size_t
-
- ; On write 'location' must be set using the flag values listed below.
- ; Notice that on read it is set by libpng however the values stored have
- ; more bits set than are listed below. Always treat the value as a
- ; bitmask. On write set only one bit - setting multiple bits may cause the
- ; chunk to be written in multiple places.
-
- location db ? ;byte ;mode of operation at read time
-ends
-end if
-
-; Flag values for the unknown chunk location byte.
-PNG_HAVE_IHDR equ 0x01
-PNG_HAVE_PLTE equ 0x02
-PNG_AFTER_IDAT equ 0x08
-
-; Maximum positive integer used in PNG is (2^31)-1
-PNG_UINT_31_MAX equ 0x7fffffff ;uint_32
-PNG_UINT_32_MAX equ -1 ;uint_32
-PNG_SIZE_MAX equ 0x60000000 ;1.5 Gb
-
-; These are constants for fixed point values encoded in the
-; PNG specification manner (x100000)
-
-PNG_FP_1 equ 100000
-PNG_FP_HALF equ 50000
-PNG_FP_MAX equ ((png_fixed_point)0x7fffffffL)
-PNG_FP_MIN equ (-PNG_FP_MAX)
-
-; These describe the color_type field in png_info.
-; color type masks
-PNG_COLOR_MASK_PALETTE equ 1
-PNG_COLOR_MASK_COLOR equ 2
-PNG_COLOR_MASK_ALPHA equ 4
-
-; color types. Note that not all combinations are legal
-PNG_COLOR_TYPE_GRAY equ 0
-PNG_COLOR_TYPE_PALETTE equ (PNG_COLOR_MASK_COLOR or PNG_COLOR_MASK_PALETTE)
-PNG_COLOR_TYPE_RGB equ (PNG_COLOR_MASK_COLOR)
-PNG_COLOR_TYPE_RGB_ALPHA equ (PNG_COLOR_MASK_COLOR or PNG_COLOR_MASK_ALPHA)
-PNG_COLOR_TYPE_GRAY_ALPHA equ (PNG_COLOR_MASK_ALPHA)
-; aliases
-PNG_COLOR_TYPE_RGBA equ PNG_COLOR_TYPE_RGB_ALPHA
-PNG_COLOR_TYPE_GA equ PNG_COLOR_TYPE_GRAY_ALPHA
-
-; This is for compression type. PNG 1.0-1.2 only define the single type.
-PNG_COMPRESSION_TYPE_BASE equ 0 ;Deflate method 8, 32K window
-PNG_COMPRESSION_TYPE_DEFAULT equ PNG_COMPRESSION_TYPE_BASE
-
-; This is for filter type. PNG 1.0-1.2 only define the single type.
-PNG_FILTER_TYPE_BASE equ 0 ;Single row per-byte filtering
-PNG_INTRAPIXEL_DIFFERENCING equ 64 ;Used only in MNG datastreams
-PNG_FILTER_TYPE_DEFAULT equ PNG_FILTER_TYPE_BASE
-
-; These are for the interlacing type. These values should NOT be changed.
-PNG_INTERLACE_NONE equ 0 ;Non-interlaced image
-PNG_INTERLACE_ADAM7 equ 1 ;Adam7 interlacing
-PNG_INTERLACE_LAST equ 2 ;Not a valid value
-
-; These are for the oFFs chunk. These values should NOT be changed.
-PNG_OFFSET_PIXEL equ 0 ;Offset in pixels
-PNG_OFFSET_MICROMETER equ 1 ;Offset in micrometers (1/10^6 meter)
-PNG_OFFSET_LAST equ 2 ;Not a valid value
-
-; These are for the pCAL chunk. These values should NOT be changed.
-PNG_EQUATION_LINEAR equ 0 ;Linear transformation
-PNG_EQUATION_BASE_E equ 1 ;Exponential base e transform
-PNG_EQUATION_ARBITRARY equ 2 ;Arbitrary base exponential transform
-PNG_EQUATION_HYPERBOLIC equ 3 ;Hyperbolic sine transformation
-PNG_EQUATION_LAST equ 4 ;Not a valid value
-
-; These are for the sCAL chunk. These values should NOT be changed.
-PNG_SCALE_UNKNOWN equ 0 ;unknown unit (image scale)
-PNG_SCALE_METER equ 1 ;meters per pixel
-PNG_SCALE_RADIAN equ 2 ;radians per pixel
-PNG_SCALE_LAST equ 3 ;Not a valid value
-
-; These are for the pHYs chunk. These values should NOT be changed.
-PNG_RESOLUTION_UNKNOWN equ 0 ;pixels/unknown unit (aspect ratio)
-PNG_RESOLUTION_METER equ 1 ;pixels/meter
-PNG_RESOLUTION_LAST equ 2 ;Not a valid value
-
-; These are for the sRGB chunk. These values should NOT be changed.
-PNG_sRGB_INTENT_PERCEPTUAL equ 0
-PNG_sRGB_INTENT_RELATIVE equ 1
-PNG_sRGB_INTENT_SATURATION equ 2
-PNG_sRGB_INTENT_ABSOLUTE equ 3
-PNG_sRGB_INTENT_LAST equ 4 ;Not a valid value
-
-; This is for text chunks
-PNG_KEYWORD_MAX_LENGTH equ 79
-
-; Maximum number of entries in PLTE/sPLT/tRNS arrays
-PNG_MAX_PALETTE_LENGTH equ 256
-
-; These determine if an ancillary chunk's data has been successfully read
-; from the PNG header, or if the application has filled in the corresponding
-; data in the info_struct to be written into the output file. The values
-; of the PNG_INFO_ defines should NOT be changed.
-
-PNG_INFO_gAMA equ 0x0001
-PNG_INFO_sBIT equ 0x0002
-PNG_INFO_cHRM equ 0x0004
-PNG_INFO_PLTE equ 0x0008
-PNG_INFO_tRNS equ 0x0010
-PNG_INFO_bKGD equ 0x0020
-PNG_INFO_hIST equ 0x0040
-PNG_INFO_pHYs equ 0x0080
-PNG_INFO_oFFs equ 0x0100
-PNG_INFO_tIME equ 0x0200
-PNG_INFO_pCAL equ 0x0400
-PNG_INFO_sRGB equ 0x0800 ; GR-P, 0.96a
-PNG_INFO_iCCP equ 0x1000 ; ESR, 1.0.6
-PNG_INFO_sPLT equ 0x2000 ; ESR, 1.0.6
-PNG_INFO_sCAL equ 0x4000 ; ESR, 1.0.6
-PNG_INFO_IDAT equ 0x8000 ; ESR, 1.0.6
-
-; This is used for the transformation routines, as some of them
-; change these values for the row. It also should enable using
-; the routines for other purposes.
-
-struct png_row_info ;png_row_info_struct
- width dd ? ;uint_32 ;width of row
- rowbytes dd ? ;png_size_t ;number of bytes in row
- color_type db ? ;byte ;color type of row
- bit_depth db ? ;byte ;bit depth of row
- channels db ? ;byte ;number of channels (1, 2, 3, or 4)
- pixel_depth db ? ;byte ;bits per pixel (depth * channels)
-ends
-
-if PNG_SETJMP_SUPPORTED eq 1
-; This must match the function definition in , and the application
-; must include this before png.h to obtain the definition of jmp_buf. The
-; function is required to be PNG_NORETURN, but this is not checked. If the
-; function does return the application will crash via an abort() or similar
-; system level call.
-
-; If you get a warning here while building the library you may need to make
-; changes to ensure that pnglibconf.h records the calling convention used by
-; your compiler. This may be very difficult - try using a different compiler
-; to build the library!
-
-;PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), typedef);
-end if
-
-; Transform masks for the high-level interface
-PNG_TRANSFORM_IDENTITY equ 0x0000 ; read and write
-PNG_TRANSFORM_STRIP_16 equ 0x0001 ; read only
-PNG_TRANSFORM_STRIP_ALPHA equ 0x0002 ; read only
-PNG_TRANSFORM_PACKING equ 0x0004 ; read and write
-PNG_TRANSFORM_PACKSWAP equ 0x0008 ; read and write
-PNG_TRANSFORM_EXPAND equ 0x0010 ; read only
-PNG_TRANSFORM_INVERT_MONO equ 0x0020 ; read and write
-PNG_TRANSFORM_SHIFT equ 0x0040 ; read and write
-PNG_TRANSFORM_BGR equ 0x0080 ; read and write
-PNG_TRANSFORM_SWAP_ALPHA equ 0x0100 ; read and write
-PNG_TRANSFORM_SWAP_ENDIAN equ 0x0200 ; read and write
-PNG_TRANSFORM_INVERT_ALPHA equ 0x0400 ; read and write
-PNG_TRANSFORM_STRIP_FILLER equ 0x0800 ; write only
-; Added to libpng-1.2.34
-PNG_TRANSFORM_STRIP_FILLER_BEFORE equ PNG_TRANSFORM_STRIP_FILLER
-PNG_TRANSFORM_STRIP_FILLER_AFTER equ 0x1000 ; write only
-; Added to libpng-1.4.0
-PNG_TRANSFORM_GRAY_TO_RGB equ 0x2000 ; read only
-; Added to libpng-1.5.4
-PNG_TRANSFORM_EXPAND_16 equ 0x4000 ;read only
-;if INT_MAX >= 0x8000 ;else this might break
-PNG_TRANSFORM_SCALE_16 equ 0x8000 ;read only
-;end if
-
-; Flags for MNG supported features
-PNG_FLAG_MNG_EMPTY_PLTE equ 0x01
-PNG_FLAG_MNG_FILTER_64 equ 0x04
-PNG_ALL_MNG_FEATURES equ 0x05
-
-; NOTE: prior to 1.5 these functions had no 'API' style declaration,
-; this allowed the zlib default functions to be used on Windows
-; platforms. In 1.5 the zlib default malloc (which just calls malloc and
-; ignores the first argument) should be completely compatible with the
-; following.
-
-; Section 4: exported functions
-; Here are the function definitions most commonly used. This is not
-; the place to find out how to use libpng. See libpng-manual.txt for the
-; full explanation, see example.c for the summary. This just provides
-; a simple one line description of the use of each function.
-
-
-
-; Simple signature checking function. This is the same as calling
-; png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n).
-
-;#define png_check_sig(sig, n) !png_sig_cmp((sig), 0, (n))
-
-macro png_setup_abs sum
-{
-local .end0
- and eax,0xff
-if PNG_USE_ABS eq 1
- add sum,128
- sub al,128 ;v - 128
- cmp al,128
- jl @f
- neg al
- inc al ;abs(v - 128)
- @@:
- sub sum,eax
-else
- cmp eax,128
- jl @f
- add sum,256
- sub sum,eax
- jmp .end0
- @@:
- add sum,eax
- .end0:
-end if
-}
-
-; Reduce RGB to grayscale.
-PNG_ERROR_ACTION_NONE equ 1
-PNG_ERROR_ACTION_WARN equ 2
-PNG_ERROR_ACTION_ERROR equ 3
-PNG_RGB_TO_GRAY_DEFAULT equ (-1) ;for red/green coefficients
-
-; How the alpha channel is interpreted - this affects how the color channels
-; of a PNG file are returned to the calling application when an alpha channel,
-; or a tRNS chunk in a palette file, is present.
-
-; This has no effect on the way pixels are written into a PNG output
-; datastream. The color samples in a PNG datastream are never premultiplied
-; with the alpha samples.
-
-; The default is to return data according to the PNG specification: the alpha
-; channel is a linear measure of the contribution of the pixel to the
-; corresponding composited pixel, and the color channels are unassociated
-; (not premultiplied). The gamma encoded color channels must be scaled
-; according to the contribution and to do this it is necessary to undo
-; the encoding, scale the color values, perform the composition and reencode
-; the values. This is the 'PNG' mode.
-
-; The alternative is to 'associate' the alpha with the color information by
-; storing color channel values that have been scaled by the alpha.
-; image. These are the 'STANDARD', 'ASSOCIATED' or 'PREMULTIPLIED' modes
-; (the latter being the two common names for associated alpha color channels).
-
-; For the 'OPTIMIZED' mode, a pixel is treated as opaque only if the alpha
-; value is equal to the maximum value.
-
-; The final choice is to gamma encode the alpha channel as well. This is
-; broken because, in practice, no implementation that uses this choice
-; correctly undoes the encoding before handling alpha composition. Use this
-; choice only if other serious errors in the software or hardware you use
-; mandate it; the typical serious error is for dark halos to appear around
-; opaque areas of the composited PNG image because of arithmetic overflow.
-
-; The API function png_set_alpha_mode specifies which of these choices to use
-; with an enumerated 'mode' value and the gamma of the required output:
-
-PNG_ALPHA_PNG equ 0 ;according to the PNG standard
-PNG_ALPHA_STANDARD equ 1 ;according to Porter/Duff
-PNG_ALPHA_ASSOCIATED equ 1 ;as above; this is the normal practice
-PNG_ALPHA_PREMULTIPLIED equ 1 ;as above
-PNG_ALPHA_OPTIMIZED equ 2 ;'PNG' for opaque pixels, else 'STANDARD'
-PNG_ALPHA_BROKEN equ 3 ;the alpha channel is gamma encoded
-
-if (PNG_GAMMA_SUPPORTED eq 1) | (PNG_READ_ALPHA_MODE_SUPPORTED eq 1)
-; The output_gamma value is a screen gamma in libpng terminology: it expresses
-; how to decode the output values, not how they are encoded.
-
-PNG_DEFAULT_sRGB equ -1 ;sRGB gamma and color space
-PNG_GAMMA_MAC_18 equ -2 ;Old Mac '1.8' gamma and color space
-PNG_GAMMA_sRGB equ 220000 ;Television standards--matches sRGB gamma
-PNG_GAMMA_LINEAR equ PNG_FP_1 ;Linear
-end if
-
-; The values of the PNG_FILLER_ defines should NOT be changed
-PNG_FILLER_BEFORE equ 0
-PNG_FILLER_AFTER equ 1
-
-;#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
-
-; Handle alpha and tRNS by replacing with a background color. Prior to
-; libpng-1.5.4 this API must not be called before the PNG file header has been
-; read. Doing so will result in unexpected behavior and possible warnings or
-; errors if the PNG file contains a bKGD chunk.
-
-if PNG_READ_BACKGROUND_SUPPORTED eq 1
-PNG_BACKGROUND_GAMMA_UNKNOWN equ 0
-PNG_BACKGROUND_GAMMA_SCREEN equ 1
-PNG_BACKGROUND_GAMMA_FILE equ 2
-PNG_BACKGROUND_GAMMA_UNIQUE equ 3
-end if
-
-;PNG_READ_16_TO_8_SUPPORTED equ 1 ;Name prior to 1.5.4
-
-; The threshold on gamma processing is configurable but hard-wired into the
-; library. The following is the floating point variant.
-
-PNG_GAMMA_THRESHOLD equ (PNG_GAMMA_THRESHOLD_FIXED*.00001)
-
-; Handle gamma correction. Screen_gamma=(display_exponent).
-; NOTE: this API simply sets the screen and file gamma values. It will
-; therefore override the value for gamma in a PNG file if it is called after
-; the file header has been read - use with care - call before reading the PNG
-; file for best results!
-
-
-; Values for png_set_crc_action() say how to handle CRC errors in
-; ancillary and critical chunks, and whether to use the data contained
-; therein. Note that it is impossible to "discard" data in a critical
-; chunk. For versions prior to 0.90, the action was always error/quit,
-; whereas in version 0.90 and later, the action for CRC errors in ancillary
-; chunks is warn/discard. These values should NOT be changed.
-
-; value action:critical action:ancillary
-
-PNG_CRC_DEFAULT equ 0 ;error/quit warn/discard data
-PNG_CRC_ERROR_QUIT equ 1 ;error/quit error/quit
-PNG_CRC_WARN_DISCARD equ 2 ;(INVALID) warn/discard data
-PNG_CRC_WARN_USE equ 3 ;warn/use data warn/use data
-PNG_CRC_QUIET_USE equ 4 ;quiet/use data quiet/use data
-PNG_CRC_NO_CHANGE equ 5 ;use current value use current value
-
-; Flags for png_set_filter() to say which filters to use. The flags
-; are chosen so that they don't conflict with real filter types
-; below, in case they are supplied instead of the #defined constants.
-; These values should NOT be changed.
-
-PNG_NO_FILTERS equ 0x00
-PNG_FILTER_NONE equ 0x08
-PNG_FILTER_SUB equ 0x10
-PNG_FILTER_UP equ 0x20
-PNG_FILTER_AVG equ 0x40
-PNG_FILTER_PAETH equ 0x80
-PNG_FAST_FILTERS equ (PNG_FILTER_NONE or PNG_FILTER_SUB or PNG_FILTER_UP)
-PNG_ALL_FILTERS equ (PNG_FAST_FILTERS or PNG_FILTER_AVG or PNG_FILTER_PAETH)
-
-; Filter values (not flags) - used in pngwrite.c, pngwutil.c for now.
-; These defines should NOT be changed.
-
-PNG_FILTER_VALUE_NONE equ 0
-PNG_FILTER_VALUE_SUB equ 1
-PNG_FILTER_VALUE_UP equ 2
-PNG_FILTER_VALUE_AVG equ 3
-PNG_FILTER_VALUE_PAETH equ 4
-PNG_FILTER_VALUE_LAST equ 5
-
-; The following are no longer used and will be removed from libpng-1.7:
-PNG_FILTER_HEURISTIC_DEFAULT equ 0 ;Currently "UNWEIGHTED"
-PNG_FILTER_HEURISTIC_UNWEIGHTED equ 1 ;Used by libpng < 0.95
-PNG_FILTER_HEURISTIC_WEIGHTED equ 2 ;Experimental feature
-PNG_FILTER_HEURISTIC_LAST equ 3 ;Not a valid value
-
-; It is unlikely that this function works correctly as of 1.6.0 and using it
-; may result either in memory leaks or double free of allocated data.
-
-; Assignments for png_data_freer
-PNG_DESTROY_WILL_FREE_DATA equ 1
-PNG_SET_WILL_FREE_DATA equ 1
-PNG_USER_WILL_FREE_DATA equ 2
-; Flags for png_ptr->free_me and info_ptr->free_me
-PNG_FREE_HIST equ 0x0008
-PNG_FREE_ICCP equ 0x0010
-PNG_FREE_SPLT equ 0x0020
-PNG_FREE_ROWS equ 0x0040
-PNG_FREE_PCAL equ 0x0080
-PNG_FREE_SCAL equ 0x0100
-if PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED eq 1
- PNG_FREE_UNKN equ 0x0200
-end if
-PNG_FREE_LIST equ 0x0400 ;removed in 1.6.0 because it is ignored
-PNG_FREE_PLTE equ 0x1000
-PNG_FREE_TRNS equ 0x2000
-PNG_FREE_TEXT equ 0x4000
-PNG_FREE_ALL equ 0x7fff
-PNG_FREE_MUL equ 0x4220 ;PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN
-
-;if PNG_ERROR_TEXT_SUPPORTED
-
-;#else
-;# define png_chunk_error(s1,s2) png_err(s1)
-;end if
-
-;#else
-;# define png_warning(s1,s2) ((void)(s1))
-;# define png_chunk_warning(s1,s2) ((void)(s1))
-
-;if PNG_READ_SUPPORTED
-
-;#else
-;# ifdef PNG_ALLOW_BENIGN_ERRORS
-macro png_benign_error h,txt
-{
- png_warning h,txt
-}
-;# define png_chunk_benign_error png_chunk_warning
-;# else
-;# define png_benign_error png_error
-;# define png_chunk_benign_error png_chunk_error
-;# endif
-;end if
-
-
-; Provide the default handling for all unknown chunks or, optionally, for
-; specific unknown chunks.
-
-; NOTE: prior to 1.6.0 the handling specified for particular chunks on read was
-; ignored and the default was used, the per-chunk setting only had an effect on
-; write. If you wish to have chunk-specific handling on read in code that must
-; work on earlier versions you must use a user chunk callback to specify the
-; desired handling (keep or discard.)
-
-; The 'keep' parameter is a PNG_HANDLE_CHUNK_ value as listed below. The
-; parameter is interpreted as follows:
-
-; READ:
-; PNG_HANDLE_CHUNK_AS_DEFAULT:
-; Known chunks: do normal libpng processing, do not keep the chunk (but
-; see the comments below about PNG_HANDLE_AS_UNKNOWN_SUPPORTED)
-; Unknown chunks: for a specific chunk use the global default, when used
-; as the default discard the chunk data.
-; PNG_HANDLE_CHUNK_NEVER:
-; Discard the chunk data.
-; PNG_HANDLE_CHUNK_IF_SAFE:
-; Keep the chunk data if the chunk is not critical else raise a chunk
-; error.
-; PNG_HANDLE_CHUNK_ALWAYS:
-; Keep the chunk data.
-
-; If the chunk data is saved it can be retrieved using png_get_unknown_chunks,
-; below. Notice that specifying "AS_DEFAULT" as a global default is equivalent
-; to specifying "NEVER", however when "AS_DEFAULT" is used for specific chunks
-; it simply resets the behavior to the libpng default.
-
-; INTERACTION WTIH USER CHUNK CALLBACKS:
-; The per-chunk handling is always used when there is a png_user_chunk_ptr
-; callback and the callback returns 0; the chunk is then always stored *unless*
-; it is critical and the per-chunk setting is other than ALWAYS. Notice that
-; the global default is *not* used in this case. (In effect the per-chunk
-; value is incremented to at least IF_SAFE.)
-
-; IMPORTANT NOTE: this behavior will change in libpng 1.7 - the global and
-; per-chunk defaults will be honored. If you want to preserve the current
-; behavior when your callback returns 0 you must set PNG_HANDLE_CHUNK_IF_SAFE
-; as the default - if you don't do this libpng 1.6 will issue a warning.
-
-; If you want unhandled unknown chunks to be discarded in libpng 1.6 and
-; earlier simply return '1' (handled).
-
-; PNG_HANDLE_AS_UNKNOWN_SUPPORTED:
-; If this is *not* set known chunks will always be handled by libpng and
-; will never be stored in the unknown chunk list. Known chunks listed to
-; png_set_keep_unknown_chunks will have no effect. If it is set then known
-; chunks listed with a keep other than AS_DEFAULT will *never* be processed
-; by libpng, in addition critical chunks must either be processed by the
-; callback or saved.
-
-; The IHDR and IEND chunks must not be listed. Because this turns off the
-; default handling for chunks that would otherwise be recognized the
-; behavior of libpng transformations may well become incorrect!
-
-; WRITE:
-; When writing chunks the options only apply to the chunks specified by
-; png_set_unknown_chunks (below), libpng will *always* write known chunks
-; required by png_set_ calls and will always write the core critical chunks
-; (as required for PLTE).
-
-; Each chunk in the png_set_unknown_chunks list is looked up in the
-; png_set_keep_unknown_chunks list to find the keep setting, this is then
-; interpreted as follows:
-
-; PNG_HANDLE_CHUNK_AS_DEFAULT:
-; Write safe-to-copy chunks and write other chunks if the global
-; default is set to _ALWAYS, otherwise don't write this chunk.
-; PNG_HANDLE_CHUNK_NEVER:
-; Do not write the chunk.
-; PNG_HANDLE_CHUNK_IF_SAFE:
-; Write the chunk if it is safe-to-copy, otherwise do not write it.
-; PNG_HANDLE_CHUNK_ALWAYS:
-; Write the chunk.
-
-; Note that the default behavior is effectively the opposite of the read case -
-; in read unknown chunks are not stored by default, in write they are written
-; by default. Also the behavior of PNG_HANDLE_CHUNK_IF_SAFE is very different
-; - on write the safe-to-copy bit is checked, on read the critical bit is
-; checked and on read if the chunk is critical an error will be raised.
-
-; num_chunks:
-; ===========
-; If num_chunks is positive, then the "keep" parameter specifies the manner
-; for handling only those chunks appearing in the chunk_list array,
-; otherwise the chunk list array is ignored.
-
-; If num_chunks is 0 the "keep" parameter specifies the default behavior for
-; unknown chunks, as described above.
-
-; If num_chunks is negative, then the "keep" parameter specifies the manner
-; for handling all unknown chunks plus all chunks recognized by libpng
-; except for the IHDR, PLTE, tRNS, IDAT, and IEND chunks (which continue to
-; be processed by libpng.
-
-
-; For use in png_set_keep_unknown, added to version 1.2.6
-PNG_HANDLE_CHUNK_AS_DEFAULT equ 0
-PNG_HANDLE_CHUNK_NEVER equ 1
-PNG_HANDLE_CHUNK_IF_SAFE equ 2
-PNG_HANDLE_CHUNK_ALWAYS equ 3
-PNG_HANDLE_CHUNK_LAST equ 4
-
-; Removed from libpng 1.6; use png_get_io_chunk_type.
-;PNG_REMOVED(200, bytep, png_get_io_chunk_name, (png_structrp png_ptr),
-; PNG_DEPRECATED)
-
-; The flags returned by png_get_io_state() are the following:
-PNG_IO_NONE equ 0x0000 ; no I/O at this moment
-PNG_IO_READING equ 0x0001 ; currently reading
-PNG_IO_WRITING equ 0x0002 ; currently writing
-PNG_IO_SIGNATURE equ 0x0010 ; currently at the file signature
-PNG_IO_CHUNK_HDR equ 0x0020 ; currently at the chunk header
-PNG_IO_CHUNK_DATA equ 0x0040 ; currently at the chunk data
-PNG_IO_CHUNK_CRC equ 0x0080 ; currently at the chunk crc
-PNG_IO_MASK_OP equ 0x000f ; current operation: reading/writing
-PNG_IO_MASK_LOC equ 0x00f0 ; current location: sig/hdr/data/crc
-;end if /* IO_STATE */
-
-; Interlace support. The following macros are always defined so that if
-; libpng interlace handling is turned off the macros may be used to handle
-; interlaced images within the application.
-
-PNG_INTERLACE_ADAM7_PASSES equ 7
-
-; Two macros to return the first row and first column of the original,
-; full, image which appears in a given pass. 'pass' is in the range 0
-; to 6 and the result is in the range 0 to 7.
-
-macro PNG_PASS_START_ROW pass
-{
- push ebx ecx
- mov eax,pass
- mov ebx,eax
- not eax
- and eax,1
- shr ebx,1
- mov ecx,3
- sub ecx,ebx
- shl eax,cl
- and eax,7
- pop ecx ebx
-}
-macro PNG_PASS_START_COL pass
-{
- push ebx ecx
- mov eax,pass
- mov ebx,eax
- and eax,1
- inc ebx
- shr ebx,1
- mov ecx,3
- sub ecx,ebx
- shl eax,cl
- and eax,7
- pop ecx ebx
-}
-
-; A macro to return the offset between pixels in the output row for a pair of
-; pixels in the input - effectively the inverse of the 'COL_SHIFT' macro that
-; follows. Note that ROW_OFFSET is the offset from one row to the next whereas
-; COL_OFFSET is from one column to the next, within a row.
-
-;#define PNG_PASS_ROW_OFFSET(pass) ((pass)>2?(8>>(((pass)-1)>>1)):8)
-;#define PNG_PASS_COL_OFFSET(pass) (1<<((7-(pass))>>1))
-
-; Two macros to help evaluate the number of rows or columns in each
-; pass. This is expressed as a shift - effectively log2 of the number or
-; rows or columns in each 8x8 tile of the original image.
-
-macro PNG_PASS_ROW_SHIFT pass
-{
-local .end0
- mov eax,3
- cmp pass,2
- jle .end0
- mov eax,8
- sub eax,pass
- shr eax,1
- .end0:
-}
-macro PNG_PASS_COL_SHIFT pass
-{
-local .end0
- mov eax,3
- cmp pass,1
- jle .end0
- mov eax,7
- sub eax,pass
- shr eax,1
- .end0:
-}
-
-; Hence two macros to determine the number of rows or columns in a given
-; pass of an image given its height or width. In fact these macros may
-; return non-zero even though the sub-image is empty, because the other
-; dimension may be empty for a small image.
-
-macro PNG_PASS_ROWS height, pass
-{
-push ecx
-push ebx
- PNG_PASS_START_ROW pass
- mov ebx,eax
- PNG_PASS_ROW_SHIFT pass
- mov ecx,eax
- xor eax,eax
- inc eax
- shl eax,cl
- dec eax
- sub eax,ebx
-pop ebx
- add eax,height
- shr eax,cl
-pop ecx
-}
-macro PNG_PASS_COLS width, pass
-{
-push ecx
-push ebx
- PNG_PASS_START_COL pass
- mov ebx,eax
- PNG_PASS_COL_SHIFT pass
- mov ecx,eax
- xor eax,eax
- inc eax
- shl eax,cl
- dec eax
- sub eax,ebx
-pop ebx
- add eax,width
- shr eax,cl
-pop ecx
-}
-
-; For the reader row callbacks (both progressive and sequential) it is
-; necessary to find the row in the output image given a row in an interlaced
-; image, so two more macros:
-
-;#define PNG_ROW_FROM_PASS_ROW(y_in, pass) \
-; (((y_in)<>(((7-(off))-(pass))<<2)) & 0xF) | \
-; ((0x01145AF0>>(((7-(off))-(pass))<<2)) & 0xF0))
-
-;#define PNG_ROW_IN_INTERLACE_PASS(y, pass) \
-; ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1)
-;#define PNG_COL_IN_INTERLACE_PASS(x, pass) \
-; ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1)
-
-;if PNG_READ_COMPOSITE_NODIV_SUPPORTED
-; With these routines we avoid an integer divide, which will be slower on
-; most machines. However, it does take more operations than the corresponding
-; divide method, so it may be slower on a few RISC systems. There are two
-; shifts (by 8 or 16 bits) and an addition, versus a single integer divide.
-
-; Note that the rounding factors are NOT supposed to be the same! 128 and
-; 32768 are correct for the NODIV code; 127 and 32767 are correct for the
-; standard method.
-
-; [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ]
-
-
-; fg and bg should be in `gamma 1.0' space; alpha is the opacity
-
-;# define png_composite(composite, fg, alpha, bg) \
-; { \
-; uint_16 temp = (uint_16)((uint_16)(fg) \
-; * (uint_16)(alpha) \
-; + (uint_16)(bg)*(uint_16)(255 \
-; - (uint_16)(alpha)) + 128); \
-; (composite) = (byte)(((temp + (temp >> 8)) >> 8) & 0xff); \
-; }
-
-;# define png_composite_16(composite, fg, alpha, bg) \
-; { \
-; uint_32 temp = (uint_32)((uint_32)(fg) \
-; * (uint_32)(alpha) \
-; + (uint_32)(bg)*(65535 \
-; - (uint_32)(alpha)) + 32768); \
-; (composite) = (uint_16)(0xffff & ((temp + (temp >> 16)) >> 16)); \
-; }
-
-;#else /* Standard method using integer division */
-
-;# define png_composite(composite, fg, alpha, bg) \
-; (composite) = \
-; (byte)(0xff & (((uint_16)(fg) * (uint_16)(alpha) + \
-; (uint_16)(bg) * (uint_16)(255 - (uint_16)(alpha)) + \
-; 127) / 255))
-
-;# define png_composite_16(composite, fg, alpha, bg) \
-; (composite) = \
-; (uint_16)(0xffff & (((uint_32)(fg) * (uint_32)(alpha) + \
-; (uint_32)(bg)*(uint_32)(65535 - (uint_32)(alpha)) + \
-; 32767) / 65535))
-;end if /* READ_COMPOSITE_NODIV */
-
-if PNG_USE_READ_MACROS eq 1
-; Inline macros to do direct reads of bytes from the input buffer.
-; The png_get_int_32() routine assumes we are using two's complement
-; format for negative values, which is almost certainly true.
-
-;# define PNG_get_uint_32(buf) \
-; (((uint_32)(*(buf)) << 24) + \
-; ((uint_32)(*((buf) + 1)) << 16) + \
-; ((uint_32)(*((buf) + 2)) << 8) + \
-; ((uint_32)(*((buf) + 3))))
-
- ; From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the
- ; function) incorrectly returned a value of type uint_32.
-
-;# define PNG_get_uint_16(buf) \
-; ((uint_16) \
-; (((unsigned int)(*(buf)) << 8) + \
-; ((unsigned int)(*((buf) + 1)))))
-
-;# define PNG_get_int_32(buf) \
-; ((int_32)((*(buf) & 0x80) \
-; ? -((int_32)(((png_get_uint_32(buf)^0xffffffffU)+1U)&0x7fffffffU)) \
-; : (int_32)png_get_uint_32(buf)))
-end if
-
-;/*******************************************************************************
-; Section 5: SIMPLIFIED API
-; *******************************************************************************
-
-; Please read the documentation in libpng-manual.txt (TODO: write said
-; documentation) if you don't understand what follows.
-
-; The simplified API hides the details of both libpng and the PNG file format
-; itself. It allows PNG files to be read into a very limited number of
-; in-memory bitmap formats or to be written from the same formats. If these
-; formats do not accomodate your needs then you can, and should, use the more
-; sophisticated APIs above - these support a wide variety of in-memory formats
-; and a wide variety of sophisticated transformations to those formats as well
-; as a wide variety of APIs to manipulate ancillary information.
-
-; To read a PNG file using the simplified API:
-
-; 1) Declare a 'png_image' structure (see below) on the stack, set the
-; version field to PNG_IMAGE_VERSION and the 'opaque' pointer to NULL
-; (this is REQUIRED, your program may crash if you don't do it.)
-; 2) Call the appropriate png_image_begin_read... function.
-; 3) Set the png_image 'format' member to the required sample format.
-; 4) Allocate a buffer for the image and, if required, the color-map.
-; 5) Call png_image_finish_read to read the image and, if required, the
-; color-map into your buffers.
-
-; There are no restrictions on the format of the PNG input itself; all valid
-; color types, bit depths, and interlace methods are acceptable, and the
-; input image is transformed as necessary to the requested in-memory format
-; during the png_image_finish_read() step. The only caveat is that if you
-; request a color-mapped image from a PNG that is full-color or makes
-; complex use of an alpha channel the transformation is extremely lossy and the
-; result may look terrible.
-
-; To write a PNG file using the simplified API:
-
-; 1) Declare a 'png_image' structure on the stack and memset() it to all zero.
-; 2) Initialize the members of the structure that describe the image, setting
-; the 'format' member to the format of the image samples.
-; 3) Call the appropriate png_image_write... function with a pointer to the
-; image and, if necessary, the color-map to write the PNG data.
-
-; png_image is a structure that describes the in-memory format of an image
-; when it is being read or defines the in-memory format of an image that you
-; need to write:
-
-;#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) || \
-; defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
-
-PNG_IMAGE_VERSION equ 1
-
-struct png_image
- opaque dd ? ;png_controlp ;Initialize to NULL, free with png_image_free
- version dd ? ;uint_32 ;Set to PNG_IMAGE_VERSION
- width dd ? ;uint_32 ;Image width in pixels (columns)
- height dd ? ;uint_32 ;Image height in pixels (rows)
- format dd ? ;uint_32 ;Image format as defined below
- flags dd ? ;uint_32 ;A bit mask containing informational flags
- colormap_entries dd ? ;uint_32 ;Number of entries in the color-map
-
- ; In the event of an error or warning the following field will be set to a
- ; non-zero value and the 'message' field will contain a '\0' terminated
- ; string with the libpng error or warning message. If both warnings and
- ; an error were encountered, only the error is recorded. If there
- ; are multiple warnings, only the first one is recorded.
-
- ; The upper 30 bits of this value are reserved, the low two bits contain
- ; a value as follows:
-
-PNG_IMAGE_WARNING equ 1
-PNG_IMAGE_ERROR equ 2
-
-; The result is a two-bit code such that a value more than 1 indicates
-; a failure in the API just called:
-
-; 0 - no warning or error
-; 1 - warning
-; 2 - error
-; 3 - error preceded by warning
-
-;# define PNG_IMAGE_FAILED(png_cntrl) ((((png_cntrl).warning_or_error)&0x03)>1)
-
- warning_or_error dd ? ;uint_32
- message rb 64 ;char[64]
-ends
-
-; The samples of the image have one to four channels whose components have
-; original values in the range 0 to 1.0:
-
-; 1: A single gray or luminance channel (G).
-; 2: A gray/luminance channel and an alpha channel (GA).
-; 3: Three red, green, blue color channels (RGB).
-; 4: Three color channels and an alpha channel (RGBA).
-
-; The components are encoded in one of two ways:
-
-; a) As a small integer, value 0..255, contained in a single byte. For the
-; alpha channel the original value is simply value/255. For the color or
-; luminance channels the value is encoded according to the sRGB specification
-; and matches the 8-bit format expected by typical display devices.
-
-; The color/gray channels are not scaled (pre-multiplied) by the alpha
-; channel and are suitable for passing to color management software.
-
-; b) As a value in the range 0..65535, contained in a 2-byte integer. All
-; channels can be converted to the original value by dividing by 65535; all
-; channels are linear. Color channels use the RGB encoding (RGB end-points) of
-; the sRGB specification. This encoding is identified by the
-; PNG_FORMAT_FLAG_LINEAR flag below.
-
-; When the simplified API needs to convert between sRGB and linear colorspaces,
-; the actual sRGB transfer curve defined in the sRGB specification (see the
-; article at http://en.wikipedia.org/wiki/SRGB) is used, not the gamma=1/2.2
-; approximation used elsewhere in libpng.
-
-; When an alpha channel is present it is expected to denote pixel coverage
-; of the color or luminance channels and is returned as an associated alpha
-; channel: the color/gray channels are scaled (pre-multiplied) by the alpha
-; value.
-
-; The samples are either contained directly in the image data, between 1 and 8
-; bytes per pixel according to the encoding, or are held in a color-map indexed
-; by bytes in the image data. In the case of a color-map the color-map entries
-; are individual samples, encoded as above, and the image data has one byte per
-; pixel to select the relevant sample from the color-map.
-
-
-; PNG_FORMAT_*
-
-; #defines to be used in png_image::format. Each #define identifies a
-; particular layout of sample data and, if present, alpha values. There are
-; separate defines for each of the two component encodings.
-
-; A format is built up using single bit flag values. All combinations are
-; valid. Formats can be built up from the flag values or you can use one of
-; the predefined values below. When testing formats always use the FORMAT_FLAG
-; macros to test for individual features - future versions of the library may
-; add new flags.
-
-; When reading or writing color-mapped images the format should be set to the
-; format of the entries in the color-map then png_image_{read,write}_colormap
-; called to read or write the color-map and set the format correctly for the
-; image data. Do not set the PNG_FORMAT_FLAG_COLORMAP bit directly!
-
-; NOTE: libpng can be built with particular features disabled. If you see
-; compiler errors because the definition of one of the following flags has been
-; compiled out it is because libpng does not have the required support. It is
-; possible, however, for the libpng configuration to enable the format on just
-; read or just write; in that case you may see an error at run time. You can
-; guard against this by checking for the definition of the appropriate
-; "_SUPPORTED" macro, one of:
-
-; PNG_SIMPLIFIED_{READ,WRITE}_{BGR,AFIRST}_SUPPORTED
-
-PNG_FORMAT_FLAG_ALPHA equ 0x01 ;format with an alpha channel
-PNG_FORMAT_FLAG_COLOR equ 0x02 ;color format: otherwise grayscale
-PNG_FORMAT_FLAG_LINEAR equ 0x04 ;2-byte channels else 1-byte
-PNG_FORMAT_FLAG_COLORMAP equ 0x08 ;image data is color-mapped
-
-PNG_FORMAT_FLAG_BGR equ 0x10 ;BGR colors, else order is RGB
-
-PNG_FORMAT_FLAG_AFIRST equ 0x20 ;alpha channel comes first
-
-; Commonly used formats have predefined macros.
-
-; First the single byte (sRGB) formats:
-
-PNG_FORMAT_GRAY equ 0
-PNG_FORMAT_GA equ PNG_FORMAT_FLAG_ALPHA
-PNG_FORMAT_AG equ (PNG_FORMAT_GA|PNG_FORMAT_FLAG_AFIRST)
-PNG_FORMAT_RGB equ PNG_FORMAT_FLAG_COLOR
-PNG_FORMAT_BGR equ (PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_BGR)
-PNG_FORMAT_RGBA equ (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_ALPHA)
-PNG_FORMAT_ARGB equ (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_AFIRST)
-PNG_FORMAT_BGRA equ (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_ALPHA)
-PNG_FORMAT_ABGR equ (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_AFIRST)
-
-; Then the linear 2-byte formats. When naming these "Y" is used to
-; indicate a luminance (gray) channel.
-
-PNG_FORMAT_LINEAR_Y equ PNG_FORMAT_FLAG_LINEAR
-PNG_FORMAT_LINEAR_Y_ALPHA equ (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_ALPHA)
-PNG_FORMAT_LINEAR_RGB equ (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR)
-PNG_FORMAT_LINEAR_RGB_ALPHA equ\
- (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA)
-
-; With color-mapped formats the image data is one byte for each pixel, the byte
-; is an index into the color-map which is formatted as above. To obtain a
-; color-mapped format it is sufficient just to add the PNG_FOMAT_FLAG_COLORMAP
-; to one of the above definitions, or you can use one of the definitions below.
-
-PNG_FORMAT_RGB_COLORMAP equ (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_COLORMAP)
-PNG_FORMAT_BGR_COLORMAP equ (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_COLORMAP)
-PNG_FORMAT_RGBA_COLORMAP equ (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_COLORMAP)
-PNG_FORMAT_ARGB_COLORMAP equ (PNG_FORMAT_ARGB|PNG_FORMAT_FLAG_COLORMAP)
-PNG_FORMAT_BGRA_COLORMAP equ (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_COLORMAP)
-PNG_FORMAT_ABGR_COLORMAP equ (PNG_FORMAT_ABGR|PNG_FORMAT_FLAG_COLORMAP)
-
-; PNG_IMAGE macros
-
-; These are convenience macros to derive information from a png_image
-; structure. The PNG_IMAGE_SAMPLE_ macros return values appropriate to the
-; actual image sample values - either the entries in the color-map or the
-; pixels in the image. The PNG_IMAGE_PIXEL_ macros return corresponding values
-; for the pixels and will always return 1 for color-mapped formats. The
-; remaining macros return information about the rows in the image and the
-; complete image.
-
-; NOTE: All the macros that take a png_image::format parameter are compile time
-; constants if the format parameter is, itself, a constant. Therefore these
-; macros can be used in array declarations and case labels where required.
-; Similarly the macros are also pre-processor constants (sizeof is not used) so
-; they can be used in #if tests.
-
-; First the information about the samples.
-
-macro PNG_IMAGE_SAMPLE_CHANNELS fmt
-{
- mov eax,fmt
- and eax,PNG_FORMAT_FLAG_COLOR or PNG_FORMAT_FLAG_ALPHA
- inc eax
-}
-; Return the total number of channels in a given format: 1..4
-
-;#define PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt)\
-; ((((fmt) & PNG_FORMAT_FLAG_LINEAR) >> 2)+1)
-; /* Return the size in bytes of a single component of a pixel or color-map
-; entry (as appropriate) in the image: 1 or 2.
-
-
-;#define PNG_IMAGE_SAMPLE_SIZE(fmt)\
-; (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt))
-; /* This is the size of the sample data for one sample. If the image is
-; color-mapped it is the size of one color-map entry (and image pixels are
-; one byte in size), otherwise it is the size of one image pixel.
-
-
-;#define PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(fmt)\
-; (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * 256)
-; /* The maximum size of the color-map required by the format expressed in a
-; count of components. This can be used to compile-time allocate a
-; color-map:
-
-; uint_16 colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(linear_fmt)];
-
-; byte colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(sRGB_fmt)];
-
-; Alternatively use the PNG_IMAGE_COLORMAP_SIZE macro below to use the
-; information from one of the png_image_begin_read_ APIs and dynamically
-; allocate the required memory.
-
-
-; Corresponding information about the pixels
-macro PNG_IMAGE_PIXEL_ p1,fmt
-{
-local .end0
-local .end1
- mov eax,fmt
- and eax,PNG_FORMAT_FLAG_COLORMAP
- cmp eax,0
- je .end0
- xor eax,eax
- inc eax
- jmp .end1
- .end0:
- p1 fmt
- .end1:
-}
-
-macro PNG_IMAGE_PIXEL_CHANNELS fmt
-{
- PNG_IMAGE_PIXEL_ PNG_IMAGE_SAMPLE_CHANNELS,fmt
-}
-; The number of separate channels (components) in a pixel; 1 for a
-; color-mapped image.
-
-
-;#define PNG_IMAGE_PIXEL_COMPONENT_SIZE(fmt)\
-; PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_COMPONENT_SIZE,fmt)
-; /* The size, in bytes, of each component in a pixel; 1 for a color-mapped
-; image.
-
-
-;#define PNG_IMAGE_PIXEL_SIZE(fmt) PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_SIZE,fmt)
-; /* The size, in bytes, of a complete pixel; 1 for a color-mapped image. */
-
-; Information about the whole row, or whole image
-;#define PNG_IMAGE_ROW_STRIDE(image)\
-; (PNG_IMAGE_PIXEL_CHANNELS((image).format) * (image).width)
-; Return the total number of components in a single row of the image; this
-; is the minimum 'row stride', the minimum count of components between each
-; row. For a color-mapped image this is the minimum number of bytes in a
-; row.
-
-; WARNING: this macro overflows for some images with more than one component
-; and very large image widths. libpng will refuse to process an image where
-; this macro would overflow.
-
-
-;#define PNG_IMAGE_BUFFER_SIZE(image, row_stride)\
-; (PNG_IMAGE_PIXEL_COMPONENT_SIZE((image).format)*(image).height*(row_stride))
-; Return the size, in bytes, of an image buffer given a png_image and a row
-; stride - the number of components to leave space for in each row.
-
-; WARNING: this macro overflows a 32-bit integer for some large PNG images,
-; libpng will refuse to process an image where such an overflow would occur.
-
-
-;#define PNG_IMAGE_SIZE(image)\
-; PNG_IMAGE_BUFFER_SIZE(image, PNG_IMAGE_ROW_STRIDE(image))
-; Return the size, in bytes, of the image in memory given just a png_image;
-; the row stride is the minimum stride required for the image.
-
-
-;#define PNG_IMAGE_COLORMAP_SIZE(image)\
-; (PNG_IMAGE_SAMPLE_SIZE((image).format) * (image).colormap_entries)
-; Return the size, in bytes, of the color-map of this image. If the image
-; format is not a color-map format this will return a size sufficient for
-; 256 entries in the given format; check PNG_FORMAT_FLAG_COLORMAP if
-; you don't want to allocate a color-map in this case.
-
-
-; PNG_IMAGE_FLAG_*
-
-; Flags containing additional information about the image are held in the
-; 'flags' field of png_image.
-
-PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB equ 0x01
-; This indicates the the RGB values of the in-memory bitmap do not
-; correspond to the red, green and blue end-points defined by sRGB.
-
-PNG_IMAGE_FLAG_FAST equ 0x02
-; On write emphasise speed over compression; the resultant PNG file will be
-; larger but will be produced significantly faster, particular for large
-; images. Do not use this option for images which will be distributed, only
-; used it when producing intermediate files that will be read back in
-; repeatedly. For a typical 24-bit image the option will double the read
-; speed at the cost of increasing the image size by 25%, however for many
-; more compressible images the PNG file can be 10 times larger with only a
-; slight speed gain.
-
-PNG_IMAGE_FLAG_16BIT_sRGB equ 0x04
-; On read if the image is a 16-bit per component image and there is no gAMA
-; or sRGB chunk assume that the components are sRGB encoded. Notice that
-; images output by the simplified API always have gamma information; setting
-; this flag only affects the interpretation of 16-bit images from an
-; external source. It is recommended that the application expose this flag
-; to the user; the user can normally easily recognize the difference between
-; linear and sRGB encoding. This flag has no effect on write - the data
-; passed to the write APIs must have the correct encoding (as defined
-; above.)
-
-; If the flag is not set (the default) input 16-bit per component data is
-; assumed to be linear.
-
-; NOTE: the flag can only be set after the png_image_begin_read_ call,
-; because that call initializes the 'flags' field.
-
-if PNG_SIMPLIFIED_WRITE_SUPPORTED eq 1
-; WRITE APIS
-; ----------
-; For write you must initialize a png_image structure to describe the image to
-; be written. To do this use memset to set the whole structure to 0 then
-; initialize fields describing your image.
-
-; version: must be set to PNG_IMAGE_VERSION
-; opaque: must be initialized to NULL
-; width: image width in pixels
-; height: image height in rows
-; format: the format of the data (image and color-map) you wish to write
-; flags: set to 0 unless one of the defined flags applies; set
-; PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB for color format images where the RGB
-; values do not correspond to the colors in sRGB.
-; colormap_entries: set to the number of entries in the color-map (0 to 256)
-
-; With all write APIs if image is in one of the linear formats with 16-bit
-; data then setting convert_to_8_bit will cause the output to be an 8-bit PNG
-; gamma encoded according to the sRGB specification, otherwise a 16-bit linear
-; encoded PNG file is written.
-
-; With color-mapped data formats the colormap parameter point to a color-map
-; with at least image->colormap_entries encoded in the specified format. If
-; the format is linear the written PNG color-map will be converted to sRGB
-; regardless of the convert_to_8_bit flag.
-
-; With all APIs row_stride is handled as in the read APIs - it is the spacing
-; from one row to the next in component sized units (1 or 2 bytes) and if
-; negative indicates a bottom-up row layout in the buffer. If row_stride is
-; zero, libpng will calculate it for you from the image width and number of
-; channels.
-
-; Note that the write API does not support interlacing, sub-8-bit pixels or
-; most ancillary chunks. If you need to write text chunks (e.g. for copyright
-; notices) you need to use one of the other APIs.
-
-
-;#define png_image_write_get_memory_size(image, size, convert_to_8_bit, buffer,\
-; row_stride, colormap)\
-; png_image_write_to_memory(&(image), 0, &(size), convert_to_8_bit, buffer,\
-; row_stride, colormap)
-; Return the amount of memory in 'size' required to compress this image.
-; The png_image structure 'image' must be filled in as in the above
-; function and must not be changed before the actual write call, the buffer
-; and all other parameters must also be identical to that in the final
-; write call. The 'size' variable need not be initialized.
-
-; NOTE: the macro returns true/false, if false is returned 'size' will be
-; set to zero and the write failed and probably will fail if tried again.
-
-; You can pre-allocate the buffer by making sure it is of sufficient size
-; regardless of the amount of compression achieved. The buffer size will
-; always be bigger than the original image and it will never be filled. The
-; following macros are provided to assist in allocating the buffer.
-
-;#define PNG_IMAGE_DATA_SIZE(image) (PNG_IMAGE_SIZE(image)+(image).height)
-; The number of uncompressed bytes in the PNG byte encoding of the image;
-; uncompressing the PNG IDAT data will give this number of bytes.
-
-; NOTE: while PNG_IMAGE_SIZE cannot overflow for an image in memory this
-; macro can because of the extra bytes used in the PNG byte encoding. You
-; need to avoid this macro if your image size approaches 2^30 in width or
-; height. The same goes for the remainder of these macros; they all produce
-; bigger numbers than the actual in-memory image size.
-
-;#ifndef PNG_ZLIB_MAX_SIZE
-;# define PNG_ZLIB_MAX_SIZE(b) ((b)+(((b)+7U)>>3)+(((b)+63U)>>6)+11U)
-; An upper bound on the number of compressed bytes given 'b' uncompressed
-; bytes. This is based on deflateBounds() in zlib; different
-; implementations of zlib compression may conceivably produce more data so
-; if your zlib implementation is not zlib itself redefine this macro
-; appropriately.
-
-;end if
-
-;#define PNG_IMAGE_COMPRESSED_SIZE_MAX(image)\
-; PNG_ZLIB_MAX_SIZE((png_alloc_size_t)PNG_IMAGE_DATA_SIZE(image))
- ; An upper bound on the size of the data in the PNG IDAT chunks.
-
-;#define PNG_IMAGE_PNG_SIZE_MAX_(image, image_size)\
-; ((8U/*sig*/+25U/*IHDR*/+16U/*gAMA*/+44U/*cHRM*/+12U/*IEND*/+\
-; (((image).format&PNG_FORMAT_FLAG_COLORMAP)?/*colormap: PLTE, tRNS*/\
-; 12U+3U*(image).colormap_entries/*PLTE data*/+\
-; (((image).format&PNG_FORMAT_FLAG_ALPHA)?\
-; 12U/*tRNS*/+(image).colormap_entries:0U):0U)+\
-; 12U)+(12U*((image_size)/PNG_ZBUF_SIZE))/*IDAT*/+(image_size))
-
-; A helper for the following macro; if your compiler cannot handle the
-; following macro use this one with the result of
-; PNG_IMAGE_COMPRESSED_SIZE_MAX(image) as the second argument (most
-; compilers should handle this just fine.)
-
-;#define PNG_IMAGE_PNG_SIZE_MAX(image)\
-; PNG_IMAGE_PNG_SIZE_MAX_(image, PNG_IMAGE_COMPRESSED_SIZE_MAX(image))
-; An upper bound on the total length of the PNG data stream for 'image'.
-; The result is of type png_alloc_size_t, on 32-bit systems this may
-; overflow even though PNG_IMAGE_DATA_SIZE does not overflow; the write will
-; run out of buffer space but return a corrected size which should work.
-
-end if ;SIMPLIFIED_WRITE
-;/*******************************************************************************
-; END OF SIMPLIFIED API
-; ******************************************************************************/
-;end if /* SIMPLIFIED_{READ|WRITE} */
-
-;/*******************************************************************************
-; Section 6: IMPLEMENTATION OPTIONS
-; *******************************************************************************
-
-; Support for arbitrary implementation-specific optimizations. The API allows
-; particular options to be turned on or off. 'Option' is the number of the
-; option and 'onoff' is 0 (off) or non-0 (on). The value returned is given
-; by the PNG_OPTION_ defines below.
-
-; HARDWARE: normally hardware capabilites, such as the Intel SSE instructions,
-; are detected at run time, however sometimes it may be impossible
-; to do this in user mode, in which case it is necessary to discover
-; the capabilities in an OS specific way. Such capabilities are
-; listed here when libpng has support for them and must be turned
-; ON by the application if present.
-
-; SOFTWARE: sometimes software optimizations actually result in performance
-; decrease on some architectures or systems, or with some sets of
-; PNG images. 'Software' options allow such optimizations to be
-; selected at run time.
-
-if PNG_SET_OPTION_SUPPORTED eq 1
-if PNG_ARM_NEON_API_SUPPORTED eq 1
- PNG_ARM_NEON equ 0 ;HARDWARE: ARM Neon SIMD instructions supported
-end if
-PNG_MAXIMUM_INFLATE_WINDOW equ 2 ;SOFTWARE: force maximum window
-PNG_SKIP_sRGB_CHECK_PROFILE equ 4 ;SOFTWARE: Check ICC profile for sRGB
-if PNG_MIPS_MSA_API_SUPPORTED eq 1
- PNG_MIPS_MSA equ 6 ;HARDWARE: MIPS Msa SIMD instructions supported
-end if
-PNG_OPTION_NEXT equ 8 ;Next option - numbers must be even
-
-; Return values: NOTE: there are four values and 'off' is *not* zero
-PNG_OPTION_UNSET equ 0 ;Unset - defaults to off
-PNG_OPTION_INVALID equ 1 ;Option number out of range
-PNG_OPTION_OFF equ 2
-PNG_OPTION_ON equ 3
-end if ;SET_OPTION
-
-;/*******************************************************************************
-; END OF HARDWARE AND SOFTWARE OPTIONS
-; ******************************************************************************/
-
-; Maintainer: Put new public prototypes here ^, in libpng.3, in project
-; defs, and in scripts/symbols.def.
-
-
-; The last ordinal number (this is the *last* one already used; the next
-; one to use is one more than this.)
-
-;end if /* PNG_VERSION_INFO_ONLY */
-; Do not put anything past this line
+
+; png.inc - header file for PNG reference library
+
+; libpng version 1.6.25, September 1, 2016
+
+; Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
+; (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+; (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+
+; This code is released under the libpng license (See LICENSE, below)
+
+; Authors and maintainers:
+; libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
+; libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger
+; libpng versions 0.97, January 1998, through 1.6.25, September 1, 2016:
+; Glenn Randers-Pehrson.
+; See also "Contributing Authors", below.
+
+
+
+; COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:
+
+; If you modify libpng you may insert additional notices immediately following
+; this sentence.
+
+; This code is released under the libpng license.
+
+; Some files in the "contrib" directory and some configure-generated
+; files that are distributed with libpng have other copyright owners and
+; are released under other open source licenses.
+
+; libpng versions 1.0.7, July 1, 2000 through 1.6.25, September 1, 2016 are
+; Copyright (c) 2000-2002, 2004, 2006-2016 Glenn Randers-Pehrson, are
+; derived from libpng-1.0.6, and are distributed according to the same
+; disclaimer and license as libpng-1.0.6 with the following individuals
+; added to the list of Contributing Authors:
+
+; Simon-Pierre Cadieux
+; Eric S. Raymond
+; Mans Rullgard
+; Cosmin Truta
+; Gilles Vollant
+; James Yu
+; Mandar Sahastrabuddhe
+
+; and with the following additions to the disclaimer:
+
+; There is no warranty against interference with your enjoyment of the
+; library or against infringement. There is no warranty that our
+; efforts or the library will fulfill any of your particular purposes
+; or needs. This library is provided with all faults, and the entire
+; risk of satisfactory quality, performance, accuracy, and effort is with
+; the user.
+
+; Some files in the "contrib" directory have other copyright owners and
+; are released under other open source licenses.
+
+
+; libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
+; Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
+; libpng-0.96, and are distributed according to the same disclaimer and
+; license as libpng-0.96, with the following individuals added to the list
+; of Contributing Authors:
+
+; Tom Lane
+; Glenn Randers-Pehrson
+; Willem van Schaik
+
+; Some files in the "scripts" directory have different copyright owners
+; but are also released under this license.
+
+; libpng versions 0.89, June 1996, through 0.96, May 1997, are
+; Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88,
+; and are distributed according to the same disclaimer and license as
+; libpng-0.88, with the following individuals added to the list of
+; Contributing Authors:
+
+; John Bowler
+; Kevin Bracey
+; Sam Bushell
+; Magnus Holmgren
+; Greg Roelofs
+; Tom Tanner
+
+; Some files in the "scripts" directory have other copyright owners
+; but are released under this license.
+
+; libpng versions 0.5, May 1995, through 0.88, January 1996, are
+; Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
+
+; For the purposes of this copyright and license, "Contributing Authors"
+; is defined as the following set of individuals:
+
+; Andreas Dilger
+; Dave Martindale
+; Guy Eric Schalnat
+; Paul Schmidt
+; Tim Wegner
+
+; The PNG Reference Library is supplied "AS IS". The Contributing Authors
+; and Group 42, Inc. disclaim all warranties, expressed or implied,
+; including, without limitation, the warranties of merchantability and of
+; fitness for any purpose. The Contributing Authors and Group 42, Inc.
+; assume no liability for direct, indirect, incidental, special, exemplary,
+; or consequential damages, which may result from the use of the PNG
+; Reference Library, even if advised of the possibility of such damage.
+
+; Permission is hereby granted to use, copy, modify, and distribute this
+; source code, or portions hereof, for any purpose, without fee, subject
+; to the following restrictions:
+
+; 1. The origin of this source code must not be misrepresented.
+
+; 2. Altered versions must be plainly marked as such and must not
+; be misrepresented as being the original source.
+
+; 3. This Copyright notice may not be removed or altered from any
+; source or altered source distribution.
+
+; The Contributing Authors and Group 42, Inc. specifically permit, without
+; fee, and encourage the use of this source code as a component to
+; supporting the PNG file format in commercial products. If you use this
+; source code in a product, acknowledgment is not required but would be
+; appreciated.
+
+; END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE.
+
+; TRADEMARK:
+
+; The name "libpng" has not been registered by the Copyright owner
+; as a trademark in any jurisdiction. However, because libpng has
+; been distributed and maintained world-wide, continually since 1995,
+; the Copyright owner claims "common-law trademark protection" in any
+; jurisdiction where common-law trademark is recognized.
+
+; OSI CERTIFICATION:
+
+; Libpng is OSI Certified Open Source Software. OSI Certified Open Source is
+; a certification mark of the Open Source Initiative. OSI has not addressed
+; the additional disclaimers inserted at version 1.0.7.
+
+; EXPORT CONTROL:
+
+; The Copyright owner believes that the Export Control Classification
+; Number (ECCN) for libpng is EAR99, which means not subject to export
+; controls or International Traffic in Arms Regulations (ITAR) because
+; it is open source, publicly available software, that does not contain
+; any encryption software. See the EAR, paragraphs 734.3(b)(3) and
+; 734.7(b).
+
+
+
+; A "png_get_copyright" function is available, for convenient use in "about"
+; boxes and the like:
+
+; printf("%s", png_get_copyright(NULL));
+
+; Also, the PNG logo (in PNG format, of course) is supplied in the
+; files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31).
+
+
+
+; The contributing authors would like to thank all those who helped
+; with testing, bug fixes, and patience. This wouldn't have been
+; possible without all of you.
+
+; Thanks to Frank J. T. Wojcik for helping with the documentation.
+
+;
+; Note about libpng version numbers:
+;
+; Due to various miscommunications, unforeseen code incompatibilities
+; and occasional factors outside the authors' control, version numbering
+; on the library has not always been consistent and straightforward.
+; The following table summarizes matters since version 0.89c, which was
+; the first widely used release:
+;
+; source png.h png.h shared-lib
+; version string int version
+; ------- ------ ----- ----------
+; ...
+; 1.2.56 13 10256 12.so.0.56[.0]
+; ...
+; 1.5.27 15 10527 15.so.15.27[.0]
+; ...
+; 1.6.25 16 10625 16.so.16.25[.0]
+
+; Henceforth the source version will match the shared-library major
+; and minor numbers; the shared-library major version number will be
+; used for changes in backward compatibility, as it is intended. The
+; PNG_LIBPNG_VER macro, which is not used within libpng but is available
+; for applications, is an unsigned integer of the form xyyzz corresponding
+; to the source version x.y.z (leading zeros in y and z). Beta versions
+; were given the previous public release number plus a letter, until
+; version 1.0.6j; from then on they were given the upcoming public
+; release number plus "betaNN" or "rcNN".
+
+; Binary incompatibility exists only when applications make direct access
+; to the info_ptr or png_ptr members through png.h, and the compiled
+; application is loaded with a different version of the library.
+
+; DLLNUM will change each time there are forward or backward changes
+; in binary compatibility (e.g., when a new feature is added).
+
+; See libpng.txt or libpng.3 for more information. The PNG specification
+; is available as a W3C Recommendation and as an ISO Specification,
+;
+
+; If you just need to read a PNG file and don't want to read the documentation
+; skip to the end of this file and read the section entitled 'simplified API'.
+
+
+; Version information for png.h - this should match the version in png.asm
+PNG_LIBPNG_VER_STRING db '1.6.25',0
+PNG_HEADER_VERSION_STRING db ' libpng version 1.6.25 - September 1, 2016',13,10,0
+
+PNG_LIBPNG_VER_SONUM equ 16
+PNG_LIBPNG_VER_DLLNUM equ 16
+
+; These should match the first 3 components of PNG_LIBPNG_VER_STRING:
+PNG_LIBPNG_VER_MAJOR equ 1
+PNG_LIBPNG_VER_MINOR equ 6
+PNG_LIBPNG_VER_RELEASE equ 25
+
+; This should match the numeric part of the final component of
+; PNG_LIBPNG_VER_STRING, omitting any leading zero:
+
+
+PNG_LIBPNG_VER_BUILD equ 0
+
+; Release Status
+PNG_LIBPNG_BUILD_ALPHA equ 1
+PNG_LIBPNG_BUILD_BETA equ 2
+PNG_LIBPNG_BUILD_RC equ 3
+PNG_LIBPNG_BUILD_STABLE equ 4
+PNG_LIBPNG_BUILD_RELEASE_STATUS_MASK equ 7
+
+; Release-Specific Flags
+PNG_LIBPNG_BUILD_PATCH equ 8 ;Can be OR'ed with PNG_LIBPNG_BUILD_STABLE only
+PNG_LIBPNG_BUILD_PRIVATE equ 16 ;Cannot be OR'ed with PNG_LIBPNG_BUILD_SPECIAL
+PNG_LIBPNG_BUILD_SPECIAL equ 32 ;Cannot be OR'ed with PNG_LIBPNG_BUILD_PRIVATE
+
+PNG_LIBPNG_BUILD_BASE_TYPE equ PNG_LIBPNG_BUILD_STABLE
+
+; Careful here. At one time, Guy wanted to use 082, but that would be octal.
+; We must not include leading zeros.
+; Versions 0.7 through 1.0.0 were in the range 0 to 100 here (only
+; version 1.0.0 was mis-numbered 100 instead of 10000). From
+; version 1.0.1 it's xxyyzz, where x=major, y=minor, z=release
+
+PNG_LIBPNG_VER equ 10625 ;1.6.25
+
+; Library configuration: these options cannot be changed after
+; the library has been built.
+
+
+; Added at libpng-1.2.8
+
+; Ref MSDN: Private as priority over Special
+; VS_FF_PRIVATEBUILD File *was not* built using standard release
+; procedures. If this value is given, the StringFileInfo block must
+; contain a PrivateBuild string.
+
+; VS_FF_SPECIALBUILD File *was* built by the original company using
+; standard release procedures but is a variation of the standard
+; file of the same version number. If this value is given, the
+; StringFileInfo block must contain a SpecialBuild string.
+
+;if PNG_USER_PRIVATEBUILD /* From pnglibconf.h */
+;# define PNG_LIBPNG_BUILD_TYPE \
+; (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_PRIVATE)
+;#else
+;# ifdef PNG_LIBPNG_SPECIALBUILD
+;# define PNG_LIBPNG_BUILD_TYPE \
+; (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_SPECIAL)
+;# else
+;# define PNG_LIBPNG_BUILD_TYPE (PNG_LIBPNG_BUILD_BASE_TYPE)
+;# endif
+;end if
+
+;#ifndef PNG_VERSION_INFO_ONLY
+
+; Version information for C files, stored in png.asm. This had better match
+; the version above.
+
+;#define png_libpng_ver png_get_header_ver(NULL)
+
+; This file is arranged in several sections:
+
+; 1. [omitted]
+; 2. Any configuration options that can be specified by for the application
+; code when it is built. (Build time configuration is in pnglibconf.h)
+; 3. Type definitions (base types are defined in pngconf.h), structure
+; definitions.
+; 4. Exported library functions.
+; 5. Simplified API.
+; 6. Implementation options.
+
+; The library source code has additional files (principally pngpriv.h) that
+; allow configuration of the library.
+
+
+; Section 1: [omitted]
+
+; Section 2: run time configuration
+; See pnglibconf.h for build time configuration
+
+; Run time configuration allows the application to choose between
+; implementations of certain arithmetic APIs. The default is set
+; at build time and recorded in pnglibconf.h, but it is safe to
+; override these (and only these) settings. Note that this won't
+; change what the library does, only application code, and the
+; settings can (and probably should) be made on a per-file basis
+; by setting the #defines before including png.h
+
+; Use macros to read integers from PNG data or use the exported
+; functions?
+; PNG_USE_READ_MACROS: use the macros (see below) Note that
+; the macros evaluate their argument multiple times.
+; PNG_NO_USE_READ_MACROS: call the relevant library function.
+
+; Use the alternative algorithm for compositing alpha samples that
+; does not use division?
+; PNG_READ_COMPOSITE_NODIV_SUPPORTED: use the 'no division'
+; algorithm.
+; PNG_NO_READ_COMPOSITE_NODIV: use the 'division' algorithm.
+
+; How to handle benign errors if PNG_ALLOW_BENIGN_ERRORS is
+; false?
+; PNG_ALLOW_BENIGN_ERRORS: map calls to the benign error
+; APIs to png_warning.
+; Otherwise the calls are mapped to png_error.
+
+
+; Section 3: type definitions, including structures and compile time
+; constants.
+; See pngconf.h for base types that vary by machine/system
+
+
+; This triggers a compiler error in png.c, if png.c and png.h
+; do not agree upon the version number.
+
+;typedef char* png_libpng_version_1_6_25;
+
+; Basic control structions. Read libpng-manual.txt or libpng.3 for more info.
+
+; png_struct is the cache of information used while reading or writing a single
+; PNG file. One of these is always required, although the simplified API
+; (below) hides the creation and destruction of it.
+
+; png_info contains information read from or to be written to a PNG file. One
+; or more of these must exist while reading or creating a PNG file. The
+; information is not used by libpng during read but is used to control what
+; gets written when a PNG file is created. "png_get_" function calls read
+; information during read and "png_set_" functions calls write information
+; when creating a PNG.
+; been moved into a separate header file that is not accessible to
+; applications. Read libpng-manual.txt or libpng.3 for more info.
+
+; Types with names ending 'p' are pointer types. The corresponding types with
+; names ending 'rp' are identical pointer types except that the pointer is
+; marked 'restrict', which means that it is the only pointer to the object
+; passed to the function. Applications should not use the 'restrict' types;
+; it is always valid to pass 'p' to a pointer with a function argument of the
+; corresponding 'rp' type. Different compilers have different rules with
+; regard to type matching in the presence of 'restrict'. For backward
+; compatibility libpng callbacks never have 'restrict' in their parameters and,
+; consequentially, writing portable application code is extremely difficult if
+; an attempt is made to use 'restrict'.
+
+; Three color definitions. The order of the red, green, and blue, (and the
+; exact size) is not important, although the size of the fields need to
+; be byte or uint_16 (as defined below).
+
+struct png_color
+ red db ? ;byte
+ green db ? ;byte
+ blue db ? ;byte
+ends
+
+struct png_color_16
+ index db ? ;byte ;used for palette files
+ red dw ? ;uint_16 ;for use in red green blue files
+ green dw ? ;uint_16
+ blue dw ? ;uint_16
+ gray dw ? ;uint_16 ;for use in grayscale files
+ends
+
+struct png_color_8
+ red db ? ;byte ;for use in red green blue files
+ green db ? ;byte
+ blue db ? ;byte
+ gray db ? ;byte ;for use in grayscale files
+ alpha db ? ;byte ;for alpha channel files
+ends
+
+
+; The following two structures are used for the in-core representation
+; of sPLT chunks.
+
+struct png_sPLT_entry
+ red dw ? ;uint_16
+ green dw ? ;uint_16
+ blue dw ? ;uint_16
+ alpha dw ? ;uint_16
+ frequency dw ? ;uint_16
+ends
+
+; When the depth of the sPLT palette is 8 bits, the color and alpha samples
+; occupy the LSB of their respective members, and the MSB of each member
+; is zero-filled. The frequency member always occupies the full 16 bits.
+
+
+struct png_sPLT_t
+ name dd ? ;charp ;palette name
+ depth db ? ;byte ;depth of palette samples
+ entries dd ? ;png_sPLT_entryp ;palette entries
+ nentries dd ? ;int_32 ;number of palette entries
+ends
+
+if PNG_TEXT_SUPPORTED eq 1
+; png_text holds the contents of a text/ztxt/itxt chunk in a PNG file,
+; and whether that contents is compressed or not. The "key" field
+; points to a regular zero-terminated C string. The "text" fields can be a
+; regular C string, an empty string, or a NULL pointer.
+; However, the structure returned by png_get_text() will always contain
+; the "text" field as a regular zero-terminated C string (possibly
+; empty), never a NULL pointer, so it can be safely used in printf() and
+; other string-handling functions. Note that the "itxt_length", "lang", and
+; "lang_key" members of the structure only exist when the library is built
+; with iTXt chunk support. Prior to libpng-1.4.0 the library was built by
+; default without iTXt support. Also note that when iTXt *is* supported,
+; the "lang" and "lang_key" fields contain NULL pointers when the
+; "compression" field contains * PNG_TEXT_COMPRESSION_NONE or
+; PNG_TEXT_COMPRESSION_zTXt. Note that the "compression value" is not the
+; same as what appears in the PNG tEXt/zTXt/iTXt chunk's "compression flag"
+; which is always 0 or 1, or its "compression method" which is always 0.
+
+struct png_text
+ compression dd ? ;int ;compression value:
+ ;-1: tEXt, none
+ ; 0: zTXt, deflate
+ ; 1: iTXt, none
+ ; 2: iTXt, deflate
+ key dd ? ;charp ;keyword, 1-79 character description of "text"
+ text dd ? ;charp ;comment, may be an empty string (ie "")
+ ; or a NULL pointer
+ text_length dd ? ;png_size_t ;length of the text string
+ itxt_length dd ? ;png_size_t ;length of the itxt string
+ lang dd ? ;charp ;language code, 0-79 characters
+ ; or a NULL pointer
+ lang_key dd ? ;charp ;keyword translated UTF-8 string, 0 or more
+ ; chars or a NULL pointer
+ends
+end if
+
+; Supported compression types for text in PNG files (tEXt, and zTXt).
+; The values of the PNG_TEXT_COMPRESSION_ defines should NOT be changed.
+PNG_TEXT_COMPRESSION_NONE_WR equ -3
+PNG_TEXT_COMPRESSION_zTXt_WR equ -2
+PNG_TEXT_COMPRESSION_NONE equ -1
+PNG_TEXT_COMPRESSION_zTXt equ 0
+PNG_ITXT_COMPRESSION_NONE equ 1
+PNG_ITXT_COMPRESSION_zTXt equ 2
+PNG_TEXT_COMPRESSION_LAST equ 3 ;Not a valid value
+
+; png_time is a way to hold the time in an machine independent way.
+; Two conversions are provided, both from time_t and struct tm. There
+; is no portable way to convert to either of these structures, as far
+; as I know. If you know of a portable way, send it to me. As a side
+; note - PNG has always been Year 2000 compliant!
+
+struct png_time
+ year dw ? ;uint_16 ;full year, as in, 1995
+ month db ? ;byte ;month of year, 1 - 12
+ day db ? ;byte ;day of month, 1 - 31
+ hour db ? ;byte ;hour of day, 0 - 23
+ minute db ? ;byte ;minute of hour, 0 - 59
+ second db ? ;byte ;second of minute, 0 - 60 (for leap seconds)
+ends
+
+if (PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED eq 1) | (PNG_USER_CHUNKS_SUPPORTED eq 1)
+; png_unknown_chunk is a structure to hold queued chunks for which there is
+; no specific support. The idea is that we can use this to queue
+; up private chunks for output even though the library doesn't actually
+; know about their semantics.
+
+; The data in the structure is set by libpng on read and used on write.
+
+struct png_unknown_chunk
+ name rb 5 ;byte[5] ;Textual chunk name with '\0' terminator
+ rb 3 ;align
+ podata dd ? ;byte* ;Data, should not be modified on read!
+ size dd ? ;png_size_t
+
+ ; On write 'location' must be set using the flag values listed below.
+ ; Notice that on read it is set by libpng however the values stored have
+ ; more bits set than are listed below. Always treat the value as a
+ ; bitmask. On write set only one bit - setting multiple bits may cause the
+ ; chunk to be written in multiple places.
+
+ location db ? ;byte ;mode of operation at read time
+ends
+end if
+
+; Flag values for the unknown chunk location byte.
+PNG_HAVE_IHDR equ 0x01
+PNG_HAVE_PLTE equ 0x02
+PNG_AFTER_IDAT equ 0x08
+
+; Maximum positive integer used in PNG is (2^31)-1
+PNG_UINT_31_MAX equ 0x7fffffff ;uint_32
+PNG_UINT_32_MAX equ -1 ;uint_32
+PNG_SIZE_MAX equ 0x60000000 ;1.5 Gb
+
+; These are constants for fixed point values encoded in the
+; PNG specification manner (x100000)
+
+PNG_FP_1 equ 100000
+PNG_FP_HALF equ 50000
+PNG_FP_MAX equ ((png_fixed_point)0x7fffffffL)
+PNG_FP_MIN equ (-PNG_FP_MAX)
+
+; These describe the color_type field in png_info.
+; color type masks
+PNG_COLOR_MASK_PALETTE equ 1
+PNG_COLOR_MASK_COLOR equ 2
+PNG_COLOR_MASK_ALPHA equ 4
+
+; color types. Note that not all combinations are legal
+PNG_COLOR_TYPE_GRAY equ 0
+PNG_COLOR_TYPE_PALETTE equ (PNG_COLOR_MASK_COLOR or PNG_COLOR_MASK_PALETTE)
+PNG_COLOR_TYPE_RGB equ (PNG_COLOR_MASK_COLOR)
+PNG_COLOR_TYPE_RGB_ALPHA equ (PNG_COLOR_MASK_COLOR or PNG_COLOR_MASK_ALPHA)
+PNG_COLOR_TYPE_GRAY_ALPHA equ (PNG_COLOR_MASK_ALPHA)
+; aliases
+PNG_COLOR_TYPE_RGBA equ PNG_COLOR_TYPE_RGB_ALPHA
+PNG_COLOR_TYPE_GA equ PNG_COLOR_TYPE_GRAY_ALPHA
+
+; This is for compression type. PNG 1.0-1.2 only define the single type.
+PNG_COMPRESSION_TYPE_BASE equ 0 ;Deflate method 8, 32K window
+PNG_COMPRESSION_TYPE_DEFAULT equ PNG_COMPRESSION_TYPE_BASE
+
+; This is for filter type. PNG 1.0-1.2 only define the single type.
+PNG_FILTER_TYPE_BASE equ 0 ;Single row per-byte filtering
+PNG_INTRAPIXEL_DIFFERENCING equ 64 ;Used only in MNG datastreams
+PNG_FILTER_TYPE_DEFAULT equ PNG_FILTER_TYPE_BASE
+
+; These are for the interlacing type. These values should NOT be changed.
+PNG_INTERLACE_NONE equ 0 ;Non-interlaced image
+PNG_INTERLACE_ADAM7 equ 1 ;Adam7 interlacing
+PNG_INTERLACE_LAST equ 2 ;Not a valid value
+
+; These are for the oFFs chunk. These values should NOT be changed.
+PNG_OFFSET_PIXEL equ 0 ;Offset in pixels
+PNG_OFFSET_MICROMETER equ 1 ;Offset in micrometers (1/10^6 meter)
+PNG_OFFSET_LAST equ 2 ;Not a valid value
+
+; These are for the pCAL chunk. These values should NOT be changed.
+PNG_EQUATION_LINEAR equ 0 ;Linear transformation
+PNG_EQUATION_BASE_E equ 1 ;Exponential base e transform
+PNG_EQUATION_ARBITRARY equ 2 ;Arbitrary base exponential transform
+PNG_EQUATION_HYPERBOLIC equ 3 ;Hyperbolic sine transformation
+PNG_EQUATION_LAST equ 4 ;Not a valid value
+
+; These are for the sCAL chunk. These values should NOT be changed.
+PNG_SCALE_UNKNOWN equ 0 ;unknown unit (image scale)
+PNG_SCALE_METER equ 1 ;meters per pixel
+PNG_SCALE_RADIAN equ 2 ;radians per pixel
+PNG_SCALE_LAST equ 3 ;Not a valid value
+
+; These are for the pHYs chunk. These values should NOT be changed.
+PNG_RESOLUTION_UNKNOWN equ 0 ;pixels/unknown unit (aspect ratio)
+PNG_RESOLUTION_METER equ 1 ;pixels/meter
+PNG_RESOLUTION_LAST equ 2 ;Not a valid value
+
+; These are for the sRGB chunk. These values should NOT be changed.
+PNG_sRGB_INTENT_PERCEPTUAL equ 0
+PNG_sRGB_INTENT_RELATIVE equ 1
+PNG_sRGB_INTENT_SATURATION equ 2
+PNG_sRGB_INTENT_ABSOLUTE equ 3
+PNG_sRGB_INTENT_LAST equ 4 ;Not a valid value
+
+; This is for text chunks
+PNG_KEYWORD_MAX_LENGTH equ 79
+
+; Maximum number of entries in PLTE/sPLT/tRNS arrays
+PNG_MAX_PALETTE_LENGTH equ 256
+
+; These determine if an ancillary chunk's data has been successfully read
+; from the PNG header, or if the application has filled in the corresponding
+; data in the info_struct to be written into the output file. The values
+; of the PNG_INFO_ defines should NOT be changed.
+
+PNG_INFO_gAMA equ 0x0001
+PNG_INFO_sBIT equ 0x0002
+PNG_INFO_cHRM equ 0x0004
+PNG_INFO_PLTE equ 0x0008
+PNG_INFO_tRNS equ 0x0010
+PNG_INFO_bKGD equ 0x0020
+PNG_INFO_hIST equ 0x0040
+PNG_INFO_pHYs equ 0x0080
+PNG_INFO_oFFs equ 0x0100
+PNG_INFO_tIME equ 0x0200
+PNG_INFO_pCAL equ 0x0400
+PNG_INFO_sRGB equ 0x0800 ; GR-P, 0.96a
+PNG_INFO_iCCP equ 0x1000 ; ESR, 1.0.6
+PNG_INFO_sPLT equ 0x2000 ; ESR, 1.0.6
+PNG_INFO_sCAL equ 0x4000 ; ESR, 1.0.6
+PNG_INFO_IDAT equ 0x8000 ; ESR, 1.0.6
+
+; This is used for the transformation routines, as some of them
+; change these values for the row. It also should enable using
+; the routines for other purposes.
+
+struct png_row_info ;png_row_info_struct
+ width dd ? ;uint_32 ;width of row
+ rowbytes dd ? ;png_size_t ;number of bytes in row
+ color_type db ? ;byte ;color type of row
+ bit_depth db ? ;byte ;bit depth of row
+ channels db ? ;byte ;number of channels (1, 2, 3, or 4)
+ pixel_depth db ? ;byte ;bits per pixel (depth * channels)
+ends
+
+if PNG_SETJMP_SUPPORTED eq 1
+; This must match the function definition in , and the application
+; must include this before png.h to obtain the definition of jmp_buf. The
+; function is required to be PNG_NORETURN, but this is not checked. If the
+; function does return the application will crash via an abort() or similar
+; system level call.
+
+; If you get a warning here while building the library you may need to make
+; changes to ensure that pnglibconf.h records the calling convention used by
+; your compiler. This may be very difficult - try using a different compiler
+; to build the library!
+
+;PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), typedef);
+end if
+
+; Transform masks for the high-level interface
+PNG_TRANSFORM_IDENTITY equ 0x0000 ; read and write
+PNG_TRANSFORM_STRIP_16 equ 0x0001 ; read only
+PNG_TRANSFORM_STRIP_ALPHA equ 0x0002 ; read only
+PNG_TRANSFORM_PACKING equ 0x0004 ; read and write
+PNG_TRANSFORM_PACKSWAP equ 0x0008 ; read and write
+PNG_TRANSFORM_EXPAND equ 0x0010 ; read only
+PNG_TRANSFORM_INVERT_MONO equ 0x0020 ; read and write
+PNG_TRANSFORM_SHIFT equ 0x0040 ; read and write
+PNG_TRANSFORM_BGR equ 0x0080 ; read and write
+PNG_TRANSFORM_SWAP_ALPHA equ 0x0100 ; read and write
+PNG_TRANSFORM_SWAP_ENDIAN equ 0x0200 ; read and write
+PNG_TRANSFORM_INVERT_ALPHA equ 0x0400 ; read and write
+PNG_TRANSFORM_STRIP_FILLER equ 0x0800 ; write only
+; Added to libpng-1.2.34
+PNG_TRANSFORM_STRIP_FILLER_BEFORE equ PNG_TRANSFORM_STRIP_FILLER
+PNG_TRANSFORM_STRIP_FILLER_AFTER equ 0x1000 ; write only
+; Added to libpng-1.4.0
+PNG_TRANSFORM_GRAY_TO_RGB equ 0x2000 ; read only
+; Added to libpng-1.5.4
+PNG_TRANSFORM_EXPAND_16 equ 0x4000 ;read only
+;if INT_MAX >= 0x8000 ;else this might break
+PNG_TRANSFORM_SCALE_16 equ 0x8000 ;read only
+;end if
+
+; Flags for MNG supported features
+PNG_FLAG_MNG_EMPTY_PLTE equ 0x01
+PNG_FLAG_MNG_FILTER_64 equ 0x04
+PNG_ALL_MNG_FEATURES equ 0x05
+
+; NOTE: prior to 1.5 these functions had no 'API' style declaration,
+; this allowed the zlib default functions to be used on Windows
+; platforms. In 1.5 the zlib default malloc (which just calls malloc and
+; ignores the first argument) should be completely compatible with the
+; following.
+
+; Section 4: exported functions
+; Here are the function definitions most commonly used. This is not
+; the place to find out how to use libpng. See libpng-manual.txt for the
+; full explanation, see example.c for the summary. This just provides
+; a simple one line description of the use of each function.
+
+
+
+; Simple signature checking function. This is the same as calling
+; png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n).
+
+;#define png_check_sig(sig, n) !png_sig_cmp((sig), 0, (n))
+
+macro png_setup_abs sum
+{
+local .end0
+ and eax,0xff
+if PNG_USE_ABS eq 1
+ add sum,128
+ sub al,128 ;v - 128
+ cmp al,128
+ jl @f
+ neg al
+ inc al ;abs(v - 128)
+ @@:
+ sub sum,eax
+else
+ cmp eax,128
+ jl @f
+ add sum,256
+ sub sum,eax
+ jmp .end0
+ @@:
+ add sum,eax
+ .end0:
+end if
+}
+
+; Reduce RGB to grayscale.
+PNG_ERROR_ACTION_NONE equ 1
+PNG_ERROR_ACTION_WARN equ 2
+PNG_ERROR_ACTION_ERROR equ 3
+PNG_RGB_TO_GRAY_DEFAULT equ (-1) ;for red/green coefficients
+
+; How the alpha channel is interpreted - this affects how the color channels
+; of a PNG file are returned to the calling application when an alpha channel,
+; or a tRNS chunk in a palette file, is present.
+
+; This has no effect on the way pixels are written into a PNG output
+; datastream. The color samples in a PNG datastream are never premultiplied
+; with the alpha samples.
+
+; The default is to return data according to the PNG specification: the alpha
+; channel is a linear measure of the contribution of the pixel to the
+; corresponding composited pixel, and the color channels are unassociated
+; (not premultiplied). The gamma encoded color channels must be scaled
+; according to the contribution and to do this it is necessary to undo
+; the encoding, scale the color values, perform the composition and reencode
+; the values. This is the 'PNG' mode.
+
+; The alternative is to 'associate' the alpha with the color information by
+; storing color channel values that have been scaled by the alpha.
+; image. These are the 'STANDARD', 'ASSOCIATED' or 'PREMULTIPLIED' modes
+; (the latter being the two common names for associated alpha color channels).
+
+; For the 'OPTIMIZED' mode, a pixel is treated as opaque only if the alpha
+; value is equal to the maximum value.
+
+; The final choice is to gamma encode the alpha channel as well. This is
+; broken because, in practice, no implementation that uses this choice
+; correctly undoes the encoding before handling alpha composition. Use this
+; choice only if other serious errors in the software or hardware you use
+; mandate it; the typical serious error is for dark halos to appear around
+; opaque areas of the composited PNG image because of arithmetic overflow.
+
+; The API function png_set_alpha_mode specifies which of these choices to use
+; with an enumerated 'mode' value and the gamma of the required output:
+
+PNG_ALPHA_PNG equ 0 ;according to the PNG standard
+PNG_ALPHA_STANDARD equ 1 ;according to Porter/Duff
+PNG_ALPHA_ASSOCIATED equ 1 ;as above; this is the normal practice
+PNG_ALPHA_PREMULTIPLIED equ 1 ;as above
+PNG_ALPHA_OPTIMIZED equ 2 ;'PNG' for opaque pixels, else 'STANDARD'
+PNG_ALPHA_BROKEN equ 3 ;the alpha channel is gamma encoded
+
+if (PNG_GAMMA_SUPPORTED eq 1) | (PNG_READ_ALPHA_MODE_SUPPORTED eq 1)
+; The output_gamma value is a screen gamma in libpng terminology: it expresses
+; how to decode the output values, not how they are encoded.
+
+PNG_DEFAULT_sRGB equ -1 ;sRGB gamma and color space
+PNG_GAMMA_MAC_18 equ -2 ;Old Mac '1.8' gamma and color space
+PNG_GAMMA_sRGB equ 220000 ;Television standards--matches sRGB gamma
+PNG_GAMMA_LINEAR equ PNG_FP_1 ;Linear
+end if
+
+; The values of the PNG_FILLER_ defines should NOT be changed
+PNG_FILLER_BEFORE equ 0
+PNG_FILLER_AFTER equ 1
+
+;#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
+
+; Handle alpha and tRNS by replacing with a background color. Prior to
+; libpng-1.5.4 this API must not be called before the PNG file header has been
+; read. Doing so will result in unexpected behavior and possible warnings or
+; errors if the PNG file contains a bKGD chunk.
+
+if PNG_READ_BACKGROUND_SUPPORTED eq 1
+PNG_BACKGROUND_GAMMA_UNKNOWN equ 0
+PNG_BACKGROUND_GAMMA_SCREEN equ 1
+PNG_BACKGROUND_GAMMA_FILE equ 2
+PNG_BACKGROUND_GAMMA_UNIQUE equ 3
+end if
+
+;PNG_READ_16_TO_8_SUPPORTED equ 1 ;Name prior to 1.5.4
+
+; The threshold on gamma processing is configurable but hard-wired into the
+; library. The following is the floating point variant.
+
+PNG_GAMMA_THRESHOLD equ (PNG_GAMMA_THRESHOLD_FIXED*.00001)
+
+; Handle gamma correction. Screen_gamma=(display_exponent).
+; NOTE: this API simply sets the screen and file gamma values. It will
+; therefore override the value for gamma in a PNG file if it is called after
+; the file header has been read - use with care - call before reading the PNG
+; file for best results!
+
+
+; Values for png_set_crc_action() say how to handle CRC errors in
+; ancillary and critical chunks, and whether to use the data contained
+; therein. Note that it is impossible to "discard" data in a critical
+; chunk. For versions prior to 0.90, the action was always error/quit,
+; whereas in version 0.90 and later, the action for CRC errors in ancillary
+; chunks is warn/discard. These values should NOT be changed.
+
+; value action:critical action:ancillary
+
+PNG_CRC_DEFAULT equ 0 ;error/quit warn/discard data
+PNG_CRC_ERROR_QUIT equ 1 ;error/quit error/quit
+PNG_CRC_WARN_DISCARD equ 2 ;(INVALID) warn/discard data
+PNG_CRC_WARN_USE equ 3 ;warn/use data warn/use data
+PNG_CRC_QUIET_USE equ 4 ;quiet/use data quiet/use data
+PNG_CRC_NO_CHANGE equ 5 ;use current value use current value
+
+; Flags for png_set_filter() to say which filters to use. The flags
+; are chosen so that they don't conflict with real filter types
+; below, in case they are supplied instead of the #defined constants.
+; These values should NOT be changed.
+
+PNG_NO_FILTERS equ 0x00
+PNG_FILTER_NONE equ 0x08
+PNG_FILTER_SUB equ 0x10
+PNG_FILTER_UP equ 0x20
+PNG_FILTER_AVG equ 0x40
+PNG_FILTER_PAETH equ 0x80
+PNG_FAST_FILTERS equ (PNG_FILTER_NONE or PNG_FILTER_SUB or PNG_FILTER_UP)
+PNG_ALL_FILTERS equ (PNG_FAST_FILTERS or PNG_FILTER_AVG or PNG_FILTER_PAETH)
+
+; Filter values (not flags) - used in pngwrite.c, pngwutil.c for now.
+; These defines should NOT be changed.
+
+PNG_FILTER_VALUE_NONE equ 0
+PNG_FILTER_VALUE_SUB equ 1
+PNG_FILTER_VALUE_UP equ 2
+PNG_FILTER_VALUE_AVG equ 3
+PNG_FILTER_VALUE_PAETH equ 4
+PNG_FILTER_VALUE_LAST equ 5
+
+; The following are no longer used and will be removed from libpng-1.7:
+PNG_FILTER_HEURISTIC_DEFAULT equ 0 ;Currently "UNWEIGHTED"
+PNG_FILTER_HEURISTIC_UNWEIGHTED equ 1 ;Used by libpng < 0.95
+PNG_FILTER_HEURISTIC_WEIGHTED equ 2 ;Experimental feature
+PNG_FILTER_HEURISTIC_LAST equ 3 ;Not a valid value
+
+; It is unlikely that this function works correctly as of 1.6.0 and using it
+; may result either in memory leaks or double free of allocated data.
+
+; Assignments for png_data_freer
+PNG_DESTROY_WILL_FREE_DATA equ 1
+PNG_SET_WILL_FREE_DATA equ 1
+PNG_USER_WILL_FREE_DATA equ 2
+; Flags for png_ptr->free_me and info_ptr->free_me
+PNG_FREE_HIST equ 0x0008
+PNG_FREE_ICCP equ 0x0010
+PNG_FREE_SPLT equ 0x0020
+PNG_FREE_ROWS equ 0x0040
+PNG_FREE_PCAL equ 0x0080
+PNG_FREE_SCAL equ 0x0100
+if PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED eq 1
+ PNG_FREE_UNKN equ 0x0200
+end if
+PNG_FREE_LIST equ 0x0400 ;removed in 1.6.0 because it is ignored
+PNG_FREE_PLTE equ 0x1000
+PNG_FREE_TRNS equ 0x2000
+PNG_FREE_TEXT equ 0x4000
+PNG_FREE_ALL equ 0x7fff
+PNG_FREE_MUL equ 0x4220 ;PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN
+
+;if PNG_ERROR_TEXT_SUPPORTED
+
+;#else
+;# define png_chunk_error(s1,s2) png_err(s1)
+;end if
+
+;#else
+;# define png_warning(s1,s2) ((void)(s1))
+;# define png_chunk_warning(s1,s2) ((void)(s1))
+
+;if PNG_READ_SUPPORTED
+
+;#else
+;# ifdef PNG_ALLOW_BENIGN_ERRORS
+macro png_benign_error h,txt
+{
+ png_warning h,txt
+}
+;# define png_chunk_benign_error png_chunk_warning
+;# else
+;# define png_benign_error png_error
+;# define png_chunk_benign_error png_chunk_error
+;# endif
+;end if
+
+
+; Provide the default handling for all unknown chunks or, optionally, for
+; specific unknown chunks.
+
+; NOTE: prior to 1.6.0 the handling specified for particular chunks on read was
+; ignored and the default was used, the per-chunk setting only had an effect on
+; write. If you wish to have chunk-specific handling on read in code that must
+; work on earlier versions you must use a user chunk callback to specify the
+; desired handling (keep or discard.)
+
+; The 'keep' parameter is a PNG_HANDLE_CHUNK_ value as listed below. The
+; parameter is interpreted as follows:
+
+; READ:
+; PNG_HANDLE_CHUNK_AS_DEFAULT:
+; Known chunks: do normal libpng processing, do not keep the chunk (but
+; see the comments below about PNG_HANDLE_AS_UNKNOWN_SUPPORTED)
+; Unknown chunks: for a specific chunk use the global default, when used
+; as the default discard the chunk data.
+; PNG_HANDLE_CHUNK_NEVER:
+; Discard the chunk data.
+; PNG_HANDLE_CHUNK_IF_SAFE:
+; Keep the chunk data if the chunk is not critical else raise a chunk
+; error.
+; PNG_HANDLE_CHUNK_ALWAYS:
+; Keep the chunk data.
+
+; If the chunk data is saved it can be retrieved using png_get_unknown_chunks,
+; below. Notice that specifying "AS_DEFAULT" as a global default is equivalent
+; to specifying "NEVER", however when "AS_DEFAULT" is used for specific chunks
+; it simply resets the behavior to the libpng default.
+
+; INTERACTION WTIH USER CHUNK CALLBACKS:
+; The per-chunk handling is always used when there is a png_user_chunk_ptr
+; callback and the callback returns 0; the chunk is then always stored *unless*
+; it is critical and the per-chunk setting is other than ALWAYS. Notice that
+; the global default is *not* used in this case. (In effect the per-chunk
+; value is incremented to at least IF_SAFE.)
+
+; IMPORTANT NOTE: this behavior will change in libpng 1.7 - the global and
+; per-chunk defaults will be honored. If you want to preserve the current
+; behavior when your callback returns 0 you must set PNG_HANDLE_CHUNK_IF_SAFE
+; as the default - if you don't do this libpng 1.6 will issue a warning.
+
+; If you want unhandled unknown chunks to be discarded in libpng 1.6 and
+; earlier simply return '1' (handled).
+
+; PNG_HANDLE_AS_UNKNOWN_SUPPORTED:
+; If this is *not* set known chunks will always be handled by libpng and
+; will never be stored in the unknown chunk list. Known chunks listed to
+; png_set_keep_unknown_chunks will have no effect. If it is set then known
+; chunks listed with a keep other than AS_DEFAULT will *never* be processed
+; by libpng, in addition critical chunks must either be processed by the
+; callback or saved.
+
+; The IHDR and IEND chunks must not be listed. Because this turns off the
+; default handling for chunks that would otherwise be recognized the
+; behavior of libpng transformations may well become incorrect!
+
+; WRITE:
+; When writing chunks the options only apply to the chunks specified by
+; png_set_unknown_chunks (below), libpng will *always* write known chunks
+; required by png_set_ calls and will always write the core critical chunks
+; (as required for PLTE).
+
+; Each chunk in the png_set_unknown_chunks list is looked up in the
+; png_set_keep_unknown_chunks list to find the keep setting, this is then
+; interpreted as follows:
+
+; PNG_HANDLE_CHUNK_AS_DEFAULT:
+; Write safe-to-copy chunks and write other chunks if the global
+; default is set to _ALWAYS, otherwise don't write this chunk.
+; PNG_HANDLE_CHUNK_NEVER:
+; Do not write the chunk.
+; PNG_HANDLE_CHUNK_IF_SAFE:
+; Write the chunk if it is safe-to-copy, otherwise do not write it.
+; PNG_HANDLE_CHUNK_ALWAYS:
+; Write the chunk.
+
+; Note that the default behavior is effectively the opposite of the read case -
+; in read unknown chunks are not stored by default, in write they are written
+; by default. Also the behavior of PNG_HANDLE_CHUNK_IF_SAFE is very different
+; - on write the safe-to-copy bit is checked, on read the critical bit is
+; checked and on read if the chunk is critical an error will be raised.
+
+; num_chunks:
+; ===========
+; If num_chunks is positive, then the "keep" parameter specifies the manner
+; for handling only those chunks appearing in the chunk_list array,
+; otherwise the chunk list array is ignored.
+
+; If num_chunks is 0 the "keep" parameter specifies the default behavior for
+; unknown chunks, as described above.
+
+; If num_chunks is negative, then the "keep" parameter specifies the manner
+; for handling all unknown chunks plus all chunks recognized by libpng
+; except for the IHDR, PLTE, tRNS, IDAT, and IEND chunks (which continue to
+; be processed by libpng.
+
+
+; For use in png_set_keep_unknown, added to version 1.2.6
+PNG_HANDLE_CHUNK_AS_DEFAULT equ 0
+PNG_HANDLE_CHUNK_NEVER equ 1
+PNG_HANDLE_CHUNK_IF_SAFE equ 2
+PNG_HANDLE_CHUNK_ALWAYS equ 3
+PNG_HANDLE_CHUNK_LAST equ 4
+
+; Removed from libpng 1.6; use png_get_io_chunk_type.
+;PNG_REMOVED(200, bytep, png_get_io_chunk_name, (png_structrp png_ptr),
+; PNG_DEPRECATED)
+
+; The flags returned by png_get_io_state() are the following:
+PNG_IO_NONE equ 0x0000 ; no I/O at this moment
+PNG_IO_READING equ 0x0001 ; currently reading
+PNG_IO_WRITING equ 0x0002 ; currently writing
+PNG_IO_SIGNATURE equ 0x0010 ; currently at the file signature
+PNG_IO_CHUNK_HDR equ 0x0020 ; currently at the chunk header
+PNG_IO_CHUNK_DATA equ 0x0040 ; currently at the chunk data
+PNG_IO_CHUNK_CRC equ 0x0080 ; currently at the chunk crc
+PNG_IO_MASK_OP equ 0x000f ; current operation: reading/writing
+PNG_IO_MASK_LOC equ 0x00f0 ; current location: sig/hdr/data/crc
+;end if /* IO_STATE */
+
+; Interlace support. The following macros are always defined so that if
+; libpng interlace handling is turned off the macros may be used to handle
+; interlaced images within the application.
+
+PNG_INTERLACE_ADAM7_PASSES equ 7
+
+; Two macros to return the first row and first column of the original,
+; full, image which appears in a given pass. 'pass' is in the range 0
+; to 6 and the result is in the range 0 to 7.
+
+macro PNG_PASS_START_ROW pass
+{
+ push ebx ecx
+ mov eax,pass
+ mov ebx,eax
+ not eax
+ and eax,1
+ shr ebx,1
+ mov ecx,3
+ sub ecx,ebx
+ shl eax,cl
+ and eax,7
+ pop ecx ebx
+}
+macro PNG_PASS_START_COL pass
+{
+ push ebx ecx
+ mov eax,pass
+ mov ebx,eax
+ and eax,1
+ inc ebx
+ shr ebx,1
+ mov ecx,3
+ sub ecx,ebx
+ shl eax,cl
+ and eax,7
+ pop ecx ebx
+}
+
+; A macro to return the offset between pixels in the output row for a pair of
+; pixels in the input - effectively the inverse of the 'COL_SHIFT' macro that
+; follows. Note that ROW_OFFSET is the offset from one row to the next whereas
+; COL_OFFSET is from one column to the next, within a row.
+
+;#define PNG_PASS_ROW_OFFSET(pass) ((pass)>2?(8>>(((pass)-1)>>1)):8)
+;#define PNG_PASS_COL_OFFSET(pass) (1<<((7-(pass))>>1))
+
+; Two macros to help evaluate the number of rows or columns in each
+; pass. This is expressed as a shift - effectively log2 of the number or
+; rows or columns in each 8x8 tile of the original image.
+
+macro PNG_PASS_ROW_SHIFT pass
+{
+local .end0
+ mov eax,3
+ cmp pass,2
+ jle .end0
+ mov eax,8
+ sub eax,pass
+ shr eax,1
+ .end0:
+}
+macro PNG_PASS_COL_SHIFT pass
+{
+local .end0
+ mov eax,3
+ cmp pass,1
+ jle .end0
+ mov eax,7
+ sub eax,pass
+ shr eax,1
+ .end0:
+}
+
+; Hence two macros to determine the number of rows or columns in a given
+; pass of an image given its height or width. In fact these macros may
+; return non-zero even though the sub-image is empty, because the other
+; dimension may be empty for a small image.
+
+macro PNG_PASS_ROWS height, pass
+{
+push ecx
+push ebx
+ PNG_PASS_START_ROW pass
+ mov ebx,eax
+ PNG_PASS_ROW_SHIFT pass
+ mov ecx,eax
+ xor eax,eax
+ inc eax
+ shl eax,cl
+ dec eax
+ sub eax,ebx
+pop ebx
+ add eax,height
+ shr eax,cl
+pop ecx
+}
+macro PNG_PASS_COLS width, pass
+{
+push ecx
+push ebx
+ PNG_PASS_START_COL pass
+ mov ebx,eax
+ PNG_PASS_COL_SHIFT pass
+ mov ecx,eax
+ xor eax,eax
+ inc eax
+ shl eax,cl
+ dec eax
+ sub eax,ebx
+pop ebx
+ add eax,width
+ shr eax,cl
+pop ecx
+}
+
+; For the reader row callbacks (both progressive and sequential) it is
+; necessary to find the row in the output image given a row in an interlaced
+; image, so two more macros:
+
+;#define PNG_ROW_FROM_PASS_ROW(y_in, pass) \
+; (((y_in)<>(((7-(off))-(pass))<<2)) & 0xF) | \
+; ((0x01145AF0>>(((7-(off))-(pass))<<2)) & 0xF0))
+
+;#define PNG_ROW_IN_INTERLACE_PASS(y, pass) \
+; ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1)
+;#define PNG_COL_IN_INTERLACE_PASS(x, pass) \
+; ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1)
+
+;if PNG_READ_COMPOSITE_NODIV_SUPPORTED
+; With these routines we avoid an integer divide, which will be slower on
+; most machines. However, it does take more operations than the corresponding
+; divide method, so it may be slower on a few RISC systems. There are two
+; shifts (by 8 or 16 bits) and an addition, versus a single integer divide.
+
+; Note that the rounding factors are NOT supposed to be the same! 128 and
+; 32768 are correct for the NODIV code; 127 and 32767 are correct for the
+; standard method.
+
+; [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ]
+
+
+; fg and bg should be in `gamma 1.0' space; alpha is the opacity
+
+;# define png_composite(composite, fg, alpha, bg) \
+; { \
+; uint_16 temp = (uint_16)((uint_16)(fg) \
+; * (uint_16)(alpha) \
+; + (uint_16)(bg)*(uint_16)(255 \
+; - (uint_16)(alpha)) + 128); \
+; (composite) = (byte)(((temp + (temp >> 8)) >> 8) & 0xff); \
+; }
+
+;# define png_composite_16(composite, fg, alpha, bg) \
+; { \
+; uint_32 temp = (uint_32)((uint_32)(fg) \
+; * (uint_32)(alpha) \
+; + (uint_32)(bg)*(65535 \
+; - (uint_32)(alpha)) + 32768); \
+; (composite) = (uint_16)(0xffff & ((temp + (temp >> 16)) >> 16)); \
+; }
+
+;#else /* Standard method using integer division */
+
+;# define png_composite(composite, fg, alpha, bg) \
+; (composite) = \
+; (byte)(0xff & (((uint_16)(fg) * (uint_16)(alpha) + \
+; (uint_16)(bg) * (uint_16)(255 - (uint_16)(alpha)) + \
+; 127) / 255))
+
+;# define png_composite_16(composite, fg, alpha, bg) \
+; (composite) = \
+; (uint_16)(0xffff & (((uint_32)(fg) * (uint_32)(alpha) + \
+; (uint_32)(bg)*(uint_32)(65535 - (uint_32)(alpha)) + \
+; 32767) / 65535))
+;end if /* READ_COMPOSITE_NODIV */
+
+if PNG_USE_READ_MACROS eq 1
+; Inline macros to do direct reads of bytes from the input buffer.
+; The png_get_int_32() routine assumes we are using two's complement
+; format for negative values, which is almost certainly true.
+
+;# define PNG_get_uint_32(buf) \
+; (((uint_32)(*(buf)) << 24) + \
+; ((uint_32)(*((buf) + 1)) << 16) + \
+; ((uint_32)(*((buf) + 2)) << 8) + \
+; ((uint_32)(*((buf) + 3))))
+
+ ; From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the
+ ; function) incorrectly returned a value of type uint_32.
+
+;# define PNG_get_uint_16(buf) \
+; ((uint_16) \
+; (((unsigned int)(*(buf)) << 8) + \
+; ((unsigned int)(*((buf) + 1)))))
+
+;# define PNG_get_int_32(buf) \
+; ((int_32)((*(buf) & 0x80) \
+; ? -((int_32)(((png_get_uint_32(buf)^0xffffffffU)+1U)&0x7fffffffU)) \
+; : (int_32)png_get_uint_32(buf)))
+end if
+
+;/*******************************************************************************
+; Section 5: SIMPLIFIED API
+; *******************************************************************************
+
+; Please read the documentation in libpng-manual.txt (TODO: write said
+; documentation) if you don't understand what follows.
+
+; The simplified API hides the details of both libpng and the PNG file format
+; itself. It allows PNG files to be read into a very limited number of
+; in-memory bitmap formats or to be written from the same formats. If these
+; formats do not accomodate your needs then you can, and should, use the more
+; sophisticated APIs above - these support a wide variety of in-memory formats
+; and a wide variety of sophisticated transformations to those formats as well
+; as a wide variety of APIs to manipulate ancillary information.
+
+; To read a PNG file using the simplified API:
+
+; 1) Declare a 'png_image' structure (see below) on the stack, set the
+; version field to PNG_IMAGE_VERSION and the 'opaque' pointer to NULL
+; (this is REQUIRED, your program may crash if you don't do it.)
+; 2) Call the appropriate png_image_begin_read... function.
+; 3) Set the png_image 'format' member to the required sample format.
+; 4) Allocate a buffer for the image and, if required, the color-map.
+; 5) Call png_image_finish_read to read the image and, if required, the
+; color-map into your buffers.
+
+; There are no restrictions on the format of the PNG input itself; all valid
+; color types, bit depths, and interlace methods are acceptable, and the
+; input image is transformed as necessary to the requested in-memory format
+; during the png_image_finish_read() step. The only caveat is that if you
+; request a color-mapped image from a PNG that is full-color or makes
+; complex use of an alpha channel the transformation is extremely lossy and the
+; result may look terrible.
+
+; To write a PNG file using the simplified API:
+
+; 1) Declare a 'png_image' structure on the stack and memset() it to all zero.
+; 2) Initialize the members of the structure that describe the image, setting
+; the 'format' member to the format of the image samples.
+; 3) Call the appropriate png_image_write... function with a pointer to the
+; image and, if necessary, the color-map to write the PNG data.
+
+; png_image is a structure that describes the in-memory format of an image
+; when it is being read or defines the in-memory format of an image that you
+; need to write:
+
+;#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) || \
+; defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
+
+PNG_IMAGE_VERSION equ 1
+
+struct png_image
+ opaque dd ? ;png_controlp ;Initialize to NULL, free with png_image_free
+ version dd ? ;uint_32 ;Set to PNG_IMAGE_VERSION
+ width dd ? ;uint_32 ;Image width in pixels (columns)
+ height dd ? ;uint_32 ;Image height in pixels (rows)
+ format dd ? ;uint_32 ;Image format as defined below
+ flags dd ? ;uint_32 ;A bit mask containing informational flags
+ colormap_entries dd ? ;uint_32 ;Number of entries in the color-map
+
+ ; In the event of an error or warning the following field will be set to a
+ ; non-zero value and the 'message' field will contain a '\0' terminated
+ ; string with the libpng error or warning message. If both warnings and
+ ; an error were encountered, only the error is recorded. If there
+ ; are multiple warnings, only the first one is recorded.
+
+ ; The upper 30 bits of this value are reserved, the low two bits contain
+ ; a value as follows:
+
+PNG_IMAGE_WARNING equ 1
+PNG_IMAGE_ERROR equ 2
+
+; The result is a two-bit code such that a value more than 1 indicates
+; a failure in the API just called:
+
+; 0 - no warning or error
+; 1 - warning
+; 2 - error
+; 3 - error preceded by warning
+
+;# define PNG_IMAGE_FAILED(png_cntrl) ((((png_cntrl).warning_or_error)&0x03)>1)
+
+ warning_or_error dd ? ;uint_32
+ message rb 64 ;char[64]
+ends
+
+; The samples of the image have one to four channels whose components have
+; original values in the range 0 to 1.0:
+
+; 1: A single gray or luminance channel (G).
+; 2: A gray/luminance channel and an alpha channel (GA).
+; 3: Three red, green, blue color channels (RGB).
+; 4: Three color channels and an alpha channel (RGBA).
+
+; The components are encoded in one of two ways:
+
+; a) As a small integer, value 0..255, contained in a single byte. For the
+; alpha channel the original value is simply value/255. For the color or
+; luminance channels the value is encoded according to the sRGB specification
+; and matches the 8-bit format expected by typical display devices.
+
+; The color/gray channels are not scaled (pre-multiplied) by the alpha
+; channel and are suitable for passing to color management software.
+
+; b) As a value in the range 0..65535, contained in a 2-byte integer. All
+; channels can be converted to the original value by dividing by 65535; all
+; channels are linear. Color channels use the RGB encoding (RGB end-points) of
+; the sRGB specification. This encoding is identified by the
+; PNG_FORMAT_FLAG_LINEAR flag below.
+
+; When the simplified API needs to convert between sRGB and linear colorspaces,
+; the actual sRGB transfer curve defined in the sRGB specification (see the
+; article at http://en.wikipedia.org/wiki/SRGB) is used, not the gamma=1/2.2
+; approximation used elsewhere in libpng.
+
+; When an alpha channel is present it is expected to denote pixel coverage
+; of the color or luminance channels and is returned as an associated alpha
+; channel: the color/gray channels are scaled (pre-multiplied) by the alpha
+; value.
+
+; The samples are either contained directly in the image data, between 1 and 8
+; bytes per pixel according to the encoding, or are held in a color-map indexed
+; by bytes in the image data. In the case of a color-map the color-map entries
+; are individual samples, encoded as above, and the image data has one byte per
+; pixel to select the relevant sample from the color-map.
+
+
+; PNG_FORMAT_*
+
+; #defines to be used in png_image::format. Each #define identifies a
+; particular layout of sample data and, if present, alpha values. There are
+; separate defines for each of the two component encodings.
+
+; A format is built up using single bit flag values. All combinations are
+; valid. Formats can be built up from the flag values or you can use one of
+; the predefined values below. When testing formats always use the FORMAT_FLAG
+; macros to test for individual features - future versions of the library may
+; add new flags.
+
+; When reading or writing color-mapped images the format should be set to the
+; format of the entries in the color-map then png_image_{read,write}_colormap
+; called to read or write the color-map and set the format correctly for the
+; image data. Do not set the PNG_FORMAT_FLAG_COLORMAP bit directly!
+
+; NOTE: libpng can be built with particular features disabled. If you see
+; compiler errors because the definition of one of the following flags has been
+; compiled out it is because libpng does not have the required support. It is
+; possible, however, for the libpng configuration to enable the format on just
+; read or just write; in that case you may see an error at run time. You can
+; guard against this by checking for the definition of the appropriate
+; "_SUPPORTED" macro, one of:
+
+; PNG_SIMPLIFIED_{READ,WRITE}_{BGR,AFIRST}_SUPPORTED
+
+PNG_FORMAT_FLAG_ALPHA equ 0x01 ;format with an alpha channel
+PNG_FORMAT_FLAG_COLOR equ 0x02 ;color format: otherwise grayscale
+PNG_FORMAT_FLAG_LINEAR equ 0x04 ;2-byte channels else 1-byte
+PNG_FORMAT_FLAG_COLORMAP equ 0x08 ;image data is color-mapped
+
+PNG_FORMAT_FLAG_BGR equ 0x10 ;BGR colors, else order is RGB
+
+PNG_FORMAT_FLAG_AFIRST equ 0x20 ;alpha channel comes first
+
+; Commonly used formats have predefined macros.
+
+; First the single byte (sRGB) formats:
+
+PNG_FORMAT_GRAY equ 0
+PNG_FORMAT_GA equ PNG_FORMAT_FLAG_ALPHA
+PNG_FORMAT_AG equ (PNG_FORMAT_GA|PNG_FORMAT_FLAG_AFIRST)
+PNG_FORMAT_RGB equ PNG_FORMAT_FLAG_COLOR
+PNG_FORMAT_BGR equ (PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_BGR)
+PNG_FORMAT_RGBA equ (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_ALPHA)
+PNG_FORMAT_ARGB equ (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_AFIRST)
+PNG_FORMAT_BGRA equ (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_ALPHA)
+PNG_FORMAT_ABGR equ (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_AFIRST)
+
+; Then the linear 2-byte formats. When naming these "Y" is used to
+; indicate a luminance (gray) channel.
+
+PNG_FORMAT_LINEAR_Y equ PNG_FORMAT_FLAG_LINEAR
+PNG_FORMAT_LINEAR_Y_ALPHA equ (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_ALPHA)
+PNG_FORMAT_LINEAR_RGB equ (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR)
+PNG_FORMAT_LINEAR_RGB_ALPHA equ\
+ (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA)
+
+; With color-mapped formats the image data is one byte for each pixel, the byte
+; is an index into the color-map which is formatted as above. To obtain a
+; color-mapped format it is sufficient just to add the PNG_FOMAT_FLAG_COLORMAP
+; to one of the above definitions, or you can use one of the definitions below.
+
+PNG_FORMAT_RGB_COLORMAP equ (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_COLORMAP)
+PNG_FORMAT_BGR_COLORMAP equ (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_COLORMAP)
+PNG_FORMAT_RGBA_COLORMAP equ (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_COLORMAP)
+PNG_FORMAT_ARGB_COLORMAP equ (PNG_FORMAT_ARGB|PNG_FORMAT_FLAG_COLORMAP)
+PNG_FORMAT_BGRA_COLORMAP equ (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_COLORMAP)
+PNG_FORMAT_ABGR_COLORMAP equ (PNG_FORMAT_ABGR|PNG_FORMAT_FLAG_COLORMAP)
+
+; PNG_IMAGE macros
+
+; These are convenience macros to derive information from a png_image
+; structure. The PNG_IMAGE_SAMPLE_ macros return values appropriate to the
+; actual image sample values - either the entries in the color-map or the
+; pixels in the image. The PNG_IMAGE_PIXEL_ macros return corresponding values
+; for the pixels and will always return 1 for color-mapped formats. The
+; remaining macros return information about the rows in the image and the
+; complete image.
+
+; NOTE: All the macros that take a png_image::format parameter are compile time
+; constants if the format parameter is, itself, a constant. Therefore these
+; macros can be used in array declarations and case labels where required.
+; Similarly the macros are also pre-processor constants (sizeof is not used) so
+; they can be used in #if tests.
+
+; First the information about the samples.
+
+macro PNG_IMAGE_SAMPLE_CHANNELS fmt
+{
+ mov eax,fmt
+ and eax,PNG_FORMAT_FLAG_COLOR or PNG_FORMAT_FLAG_ALPHA
+ inc eax
+}
+; Return the total number of channels in a given format: 1..4
+
+;#define PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt)\
+; ((((fmt) & PNG_FORMAT_FLAG_LINEAR) >> 2)+1)
+; /* Return the size in bytes of a single component of a pixel or color-map
+; entry (as appropriate) in the image: 1 or 2.
+
+
+;#define PNG_IMAGE_SAMPLE_SIZE(fmt)\
+; (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt))
+; /* This is the size of the sample data for one sample. If the image is
+; color-mapped it is the size of one color-map entry (and image pixels are
+; one byte in size), otherwise it is the size of one image pixel.
+
+
+;#define PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(fmt)\
+; (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * 256)
+; /* The maximum size of the color-map required by the format expressed in a
+; count of components. This can be used to compile-time allocate a
+; color-map:
+
+; uint_16 colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(linear_fmt)];
+
+; byte colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(sRGB_fmt)];
+
+; Alternatively use the PNG_IMAGE_COLORMAP_SIZE macro below to use the
+; information from one of the png_image_begin_read_ APIs and dynamically
+; allocate the required memory.
+
+
+; Corresponding information about the pixels
+macro PNG_IMAGE_PIXEL_ p1,fmt
+{
+local .end0
+local .end1
+ mov eax,fmt
+ and eax,PNG_FORMAT_FLAG_COLORMAP
+ cmp eax,0
+ je .end0
+ xor eax,eax
+ inc eax
+ jmp .end1
+ .end0:
+ p1 fmt
+ .end1:
+}
+
+macro PNG_IMAGE_PIXEL_CHANNELS fmt
+{
+ PNG_IMAGE_PIXEL_ PNG_IMAGE_SAMPLE_CHANNELS,fmt
+}
+; The number of separate channels (components) in a pixel; 1 for a
+; color-mapped image.
+
+
+;#define PNG_IMAGE_PIXEL_COMPONENT_SIZE(fmt)\
+; PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_COMPONENT_SIZE,fmt)
+; /* The size, in bytes, of each component in a pixel; 1 for a color-mapped
+; image.
+
+
+;#define PNG_IMAGE_PIXEL_SIZE(fmt) PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_SIZE,fmt)
+; /* The size, in bytes, of a complete pixel; 1 for a color-mapped image. */
+
+; Information about the whole row, or whole image
+;#define PNG_IMAGE_ROW_STRIDE(image)\
+; (PNG_IMAGE_PIXEL_CHANNELS((image).format) * (image).width)
+; Return the total number of components in a single row of the image; this
+; is the minimum 'row stride', the minimum count of components between each
+; row. For a color-mapped image this is the minimum number of bytes in a
+; row.
+
+; WARNING: this macro overflows for some images with more than one component
+; and very large image widths. libpng will refuse to process an image where
+; this macro would overflow.
+
+
+;#define PNG_IMAGE_BUFFER_SIZE(image, row_stride)\
+; (PNG_IMAGE_PIXEL_COMPONENT_SIZE((image).format)*(image).height*(row_stride))
+; Return the size, in bytes, of an image buffer given a png_image and a row
+; stride - the number of components to leave space for in each row.
+
+; WARNING: this macro overflows a 32-bit integer for some large PNG images,
+; libpng will refuse to process an image where such an overflow would occur.
+
+
+;#define PNG_IMAGE_SIZE(image)\
+; PNG_IMAGE_BUFFER_SIZE(image, PNG_IMAGE_ROW_STRIDE(image))
+; Return the size, in bytes, of the image in memory given just a png_image;
+; the row stride is the minimum stride required for the image.
+
+
+;#define PNG_IMAGE_COLORMAP_SIZE(image)\
+; (PNG_IMAGE_SAMPLE_SIZE((image).format) * (image).colormap_entries)
+; Return the size, in bytes, of the color-map of this image. If the image
+; format is not a color-map format this will return a size sufficient for
+; 256 entries in the given format; check PNG_FORMAT_FLAG_COLORMAP if
+; you don't want to allocate a color-map in this case.
+
+
+; PNG_IMAGE_FLAG_*
+
+; Flags containing additional information about the image are held in the
+; 'flags' field of png_image.
+
+PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB equ 0x01
+; This indicates the the RGB values of the in-memory bitmap do not
+; correspond to the red, green and blue end-points defined by sRGB.
+
+PNG_IMAGE_FLAG_FAST equ 0x02
+; On write emphasise speed over compression; the resultant PNG file will be
+; larger but will be produced significantly faster, particular for large
+; images. Do not use this option for images which will be distributed, only
+; used it when producing intermediate files that will be read back in
+; repeatedly. For a typical 24-bit image the option will double the read
+; speed at the cost of increasing the image size by 25%, however for many
+; more compressible images the PNG file can be 10 times larger with only a
+; slight speed gain.
+
+PNG_IMAGE_FLAG_16BIT_sRGB equ 0x04
+; On read if the image is a 16-bit per component image and there is no gAMA
+; or sRGB chunk assume that the components are sRGB encoded. Notice that
+; images output by the simplified API always have gamma information; setting
+; this flag only affects the interpretation of 16-bit images from an
+; external source. It is recommended that the application expose this flag
+; to the user; the user can normally easily recognize the difference between
+; linear and sRGB encoding. This flag has no effect on write - the data
+; passed to the write APIs must have the correct encoding (as defined
+; above.)
+
+; If the flag is not set (the default) input 16-bit per component data is
+; assumed to be linear.
+
+; NOTE: the flag can only be set after the png_image_begin_read_ call,
+; because that call initializes the 'flags' field.
+
+if PNG_SIMPLIFIED_WRITE_SUPPORTED eq 1
+; WRITE APIS
+; ----------
+; For write you must initialize a png_image structure to describe the image to
+; be written. To do this use memset to set the whole structure to 0 then
+; initialize fields describing your image.
+
+; version: must be set to PNG_IMAGE_VERSION
+; opaque: must be initialized to NULL
+; width: image width in pixels
+; height: image height in rows
+; format: the format of the data (image and color-map) you wish to write
+; flags: set to 0 unless one of the defined flags applies; set
+; PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB for color format images where the RGB
+; values do not correspond to the colors in sRGB.
+; colormap_entries: set to the number of entries in the color-map (0 to 256)
+
+; With all write APIs if image is in one of the linear formats with 16-bit
+; data then setting convert_to_8_bit will cause the output to be an 8-bit PNG
+; gamma encoded according to the sRGB specification, otherwise a 16-bit linear
+; encoded PNG file is written.
+
+; With color-mapped data formats the colormap parameter point to a color-map
+; with at least image->colormap_entries encoded in the specified format. If
+; the format is linear the written PNG color-map will be converted to sRGB
+; regardless of the convert_to_8_bit flag.
+
+; With all APIs row_stride is handled as in the read APIs - it is the spacing
+; from one row to the next in component sized units (1 or 2 bytes) and if
+; negative indicates a bottom-up row layout in the buffer. If row_stride is
+; zero, libpng will calculate it for you from the image width and number of
+; channels.
+
+; Note that the write API does not support interlacing, sub-8-bit pixels or
+; most ancillary chunks. If you need to write text chunks (e.g. for copyright
+; notices) you need to use one of the other APIs.
+
+
+;#define png_image_write_get_memory_size(image, size, convert_to_8_bit, buffer,\
+; row_stride, colormap)\
+; png_image_write_to_memory(&(image), 0, &(size), convert_to_8_bit, buffer,\
+; row_stride, colormap)
+; Return the amount of memory in 'size' required to compress this image.
+; The png_image structure 'image' must be filled in as in the above
+; function and must not be changed before the actual write call, the buffer
+; and all other parameters must also be identical to that in the final
+; write call. The 'size' variable need not be initialized.
+
+; NOTE: the macro returns true/false, if false is returned 'size' will be
+; set to zero and the write failed and probably will fail if tried again.
+
+; You can pre-allocate the buffer by making sure it is of sufficient size
+; regardless of the amount of compression achieved. The buffer size will
+; always be bigger than the original image and it will never be filled. The
+; following macros are provided to assist in allocating the buffer.
+
+;#define PNG_IMAGE_DATA_SIZE(image) (PNG_IMAGE_SIZE(image)+(image).height)
+; The number of uncompressed bytes in the PNG byte encoding of the image;
+; uncompressing the PNG IDAT data will give this number of bytes.
+
+; NOTE: while PNG_IMAGE_SIZE cannot overflow for an image in memory this
+; macro can because of the extra bytes used in the PNG byte encoding. You
+; need to avoid this macro if your image size approaches 2^30 in width or
+; height. The same goes for the remainder of these macros; they all produce
+; bigger numbers than the actual in-memory image size.
+
+;#ifndef PNG_ZLIB_MAX_SIZE
+;# define PNG_ZLIB_MAX_SIZE(b) ((b)+(((b)+7U)>>3)+(((b)+63U)>>6)+11U)
+; An upper bound on the number of compressed bytes given 'b' uncompressed
+; bytes. This is based on deflateBounds() in zlib; different
+; implementations of zlib compression may conceivably produce more data so
+; if your zlib implementation is not zlib itself redefine this macro
+; appropriately.
+
+;end if
+
+;#define PNG_IMAGE_COMPRESSED_SIZE_MAX(image)\
+; PNG_ZLIB_MAX_SIZE((png_alloc_size_t)PNG_IMAGE_DATA_SIZE(image))
+ ; An upper bound on the size of the data in the PNG IDAT chunks.
+
+;#define PNG_IMAGE_PNG_SIZE_MAX_(image, image_size)\
+; ((8U/*sig*/+25U/*IHDR*/+16U/*gAMA*/+44U/*cHRM*/+12U/*IEND*/+\
+; (((image).format&PNG_FORMAT_FLAG_COLORMAP)?/*colormap: PLTE, tRNS*/\
+; 12U+3U*(image).colormap_entries/*PLTE data*/+\
+; (((image).format&PNG_FORMAT_FLAG_ALPHA)?\
+; 12U/*tRNS*/+(image).colormap_entries:0U):0U)+\
+; 12U)+(12U*((image_size)/PNG_ZBUF_SIZE))/*IDAT*/+(image_size))
+
+; A helper for the following macro; if your compiler cannot handle the
+; following macro use this one with the result of
+; PNG_IMAGE_COMPRESSED_SIZE_MAX(image) as the second argument (most
+; compilers should handle this just fine.)
+
+;#define PNG_IMAGE_PNG_SIZE_MAX(image)\
+; PNG_IMAGE_PNG_SIZE_MAX_(image, PNG_IMAGE_COMPRESSED_SIZE_MAX(image))
+; An upper bound on the total length of the PNG data stream for 'image'.
+; The result is of type png_alloc_size_t, on 32-bit systems this may
+; overflow even though PNG_IMAGE_DATA_SIZE does not overflow; the write will
+; run out of buffer space but return a corrected size which should work.
+
+end if ;SIMPLIFIED_WRITE
+;/*******************************************************************************
+; END OF SIMPLIFIED API
+; ******************************************************************************/
+;end if /* SIMPLIFIED_{READ|WRITE} */
+
+;/*******************************************************************************
+; Section 6: IMPLEMENTATION OPTIONS
+; *******************************************************************************
+
+; Support for arbitrary implementation-specific optimizations. The API allows
+; particular options to be turned on or off. 'Option' is the number of the
+; option and 'onoff' is 0 (off) or non-0 (on). The value returned is given
+; by the PNG_OPTION_ defines below.
+
+; HARDWARE: normally hardware capabilites, such as the Intel SSE instructions,
+; are detected at run time, however sometimes it may be impossible
+; to do this in user mode, in which case it is necessary to discover
+; the capabilities in an OS specific way. Such capabilities are
+; listed here when libpng has support for them and must be turned
+; ON by the application if present.
+
+; SOFTWARE: sometimes software optimizations actually result in performance
+; decrease on some architectures or systems, or with some sets of
+; PNG images. 'Software' options allow such optimizations to be
+; selected at run time.
+
+if PNG_SET_OPTION_SUPPORTED eq 1
+if PNG_ARM_NEON_API_SUPPORTED eq 1
+ PNG_ARM_NEON equ 0 ;HARDWARE: ARM Neon SIMD instructions supported
+end if
+PNG_MAXIMUM_INFLATE_WINDOW equ 2 ;SOFTWARE: force maximum window
+PNG_SKIP_sRGB_CHECK_PROFILE equ 4 ;SOFTWARE: Check ICC profile for sRGB
+if PNG_MIPS_MSA_API_SUPPORTED eq 1
+ PNG_MIPS_MSA equ 6 ;HARDWARE: MIPS Msa SIMD instructions supported
+end if
+PNG_OPTION_NEXT equ 8 ;Next option - numbers must be even
+
+; Return values: NOTE: there are four values and 'off' is *not* zero
+PNG_OPTION_UNSET equ 0 ;Unset - defaults to off
+PNG_OPTION_INVALID equ 1 ;Option number out of range
+PNG_OPTION_OFF equ 2
+PNG_OPTION_ON equ 3
+end if ;SET_OPTION
+
+;/*******************************************************************************
+; END OF HARDWARE AND SOFTWARE OPTIONS
+; ******************************************************************************/
+
+; Maintainer: Put new public prototypes here ^, in libpng.3, in project
+; defs, and in scripts/symbols.def.
+
+
+; The last ordinal number (this is the *last* one already used; the next
+; one to use is one more than this.)
+
+;end if /* PNG_VERSION_INFO_ONLY */
+; Do not put anything past this line
diff --git a/programs/develop/libraries/libs-dev/libimg/png/libpng/pngerror.asm b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngerror.asm
index 001d21630..00404ba8a 100644
--- a/programs/develop/libraries/libs-dev/libimg/png/libpng/pngerror.asm
+++ b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngerror.asm
@@ -1,897 +1,897 @@
-
-; pngerror.asm - stub functions for i/o and memory allocation
-
-; Last changed in libpng 1.6.24 [August 4, 2016]
-; Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
-; (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
-; (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
-
-; This code is released under the libpng license.
-; For conditions of distribution and use, see the disclaimer
-; and license in png.h
-
-; This file provides a location for all error handling. Users who
-; need special error handling are expected to write replacement functions
-; and use png_set_error_fn() to use those functions. See the instructions
-; at each function.
-
-; This function is called whenever there is a fatal error. This function
-; should not be changed. If there is a need to handle errors differently,
-; you should supply a replacement error function and use png_set_error_fn()
-; to replace the error function at run-time.
-
-;if PNG_ERROR_TEXT_SUPPORTED
-;void png_error(png_const_structrp png_ptr, charp error_message)
-;{
-if PNG_ERROR_NUMBERS_SUPPORTED eq 1
-; char msg[16];
-; if (png_ptr != NULL)
-; {
-; if ((png_ptr->flags &
-; (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0)
-; {
-; if (*error_message == PNG_LITERAL_SHARP)
-; {
- ;Strip "#nnnn " from beginning of error message.
-; int offset;
-; for (offset = 1; offset<15; offset++)
-; if (error_message[offset] == ' ')
-; break;
-
-; if ((png_ptr->flags & PNG_FLAG_STRIP_ERROR_TEXT) != 0)
-; {
-; int i;
-; for (i = 0; i < offset - 1; i++)
-; msg[i] = error_message[i + 1];
-; msg[i - 1] = '\0';
-; error_message = msg;
-; }
-
-; else
-; error_message += offset;
-; }
-
-; else
-; {
-; if ((png_ptr->flags & PNG_FLAG_STRIP_ERROR_TEXT) != 0)
-; {
-; msg[0] = '0';
-; msg[1] = '\0';
-; error_message = msg;
-; }
-; }
-; }
-; }
-end if
-; if (png_ptr != NULL && png_ptr->error_fn != NULL)
-; (*(png_ptr->error_fn))(png_ptr, error_message);
-
- ; If the custom handler doesn't exist, or if it returns,
- ; use the default handler, which will not return.
-; png_default_error(png_ptr, error_message);
-;}
-;#else
-;void png_err(png_const_structrp png_ptr)
-;{
- ; Prior to 1.5.2 the error_fn received a NULL pointer, expressed
- ; erroneously as '\0', instead of the empty string "". This was
- ; apparently an error, introduced in libpng-1.2.20, and png_default_error
- ; will crash in this case.
-
-; if (png_ptr != NULL && png_ptr->error_fn != NULL)
-; (*(png_ptr->error_fn))(png_ptr, "");
-
- ; If the custom handler doesn't exist, or if it returns,
- ; use the default handler, which will not return.
-; png_default_error(png_ptr, "");
-;}
-;end if /* ERROR_TEXT */
-
-; Utility to safely appends strings to a buffer. This never errors out so
-; error checking is not required in the caller.
-
-;size_t (charp buffer, size_t bufsize, size_t pos, charp string)
-align 4
-proc png_safecat uses ebx ecx edi esi, buffer:dword, bufsize:dword, pos:dword, string:dword
- mov edi,[buffer]
- cmp edi,0
- je .end0
- mov ebx,[pos]
- mov ecx,[bufsize]
- cmp ebx,ecx
- jge .end0 ;if (..!=0 && ..<..)
- mov esi,[string]
- cmp esi,0
- je .end1 ;if (..!=0)
- dec ecx
- @@:
- cmp byte[esi],0
- je .end1
- cmp ebx,ecx
- jge .end1
- movsb
- inc ebx
- jmp @b
-align 4
- .end1:
- xor al,al
- stosb
- .end0:
- mov eax,ebx
- ret
-endp
-
-;#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_TIME_RFC1123_SUPPORTED)
-; Utility to dump an unsigned value into a buffer, given a start pointer and
-; and end pointer (which should point just *beyond* the end of the buffer!)
-; Returns the pointer to the start of the formatted string.
-
-;charp png_format_number(charp start, charp end, int format,
-; png_alloc_size_t number)
-;{
-; int count = 0; /* number of digits output */
-; int mincount = 1; /* minimum number required */
-; int output = 0; /* digit output (for the fixed point format) */
-
-; *--end = '\0';
-
-; /* This is written so that the loop always runs at least once, even with
-; * number zero.
-
-; while (end > start && (number != 0 || count < mincount))
-; {
-
-; char digits[] = "0123456789ABCDEF";
-
-; switch (format)
-; {
-; case PNG_NUMBER_FORMAT_fixed:
-; /* Needs five digits (the fraction) */
-; mincount = 5;
-; if (output != 0 || number % 10 != 0)
-; {
-; *--end = digits[number % 10];
-; output = 1;
-; }
-; number /= 10;
-; break;
-
-; case PNG_NUMBER_FORMAT_02u:
-; /* Expects at least 2 digits. */
-; mincount = 2;
-; /* FALL THROUGH */
-
-; case PNG_NUMBER_FORMAT_u:
-; *--end = digits[number % 10];
-; number /= 10;
-; break;
-
-; case PNG_NUMBER_FORMAT_02x:
-; /* This format expects at least two digits */
-; mincount = 2;
-; /* FALL THROUGH */
-
-; case PNG_NUMBER_FORMAT_x:
-; *--end = digits[number & 0xf];
-; number >>= 4;
-; break;
-
-; default: /* an error */
-; number = 0;
-; break;
-; }
-
- ; Keep track of the number of digits added
-; ++count;
-
- ; Float a fixed number here:
-; if ((format == PNG_NUMBER_FORMAT_fixed) && (count == 5) && (end > start))
-; {
- ; End of the fraction, but maybe nothing was output? In that case
- ; drop the decimal point. If the number is a true zero handle that
- ; here.
-
-; if (output != 0)
-; *--end = '.';
-; else if (number == 0) /* and !output */
-; *--end = '0';
-; }
-; }
-
-; return end;
-;}
-;end if
-
-;if PNG_WARNINGS_SUPPORTED
-; This function is called whenever there is a non-fatal error. This function
-; should not be changed. If there is a need to handle warnings differently,
-; you should supply a replacement warning function and use
-; png_set_error_fn() to replace the warning function at run-time.
-
-;void png_warning(png_const_structrp png_ptr, charp warning_message)
-;{
-; int offset = 0;
-; if (png_ptr != NULL)
-; {
-if PNG_ERROR_NUMBERS_SUPPORTED eq 1
-; if ((png_ptr->flags &
-; (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0)
-end if
-; {
-; if (*warning_message == PNG_LITERAL_SHARP)
-; {
-; for (offset = 1; offset < 15; offset++)
-; if (warning_message[offset] == ' ')
-; break;
-; }
-; }
-; }
-; if (png_ptr != NULL && png_ptr->warning_fn != NULL)
-; (*(png_ptr->warning_fn))(png_ptr, warning_message + offset);
-; else
-; png_default_warning(png_ptr, warning_message + offset);
-;}
-
-; These functions support 'formatted' warning messages with up to
-; PNG_WARNING_PARAMETER_COUNT parameters. In the format string the parameter
-; is introduced by @, where 'number' starts at 1. This follows the
-; standard established by X/Open for internationalizable error messages.
-
-;void
-;png_warning_parameter(png_warning_parameters p, int number,
-; charp string)
-;{
-; if (number > 0 && number <= PNG_WARNING_PARAMETER_COUNT)
-; (void)png_safecat(p[number-1], (sizeof p[number-1]), 0, string);
-;}
-
-;void
-;png_warning_parameter_unsigned(png_warning_parameters p, int number, int format,
-; png_alloc_size_t value)
-;{
-; char buffer[PNG_NUMBER_BUFFER_SIZE];
-; png_warning_parameter(p, number, PNG_FORMAT_NUMBER(buffer, format, value));
-;}
-
-;void (png_warning_parameters p, int number, int format, int_32 value)
-align 4
-proc png_warning_parameter_signed, p:dword, number:dword, format:dword, value:dword
-; png_alloc_size_t u;
-; charp str;
-; char buffer[PNG_NUMBER_BUFFER_SIZE];
-
- ; Avoid overflow by doing the negate in a png_alloc_size_t:
-; u = (png_alloc_size_t)value;
-; if (value < 0)
-; u = ~u + 1;
-
-; str = PNG_FORMAT_NUMBER(buffer, format, u);
-
-; if (value < 0 && str > buffer)
-; *--str = '-';
-
-; png_warning_parameter(p, number, str);
- ret
-endp
-
-;void (png_const_structrp png_ptr, png_warning_parameters p, charp message)
-align 4
-proc png_formatted_warning, png_ptr:dword, p:dword, message:dword
- ; The internal buffer is just 192 bytes - enough for all our messages,
- ; overflow doesn't happen because this code checks! If someone figures
- ; out how to send us a message longer than 192 bytes, all that will
- ; happen is that the message will be truncated appropriately.
-
-; size_t i = 0; /* Index in the msg[] buffer: */
-; char msg[192];
-
- ; Each iteration through the following loop writes at most one character
- ; to msg[i++] then returns here to validate that there is still space for
- ; the trailing '\0'. It may (in the case of a parameter) read more than
- ; one character from message[]; it must check for '\0' and continue to the
- ; test if it finds the end of string.
-
-; while (i<(sizeof msg)-1 && *message != '\0')
-; {
- ; '@' at end of string is now just printed (previously it was skipped);
- ; it is an error in the calling code to terminate the string with @.
-
-; if (p != NULL && *message == '@' && message[1] != '\0')
-; {
-; int parameter_char = *++message; /* Consume the '@' */
-; char valid_parameters[] = "123456789";
-; int parameter = 0;
-
- ; Search for the parameter digit, the index in the string is the
- ; parameter to use.
-
-; while (valid_parameters[parameter] != parameter_char &&
-; valid_parameters[parameter] != '\0')
-; ++parameter;
-
- ; If the parameter digit is out of range it will just get printed.
-; if (parameter < PNG_WARNING_PARAMETER_COUNT)
-; {
- ; Append this parameter
-; charp parm = p[parameter];
-; charp pend = p[parameter] + (sizeof p[parameter]);
-
- ; No need to copy the trailing '\0' here, but there is no guarantee
- ; that parm[] has been initialized, so there is no guarantee of a
- ; trailing '\0':
-
-; while (i<(sizeof msg)-1 && *parm != '\0' && parm < pend)
-; msg[i++] = *parm++;
-
- ; Consume the parameter digit too:
-; ++message;
-; continue;
-; }
-
- ; else not a parameter and there is a character after the @ sign; just
- ; copy that. This is known not to be '\0' because of the test above.
-
-; }
-
- ; At this point *message can't be '\0', even in the bad parameter case
- ; above where there is a lone '@' at the end of the message string.
-
-; msg[i++] = *message++;
-; }
-
- ; i is always less than (sizeof msg), so:
-; msg[i] = '\0';
-
- ; And this is the formatted message. It may be larger than
- ; PNG_MAX_ERROR_TEXT, but that is only used for 'chunk' errors and these
- ; are not (currently) formatted.
-
-; png_warning(png_ptr, msg);
- ret
-endp
-;end if /* WARNINGS */
-
-;void png_benign_error(png_const_structrp png_ptr, charp error_message)
-;{
-; if ((png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) != 0)
-; {
-;# ifdef PNG_READ_SUPPORTED
-; if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
-; png_ptr->chunk_name != 0)
-; png_chunk_warning(png_ptr, error_message);
-; else
-;# endif
-; png_warning(png_ptr, error_message);
-; }
-
-; else
-; {
-;# ifdef PNG_READ_SUPPORTED
-; if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
-; png_ptr->chunk_name != 0)
-; png_chunk_error(png_ptr, error_message);
-; else
-;# endif
-; png_error(png_ptr, error_message);
-; }
-;}
-
-;void png_app_warning(png_const_structrp png_ptr, charp error_message)
-;{
-; if ((png_ptr->flags & PNG_FLAG_APP_WARNINGS_WARN) != 0)
-; png_warning(png_ptr, error_message);
-; else
-; png_error(png_ptr, error_message);
-;}
-
-;void (png_structrp png_ptr, charp error_message)
-align 4
-proc png_app_error uses eax edi, png_ptr:dword, error_message:dword
- mov edi,[png_ptr]
- mov eax,[edi+png_struct.flags]
- and eax,PNG_FLAG_APP_ERRORS_WARN
- cmp eax,0
- je @f ;if (..!=0)
- png_warning edi, [error_message]
- jmp .end0
- @@: ;else
- png_error edi, [error_message]
- .end0:
- ret
-endp
-
-PNG_MAX_ERROR_TEXT equ 196 ;Currently limited by profile_error in png.asm
-if (PNG_WARNINGS_SUPPORTED eq 1) | \
- ((PNG_READ_SUPPORTED eq 1) & (PNG_ERROR_TEXT_SUPPORTED eq 1))
-; These utilities are used internally to build an error message that relates
-; to the current chunk. The chunk name comes from png_ptr->chunk_name,
-; which is used to prefix the message. The message is limited in length
-; to 63 bytes. The name characters are output as hex digits wrapped in []
-; if the character is invalid.
-
-;#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
-align 4
-png_digit db \ ;char[16]
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', \
- 'A', 'B', 'C', 'D', 'E', 'F'
-
-;void (png_const_structrp png_ptr, charp buffer, charp error_message)
-align 4
-proc png_format_buffer, png_ptr:dword, buffer:dword, error_message:dword
-; uint_32 chunk_name = png_ptr->chunk_name;
-; int iout = 0, ishift = 24;
-
-; while (ishift >= 0)
-; {
-; int c = (int)(chunk_name >> ishift) & 0xff;
-
-; ishift -= 8;
-; if (isnonalpha(c) != 0)
-; {
-; buffer[iout++] = PNG_LITERAL_LEFT_SQUARE_BRACKET;
-; buffer[iout++] = png_digit[(c & 0xf0) >> 4];
-; buffer[iout++] = png_digit[c & 0x0f];
-; buffer[iout++] = PNG_LITERAL_RIGHT_SQUARE_BRACKET;
-; }
-
-; else
-; {
-; buffer[iout++] = (char)c;
-; }
-; }
-
-; if (error_message == NULL)
-; buffer[iout] = '\0';
-
-; else
-; {
-; int iin = 0;
-
-; buffer[iout++] = ':';
-; buffer[iout++] = ' ';
-
-; while (iin < PNG_MAX_ERROR_TEXT-1 && error_message[iin] != '\0')
-; buffer[iout++] = error_message[iin++];
-
- ;iin < PNG_MAX_ERROR_TEXT, so the following is safe:
-; buffer[iout] = '\0';
-; }
- ret
-endp
-end if ;WARNINGS || ERROR_TEXT
-
-;void (png_const_structrp png_ptr, charp error_message)
-align 4
-proc png_chunk_error, png_ptr:dword, error_message:dword
-; char msg[18+PNG_MAX_ERROR_TEXT];
-; if (png_ptr == NULL)
-; png_error(png_ptr, error_message);
-
-; else
-; {
-; png_format_buffer(png_ptr, msg, error_message);
-; png_error(png_ptr, msg);
-; }
- ret
-endp
-
-;void (png_const_structrp png_ptr, charp warning_message)
-align 4
-proc png_chunk_warning, png_ptr:dword, warning_message:dword
-; char msg[18+PNG_MAX_ERROR_TEXT];
-; if (png_ptr == NULL)
-; png_warning(png_ptr, warning_message);
-
-; else
-; {
-; png_format_buffer(png_ptr, msg, warning_message);
-; png_warning(png_ptr, msg);
-; }
- ret
-endp
-
-;void (png_const_structrp png_ptr, charp error_message)
-align 4
-proc png_chunk_benign_error, png_ptr:dword, error_message:dword
-; if ((png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) != 0)
-; png_chunk_warning(png_ptr, error_message);
-
-; else
-; png_chunk_error(png_ptr, error_message);
- ret
-endp
-
-;void (png_const_structrp png_ptr, charp message, int error)
-align 4
-proc png_chunk_report, png_ptr:dword, message:dword, error:dword
- ; This is always supported, but for just read or just write it
- ; unconditionally does the right thing.
-
-;# if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED)
-; if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
-;# endif
-
-if PNG_READ_SUPPORTED eq 1
-; {
-; if (error < PNG_CHUNK_ERROR)
-; png_chunk_warning(png_ptr, message);
-
-; else
-; png_chunk_benign_error(png_ptr, message);
-; }
-end if
-
-;# if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED)
-; else if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
-;# endif
-
-if PNG_WRITE_SUPPORTED eq 1
-; {
-; if (error < PNG_CHUNK_WRITE_ERROR)
-; png_app_warning(png_ptr, message);
-;
-; else
-; png_app_error(png_ptr, message);
-; }
-end if
- ret
-endp
-
-;void (png_const_structrp png_ptr, charp name)
-align 4
-proc png_fixed_error, png_ptr:dword, name:dword
-;# define fixed_message "fixed point overflow in "
-;# define fixed_message_ln ((sizeof fixed_message)-1)
-; int iin;
-; char msg[fixed_message_ln+PNG_MAX_ERROR_TEXT];
-; memcpy(msg, fixed_message, fixed_message_ln);
-; iin = 0;
-; if (name != NULL)
-; while (iin < (PNG_MAX_ERROR_TEXT-1) && name[iin] != 0)
-; {
-; msg[fixed_message_ln + iin] = name[iin];
-; ++iin;
-; }
-; msg[fixed_message_ln + iin] = 0;
-; png_error(png_ptr, msg);
- ret
-endp
-
-; This API only exists if ANSI-C style error handling is used,
-; otherwise it is necessary for png_default_error to be overridden.
-
-;jmp_buf* (png_structrp png_ptr, png_longjmp_ptr longjmp_fn,
-; size_t jmp_buf_size)
-align 4
-proc png_set_longjmp_fn, png_ptr:dword, longjmp_fn:dword, jmp_buf_size:dword
- ; From libpng 1.6.0 the app gets one chance to set a 'jmpbuf_size' value
- ; and it must not change after that. Libpng doesn't care how big the
- ; buffer is, just that it doesn't change.
-
- ; If the buffer size is no *larger* than the size of jmp_buf when libpng is
- ; compiled a built in jmp_buf is returned; this preserves the pre-1.6.0
- ; semantics that this call will not fail. If the size is larger, however,
- ; the buffer is allocated and this may fail, causing the function to return
- ; NULL.
-
-; if (png_ptr == NULL)
-; return NULL;
-
-; if (png_ptr->jmp_buf_ptr == NULL)
-; {
-; png_ptr->jmp_buf_size = 0; /* not allocated */
-
-; if (jmp_buf_size <= (sizeof png_ptr->jmp_buf_local))
-; png_ptr->jmp_buf_ptr = &png_ptr->jmp_buf_local;
-
-; else
-; {
-; png_ptr->jmp_buf_ptr = png_malloc_warn(png_ptr, jmp_buf_size);
-
-; if (png_ptr->jmp_buf_ptr == NULL)
-; return NULL; /* new NULL return on OOM */
-
-; png_ptr->jmp_buf_size = jmp_buf_size;
-; }
-; }
-
-; else /* Already allocated: check the size */
-; {
-; size_t size = png_ptr->jmp_buf_size;
-
-; if (size == 0)
-; {
-; size = (sizeof png_ptr->jmp_buf_local);
-; if (png_ptr->jmp_buf_ptr != &png_ptr->jmp_buf_local)
-; {
- ; This is an internal error in libpng: somehow we have been left
- ; with a stack allocated jmp_buf when the application regained
- ; control. It's always possible to fix this up, but for the moment
- ; this is a png_error because that makes it easy to detect.
-
-; png_error(png_ptr, "Libpng jmp_buf still allocated");
-; /* png_ptr->jmp_buf_ptr = &png_ptr->jmp_buf_local; */
-; }
-; }
-
-; if (size != jmp_buf_size)
-; {
-; png_warning(png_ptr, "Application jmp_buf size changed");
-; return NULL; /* caller will probably crash: no choice here */
-; }
-; }
-
- ; Finally fill in the function, now we have a satisfactory buffer. It is
- ; valid to change the function on every call.
-
-; png_ptr->longjmp_fn = longjmp_fn;
-; return png_ptr->jmp_buf_ptr;
-.end_f:
- ret
-endp
-
-;void (png_structrp png_ptr)
-align 4
-proc png_free_jmpbuf, png_ptr:dword
-; if (png_ptr != NULL)
-; {
-; jmp_buf *jb = png_ptr->jmp_buf_ptr;
-
- ; A size of 0 is used to indicate a local, stack, allocation of the
- ; pointer; used here and in png.c
-
-; if (jb != NULL && png_ptr->jmp_buf_size > 0)
-; {
-
- ; This stuff is so that a failure to free the error control structure
- ; does not leave libpng in a state with no valid error handling: the
- ; free always succeeds, if there is an error it gets ignored.
-
-; if (jb != &png_ptr->jmp_buf_local)
-; {
-; /* Make an internal, libpng, jmp_buf to return here */
-; jmp_buf free_jmp_buf;
-
-; if (!setjmp(free_jmp_buf))
-; {
-; png_ptr->jmp_buf_ptr = &free_jmp_buf; /* come back here */
-; png_ptr->jmp_buf_size = 0; /* stack allocation */
-; png_ptr->longjmp_fn = longjmp;
-; png_free(png_ptr, jb); /* Return to setjmp on error */
-; }
-; }
-; }
-
- ; *Always* cancel everything out:
-; png_ptr->jmp_buf_size = 0;
-; png_ptr->jmp_buf_ptr = NULL;
-; png_ptr->longjmp_fn = 0;
-; }
- ret
-endp
-
-; This is the default error handling function. Note that replacements for
-; this function MUST NOT RETURN, or the program will likely crash. This
-; function is used by default, or if the program supplies NULL for the
-; error function pointer in png_set_error_fn().
-
-;void (png_const_structrp png_ptr, charp error_message)
-align 4
-proc png_default_error, png_ptr:dword, error_message:dword
-if PNG_CONSOLE_IO_SUPPORTED eq 1
-if PNG_ERROR_NUMBERS_SUPPORTED eq 1
- ; Check on NULL only added in 1.5.4
-; if (error_message != NULL && *error_message == PNG_LITERAL_SHARP)
-; {
- ; Strip "#nnnn " from beginning of error message.
-; int offset;
-; char error_number[16];
-; for (offset = 0; offset<15; offset++)
-; {
-; error_number[offset] = error_message[offset + 1];
-; if (error_message[offset] == ' ')
-; break;
-; }
-
-; if ((offset > 1) && (offset < 15))
-; {
-; error_number[offset - 1] = '\0';
-; fprintf(stderr, "libpng error no. %s: %s",
-; error_number, error_message + offset + 1);
-; fprintf(stderr, PNG_STRING_NEWLINE);
-; }
-
-; else
-; {
-; fprintf(stderr, "libpng error: %s, offset=%d",
-; error_message, offset);
-; fprintf(stderr, PNG_STRING_NEWLINE);
-; }
-; }
-; else
-end if
-; {
-; fprintf(stderr, "libpng error: %s", error_message ? error_message :
-; "undefined");
-; fprintf(stderr, PNG_STRING_NEWLINE);
-; }
-end if
-; png_longjmp(png_ptr, 1);
- ret
-endp
-
-; This function is called when there is a warning, but the library thinks
-; it can continue anyway. Replacement functions don't have to do anything
-; here if you don't want them to. In the default configuration, png_ptr is
-; not used, but it is passed in case it may be useful.
-
-;void (png_const_structrp png_ptr, charp warning_message)
-align 4
-proc png_default_warning, png_ptr:dword, warning_message:dword
-if PNG_CONSOLE_IO_SUPPORTED eq 1
-if PNG_ERROR_NUMBERS_SUPPORTED eq 1
-; if (*warning_message == PNG_LITERAL_SHARP)
-; {
-; int offset;
-; char warning_number[16];
-; for (offset = 0; offset < 15; offset++)
-; {
-; warning_number[offset] = warning_message[offset + 1];
-; if (warning_message[offset] == ' ')
-; break;
-; }
-
-; if ((offset > 1) && (offset < 15))
-; {
-; warning_number[offset + 1] = '\0';
-; fprintf(stderr, "libpng warning no. %s: %s",
-; warning_number, warning_message + offset);
-; fprintf(stderr, PNG_STRING_NEWLINE);
-; }
-
-; else
-; {
-; fprintf(stderr, "libpng warning: %s",
-; warning_message);
-; fprintf(stderr, PNG_STRING_NEWLINE);
-; }
-; }
-; else
-end if
-; {
-; fprintf(stderr, "libpng warning: %s", warning_message);
-; fprintf(stderr, PNG_STRING_NEWLINE);
-; }
-end if
- ret
-endp
-
-; This function is called when the application wants to use another method
-; of handling errors and warnings. Note that the error function MUST NOT
-; return to the calling routine or serious problems will occur. The return
-; method used in the default routine calls longjmp(png_ptr->jmp_buf_ptr, 1)
-
-;void (png_structrp png_ptr, voidp error_ptr,
-; png_error_ptr error_fn, png_error_ptr warning_fn)
-align 4
-proc png_set_error_fn, png_ptr:dword, error_ptr:dword, error_fn:dword, warning_fn:dword
-; if (png_ptr == NULL)
-; return;
-
-; png_ptr->error_ptr = error_ptr;
-; png_ptr->error_fn = error_fn;
-if PNG_WARNINGS_SUPPORTED eq 1
-; png_ptr->warning_fn = warning_fn;
-end if
- ret
-endp
-
-
-; This function returns a pointer to the error_ptr associated with the user
-; functions. The application should free any memory associated with this
-; pointer before png_write_destroy and png_read_destroy are called.
-
-;voidp (png_const_structrp png_ptr)
-align 4
-proc png_get_error_ptr, png_ptr:dword
-; if (png_ptr == NULL)
-; return NULL;
-
-; return ((voidp)png_ptr->error_ptr);
- ret
-endp
-
-;void (png_structrp png_ptr, uint_32 strip_mode)
-align 4
-proc png_set_strip_error_numbers, png_ptr:dword, strip_mode:dword
-; if (png_ptr != NULL)
-; {
-; png_ptr->flags &=
-; ((~(PNG_FLAG_STRIP_ERROR_NUMBERS |
-; PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode);
-; }
- ret
-endp
-
-; Currently the above both depend on SETJMP_SUPPORTED, however it would be
-; possible to implement without setjmp support just so long as there is some
-; way to handle the error return here:
-
-;void (png_structp png_nonconst_ptr, charp error_message)
-align 4
-proc png_safe_error uses eax ebx, png_nonconst_ptr:dword, error_message:dword
- mov ebx,[png_nonconst_ptr]
- mov ebx,[ebx+png_struct.error_ptr]
- ; An error is always logged here, overwriting anything (typically a warning)
- ; that is already there:
-
- cmp ebx,0
- je .end0 ;if (..!=0)
- stdcall png_safecat, dword[ebx+png_image.message], sizeof.png_image.message, 0, [error_message]
- or dword[ebx+png_image.warning_or_error], PNG_IMAGE_ERROR
-
- ; Retrieve the jmp_buf from within the png_control, making this work for
- ; C++ compilation too is pretty tricky: C++ wants a pointer to the first
- ; element of a jmp_buf, but C doesn't tell us the type of that.
-
-; if (image->opaque != NULL && image->opaque->error_buf != NULL)
-; longjmp(png_control_jmp_buf(image->opaque), 1);
-
- ; Missing longjmp buffer, the following is to help debugging:
-; {
-; size_t pos = png_safecat(image->message, (sizeof image->message), 0,
-; "bad longjmp: ");
-; png_safecat(image->message, (sizeof image->message), pos,
-; error_message);
-; }
- .end0:
-
- ; Here on an internal programming error.
-; abort();
- ret
-endp
-
-;void (png_structp png_nonconst_ptr, charp warning_message)
-align 4
-proc png_safe_warning uses eax ebx, png_nonconst_ptr:dword, warning_message:dword
- mov ebx,[png_nonconst_ptr]
- mov ebx,[ebx+png_struct.error_ptr]
-
- ; A warning is only logged if there is no prior warning or error.
- cmp dword[ebx+png_image.warning_or_error],0
- jne @f ;if (..==0)
- stdcall png_safecat, dword[ebx+png_image.message], sizeof.png_image.message, 0, [warning_message]
- or dword[ebx+png_image.warning_or_error], PNG_IMAGE_WARNING
- @@:
- ret
-endp
-
-;int (png_imagep image_in, int (*function)(voidp), voidp arg)
-align 4
-proc png_safe_execute uses ebx, image_in:dword, function:dword, arg:dword
-; volatile png_imagep image = image_in;
-; volatile int result;
-; volatile voidp saved_error_buf;
-; jmp_buf safe_jmpbuf;
-
- ; Safely execute function(arg) with png_error returning to this function.
- mov ebx,[image_in]
-; saved_error_buf = image->opaque->error_buf;
-; result = setjmp(safe_jmpbuf) == 0;
-
-; if (result != 0)
-; {
-; image->opaque->error_buf = safe_jmpbuf;
- stdcall [function], [arg]
-; }
-
-; image->opaque->error_buf = saved_error_buf;
-
- ; And do the cleanup prior to any failure return.
- cmp eax,0
- jne @f ;if (..==0)
- stdcall png_image_free, ebx
- @@:
- ret
-endp
-
+
+; pngerror.asm - stub functions for i/o and memory allocation
+
+; Last changed in libpng 1.6.24 [August 4, 2016]
+; Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
+; (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+; (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+
+; This code is released under the libpng license.
+; For conditions of distribution and use, see the disclaimer
+; and license in png.h
+
+; This file provides a location for all error handling. Users who
+; need special error handling are expected to write replacement functions
+; and use png_set_error_fn() to use those functions. See the instructions
+; at each function.
+
+; This function is called whenever there is a fatal error. This function
+; should not be changed. If there is a need to handle errors differently,
+; you should supply a replacement error function and use png_set_error_fn()
+; to replace the error function at run-time.
+
+;if PNG_ERROR_TEXT_SUPPORTED
+;void png_error(png_const_structrp png_ptr, charp error_message)
+;{
+if PNG_ERROR_NUMBERS_SUPPORTED eq 1
+; char msg[16];
+; if (png_ptr != NULL)
+; {
+; if ((png_ptr->flags &
+; (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0)
+; {
+; if (*error_message == PNG_LITERAL_SHARP)
+; {
+ ;Strip "#nnnn " from beginning of error message.
+; int offset;
+; for (offset = 1; offset<15; offset++)
+; if (error_message[offset] == ' ')
+; break;
+
+; if ((png_ptr->flags & PNG_FLAG_STRIP_ERROR_TEXT) != 0)
+; {
+; int i;
+; for (i = 0; i < offset - 1; i++)
+; msg[i] = error_message[i + 1];
+; msg[i - 1] = '\0';
+; error_message = msg;
+; }
+
+; else
+; error_message += offset;
+; }
+
+; else
+; {
+; if ((png_ptr->flags & PNG_FLAG_STRIP_ERROR_TEXT) != 0)
+; {
+; msg[0] = '0';
+; msg[1] = '\0';
+; error_message = msg;
+; }
+; }
+; }
+; }
+end if
+; if (png_ptr != NULL && png_ptr->error_fn != NULL)
+; (*(png_ptr->error_fn))(png_ptr, error_message);
+
+ ; If the custom handler doesn't exist, or if it returns,
+ ; use the default handler, which will not return.
+; png_default_error(png_ptr, error_message);
+;}
+;#else
+;void png_err(png_const_structrp png_ptr)
+;{
+ ; Prior to 1.5.2 the error_fn received a NULL pointer, expressed
+ ; erroneously as '\0', instead of the empty string "". This was
+ ; apparently an error, introduced in libpng-1.2.20, and png_default_error
+ ; will crash in this case.
+
+; if (png_ptr != NULL && png_ptr->error_fn != NULL)
+; (*(png_ptr->error_fn))(png_ptr, "");
+
+ ; If the custom handler doesn't exist, or if it returns,
+ ; use the default handler, which will not return.
+; png_default_error(png_ptr, "");
+;}
+;end if /* ERROR_TEXT */
+
+; Utility to safely appends strings to a buffer. This never errors out so
+; error checking is not required in the caller.
+
+;size_t (charp buffer, size_t bufsize, size_t pos, charp string)
+align 4
+proc png_safecat uses ebx ecx edi esi, buffer:dword, bufsize:dword, pos:dword, string:dword
+ mov edi,[buffer]
+ cmp edi,0
+ je .end0
+ mov ebx,[pos]
+ mov ecx,[bufsize]
+ cmp ebx,ecx
+ jge .end0 ;if (..!=0 && ..<..)
+ mov esi,[string]
+ cmp esi,0
+ je .end1 ;if (..!=0)
+ dec ecx
+ @@:
+ cmp byte[esi],0
+ je .end1
+ cmp ebx,ecx
+ jge .end1
+ movsb
+ inc ebx
+ jmp @b
+align 4
+ .end1:
+ xor al,al
+ stosb
+ .end0:
+ mov eax,ebx
+ ret
+endp
+
+;#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_TIME_RFC1123_SUPPORTED)
+; Utility to dump an unsigned value into a buffer, given a start pointer and
+; and end pointer (which should point just *beyond* the end of the buffer!)
+; Returns the pointer to the start of the formatted string.
+
+;charp png_format_number(charp start, charp end, int format,
+; png_alloc_size_t number)
+;{
+; int count = 0; /* number of digits output */
+; int mincount = 1; /* minimum number required */
+; int output = 0; /* digit output (for the fixed point format) */
+
+; *--end = '\0';
+
+; /* This is written so that the loop always runs at least once, even with
+; * number zero.
+
+; while (end > start && (number != 0 || count < mincount))
+; {
+
+; char digits[] = "0123456789ABCDEF";
+
+; switch (format)
+; {
+; case PNG_NUMBER_FORMAT_fixed:
+; /* Needs five digits (the fraction) */
+; mincount = 5;
+; if (output != 0 || number % 10 != 0)
+; {
+; *--end = digits[number % 10];
+; output = 1;
+; }
+; number /= 10;
+; break;
+
+; case PNG_NUMBER_FORMAT_02u:
+; /* Expects at least 2 digits. */
+; mincount = 2;
+; /* FALL THROUGH */
+
+; case PNG_NUMBER_FORMAT_u:
+; *--end = digits[number % 10];
+; number /= 10;
+; break;
+
+; case PNG_NUMBER_FORMAT_02x:
+; /* This format expects at least two digits */
+; mincount = 2;
+; /* FALL THROUGH */
+
+; case PNG_NUMBER_FORMAT_x:
+; *--end = digits[number & 0xf];
+; number >>= 4;
+; break;
+
+; default: /* an error */
+; number = 0;
+; break;
+; }
+
+ ; Keep track of the number of digits added
+; ++count;
+
+ ; Float a fixed number here:
+; if ((format == PNG_NUMBER_FORMAT_fixed) && (count == 5) && (end > start))
+; {
+ ; End of the fraction, but maybe nothing was output? In that case
+ ; drop the decimal point. If the number is a true zero handle that
+ ; here.
+
+; if (output != 0)
+; *--end = '.';
+; else if (number == 0) /* and !output */
+; *--end = '0';
+; }
+; }
+
+; return end;
+;}
+;end if
+
+;if PNG_WARNINGS_SUPPORTED
+; This function is called whenever there is a non-fatal error. This function
+; should not be changed. If there is a need to handle warnings differently,
+; you should supply a replacement warning function and use
+; png_set_error_fn() to replace the warning function at run-time.
+
+;void png_warning(png_const_structrp png_ptr, charp warning_message)
+;{
+; int offset = 0;
+; if (png_ptr != NULL)
+; {
+if PNG_ERROR_NUMBERS_SUPPORTED eq 1
+; if ((png_ptr->flags &
+; (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0)
+end if
+; {
+; if (*warning_message == PNG_LITERAL_SHARP)
+; {
+; for (offset = 1; offset < 15; offset++)
+; if (warning_message[offset] == ' ')
+; break;
+; }
+; }
+; }
+; if (png_ptr != NULL && png_ptr->warning_fn != NULL)
+; (*(png_ptr->warning_fn))(png_ptr, warning_message + offset);
+; else
+; png_default_warning(png_ptr, warning_message + offset);
+;}
+
+; These functions support 'formatted' warning messages with up to
+; PNG_WARNING_PARAMETER_COUNT parameters. In the format string the parameter
+; is introduced by @, where 'number' starts at 1. This follows the
+; standard established by X/Open for internationalizable error messages.
+
+;void
+;png_warning_parameter(png_warning_parameters p, int number,
+; charp string)
+;{
+; if (number > 0 && number <= PNG_WARNING_PARAMETER_COUNT)
+; (void)png_safecat(p[number-1], (sizeof p[number-1]), 0, string);
+;}
+
+;void
+;png_warning_parameter_unsigned(png_warning_parameters p, int number, int format,
+; png_alloc_size_t value)
+;{
+; char buffer[PNG_NUMBER_BUFFER_SIZE];
+; png_warning_parameter(p, number, PNG_FORMAT_NUMBER(buffer, format, value));
+;}
+
+;void (png_warning_parameters p, int number, int format, int_32 value)
+align 4
+proc png_warning_parameter_signed, p:dword, number:dword, format:dword, value:dword
+; png_alloc_size_t u;
+; charp str;
+; char buffer[PNG_NUMBER_BUFFER_SIZE];
+
+ ; Avoid overflow by doing the negate in a png_alloc_size_t:
+; u = (png_alloc_size_t)value;
+; if (value < 0)
+; u = ~u + 1;
+
+; str = PNG_FORMAT_NUMBER(buffer, format, u);
+
+; if (value < 0 && str > buffer)
+; *--str = '-';
+
+; png_warning_parameter(p, number, str);
+ ret
+endp
+
+;void (png_const_structrp png_ptr, png_warning_parameters p, charp message)
+align 4
+proc png_formatted_warning, png_ptr:dword, p:dword, message:dword
+ ; The internal buffer is just 192 bytes - enough for all our messages,
+ ; overflow doesn't happen because this code checks! If someone figures
+ ; out how to send us a message longer than 192 bytes, all that will
+ ; happen is that the message will be truncated appropriately.
+
+; size_t i = 0; /* Index in the msg[] buffer: */
+; char msg[192];
+
+ ; Each iteration through the following loop writes at most one character
+ ; to msg[i++] then returns here to validate that there is still space for
+ ; the trailing '\0'. It may (in the case of a parameter) read more than
+ ; one character from message[]; it must check for '\0' and continue to the
+ ; test if it finds the end of string.
+
+; while (i<(sizeof msg)-1 && *message != '\0')
+; {
+ ; '@' at end of string is now just printed (previously it was skipped);
+ ; it is an error in the calling code to terminate the string with @.
+
+; if (p != NULL && *message == '@' && message[1] != '\0')
+; {
+; int parameter_char = *++message; /* Consume the '@' */
+; char valid_parameters[] = "123456789";
+; int parameter = 0;
+
+ ; Search for the parameter digit, the index in the string is the
+ ; parameter to use.
+
+; while (valid_parameters[parameter] != parameter_char &&
+; valid_parameters[parameter] != '\0')
+; ++parameter;
+
+ ; If the parameter digit is out of range it will just get printed.
+; if (parameter < PNG_WARNING_PARAMETER_COUNT)
+; {
+ ; Append this parameter
+; charp parm = p[parameter];
+; charp pend = p[parameter] + (sizeof p[parameter]);
+
+ ; No need to copy the trailing '\0' here, but there is no guarantee
+ ; that parm[] has been initialized, so there is no guarantee of a
+ ; trailing '\0':
+
+; while (i<(sizeof msg)-1 && *parm != '\0' && parm < pend)
+; msg[i++] = *parm++;
+
+ ; Consume the parameter digit too:
+; ++message;
+; continue;
+; }
+
+ ; else not a parameter and there is a character after the @ sign; just
+ ; copy that. This is known not to be '\0' because of the test above.
+
+; }
+
+ ; At this point *message can't be '\0', even in the bad parameter case
+ ; above where there is a lone '@' at the end of the message string.
+
+; msg[i++] = *message++;
+; }
+
+ ; i is always less than (sizeof msg), so:
+; msg[i] = '\0';
+
+ ; And this is the formatted message. It may be larger than
+ ; PNG_MAX_ERROR_TEXT, but that is only used for 'chunk' errors and these
+ ; are not (currently) formatted.
+
+; png_warning(png_ptr, msg);
+ ret
+endp
+;end if /* WARNINGS */
+
+;void png_benign_error(png_const_structrp png_ptr, charp error_message)
+;{
+; if ((png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) != 0)
+; {
+;# ifdef PNG_READ_SUPPORTED
+; if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
+; png_ptr->chunk_name != 0)
+; png_chunk_warning(png_ptr, error_message);
+; else
+;# endif
+; png_warning(png_ptr, error_message);
+; }
+
+; else
+; {
+;# ifdef PNG_READ_SUPPORTED
+; if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
+; png_ptr->chunk_name != 0)
+; png_chunk_error(png_ptr, error_message);
+; else
+;# endif
+; png_error(png_ptr, error_message);
+; }
+;}
+
+;void png_app_warning(png_const_structrp png_ptr, charp error_message)
+;{
+; if ((png_ptr->flags & PNG_FLAG_APP_WARNINGS_WARN) != 0)
+; png_warning(png_ptr, error_message);
+; else
+; png_error(png_ptr, error_message);
+;}
+
+;void (png_structrp png_ptr, charp error_message)
+align 4
+proc png_app_error uses eax edi, png_ptr:dword, error_message:dword
+ mov edi,[png_ptr]
+ mov eax,[edi+png_struct.flags]
+ and eax,PNG_FLAG_APP_ERRORS_WARN
+ cmp eax,0
+ je @f ;if (..!=0)
+ png_warning edi, [error_message]
+ jmp .end0
+ @@: ;else
+ png_error edi, [error_message]
+ .end0:
+ ret
+endp
+
+PNG_MAX_ERROR_TEXT equ 196 ;Currently limited by profile_error in png.asm
+if (PNG_WARNINGS_SUPPORTED eq 1) | \
+ ((PNG_READ_SUPPORTED eq 1) & (PNG_ERROR_TEXT_SUPPORTED eq 1))
+; These utilities are used internally to build an error message that relates
+; to the current chunk. The chunk name comes from png_ptr->chunk_name,
+; which is used to prefix the message. The message is limited in length
+; to 63 bytes. The name characters are output as hex digits wrapped in []
+; if the character is invalid.
+
+;#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
+align 4
+png_digit db \ ;char[16]
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', \
+ 'A', 'B', 'C', 'D', 'E', 'F'
+
+;void (png_const_structrp png_ptr, charp buffer, charp error_message)
+align 4
+proc png_format_buffer, png_ptr:dword, buffer:dword, error_message:dword
+; uint_32 chunk_name = png_ptr->chunk_name;
+; int iout = 0, ishift = 24;
+
+; while (ishift >= 0)
+; {
+; int c = (int)(chunk_name >> ishift) & 0xff;
+
+; ishift -= 8;
+; if (isnonalpha(c) != 0)
+; {
+; buffer[iout++] = PNG_LITERAL_LEFT_SQUARE_BRACKET;
+; buffer[iout++] = png_digit[(c & 0xf0) >> 4];
+; buffer[iout++] = png_digit[c & 0x0f];
+; buffer[iout++] = PNG_LITERAL_RIGHT_SQUARE_BRACKET;
+; }
+
+; else
+; {
+; buffer[iout++] = (char)c;
+; }
+; }
+
+; if (error_message == NULL)
+; buffer[iout] = '\0';
+
+; else
+; {
+; int iin = 0;
+
+; buffer[iout++] = ':';
+; buffer[iout++] = ' ';
+
+; while (iin < PNG_MAX_ERROR_TEXT-1 && error_message[iin] != '\0')
+; buffer[iout++] = error_message[iin++];
+
+ ;iin < PNG_MAX_ERROR_TEXT, so the following is safe:
+; buffer[iout] = '\0';
+; }
+ ret
+endp
+end if ;WARNINGS || ERROR_TEXT
+
+;void (png_const_structrp png_ptr, charp error_message)
+align 4
+proc png_chunk_error, png_ptr:dword, error_message:dword
+; char msg[18+PNG_MAX_ERROR_TEXT];
+; if (png_ptr == NULL)
+; png_error(png_ptr, error_message);
+
+; else
+; {
+; png_format_buffer(png_ptr, msg, error_message);
+; png_error(png_ptr, msg);
+; }
+ ret
+endp
+
+;void (png_const_structrp png_ptr, charp warning_message)
+align 4
+proc png_chunk_warning, png_ptr:dword, warning_message:dword
+; char msg[18+PNG_MAX_ERROR_TEXT];
+; if (png_ptr == NULL)
+; png_warning(png_ptr, warning_message);
+
+; else
+; {
+; png_format_buffer(png_ptr, msg, warning_message);
+; png_warning(png_ptr, msg);
+; }
+ ret
+endp
+
+;void (png_const_structrp png_ptr, charp error_message)
+align 4
+proc png_chunk_benign_error, png_ptr:dword, error_message:dword
+; if ((png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) != 0)
+; png_chunk_warning(png_ptr, error_message);
+
+; else
+; png_chunk_error(png_ptr, error_message);
+ ret
+endp
+
+;void (png_const_structrp png_ptr, charp message, int error)
+align 4
+proc png_chunk_report, png_ptr:dword, message:dword, error:dword
+ ; This is always supported, but for just read or just write it
+ ; unconditionally does the right thing.
+
+;# if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED)
+; if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
+;# endif
+
+if PNG_READ_SUPPORTED eq 1
+; {
+; if (error < PNG_CHUNK_ERROR)
+; png_chunk_warning(png_ptr, message);
+
+; else
+; png_chunk_benign_error(png_ptr, message);
+; }
+end if
+
+;# if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED)
+; else if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
+;# endif
+
+if PNG_WRITE_SUPPORTED eq 1
+; {
+; if (error < PNG_CHUNK_WRITE_ERROR)
+; png_app_warning(png_ptr, message);
+;
+; else
+; png_app_error(png_ptr, message);
+; }
+end if
+ ret
+endp
+
+;void (png_const_structrp png_ptr, charp name)
+align 4
+proc png_fixed_error, png_ptr:dword, name:dword
+;# define fixed_message "fixed point overflow in "
+;# define fixed_message_ln ((sizeof fixed_message)-1)
+; int iin;
+; char msg[fixed_message_ln+PNG_MAX_ERROR_TEXT];
+; memcpy(msg, fixed_message, fixed_message_ln);
+; iin = 0;
+; if (name != NULL)
+; while (iin < (PNG_MAX_ERROR_TEXT-1) && name[iin] != 0)
+; {
+; msg[fixed_message_ln + iin] = name[iin];
+; ++iin;
+; }
+; msg[fixed_message_ln + iin] = 0;
+; png_error(png_ptr, msg);
+ ret
+endp
+
+; This API only exists if ANSI-C style error handling is used,
+; otherwise it is necessary for png_default_error to be overridden.
+
+;jmp_buf* (png_structrp png_ptr, png_longjmp_ptr longjmp_fn,
+; size_t jmp_buf_size)
+align 4
+proc png_set_longjmp_fn, png_ptr:dword, longjmp_fn:dword, jmp_buf_size:dword
+ ; From libpng 1.6.0 the app gets one chance to set a 'jmpbuf_size' value
+ ; and it must not change after that. Libpng doesn't care how big the
+ ; buffer is, just that it doesn't change.
+
+ ; If the buffer size is no *larger* than the size of jmp_buf when libpng is
+ ; compiled a built in jmp_buf is returned; this preserves the pre-1.6.0
+ ; semantics that this call will not fail. If the size is larger, however,
+ ; the buffer is allocated and this may fail, causing the function to return
+ ; NULL.
+
+; if (png_ptr == NULL)
+; return NULL;
+
+; if (png_ptr->jmp_buf_ptr == NULL)
+; {
+; png_ptr->jmp_buf_size = 0; /* not allocated */
+
+; if (jmp_buf_size <= (sizeof png_ptr->jmp_buf_local))
+; png_ptr->jmp_buf_ptr = &png_ptr->jmp_buf_local;
+
+; else
+; {
+; png_ptr->jmp_buf_ptr = png_malloc_warn(png_ptr, jmp_buf_size);
+
+; if (png_ptr->jmp_buf_ptr == NULL)
+; return NULL; /* new NULL return on OOM */
+
+; png_ptr->jmp_buf_size = jmp_buf_size;
+; }
+; }
+
+; else /* Already allocated: check the size */
+; {
+; size_t size = png_ptr->jmp_buf_size;
+
+; if (size == 0)
+; {
+; size = (sizeof png_ptr->jmp_buf_local);
+; if (png_ptr->jmp_buf_ptr != &png_ptr->jmp_buf_local)
+; {
+ ; This is an internal error in libpng: somehow we have been left
+ ; with a stack allocated jmp_buf when the application regained
+ ; control. It's always possible to fix this up, but for the moment
+ ; this is a png_error because that makes it easy to detect.
+
+; png_error(png_ptr, "Libpng jmp_buf still allocated");
+; /* png_ptr->jmp_buf_ptr = &png_ptr->jmp_buf_local; */
+; }
+; }
+
+; if (size != jmp_buf_size)
+; {
+; png_warning(png_ptr, "Application jmp_buf size changed");
+; return NULL; /* caller will probably crash: no choice here */
+; }
+; }
+
+ ; Finally fill in the function, now we have a satisfactory buffer. It is
+ ; valid to change the function on every call.
+
+; png_ptr->longjmp_fn = longjmp_fn;
+; return png_ptr->jmp_buf_ptr;
+.end_f:
+ ret
+endp
+
+;void (png_structrp png_ptr)
+align 4
+proc png_free_jmpbuf, png_ptr:dword
+; if (png_ptr != NULL)
+; {
+; jmp_buf *jb = png_ptr->jmp_buf_ptr;
+
+ ; A size of 0 is used to indicate a local, stack, allocation of the
+ ; pointer; used here and in png.c
+
+; if (jb != NULL && png_ptr->jmp_buf_size > 0)
+; {
+
+ ; This stuff is so that a failure to free the error control structure
+ ; does not leave libpng in a state with no valid error handling: the
+ ; free always succeeds, if there is an error it gets ignored.
+
+; if (jb != &png_ptr->jmp_buf_local)
+; {
+; /* Make an internal, libpng, jmp_buf to return here */
+; jmp_buf free_jmp_buf;
+
+; if (!setjmp(free_jmp_buf))
+; {
+; png_ptr->jmp_buf_ptr = &free_jmp_buf; /* come back here */
+; png_ptr->jmp_buf_size = 0; /* stack allocation */
+; png_ptr->longjmp_fn = longjmp;
+; png_free(png_ptr, jb); /* Return to setjmp on error */
+; }
+; }
+; }
+
+ ; *Always* cancel everything out:
+; png_ptr->jmp_buf_size = 0;
+; png_ptr->jmp_buf_ptr = NULL;
+; png_ptr->longjmp_fn = 0;
+; }
+ ret
+endp
+
+; This is the default error handling function. Note that replacements for
+; this function MUST NOT RETURN, or the program will likely crash. This
+; function is used by default, or if the program supplies NULL for the
+; error function pointer in png_set_error_fn().
+
+;void (png_const_structrp png_ptr, charp error_message)
+align 4
+proc png_default_error, png_ptr:dword, error_message:dword
+if PNG_CONSOLE_IO_SUPPORTED eq 1
+if PNG_ERROR_NUMBERS_SUPPORTED eq 1
+ ; Check on NULL only added in 1.5.4
+; if (error_message != NULL && *error_message == PNG_LITERAL_SHARP)
+; {
+ ; Strip "#nnnn " from beginning of error message.
+; int offset;
+; char error_number[16];
+; for (offset = 0; offset<15; offset++)
+; {
+; error_number[offset] = error_message[offset + 1];
+; if (error_message[offset] == ' ')
+; break;
+; }
+
+; if ((offset > 1) && (offset < 15))
+; {
+; error_number[offset - 1] = '\0';
+; fprintf(stderr, "libpng error no. %s: %s",
+; error_number, error_message + offset + 1);
+; fprintf(stderr, PNG_STRING_NEWLINE);
+; }
+
+; else
+; {
+; fprintf(stderr, "libpng error: %s, offset=%d",
+; error_message, offset);
+; fprintf(stderr, PNG_STRING_NEWLINE);
+; }
+; }
+; else
+end if
+; {
+; fprintf(stderr, "libpng error: %s", error_message ? error_message :
+; "undefined");
+; fprintf(stderr, PNG_STRING_NEWLINE);
+; }
+end if
+; png_longjmp(png_ptr, 1);
+ ret
+endp
+
+; This function is called when there is a warning, but the library thinks
+; it can continue anyway. Replacement functions don't have to do anything
+; here if you don't want them to. In the default configuration, png_ptr is
+; not used, but it is passed in case it may be useful.
+
+;void (png_const_structrp png_ptr, charp warning_message)
+align 4
+proc png_default_warning, png_ptr:dword, warning_message:dword
+if PNG_CONSOLE_IO_SUPPORTED eq 1
+if PNG_ERROR_NUMBERS_SUPPORTED eq 1
+; if (*warning_message == PNG_LITERAL_SHARP)
+; {
+; int offset;
+; char warning_number[16];
+; for (offset = 0; offset < 15; offset++)
+; {
+; warning_number[offset] = warning_message[offset + 1];
+; if (warning_message[offset] == ' ')
+; break;
+; }
+
+; if ((offset > 1) && (offset < 15))
+; {
+; warning_number[offset + 1] = '\0';
+; fprintf(stderr, "libpng warning no. %s: %s",
+; warning_number, warning_message + offset);
+; fprintf(stderr, PNG_STRING_NEWLINE);
+; }
+
+; else
+; {
+; fprintf(stderr, "libpng warning: %s",
+; warning_message);
+; fprintf(stderr, PNG_STRING_NEWLINE);
+; }
+; }
+; else
+end if
+; {
+; fprintf(stderr, "libpng warning: %s", warning_message);
+; fprintf(stderr, PNG_STRING_NEWLINE);
+; }
+end if
+ ret
+endp
+
+; This function is called when the application wants to use another method
+; of handling errors and warnings. Note that the error function MUST NOT
+; return to the calling routine or serious problems will occur. The return
+; method used in the default routine calls longjmp(png_ptr->jmp_buf_ptr, 1)
+
+;void (png_structrp png_ptr, voidp error_ptr,
+; png_error_ptr error_fn, png_error_ptr warning_fn)
+align 4
+proc png_set_error_fn, png_ptr:dword, error_ptr:dword, error_fn:dword, warning_fn:dword
+; if (png_ptr == NULL)
+; return;
+
+; png_ptr->error_ptr = error_ptr;
+; png_ptr->error_fn = error_fn;
+if PNG_WARNINGS_SUPPORTED eq 1
+; png_ptr->warning_fn = warning_fn;
+end if
+ ret
+endp
+
+
+; This function returns a pointer to the error_ptr associated with the user
+; functions. The application should free any memory associated with this
+; pointer before png_write_destroy and png_read_destroy are called.
+
+;voidp (png_const_structrp png_ptr)
+align 4
+proc png_get_error_ptr, png_ptr:dword
+; if (png_ptr == NULL)
+; return NULL;
+
+; return ((voidp)png_ptr->error_ptr);
+ ret
+endp
+
+;void (png_structrp png_ptr, uint_32 strip_mode)
+align 4
+proc png_set_strip_error_numbers, png_ptr:dword, strip_mode:dword
+; if (png_ptr != NULL)
+; {
+; png_ptr->flags &=
+; ((~(PNG_FLAG_STRIP_ERROR_NUMBERS |
+; PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode);
+; }
+ ret
+endp
+
+; Currently the above both depend on SETJMP_SUPPORTED, however it would be
+; possible to implement without setjmp support just so long as there is some
+; way to handle the error return here:
+
+;void (png_structp png_nonconst_ptr, charp error_message)
+align 4
+proc png_safe_error uses eax ebx, png_nonconst_ptr:dword, error_message:dword
+ mov ebx,[png_nonconst_ptr]
+ mov ebx,[ebx+png_struct.error_ptr]
+ ; An error is always logged here, overwriting anything (typically a warning)
+ ; that is already there:
+
+ cmp ebx,0
+ je .end0 ;if (..!=0)
+ stdcall png_safecat, dword[ebx+png_image.message], sizeof.png_image.message, 0, [error_message]
+ or dword[ebx+png_image.warning_or_error], PNG_IMAGE_ERROR
+
+ ; Retrieve the jmp_buf from within the png_control, making this work for
+ ; C++ compilation too is pretty tricky: C++ wants a pointer to the first
+ ; element of a jmp_buf, but C doesn't tell us the type of that.
+
+; if (image->opaque != NULL && image->opaque->error_buf != NULL)
+; longjmp(png_control_jmp_buf(image->opaque), 1);
+
+ ; Missing longjmp buffer, the following is to help debugging:
+; {
+; size_t pos = png_safecat(image->message, (sizeof image->message), 0,
+; "bad longjmp: ");
+; png_safecat(image->message, (sizeof image->message), pos,
+; error_message);
+; }
+ .end0:
+
+ ; Here on an internal programming error.
+; abort();
+ ret
+endp
+
+;void (png_structp png_nonconst_ptr, charp warning_message)
+align 4
+proc png_safe_warning uses eax ebx, png_nonconst_ptr:dword, warning_message:dword
+ mov ebx,[png_nonconst_ptr]
+ mov ebx,[ebx+png_struct.error_ptr]
+
+ ; A warning is only logged if there is no prior warning or error.
+ cmp dword[ebx+png_image.warning_or_error],0
+ jne @f ;if (..==0)
+ stdcall png_safecat, dword[ebx+png_image.message], sizeof.png_image.message, 0, [warning_message]
+ or dword[ebx+png_image.warning_or_error], PNG_IMAGE_WARNING
+ @@:
+ ret
+endp
+
+;int (png_imagep image_in, int (*function)(voidp), voidp arg)
+align 4
+proc png_safe_execute uses ebx, image_in:dword, function:dword, arg:dword
+; volatile png_imagep image = image_in;
+; volatile int result;
+; volatile voidp saved_error_buf;
+; jmp_buf safe_jmpbuf;
+
+ ; Safely execute function(arg) with png_error returning to this function.
+ mov ebx,[image_in]
+; saved_error_buf = image->opaque->error_buf;
+; result = setjmp(safe_jmpbuf) == 0;
+
+; if (result != 0)
+; {
+; image->opaque->error_buf = safe_jmpbuf;
+ stdcall [function], [arg]
+; }
+
+; image->opaque->error_buf = saved_error_buf;
+
+ ; And do the cleanup prior to any failure return.
+ cmp eax,0
+ jne @f ;if (..==0)
+ stdcall png_image_free, ebx
+ @@:
+ ret
+endp
+
diff --git a/programs/develop/libraries/libs-dev/libimg/png/libpng/pngget.asm b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngget.asm
index 18d39d769..cae62c9ee 100644
--- a/programs/develop/libraries/libs-dev/libimg/png/libpng/pngget.asm
+++ b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngget.asm
@@ -1,1282 +1,1282 @@
-
-; pngget.asm - retrieval of values from info struct
-
-; Last changed in libpng 1.6.24 [August 4, 2016]
-; Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
-; (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
-; (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
-
-; This code is released under the libpng license.
-; For conditions of distribution and use, see the disclaimer
-; and license in png.inc
-
-
-;uint_32 (png_structrp png_ptr, png_inforp info_ptr, uint_32 flag)
-align 4
-proc png_get_valid, png_ptr:dword, info_ptr:dword, flag:dword
- mov eax,[png_ptr]
- cmp eax,0
- je @f
- mov eax,[info_ptr]
- cmp eax,0
- je @f ;if (..!=0 || ..!=0)
- mov eax,[eax+png_info_def.valid]
- and eax,[flag]
- @@:
- ret
-endp
-
-;png_size_t (png_structrp png_ptr, png_inforp info_ptr)
-align 4
-proc png_get_rowbytes, png_ptr:dword, info_ptr:dword
- mov eax,[png_ptr]
- cmp eax,0
- je @f
- mov eax,[info_ptr]
- cmp eax,0
- je @f ;if (..!=0 || ..!=0)
- mov eax,[eax+png_info_def.rowbytes]
- @@:
- ret
-endp
-
-;bytepp (png_structrp png_ptr, png_inforp info_ptr)
-align 4
-proc png_get_rows, png_ptr:dword, info_ptr:dword
- mov eax,[png_ptr]
- cmp eax,0
- je @f
- mov eax,[info_ptr]
- cmp eax,0
- je @f ;if (..!=0 || ..!=0)
- mov eax,[eax+png_info_def.row_pointers]
- @@:
- ret
-endp
-
-; Easy access to info, added in libpng-0.99
-;uint_32 (png_structrp png_ptr, png_inforp info_ptr)
-align 4
-proc png_get_image_width, png_ptr:dword, info_ptr:dword
- mov eax,[png_ptr]
- cmp eax,0
- je @f
- mov eax,[info_ptr]
- cmp eax,0
- je @f ;if (..!=0 || ..!=0)
- mov eax,[eax+png_info_def.width]
- @@:
- ret
-endp
-
-;uint_32 (png_structrp png_ptr, png_inforp info_ptr)
-align 4
-proc png_get_image_height, png_ptr:dword, info_ptr:dword
- mov eax,[png_ptr]
- cmp eax,0
- je @f
- mov eax,[info_ptr]
- cmp eax,0
- je @f ;if (..!=0 || ..!=0)
- mov eax,[eax+png_info_def.height]
- @@:
- ret
-endp
-
-;byte (png_structrp png_ptr, png_inforp info_ptr)
-align 4
-proc png_get_bit_depth, png_ptr:dword, info_ptr:dword
- mov eax,[png_ptr]
- cmp eax,0
- je @f
- mov eax,[info_ptr]
- cmp eax,0
- je @f ;if (..!=0 || ..!=0)
- movzx eax,byte[eax+png_info_def.bit_depth]
- @@:
- ret
-endp
-
-;byte (png_structrp png_ptr, png_inforp info_ptr)
-align 4
-proc png_get_color_type, png_ptr:dword, info_ptr:dword
- mov eax,[png_ptr]
- cmp eax,0
- je @f
- mov eax,[info_ptr]
- cmp eax,0
- je @f ;if (..!=0 || ..!=0)
- movzx eax,byte[eax+png_info_def.color_type]
- @@:
- ret
-endp
-
-;byte (png_structrp png_ptr, png_inforp info_ptr)
-align 4
-proc png_get_filter_type, png_ptr:dword, info_ptr:dword
- mov eax,[png_ptr]
- cmp eax,0
- je @f
- mov eax,[info_ptr]
- cmp eax,0
- je @f ;if (..!=0 || ..!=0)
- movzx eax,byte[eax+png_info_def.filter_type]
- @@:
- ret
-endp
-
-;byte (png_structrp png_ptr, png_inforp info_ptr)
-align 4
-proc png_get_interlace_type, png_ptr:dword, info_ptr:dword
- mov eax,[png_ptr]
- cmp eax,0
- je @f
- mov eax,[info_ptr]
- cmp eax,0
- je @f ;if (..!=0 || ..!=0)
- movzx eax,byte[eax+png_info_def.interlace_type]
- @@:
- ret
-endp
-
-;byte (png_structrp png_ptr, png_inforp info_ptr)
-align 4
-proc png_get_compression_type, png_ptr:dword, info_ptr:dword
- mov eax,[png_ptr]
- cmp eax,0
- je @f
- mov eax,[info_ptr]
- cmp eax,0
- je @f ;if (..!=0 || ..!=0)
- mov eax,[eax+png_info_def.compression_type]
- @@:
- ret
-endp
-
-;uint_32 (png_structrp png_ptr, png_inforp info_ptr)
-align 4
-proc png_get_x_pixels_per_meter, png_ptr:dword, info_ptr:dword
-if PNG_pHYs_SUPPORTED eq 1
- mov eax,[png_ptr]
- cmp eax,0
- je @f
- mov esi,[info_ptr]
- cmp esi,0
- je @f
- mov eax,[esi+png_info_def.valid]
- and eax,PNG_INFO_pHYs
- cmp eax,0
- je @f ;if (..!=0 && ..!=0 && ..!=0)
- png_debug1 1, 'in %s retrieval function', 'png_get_x_pixels_per_meter'
-
- cmp dword[esi+png_info_def.phys_unit_type],PNG_RESOLUTION_METER
- jne @f ;if (..==..)
- mov eax,[esi+png_info_def.x_pixels_per_unit]
- jmp .end_f
- @@:
-end if
- xor eax,eax
-.end_f:
- ret
-endp
-
-;uint_32 (png_structrp png_ptr, png_inforp info_ptr)
-align 4
-proc png_get_y_pixels_per_meter, png_ptr:dword, info_ptr:dword
-if PNG_pHYs_SUPPORTED eq 1
- mov eax,[png_ptr]
- cmp eax,0
- je @f
- mov esi,[info_ptr]
- cmp esi,0
- je @f
- mov eax,[esi+png_info_def.valid]
- and eax,PNG_INFO_pHYs
- cmp eax,0
- je @f ;if (..!=0 && ..!=0 && ..!=0)
- png_debug1 1, 'in %s retrieval function', 'png_get_y_pixels_per_meter'
-
- cmp dword[esi+png_info_def.phys_unit_type],PNG_RESOLUTION_METER
- jne @f ;if (..==..)
- mov eax,[esi+png_info_def.y_pixels_per_unit]
- jmp .end_f
- @@:
-end if
- xor eax,eax
-.end_f:
- ret
-endp
-
-;uint_32 (png_structrp png_ptr, png_inforp info_ptr)
-align 4
-proc png_get_pixels_per_meter uses esi, png_ptr:dword, info_ptr:dword
-if PNG_pHYs_SUPPORTED eq 1
- mov eax,[png_ptr]
- cmp eax,0
- je @f
- mov esi,[info_ptr]
- cmp esi,0
- je @f
- mov eax,[esi+png_info_def.valid]
- and eax,PNG_INFO_pHYs
- cmp eax,0
- je @f ;if (..!=0 && ..!=0 && ..!=0)
- png_debug1 1, 'in %s retrieval function', 'png_get_pixels_per_meter'
-
- cmp dword[esi+png_info_def.phys_unit_type],PNG_RESOLUTION_METER
- jne @f
- mov eax,[esi+png_info_def.x_pixels_per_unit]
- cmp eax,[esi+png_info_def.y_pixels_per_unit]
- jne @f ;if (..==.. && ..==..)
- jmp .end_f
- @@:
-end if
- xor eax,eax
-.end_f:
- ret
-endp
-
-;float (png_structrp png_ptr, png_inforp info_ptr)
-align 4
-proc png_get_pixel_aspect_ratio, png_ptr:dword, info_ptr:dword
-if PNG_READ_pHYs_SUPPORTED eq 1
-; if (png_ptr != NULL && info_ptr != NULL &&
-; (info_ptr->valid & PNG_INFO_pHYs) != 0)
-; {
- png_debug1 1, 'in %s retrieval function', 'png_get_aspect_ratio'
-
-; if (info_ptr->x_pixels_per_unit != 0)
-; return ((float)((float)info_ptr->y_pixels_per_unit
-; /(float)info_ptr->x_pixels_per_unit));
-; }
-end if
-
-; return ((float)0.0);
- ret
-endp
-
-;png_fixed_point (png_structrp png_ptr, png_inforp info_ptr)
-align 4
-proc png_get_pixel_aspect_ratio_fixed, png_ptr:dword, info_ptr:dword
-if PNG_READ_pHYs_SUPPORTED eq 1
-; if (png_ptr != NULL && info_ptr != NULL &&
-; (info_ptr->valid & PNG_INFO_pHYs) != 0 &&
-; info_ptr->x_pixels_per_unit > 0 && info_ptr->y_pixels_per_unit > 0 &&
-; info_ptr->x_pixels_per_unit <= PNG_UINT_31_MAX &&
-; info_ptr->y_pixels_per_unit <= PNG_UINT_31_MAX)
-; {
-; png_fixed_point res;
-
- png_debug1 1, 'in %s retrieval function', 'png_get_aspect_ratio_fixed'
-
- ; The following casts work because a PNG 4 byte integer only has a valid
- ; range of 0..2^31-1; otherwise the cast might overflow.
-
-; if (png_muldiv(&res, (int_32)info_ptr->y_pixels_per_unit, PNG_FP_1,
-; (int_32)info_ptr->x_pixels_per_unit) != 0)
-; return res;
-; }
-end if
-
-; return 0;
- ret
-endp
-
-;int_32 (png_structrp png_ptr, png_inforp info_ptr)
-align 4
-proc png_get_x_offset_microns, png_ptr:dword, info_ptr:dword
-if PNG_oFFs_SUPPORTED eq 1
-; if (png_ptr != NULL && info_ptr != NULL &&
-; (info_ptr->valid & PNG_INFO_oFFs) != 0)
-; {
- png_debug1 1, 'in %s retrieval function', 'png_get_x_offset_microns'
-
-; if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER)
-; return (info_ptr->x_offset);
-; }
-end if
-
- xor eax,eax
- ret
-endp
-
-;int_32 (png_structrp png_ptr, png_inforp info_ptr)
-align 4
-proc png_get_y_offset_microns, png_ptr:dword, info_ptr:dword
-if PNG_oFFs_SUPPORTED eq 1
-; if (png_ptr != NULL && info_ptr != NULL &&
-; (info_ptr->valid & PNG_INFO_oFFs) != 0)
-; {
- png_debug1 1, 'in %s retrieval function', 'png_get_y_offset_microns'
-
-; if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER)
-; return (info_ptr->y_offset);
-; }
-end if
-
- xor eax,eax
- ret
-endp
-
-;int_32 (png_structrp png_ptr, png_inforp info_ptr)
-align 4
-proc png_get_x_offset_pixels, png_ptr:dword, info_ptr:dword
-if PNG_oFFs_SUPPORTED eq 1
-; if (png_ptr != NULL && info_ptr != NULL &&
-; (info_ptr->valid & PNG_INFO_oFFs) != 0)
-; {
- png_debug1 1, 'in %s retrieval function', 'png_get_x_offset_pixels'
-
-; if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL)
-; return (info_ptr->x_offset);
-; }
-end if
-
- xor eax,eax
- ret
-endp
-
-;int_32 (png_structrp png_ptr, png_inforp info_ptr)
-align 4
-proc png_get_y_offset_pixels, png_ptr:dword, info_ptr:dword
-if PNG_oFFs_SUPPORTED eq 1
-; if (png_ptr != NULL && info_ptr != NULL &&
-; (info_ptr->valid & PNG_INFO_oFFs) != 0)
-; {
- png_debug1 1, 'in %s retrieval function', 'png_get_y_offset_pixels'
-
-; if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL)
-; return (info_ptr->y_offset);
-; }
-end if
-
- xor eax,eax
- ret
-endp
-
-;uint_32 (uint_32 ppm)
-align 4
-proc ppi_from_ppm, ppm:dword
-;#if 0
- ; The conversion is *(2.54/100), in binary (32 digits):
- ; .00000110100000001001110101001001
-
-; uint_32 t1001, t1101;
-; ppm >>= 1; /* .1 */
-; t1001 = ppm + (ppm >> 3); /* .1001 */
-; t1101 = t1001 + (ppm >> 1); /* .1101 */
-; ppm >>= 20; /* .000000000000000000001 */
-; t1101 += t1101 >> 15; /* .1101000000000001101 */
-; t1001 >>= 11; /* .000000000001001 */
-; t1001 += t1001 >> 12; /* .000000000001001000000001001 */
-; ppm += t1001; /* .000000000001001000001001001 */
-; ppm += t1101; /* .110100000001001110101001001 */
-; return (ppm + 16) >> 5;/* .00000110100000001001110101001001 */
-;#else
- ; The argument is a PNG unsigned integer, so it is not permitted
- ; to be bigger than 2^31.
-
-; png_fixed_point result;
-; if (ppm <= PNG_UINT_31_MAX && png_muldiv(&result, (int_32)ppm, 127,
-; 5000) != 0)
-; return result;
-
- ; Overflow.
-; return 0;
-;end if
- ret
-endp
-
-;uint_32 (png_structrp png_ptr, png_inforp info_ptr)
-align 4
-proc png_get_pixels_per_inch, png_ptr:dword, info_ptr:dword
- stdcall png_get_pixels_per_meter, [png_ptr], [info_ptr]
- stdcall ppi_from_ppm, eax
- ret
-endp
-
-;uint_32 (png_structrp png_ptr, png_inforp info_ptr)
-align 4
-proc png_get_x_pixels_per_inch, png_ptr:dword, info_ptr:dword
- stdcall png_get_x_pixels_per_meter, [png_ptr], [info_ptr]
- stdcall ppi_from_ppm, eax
- ret
-endp
-
-;uint_32 (png_structrp png_ptr, png_inforp info_ptr)
-align 4
-proc png_get_y_pixels_per_inch, png_ptr:dword, info_ptr:dword
- stdcall png_get_y_pixels_per_meter, [png_ptr], [info_ptr]
- stdcall ppi_from_ppm, eax
- ret
-endp
-
-;png_fixed_point (png_structrp png_ptr, int_32 microns)
-align 4
-proc png_fixed_inches_from_microns, png_ptr:dword, microns:dword
- ; Convert from metres * 1,000,000 to inches * 100,000, meters to
- ; inches is simply *(100/2.54), so we want *(10/2.54) == 500/127.
- ; Notice that this can overflow - a warning is output and 0 is
- ; returned.
-
- stdcall png_muldiv_warn, [png_ptr], [microns], 500, 127
- ret
-endp
-
-;png_fixed_point (png_structrp png_ptr, png_inforp info_ptr)
-align 4
-proc png_get_x_offset_inches_fixed, png_ptr:dword, info_ptr:dword
- stdcall png_get_x_offset_microns, [png_ptr], [info_ptr]
- stdcall png_fixed_inches_from_microns, [png_ptr], eax
- ret
-endp
-
-;png_fixed_point (png_structrp png_ptr, png_inforp info_ptr)
-align 4
-proc png_get_y_offset_inches_fixed, png_ptr:dword, info_ptr:dword
- stdcall png_get_y_offset_microns, [png_ptr], [info_ptr]
- stdcall png_fixed_inches_from_microns, [png_ptr], eax
- ret
-endp
-
-;float (png_structrp png_ptr, png_inforp info_ptr)
-align 4
-proc png_get_x_offset_inches, png_ptr:dword, info_ptr:dword
- ; To avoid the overflow do the conversion directly in floating
- ; point.
-
-; return (float)(png_get_x_offset_microns(png_ptr, info_ptr) * .00003937);
- ret
-endp
-
-;float (png_structrp png_ptr, png_inforp info_ptr)
-align 4
-proc png_get_y_offset_inches, png_ptr:dword, info_ptr:dword
- ; To avoid the overflow do the conversion directly in floating
- ; point.
-
-; return (float)(png_get_y_offset_microns(png_ptr, info_ptr) * .00003937);
- ret
-endp
-
-;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
-; uint_32 *res_x, uint_32 *res_y, int *unit_type)
-align 4
-proc png_get_pHYs_dpi, png_ptr:dword, info_ptr:dword, res_x:dword, res_y:dword, unit_type:dword
-; uint_32 retval = 0;
-
-; if (png_ptr != NULL && info_ptr != NULL &&
-; (info_ptr->valid & PNG_INFO_pHYs) != 0)
-; {
- png_debug1 1, 'in %s retrieval function', 'pHYs'
-
-; if (res_x != NULL)
-; {
-; *res_x = info_ptr->x_pixels_per_unit;
-; retval |= PNG_INFO_pHYs;
-; }
-
-; if (res_y != NULL)
-; {
-; *res_y = info_ptr->y_pixels_per_unit;
-; retval |= PNG_INFO_pHYs;
-; }
-
-; if (unit_type != NULL)
-; {
-; *unit_type = (int)info_ptr->phys_unit_type;
-; retval |= PNG_INFO_pHYs;
-
-; if (*unit_type == 1)
-; {
-; if (res_x != NULL) *res_x = (uint_32)(*res_x * .0254 + .50);
-; if (res_y != NULL) *res_y = (uint_32)(*res_y * .0254 + .50);
-; }
-; }
-; }
-
-; return (retval);
- ret
-endp
-
-; png_get_channels really belongs in here, too, but it's been around longer
-
-;byte (png_structrp png_ptr, png_inforp info_ptr)
-align 4
-proc png_get_channels, png_ptr:dword, info_ptr:dword
- mov eax,[png_ptr]
- cmp eax,0
- je @f
- mov eax,[info_ptr]
- cmp eax,0
- je @f ;if (..!=0 || ..!=0)
- movzx eax,byte[eax+png_info_def.channels]
- @@:
- ret
-endp
-
-;bytep (png_structrp png_ptr, png_inforp info_ptr)
-align 4
-proc png_get_signature, png_ptr:dword, info_ptr:dword
- mov eax,[png_ptr]
- cmp eax,0
- je @f
- mov eax,[info_ptr]
- cmp eax,0
- je @f ;if (..!=0 || ..!=0)
- movzx eax,byte[eax+png_info_def.signature]
- @@:
- ret
-endp
-
-;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
-; png_color_16p *background)
-align 4
-proc png_get_bKGD, png_ptr:dword, info_ptr:dword, background:dword
-; if (png_ptr != NULL && info_ptr != NULL &&
-; (info_ptr->valid & PNG_INFO_bKGD) != 0 &&
-; background != NULL)
-; {
- png_debug1 1, 'in %s retrieval function', 'bKGD'
-
-; *background = &(info_ptr->background);
-; return (PNG_INFO_bKGD);
-; }
-
- xor eax,eax
- ret
-endp
-
-;if PNG_cHRM_SUPPORTED
-; The XYZ APIs were added in 1.5.5 to take advantage of the code added at the
-; same time to correct the rgb grayscale coefficient defaults obtained from the
-; cHRM chunk in 1.5.4
-
-;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
-; double *white_x, double *white_y, double *red_x, double *red_y,
-; double *green_x, double *green_y, double *blue_x, double *blue_y)
-align 4
-proc png_get_cHRM, png_ptr:dword, info_ptr:dword, white_x:dword, white_y:dword, red_x:dword, red_y:dword, green_x:dword, green_y:dword, blue_x:dword, blue_y:dword
- ; Quiet API change: this code used to only return the end points if a cHRM
- ; chunk was present, but the end points can also come from iCCP or sRGB
- ; chunks, so in 1.6.0 the png_get_ APIs return the end points regardless and
- ; the png_set_ APIs merely check that set end points are mutually
- ; consistent.
-
-; if (png_ptr != NULL && info_ptr != NULL &&
-; (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
-; {
- png_debug1 1, 'in %s retrieval function', 'cHRM'
-
-; if (white_x != NULL)
-; *white_x = png_float(png_ptr,
-; info_ptr->colorspace.end_points_xy.whitex, "cHRM white X");
-; if (white_y != NULL)
-; *white_y = png_float(png_ptr,
-; info_ptr->colorspace.end_points_xy.whitey, "cHRM white Y");
-; if (red_x != NULL)
-; *red_x = png_float(png_ptr, info_ptr->colorspace.end_points_xy.redx,
-; "cHRM red X");
-; if (red_y != NULL)
-; *red_y = png_float(png_ptr, info_ptr->colorspace.end_points_xy.redy,
-; "cHRM red Y");
-; if (green_x != NULL)
-; *green_x = png_float(png_ptr,
-; info_ptr->colorspace.end_points_xy.greenx, "cHRM green X");
-; if (green_y != NULL)
-; *green_y = png_float(png_ptr,
-; info_ptr->colorspace.end_points_xy.greeny, "cHRM green Y");
-; if (blue_x != NULL)
-; *blue_x = png_float(png_ptr, info_ptr->colorspace.end_points_xy.bluex,
-; "cHRM blue X");
-; if (blue_y != NULL)
-; *blue_y = png_float(png_ptr, info_ptr->colorspace.end_points_xy.bluey,
-; "cHRM blue Y");
-; return (PNG_INFO_cHRM);
-; }
-
- xor eax,eax
- ret
-endp
-
-;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
-; double *red_X, double *red_Y, double *red_Z, double *green_X,
-; double *green_Y, double *green_Z, double *blue_X, double *blue_Y,
-; double *blue_Z)
-align 4
-proc png_get_cHRM_XYZ, png_ptr:dword, info_ptr:dword, red_X:dword, red_Y:dword, red_Z:dword, green_X:dword, green_Y:dword, green_Z:dword, blue_X:dword, blue_Y:dword, blue_Z:dword
-; if (png_ptr != NULL && info_ptr != NULL &&
-; (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
-; {
- png_debug1 1, 'in %s retrieval function', 'cHRM_XYZ(float)'
-
-; if (red_X != NULL)
-; *red_X = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_X,
-; "cHRM red X");
-; if (red_Y != NULL)
-; *red_Y = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_Y,
-; "cHRM red Y");
-; if (red_Z != NULL)
-; *red_Z = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_Z,
-; "cHRM red Z");
-; if (green_X != NULL)
-; *green_X = png_float(png_ptr,
-; info_ptr->colorspace.end_points_XYZ.green_X, "cHRM green X");
-; if (green_Y != NULL)
-; *green_Y = png_float(png_ptr,
-; info_ptr->colorspace.end_points_XYZ.green_Y, "cHRM green Y");
-; if (green_Z != NULL)
-; *green_Z = png_float(png_ptr,
-; info_ptr->colorspace.end_points_XYZ.green_Z, "cHRM green Z");
-; if (blue_X != NULL)
-; *blue_X = png_float(png_ptr,
-; info_ptr->colorspace.end_points_XYZ.blue_X, "cHRM blue X");
-; if (blue_Y != NULL)
-; *blue_Y = png_float(png_ptr,
-; info_ptr->colorspace.end_points_XYZ.blue_Y, "cHRM blue Y");
-; if (blue_Z != NULL)
-; *blue_Z = png_float(png_ptr,
-; info_ptr->colorspace.end_points_XYZ.blue_Z, "cHRM blue Z");
-; return (PNG_INFO_cHRM);
-; }
-
- xor eax,eax
- ret
-endp
-
-;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
-; png_fixed_point *int_red_X, png_fixed_point *int_red_Y,
-; png_fixed_point *int_red_Z, png_fixed_point *int_green_X,
-; png_fixed_point *int_green_Y, png_fixed_point *int_green_Z,
-; png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y,
-; png_fixed_point *int_blue_Z)
-align 4
-proc png_get_cHRM_XYZ_fixed, png_ptr:dword, info_ptr:dword, int_red_X:dword, int_red_Y:dword, int_red_Z:dword, int_green_X:dword, int_green_Y:dword, int_green_Z:dword, int_blue_X:dword, int_blue_Y:dword, int_blue_Z:dword
-; if (png_ptr != NULL && info_ptr != NULL &&
-; (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
-; {
- png_debug1 1, 'in %s retrieval function', 'cHRM_XYZ'
-
-; if (int_red_X != NULL)
-; *int_red_X = info_ptr->colorspace.end_points_XYZ.red_X;
-; if (int_red_Y != NULL)
-; *int_red_Y = info_ptr->colorspace.end_points_XYZ.red_Y;
-; if (int_red_Z != NULL)
-; *int_red_Z = info_ptr->colorspace.end_points_XYZ.red_Z;
-; if (int_green_X != NULL)
-; *int_green_X = info_ptr->colorspace.end_points_XYZ.green_X;
-; if (int_green_Y != NULL)
-; *int_green_Y = info_ptr->colorspace.end_points_XYZ.green_Y;
-; if (int_green_Z != NULL)
-; *int_green_Z = info_ptr->colorspace.end_points_XYZ.green_Z;
-; if (int_blue_X != NULL)
-; *int_blue_X = info_ptr->colorspace.end_points_XYZ.blue_X;
-; if (int_blue_Y != NULL)
-; *int_blue_Y = info_ptr->colorspace.end_points_XYZ.blue_Y;
-; if (int_blue_Z != NULL)
-; *int_blue_Z = info_ptr->colorspace.end_points_XYZ.blue_Z;
-; return (PNG_INFO_cHRM);
-; }
-
- xor eax,eax
-.end_f:
- ret
-endp
-
-;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
-; png_fixed_point *white_x, png_fixed_point *white_y, png_fixed_point *red_x,
-; png_fixed_point *red_y, png_fixed_point *green_x, png_fixed_point *green_y,
-; png_fixed_point *blue_x, png_fixed_point *blue_y)
-align 4
-proc png_get_cHRM_fixed, png_ptr:dword, info_ptr:dword, white_x:dword, white_y:dword, red_x:dword, red_y:dword, green_x:dword, green_y:dword, blue_x:dword, blue_y:dword
- png_debug1 1, 'in %s retrieval function', 'cHRM'
-
-; if (png_ptr != NULL && info_ptr != NULL &&
-; (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
-; {
-; if (white_x != NULL)
-; *white_x = info_ptr->colorspace.end_points_xy.whitex;
-; if (white_y != NULL)
-; *white_y = info_ptr->colorspace.end_points_xy.whitey;
-; if (red_x != NULL)
-; *red_x = info_ptr->colorspace.end_points_xy.redx;
-; if (red_y != NULL)
-; *red_y = info_ptr->colorspace.end_points_xy.redy;
-; if (green_x != NULL)
-; *green_x = info_ptr->colorspace.end_points_xy.greenx;
-; if (green_y != NULL)
-; *green_y = info_ptr->colorspace.end_points_xy.greeny;
-; if (blue_x != NULL)
-; *blue_x = info_ptr->colorspace.end_points_xy.bluex;
-; if (blue_y != NULL)
-; *blue_y = info_ptr->colorspace.end_points_xy.bluey;
-; return (PNG_INFO_cHRM);
-; }
-
- xor eax,eax
- ret
-endp
-;end if
-
-;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
-; png_fixed_point *file_gamma)
-align 4
-proc png_get_gAMA_fixed, png_ptr:dword, info_ptr:dword, file_gamma:dword
- png_debug1 1, 'in %s retrieval function', 'gAMA'
-
-; if (png_ptr != NULL && info_ptr != NULL &&
-; (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 &&
-; file_gamma != NULL)
-; {
-; *file_gamma = info_ptr->colorspace.gamma;
-; return (PNG_INFO_gAMA);
-; }
-
- xor eax,eax
- ret
-endp
-
-;uint_32 (png_structrp png_ptr, png_inforp info_ptr, double *file_gamma)
-align 4
-proc png_get_gAMA, png_ptr:dword, info_ptr:dword, file_gamma:dword
- png_debug1 1, 'in %s retrieval function', 'gAMA(float)'
-
-; if (png_ptr != NULL && info_ptr != NULL &&
-; (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 &&
-; file_gamma != NULL)
-; {
-; *file_gamma = png_float(png_ptr, info_ptr->colorspace.gamma,
-; "png_get_gAMA");
-; return (PNG_INFO_gAMA);
-; }
-
- xor eax,eax
- ret
-endp
-
-;uint_32 (png_structrp png_ptr, png_inforp info_ptr, int *file_srgb_intent)
-align 4
-proc png_get_sRGB, png_ptr:dword, info_ptr:dword, file_srgb_intent:dword
- png_debug1 1, 'in %s retrieval function', 'sRGB'
-
-; if (png_ptr != NULL && info_ptr != NULL &&
-; (info_ptr->valid & PNG_INFO_sRGB) != 0 && file_srgb_intent != NULL)
-; {
-; *file_srgb_intent = info_ptr->colorspace.rendering_intent;
-; return (PNG_INFO_sRGB);
-; }
-
- xor eax,eax
- ret
-endp
-
-;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
-; png_charpp name, int *compression_type, bytepp profile, uint_32 *proflen)
-align 4
-proc png_get_iCCP, png_ptr:dword, info_ptr:dword, name:dword, compression_type:dword, profile:dword, proflen:dword
- png_debug1 1, 'in %s retrieval function', 'iCCP'
-
-; if (png_ptr != NULL && info_ptr != NULL &&
-; (info_ptr->valid & PNG_INFO_iCCP) != 0 &&
-; name != NULL && compression_type != NULL && profile != NULL &&
-; proflen != NULL)
-; {
-; *name = info_ptr->iccp_name;
-; *profile = info_ptr->iccp_profile;
-; *proflen = png_get_uint_32(info_ptr->iccp_profile);
- ; This is somewhat irrelevant since the profile data returned has
- ; actually been uncompressed.
-
-; *compression_type = PNG_COMPRESSION_TYPE_BASE;
-; return (PNG_INFO_iCCP);
-; }
-
- xor eax,eax
- ret
-endp
-
-;int (png_structrp png_ptr, png_inforp info_ptr,
-; png_sPLT_tpp spalettes)
-align 4
-proc png_get_sPLT, png_ptr:dword, info_ptr:dword, spalettes:dword
-; if (png_ptr != NULL && info_ptr != NULL && spalettes != NULL)
-; {
-; *spalettes = info_ptr->splt_palettes;
-; return info_ptr->splt_palettes_num;
-; }
-
- xor eax,eax
- ret
-endp
-
-;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
-; uint_16p hist)
-align 4
-proc png_get_hIST, png_ptr:dword, info_ptr:dword, hist:dword
- png_debug1 1, 'in %s retrieval function', 'hIST'
-
-; if (png_ptr != NULL && info_ptr != NULL &&
-; (info_ptr->valid & PNG_INFO_hIST) != 0 && hist != NULL)
-; {
-; *hist = info_ptr->hist;
-; return (PNG_INFO_hIST);
-; }
-
- xor eax,eax
- ret
-endp
-
-;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
-; uint_32 *width, uint_32 *height, int *bit_depth,
-; int *color_type, int *interlace_type, int *compression_type,
-; int *filter_type)
-align 4
-proc png_get_IHDR, png_ptr:dword, info_ptr:dword,\
- width:dword, height:dword, bit_depth:dword, color_type:dword,\
- interlace_type:dword, compression_type:dword, filter_type:dword
- png_debug1 1, 'in %s retrieval function', 'IHDR'
-
-; if (png_ptr == NULL || info_ptr == NULL)
-; return (0);
-
-; if (width != NULL)
-; *width = info_ptr->width;
-
-; if (height != NULL)
-; *height = info_ptr->height;
-
-; if (bit_depth != NULL)
-; *bit_depth = info_ptr->bit_depth;
-
-; if (color_type != NULL)
-; *color_type = info_ptr->color_type;
-
-; if (compression_type != NULL)
-; *compression_type = info_ptr->compression_type;
-
-; if (filter_type != NULL)
-; *filter_type = info_ptr->filter_type;
-
-; if (interlace_type != NULL)
-; *interlace_type = info_ptr->interlace_type;
-
- ; This is redundant if we can be sure that the info_ptr values were all
- ; assigned in png_set_IHDR(). We do the check anyhow in case an
- ; application has ignored our advice not to mess with the members
- ; of info_ptr directly.
-
-; png_check_IHDR(png_ptr, info_ptr->width, info_ptr->height,
-; info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type,
-; info_ptr->compression_type, info_ptr->filter_type);
-
- xor eax,eax
- inc eax
- ret
-endp
-
-;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
-; int_32 *offset_x, int_32 *offset_y, int *unit_type)
-align 4
-proc png_get_oFFs, png_ptr:dword, info_ptr:dword, offset_x:dword, offset_y:dword, unit_type:dword
- png_debug1 1, 'in %s retrieval function', 'oFFs'
-
-; if (png_ptr != NULL && info_ptr != NULL &&
-; (info_ptr->valid & PNG_INFO_oFFs) != 0 &&
-; offset_x != NULL && offset_y != NULL && unit_type != NULL)
-; {
-; *offset_x = info_ptr->x_offset;
-; *offset_y = info_ptr->y_offset;
-; *unit_type = (int)info_ptr->offset_unit_type;
-; return (PNG_INFO_oFFs);
-; }
-
- xor eax,eax
- ret
-endp
-
-;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
-; charp *purpose, int_32 *X0, int_32 *X1, int *type, int *nparams,
-; charp *units, charpp *params)
-align 4
-proc png_get_pCAL, png_ptr:dword, info_ptr:dword, purpose:dword, X0:dword, X1:dword, type:dword, nparams:dword, units:dword, params:dword
- png_debug1 1, 'in %s retrieval function', 'pCAL'
-
-; if (png_ptr != NULL && info_ptr != NULL &&
-; (info_ptr->valid & PNG_INFO_pCAL) != 0 &&
-; purpose != NULL && X0 != NULL && X1 != NULL && type != NULL &&
-; nparams != NULL && units != NULL && params != NULL)
-; {
-; *purpose = info_ptr->pcal_purpose;
-; *X0 = info_ptr->pcal_X0;
-; *X1 = info_ptr->pcal_X1;
-; *type = (int)info_ptr->pcal_type;
-; *nparams = (int)info_ptr->pcal_nparams;
-; *units = info_ptr->pcal_units;
-; *params = info_ptr->pcal_params;
-; return (PNG_INFO_pCAL);
-; }
-
- xor eax,eax
- ret
-endp
-
-;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
-; int *unit, png_fixed_point *width, png_fixed_point *height)
-align 4
-proc png_get_sCAL_fixed, png_ptr:dword, info_ptr:dword, unit:dword, width:dword, height:dword
-; if (png_ptr != NULL && info_ptr != NULL &&
-; (info_ptr->valid & PNG_INFO_sCAL) != 0)
-; {
-; *unit = info_ptr->scal_unit;
- ;TODO: make this work without FP support; the API is currently eliminated
- ; if neither floating point APIs nor internal floating point arithmetic
- ; are enabled.
-
-; *width = png_fixed(png_ptr, atof(info_ptr->scal_s_width), "sCAL width");
-; *height = png_fixed(png_ptr, atof(info_ptr->scal_s_height),
-; "sCAL height");
-; return (PNG_INFO_sCAL);
-; }
-
-; return(0);
- ret
-endp
-
-;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
-; int *unit, double *width, double *height)
-align 4
-proc png_get_sCAL, png_ptr:dword, info_ptr:dword, unit:dword, width:dword, height:dword
-; if (png_ptr != NULL && info_ptr != NULL &&
-; (info_ptr->valid & PNG_INFO_sCAL) != 0)
-; {
-; *unit = info_ptr->scal_unit;
-; *width = atof(info_ptr->scal_s_width);
-; *height = atof(info_ptr->scal_s_height);
-; return (PNG_INFO_sCAL);
-; }
-
-; return(0);
- ret
-endp
-
-;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
-; int *unit, charpp width, charpp height)
-align 4
-proc png_get_sCAL_s, png_ptr:dword, info_ptr:dword, unit:dword, width:dword, height:dword
-; if (png_ptr != NULL && info_ptr != NULL &&
-; (info_ptr->valid & PNG_INFO_sCAL) != 0)
-; {
-; *unit = info_ptr->scal_unit;
-; *width = info_ptr->scal_s_width;
-; *height = info_ptr->scal_s_height;
-; return (PNG_INFO_sCAL);
-; }
-
- xor eax,eax
-.end_f:
- ret
-endp
-
-;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
-; uint_32 *res_x, uint_32 *res_y, int *unit_type)
-align 4
-proc png_get_pHYs, png_ptr:dword, info_ptr:dword, res_x:dword, res_y:dword, unit_type:dword
-; uint_32 retval = 0;
-
- png_debug1 1, 'in %s retrieval function', 'pHYs'
-
-; if (png_ptr != NULL && info_ptr != NULL &&
-; (info_ptr->valid & PNG_INFO_pHYs) != 0)
-; {
-; if (res_x != NULL)
-; {
-; *res_x = info_ptr->x_pixels_per_unit;
-; retval |= PNG_INFO_pHYs;
-; }
-
-; if (res_y != NULL)
-; {
-; *res_y = info_ptr->y_pixels_per_unit;
-; retval |= PNG_INFO_pHYs;
-; }
-
-; if (unit_type != NULL)
-; {
-; *unit_type = (int)info_ptr->phys_unit_type;
-; retval |= PNG_INFO_pHYs;
-; }
-; }
-
-; return (retval);
- ret
-endp
-
-;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
-; png_colorp *palette, int *num_palette)
-align 4
-proc png_get_PLTE, png_ptr:dword, info_ptr:dword, palette:dword, num_palette:dword
- png_debug1 1, 'in %s retrieval function', 'PLTE'
-
-; if (png_ptr != NULL && info_ptr != NULL &&
-; (info_ptr->valid & PNG_INFO_PLTE) != 0 && palette != NULL)
-; {
-; *palette = info_ptr->palette;
-; *num_palette = info_ptr->num_palette;
-; png_debug1(3, "num_palette = %d", *num_palette);
-; return (PNG_INFO_PLTE);
-; }
-
- xor eax,eax
- ret
-endp
-
-;uint_32 (png_structrp png_ptr, png_inforp info_ptr, png_color_8p *sig_bit)
-align 4
-proc png_get_sBIT, png_ptr:dword, info_ptr:dword, sig_bit:dword
- png_debug1 1, 'in %s retrieval function', 'sBIT'
-
-; if (png_ptr != NULL && info_ptr != NULL &&
-; (info_ptr->valid & PNG_INFO_sBIT) != 0 && sig_bit != NULL)
-; {
-; *sig_bit = &(info_ptr->sig_bit);
-; return (PNG_INFO_sBIT);
-; }
-
- xor eax,eax
- ret
-endp
-
-;int (png_structrp png_ptr, png_inforp info_ptr, png_textp *text_ptr, int *num_text)
-align 4
-proc png_get_text, png_ptr:dword, info_ptr:dword, text_ptr:dword, num_text:dword
-; if (png_ptr != NULL && info_ptr != NULL && info_ptr->num_text > 0)
-; {
-; png_debug1(1, "in 0x%lx retrieval function",
-; (unsigned long)png_ptr->chunk_name);
-
-; if (text_ptr != NULL)
-; *text_ptr = info_ptr->text;
-
-; if (num_text != NULL)
-; *num_text = info_ptr->num_text;
-
-; return info_ptr->num_text;
-; }
-
-; if (num_text != NULL)
-; *num_text = 0;
-
-; return(0);
- ret
-endp
-
-;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
-; png_timep *mod_time)
-align 4
-proc png_get_tIME, png_ptr:dword, info_ptr:dword, mod_time:dword
- png_debug1 1, 'in %s retrieval function', 'tIME'
-
-; if (png_ptr != NULL && info_ptr != NULL &&
-; (info_ptr->valid & PNG_INFO_tIME) != 0 && mod_time != NULL)
-; {
-; *mod_time = &(info_ptr->mod_time);
-; return (PNG_INFO_tIME);
-; }
-
- xor eax,eax
- ret
-endp
-
-;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
-; bytep *trans_alpha, int *num_trans, png_color_16p *trans_color)
-align 4
-proc png_get_tRNS, png_ptr:dword, info_ptr:dword, trans_alpha:dword, num_trans:dword, trans_color:dword
-; uint_32 retval = 0;
-; if (png_ptr != NULL && info_ptr != NULL &&
-; (info_ptr->valid & PNG_INFO_tRNS) != 0)
-; {
- png_debug1 1, 'in %s retrieval function', 'tRNS'
-
-; if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
-; {
-; if (trans_alpha != NULL)
-; {
-; *trans_alpha = info_ptr->trans_alpha;
-; retval |= PNG_INFO_tRNS;
-; }
-
-; if (trans_color != NULL)
-; *trans_color = &(info_ptr->trans_color);
-; }
-
-; else /* if (info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) */
-; {
-; if (trans_color != NULL)
-; {
-; *trans_color = &(info_ptr->trans_color);
-; retval |= PNG_INFO_tRNS;
-; }
-
-; if (trans_alpha != NULL)
-; *trans_alpha = NULL;
-; }
-
-; if (num_trans != NULL)
-; {
-; *num_trans = info_ptr->num_trans;
-; retval |= PNG_INFO_tRNS;
-; }
-; }
-
-; return (retval);
- ret
-endp
-
-;int (png_structrp png_ptr, png_inforp info_ptr,
-; png_unknown_chunkpp unknowns)
-align 4
-proc png_get_unknown_chunks, png_ptr:dword, info_ptr:dword, unknowns:dword
-; if (png_ptr != NULL && info_ptr != NULL && unknowns != NULL)
-; {
-; *unknowns = info_ptr->unknown_chunks;
-; return info_ptr->unknown_chunks_num;
-; }
-
- xor eax,eax
- ret
-endp
-
-;byte (png_structrp png_ptr)
-align 4
-proc png_get_rgb_to_gray_status, png_ptr:dword
- mov eax,[png_ptr]
- cmp eax,0
- je @f
- mov eax,[eax+png_struct.rgb_to_gray_status]
- @@:
- ret
-endp
-
-;voidp (png_structrp png_ptr)
-align 4
-proc png_get_user_chunk_ptr, png_ptr:dword
- mov eax,[png_ptr]
- cmp eax,0
- je @f
- mov eax,[eax+png_struct.user_chunk_ptr]
- @@:
- ret
-endp
-
-;png_size_t (png_structrp png_ptr)
-align 4
-proc png_get_compression_buffer_size uses ebx, png_ptr:dword
- mov eax,[png_ptr]
- cmp eax,0
- je .end_f ;if (..==0) return 0
-
-if PNG_WRITE_SUPPORTED eq 1
- mov ebx,[eax+png_struct.mode]
- and ebx,PNG_IS_READ_STRUCT
- cmp ebx,0
-; if (..!=0)
-end if
-; {
-if PNG_SEQUENTIAL_READ_SUPPORTED eq 1
- mov eax,[eax+png_struct.IDAT_read_size]
-else
- mov eax,PNG_IDAT_READ_SIZE
-end if
-; }
-
-if PNG_WRITE_SUPPORTED eq 1
- jmp .end_f
-; else
- mov eax,[eax+png_struct.zbuffer_size]
-end if
-.end_f:
- ret
-endp
-
-; These functions were added to libpng 1.2.6 and were enabled
-; by default in libpng-1.4.0
-;uint_32 (png_structrp png_ptr)
-align 4
-proc png_get_user_width_max, png_ptr:dword
- mov eax,[png_ptr]
- cmp eax,0
- je @f
- mov eax,[eax+png_struct.user_width_max]
- @@:
- ret
-endp
-
-;uint_32 (png_structrp png_ptr)
-align 4
-proc png_get_user_height_max, png_ptr:dword
- mov eax,[png_ptr]
- cmp eax,0
- je @f
- mov eax,[eax+png_struct.user_height_max]
- @@:
- ret
-endp
-
-; This function was added to libpng 1.4.0
-;uint_32 (png_structrp png_ptr)
-align 4
-proc png_get_chunk_cache_max, png_ptr:dword
- mov eax,[png_ptr]
- cmp eax,0
- je @f
- mov eax,[eax+png_struct.user_chunk_cache_max]
- @@:
- ret
-endp
-
-; This function was added to libpng 1.4.1
-;png_alloc_size_t (png_structrp png_ptr)
-align 4
-proc png_get_chunk_malloc_max, png_ptr:dword
- mov eax,[png_ptr]
- cmp eax,0
- je @f
- mov eax,[eax+png_struct.user_chunk_malloc_max]
- @@:
- ret
-endp
-
-; These functions were added to libpng 1.4.0
-;uint_32 (png_structrp png_ptr)
-align 4
-proc png_get_io_state, png_ptr:dword
- mov eax,[png_ptr]
- mov eax,[eax+png_struct.io_state]
- ret
-endp
-
-;uint_32 (png_structrp png_ptr)
-align 4
-proc png_get_io_chunk_type, png_ptr:dword
- mov eax,[png_ptr]
- mov eax,[eax+png_struct.chunk_name]
- ret
-endp
-
-;int (png_const_structp png_ptr, png_const_infop info_ptr)
-align 4
-proc png_get_palette_max, png_ptr:dword, info_ptr:dword
- mov eax,[png_ptr]
- cmp eax,0
- je @f
- cmp dword[info_ptr],0
- je @f ;if (..!=0 && ..!=0)
- mov eax,[eax+png_struct.num_palette_max]
- jmp .end_f
- @@:
- xor eax,eax
- dec eax
-.end_f:
- ret
-endp
-
+
+; pngget.asm - retrieval of values from info struct
+
+; Last changed in libpng 1.6.24 [August 4, 2016]
+; Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
+; (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+; (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+
+; This code is released under the libpng license.
+; For conditions of distribution and use, see the disclaimer
+; and license in png.inc
+
+
+;uint_32 (png_structrp png_ptr, png_inforp info_ptr, uint_32 flag)
+align 4
+proc png_get_valid, png_ptr:dword, info_ptr:dword, flag:dword
+ mov eax,[png_ptr]
+ cmp eax,0
+ je @f
+ mov eax,[info_ptr]
+ cmp eax,0
+ je @f ;if (..!=0 || ..!=0)
+ mov eax,[eax+png_info_def.valid]
+ and eax,[flag]
+ @@:
+ ret
+endp
+
+;png_size_t (png_structrp png_ptr, png_inforp info_ptr)
+align 4
+proc png_get_rowbytes, png_ptr:dword, info_ptr:dword
+ mov eax,[png_ptr]
+ cmp eax,0
+ je @f
+ mov eax,[info_ptr]
+ cmp eax,0
+ je @f ;if (..!=0 || ..!=0)
+ mov eax,[eax+png_info_def.rowbytes]
+ @@:
+ ret
+endp
+
+;bytepp (png_structrp png_ptr, png_inforp info_ptr)
+align 4
+proc png_get_rows, png_ptr:dword, info_ptr:dword
+ mov eax,[png_ptr]
+ cmp eax,0
+ je @f
+ mov eax,[info_ptr]
+ cmp eax,0
+ je @f ;if (..!=0 || ..!=0)
+ mov eax,[eax+png_info_def.row_pointers]
+ @@:
+ ret
+endp
+
+; Easy access to info, added in libpng-0.99
+;uint_32 (png_structrp png_ptr, png_inforp info_ptr)
+align 4
+proc png_get_image_width, png_ptr:dword, info_ptr:dword
+ mov eax,[png_ptr]
+ cmp eax,0
+ je @f
+ mov eax,[info_ptr]
+ cmp eax,0
+ je @f ;if (..!=0 || ..!=0)
+ mov eax,[eax+png_info_def.width]
+ @@:
+ ret
+endp
+
+;uint_32 (png_structrp png_ptr, png_inforp info_ptr)
+align 4
+proc png_get_image_height, png_ptr:dword, info_ptr:dword
+ mov eax,[png_ptr]
+ cmp eax,0
+ je @f
+ mov eax,[info_ptr]
+ cmp eax,0
+ je @f ;if (..!=0 || ..!=0)
+ mov eax,[eax+png_info_def.height]
+ @@:
+ ret
+endp
+
+;byte (png_structrp png_ptr, png_inforp info_ptr)
+align 4
+proc png_get_bit_depth, png_ptr:dword, info_ptr:dword
+ mov eax,[png_ptr]
+ cmp eax,0
+ je @f
+ mov eax,[info_ptr]
+ cmp eax,0
+ je @f ;if (..!=0 || ..!=0)
+ movzx eax,byte[eax+png_info_def.bit_depth]
+ @@:
+ ret
+endp
+
+;byte (png_structrp png_ptr, png_inforp info_ptr)
+align 4
+proc png_get_color_type, png_ptr:dword, info_ptr:dword
+ mov eax,[png_ptr]
+ cmp eax,0
+ je @f
+ mov eax,[info_ptr]
+ cmp eax,0
+ je @f ;if (..!=0 || ..!=0)
+ movzx eax,byte[eax+png_info_def.color_type]
+ @@:
+ ret
+endp
+
+;byte (png_structrp png_ptr, png_inforp info_ptr)
+align 4
+proc png_get_filter_type, png_ptr:dword, info_ptr:dword
+ mov eax,[png_ptr]
+ cmp eax,0
+ je @f
+ mov eax,[info_ptr]
+ cmp eax,0
+ je @f ;if (..!=0 || ..!=0)
+ movzx eax,byte[eax+png_info_def.filter_type]
+ @@:
+ ret
+endp
+
+;byte (png_structrp png_ptr, png_inforp info_ptr)
+align 4
+proc png_get_interlace_type, png_ptr:dword, info_ptr:dword
+ mov eax,[png_ptr]
+ cmp eax,0
+ je @f
+ mov eax,[info_ptr]
+ cmp eax,0
+ je @f ;if (..!=0 || ..!=0)
+ movzx eax,byte[eax+png_info_def.interlace_type]
+ @@:
+ ret
+endp
+
+;byte (png_structrp png_ptr, png_inforp info_ptr)
+align 4
+proc png_get_compression_type, png_ptr:dword, info_ptr:dword
+ mov eax,[png_ptr]
+ cmp eax,0
+ je @f
+ mov eax,[info_ptr]
+ cmp eax,0
+ je @f ;if (..!=0 || ..!=0)
+ mov eax,[eax+png_info_def.compression_type]
+ @@:
+ ret
+endp
+
+;uint_32 (png_structrp png_ptr, png_inforp info_ptr)
+align 4
+proc png_get_x_pixels_per_meter, png_ptr:dword, info_ptr:dword
+if PNG_pHYs_SUPPORTED eq 1
+ mov eax,[png_ptr]
+ cmp eax,0
+ je @f
+ mov esi,[info_ptr]
+ cmp esi,0
+ je @f
+ mov eax,[esi+png_info_def.valid]
+ and eax,PNG_INFO_pHYs
+ cmp eax,0
+ je @f ;if (..!=0 && ..!=0 && ..!=0)
+ png_debug1 1, 'in %s retrieval function', 'png_get_x_pixels_per_meter'
+
+ cmp dword[esi+png_info_def.phys_unit_type],PNG_RESOLUTION_METER
+ jne @f ;if (..==..)
+ mov eax,[esi+png_info_def.x_pixels_per_unit]
+ jmp .end_f
+ @@:
+end if
+ xor eax,eax
+.end_f:
+ ret
+endp
+
+;uint_32 (png_structrp png_ptr, png_inforp info_ptr)
+align 4
+proc png_get_y_pixels_per_meter, png_ptr:dword, info_ptr:dword
+if PNG_pHYs_SUPPORTED eq 1
+ mov eax,[png_ptr]
+ cmp eax,0
+ je @f
+ mov esi,[info_ptr]
+ cmp esi,0
+ je @f
+ mov eax,[esi+png_info_def.valid]
+ and eax,PNG_INFO_pHYs
+ cmp eax,0
+ je @f ;if (..!=0 && ..!=0 && ..!=0)
+ png_debug1 1, 'in %s retrieval function', 'png_get_y_pixels_per_meter'
+
+ cmp dword[esi+png_info_def.phys_unit_type],PNG_RESOLUTION_METER
+ jne @f ;if (..==..)
+ mov eax,[esi+png_info_def.y_pixels_per_unit]
+ jmp .end_f
+ @@:
+end if
+ xor eax,eax
+.end_f:
+ ret
+endp
+
+;uint_32 (png_structrp png_ptr, png_inforp info_ptr)
+align 4
+proc png_get_pixels_per_meter uses esi, png_ptr:dword, info_ptr:dword
+if PNG_pHYs_SUPPORTED eq 1
+ mov eax,[png_ptr]
+ cmp eax,0
+ je @f
+ mov esi,[info_ptr]
+ cmp esi,0
+ je @f
+ mov eax,[esi+png_info_def.valid]
+ and eax,PNG_INFO_pHYs
+ cmp eax,0
+ je @f ;if (..!=0 && ..!=0 && ..!=0)
+ png_debug1 1, 'in %s retrieval function', 'png_get_pixels_per_meter'
+
+ cmp dword[esi+png_info_def.phys_unit_type],PNG_RESOLUTION_METER
+ jne @f
+ mov eax,[esi+png_info_def.x_pixels_per_unit]
+ cmp eax,[esi+png_info_def.y_pixels_per_unit]
+ jne @f ;if (..==.. && ..==..)
+ jmp .end_f
+ @@:
+end if
+ xor eax,eax
+.end_f:
+ ret
+endp
+
+;float (png_structrp png_ptr, png_inforp info_ptr)
+align 4
+proc png_get_pixel_aspect_ratio, png_ptr:dword, info_ptr:dword
+if PNG_READ_pHYs_SUPPORTED eq 1
+; if (png_ptr != NULL && info_ptr != NULL &&
+; (info_ptr->valid & PNG_INFO_pHYs) != 0)
+; {
+ png_debug1 1, 'in %s retrieval function', 'png_get_aspect_ratio'
+
+; if (info_ptr->x_pixels_per_unit != 0)
+; return ((float)((float)info_ptr->y_pixels_per_unit
+; /(float)info_ptr->x_pixels_per_unit));
+; }
+end if
+
+; return ((float)0.0);
+ ret
+endp
+
+;png_fixed_point (png_structrp png_ptr, png_inforp info_ptr)
+align 4
+proc png_get_pixel_aspect_ratio_fixed, png_ptr:dword, info_ptr:dword
+if PNG_READ_pHYs_SUPPORTED eq 1
+; if (png_ptr != NULL && info_ptr != NULL &&
+; (info_ptr->valid & PNG_INFO_pHYs) != 0 &&
+; info_ptr->x_pixels_per_unit > 0 && info_ptr->y_pixels_per_unit > 0 &&
+; info_ptr->x_pixels_per_unit <= PNG_UINT_31_MAX &&
+; info_ptr->y_pixels_per_unit <= PNG_UINT_31_MAX)
+; {
+; png_fixed_point res;
+
+ png_debug1 1, 'in %s retrieval function', 'png_get_aspect_ratio_fixed'
+
+ ; The following casts work because a PNG 4 byte integer only has a valid
+ ; range of 0..2^31-1; otherwise the cast might overflow.
+
+; if (png_muldiv(&res, (int_32)info_ptr->y_pixels_per_unit, PNG_FP_1,
+; (int_32)info_ptr->x_pixels_per_unit) != 0)
+; return res;
+; }
+end if
+
+; return 0;
+ ret
+endp
+
+;int_32 (png_structrp png_ptr, png_inforp info_ptr)
+align 4
+proc png_get_x_offset_microns, png_ptr:dword, info_ptr:dword
+if PNG_oFFs_SUPPORTED eq 1
+; if (png_ptr != NULL && info_ptr != NULL &&
+; (info_ptr->valid & PNG_INFO_oFFs) != 0)
+; {
+ png_debug1 1, 'in %s retrieval function', 'png_get_x_offset_microns'
+
+; if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER)
+; return (info_ptr->x_offset);
+; }
+end if
+
+ xor eax,eax
+ ret
+endp
+
+;int_32 (png_structrp png_ptr, png_inforp info_ptr)
+align 4
+proc png_get_y_offset_microns, png_ptr:dword, info_ptr:dword
+if PNG_oFFs_SUPPORTED eq 1
+; if (png_ptr != NULL && info_ptr != NULL &&
+; (info_ptr->valid & PNG_INFO_oFFs) != 0)
+; {
+ png_debug1 1, 'in %s retrieval function', 'png_get_y_offset_microns'
+
+; if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER)
+; return (info_ptr->y_offset);
+; }
+end if
+
+ xor eax,eax
+ ret
+endp
+
+;int_32 (png_structrp png_ptr, png_inforp info_ptr)
+align 4
+proc png_get_x_offset_pixels, png_ptr:dword, info_ptr:dword
+if PNG_oFFs_SUPPORTED eq 1
+; if (png_ptr != NULL && info_ptr != NULL &&
+; (info_ptr->valid & PNG_INFO_oFFs) != 0)
+; {
+ png_debug1 1, 'in %s retrieval function', 'png_get_x_offset_pixels'
+
+; if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL)
+; return (info_ptr->x_offset);
+; }
+end if
+
+ xor eax,eax
+ ret
+endp
+
+;int_32 (png_structrp png_ptr, png_inforp info_ptr)
+align 4
+proc png_get_y_offset_pixels, png_ptr:dword, info_ptr:dword
+if PNG_oFFs_SUPPORTED eq 1
+; if (png_ptr != NULL && info_ptr != NULL &&
+; (info_ptr->valid & PNG_INFO_oFFs) != 0)
+; {
+ png_debug1 1, 'in %s retrieval function', 'png_get_y_offset_pixels'
+
+; if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL)
+; return (info_ptr->y_offset);
+; }
+end if
+
+ xor eax,eax
+ ret
+endp
+
+;uint_32 (uint_32 ppm)
+align 4
+proc ppi_from_ppm, ppm:dword
+;#if 0
+ ; The conversion is *(2.54/100), in binary (32 digits):
+ ; .00000110100000001001110101001001
+
+; uint_32 t1001, t1101;
+; ppm >>= 1; /* .1 */
+; t1001 = ppm + (ppm >> 3); /* .1001 */
+; t1101 = t1001 + (ppm >> 1); /* .1101 */
+; ppm >>= 20; /* .000000000000000000001 */
+; t1101 += t1101 >> 15; /* .1101000000000001101 */
+; t1001 >>= 11; /* .000000000001001 */
+; t1001 += t1001 >> 12; /* .000000000001001000000001001 */
+; ppm += t1001; /* .000000000001001000001001001 */
+; ppm += t1101; /* .110100000001001110101001001 */
+; return (ppm + 16) >> 5;/* .00000110100000001001110101001001 */
+;#else
+ ; The argument is a PNG unsigned integer, so it is not permitted
+ ; to be bigger than 2^31.
+
+; png_fixed_point result;
+; if (ppm <= PNG_UINT_31_MAX && png_muldiv(&result, (int_32)ppm, 127,
+; 5000) != 0)
+; return result;
+
+ ; Overflow.
+; return 0;
+;end if
+ ret
+endp
+
+;uint_32 (png_structrp png_ptr, png_inforp info_ptr)
+align 4
+proc png_get_pixels_per_inch, png_ptr:dword, info_ptr:dword
+ stdcall png_get_pixels_per_meter, [png_ptr], [info_ptr]
+ stdcall ppi_from_ppm, eax
+ ret
+endp
+
+;uint_32 (png_structrp png_ptr, png_inforp info_ptr)
+align 4
+proc png_get_x_pixels_per_inch, png_ptr:dword, info_ptr:dword
+ stdcall png_get_x_pixels_per_meter, [png_ptr], [info_ptr]
+ stdcall ppi_from_ppm, eax
+ ret
+endp
+
+;uint_32 (png_structrp png_ptr, png_inforp info_ptr)
+align 4
+proc png_get_y_pixels_per_inch, png_ptr:dword, info_ptr:dword
+ stdcall png_get_y_pixels_per_meter, [png_ptr], [info_ptr]
+ stdcall ppi_from_ppm, eax
+ ret
+endp
+
+;png_fixed_point (png_structrp png_ptr, int_32 microns)
+align 4
+proc png_fixed_inches_from_microns, png_ptr:dword, microns:dword
+ ; Convert from metres * 1,000,000 to inches * 100,000, meters to
+ ; inches is simply *(100/2.54), so we want *(10/2.54) == 500/127.
+ ; Notice that this can overflow - a warning is output and 0 is
+ ; returned.
+
+ stdcall png_muldiv_warn, [png_ptr], [microns], 500, 127
+ ret
+endp
+
+;png_fixed_point (png_structrp png_ptr, png_inforp info_ptr)
+align 4
+proc png_get_x_offset_inches_fixed, png_ptr:dword, info_ptr:dword
+ stdcall png_get_x_offset_microns, [png_ptr], [info_ptr]
+ stdcall png_fixed_inches_from_microns, [png_ptr], eax
+ ret
+endp
+
+;png_fixed_point (png_structrp png_ptr, png_inforp info_ptr)
+align 4
+proc png_get_y_offset_inches_fixed, png_ptr:dword, info_ptr:dword
+ stdcall png_get_y_offset_microns, [png_ptr], [info_ptr]
+ stdcall png_fixed_inches_from_microns, [png_ptr], eax
+ ret
+endp
+
+;float (png_structrp png_ptr, png_inforp info_ptr)
+align 4
+proc png_get_x_offset_inches, png_ptr:dword, info_ptr:dword
+ ; To avoid the overflow do the conversion directly in floating
+ ; point.
+
+; return (float)(png_get_x_offset_microns(png_ptr, info_ptr) * .00003937);
+ ret
+endp
+
+;float (png_structrp png_ptr, png_inforp info_ptr)
+align 4
+proc png_get_y_offset_inches, png_ptr:dword, info_ptr:dword
+ ; To avoid the overflow do the conversion directly in floating
+ ; point.
+
+; return (float)(png_get_y_offset_microns(png_ptr, info_ptr) * .00003937);
+ ret
+endp
+
+;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
+; uint_32 *res_x, uint_32 *res_y, int *unit_type)
+align 4
+proc png_get_pHYs_dpi, png_ptr:dword, info_ptr:dword, res_x:dword, res_y:dword, unit_type:dword
+; uint_32 retval = 0;
+
+; if (png_ptr != NULL && info_ptr != NULL &&
+; (info_ptr->valid & PNG_INFO_pHYs) != 0)
+; {
+ png_debug1 1, 'in %s retrieval function', 'pHYs'
+
+; if (res_x != NULL)
+; {
+; *res_x = info_ptr->x_pixels_per_unit;
+; retval |= PNG_INFO_pHYs;
+; }
+
+; if (res_y != NULL)
+; {
+; *res_y = info_ptr->y_pixels_per_unit;
+; retval |= PNG_INFO_pHYs;
+; }
+
+; if (unit_type != NULL)
+; {
+; *unit_type = (int)info_ptr->phys_unit_type;
+; retval |= PNG_INFO_pHYs;
+
+; if (*unit_type == 1)
+; {
+; if (res_x != NULL) *res_x = (uint_32)(*res_x * .0254 + .50);
+; if (res_y != NULL) *res_y = (uint_32)(*res_y * .0254 + .50);
+; }
+; }
+; }
+
+; return (retval);
+ ret
+endp
+
+; png_get_channels really belongs in here, too, but it's been around longer
+
+;byte (png_structrp png_ptr, png_inforp info_ptr)
+align 4
+proc png_get_channels, png_ptr:dword, info_ptr:dword
+ mov eax,[png_ptr]
+ cmp eax,0
+ je @f
+ mov eax,[info_ptr]
+ cmp eax,0
+ je @f ;if (..!=0 || ..!=0)
+ movzx eax,byte[eax+png_info_def.channels]
+ @@:
+ ret
+endp
+
+;bytep (png_structrp png_ptr, png_inforp info_ptr)
+align 4
+proc png_get_signature, png_ptr:dword, info_ptr:dword
+ mov eax,[png_ptr]
+ cmp eax,0
+ je @f
+ mov eax,[info_ptr]
+ cmp eax,0
+ je @f ;if (..!=0 || ..!=0)
+ movzx eax,byte[eax+png_info_def.signature]
+ @@:
+ ret
+endp
+
+;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
+; png_color_16p *background)
+align 4
+proc png_get_bKGD, png_ptr:dword, info_ptr:dword, background:dword
+; if (png_ptr != NULL && info_ptr != NULL &&
+; (info_ptr->valid & PNG_INFO_bKGD) != 0 &&
+; background != NULL)
+; {
+ png_debug1 1, 'in %s retrieval function', 'bKGD'
+
+; *background = &(info_ptr->background);
+; return (PNG_INFO_bKGD);
+; }
+
+ xor eax,eax
+ ret
+endp
+
+;if PNG_cHRM_SUPPORTED
+; The XYZ APIs were added in 1.5.5 to take advantage of the code added at the
+; same time to correct the rgb grayscale coefficient defaults obtained from the
+; cHRM chunk in 1.5.4
+
+;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
+; double *white_x, double *white_y, double *red_x, double *red_y,
+; double *green_x, double *green_y, double *blue_x, double *blue_y)
+align 4
+proc png_get_cHRM, png_ptr:dword, info_ptr:dword, white_x:dword, white_y:dword, red_x:dword, red_y:dword, green_x:dword, green_y:dword, blue_x:dword, blue_y:dword
+ ; Quiet API change: this code used to only return the end points if a cHRM
+ ; chunk was present, but the end points can also come from iCCP or sRGB
+ ; chunks, so in 1.6.0 the png_get_ APIs return the end points regardless and
+ ; the png_set_ APIs merely check that set end points are mutually
+ ; consistent.
+
+; if (png_ptr != NULL && info_ptr != NULL &&
+; (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
+; {
+ png_debug1 1, 'in %s retrieval function', 'cHRM'
+
+; if (white_x != NULL)
+; *white_x = png_float(png_ptr,
+; info_ptr->colorspace.end_points_xy.whitex, "cHRM white X");
+; if (white_y != NULL)
+; *white_y = png_float(png_ptr,
+; info_ptr->colorspace.end_points_xy.whitey, "cHRM white Y");
+; if (red_x != NULL)
+; *red_x = png_float(png_ptr, info_ptr->colorspace.end_points_xy.redx,
+; "cHRM red X");
+; if (red_y != NULL)
+; *red_y = png_float(png_ptr, info_ptr->colorspace.end_points_xy.redy,
+; "cHRM red Y");
+; if (green_x != NULL)
+; *green_x = png_float(png_ptr,
+; info_ptr->colorspace.end_points_xy.greenx, "cHRM green X");
+; if (green_y != NULL)
+; *green_y = png_float(png_ptr,
+; info_ptr->colorspace.end_points_xy.greeny, "cHRM green Y");
+; if (blue_x != NULL)
+; *blue_x = png_float(png_ptr, info_ptr->colorspace.end_points_xy.bluex,
+; "cHRM blue X");
+; if (blue_y != NULL)
+; *blue_y = png_float(png_ptr, info_ptr->colorspace.end_points_xy.bluey,
+; "cHRM blue Y");
+; return (PNG_INFO_cHRM);
+; }
+
+ xor eax,eax
+ ret
+endp
+
+;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
+; double *red_X, double *red_Y, double *red_Z, double *green_X,
+; double *green_Y, double *green_Z, double *blue_X, double *blue_Y,
+; double *blue_Z)
+align 4
+proc png_get_cHRM_XYZ, png_ptr:dword, info_ptr:dword, red_X:dword, red_Y:dword, red_Z:dword, green_X:dword, green_Y:dword, green_Z:dword, blue_X:dword, blue_Y:dword, blue_Z:dword
+; if (png_ptr != NULL && info_ptr != NULL &&
+; (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
+; {
+ png_debug1 1, 'in %s retrieval function', 'cHRM_XYZ(float)'
+
+; if (red_X != NULL)
+; *red_X = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_X,
+; "cHRM red X");
+; if (red_Y != NULL)
+; *red_Y = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_Y,
+; "cHRM red Y");
+; if (red_Z != NULL)
+; *red_Z = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_Z,
+; "cHRM red Z");
+; if (green_X != NULL)
+; *green_X = png_float(png_ptr,
+; info_ptr->colorspace.end_points_XYZ.green_X, "cHRM green X");
+; if (green_Y != NULL)
+; *green_Y = png_float(png_ptr,
+; info_ptr->colorspace.end_points_XYZ.green_Y, "cHRM green Y");
+; if (green_Z != NULL)
+; *green_Z = png_float(png_ptr,
+; info_ptr->colorspace.end_points_XYZ.green_Z, "cHRM green Z");
+; if (blue_X != NULL)
+; *blue_X = png_float(png_ptr,
+; info_ptr->colorspace.end_points_XYZ.blue_X, "cHRM blue X");
+; if (blue_Y != NULL)
+; *blue_Y = png_float(png_ptr,
+; info_ptr->colorspace.end_points_XYZ.blue_Y, "cHRM blue Y");
+; if (blue_Z != NULL)
+; *blue_Z = png_float(png_ptr,
+; info_ptr->colorspace.end_points_XYZ.blue_Z, "cHRM blue Z");
+; return (PNG_INFO_cHRM);
+; }
+
+ xor eax,eax
+ ret
+endp
+
+;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
+; png_fixed_point *int_red_X, png_fixed_point *int_red_Y,
+; png_fixed_point *int_red_Z, png_fixed_point *int_green_X,
+; png_fixed_point *int_green_Y, png_fixed_point *int_green_Z,
+; png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y,
+; png_fixed_point *int_blue_Z)
+align 4
+proc png_get_cHRM_XYZ_fixed, png_ptr:dword, info_ptr:dword, int_red_X:dword, int_red_Y:dword, int_red_Z:dword, int_green_X:dword, int_green_Y:dword, int_green_Z:dword, int_blue_X:dword, int_blue_Y:dword, int_blue_Z:dword
+; if (png_ptr != NULL && info_ptr != NULL &&
+; (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
+; {
+ png_debug1 1, 'in %s retrieval function', 'cHRM_XYZ'
+
+; if (int_red_X != NULL)
+; *int_red_X = info_ptr->colorspace.end_points_XYZ.red_X;
+; if (int_red_Y != NULL)
+; *int_red_Y = info_ptr->colorspace.end_points_XYZ.red_Y;
+; if (int_red_Z != NULL)
+; *int_red_Z = info_ptr->colorspace.end_points_XYZ.red_Z;
+; if (int_green_X != NULL)
+; *int_green_X = info_ptr->colorspace.end_points_XYZ.green_X;
+; if (int_green_Y != NULL)
+; *int_green_Y = info_ptr->colorspace.end_points_XYZ.green_Y;
+; if (int_green_Z != NULL)
+; *int_green_Z = info_ptr->colorspace.end_points_XYZ.green_Z;
+; if (int_blue_X != NULL)
+; *int_blue_X = info_ptr->colorspace.end_points_XYZ.blue_X;
+; if (int_blue_Y != NULL)
+; *int_blue_Y = info_ptr->colorspace.end_points_XYZ.blue_Y;
+; if (int_blue_Z != NULL)
+; *int_blue_Z = info_ptr->colorspace.end_points_XYZ.blue_Z;
+; return (PNG_INFO_cHRM);
+; }
+
+ xor eax,eax
+.end_f:
+ ret
+endp
+
+;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
+; png_fixed_point *white_x, png_fixed_point *white_y, png_fixed_point *red_x,
+; png_fixed_point *red_y, png_fixed_point *green_x, png_fixed_point *green_y,
+; png_fixed_point *blue_x, png_fixed_point *blue_y)
+align 4
+proc png_get_cHRM_fixed, png_ptr:dword, info_ptr:dword, white_x:dword, white_y:dword, red_x:dword, red_y:dword, green_x:dword, green_y:dword, blue_x:dword, blue_y:dword
+ png_debug1 1, 'in %s retrieval function', 'cHRM'
+
+; if (png_ptr != NULL && info_ptr != NULL &&
+; (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
+; {
+; if (white_x != NULL)
+; *white_x = info_ptr->colorspace.end_points_xy.whitex;
+; if (white_y != NULL)
+; *white_y = info_ptr->colorspace.end_points_xy.whitey;
+; if (red_x != NULL)
+; *red_x = info_ptr->colorspace.end_points_xy.redx;
+; if (red_y != NULL)
+; *red_y = info_ptr->colorspace.end_points_xy.redy;
+; if (green_x != NULL)
+; *green_x = info_ptr->colorspace.end_points_xy.greenx;
+; if (green_y != NULL)
+; *green_y = info_ptr->colorspace.end_points_xy.greeny;
+; if (blue_x != NULL)
+; *blue_x = info_ptr->colorspace.end_points_xy.bluex;
+; if (blue_y != NULL)
+; *blue_y = info_ptr->colorspace.end_points_xy.bluey;
+; return (PNG_INFO_cHRM);
+; }
+
+ xor eax,eax
+ ret
+endp
+;end if
+
+;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
+; png_fixed_point *file_gamma)
+align 4
+proc png_get_gAMA_fixed, png_ptr:dword, info_ptr:dword, file_gamma:dword
+ png_debug1 1, 'in %s retrieval function', 'gAMA'
+
+; if (png_ptr != NULL && info_ptr != NULL &&
+; (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 &&
+; file_gamma != NULL)
+; {
+; *file_gamma = info_ptr->colorspace.gamma;
+; return (PNG_INFO_gAMA);
+; }
+
+ xor eax,eax
+ ret
+endp
+
+;uint_32 (png_structrp png_ptr, png_inforp info_ptr, double *file_gamma)
+align 4
+proc png_get_gAMA, png_ptr:dword, info_ptr:dword, file_gamma:dword
+ png_debug1 1, 'in %s retrieval function', 'gAMA(float)'
+
+; if (png_ptr != NULL && info_ptr != NULL &&
+; (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 &&
+; file_gamma != NULL)
+; {
+; *file_gamma = png_float(png_ptr, info_ptr->colorspace.gamma,
+; "png_get_gAMA");
+; return (PNG_INFO_gAMA);
+; }
+
+ xor eax,eax
+ ret
+endp
+
+;uint_32 (png_structrp png_ptr, png_inforp info_ptr, int *file_srgb_intent)
+align 4
+proc png_get_sRGB, png_ptr:dword, info_ptr:dword, file_srgb_intent:dword
+ png_debug1 1, 'in %s retrieval function', 'sRGB'
+
+; if (png_ptr != NULL && info_ptr != NULL &&
+; (info_ptr->valid & PNG_INFO_sRGB) != 0 && file_srgb_intent != NULL)
+; {
+; *file_srgb_intent = info_ptr->colorspace.rendering_intent;
+; return (PNG_INFO_sRGB);
+; }
+
+ xor eax,eax
+ ret
+endp
+
+;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
+; png_charpp name, int *compression_type, bytepp profile, uint_32 *proflen)
+align 4
+proc png_get_iCCP, png_ptr:dword, info_ptr:dword, name:dword, compression_type:dword, profile:dword, proflen:dword
+ png_debug1 1, 'in %s retrieval function', 'iCCP'
+
+; if (png_ptr != NULL && info_ptr != NULL &&
+; (info_ptr->valid & PNG_INFO_iCCP) != 0 &&
+; name != NULL && compression_type != NULL && profile != NULL &&
+; proflen != NULL)
+; {
+; *name = info_ptr->iccp_name;
+; *profile = info_ptr->iccp_profile;
+; *proflen = png_get_uint_32(info_ptr->iccp_profile);
+ ; This is somewhat irrelevant since the profile data returned has
+ ; actually been uncompressed.
+
+; *compression_type = PNG_COMPRESSION_TYPE_BASE;
+; return (PNG_INFO_iCCP);
+; }
+
+ xor eax,eax
+ ret
+endp
+
+;int (png_structrp png_ptr, png_inforp info_ptr,
+; png_sPLT_tpp spalettes)
+align 4
+proc png_get_sPLT, png_ptr:dword, info_ptr:dword, spalettes:dword
+; if (png_ptr != NULL && info_ptr != NULL && spalettes != NULL)
+; {
+; *spalettes = info_ptr->splt_palettes;
+; return info_ptr->splt_palettes_num;
+; }
+
+ xor eax,eax
+ ret
+endp
+
+;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
+; uint_16p hist)
+align 4
+proc png_get_hIST, png_ptr:dword, info_ptr:dword, hist:dword
+ png_debug1 1, 'in %s retrieval function', 'hIST'
+
+; if (png_ptr != NULL && info_ptr != NULL &&
+; (info_ptr->valid & PNG_INFO_hIST) != 0 && hist != NULL)
+; {
+; *hist = info_ptr->hist;
+; return (PNG_INFO_hIST);
+; }
+
+ xor eax,eax
+ ret
+endp
+
+;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
+; uint_32 *width, uint_32 *height, int *bit_depth,
+; int *color_type, int *interlace_type, int *compression_type,
+; int *filter_type)
+align 4
+proc png_get_IHDR, png_ptr:dword, info_ptr:dword,\
+ width:dword, height:dword, bit_depth:dword, color_type:dword,\
+ interlace_type:dword, compression_type:dword, filter_type:dword
+ png_debug1 1, 'in %s retrieval function', 'IHDR'
+
+; if (png_ptr == NULL || info_ptr == NULL)
+; return (0);
+
+; if (width != NULL)
+; *width = info_ptr->width;
+
+; if (height != NULL)
+; *height = info_ptr->height;
+
+; if (bit_depth != NULL)
+; *bit_depth = info_ptr->bit_depth;
+
+; if (color_type != NULL)
+; *color_type = info_ptr->color_type;
+
+; if (compression_type != NULL)
+; *compression_type = info_ptr->compression_type;
+
+; if (filter_type != NULL)
+; *filter_type = info_ptr->filter_type;
+
+; if (interlace_type != NULL)
+; *interlace_type = info_ptr->interlace_type;
+
+ ; This is redundant if we can be sure that the info_ptr values were all
+ ; assigned in png_set_IHDR(). We do the check anyhow in case an
+ ; application has ignored our advice not to mess with the members
+ ; of info_ptr directly.
+
+; png_check_IHDR(png_ptr, info_ptr->width, info_ptr->height,
+; info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type,
+; info_ptr->compression_type, info_ptr->filter_type);
+
+ xor eax,eax
+ inc eax
+ ret
+endp
+
+;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
+; int_32 *offset_x, int_32 *offset_y, int *unit_type)
+align 4
+proc png_get_oFFs, png_ptr:dword, info_ptr:dword, offset_x:dword, offset_y:dword, unit_type:dword
+ png_debug1 1, 'in %s retrieval function', 'oFFs'
+
+; if (png_ptr != NULL && info_ptr != NULL &&
+; (info_ptr->valid & PNG_INFO_oFFs) != 0 &&
+; offset_x != NULL && offset_y != NULL && unit_type != NULL)
+; {
+; *offset_x = info_ptr->x_offset;
+; *offset_y = info_ptr->y_offset;
+; *unit_type = (int)info_ptr->offset_unit_type;
+; return (PNG_INFO_oFFs);
+; }
+
+ xor eax,eax
+ ret
+endp
+
+;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
+; charp *purpose, int_32 *X0, int_32 *X1, int *type, int *nparams,
+; charp *units, charpp *params)
+align 4
+proc png_get_pCAL, png_ptr:dword, info_ptr:dword, purpose:dword, X0:dword, X1:dword, type:dword, nparams:dword, units:dword, params:dword
+ png_debug1 1, 'in %s retrieval function', 'pCAL'
+
+; if (png_ptr != NULL && info_ptr != NULL &&
+; (info_ptr->valid & PNG_INFO_pCAL) != 0 &&
+; purpose != NULL && X0 != NULL && X1 != NULL && type != NULL &&
+; nparams != NULL && units != NULL && params != NULL)
+; {
+; *purpose = info_ptr->pcal_purpose;
+; *X0 = info_ptr->pcal_X0;
+; *X1 = info_ptr->pcal_X1;
+; *type = (int)info_ptr->pcal_type;
+; *nparams = (int)info_ptr->pcal_nparams;
+; *units = info_ptr->pcal_units;
+; *params = info_ptr->pcal_params;
+; return (PNG_INFO_pCAL);
+; }
+
+ xor eax,eax
+ ret
+endp
+
+;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
+; int *unit, png_fixed_point *width, png_fixed_point *height)
+align 4
+proc png_get_sCAL_fixed, png_ptr:dword, info_ptr:dword, unit:dword, width:dword, height:dword
+; if (png_ptr != NULL && info_ptr != NULL &&
+; (info_ptr->valid & PNG_INFO_sCAL) != 0)
+; {
+; *unit = info_ptr->scal_unit;
+ ;TODO: make this work without FP support; the API is currently eliminated
+ ; if neither floating point APIs nor internal floating point arithmetic
+ ; are enabled.
+
+; *width = png_fixed(png_ptr, atof(info_ptr->scal_s_width), "sCAL width");
+; *height = png_fixed(png_ptr, atof(info_ptr->scal_s_height),
+; "sCAL height");
+; return (PNG_INFO_sCAL);
+; }
+
+; return(0);
+ ret
+endp
+
+;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
+; int *unit, double *width, double *height)
+align 4
+proc png_get_sCAL, png_ptr:dword, info_ptr:dword, unit:dword, width:dword, height:dword
+; if (png_ptr != NULL && info_ptr != NULL &&
+; (info_ptr->valid & PNG_INFO_sCAL) != 0)
+; {
+; *unit = info_ptr->scal_unit;
+; *width = atof(info_ptr->scal_s_width);
+; *height = atof(info_ptr->scal_s_height);
+; return (PNG_INFO_sCAL);
+; }
+
+; return(0);
+ ret
+endp
+
+;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
+; int *unit, charpp width, charpp height)
+align 4
+proc png_get_sCAL_s, png_ptr:dword, info_ptr:dword, unit:dword, width:dword, height:dword
+; if (png_ptr != NULL && info_ptr != NULL &&
+; (info_ptr->valid & PNG_INFO_sCAL) != 0)
+; {
+; *unit = info_ptr->scal_unit;
+; *width = info_ptr->scal_s_width;
+; *height = info_ptr->scal_s_height;
+; return (PNG_INFO_sCAL);
+; }
+
+ xor eax,eax
+.end_f:
+ ret
+endp
+
+;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
+; uint_32 *res_x, uint_32 *res_y, int *unit_type)
+align 4
+proc png_get_pHYs, png_ptr:dword, info_ptr:dword, res_x:dword, res_y:dword, unit_type:dword
+; uint_32 retval = 0;
+
+ png_debug1 1, 'in %s retrieval function', 'pHYs'
+
+; if (png_ptr != NULL && info_ptr != NULL &&
+; (info_ptr->valid & PNG_INFO_pHYs) != 0)
+; {
+; if (res_x != NULL)
+; {
+; *res_x = info_ptr->x_pixels_per_unit;
+; retval |= PNG_INFO_pHYs;
+; }
+
+; if (res_y != NULL)
+; {
+; *res_y = info_ptr->y_pixels_per_unit;
+; retval |= PNG_INFO_pHYs;
+; }
+
+; if (unit_type != NULL)
+; {
+; *unit_type = (int)info_ptr->phys_unit_type;
+; retval |= PNG_INFO_pHYs;
+; }
+; }
+
+; return (retval);
+ ret
+endp
+
+;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
+; png_colorp *palette, int *num_palette)
+align 4
+proc png_get_PLTE, png_ptr:dword, info_ptr:dword, palette:dword, num_palette:dword
+ png_debug1 1, 'in %s retrieval function', 'PLTE'
+
+; if (png_ptr != NULL && info_ptr != NULL &&
+; (info_ptr->valid & PNG_INFO_PLTE) != 0 && palette != NULL)
+; {
+; *palette = info_ptr->palette;
+; *num_palette = info_ptr->num_palette;
+; png_debug1(3, "num_palette = %d", *num_palette);
+; return (PNG_INFO_PLTE);
+; }
+
+ xor eax,eax
+ ret
+endp
+
+;uint_32 (png_structrp png_ptr, png_inforp info_ptr, png_color_8p *sig_bit)
+align 4
+proc png_get_sBIT, png_ptr:dword, info_ptr:dword, sig_bit:dword
+ png_debug1 1, 'in %s retrieval function', 'sBIT'
+
+; if (png_ptr != NULL && info_ptr != NULL &&
+; (info_ptr->valid & PNG_INFO_sBIT) != 0 && sig_bit != NULL)
+; {
+; *sig_bit = &(info_ptr->sig_bit);
+; return (PNG_INFO_sBIT);
+; }
+
+ xor eax,eax
+ ret
+endp
+
+;int (png_structrp png_ptr, png_inforp info_ptr, png_textp *text_ptr, int *num_text)
+align 4
+proc png_get_text, png_ptr:dword, info_ptr:dword, text_ptr:dword, num_text:dword
+; if (png_ptr != NULL && info_ptr != NULL && info_ptr->num_text > 0)
+; {
+; png_debug1(1, "in 0x%lx retrieval function",
+; (unsigned long)png_ptr->chunk_name);
+
+; if (text_ptr != NULL)
+; *text_ptr = info_ptr->text;
+
+; if (num_text != NULL)
+; *num_text = info_ptr->num_text;
+
+; return info_ptr->num_text;
+; }
+
+; if (num_text != NULL)
+; *num_text = 0;
+
+; return(0);
+ ret
+endp
+
+;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
+; png_timep *mod_time)
+align 4
+proc png_get_tIME, png_ptr:dword, info_ptr:dword, mod_time:dword
+ png_debug1 1, 'in %s retrieval function', 'tIME'
+
+; if (png_ptr != NULL && info_ptr != NULL &&
+; (info_ptr->valid & PNG_INFO_tIME) != 0 && mod_time != NULL)
+; {
+; *mod_time = &(info_ptr->mod_time);
+; return (PNG_INFO_tIME);
+; }
+
+ xor eax,eax
+ ret
+endp
+
+;uint_32 (png_structrp png_ptr, png_inforp info_ptr,
+; bytep *trans_alpha, int *num_trans, png_color_16p *trans_color)
+align 4
+proc png_get_tRNS, png_ptr:dword, info_ptr:dword, trans_alpha:dword, num_trans:dword, trans_color:dword
+; uint_32 retval = 0;
+; if (png_ptr != NULL && info_ptr != NULL &&
+; (info_ptr->valid & PNG_INFO_tRNS) != 0)
+; {
+ png_debug1 1, 'in %s retrieval function', 'tRNS'
+
+; if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+; {
+; if (trans_alpha != NULL)
+; {
+; *trans_alpha = info_ptr->trans_alpha;
+; retval |= PNG_INFO_tRNS;
+; }
+
+; if (trans_color != NULL)
+; *trans_color = &(info_ptr->trans_color);
+; }
+
+; else /* if (info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) */
+; {
+; if (trans_color != NULL)
+; {
+; *trans_color = &(info_ptr->trans_color);
+; retval |= PNG_INFO_tRNS;
+; }
+
+; if (trans_alpha != NULL)
+; *trans_alpha = NULL;
+; }
+
+; if (num_trans != NULL)
+; {
+; *num_trans = info_ptr->num_trans;
+; retval |= PNG_INFO_tRNS;
+; }
+; }
+
+; return (retval);
+ ret
+endp
+
+;int (png_structrp png_ptr, png_inforp info_ptr,
+; png_unknown_chunkpp unknowns)
+align 4
+proc png_get_unknown_chunks, png_ptr:dword, info_ptr:dword, unknowns:dword
+; if (png_ptr != NULL && info_ptr != NULL && unknowns != NULL)
+; {
+; *unknowns = info_ptr->unknown_chunks;
+; return info_ptr->unknown_chunks_num;
+; }
+
+ xor eax,eax
+ ret
+endp
+
+;byte (png_structrp png_ptr)
+align 4
+proc png_get_rgb_to_gray_status, png_ptr:dword
+ mov eax,[png_ptr]
+ cmp eax,0
+ je @f
+ mov eax,[eax+png_struct.rgb_to_gray_status]
+ @@:
+ ret
+endp
+
+;voidp (png_structrp png_ptr)
+align 4
+proc png_get_user_chunk_ptr, png_ptr:dword
+ mov eax,[png_ptr]
+ cmp eax,0
+ je @f
+ mov eax,[eax+png_struct.user_chunk_ptr]
+ @@:
+ ret
+endp
+
+;png_size_t (png_structrp png_ptr)
+align 4
+proc png_get_compression_buffer_size uses ebx, png_ptr:dword
+ mov eax,[png_ptr]
+ cmp eax,0
+ je .end_f ;if (..==0) return 0
+
+if PNG_WRITE_SUPPORTED eq 1
+ mov ebx,[eax+png_struct.mode]
+ and ebx,PNG_IS_READ_STRUCT
+ cmp ebx,0
+; if (..!=0)
+end if
+; {
+if PNG_SEQUENTIAL_READ_SUPPORTED eq 1
+ mov eax,[eax+png_struct.IDAT_read_size]
+else
+ mov eax,PNG_IDAT_READ_SIZE
+end if
+; }
+
+if PNG_WRITE_SUPPORTED eq 1
+ jmp .end_f
+; else
+ mov eax,[eax+png_struct.zbuffer_size]
+end if
+.end_f:
+ ret
+endp
+
+; These functions were added to libpng 1.2.6 and were enabled
+; by default in libpng-1.4.0
+;uint_32 (png_structrp png_ptr)
+align 4
+proc png_get_user_width_max, png_ptr:dword
+ mov eax,[png_ptr]
+ cmp eax,0
+ je @f
+ mov eax,[eax+png_struct.user_width_max]
+ @@:
+ ret
+endp
+
+;uint_32 (png_structrp png_ptr)
+align 4
+proc png_get_user_height_max, png_ptr:dword
+ mov eax,[png_ptr]
+ cmp eax,0
+ je @f
+ mov eax,[eax+png_struct.user_height_max]
+ @@:
+ ret
+endp
+
+; This function was added to libpng 1.4.0
+;uint_32 (png_structrp png_ptr)
+align 4
+proc png_get_chunk_cache_max, png_ptr:dword
+ mov eax,[png_ptr]
+ cmp eax,0
+ je @f
+ mov eax,[eax+png_struct.user_chunk_cache_max]
+ @@:
+ ret
+endp
+
+; This function was added to libpng 1.4.1
+;png_alloc_size_t (png_structrp png_ptr)
+align 4
+proc png_get_chunk_malloc_max, png_ptr:dword
+ mov eax,[png_ptr]
+ cmp eax,0
+ je @f
+ mov eax,[eax+png_struct.user_chunk_malloc_max]
+ @@:
+ ret
+endp
+
+; These functions were added to libpng 1.4.0
+;uint_32 (png_structrp png_ptr)
+align 4
+proc png_get_io_state, png_ptr:dword
+ mov eax,[png_ptr]
+ mov eax,[eax+png_struct.io_state]
+ ret
+endp
+
+;uint_32 (png_structrp png_ptr)
+align 4
+proc png_get_io_chunk_type, png_ptr:dword
+ mov eax,[png_ptr]
+ mov eax,[eax+png_struct.chunk_name]
+ ret
+endp
+
+;int (png_const_structp png_ptr, png_const_infop info_ptr)
+align 4
+proc png_get_palette_max, png_ptr:dword, info_ptr:dword
+ mov eax,[png_ptr]
+ cmp eax,0
+ je @f
+ cmp dword[info_ptr],0
+ je @f ;if (..!=0 && ..!=0)
+ mov eax,[eax+png_struct.num_palette_max]
+ jmp .end_f
+ @@:
+ xor eax,eax
+ dec eax
+.end_f:
+ ret
+endp
+
diff --git a/programs/develop/libraries/libs-dev/libimg/png/libpng/pnginfo.inc b/programs/develop/libraries/libs-dev/libimg/png/libpng/pnginfo.inc
index 793b4207f..ff83925a0 100644
--- a/programs/develop/libraries/libs-dev/libimg/png/libpng/pnginfo.inc
+++ b/programs/develop/libraries/libs-dev/libimg/png/libpng/pnginfo.inc
@@ -1,253 +1,253 @@
-
-; pnginfo.inc - header file for PNG reference library
-
-; Last changed in libpng 1.6.1 [March 28, 2013]
-; Copyright (c) 1998-2002,2004,2006-2013 Glenn Randers-Pehrson
-; (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
-; (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
-
-; This code is released under the libpng license.
-; For conditions of distribution and use, see the disclaimer
-; and license in png.inc
-
-; png_info is a structure that holds the information in a PNG file so
-; that the application can find out the characteristics of the image.
-; If you are reading the file, this structure will tell you what is
-; in the PNG file. If you are writing the file, fill in the information
-; you want to put into the PNG file, using png_set_*() functions, then
-; call png_write_info().
-
-; The names chosen should be very close to the PNG specification, so
-; consult that document for information about the meaning of each field.
-
-; With libpng < 0.95, it was only possible to directly set and read the
-; the values in the png_info_struct, which meant that the contents and
-; order of the values had to remain fixed. With libpng 0.95 and later,
-; however, there are now functions that abstract the contents of
-; png_info_struct from the application, so this makes it easier to use
-; libpng with dynamic libraries, and even makes it possible to use
-; libraries that don't have all of the libpng ancillary chunk-handing
-; functionality. In libpng-1.5.0 this was moved into a separate private
-; file that is not visible to applications.
-
-; The following members may have allocated storage attached that should be
-; cleaned up before the structure is discarded: palette, trans, text,
-; pcal_purpose, pcal_units, pcal_params, hist, iccp_name, iccp_profile,
-; splt_palettes, scal_unit, row_pointers, and unknowns. By default, these
-; are automatically freed when the info structure is deallocated, if they were
-; allocated internally by libpng. This behavior can be changed by means
-; of the png_data_freer() function.
-
-; More allocation details: all the chunk-reading functions that
-; change these members go through the corresponding png_set_*
-; functions. A function to clear these members is available: see
-; png_free_data(). The png_set_* functions do not depend on being
-; able to point info structure members to any of the storage they are
-; passed (they make their own copies), EXCEPT that the png_set_text
-; functions use the same storage passed to them in the text_ptr or
-; itxt_ptr structure argument, and the png_set_rows and png_set_unknowns
-; functions do not make their own copies.
-
-
-struct png_info_def
- ; The following are necessary for every PNG file
- width dd ? ;uint_32 ;width of image in pixels (from IHDR)
- height dd ? ;uint_32 ;height of image in pixels (from IHDR)
- valid dd ? ;uint_32 ;valid chunk data (see PNG_INFO_ below)
- rowbytes dd ? ;png_size_t ;bytes needed to hold an untransformed row
- palette dd ? ;png_colorp ; array of color values (valid & PNG_INFO_PLTE)
- num_palette dw ? ;uint_16 ;number of color entries in "palette" (PLTE)
- num_trans dw ? ;uint_16 ;number of transparent palette color (tRNS)
- bit_depth db ? ;byte ;1, 2, 4, 8, or 16 bits/channel (from IHDR)
- color_type db ? ;byte ;see PNG_COLOR_TYPE_ below (from IHDR)
- ; The following three should have been named *_method not *_type
- compression_type db ? ;byte ;must be PNG_COMPRESSION_TYPE_BASE (IHDR)
- filter_type db ? ;byte ;must be PNG_FILTER_TYPE_BASE (from IHDR)
- interlace_type db ? ;byte ;One of PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7
-
- ; The following are set by png_set_IHDR, called from the application on
- ; write, but the are never actually used by the write code.
-
- channels db ? ;byte ;number of data channels per pixel (1, 2, 3, 4)
- pixel_depth db ? ;byte ;number of bits per pixel
- spare_byte db ? ;byte ;to align the data, and for future use
-
-if PNG_READ_SUPPORTED eq 1
- ; This is never set during write
- signature db 8 ;byte[8] ;magic bytes read by libpng from start of file
-end if
-
- ; The rest of the data is optional. If you are reading, check the
- ; valid field to see if the information in these are valid. If you
- ; are writing, set the valid field to those chunks you want written,
- ; and initialize the appropriate fields below.
-
-
-if (PNG_COLORSPACE_SUPPORTED eq 1) | (PNG_GAMMA_SUPPORTED eq 1)
- ; png_colorspace only contains 'flags' if neither GAMMA or COLORSPACE are
- ; defined. When COLORSPACE is switched on all the colorspace-defining
- ; chunks should be enabled, when GAMMA is switched on all the gamma-defining
- ; chunks should be enabled. If this is not done it becomes possible to read
- ; inconsistent PNG files and assign a probably incorrect interpretation to
- ; the information. (In other words, by carefully choosing which chunks to
- ; recognize the system configuration can select an interpretation for PNG
- ; files containing ambiguous data and this will result in inconsistent
- ; behavior between different libpng builds!)
-
- colorspace png_colorspace
-end if
-
-if PNG_iCCP_SUPPORTED eq 1
- ; iCCP chunk data.
- iccp_name dd ? ;charp ;profile name
- iccp_profile dd ? ;bytep ;International Color Consortium profile data
- iccp_proflen dd ? ;uint_32 ;ICC profile data length
-end if
-
-if PNG_TEXT_SUPPORTED eq 1
- ; The tEXt, and zTXt chunks contain human-readable textual data in
- ; uncompressed, compressed, and optionally compressed forms, respectively.
- ; The data in "text" is an array of pointers to uncompressed,
- ; null-terminated C strings. Each chunk has a keyword that describes the
- ; textual data contained in that chunk. Keywords are not required to be
- ; unique, and the text string may be empty. Any number of text chunks may
- ; be in an image.
-
- num_text dd ? ;int ;number of comments read or comments to write
- max_text dd ? ;int ;current size of text array
- text dd ? ;png_textp ;array of comments read or comments to write
-end if ;TEXT
-
-if PNG_tIME_SUPPORTED eq 1
- ; The tIME chunk holds the last time the displayed image data was
- ; modified. See the png_time struct for the contents of this struct.
-
- mod_time png_time
-end if
-
-if PNG_sBIT_SUPPORTED eq 1
- ; The sBIT chunk specifies the number of significant high-order bits
- ; in the pixel data. Values are in the range [1, bit_depth], and are
- ; only specified for the channels in the pixel data. The contents of
- ; the low-order bits is not specified. Data is valid if
- ; (valid & PNG_INFO_sBIT) is non-zero.
-
- sig_bit png_color_8 ; significant bits in color channels
-end if
-
-if (PNG_tRNS_SUPPORTED eq 1) | (PNG_READ_EXPAND_SUPPORTED eq 1) | (PNG_READ_BACKGROUND_SUPPORTED eq 1)
- ; The tRNS chunk supplies transparency data for paletted images and
- ; other image types that don't need a full alpha channel. There are
- ; "num_trans" transparency values for a paletted image, stored in the
- ; same order as the palette colors, starting from index 0. Values
- ; for the data are in the range [0, 255], ranging from fully transparent
- ; to fully opaque, respectively. For non-paletted images, there is a
- ; single color specified that should be treated as fully transparent.
- ; Data is valid if (valid & PNG_INFO_tRNS) is non-zero.
-
- trans_alpha dd ? ;bytep ; alpha values for paletted image
- trans_color png_color_16 ;transparent color for non-palette image
-end if
-
-if (PNG_bKGD_SUPPORTED eq 1) | (PNG_READ_BACKGROUND_SUPPORTED eq 1)
- ; The bKGD chunk gives the suggested image background color if the
- ; display program does not have its own background color and the image
- ; is needs to composited onto a background before display. The colors
- ; in "background" are normally in the same color space/depth as the
- ; pixel data. Data is valid if (valid & PNG_INFO_bKGD) is non-zero.
-
- background png_color_16
-end if
-
-if PNG_oFFs_SUPPORTED eq 1
- ; The oFFs chunk gives the offset in "offset_unit_type" units rightwards
- ; and downwards from the top-left corner of the display, page, or other
- ; application-specific co-ordinate space. See the PNG_OFFSET_ defines
- ; below for the unit types. Valid if (valid & PNG_INFO_oFFs) non-zero.
-
- x_offset dd ? ;int_32 ;x offset on page
- y_offset dd ? ;int_32 ;y offset on page
- offset_unit_type db ? ;byte ;offset units type
-end if
-
-if PNG_pHYs_SUPPORTED eq 1
- ; The pHYs chunk gives the physical pixel density of the image for
- ; display or printing in "phys_unit_type" units (see PNG_RESOLUTION_
- ; defines below). Data is valid if (valid & PNG_INFO_pHYs) is non-zero.
-
- x_pixels_per_unit dd ? ;uint_32 ;horizontal pixel density
- y_pixels_per_unit dd ? ;uint_32 ;vertical pixel density
- phys_unit_type db ? ;byte ;resolution type (see PNG_RESOLUTION_ below)
-end if
-
-if PNG_hIST_SUPPORTED eq 1
- ; The hIST chunk contains the relative frequency or importance of the
- ; various palette entries, so that a viewer can intelligently select a
- ; reduced-color palette, if required. Data is an array of "num_palette"
- ; values in the range [0,65535]. Data valid if (valid & PNG_INFO_hIST)
- ; is non-zero.
-
- hist dd ? ;uint_16p
-end if
-
-if PNG_pCAL_SUPPORTED eq 1
- ; The pCAL chunk describes a transformation between the stored pixel
- ; values and original physical data values used to create the image.
- ; The integer range [0, 2^bit_depth - 1] maps to the floating-point
- ; range given by [pcal_X0, pcal_X1], and are further transformed by a
- ; (possibly non-linear) transformation function given by "pcal_type"
- ; and "pcal_params" into "pcal_units". Please see the PNG_EQUATION_
- ; defines below, and the PNG-Group's PNG extensions document for a
- ; complete description of the transformations and how they should be
- ; implemented, and for a description of the ASCII parameter strings.
- ; Data values are valid if (valid & PNG_INFO_pCAL) non-zero.
-
- pcal_purpose dd ? ;charp ;pCAL chunk description string
- pcal_X0 dd ? ;int_32 ;minimum value
- pcal_X1 dd ? ;int_32 ;maximum value
- pcal_units dd ? ;charp ;Latin-1 string giving physical units
- pcal_params dd ? ;charpp ;ASCII strings containing parameter values
- pcal_type db ? ;byte ;equation type (see PNG_EQUATION_ below)
- pcal_nparams db ? ;byte ;number of parameters given in pcal_params
-end if
-
-; New members added in libpng-1.0.6
- free_me dd ? ;uint_32 ;flags items libpng is responsible for freeing
-
-if PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED eq 1
- ; Storage for unknown chunks that the library doesn't recognize.
- unknown_chunks dd ? ;png_unknown_chunkp
-
- ; The type of this field is limited by the type of
- ; png_struct::user_chunk_cache_max, else overflow can occur.
-
- unknown_chunks_num dd ? ;int
-end if
-
-if PNG_sPLT_SUPPORTED eq 1
- ; Data on sPLT chunks (there may be more than one).
- splt_palettes dd ? ;png_sPLT_tp
- splt_palettes_num dd ? ;int ;Match type returned by png_get API
-end if
-
-if PNG_sCAL_SUPPORTED eq 1
- ; The sCAL chunk describes the actual physical dimensions of the
- ; subject matter of the graphic. The chunk contains a unit specification
- ; a byte value, and two ASCII strings representing floating-point
- ; values. The values are width and height corresponsing to one pixel
- ; in the image. Data values are valid if (valid & PNG_INFO_sCAL) is
- ; non-zero.
-
- scal_unit db ? ;byte ;unit of physical scale
- scal_s_width dd ? ;charp ;string containing height
- scal_s_height dd ? ;charp ;string containing width
-end if
-
-if PNG_INFO_IMAGE_SUPPORTED eq 1
- ; Memory has been allocated if (valid & PNG_ALLOCATED_INFO_ROWS)
- ; non-zero
- ; Data valid if (valid & PNG_INFO_IDAT) non-zero
- row_pointers dd ? ;bytepp ;the image bits
-end if
-
-ends
+
+; pnginfo.inc - header file for PNG reference library
+
+; Last changed in libpng 1.6.1 [March 28, 2013]
+; Copyright (c) 1998-2002,2004,2006-2013 Glenn Randers-Pehrson
+; (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+; (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+
+; This code is released under the libpng license.
+; For conditions of distribution and use, see the disclaimer
+; and license in png.inc
+
+; png_info is a structure that holds the information in a PNG file so
+; that the application can find out the characteristics of the image.
+; If you are reading the file, this structure will tell you what is
+; in the PNG file. If you are writing the file, fill in the information
+; you want to put into the PNG file, using png_set_*() functions, then
+; call png_write_info().
+
+; The names chosen should be very close to the PNG specification, so
+; consult that document for information about the meaning of each field.
+
+; With libpng < 0.95, it was only possible to directly set and read the
+; the values in the png_info_struct, which meant that the contents and
+; order of the values had to remain fixed. With libpng 0.95 and later,
+; however, there are now functions that abstract the contents of
+; png_info_struct from the application, so this makes it easier to use
+; libpng with dynamic libraries, and even makes it possible to use
+; libraries that don't have all of the libpng ancillary chunk-handing
+; functionality. In libpng-1.5.0 this was moved into a separate private
+; file that is not visible to applications.
+
+; The following members may have allocated storage attached that should be
+; cleaned up before the structure is discarded: palette, trans, text,
+; pcal_purpose, pcal_units, pcal_params, hist, iccp_name, iccp_profile,
+; splt_palettes, scal_unit, row_pointers, and unknowns. By default, these
+; are automatically freed when the info structure is deallocated, if they were
+; allocated internally by libpng. This behavior can be changed by means
+; of the png_data_freer() function.
+
+; More allocation details: all the chunk-reading functions that
+; change these members go through the corresponding png_set_*
+; functions. A function to clear these members is available: see
+; png_free_data(). The png_set_* functions do not depend on being
+; able to point info structure members to any of the storage they are
+; passed (they make their own copies), EXCEPT that the png_set_text
+; functions use the same storage passed to them in the text_ptr or
+; itxt_ptr structure argument, and the png_set_rows and png_set_unknowns
+; functions do not make their own copies.
+
+
+struct png_info_def
+ ; The following are necessary for every PNG file
+ width dd ? ;uint_32 ;width of image in pixels (from IHDR)
+ height dd ? ;uint_32 ;height of image in pixels (from IHDR)
+ valid dd ? ;uint_32 ;valid chunk data (see PNG_INFO_ below)
+ rowbytes dd ? ;png_size_t ;bytes needed to hold an untransformed row
+ palette dd ? ;png_colorp ; array of color values (valid & PNG_INFO_PLTE)
+ num_palette dw ? ;uint_16 ;number of color entries in "palette" (PLTE)
+ num_trans dw ? ;uint_16 ;number of transparent palette color (tRNS)
+ bit_depth db ? ;byte ;1, 2, 4, 8, or 16 bits/channel (from IHDR)
+ color_type db ? ;byte ;see PNG_COLOR_TYPE_ below (from IHDR)
+ ; The following three should have been named *_method not *_type
+ compression_type db ? ;byte ;must be PNG_COMPRESSION_TYPE_BASE (IHDR)
+ filter_type db ? ;byte ;must be PNG_FILTER_TYPE_BASE (from IHDR)
+ interlace_type db ? ;byte ;One of PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7
+
+ ; The following are set by png_set_IHDR, called from the application on
+ ; write, but the are never actually used by the write code.
+
+ channels db ? ;byte ;number of data channels per pixel (1, 2, 3, 4)
+ pixel_depth db ? ;byte ;number of bits per pixel
+ spare_byte db ? ;byte ;to align the data, and for future use
+
+if PNG_READ_SUPPORTED eq 1
+ ; This is never set during write
+ signature db 8 ;byte[8] ;magic bytes read by libpng from start of file
+end if
+
+ ; The rest of the data is optional. If you are reading, check the
+ ; valid field to see if the information in these are valid. If you
+ ; are writing, set the valid field to those chunks you want written,
+ ; and initialize the appropriate fields below.
+
+
+if (PNG_COLORSPACE_SUPPORTED eq 1) | (PNG_GAMMA_SUPPORTED eq 1)
+ ; png_colorspace only contains 'flags' if neither GAMMA or COLORSPACE are
+ ; defined. When COLORSPACE is switched on all the colorspace-defining
+ ; chunks should be enabled, when GAMMA is switched on all the gamma-defining
+ ; chunks should be enabled. If this is not done it becomes possible to read
+ ; inconsistent PNG files and assign a probably incorrect interpretation to
+ ; the information. (In other words, by carefully choosing which chunks to
+ ; recognize the system configuration can select an interpretation for PNG
+ ; files containing ambiguous data and this will result in inconsistent
+ ; behavior between different libpng builds!)
+
+ colorspace png_colorspace
+end if
+
+if PNG_iCCP_SUPPORTED eq 1
+ ; iCCP chunk data.
+ iccp_name dd ? ;charp ;profile name
+ iccp_profile dd ? ;bytep ;International Color Consortium profile data
+ iccp_proflen dd ? ;uint_32 ;ICC profile data length
+end if
+
+if PNG_TEXT_SUPPORTED eq 1
+ ; The tEXt, and zTXt chunks contain human-readable textual data in
+ ; uncompressed, compressed, and optionally compressed forms, respectively.
+ ; The data in "text" is an array of pointers to uncompressed,
+ ; null-terminated C strings. Each chunk has a keyword that describes the
+ ; textual data contained in that chunk. Keywords are not required to be
+ ; unique, and the text string may be empty. Any number of text chunks may
+ ; be in an image.
+
+ num_text dd ? ;int ;number of comments read or comments to write
+ max_text dd ? ;int ;current size of text array
+ text dd ? ;png_textp ;array of comments read or comments to write
+end if ;TEXT
+
+if PNG_tIME_SUPPORTED eq 1
+ ; The tIME chunk holds the last time the displayed image data was
+ ; modified. See the png_time struct for the contents of this struct.
+
+ mod_time png_time
+end if
+
+if PNG_sBIT_SUPPORTED eq 1
+ ; The sBIT chunk specifies the number of significant high-order bits
+ ; in the pixel data. Values are in the range [1, bit_depth], and are
+ ; only specified for the channels in the pixel data. The contents of
+ ; the low-order bits is not specified. Data is valid if
+ ; (valid & PNG_INFO_sBIT) is non-zero.
+
+ sig_bit png_color_8 ; significant bits in color channels
+end if
+
+if (PNG_tRNS_SUPPORTED eq 1) | (PNG_READ_EXPAND_SUPPORTED eq 1) | (PNG_READ_BACKGROUND_SUPPORTED eq 1)
+ ; The tRNS chunk supplies transparency data for paletted images and
+ ; other image types that don't need a full alpha channel. There are
+ ; "num_trans" transparency values for a paletted image, stored in the
+ ; same order as the palette colors, starting from index 0. Values
+ ; for the data are in the range [0, 255], ranging from fully transparent
+ ; to fully opaque, respectively. For non-paletted images, there is a
+ ; single color specified that should be treated as fully transparent.
+ ; Data is valid if (valid & PNG_INFO_tRNS) is non-zero.
+
+ trans_alpha dd ? ;bytep ; alpha values for paletted image
+ trans_color png_color_16 ;transparent color for non-palette image
+end if
+
+if (PNG_bKGD_SUPPORTED eq 1) | (PNG_READ_BACKGROUND_SUPPORTED eq 1)
+ ; The bKGD chunk gives the suggested image background color if the
+ ; display program does not have its own background color and the image
+ ; is needs to composited onto a background before display. The colors
+ ; in "background" are normally in the same color space/depth as the
+ ; pixel data. Data is valid if (valid & PNG_INFO_bKGD) is non-zero.
+
+ background png_color_16
+end if
+
+if PNG_oFFs_SUPPORTED eq 1
+ ; The oFFs chunk gives the offset in "offset_unit_type" units rightwards
+ ; and downwards from the top-left corner of the display, page, or other
+ ; application-specific co-ordinate space. See the PNG_OFFSET_ defines
+ ; below for the unit types. Valid if (valid & PNG_INFO_oFFs) non-zero.
+
+ x_offset dd ? ;int_32 ;x offset on page
+ y_offset dd ? ;int_32 ;y offset on page
+ offset_unit_type db ? ;byte ;offset units type
+end if
+
+if PNG_pHYs_SUPPORTED eq 1
+ ; The pHYs chunk gives the physical pixel density of the image for
+ ; display or printing in "phys_unit_type" units (see PNG_RESOLUTION_
+ ; defines below). Data is valid if (valid & PNG_INFO_pHYs) is non-zero.
+
+ x_pixels_per_unit dd ? ;uint_32 ;horizontal pixel density
+ y_pixels_per_unit dd ? ;uint_32 ;vertical pixel density
+ phys_unit_type db ? ;byte ;resolution type (see PNG_RESOLUTION_ below)
+end if
+
+if PNG_hIST_SUPPORTED eq 1
+ ; The hIST chunk contains the relative frequency or importance of the
+ ; various palette entries, so that a viewer can intelligently select a
+ ; reduced-color palette, if required. Data is an array of "num_palette"
+ ; values in the range [0,65535]. Data valid if (valid & PNG_INFO_hIST)
+ ; is non-zero.
+
+ hist dd ? ;uint_16p
+end if
+
+if PNG_pCAL_SUPPORTED eq 1
+ ; The pCAL chunk describes a transformation between the stored pixel
+ ; values and original physical data values used to create the image.
+ ; The integer range [0, 2^bit_depth - 1] maps to the floating-point
+ ; range given by [pcal_X0, pcal_X1], and are further transformed by a
+ ; (possibly non-linear) transformation function given by "pcal_type"
+ ; and "pcal_params" into "pcal_units". Please see the PNG_EQUATION_
+ ; defines below, and the PNG-Group's PNG extensions document for a
+ ; complete description of the transformations and how they should be
+ ; implemented, and for a description of the ASCII parameter strings.
+ ; Data values are valid if (valid & PNG_INFO_pCAL) non-zero.
+
+ pcal_purpose dd ? ;charp ;pCAL chunk description string
+ pcal_X0 dd ? ;int_32 ;minimum value
+ pcal_X1 dd ? ;int_32 ;maximum value
+ pcal_units dd ? ;charp ;Latin-1 string giving physical units
+ pcal_params dd ? ;charpp ;ASCII strings containing parameter values
+ pcal_type db ? ;byte ;equation type (see PNG_EQUATION_ below)
+ pcal_nparams db ? ;byte ;number of parameters given in pcal_params
+end if
+
+; New members added in libpng-1.0.6
+ free_me dd ? ;uint_32 ;flags items libpng is responsible for freeing
+
+if PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED eq 1
+ ; Storage for unknown chunks that the library doesn't recognize.
+ unknown_chunks dd ? ;png_unknown_chunkp
+
+ ; The type of this field is limited by the type of
+ ; png_struct::user_chunk_cache_max, else overflow can occur.
+
+ unknown_chunks_num dd ? ;int
+end if
+
+if PNG_sPLT_SUPPORTED eq 1
+ ; Data on sPLT chunks (there may be more than one).
+ splt_palettes dd ? ;png_sPLT_tp
+ splt_palettes_num dd ? ;int ;Match type returned by png_get API
+end if
+
+if PNG_sCAL_SUPPORTED eq 1
+ ; The sCAL chunk describes the actual physical dimensions of the
+ ; subject matter of the graphic. The chunk contains a unit specification
+ ; a byte value, and two ASCII strings representing floating-point
+ ; values. The values are width and height corresponsing to one pixel
+ ; in the image. Data values are valid if (valid & PNG_INFO_sCAL) is
+ ; non-zero.
+
+ scal_unit db ? ;byte ;unit of physical scale
+ scal_s_width dd ? ;charp ;string containing height
+ scal_s_height dd ? ;charp ;string containing width
+end if
+
+if PNG_INFO_IMAGE_SUPPORTED eq 1
+ ; Memory has been allocated if (valid & PNG_ALLOCATED_INFO_ROWS)
+ ; non-zero
+ ; Data valid if (valid & PNG_INFO_IDAT) non-zero
+ row_pointers dd ? ;bytepp ;the image bits
+end if
+
+ends
diff --git a/programs/develop/libraries/libs-dev/libimg/png/libpng/pnglibconf.inc b/programs/develop/libraries/libs-dev/libimg/png/libpng/pnglibconf.inc
index 4af1feb99..da4e459a9 100644
--- a/programs/develop/libraries/libs-dev/libimg/png/libpng/pnglibconf.inc
+++ b/programs/develop/libraries/libs-dev/libimg/png/libpng/pnglibconf.inc
@@ -1,209 +1,209 @@
-; libpng 1.6.25 STANDARD API DEFINITION
-
-; pnglibconf.inc - library build configuration
-
-; Libpng version 1.6.25 - September 1, 2016
-
-; Copyright (c) 1998-2015 Glenn Randers-Pehrson
-
-; This code is released under the libpng license.
-; For conditions of distribution and use, see the disclaimer
-; and license in png.inc
-
-; pnglibconf.inc
-; Machine generated file: DO NOT EDIT
-; Derived from: scripts/pnglibconf.dfa
-
-; options
-PNG_16BIT_SUPPORTED equ 1
-PNG_ALIGNED_MEMORY_SUPPORTED equ 1
-;/*#undef PNG_ARM_NEON_API_SUPPORTED*/
-;/*#undef PNG_ARM_NEON_CHECK_SUPPORTED*/
-PNG_BENIGN_ERRORS_SUPPORTED equ 1
-PNG_BENIGN_READ_ERRORS_SUPPORTED equ 1
-;/*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/
-PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED equ 1
-PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED equ 1
-PNG_COLORSPACE_SUPPORTED equ 1
-PNG_CONSOLE_IO_SUPPORTED equ 1
-PNG_CONVERT_tIME_SUPPORTED equ 1
-PNG_EASY_ACCESS_SUPPORTED equ 1
-;/*#undef PNG_ERROR_NUMBERS_SUPPORTED*/
-PNG_ERROR_TEXT_SUPPORTED equ 1
-PNG_FIXED_POINT_SUPPORTED equ 1
-PNG_FLOATING_ARITHMETIC_SUPPORTED equ 1
-PNG_FLOATING_POINT_SUPPORTED equ 1
-PNG_FORMAT_AFIRST_SUPPORTED equ 1
-PNG_FORMAT_BGR_SUPPORTED equ 1
-PNG_GAMMA_SUPPORTED equ 1
-PNG_GET_PALETTE_MAX_SUPPORTED equ 1
-PNG_HANDLE_AS_UNKNOWN_SUPPORTED equ 1
-PNG_INCH_CONVERSIONS_SUPPORTED equ 1
-PNG_INFO_IMAGE_SUPPORTED equ 1
-PNG_IO_STATE_SUPPORTED equ 1
-PNG_MNG_FEATURES_SUPPORTED equ 0
-PNG_POINTER_INDEXING_SUPPORTED equ 1
-PNG_PROGRESSIVE_READ_SUPPORTED equ 0
-PNG_READ_16BIT_SUPPORTED equ 0
-PNG_READ_ALPHA_MODE_SUPPORTED equ 0
-PNG_READ_ANCILLARY_CHUNKS_SUPPORTED equ 0
-PNG_READ_BACKGROUND_SUPPORTED equ 0
-PNG_READ_BGR_SUPPORTED equ 0
-PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED equ 0
-PNG_READ_COMPOSITE_NODIV_SUPPORTED equ 0
-PNG_READ_COMPRESSED_TEXT_SUPPORTED equ 0
-PNG_READ_EXPAND_16_SUPPORTED equ 0
-PNG_READ_EXPAND_SUPPORTED equ 0
-PNG_READ_FILLER_SUPPORTED equ 0
-PNG_READ_GAMMA_SUPPORTED equ 0
-PNG_READ_GET_PALETTE_MAX_SUPPORTED equ 0
-PNG_READ_GRAY_TO_RGB_SUPPORTED equ 0
-PNG_READ_INTERLACING_SUPPORTED equ 0
-PNG_READ_INT_FUNCTIONS_SUPPORTED equ 0
-PNG_READ_INVERT_ALPHA_SUPPORTED equ 0
-PNG_READ_INVERT_SUPPORTED equ 0
-PNG_READ_OPT_PLTE_SUPPORTED equ 0
-PNG_READ_PACKSWAP_SUPPORTED equ 0
-PNG_READ_PACK_SUPPORTED equ 0
-PNG_READ_QUANTIZE_SUPPORTED equ 0
-PNG_READ_RGB_TO_GRAY_SUPPORTED equ 0
-PNG_READ_SCALE_16_TO_8_SUPPORTED equ 0
-PNG_READ_SHIFT_SUPPORTED equ 0
-PNG_READ_STRIP_16_TO_8_SUPPORTED equ 0
-PNG_READ_STRIP_ALPHA_SUPPORTED equ 0
-PNG_READ_SUPPORTED equ 0
-PNG_READ_SWAP_ALPHA_SUPPORTED equ 0
-PNG_READ_SWAP_SUPPORTED equ 0
-PNG_READ_TEXT_SUPPORTED equ 0
-PNG_READ_TRANSFORMS_SUPPORTED equ 0
-PNG_READ_UNKNOWN_CHUNKS_SUPPORTED equ 0
-PNG_READ_USER_CHUNKS_SUPPORTED equ 0
-PNG_READ_USER_TRANSFORM_SUPPORTED equ 0
-PNG_READ_bKGD_SUPPORTED equ 0
-PNG_READ_cHRM_SUPPORTED equ 0
-PNG_READ_gAMA_SUPPORTED equ 0
-PNG_READ_hIST_SUPPORTED equ 0
-PNG_READ_iCCP_SUPPORTED equ 0
-PNG_READ_iTXt_SUPPORTED equ 0
-PNG_READ_oFFs_SUPPORTED equ 0
-PNG_READ_pCAL_SUPPORTED equ 0
-PNG_READ_pHYs_SUPPORTED equ 0
-PNG_READ_sBIT_SUPPORTED equ 0
-PNG_READ_sCAL_SUPPORTED equ 0
-PNG_READ_sPLT_SUPPORTED equ 0
-PNG_READ_sRGB_SUPPORTED equ 0
-PNG_READ_tEXt_SUPPORTED equ 0
-PNG_READ_tIME_SUPPORTED equ 0
-PNG_READ_tRNS_SUPPORTED equ 0
-PNG_READ_zTXt_SUPPORTED equ 0
-PNG_SAVE_INT_32_SUPPORTED equ 1
-PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED equ 1
-PNG_SEQUENTIAL_READ_SUPPORTED equ 1
-PNG_SETJMP_SUPPORTED equ 0 ;1 ;setjmp.h — заголовочный файл стандартной библиотеки языка Си
-PNG_SET_OPTION_SUPPORTED equ 1
-PNG_SET_UNKNOWN_CHUNKS_SUPPORTED equ 1
-PNG_SET_USER_LIMITS_SUPPORTED equ 1
-PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED equ 1
-PNG_SIMPLIFIED_READ_BGR_SUPPORTED equ 1
-PNG_SIMPLIFIED_READ_SUPPORTED equ 1
-PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED equ 1
-PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED equ 1
-PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED equ 0 ;1
-PNG_SIMPLIFIED_WRITE_SUPPORTED equ 1
-PNG_STDIO_SUPPORTED equ 1
-PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED equ 1
-PNG_TEXT_SUPPORTED equ 0
-PNG_TIME_RFC1123_SUPPORTED equ 1
-PNG_UNKNOWN_CHUNKS_SUPPORTED equ 1
-PNG_USER_CHUNKS_SUPPORTED equ 1
-PNG_USER_LIMITS_SUPPORTED equ 1
-PNG_USER_MEM_SUPPORTED equ 1
-PNG_USER_TRANSFORM_INFO_SUPPORTED equ 1
-PNG_USER_TRANSFORM_PTR_SUPPORTED equ 1
-PNG_WARNINGS_SUPPORTED equ 0
-PNG_WRITE_16BIT_SUPPORTED equ 1
-PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED equ 1
-PNG_WRITE_BGR_SUPPORTED equ 1
-PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED equ 1
-PNG_WRITE_COMPRESSED_TEXT_SUPPORTED equ 1
-PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED equ 1
-PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED equ 0
-PNG_WRITE_FILLER_SUPPORTED equ 1
-PNG_WRITE_FILTER_SUPPORTED equ 1
-PNG_WRITE_FLUSH_SUPPORTED equ 1
-PNG_WRITE_GET_PALETTE_MAX_SUPPORTED equ 1
-PNG_WRITE_INTERLACING_SUPPORTED equ 0
-PNG_WRITE_INT_FUNCTIONS_SUPPORTED equ 1
-PNG_WRITE_INVERT_ALPHA_SUPPORTED equ 1
-PNG_WRITE_INVERT_SUPPORTED equ 1
-PNG_WRITE_OPTIMIZE_CMF_SUPPORTED equ 1
-PNG_WRITE_PACKSWAP_SUPPORTED equ 1
-PNG_WRITE_PACK_SUPPORTED equ 1
-PNG_WRITE_SHIFT_SUPPORTED equ 1
-PNG_WRITE_SUPPORTED equ 1
-PNG_WRITE_SWAP_ALPHA_SUPPORTED equ 1
-PNG_WRITE_SWAP_SUPPORTED equ 1
-PNG_WRITE_TEXT_SUPPORTED equ 0
-PNG_WRITE_TRANSFORMS_SUPPORTED equ 1
-PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED equ 0
-PNG_WRITE_USER_TRANSFORM_SUPPORTED equ 1
-PNG_WRITE_WEIGHTED_FILTER_SUPPORTED equ 1
-PNG_WRITE_bKGD_SUPPORTED equ 0
-PNG_WRITE_cHRM_SUPPORTED equ 0
-PNG_WRITE_gAMA_SUPPORTED equ 0
-PNG_WRITE_hIST_SUPPORTED equ 0
-PNG_WRITE_iCCP_SUPPORTED equ 0
-PNG_WRITE_iTXt_SUPPORTED equ 0
-PNG_WRITE_oFFs_SUPPORTED equ 0
-PNG_WRITE_pCAL_SUPPORTED equ 0
-PNG_WRITE_pHYs_SUPPORTED equ 0
-PNG_WRITE_sBIT_SUPPORTED equ 0
-PNG_WRITE_sCAL_SUPPORTED equ 0
-PNG_WRITE_sPLT_SUPPORTED equ 0
-PNG_WRITE_sRGB_SUPPORTED equ 0
-PNG_WRITE_tEXt_SUPPORTED equ 0
-PNG_WRITE_tIME_SUPPORTED equ 0
-PNG_WRITE_tRNS_SUPPORTED equ 0
-PNG_WRITE_zTXt_SUPPORTED equ 0
-PNG_bKGD_SUPPORTED equ 0
-PNG_cHRM_SUPPORTED equ 0
-PNG_gAMA_SUPPORTED equ 0
-PNG_hIST_SUPPORTED equ 0
-PNG_iCCP_SUPPORTED equ 0
-PNG_iTXt_SUPPORTED equ 0
-PNG_oFFs_SUPPORTED equ 0
-PNG_pCAL_SUPPORTED equ 0
-PNG_pHYs_SUPPORTED equ 0
-PNG_sBIT_SUPPORTED equ 0
-PNG_sCAL_SUPPORTED equ 0
-PNG_sPLT_SUPPORTED equ 0
-PNG_sRGB_SUPPORTED equ 0
-PNG_tEXt_SUPPORTED equ 0
-PNG_tIME_SUPPORTED equ 0
-PNG_tRNS_SUPPORTED equ 0
-PNG_zTXt_SUPPORTED equ 0
-; end of options
-; settings
-PNG_API_RULE equ 0
-PNG_DEFAULT_READ_MACROS equ 1
-PNG_GAMMA_THRESHOLD_FIXED equ 5000
-PNG_ZBUF_SIZE equ 8192
-PNG_IDAT_READ_SIZE equ PNG_ZBUF_SIZE
-PNG_INFLATE_BUF_SIZE equ 1024
-PNG_MAX_GAMMA_8 equ 11
-PNG_QUANTIZE_BLUE_BITS equ 5
-PNG_QUANTIZE_GREEN_BITS equ 5
-PNG_QUANTIZE_RED_BITS equ 5
-PNG_TEXT_Z_DEFAULT_COMPRESSION equ (-1)
-PNG_TEXT_Z_DEFAULT_STRATEGY equ 0
-PNG_USER_CHUNK_CACHE_MAX equ 1000
-PNG_USER_CHUNK_MALLOC_MAX equ 8000000
-PNG_USER_HEIGHT_MAX equ 1000000
-PNG_USER_WIDTH_MAX equ 1000000
-PNG_ZLIB_VERNUM equ 0 ;unknown
-PNG_Z_DEFAULT_COMPRESSION equ (-1)
-PNG_Z_DEFAULT_NOFILTER_STRATEGY equ 0
-PNG_Z_DEFAULT_STRATEGY equ 1
-PNG_sCAL_PRECISION equ 5
-PNG_sRGB_PROFILE_CHECKS equ 2
-; end of settings
+; libpng 1.6.25 STANDARD API DEFINITION
+
+; pnglibconf.inc - library build configuration
+
+; Libpng version 1.6.25 - September 1, 2016
+
+; Copyright (c) 1998-2015 Glenn Randers-Pehrson
+
+; This code is released under the libpng license.
+; For conditions of distribution and use, see the disclaimer
+; and license in png.inc
+
+; pnglibconf.inc
+; Machine generated file: DO NOT EDIT
+; Derived from: scripts/pnglibconf.dfa
+
+; options
+PNG_16BIT_SUPPORTED equ 1
+PNG_ALIGNED_MEMORY_SUPPORTED equ 1
+;/*#undef PNG_ARM_NEON_API_SUPPORTED*/
+;/*#undef PNG_ARM_NEON_CHECK_SUPPORTED*/
+PNG_BENIGN_ERRORS_SUPPORTED equ 1
+PNG_BENIGN_READ_ERRORS_SUPPORTED equ 1
+;/*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/
+PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED equ 1
+PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED equ 1
+PNG_COLORSPACE_SUPPORTED equ 1
+PNG_CONSOLE_IO_SUPPORTED equ 1
+PNG_CONVERT_tIME_SUPPORTED equ 1
+PNG_EASY_ACCESS_SUPPORTED equ 1
+;/*#undef PNG_ERROR_NUMBERS_SUPPORTED*/
+PNG_ERROR_TEXT_SUPPORTED equ 1
+PNG_FIXED_POINT_SUPPORTED equ 1
+PNG_FLOATING_ARITHMETIC_SUPPORTED equ 1
+PNG_FLOATING_POINT_SUPPORTED equ 1
+PNG_FORMAT_AFIRST_SUPPORTED equ 1
+PNG_FORMAT_BGR_SUPPORTED equ 1
+PNG_GAMMA_SUPPORTED equ 1
+PNG_GET_PALETTE_MAX_SUPPORTED equ 1
+PNG_HANDLE_AS_UNKNOWN_SUPPORTED equ 1
+PNG_INCH_CONVERSIONS_SUPPORTED equ 1
+PNG_INFO_IMAGE_SUPPORTED equ 1
+PNG_IO_STATE_SUPPORTED equ 1
+PNG_MNG_FEATURES_SUPPORTED equ 0
+PNG_POINTER_INDEXING_SUPPORTED equ 1
+PNG_PROGRESSIVE_READ_SUPPORTED equ 0
+PNG_READ_16BIT_SUPPORTED equ 0
+PNG_READ_ALPHA_MODE_SUPPORTED equ 0
+PNG_READ_ANCILLARY_CHUNKS_SUPPORTED equ 0
+PNG_READ_BACKGROUND_SUPPORTED equ 0
+PNG_READ_BGR_SUPPORTED equ 0
+PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED equ 0
+PNG_READ_COMPOSITE_NODIV_SUPPORTED equ 0
+PNG_READ_COMPRESSED_TEXT_SUPPORTED equ 0
+PNG_READ_EXPAND_16_SUPPORTED equ 0
+PNG_READ_EXPAND_SUPPORTED equ 0
+PNG_READ_FILLER_SUPPORTED equ 0
+PNG_READ_GAMMA_SUPPORTED equ 0
+PNG_READ_GET_PALETTE_MAX_SUPPORTED equ 0
+PNG_READ_GRAY_TO_RGB_SUPPORTED equ 0
+PNG_READ_INTERLACING_SUPPORTED equ 0
+PNG_READ_INT_FUNCTIONS_SUPPORTED equ 0
+PNG_READ_INVERT_ALPHA_SUPPORTED equ 0
+PNG_READ_INVERT_SUPPORTED equ 0
+PNG_READ_OPT_PLTE_SUPPORTED equ 0
+PNG_READ_PACKSWAP_SUPPORTED equ 0
+PNG_READ_PACK_SUPPORTED equ 0
+PNG_READ_QUANTIZE_SUPPORTED equ 0
+PNG_READ_RGB_TO_GRAY_SUPPORTED equ 0
+PNG_READ_SCALE_16_TO_8_SUPPORTED equ 0
+PNG_READ_SHIFT_SUPPORTED equ 0
+PNG_READ_STRIP_16_TO_8_SUPPORTED equ 0
+PNG_READ_STRIP_ALPHA_SUPPORTED equ 0
+PNG_READ_SUPPORTED equ 0
+PNG_READ_SWAP_ALPHA_SUPPORTED equ 0
+PNG_READ_SWAP_SUPPORTED equ 0
+PNG_READ_TEXT_SUPPORTED equ 0
+PNG_READ_TRANSFORMS_SUPPORTED equ 0
+PNG_READ_UNKNOWN_CHUNKS_SUPPORTED equ 0
+PNG_READ_USER_CHUNKS_SUPPORTED equ 0
+PNG_READ_USER_TRANSFORM_SUPPORTED equ 0
+PNG_READ_bKGD_SUPPORTED equ 0
+PNG_READ_cHRM_SUPPORTED equ 0
+PNG_READ_gAMA_SUPPORTED equ 0
+PNG_READ_hIST_SUPPORTED equ 0
+PNG_READ_iCCP_SUPPORTED equ 0
+PNG_READ_iTXt_SUPPORTED equ 0
+PNG_READ_oFFs_SUPPORTED equ 0
+PNG_READ_pCAL_SUPPORTED equ 0
+PNG_READ_pHYs_SUPPORTED equ 0
+PNG_READ_sBIT_SUPPORTED equ 0
+PNG_READ_sCAL_SUPPORTED equ 0
+PNG_READ_sPLT_SUPPORTED equ 0
+PNG_READ_sRGB_SUPPORTED equ 0
+PNG_READ_tEXt_SUPPORTED equ 0
+PNG_READ_tIME_SUPPORTED equ 0
+PNG_READ_tRNS_SUPPORTED equ 0
+PNG_READ_zTXt_SUPPORTED equ 0
+PNG_SAVE_INT_32_SUPPORTED equ 1
+PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED equ 1
+PNG_SEQUENTIAL_READ_SUPPORTED equ 1
+PNG_SETJMP_SUPPORTED equ 0 ;1 ;setjmp.h — заголовочный файл стандартной библиотеки языка Си
+PNG_SET_OPTION_SUPPORTED equ 1
+PNG_SET_UNKNOWN_CHUNKS_SUPPORTED equ 1
+PNG_SET_USER_LIMITS_SUPPORTED equ 1
+PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED equ 1
+PNG_SIMPLIFIED_READ_BGR_SUPPORTED equ 1
+PNG_SIMPLIFIED_READ_SUPPORTED equ 1
+PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED equ 1
+PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED equ 1
+PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED equ 0 ;1
+PNG_SIMPLIFIED_WRITE_SUPPORTED equ 1
+PNG_STDIO_SUPPORTED equ 1
+PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED equ 1
+PNG_TEXT_SUPPORTED equ 0
+PNG_TIME_RFC1123_SUPPORTED equ 1
+PNG_UNKNOWN_CHUNKS_SUPPORTED equ 1
+PNG_USER_CHUNKS_SUPPORTED equ 1
+PNG_USER_LIMITS_SUPPORTED equ 1
+PNG_USER_MEM_SUPPORTED equ 1
+PNG_USER_TRANSFORM_INFO_SUPPORTED equ 1
+PNG_USER_TRANSFORM_PTR_SUPPORTED equ 1
+PNG_WARNINGS_SUPPORTED equ 0
+PNG_WRITE_16BIT_SUPPORTED equ 1
+PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED equ 1
+PNG_WRITE_BGR_SUPPORTED equ 1
+PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED equ 1
+PNG_WRITE_COMPRESSED_TEXT_SUPPORTED equ 1
+PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED equ 1
+PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED equ 0
+PNG_WRITE_FILLER_SUPPORTED equ 1
+PNG_WRITE_FILTER_SUPPORTED equ 1
+PNG_WRITE_FLUSH_SUPPORTED equ 1
+PNG_WRITE_GET_PALETTE_MAX_SUPPORTED equ 1
+PNG_WRITE_INTERLACING_SUPPORTED equ 0
+PNG_WRITE_INT_FUNCTIONS_SUPPORTED equ 1
+PNG_WRITE_INVERT_ALPHA_SUPPORTED equ 1
+PNG_WRITE_INVERT_SUPPORTED equ 1
+PNG_WRITE_OPTIMIZE_CMF_SUPPORTED equ 1
+PNG_WRITE_PACKSWAP_SUPPORTED equ 1
+PNG_WRITE_PACK_SUPPORTED equ 1
+PNG_WRITE_SHIFT_SUPPORTED equ 1
+PNG_WRITE_SUPPORTED equ 1
+PNG_WRITE_SWAP_ALPHA_SUPPORTED equ 1
+PNG_WRITE_SWAP_SUPPORTED equ 1
+PNG_WRITE_TEXT_SUPPORTED equ 0
+PNG_WRITE_TRANSFORMS_SUPPORTED equ 1
+PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED equ 0
+PNG_WRITE_USER_TRANSFORM_SUPPORTED equ 1
+PNG_WRITE_WEIGHTED_FILTER_SUPPORTED equ 1
+PNG_WRITE_bKGD_SUPPORTED equ 0
+PNG_WRITE_cHRM_SUPPORTED equ 0
+PNG_WRITE_gAMA_SUPPORTED equ 0
+PNG_WRITE_hIST_SUPPORTED equ 0
+PNG_WRITE_iCCP_SUPPORTED equ 0
+PNG_WRITE_iTXt_SUPPORTED equ 0
+PNG_WRITE_oFFs_SUPPORTED equ 0
+PNG_WRITE_pCAL_SUPPORTED equ 0
+PNG_WRITE_pHYs_SUPPORTED equ 0
+PNG_WRITE_sBIT_SUPPORTED equ 0
+PNG_WRITE_sCAL_SUPPORTED equ 0
+PNG_WRITE_sPLT_SUPPORTED equ 0
+PNG_WRITE_sRGB_SUPPORTED equ 0
+PNG_WRITE_tEXt_SUPPORTED equ 0
+PNG_WRITE_tIME_SUPPORTED equ 0
+PNG_WRITE_tRNS_SUPPORTED equ 0
+PNG_WRITE_zTXt_SUPPORTED equ 0
+PNG_bKGD_SUPPORTED equ 0
+PNG_cHRM_SUPPORTED equ 0
+PNG_gAMA_SUPPORTED equ 0
+PNG_hIST_SUPPORTED equ 0
+PNG_iCCP_SUPPORTED equ 0
+PNG_iTXt_SUPPORTED equ 0
+PNG_oFFs_SUPPORTED equ 0
+PNG_pCAL_SUPPORTED equ 0
+PNG_pHYs_SUPPORTED equ 0
+PNG_sBIT_SUPPORTED equ 0
+PNG_sCAL_SUPPORTED equ 0
+PNG_sPLT_SUPPORTED equ 0
+PNG_sRGB_SUPPORTED equ 0
+PNG_tEXt_SUPPORTED equ 0
+PNG_tIME_SUPPORTED equ 0
+PNG_tRNS_SUPPORTED equ 0
+PNG_zTXt_SUPPORTED equ 0
+; end of options
+; settings
+PNG_API_RULE equ 0
+PNG_DEFAULT_READ_MACROS equ 1
+PNG_GAMMA_THRESHOLD_FIXED equ 5000
+PNG_ZBUF_SIZE equ 8192
+PNG_IDAT_READ_SIZE equ PNG_ZBUF_SIZE
+PNG_INFLATE_BUF_SIZE equ 1024
+PNG_MAX_GAMMA_8 equ 11
+PNG_QUANTIZE_BLUE_BITS equ 5
+PNG_QUANTIZE_GREEN_BITS equ 5
+PNG_QUANTIZE_RED_BITS equ 5
+PNG_TEXT_Z_DEFAULT_COMPRESSION equ (-1)
+PNG_TEXT_Z_DEFAULT_STRATEGY equ 0
+PNG_USER_CHUNK_CACHE_MAX equ 1000
+PNG_USER_CHUNK_MALLOC_MAX equ 8000000
+PNG_USER_HEIGHT_MAX equ 1000000
+PNG_USER_WIDTH_MAX equ 1000000
+PNG_ZLIB_VERNUM equ 0 ;unknown
+PNG_Z_DEFAULT_COMPRESSION equ (-1)
+PNG_Z_DEFAULT_NOFILTER_STRATEGY equ 0
+PNG_Z_DEFAULT_STRATEGY equ 1
+PNG_sCAL_PRECISION equ 5
+PNG_sRGB_PROFILE_CHECKS equ 2
+; end of settings
diff --git a/programs/develop/libraries/libs-dev/libimg/png/libpng/pngmem.asm b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngmem.asm
index e49f53608..f2a1b3163 100644
--- a/programs/develop/libraries/libs-dev/libimg/png/libpng/pngmem.asm
+++ b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngmem.asm
@@ -1,303 +1,303 @@
-
-; pngmem.asm - stub functions for memory allocation
-
-; Last changed in libpng 1.6.24 [August 4, 2016%]
-; Copyright (c) 1998-2002,2004,2006-2014,2016 Glenn Randers-Pehrson
-; (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
-; (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
-
-; This code is released under the libpng license.
-; For conditions of distribution and use, see the disclaimer
-; and license in png.inc
-
-; This file provides a location for all memory allocation. Users who
-; need special memory handling are expected to supply replacement
-; functions for png_malloc() and png_free(), and to use
-; png_create_read_struct_2() and png_create_write_struct_2() to
-; identify the replacement functions.
-
-; Free a png_struct
-;void (png_structrp png_ptr)
-align 4
-proc png_destroy_png_struct uses eax ecx edi esi, png_ptr:dword
-locals
- dummy_struct png_struct
-endl
- mov edi,[png_ptr]
- cmp edi,0
- je @f ;if (..!=0)
- ; png_free might call png_error and may certainly call
- ; png_get_mem_ptr, so fake a temporary png_struct to support this.
-
- mov ecx,sizeof.png_struct
- mov esi,edi
- mov edi,ebp
- sub edi,ecx
- rep movsb ;dummy_struct = *png_ptr
- mov edi,[png_ptr]
- xor eax,eax
- mov ecx,sizeof.png_struct
- rep stosb ;memset(png_ptr, 0, (sizeof *png_ptr))
- mov esi,ebp
- sub esi,sizeof.png_struct
- stdcall png_free, esi, [png_ptr]
-
-if PNG_SETJMP_SUPPORTED eq 1
- ; We may have a jmp_buf left to deallocate.
- stdcall png_free_jmpbuf, esi
-end if
- @@:
- ret
-endp
-
-; Allocate memory. For reasonable files, size should never exceed
-; 64K. However, zlib may allocate more than 64K if you don't tell
-; it not to. See zconf.h and png.h for more information. zlib does
-; need to allocate exactly 64K, so whatever you call here must
-; have the ability to do that.
-
-;voidp (const_structrp png_ptr, png_alloc_size_t size)
-align 4
-proc png_calloc uses ebx ecx edi, png_ptr:dword, size:dword
- stdcall png_malloc, [png_ptr], [size]
-
- cmp eax,0
- je @f ;if (..!=0)
- mov ebx,eax
- mov edi,eax
- mov ecx,[size]
- xor eax,eax
- rep stosb ;memset(ret, 0, size)
- mov eax,ebx
- @@:
- ret
-endp
-
-; png_malloc_base, an internal function added at libpng 1.6.0, does the work of
-; allocating memory, taking into account limits and PNG_USER_MEM_SUPPORTED.
-; Checking and error handling must happen outside this routine; it returns NULL
-; if the allocation cannot be done (for any reason.)
-
-;voidp (const_structrp png_ptr, png_alloc_size_t size)
-align 4
-proc png_malloc_base uses ebx ecx, png_ptr:dword, size:dword
- ; Moved to png_malloc_base from png_malloc_default in 1.6.0; the DOS
- ; allocators have also been removed in 1.6.0, so any 16-bit system now has
- ; to implement a user memory handler. This checks to be sure it isn't
- ; called with big numbers.
-
- ; Some compilers complain that this is always true. However, it
- ; can be false when integer overflow happens.
-
- cmp dword[size],0
- jle .end0
- cmp dword[size],PNG_SIZE_MAX
- jg .end0 ; if (..>.. && ..<=..)
-if PNG_MAX_MALLOC_64K eq 1
- cmp dword[size],65536
- jg .end0
-end if
-if PNG_USER_MEM_SUPPORTED eq 1
- mov ebx,[png_ptr]
- cmp ebx,0
- je @f
- cmp dword[ebx+png_struct.malloc_fn],0
- je @f ;if (..!=0 && ..!=0)
- stdcall [ebx+png_struct.malloc_fn], ebx, [size]
- jmp .end_f
- @@: ;else
-end if
- ;stdcall [mem.alloc], [size]
- mcall SF_SYS_MISC, SSF_MEM_ALLOC, [size]
- jmp .end_f ;checked for truncation above
- .end0: ;else
- xor eax,eax
-.end_f:
- ret
-endp
-
-; This is really here only to work round a spurious warning in GCC 4.6 and 4.7
-; that arises because of the checks in png_realloc_array that are repeated in
-; png_malloc_array.
-
-;voidp (const_structrp png_ptr, int nelements, size_t element_size)
-align 4
-proc png_malloc_array_checked, png_ptr:dword, nelements:dword, element_size:dword
-; png_alloc_size_t req = nelements; /* known to be > 0 */
-
-; if (req <= PNG_SIZE_MAX/element_size)
-; return png_malloc_base(png_ptr, req * element_size);
-
- ; The failure case when the request is too large
- xor eax,eax
-.end_f:
- ret
-endp
-
-;voidp (const_structrp png_ptr, int nelements, size_t element_size)
-align 4
-proc png_malloc_array, png_ptr:dword, nelements:dword, element_size:dword
-; if (nelements <= 0 || element_size == 0)
-; png_error(png_ptr, "internal error: array alloc");
-
- stdcall png_malloc_array_checked, [png_ptr], [nelements], [element_size]
- ret
-endp
-
-;voidp (const_structrp png_ptr, const_voidp old_array,
-; int old_elements, int add_elements, size_t element_size)
-align 4
-proc png_realloc_array, png_ptr:dword, old_array:dword, old_elements:dword, add_elements:dword, element_size:dword
- ; These are internal errors:
-; if (add_elements <= 0 || element_size == 0 || old_elements < 0 ||
-; (old_array == NULL && old_elements > 0))
-; png_error(png_ptr, "internal error: array realloc");
-
- ; Check for overflow on the elements count (so the caller does not have to
- ; check.)
-
-; if (add_elements <= INT_MAX - old_elements)
-; {
-; voidp new_array = png_malloc_array_checked(png_ptr,
-; old_elements+add_elements, element_size);
-;
-; if (new_array != NULL)
-; {
- ; Because png_malloc_array worked the size calculations below cannot
- ; overflow.
-
-; if (old_elements > 0)
-; memcpy(new_array, old_array, element_size*(unsigned)old_elements);
-;
-; memset((char*)new_array + element_size*(unsigned)old_elements, 0,
-; element_size*(unsigned)add_elements);
-;
-; return new_array;
-; }
-; }
-
- xor eax,eax ;error
-.end_f:
- ret
-endp
-
-; Various functions that have different error handling are derived from this.
-; png_malloc always exists, but if PNG_USER_MEM_SUPPORTED is defined a separate
-; function png_malloc_default is also provided.
-
-;voidp (const_structrp png_ptr, png_alloc_size_t size)
-align 4
-proc png_malloc uses edi, png_ptr:dword, size:dword
- xor eax,eax
- mov edi,[png_ptr]
- cmp edi,0
- je @f ;if (..==0) return 0
-
- stdcall png_malloc_base, edi, [size]
-
- cmp eax,0
- jne @f ;if (..==0)
- png_error edi, 'Out of memory' ;'m' means png_malloc
- @@:
- ret
-endp
-
-;voidp (const_structrp png_ptr, png_alloc_size_t size)
-align 4
-proc png_malloc_default uses edi, png_ptr:dword, size:dword
- xor eax,eax
- mov edi,[png_ptr]
- cmp edi,0
- je @f ;if (..==0) return 0
-
- ; Passing 'NULL' here bypasses the application provided memory handler.
- stdcall png_malloc_base, 0, [size] ;0 - use malloc
-
- cmp eax,0
- jne @f ;if (..==0)
- png_error edi, 'Out of Memory' ;'M' means png_malloc_default
- @@:
- ret
-endp
-
-; This function was added at libpng version 1.2.3. The png_malloc_warn()
-; function will issue a png_warning and return NULL instead of issuing a
-; png_error, if it fails to allocate the requested memory.
-
-;voidp (const_structrp png_ptr, png_alloc_size_t size)
-align 4
-proc png_malloc_warn uses edi, png_ptr:dword, size:dword
- mov edi,[png_ptr]
- cmp edi,0
- je .end0 ;if (..!=0)
- stdcall png_malloc_base, edi, [size]
- cmp eax,0
- jne .end_f ;if (..!=0) return ret
-
- png_warning edi, 'Out of memory'
- .end0:
- xor eax,eax
-.end_f:
- ret
-endp
-
-; Free a pointer allocated by png_malloc(). If ptr is NULL, return
-; without taking any action.
-
-;void (const_structrp png_ptr, voidp ptr)
-align 4
-proc png_free uses eax ebx ecx, png_ptr:dword, p2ptr:dword
- mov ebx,[png_ptr]
- cmp ebx,0
- je .end_f
- mov ecx,[p2ptr]
- cmp ecx,0
- je .end_f ;if (..==0 || ..==0) return
-
-if PNG_USER_MEM_SUPPORTED eq 1
- cmp dword[ebx+png_struct.free_fn],0
- je @f ;if (..!=0)
- stdcall dword[ebx+png_struct.free_fn], ebx, [p2ptr]
- jmp .end_f
- @@: ;else
-end if
- mcall SF_SYS_MISC, SSF_MEM_FREE, [p2ptr]
-.end_f:
- ret
-endp
-
-; This function is called when the application wants to use another method
-; of allocating and freeing memory.
-
-;void (png_structrp png_ptr, voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn)
-align 4
-proc png_set_mem_fn uses eax edi, png_ptr:dword, mem_ptr:dword, malloc_fn:dword, free_fn:dword
- mov edi,[png_ptr]
- cmp edi,0
- je @f ;if (..!=0)
- mov eax,[mem_ptr]
- mov [edi+png_struct.mem_ptr],eax
- mov eax,[malloc_fn]
- mov [edi+png_struct.malloc_fn],eax
- mov eax,[free_fn]
- mov [edi+png_struct.free_fn],eax
- @@:
- ret
-endp
-
-; This function returns a pointer to the mem_ptr associated with the user
-; functions. The application should free any memory associated with this
-; pointer before png_write_destroy and png_read_destroy are called.
-
-;voidp (const_structrp png_ptr)
-align 4
-proc png_get_mem_ptr uses edi, png_ptr:dword
- xor eax,eax
- mov edi,[png_ptr]
- cmp edi,0
- je @f ;if (..==0) return 0
- mov eax,[edi+png_struct.mem_ptr]
- @@:
- ret
-endp
-
+
+; pngmem.asm - stub functions for memory allocation
+
+; Last changed in libpng 1.6.24 [August 4, 2016%]
+; Copyright (c) 1998-2002,2004,2006-2014,2016 Glenn Randers-Pehrson
+; (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+; (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+
+; This code is released under the libpng license.
+; For conditions of distribution and use, see the disclaimer
+; and license in png.inc
+
+; This file provides a location for all memory allocation. Users who
+; need special memory handling are expected to supply replacement
+; functions for png_malloc() and png_free(), and to use
+; png_create_read_struct_2() and png_create_write_struct_2() to
+; identify the replacement functions.
+
+; Free a png_struct
+;void (png_structrp png_ptr)
+align 4
+proc png_destroy_png_struct uses eax ecx edi esi, png_ptr:dword
+locals
+ dummy_struct png_struct
+endl
+ mov edi,[png_ptr]
+ cmp edi,0
+ je @f ;if (..!=0)
+ ; png_free might call png_error and may certainly call
+ ; png_get_mem_ptr, so fake a temporary png_struct to support this.
+
+ mov ecx,sizeof.png_struct
+ mov esi,edi
+ mov edi,ebp
+ sub edi,ecx
+ rep movsb ;dummy_struct = *png_ptr
+ mov edi,[png_ptr]
+ xor eax,eax
+ mov ecx,sizeof.png_struct
+ rep stosb ;memset(png_ptr, 0, (sizeof *png_ptr))
+ mov esi,ebp
+ sub esi,sizeof.png_struct
+ stdcall png_free, esi, [png_ptr]
+
+if PNG_SETJMP_SUPPORTED eq 1
+ ; We may have a jmp_buf left to deallocate.
+ stdcall png_free_jmpbuf, esi
+end if
+ @@:
+ ret
+endp
+
+; Allocate memory. For reasonable files, size should never exceed
+; 64K. However, zlib may allocate more than 64K if you don't tell
+; it not to. See zconf.h and png.h for more information. zlib does
+; need to allocate exactly 64K, so whatever you call here must
+; have the ability to do that.
+
+;voidp (const_structrp png_ptr, png_alloc_size_t size)
+align 4
+proc png_calloc uses ebx ecx edi, png_ptr:dword, size:dword
+ stdcall png_malloc, [png_ptr], [size]
+
+ cmp eax,0
+ je @f ;if (..!=0)
+ mov ebx,eax
+ mov edi,eax
+ mov ecx,[size]
+ xor eax,eax
+ rep stosb ;memset(ret, 0, size)
+ mov eax,ebx
+ @@:
+ ret
+endp
+
+; png_malloc_base, an internal function added at libpng 1.6.0, does the work of
+; allocating memory, taking into account limits and PNG_USER_MEM_SUPPORTED.
+; Checking and error handling must happen outside this routine; it returns NULL
+; if the allocation cannot be done (for any reason.)
+
+;voidp (const_structrp png_ptr, png_alloc_size_t size)
+align 4
+proc png_malloc_base uses ebx ecx, png_ptr:dword, size:dword
+ ; Moved to png_malloc_base from png_malloc_default in 1.6.0; the DOS
+ ; allocators have also been removed in 1.6.0, so any 16-bit system now has
+ ; to implement a user memory handler. This checks to be sure it isn't
+ ; called with big numbers.
+
+ ; Some compilers complain that this is always true. However, it
+ ; can be false when integer overflow happens.
+
+ cmp dword[size],0
+ jle .end0
+ cmp dword[size],PNG_SIZE_MAX
+ jg .end0 ; if (..>.. && ..<=..)
+if PNG_MAX_MALLOC_64K eq 1
+ cmp dword[size],65536
+ jg .end0
+end if
+if PNG_USER_MEM_SUPPORTED eq 1
+ mov ebx,[png_ptr]
+ cmp ebx,0
+ je @f
+ cmp dword[ebx+png_struct.malloc_fn],0
+ je @f ;if (..!=0 && ..!=0)
+ stdcall [ebx+png_struct.malloc_fn], ebx, [size]
+ jmp .end_f
+ @@: ;else
+end if
+ ;stdcall [mem.alloc], [size]
+ mcall SF_SYS_MISC, SSF_MEM_ALLOC, [size]
+ jmp .end_f ;checked for truncation above
+ .end0: ;else
+ xor eax,eax
+.end_f:
+ ret
+endp
+
+; This is really here only to work round a spurious warning in GCC 4.6 and 4.7
+; that arises because of the checks in png_realloc_array that are repeated in
+; png_malloc_array.
+
+;voidp (const_structrp png_ptr, int nelements, size_t element_size)
+align 4
+proc png_malloc_array_checked, png_ptr:dword, nelements:dword, element_size:dword
+; png_alloc_size_t req = nelements; /* known to be > 0 */
+
+; if (req <= PNG_SIZE_MAX/element_size)
+; return png_malloc_base(png_ptr, req * element_size);
+
+ ; The failure case when the request is too large
+ xor eax,eax
+.end_f:
+ ret
+endp
+
+;voidp (const_structrp png_ptr, int nelements, size_t element_size)
+align 4
+proc png_malloc_array, png_ptr:dword, nelements:dword, element_size:dword
+; if (nelements <= 0 || element_size == 0)
+; png_error(png_ptr, "internal error: array alloc");
+
+ stdcall png_malloc_array_checked, [png_ptr], [nelements], [element_size]
+ ret
+endp
+
+;voidp (const_structrp png_ptr, const_voidp old_array,
+; int old_elements, int add_elements, size_t element_size)
+align 4
+proc png_realloc_array, png_ptr:dword, old_array:dword, old_elements:dword, add_elements:dword, element_size:dword
+ ; These are internal errors:
+; if (add_elements <= 0 || element_size == 0 || old_elements < 0 ||
+; (old_array == NULL && old_elements > 0))
+; png_error(png_ptr, "internal error: array realloc");
+
+ ; Check for overflow on the elements count (so the caller does not have to
+ ; check.)
+
+; if (add_elements <= INT_MAX - old_elements)
+; {
+; voidp new_array = png_malloc_array_checked(png_ptr,
+; old_elements+add_elements, element_size);
+;
+; if (new_array != NULL)
+; {
+ ; Because png_malloc_array worked the size calculations below cannot
+ ; overflow.
+
+; if (old_elements > 0)
+; memcpy(new_array, old_array, element_size*(unsigned)old_elements);
+;
+; memset((char*)new_array + element_size*(unsigned)old_elements, 0,
+; element_size*(unsigned)add_elements);
+;
+; return new_array;
+; }
+; }
+
+ xor eax,eax ;error
+.end_f:
+ ret
+endp
+
+; Various functions that have different error handling are derived from this.
+; png_malloc always exists, but if PNG_USER_MEM_SUPPORTED is defined a separate
+; function png_malloc_default is also provided.
+
+;voidp (const_structrp png_ptr, png_alloc_size_t size)
+align 4
+proc png_malloc uses edi, png_ptr:dword, size:dword
+ xor eax,eax
+ mov edi,[png_ptr]
+ cmp edi,0
+ je @f ;if (..==0) return 0
+
+ stdcall png_malloc_base, edi, [size]
+
+ cmp eax,0
+ jne @f ;if (..==0)
+ png_error edi, 'Out of memory' ;'m' means png_malloc
+ @@:
+ ret
+endp
+
+;voidp (const_structrp png_ptr, png_alloc_size_t size)
+align 4
+proc png_malloc_default uses edi, png_ptr:dword, size:dword
+ xor eax,eax
+ mov edi,[png_ptr]
+ cmp edi,0
+ je @f ;if (..==0) return 0
+
+ ; Passing 'NULL' here bypasses the application provided memory handler.
+ stdcall png_malloc_base, 0, [size] ;0 - use malloc
+
+ cmp eax,0
+ jne @f ;if (..==0)
+ png_error edi, 'Out of Memory' ;'M' means png_malloc_default
+ @@:
+ ret
+endp
+
+; This function was added at libpng version 1.2.3. The png_malloc_warn()
+; function will issue a png_warning and return NULL instead of issuing a
+; png_error, if it fails to allocate the requested memory.
+
+;voidp (const_structrp png_ptr, png_alloc_size_t size)
+align 4
+proc png_malloc_warn uses edi, png_ptr:dword, size:dword
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end0 ;if (..!=0)
+ stdcall png_malloc_base, edi, [size]
+ cmp eax,0
+ jne .end_f ;if (..!=0) return ret
+
+ png_warning edi, 'Out of memory'
+ .end0:
+ xor eax,eax
+.end_f:
+ ret
+endp
+
+; Free a pointer allocated by png_malloc(). If ptr is NULL, return
+; without taking any action.
+
+;void (const_structrp png_ptr, voidp ptr)
+align 4
+proc png_free uses eax ebx ecx, png_ptr:dword, p2ptr:dword
+ mov ebx,[png_ptr]
+ cmp ebx,0
+ je .end_f
+ mov ecx,[p2ptr]
+ cmp ecx,0
+ je .end_f ;if (..==0 || ..==0) return
+
+if PNG_USER_MEM_SUPPORTED eq 1
+ cmp dword[ebx+png_struct.free_fn],0
+ je @f ;if (..!=0)
+ stdcall dword[ebx+png_struct.free_fn], ebx, [p2ptr]
+ jmp .end_f
+ @@: ;else
+end if
+ mcall SF_SYS_MISC, SSF_MEM_FREE, [p2ptr]
+.end_f:
+ ret
+endp
+
+; This function is called when the application wants to use another method
+; of allocating and freeing memory.
+
+;void (png_structrp png_ptr, voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn)
+align 4
+proc png_set_mem_fn uses eax edi, png_ptr:dword, mem_ptr:dword, malloc_fn:dword, free_fn:dword
+ mov edi,[png_ptr]
+ cmp edi,0
+ je @f ;if (..!=0)
+ mov eax,[mem_ptr]
+ mov [edi+png_struct.mem_ptr],eax
+ mov eax,[malloc_fn]
+ mov [edi+png_struct.malloc_fn],eax
+ mov eax,[free_fn]
+ mov [edi+png_struct.free_fn],eax
+ @@:
+ ret
+endp
+
+; This function returns a pointer to the mem_ptr associated with the user
+; functions. The application should free any memory associated with this
+; pointer before png_write_destroy and png_read_destroy are called.
+
+;voidp (const_structrp png_ptr)
+align 4
+proc png_get_mem_ptr uses edi, png_ptr:dword
+ xor eax,eax
+ mov edi,[png_ptr]
+ cmp edi,0
+ je @f ;if (..==0) return 0
+ mov eax,[edi+png_struct.mem_ptr]
+ @@:
+ ret
+endp
+
diff --git a/programs/develop/libraries/libs-dev/libimg/png/libpng/pngpriv.inc b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngpriv.inc
index 0e76add99..41e888b81 100644
--- a/programs/develop/libraries/libs-dev/libimg/png/libpng/pngpriv.inc
+++ b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngpriv.inc
@@ -1,306 +1,306 @@
-;
-; Options
-;
-
-PNG_RELEASE_BUILD equ 1
-
-;---
-; Various modes of operation. Note that after an init, mode is set to
-; zero automatically when the structure is created. Three of these
-; are defined in png.inc because they need to be visible to applications
-; that call png_set_unknown_chunk().
-
-;PNG_HAVE_IHDR 0x01 (defined in png.inc)
-;PNG_HAVE_PLTE 0x02 (defined in png.inc)
-PNG_HAVE_IDAT equ 0x04
-;PNG_AFTER_IDAT 0x08 (defined in png.inc)
-PNG_HAVE_IEND equ 0x10
- ;0x20 (unused)
- ;0x40 (unused)
- ;0x80 (unused)
-PNG_HAVE_CHUNK_HEADER equ 0x100
-PNG_WROTE_tIME equ 0x200
-PNG_WROTE_INFO_BEFORE_PLTE equ 0x400
-PNG_BACKGROUND_IS_GRAY equ 0x800
-PNG_HAVE_PNG_SIGNATURE equ 0x1000
-PNG_HAVE_CHUNK_AFTER_IDAT equ 0x2000 ;Have another chunk after IDAT
- ;0x4000 (unused)
-PNG_IS_READ_STRUCT equ 0x8000 ;Else is a write struct
-
-; Flags for the transformations the PNG library does on the image data
-PNG_BGR equ 0x0001
-PNG_INTERLACE equ 0x0002
-PNG_PACK equ 0x0004
-PNG_SHIFT equ 0x0008
-PNG_SWAP_BYTES equ 0x0010
-PNG_INVERT_MONO equ 0x0020
-PNG_QUANTIZE equ 0x0040
-PNG_COMPOSE equ 0x0080 ;Was PNG_BACKGROUND
-PNG_BACKGROUND_EXPAND equ 0x0100
-PNG_EXPAND_16 equ 0x0200 ;Added to libpng 1.5.2
-PNG_16_TO_8 equ 0x0400 ;Becomes 'chop' in 1.5.4
-PNG_RGBA equ 0x0800
-PNG_EXPAND equ 0x1000
-PNG_GAMMA equ 0x2000
-PNG_GRAY_TO_RGB equ 0x4000
-PNG_FILLER equ 0x8000
-PNG_PACKSWAP equ 0x10000
-PNG_SWAP_ALPHA equ 0x20000
-PNG_STRIP_ALPHA equ 0x40000
-PNG_INVERT_ALPHA equ 0x80000
-PNG_USER_TRANSFORM equ 0x100000
-PNG_RGB_TO_GRAY_ERR equ 0x200000
-PNG_RGB_TO_GRAY_WARN equ 0x400000
-PNG_RGB_TO_GRAY equ 0x600000 ;two bits, RGB_TO_GRAY_ERR|WARN
-PNG_ENCODE_ALPHA equ 0x800000 ;Added to libpng-1.5.4
-PNG_ADD_ALPHA equ 0x1000000 ;Added to libpng-1.2.7
-PNG_EXPAND_tRNS equ 0x2000000 ;Added to libpng-1.2.9
-PNG_SCALE_16_TO_8 equ 0x4000000 ;Added to libpng-1.5.4
- ;0x8000000 unused
- ;0x10000000 unused
- ;0x20000000 unused
- ;0x40000000 unused
-; Flags for png_create_struct
-PNG_STRUCT_PNG equ 0x0001
-PNG_STRUCT_INFO equ 0x0002
-
-; Flags for the png_ptr->flags rather than declaring a byte for each one
-PNG_FLAG_ZLIB_CUSTOM_STRATEGY equ 0x0001
-PNG_FLAG_ZSTREAM_INITIALIZED equ 0x0002 ;Added to libpng-1.6.0
- ;0x0004 unused
-PNG_FLAG_ZSTREAM_ENDED equ 0x0008 ;Added to libpng-1.6.0
- ;0x0010 unused
- ;0x0020 unused
-PNG_FLAG_ROW_INIT equ 0x0040
-PNG_FLAG_FILLER_AFTER equ 0x0080
-PNG_FLAG_CRC_ANCILLARY_USE equ 0x0100
-PNG_FLAG_CRC_ANCILLARY_NOWARN equ 0x0200
-PNG_FLAG_CRC_CRITICAL_USE equ 0x0400
-PNG_FLAG_CRC_CRITICAL_IGNORE equ 0x0800
-PNG_FLAG_ASSUME_sRGB equ 0x1000 ;Added to libpng-1.5.4
-PNG_FLAG_OPTIMIZE_ALPHA equ 0x2000 ;Added to libpng-1.5.4
-PNG_FLAG_DETECT_UNINITIALIZED equ 0x4000 ;Added to libpng-1.5.4
-;PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000
-;PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000
-PNG_FLAG_LIBRARY_MISMATCH equ 0x20000
-PNG_FLAG_STRIP_ERROR_NUMBERS equ 0x40000
-PNG_FLAG_STRIP_ERROR_TEXT equ 0x80000
-PNG_FLAG_BENIGN_ERRORS_WARN equ 0x100000 ;Added to libpng-1.4.0
-PNG_FLAG_APP_WARNINGS_WARN equ 0x200000 ;Added to libpng-1.6.0
-PNG_FLAG_APP_ERRORS_WARN equ 0x400000 ;Added to libpng-1.6.0
-
-; Gamma values (new at libpng-1.5.4):
-PNG_GAMMA_MAC_OLD equ 151724 ;Assume '1.8' is really 2.2/1.45!
-PNG_GAMMA_MAC_INVERSE equ 65909
-PNG_GAMMA_sRGB_INVERSE equ 45455
-
-macro PNG_ROWBYTES pixel_bits, width
-{
-local .end0
-if pixel_bits eq eax
-else
- mov eax,pixel_bits
-end if
- cmp eax,8
- jge .end0
- add eax,7
- .end0:
- shr eax,3
- imul eax,width
-}
-
-; In 1.7.0 the definitions will be made public in png.inc to avoid having to
-; duplicate the same definitions in application code.
-
-png_IDAT equ 'IDAT'
-png_IEND equ 'IEND'
-png_IHDR equ 'IHDR'
-png_PLTE equ 'PLTE'
-png_bKGD equ 'bKGD'
-png_cHRM equ 'cHRM'
-png_fRAc equ 'fRAc' ;registered, not defined
-png_gAMA equ 'gAMA'
-png_gIFg equ 'gIFg'
-png_gIFt equ 'gIFt' ;deprecated
-png_gIFx equ 'gIFx'
-png_hIST equ 'hIST'
-png_iCCP equ 'iCCP'
-png_iTXt equ 'iTXt'
-png_oFFs equ 'oFFs'
-png_pCAL equ 'pCAL'
-png_pHYs equ 'pHYs'
-png_sBIT equ 'sBIT'
-png_sCAL equ 'sCAL'
-png_sPLT equ 'sPLT'
-png_sRGB equ 'sRGB'
-png_sTER equ 'sTER'
-png_tEXt equ 'tEXt'
-png_tIME equ 'tIME'
-png_tRNS equ 'tRNS'
-png_zTXt equ 'zTXt'
-
-;Test on flag values as defined in the spec (section 5.4):
-macro PNG_CHUNK_ANCILLARY c
-{
- mov eax,c
- shr eax,29
- and eax,1
-}
-macro PNG_CHUNK_CRITICAL c
-{
- PNG_CHUNK_ANCILLARY c
- xor eax,1
-}
-macro PNG_CHUNK_PRIVATE c
-{
- mov eax,c
- shr eax,21
- and eax,1
-}
-macro PNG_CHUNK_RESERVED c
-{
- mov eax,c
- shr eax,13
- and eax,1
-}
-macro PNG_CHUNK_SAFE_TO_COPY c
-{
- mov eax,c
- shr eax,5
- and eax,1
-}
-
-PNG_FLAG_CRC_ANCILLARY_MASK equ (PNG_FLAG_CRC_ANCILLARY_USE or PNG_FLAG_CRC_ANCILLARY_NOWARN)
-PNG_FLAG_CRC_CRITICAL_MASK equ (PNG_FLAG_CRC_CRITICAL_USE or PNG_FLAG_CRC_CRITICAL_IGNORE)
-PNG_FLAG_CRC_MASK equ (PNG_FLAG_CRC_ANCILLARY_MASK or PNG_FLAG_CRC_CRITICAL_MASK)
-
-macro PNG_sRGB_FROM_LINEAR linear
-{
- mov eax,linear
- shr eax,15
- shl eax,1
- add eax,png_sRGB_base
- movzx eax,word[eax]
-push ebx ecx
- mov ebx,linear
- shr ebx,15
- add ebx,png_sRGB_delta
- mov ecx,linear
- and ecx,0x7fff
- imul ecx,ebx
- shr ecx,12
- add eax,ecx
-pop ecx ebx
- shr eax,8
- ;;;and eax,0xff
-}
-; Given a value 'linear' in the range 0..255*65535 calculate the 8-bit sRGB
-; encoded value with maximum error 0.646365. Note that the input is not a
-; 16-bit value; it has been multiplied by 255!
-
-PNG_UNEXPECTED_ZLIB_RETURN equ (-7)
-
-;...
-
-; Suggested size for a number buffer (enough for 64 bits and a sign!)
-PNG_NUMBER_BUFFER_SIZE equ 24
-
-; These are the integer formats currently supported, the name is formed from
-; the standard printf(3) format string.
-
-PNG_NUMBER_FORMAT_u equ 1 ;chose unsigned API!
-PNG_NUMBER_FORMAT_02u equ 2
-PNG_NUMBER_FORMAT_d equ 1 ;chose signed API!
-PNG_NUMBER_FORMAT_02d equ 2
-PNG_NUMBER_FORMAT_x equ 3
-PNG_NUMBER_FORMAT_02x equ 4
-PNG_NUMBER_FORMAT_fixed equ 5 ;choose the signed API
-
-; New defines and members adding in libpng-1.5.4
-PNG_WARNING_PARAMETER_SIZE equ 32
-PNG_WARNING_PARAMETER_COUNT equ 8 ;Maximum 9; see pngerror.asm
-
-PNG_CHUNK_WARNING equ 0 ;never an error
-PNG_CHUNK_WRITE_ERROR equ 1 ;an error only on write
-PNG_CHUNK_ERROR equ 2 ;always an error
-
-; ASCII to FP interfaces, currently only implemented if sCAL
-; support is required.
-
-; MAX_DIGITS is actually the maximum number of characters in an sCAL
-; width or height, derived from the precision (number of significant
-; digits - a build time settable option) and assumptions about the
-; maximum ridiculous exponent.
-
-PNG_sCAL_MAX_DIGITS equ PNG_sCAL_PRECISION+1+1+10 ;. E exponent
-
-; An internal API to validate the format of a floating point number.
-; The result is the index of the next character. If the number is
-; not valid it will be the index of a character in the supposed number.
-
-; The format of a number is defined in the PNG extensions specification
-; and this API is strictly conformant to that spec, not anyone elses!
-
-; The format as a regular expression is:
-
-; [+-]?[0-9]+.?([Ee][+-]?[0-9]+)?
-
-; or:
-
-; [+-]?.[0-9]+(.[0-9]+)?([Ee][+-]?[0-9]+)?
-
-; The complexity is that either integer or fraction must be present and the
-; fraction is permitted to have no digits only if the integer is present.
-
-; NOTE: The dangling E problem.
-; There is a PNG valid floating point number in the following:
-
-; PNG floating point numbers are not greedy.
-
-; Working this out requires *TWO* character lookahead (because of the
-; sign), the parser does not do this - it will fail at the 'r' - this
-; doesn't matter for PNG sCAL chunk values, but it requires more care
-; if the value were ever to be embedded in something more complex. Use
-; ANSI-C strtod if you need the lookahead.
-
-; State table for the parser.
-PNG_FP_INTEGER equ 0 ;before or in integer
-PNG_FP_FRACTION equ 1 ;before or in fraction
-PNG_FP_EXPONENT equ 2 ;before or in exponent
-PNG_FP_STATE equ 3 ;mask for the above
-PNG_FP_SAW_SIGN equ 4 ;Saw +/- in current state
-PNG_FP_SAW_DIGIT equ 8 ;Saw a digit in current state
-PNG_FP_SAW_DOT equ 16 ;Saw a dot in current state
-PNG_FP_SAW_E equ 32 ;Saw an E (or e) in current state
-PNG_FP_SAW_ANY equ 60 ;Saw any of the above 4
-
-; These three values don't affect the parser. They are set but not used.
-
-PNG_FP_WAS_VALID equ 64 ;Preceding substring is a valid fp number
-PNG_FP_NEGATIVE equ 128 ;A negative number, including "-0"
-PNG_FP_NONZERO equ 256 ;A non-zero value
-PNG_FP_STICKY equ 448 ;The above three flags
-
-; This is available for the caller to store in 'state' if required. Do not
-; call the parser after setting it (the parser sometimes clears it.)
-
-PNG_FP_INVALID equ 512 ;Available for callers as a distinct value
-
-; Result codes for the parser (boolean - true meants ok, false means
-; not ok yet.)
-
-PNG_FP_MAYBE equ 0 ;The number may be valid in the future
-PNG_FP_OK equ 1 ;The number is valid
-
-; The internal structure that png_image::opaque points to.
-struct png_control
- png_ptr dd ? ;png_structp
- info_ptr dd ? ;png_infop
- error_buf dd ? ;voidp ;Always a jmp_buf at present.
-
- memory dd ? ;bytep ;Memory buffer.
- size dd ? ;png_size_t ;Size of the memory buffer.
-
- for_write dd ? ;uint ;:1;Otherwise it is a read structure
- owned_file dd ? ;uint ;:1;We own the file in io_ptr
-ends
+;
+; Options
+;
+
+PNG_RELEASE_BUILD equ 1
+
+;---
+; Various modes of operation. Note that after an init, mode is set to
+; zero automatically when the structure is created. Three of these
+; are defined in png.inc because they need to be visible to applications
+; that call png_set_unknown_chunk().
+
+;PNG_HAVE_IHDR 0x01 (defined in png.inc)
+;PNG_HAVE_PLTE 0x02 (defined in png.inc)
+PNG_HAVE_IDAT equ 0x04
+;PNG_AFTER_IDAT 0x08 (defined in png.inc)
+PNG_HAVE_IEND equ 0x10
+ ;0x20 (unused)
+ ;0x40 (unused)
+ ;0x80 (unused)
+PNG_HAVE_CHUNK_HEADER equ 0x100
+PNG_WROTE_tIME equ 0x200
+PNG_WROTE_INFO_BEFORE_PLTE equ 0x400
+PNG_BACKGROUND_IS_GRAY equ 0x800
+PNG_HAVE_PNG_SIGNATURE equ 0x1000
+PNG_HAVE_CHUNK_AFTER_IDAT equ 0x2000 ;Have another chunk after IDAT
+ ;0x4000 (unused)
+PNG_IS_READ_STRUCT equ 0x8000 ;Else is a write struct
+
+; Flags for the transformations the PNG library does on the image data
+PNG_BGR equ 0x0001
+PNG_INTERLACE equ 0x0002
+PNG_PACK equ 0x0004
+PNG_SHIFT equ 0x0008
+PNG_SWAP_BYTES equ 0x0010
+PNG_INVERT_MONO equ 0x0020
+PNG_QUANTIZE equ 0x0040
+PNG_COMPOSE equ 0x0080 ;Was PNG_BACKGROUND
+PNG_BACKGROUND_EXPAND equ 0x0100
+PNG_EXPAND_16 equ 0x0200 ;Added to libpng 1.5.2
+PNG_16_TO_8 equ 0x0400 ;Becomes 'chop' in 1.5.4
+PNG_RGBA equ 0x0800
+PNG_EXPAND equ 0x1000
+PNG_GAMMA equ 0x2000
+PNG_GRAY_TO_RGB equ 0x4000
+PNG_FILLER equ 0x8000
+PNG_PACKSWAP equ 0x10000
+PNG_SWAP_ALPHA equ 0x20000
+PNG_STRIP_ALPHA equ 0x40000
+PNG_INVERT_ALPHA equ 0x80000
+PNG_USER_TRANSFORM equ 0x100000
+PNG_RGB_TO_GRAY_ERR equ 0x200000
+PNG_RGB_TO_GRAY_WARN equ 0x400000
+PNG_RGB_TO_GRAY equ 0x600000 ;two bits, RGB_TO_GRAY_ERR|WARN
+PNG_ENCODE_ALPHA equ 0x800000 ;Added to libpng-1.5.4
+PNG_ADD_ALPHA equ 0x1000000 ;Added to libpng-1.2.7
+PNG_EXPAND_tRNS equ 0x2000000 ;Added to libpng-1.2.9
+PNG_SCALE_16_TO_8 equ 0x4000000 ;Added to libpng-1.5.4
+ ;0x8000000 unused
+ ;0x10000000 unused
+ ;0x20000000 unused
+ ;0x40000000 unused
+; Flags for png_create_struct
+PNG_STRUCT_PNG equ 0x0001
+PNG_STRUCT_INFO equ 0x0002
+
+; Flags for the png_ptr->flags rather than declaring a byte for each one
+PNG_FLAG_ZLIB_CUSTOM_STRATEGY equ 0x0001
+PNG_FLAG_ZSTREAM_INITIALIZED equ 0x0002 ;Added to libpng-1.6.0
+ ;0x0004 unused
+PNG_FLAG_ZSTREAM_ENDED equ 0x0008 ;Added to libpng-1.6.0
+ ;0x0010 unused
+ ;0x0020 unused
+PNG_FLAG_ROW_INIT equ 0x0040
+PNG_FLAG_FILLER_AFTER equ 0x0080
+PNG_FLAG_CRC_ANCILLARY_USE equ 0x0100
+PNG_FLAG_CRC_ANCILLARY_NOWARN equ 0x0200
+PNG_FLAG_CRC_CRITICAL_USE equ 0x0400
+PNG_FLAG_CRC_CRITICAL_IGNORE equ 0x0800
+PNG_FLAG_ASSUME_sRGB equ 0x1000 ;Added to libpng-1.5.4
+PNG_FLAG_OPTIMIZE_ALPHA equ 0x2000 ;Added to libpng-1.5.4
+PNG_FLAG_DETECT_UNINITIALIZED equ 0x4000 ;Added to libpng-1.5.4
+;PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000
+;PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000
+PNG_FLAG_LIBRARY_MISMATCH equ 0x20000
+PNG_FLAG_STRIP_ERROR_NUMBERS equ 0x40000
+PNG_FLAG_STRIP_ERROR_TEXT equ 0x80000
+PNG_FLAG_BENIGN_ERRORS_WARN equ 0x100000 ;Added to libpng-1.4.0
+PNG_FLAG_APP_WARNINGS_WARN equ 0x200000 ;Added to libpng-1.6.0
+PNG_FLAG_APP_ERRORS_WARN equ 0x400000 ;Added to libpng-1.6.0
+
+; Gamma values (new at libpng-1.5.4):
+PNG_GAMMA_MAC_OLD equ 151724 ;Assume '1.8' is really 2.2/1.45!
+PNG_GAMMA_MAC_INVERSE equ 65909
+PNG_GAMMA_sRGB_INVERSE equ 45455
+
+macro PNG_ROWBYTES pixel_bits, width
+{
+local .end0
+if pixel_bits eq eax
+else
+ mov eax,pixel_bits
+end if
+ cmp eax,8
+ jge .end0
+ add eax,7
+ .end0:
+ shr eax,3
+ imul eax,width
+}
+
+; In 1.7.0 the definitions will be made public in png.inc to avoid having to
+; duplicate the same definitions in application code.
+
+png_IDAT equ 'IDAT'
+png_IEND equ 'IEND'
+png_IHDR equ 'IHDR'
+png_PLTE equ 'PLTE'
+png_bKGD equ 'bKGD'
+png_cHRM equ 'cHRM'
+png_fRAc equ 'fRAc' ;registered, not defined
+png_gAMA equ 'gAMA'
+png_gIFg equ 'gIFg'
+png_gIFt equ 'gIFt' ;deprecated
+png_gIFx equ 'gIFx'
+png_hIST equ 'hIST'
+png_iCCP equ 'iCCP'
+png_iTXt equ 'iTXt'
+png_oFFs equ 'oFFs'
+png_pCAL equ 'pCAL'
+png_pHYs equ 'pHYs'
+png_sBIT equ 'sBIT'
+png_sCAL equ 'sCAL'
+png_sPLT equ 'sPLT'
+png_sRGB equ 'sRGB'
+png_sTER equ 'sTER'
+png_tEXt equ 'tEXt'
+png_tIME equ 'tIME'
+png_tRNS equ 'tRNS'
+png_zTXt equ 'zTXt'
+
+;Test on flag values as defined in the spec (section 5.4):
+macro PNG_CHUNK_ANCILLARY c
+{
+ mov eax,c
+ shr eax,29
+ and eax,1
+}
+macro PNG_CHUNK_CRITICAL c
+{
+ PNG_CHUNK_ANCILLARY c
+ xor eax,1
+}
+macro PNG_CHUNK_PRIVATE c
+{
+ mov eax,c
+ shr eax,21
+ and eax,1
+}
+macro PNG_CHUNK_RESERVED c
+{
+ mov eax,c
+ shr eax,13
+ and eax,1
+}
+macro PNG_CHUNK_SAFE_TO_COPY c
+{
+ mov eax,c
+ shr eax,5
+ and eax,1
+}
+
+PNG_FLAG_CRC_ANCILLARY_MASK equ (PNG_FLAG_CRC_ANCILLARY_USE or PNG_FLAG_CRC_ANCILLARY_NOWARN)
+PNG_FLAG_CRC_CRITICAL_MASK equ (PNG_FLAG_CRC_CRITICAL_USE or PNG_FLAG_CRC_CRITICAL_IGNORE)
+PNG_FLAG_CRC_MASK equ (PNG_FLAG_CRC_ANCILLARY_MASK or PNG_FLAG_CRC_CRITICAL_MASK)
+
+macro PNG_sRGB_FROM_LINEAR linear
+{
+ mov eax,linear
+ shr eax,15
+ shl eax,1
+ add eax,png_sRGB_base
+ movzx eax,word[eax]
+push ebx ecx
+ mov ebx,linear
+ shr ebx,15
+ add ebx,png_sRGB_delta
+ mov ecx,linear
+ and ecx,0x7fff
+ imul ecx,ebx
+ shr ecx,12
+ add eax,ecx
+pop ecx ebx
+ shr eax,8
+ ;;;and eax,0xff
+}
+; Given a value 'linear' in the range 0..255*65535 calculate the 8-bit sRGB
+; encoded value with maximum error 0.646365. Note that the input is not a
+; 16-bit value; it has been multiplied by 255!
+
+PNG_UNEXPECTED_ZLIB_RETURN equ (-7)
+
+;...
+
+; Suggested size for a number buffer (enough for 64 bits and a sign!)
+PNG_NUMBER_BUFFER_SIZE equ 24
+
+; These are the integer formats currently supported, the name is formed from
+; the standard printf(3) format string.
+
+PNG_NUMBER_FORMAT_u equ 1 ;chose unsigned API!
+PNG_NUMBER_FORMAT_02u equ 2
+PNG_NUMBER_FORMAT_d equ 1 ;chose signed API!
+PNG_NUMBER_FORMAT_02d equ 2
+PNG_NUMBER_FORMAT_x equ 3
+PNG_NUMBER_FORMAT_02x equ 4
+PNG_NUMBER_FORMAT_fixed equ 5 ;choose the signed API
+
+; New defines and members adding in libpng-1.5.4
+PNG_WARNING_PARAMETER_SIZE equ 32
+PNG_WARNING_PARAMETER_COUNT equ 8 ;Maximum 9; see pngerror.asm
+
+PNG_CHUNK_WARNING equ 0 ;never an error
+PNG_CHUNK_WRITE_ERROR equ 1 ;an error only on write
+PNG_CHUNK_ERROR equ 2 ;always an error
+
+; ASCII to FP interfaces, currently only implemented if sCAL
+; support is required.
+
+; MAX_DIGITS is actually the maximum number of characters in an sCAL
+; width or height, derived from the precision (number of significant
+; digits - a build time settable option) and assumptions about the
+; maximum ridiculous exponent.
+
+PNG_sCAL_MAX_DIGITS equ PNG_sCAL_PRECISION+1+1+10 ;. E exponent
+
+; An internal API to validate the format of a floating point number.
+; The result is the index of the next character. If the number is
+; not valid it will be the index of a character in the supposed number.
+
+; The format of a number is defined in the PNG extensions specification
+; and this API is strictly conformant to that spec, not anyone elses!
+
+; The format as a regular expression is:
+
+; [+-]?[0-9]+.?([Ee][+-]?[0-9]+)?
+
+; or:
+
+; [+-]?.[0-9]+(.[0-9]+)?([Ee][+-]?[0-9]+)?
+
+; The complexity is that either integer or fraction must be present and the
+; fraction is permitted to have no digits only if the integer is present.
+
+; NOTE: The dangling E problem.
+; There is a PNG valid floating point number in the following:
+
+; PNG floating point numbers are not greedy.
+
+; Working this out requires *TWO* character lookahead (because of the
+; sign), the parser does not do this - it will fail at the 'r' - this
+; doesn't matter for PNG sCAL chunk values, but it requires more care
+; if the value were ever to be embedded in something more complex. Use
+; ANSI-C strtod if you need the lookahead.
+
+; State table for the parser.
+PNG_FP_INTEGER equ 0 ;before or in integer
+PNG_FP_FRACTION equ 1 ;before or in fraction
+PNG_FP_EXPONENT equ 2 ;before or in exponent
+PNG_FP_STATE equ 3 ;mask for the above
+PNG_FP_SAW_SIGN equ 4 ;Saw +/- in current state
+PNG_FP_SAW_DIGIT equ 8 ;Saw a digit in current state
+PNG_FP_SAW_DOT equ 16 ;Saw a dot in current state
+PNG_FP_SAW_E equ 32 ;Saw an E (or e) in current state
+PNG_FP_SAW_ANY equ 60 ;Saw any of the above 4
+
+; These three values don't affect the parser. They are set but not used.
+
+PNG_FP_WAS_VALID equ 64 ;Preceding substring is a valid fp number
+PNG_FP_NEGATIVE equ 128 ;A negative number, including "-0"
+PNG_FP_NONZERO equ 256 ;A non-zero value
+PNG_FP_STICKY equ 448 ;The above three flags
+
+; This is available for the caller to store in 'state' if required. Do not
+; call the parser after setting it (the parser sometimes clears it.)
+
+PNG_FP_INVALID equ 512 ;Available for callers as a distinct value
+
+; Result codes for the parser (boolean - true meants ok, false means
+; not ok yet.)
+
+PNG_FP_MAYBE equ 0 ;The number may be valid in the future
+PNG_FP_OK equ 1 ;The number is valid
+
+; The internal structure that png_image::opaque points to.
+struct png_control
+ png_ptr dd ? ;png_structp
+ info_ptr dd ? ;png_infop
+ error_buf dd ? ;voidp ;Always a jmp_buf at present.
+
+ memory dd ? ;bytep ;Memory buffer.
+ size dd ? ;png_size_t ;Size of the memory buffer.
+
+ for_write dd ? ;uint ;:1;Otherwise it is a read structure
+ owned_file dd ? ;uint ;:1;We own the file in io_ptr
+ends
diff --git a/programs/develop/libraries/libs-dev/libimg/png/libpng/pngset.asm b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngset.asm
index c054dfd88..6182a6482 100644
--- a/programs/develop/libraries/libs-dev/libimg/png/libpng/pngset.asm
+++ b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngset.asm
@@ -1,1862 +1,1862 @@
-
-; pngset.asm - storage of image information into info struct
-
-; Last changed in libpng 1.6.24 [August 4, 2016]
-; Copyright (c) 1998-2016 Glenn Randers-Pehrson
-; (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
-; (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
-
-; This code is released under the libpng license.
-; For conditions of distribution and use, see the disclaimer
-; and license in png.inc
-
-; The functions here are used during reads to store data from the file
-; into the info struct, and during writes to store application data
-; into the info struct for writing into the file. This abstracts the
-; info struct and allows us to change the structure in the future.
-
-
-;void (png_structrp png_ptr, png_inforp info_ptr, png_color_16p background)
-align 4
-proc png_set_bKGD uses ecx edi esi, png_ptr:dword, info_ptr:dword, background:dword
- png_debug1 1, 'in %s storage function', 'bKGD'
-
- cmp dword[png_ptr],0
- je .end_f
- mov edi,[info_ptr]
- cmp edi,0
- je .end_f
- mov esi,[background]
- cmp esi,0
- je .end_f ;if (..==0 || ..==0 || ..==0) return
-
- or dword[edi+png_info_def.valid],PNG_INFO_bKGD
- add edi,png_info_def.background
- mov ecx,sizeof.png_color_16
- rep movsb
-.end_f:
- ret
-endp
-
-;void (png_structrp png_ptr, png_inforp info_ptr,
-; png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x,
-; png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y,
-; png_fixed_point blue_x, png_fixed_point blue_y)
-align 4
-proc png_set_cHRM_fixed, png_ptr:dword, info_ptr:dword,\
- white_x:dword, white_y:dword, red_x:dword, red_y:dword,\
- green_x:dword, green_y:dword, blue_x:dword, blue_y:dword
-; png_xy xy;
-
- png_debug1 1, 'in %s storage function', 'cHRM fixed'
-
-; if (png_ptr == NULL || info_ptr == NULL)
-; return;
-
-; xy.redx = red_x;
-; xy.redy = red_y;
-; xy.greenx = green_x;
-; xy.greeny = green_y;
-; xy.bluex = blue_x;
-; xy.bluey = blue_y;
-; xy.whitex = white_x;
-; xy.whitey = white_y;
-
-; if (png_colorspace_set_chromaticities(png_ptr, &info_ptr->colorspace, &xy,
-; 2/* override with app values*/) != 0)
-; info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM;
-
-; png_colorspace_sync_info(png_ptr, info_ptr);
-.end_f:
- ret
-endp
-
-;void (png_structrp png_ptr, png_inforp info_ptr,
-; png_fixed_point int_red_X, png_fixed_point int_red_Y,
-; png_fixed_point int_red_Z, png_fixed_point int_green_X,
-; png_fixed_point int_green_Y, png_fixed_point int_green_Z,
-; png_fixed_point int_blue_X, png_fixed_point int_blue_Y,
-; png_fixed_point int_blue_Z)
-align 4
-proc png_set_cHRM_XYZ_fixed uses edi esi, png_ptr:dword, info_ptr:dword,\
- int_red_X:dword, int_red_Y:dword, int_red_Z:dword,\
- int_green_X:dword, int_green_Y:dword, int_green_Z:dword,\
- int_blue_X:dword, int_blue_Y:dword, int_blue_Z:dword
-; png_XYZ XYZ;
-
- png_debug1 1, 'in %s storage function', 'cHRM XYZ fixed'
-
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f
- mov esi,[info_ptr]
- cmp esi,0
- je .end_f ;if (..==0 || ..==0) return
-
-; XYZ.red_X = int_red_X;
-; XYZ.red_Y = int_red_Y;
-; XYZ.red_Z = int_red_Z;
-; XYZ.green_X = int_green_X;
-; XYZ.green_Y = int_green_Y;
-; XYZ.green_Z = int_green_Z;
-; XYZ.blue_X = int_blue_X;
-; XYZ.blue_Y = int_blue_Y;
-; XYZ.blue_Z = int_blue_Z;
-
-; if (png_colorspace_set_endpoints(png_ptr, &info_ptr->colorspace,
-; &XYZ, 2) != 0)
-; info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM;
-
- stdcall png_colorspace_sync_info, edi, esi
-.end_f:
- ret
-endp
-
-;void (png_structrp png_ptr, png_inforp info_ptr,
-; double white_x, double white_y, double red_x, double red_y,
-; double green_x, double green_y, double blue_x, double blue_y)
-align 4
-proc png_set_cHRM, png_ptr:dword, info_ptr:dword,\
- white_x:dword, white_y:dword, red_x:dword, red_y:dword,\
- green_x:dword, green_y:dword, blue_x:dword, blue_y:dword
-; png_set_cHRM_fixed(png_ptr, info_ptr,
-; png_fixed(png_ptr, white_x, "cHRM White X"),
-; png_fixed(png_ptr, white_y, "cHRM White Y"),
-; png_fixed(png_ptr, red_x, "cHRM Red X"),
-; png_fixed(png_ptr, red_y, "cHRM Red Y"),
-; png_fixed(png_ptr, green_x, "cHRM Green X"),
-; png_fixed(png_ptr, green_y, "cHRM Green Y"),
-; png_fixed(png_ptr, blue_x, "cHRM Blue X"),
-; png_fixed(png_ptr, blue_y, "cHRM Blue Y"));
- ret
-endp
-
-;void (png_structrp png_ptr, png_inforp info_ptr, double red_X,
-; double red_Y, double red_Z, double green_X, double green_Y, double green_Z,
-; double blue_X, double blue_Y, double blue_Z)
-align 4
-proc png_set_cHRM_XYZ, png_ptr:dword, info_ptr:dword, red_X:dword, red_Y:dword, red_Z:dword, green_X:dword, green_Y:dword, green_Z:dword, blue_X:dword, blue_Y:dword, blue_Z:dword
-; png_set_cHRM_XYZ_fixed(png_ptr, info_ptr,
-; png_fixed(png_ptr, red_X, "cHRM Red X"),
-; png_fixed(png_ptr, red_Y, "cHRM Red Y"),
-; png_fixed(png_ptr, red_Z, "cHRM Red Z"),
-; png_fixed(png_ptr, green_X, "cHRM Green X"),
-; png_fixed(png_ptr, green_Y, "cHRM Green Y"),
-; png_fixed(png_ptr, green_Z, "cHRM Green Z"),
-; png_fixed(png_ptr, blue_X, "cHRM Blue X"),
-; png_fixed(png_ptr, blue_Y, "cHRM Blue Y"),
-; png_fixed(png_ptr, blue_Z, "cHRM Blue Z"));
- ret
-endp
-
-;void (png_structrp png_ptr, png_inforp info_ptr, png_fixed_point file_gamma)
-align 4
-proc png_set_gAMA_fixed uses eax edi esi, png_ptr:dword, info_ptr:dword, file_gamma:dword
- png_debug1 1, 'in %s storage function', 'gAMA'
-
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f
- mov esi,[info_ptr]
- cmp esi,0
- je .end_f ;if (..== 0 || ..== 0) return
-
- mov eax,esi
- add eax,png_info_def.colorspace
- stdcall png_colorspace_set_gamma, edi, eax, [file_gamma]
- stdcall png_colorspace_sync_info, edi, esi
-.end_f:
- ret
-endp
-
-;void (png_structrp png_ptr, png_inforp info_ptr, double file_gamma)
-align 4
-proc png_set_gAMA uses eax, png_ptr:dword, info_ptr:dword, file_gamma:dword
- cStr ,'png_set_gAMA'
- stdcall png_fixed, [png_ptr], [file_gamma], eax
- stdcall png_set_gAMA_fixed, [png_ptr], [info_ptr], eax
- ret
-endp
-
-;void (png_structrp png_ptr, png_inforp info_ptr, png_uint_16p hist)
-align 4
-proc png_set_hIST uses edi esi, png_ptr:dword, info_ptr:dword, hist:dword
-; int i;
-
- png_debug1 1, 'in %s storage function', 'hIST'
-
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f
- mov esi,[info_ptr]
- cmp esi,0
- je .end_f ;if (..== 0 || ..== 0) return
-
-; if (info_ptr->num_palette == 0 || info_ptr->num_palette
-; > PNG_MAX_PALETTE_LENGTH)
-; {
-; png_warning(png_ptr,
-; "Invalid palette size, hIST allocation skipped");
-
-; return;
-; }
-
-; png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0);
-
- ; Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in
- ; version 1.2.1
-
-; info_ptr->hist = png_malloc_warn(png_ptr,
-; PNG_MAX_PALETTE_LENGTH * (sizeof (uint_16)));
-
-; if (info_ptr->hist == NULL)
-; {
-; png_warning(png_ptr, "Insufficient memory for hIST chunk data");
-
-; return;
-; }
-
-; info_ptr->free_me |= PNG_FREE_HIST;
-
-; for (i = 0; i < info_ptr->num_palette; i++)
-; info_ptr->hist[i] = hist[i];
-
- or dword[esi+png_info_def.valid], PNG_INFO_hIST
-.end_f:
- ret
-endp
-
-;void (png_structrp png_ptr, png_inforp info_ptr,
-; uint_32 width, uint_32 height, int bit_depth,
-; int color_type, int interlace_type, int compression_type, int filter_type)
-align 4
-proc png_set_IHDR, png_ptr:dword, info_ptr:dword,\
- width:dword, height:dword, bit_depth:dword, color_type:dword,\
- interlace_type:dword, compression_type:dword, filter_type:dword
- png_debug1 1, 'in %s storage function', 'IHDR'
-pushad
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f
- mov esi,[info_ptr]
- cmp esi,0
- je .end_f ;if (..== 0 || ..== 0) return
-
- mov eax,[width]
- mov [esi+png_info_def.width],eax
- mov eax,[height]
- mov [esi+png_info_def.height],eax
- movzx eax,byte[filter_type]
- mov [esi+png_info_def.filter_type],al
- push eax
- movzx eax,byte[compression_type]
- mov [esi+png_info_def.compression_type],al
- push eax
- movzx eax,byte[interlace_type]
- mov [esi+png_info_def.interlace_type],al
- push eax
- movzx ebx,byte[color_type]
- mov [esi+png_info_def.color_type],bl
- push ebx
- movzx ecx,byte[bit_depth]
- mov [esi+png_info_def.bit_depth],cl
-
- stdcall png_check_IHDR, edi, dword[esi+png_info_def.width], dword[esi+png_info_def.height], ecx
- ;, color_type, interlace_type, compression_type, filter_type
-
- cmp ebx,PNG_COLOR_TYPE_PALETTE
- jne @f ;if (..==..)
- mov byte[esi+png_info_def.channels], 1
- jmp .end0
- @@:
- mov eax,ebx
- and eax,PNG_COLOR_MASK_COLOR
- cmp eax,0
- je @f ;else if (..!=0)
- mov byte[esi+png_info_def.channels], 3
- jmp .end0
- @@: ;else
- mov byte[esi+png_info_def.channels], 1
- .end0:
-
- mov eax,ebx
- and eax,PNG_COLOR_MASK_ALPHA
- cmp eax,0
- je @f ;else if (..!=0)
- inc byte[esi+png_info_def.channels]
- @@:
-
- movzx eax,byte[esi+png_info_def.channels]
- imul eax,ecx
- mov byte[esi+png_info_def.pixel_depth],al ;channels * bit_depth
-
- PNG_ROWBYTES eax, [width]
- mov [esi+png_info_def.rowbytes], eax
-.end_f:
-popad
- ret
-endp
-
-;if PNG_oFFs_SUPPORTED
-;void (png_structrp png_ptr, png_inforp info_ptr,
-; int_32 offset_x, int_32 offset_y, int unit_type)
-align 4
-proc png_set_oFFs uses eax esi, png_ptr:dword, info_ptr:dword, offset_x:dword, offset_y:dword, unit_type:dword
- png_debug1 1, 'in %s storage function', 'oFFs'
-
- cmp dword[png_ptr],0
- je @f
- mov esi,[info_ptr]
- cmp esi,0
- je @f ;if (..==0 || ..==0) return
-
- mov eax,[offset_x]
- mov [esi+png_info_def.x_offset],eax
- mov eax,[offset_y]
- mov [esi+png_info_def.y_offset],eax
- mov al,[unit_type]
- mov [esi+png_info_def.offset_unit_type],al
- or dword[esi+png_info_def.valid], PNG_INFO_oFFs
- @@:
- ret
-endp
-
-;void (png_structrp png_ptr, png_inforp info_ptr,
-; charp purpose, int_32 X0, int_32 X1, int type,
-; int nparams, charp units, charpp params)
-align 4
-proc png_set_pCAL uses edi esi, png_ptr:dword, info_ptr:dword, purpose:dword, X0:dword, X1:dword, type:dword, nparams:dword, units:dword, params:dword
-; png_size_t length;
-; int i;
-
- png_debug1 1, 'in %s storage function', 'pCAL'
-
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f
- mov esi,[info_ptr]
- cmp esi,0
- je .end_f
- cmp dword[purpose],0
- je .end_f
- cmp dword[units],0
- je .end_f
- cmp dword[nparams],0
- jle @f
- cmp dword[params],0
- jne @f
- jmp .end_f
- @@: ;if (..==0 || ..==0 || ..==0 || ..==0 || (nparams > 0 && params == 0)) return
-
-; length = strlen(purpose) + 1;
- png_debug1 3, 'allocating purpose for info (%lu bytes)','(unsigned long)length'
-
- ; TODO: validate format of calibration name and unit name
-
- ; Check that the type matches the specification.
- cmp dword[type],0
- jl @f
- cmp dword[type],3
- jle .end0 ;if (..<0 || ..>3)
- @@:
- png_error edi, 'Invalid pCAL equation type'
- .end0:
-
- cmp dword[nparams],0
- jl @f
- cmp dword[nparams],255
- jle .end1 ;if (..<0 || ..>255)
- @@:
- png_error edi, 'Invalid pCAL parameter count'
- .end1:
-
- ; Validate params[nparams]
-; for (i=0; ipcal_purpose = png_malloc_warn(png_ptr, length);
-
-; if (info_ptr->pcal_purpose == NULL)
-; {
-; png_warning(png_ptr, "Insufficient memory for pCAL purpose");
-
-; return;
-; }
-
-; memcpy(info_ptr->pcal_purpose, purpose, length);
-
- png_debug 3, 'storing X0, X1, type, and nparams in info'
-; info_ptr->pcal_X0 = X0;
-; info_ptr->pcal_X1 = X1;
-; info_ptr->pcal_type = (byte)type;
-; info_ptr->pcal_nparams = (byte)nparams;
-
-; length = strlen(units) + 1;
- png_debug1 3, 'allocating units for info (%lu bytes)','(unsigned long)length'
-
-; info_ptr->pcal_units = png_malloc_warn(png_ptr, length);
-
-; if (info_ptr->pcal_units == NULL)
-; {
-; png_warning(png_ptr, "Insufficient memory for pCAL units");
-
-; return;
-; }
-
-; memcpy(info_ptr->pcal_units, units, length);
-
-; info_ptr->pcal_params = png_malloc_warn(png_ptr,
-; (png_size_t)((nparams + 1) * (sizeof (charp))));
-
-; if (info_ptr->pcal_params == NULL)
-; {
-; png_warning(png_ptr, "Insufficient memory for pCAL params");
-
-; return;
-; }
-
-; memset(info_ptr->pcal_params, 0, (nparams + 1) * (sizeof (charp)));
-
-; for (i = 0; i < nparams; i++)
-; {
-; length = strlen(params[i]) + 1;
-; png_debug2(3, "allocating parameter %d for info (%lu bytes)", i,
-; (unsigned long)length);
-
-; info_ptr->pcal_params[i] = (charp)png_malloc_warn(png_ptr, length);
-
-; if (info_ptr->pcal_params[i] == NULL)
-; {
-; png_warning(png_ptr, "Insufficient memory for pCAL parameter");
-
-; return;
-; }
-
-; memcpy(info_ptr->pcal_params[i], params[i], length);
-; }
-
- or dword[esi+png_info_def.valid],PNG_INFO_pCAL
- or dword[esi+png_info_def.free_me],PNG_FREE_PCAL
-.end_f:
- ret
-endp
-
-;void (png_structrp png_ptr, png_inforp info_ptr,
-; int unit, charp swidth, charp sheight)
-align 4
-proc png_set_sCAL_s, png_ptr:dword, info_ptr:dword, unit:dword, swidth:dword, sheight:dword
-; png_size_t lengthw = 0, lengthh = 0;
-
- png_debug1 1, 'in %s storage function', 'sCAL'
-
-; if (png_ptr == NULL || info_ptr == NULL)
-; return;
-
- ; Double check the unit (should never get here with an invalid
- ; unit unless this is an API call.)
-
-; if (unit != 1 && unit != 2)
-; png_error(png_ptr, "Invalid sCAL unit");
-
-; if (swidth == NULL || (lengthw = strlen(swidth)) == 0 ||
-; swidth[0] == 45 /* '-' */ || !png_check_fp_string(swidth, lengthw))
-; png_error(png_ptr, "Invalid sCAL width");
-
-; if (sheight == NULL || (lengthh = strlen(sheight)) == 0 ||
-; sheight[0] == 45 /* '-' */ || !png_check_fp_string(sheight, lengthh))
-; png_error(png_ptr, "Invalid sCAL height");
-
-; info_ptr->scal_unit = (byte)unit;
-
-; ++lengthw;
-
-; png_debug1(3, "allocating unit for info (%u bytes)", (uint)lengthw);
-
-; info_ptr->scal_s_width = png_malloc_warn(png_ptr, lengthw);
-
-; if (info_ptr->scal_s_width == NULL)
-; {
-; png_warning(png_ptr, "Memory allocation failed while processing sCAL");
-
-; return;
-; }
-
-; memcpy(info_ptr->scal_s_width, swidth, lengthw);
-
-; ++lengthh;
-
-; png_debug1(3, "allocating unit for info (%u bytes)", (uint)lengthh);
-
-; info_ptr->scal_s_height = png_malloc_warn(png_ptr, lengthh);
-
-; if (info_ptr->scal_s_height == NULL)
-; {
-; png_free (png_ptr, info_ptr->scal_s_width);
-; info_ptr->scal_s_width = NULL;
-
-; png_warning(png_ptr, "Memory allocation failed while processing sCAL");
-
-; return;
-; }
-
-; memcpy(info_ptr->scal_s_height, sheight, lengthh);
-;
-; info_ptr->valid |= PNG_INFO_sCAL;
-; info_ptr->free_me |= PNG_FREE_SCAL;
- ret
-endp
-
-;void (png_structrp png_ptr, png_inforp info_ptr, int unit,
-; double width, double height)
-align 4
-proc png_set_sCAL, png_ptr:dword, info_ptr:dword, unit:dword, width:dword, height:dword
- png_debug1 1, 'in %s storage function', 'sCAL'
-
- ; Check the arguments.
-; if (width <= 0)
-; png_warning(png_ptr, "Invalid sCAL width ignored");
-
-; else if (height <= 0)
-; png_warning(png_ptr, "Invalid sCAL height ignored");
-
-; else
-; {
- ; Convert 'width' and 'height' to ASCII.
-; char swidth[PNG_sCAL_MAX_DIGITS+1];
-; char sheight[PNG_sCAL_MAX_DIGITS+1];
-
-; png_ascii_from_fp(png_ptr, swidth, (sizeof swidth), width,
-; PNG_sCAL_PRECISION);
-; png_ascii_from_fp(png_ptr, sheight, (sizeof sheight), height,
-; PNG_sCAL_PRECISION);
-
-; png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight);
-; }
- ret
-endp
-
-;void (png_structrp png_ptr, png_inforp info_ptr, int unit,
-; png_fixed_point width, png_fixed_point height)
-align 4
-proc png_set_sCAL_fixed uses ebx ecx edi, png_ptr:dword, info_ptr:dword, unit:dword, width:dword, height:dword
-locals
- swidth rb PNG_sCAL_MAX_DIGITS+1 ;char[]
- sheight rb PNG_sCAL_MAX_DIGITS+1 ;char[]
-endl
- png_debug1 1, 'in %s storage function', 'sCAL'
- mov edi,[png_ptr]
-
- ; Check the arguments.
- cmp dword[width],0
- jg @f ;if (..<=0)
- png_warning edi, 'Invalid sCAL width ignored'
- jmp .end0
- @@:
- cmp dword[height],0
- jg @f ;else if (..<=0)
- png_warning edi, 'Invalid sCAL height ignored'
- jmp .end0
- @@: ;else
- ; Convert 'width' and 'height' to ASCII.
- mov ebx,ebp
- sub ebx,PNG_sCAL_MAX_DIGITS+1 ;sheight
- mov ecx,ebx
- sub ecx,PNG_sCAL_MAX_DIGITS+1 ;swidth
-
- stdcall png_ascii_from_fixed, edi, ecx, PNG_sCAL_MAX_DIGITS+1, [width]
- stdcall png_ascii_from_fixed, edi, ebx, PNG_sCAL_MAX_DIGITS+1, [height]
-
- stdcall png_set_sCAL_s, edi, [info_ptr], [unit], ecx, ebx
- .end0:
- ret
-endp
-
-;void (png_structrp png_ptr, png_inforp info_ptr,
-; uint_32 res_x, uint_32 res_y, int unit_type)
-align 4
-proc png_set_pHYs, png_ptr:dword, info_ptr:dword, res_x:dword, res_y:dword, unit_type:dword
- png_debug1 1, 'in %s storage function', 'pHYs'
-
-; if (png_ptr == NULL || info_ptr == NULL)
-; return;
-
-; info_ptr->x_pixels_per_unit = res_x;
-; info_ptr->y_pixels_per_unit = res_y;
-; info_ptr->phys_unit_type = (byte)unit_type;
-; info_ptr->valid |= PNG_INFO_pHYs;
- ret
-endp
-
-;void (png_structrp png_ptr, png_inforp info_ptr, png_colorp palette, int num_palette)
-align 4
-proc png_set_PLTE uses eax edi esi, png_ptr:dword, info_ptr:dword, palette:dword, num_palette:dword
-; uint_32 max_palette_length;
-
- png_debug1 1, 'in %s storage function', 'PLTE'
-
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f
- mov esi,[info_ptr]
- cmp esi,0
- je .end_f ;if (..==0 || ..==0) return
-
-; max_palette_length = (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ?
-; (1 << info_ptr->bit_depth) : PNG_MAX_PALETTE_LENGTH;
-
-; if (num_palette < 0 || num_palette > (int) max_palette_length)
-; {
-; if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
-; png_error(png_ptr, "Invalid palette length");
-
-; else
-; {
-; png_warning(png_ptr, "Invalid palette length");
-
-; return;
-; }
-; }
-
-; if ((num_palette > 0 && palette == NULL) ||
-; (num_palette == 0
-if PNG_MNG_FEATURES_SUPPORTED eq 1
-; && (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0
-end if
-; ))
-; {
-; png_error(png_ptr, "Invalid palette");
-; }
-
- ; It may not actually be necessary to set png_ptr->palette here;
- ; we do it for backward compatibility with the way the png_handle_tRNS
- ; function used to do the allocation.
-
- ; 1.6.0: the above statement appears to be incorrect; something has to set
- ; the palette inside png_struct on read.
-
- stdcall png_free_data, edi, esi, PNG_FREE_PLTE, 0
-
- ; Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead
- ; of num_palette entries, in case of an invalid PNG file or incorrect
- ; call to png_set_PLTE() with too-large sample values.
-
-; png_ptr->palette = png_calloc(png_ptr,
-; PNG_MAX_PALETTE_LENGTH * (sizeof (png_color)));
-
-; if (num_palette > 0)
-; memcpy(png_ptr->palette, palette, num_palette * (sizeof (png_color)));
- mov eax,[edi+png_struct.palette]
- mov [esi+png_info_def.palette],eax
-; info_ptr->num_palette = png_ptr->num_palette = (uint_16)num_palette;
-
- or dword[esi+png_info_def.free_me], PNG_FREE_PLTE
- or dword[esi+png_info_def.valid], PNG_INFO_PLTE
-.end_f:
- ret
-endp
-
-;void (png_structrp png_ptr, png_inforp info_ptr, png_color_8p sig_bit)
-align 4
-proc png_set_sBIT, png_ptr:dword, info_ptr:dword, sig_bit:dword
- png_debug1 1, 'in %s storage function', 'sBIT'
-
-; if (png_ptr == NULL || info_ptr == NULL || sig_bit == NULL)
-; return;
-
-; info_ptr->sig_bit = *sig_bit;
-; info_ptr->valid |= PNG_INFO_sBIT;
-.end_f:
- ret
-endp
-
-;void (png_structrp png_ptr, png_inforp info_ptr, int srgb_intent)
-align 4
-proc png_set_sRGB uses eax edi esi, png_ptr:dword, info_ptr:dword, srgb_intent:dword
- png_debug1 1, 'in %s storage function', 'sRGB'
-
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f
- mov esi,[info_ptr]
- cmp esi,0
- je .end_f ;if (..==0 || ..==0)
-
- mov eax,esi
- add eax,png_info_def.colorspace
- stdcall png_colorspace_set_sRGB, edi, eax, [srgb_intent]
- stdcall png_colorspace_sync_info, edi, esi
-.end_f:
- ret
-endp
-
-;void (png_structrp png_ptr, png_inforp info_ptr, int srgb_intent)
-align 4
-proc png_set_sRGB_gAMA_and_cHRM, png_ptr:dword, info_ptr:dword, srgb_intent:dword
- png_debug1 1, 'in %s storage function', 'sRGB_gAMA_and_cHRM'
-
-; if (png_ptr == NULL || info_ptr == NULL)
-; return;
-
-; if (png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace,
-; srgb_intent) != 0)
-; {
- ; This causes the gAMA and cHRM to be written too
-; info_ptr->colorspace.flags |=
-; PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM;
-; }
-
-; png_colorspace_sync_info(png_ptr, info_ptr);
-.end_f:
- ret
-endp
-
-;void (const_structrp png_ptr, png_inforp info_ptr,
-; charp name, int compression_type, bytep profile, uint_32 proflen)
-align 4
-proc png_set_iCCP uses edi esi, png_ptr:dword, info_ptr:dword, name:dword, compression_type:dword, profile:dword, proflen:dword
-; charp new_iccp_name;
-; bytep new_iccp_profile;
-; png_size_t length;
-
- png_debug1 1, 'in %s storage function', 'iCCP'
-
- mov esi,[info_ptr]
-; if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL)
-; return;
-
-; if (compression_type != PNG_COMPRESSION_TYPE_BASE)
-; png_app_error(png_ptr, "Invalid iCCP compression method");
-
- ; Set the colorspace first because this validates the profile; do not
- ; override previously set app cHRM or gAMA here (because likely as not the
- ; application knows better than libpng what the correct values are.) Pass
- ; the info_ptr color_type field to png_colorspace_set_ICC because in the
- ; write case it has not yet been stored in png_ptr.
-
-; {
-; int result = png_colorspace_set_ICC(png_ptr, &info_ptr->colorspace, name,
-; proflen, profile, info_ptr->color_type);
-
-; png_colorspace_sync_info(png_ptr, info_ptr);
-
- ; Don't do any of the copying if the profile was bad, or inconsistent.
-; if (result == 0)
-; return;
-
- ; But do write the gAMA and cHRM chunks from the profile.
-; info_ptr->colorspace.flags |=
-; PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM;
-; }
-
-; length = strlen(name)+1;
-; new_iccp_name = png_malloc_warn(png_ptr, length);
-
-; if (new_iccp_name == NULL)
-; {
-; png_benign_error(png_ptr, "Insufficient memory to process iCCP chunk");
-; return;
-; }
-
-; memcpy(new_iccp_name, name, length);
-; new_iccp_profile = png_malloc_warn(png_ptr, proflen);
-
-; if (new_iccp_profile == NULL)
-; {
-; png_free(png_ptr, new_iccp_name);
-; png_benign_error(png_ptr,
-; "Insufficient memory to process iCCP profile");
-; return;
-; }
-
-; memcpy(new_iccp_profile, profile, proflen);
-
-; png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0);
-
-; info_ptr->iccp_proflen = proflen;
-; info_ptr->iccp_name = new_iccp_name;
-; info_ptr->iccp_profile = new_iccp_profile;
- or dword[esi+png_info_def.free_me],PNG_FREE_ICCP
- or dword[esi+png_info_def.valid],PNG_INFO_iCCP
- ret
-endp
-
-;void (png_structrp png_ptr, png_inforp info_ptr, png_textp text_ptr, int num_text)
-align 4
-proc png_set_text uses eax edi, png_ptr:dword, info_ptr:dword, text_ptr:dword, num_text:dword
- mov edi,[png_ptr]
- stdcall png_set_text_2, edi, [info_ptr], [text_ptr], [num_text]
-
- cmp eax,0
- je @f ;if (..!=0)
- png_error edi, 'Insufficient memory to store text'
- @@:
- ret
-endp
-
-;int (png_structrp png_ptr, png_inforp info_ptr,
-; png_textp text_ptr, int num_text)
-align 4
-proc png_set_text_2, png_ptr:dword, info_ptr:dword, text_ptr:dword, num_text:dword
-; int i;
-
- png_debug1 1, 'in %lx storage function', 'png_ptr == NULL ? 0xabadca11 : (unsigned long)png_ptr->chunk_name'
-
-; if (png_ptr == NULL || info_ptr == NULL || num_text <= 0 || text_ptr == NULL)
-; return(0);
-
- ; Make sure we have enough space in the "text" array in info_struct
- ; to hold all of the incoming text_ptr objects. This compare can't overflow
- ; because max_text >= num_text (anyway, subtract of two positive integers
- ; can't overflow in any case.)
-
-; if (num_text > info_ptr->max_text - info_ptr->num_text)
-; {
-; int old_num_text = info_ptr->num_text;
-; int max_text;
-; png_textp new_text = NULL;
-
-; /* Calculate an appropriate max_text, checking for overflow. */
-; max_text = old_num_text;
-; if (num_text <= INT_MAX - max_text)
-; {
-; max_text += num_text;
-
-; /* Round up to a multiple of 8 */
-; if (max_text < INT_MAX-8)
-; max_text = (max_text + 8) & ~0x7;
-
-; else
-; max_text = INT_MAX;
-
- ; Now allocate a new array and copy the old members in; this does all
- ; the overflow checks.
-
-; new_text = png_realloc_array(png_ptr,
-; info_ptr->text, old_num_text, max_text-old_num_text,
-; sizeof *new_text);
-; }
-
-; if (new_text == NULL)
-; {
-; png_chunk_report(png_ptr, "too many text chunks",
-; PNG_CHUNK_WRITE_ERROR);
-
-; return 1;
-; }
-
-; png_free(png_ptr, info_ptr->text);
-
-; info_ptr->text = new_text;
-; info_ptr->free_me |= PNG_FREE_TEXT;
-; info_ptr->max_text = max_text;
-; /* num_text is adjusted below as the entries are copied in */
-
-; png_debug1(3, "allocated %d entries for info_ptr->text", max_text);
-; }
-
-; for (i = 0; i < num_text; i++)
-; {
-; size_t text_length, key_len;
-; size_t lang_len, lang_key_len;
-; png_textp textp = &(info_ptr->text[info_ptr->num_text]);
-
-; if (text_ptr[i].key == NULL)
-; continue;
-
-; if (text_ptr[i].compression < PNG_TEXT_COMPRESSION_NONE ||
-; text_ptr[i].compression >= PNG_TEXT_COMPRESSION_LAST)
-; {
-; png_chunk_report(png_ptr, "text compression mode is out of range",
-; PNG_CHUNK_WRITE_ERROR);
-; continue;
-; }
-
-; key_len = strlen(text_ptr[i].key);
-
-; if (text_ptr[i].compression <= 0)
-; {
-; lang_len = 0;
-; lang_key_len = 0;
-; }
-
-; else
-if PNG_iTXt_SUPPORTED eq 1
-; {
-; /* Set iTXt data */
-
-; if (text_ptr[i].lang != NULL)
-; lang_len = strlen(text_ptr[i].lang);
-;
-; else
-; lang_len = 0;
-
-; if (text_ptr[i].lang_key != NULL)
-; lang_key_len = strlen(text_ptr[i].lang_key);
-
-; else
-; lang_key_len = 0;
-; }
-else ;iTXt
-; {
-; png_chunk_report(png_ptr, "iTXt chunk not supported",
-; PNG_CHUNK_WRITE_ERROR);
-; continue;
-; }
-end if
-
-; if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0')
-; {
-; text_length = 0;
-if PNG_iTXt_SUPPORTED eq 1
-; if (text_ptr[i].compression > 0)
-; textp->compression = PNG_ITXT_COMPRESSION_NONE;
-
-; else
-end if
-; textp->compression = PNG_TEXT_COMPRESSION_NONE;
-; }
-
-; else
-; {
-; text_length = strlen(text_ptr[i].text);
-; textp->compression = text_ptr[i].compression;
-; }
-
-; textp->key = png_malloc_base(png_ptr,
-; key_len + text_length + lang_len + lang_key_len + 4);
-
-; if (textp->key == NULL)
-; {
-; png_chunk_report(png_ptr, "text chunk: out of memory",
-; PNG_CHUNK_WRITE_ERROR);
-
-; return 1;
-; }
-
-; png_debug2(2, "Allocated %lu bytes at %p in png_set_text",
-; (unsigned long)(uint_32)
-; (key_len + lang_len + lang_key_len + text_length + 4),
-; textp->key);
-
-; memcpy(textp->key, text_ptr[i].key, key_len);
-; *(textp->key + key_len) = '\0';
-
-; if (text_ptr[i].compression > 0)
-; {
-; textp->lang = textp->key + key_len + 1;
-; memcpy(textp->lang, text_ptr[i].lang, lang_len);
-; *(textp->lang + lang_len) = '\0';
-; textp->lang_key = textp->lang + lang_len + 1;
-; memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len);
-; *(textp->lang_key + lang_key_len) = '\0';
-; textp->text = textp->lang_key + lang_key_len + 1;
-; }
-
-; else
-; {
-; textp->lang=NULL;
-; textp->lang_key=NULL;
-; textp->text = textp->key + key_len + 1;
-; }
-
-; if (text_length != 0)
-; memcpy(textp->text, text_ptr[i].text, text_length);
-
-; *(textp->text + text_length) = '\0';
-
-if PNG_iTXt_SUPPORTED eq 1
-; if (textp->compression > 0)
-; {
-; textp->text_length = 0;
-; textp->itxt_length = text_length;
-; }
-
-; else
-end if
-; {
-; textp->text_length = text_length;
-; textp->itxt_length = 0;
-; }
-
-; info_ptr->num_text++;
-; png_debug1(3, "transferred text chunk %d", info_ptr->num_text);
-; }
-
- xor eax,eax
-.end_f:
- ret
-endp
-
-;void (png_structrp png_ptr, png_inforp info_ptr, png_timep mod_time)
-align 4
-proc png_set_tIME uses eax ebx ecx edi esi, png_ptr:dword, info_ptr:dword, mod_time:dword
- png_debug1 1, 'in %s storage function', 'tIME'
-
- mov ebx,[png_ptr]
- cmp ebx,0
- je .end_f
- mov edi,[info_ptr]
- cmp edi,0
- je .end_f
- mov esi,[mod_time]
- cmp esi,0
- je .end_f
- mov eax,[ebx+png_struct.mode]
- and eax,PNG_WROTE_tIME
- cmp eax,0
- jne .end_f ;if (..==0 || ..==0 || ..==0 || ..!=0) return
-
- cmp byte[esi+png_time.month],0
- je @f
- cmp byte[esi+png_time.month],12
- jg @f
- cmp byte[esi+png_time.day],0
- je @f
- cmp byte[esi+png_time.day],31
- jg @f
- cmp byte[esi+png_time.hour],23
- jg @f
- cmp byte[esi+png_time.minute],59
- jg @f
- cmp byte[esi+png_time.second],60
- jle .end0
- @@: ;if (..==0 || ..>.. || ..==0 || ..>.. || ..>.. || ..>.. || ..>..)
- png_warning ebx, 'Ignoring invalid time value'
- jmp .end_f
- .end0:
-
- mov ecx,sizeof.png_time
- push edi
- add edi,png_info_def.mod_time
- rep movsb
- pop edi
- or dword[edi+png_info_def.valid],PNG_INFO_tIME
-.end_f:
- ret
-endp
-
-;void (png_structrp png_ptr, png_inforp info_ptr,
-; bytep trans_alpha, int num_trans, png_color_16p trans_color)
-align 4
-proc png_set_tRNS, png_ptr:dword, info_ptr:dword, trans_alpha:dword, num_trans:dword, trans_color:dword
- png_debug1 1, 'in %s storage function', 'tRNS'
-
-; if (png_ptr == NULL || info_ptr == NULL)
-; return;
-
-; if (trans_alpha != NULL)
-; {
- ; It may not actually be necessary to set png_ptr->trans_alpha here;
- ; we do it for backward compatibility with the way the png_handle_tRNS
- ; function used to do the allocation.
-
- ; 1.6.0: The above statement is incorrect; png_handle_tRNS effectively
- ; relies on png_set_tRNS storing the information in png_struct
- ; (otherwise it won't be there for the code in pngrtran.c).
-
-
-; png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);
-
-; if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH)
-; {
- ; Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1
-; info_ptr->trans_alpha = png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH);
-; memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans);
-; }
-; png_ptr->trans_alpha = info_ptr->trans_alpha;
-; }
-
-; if (trans_color != NULL)
-; {
-if PNG_WARNINGS_SUPPORTED eq 1
-; if (info_ptr->bit_depth < 16)
-; {
-; int sample_max = (1 << info_ptr->bit_depth) - 1;
-;
-; if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY &&
-; trans_color->gray > sample_max) ||
-; (info_ptr->color_type == PNG_COLOR_TYPE_RGB &&
-; (trans_color->red > sample_max ||
-; trans_color->green > sample_max ||
-; trans_color->blue > sample_max)))
-; png_warning(png_ptr,
-; "tRNS chunk has out-of-range samples for bit_depth");
-; }
-end if
-
-; info_ptr->trans_color = *trans_color;
-
-; if (num_trans == 0)
-; num_trans = 1;
-; }
-
-; info_ptr->num_trans = (uint_16)num_trans;
-
-; if (num_trans != 0)
-; {
-; info_ptr->valid |= PNG_INFO_tRNS;
-; info_ptr->free_me |= PNG_FREE_TRNS;
-; }
- ret
-endp
-
-;if PNG_sPLT_SUPPORTED
-;void (png_structrp png_ptr,
-; png_inforp info_ptr, png_sPLT_tp entries, int nentries)
-
-; entries - array of png_sPLT_t structures
-; to be added to the list of palettes
-; in the info structure.
-
-; nentries - number of palette structures to be
-; added.
-
-align 4
-proc png_set_sPLT, png_ptr:dword, info_ptr:dword, entries:dword, nentries:dword
-; png_sPLT_tp np;
-
-; if (png_ptr == NULL || info_ptr == NULL || nentries <= 0 || entries == NULL)
-; return;
-
- ; Use the internal realloc function, which checks for all the possible
- ; overflows. Notice that the parameters are (int) and (size_t)
-
-; np = png_realloc_array(png_ptr,
-; info_ptr->splt_palettes, info_ptr->splt_palettes_num, nentries,
-; sizeof *np);
-
-; if (np == NULL)
-; {
-; /* Out of memory or too many chunks */
-; png_chunk_report(png_ptr, "too many sPLT chunks", PNG_CHUNK_WRITE_ERROR);
-
-; return;
-; }
-
-; png_free(png_ptr, info_ptr->splt_palettes);
-; info_ptr->splt_palettes = np;
-; info_ptr->free_me |= PNG_FREE_SPLT;
-
-; np += info_ptr->splt_palettes_num;
-
-; do
-; {
-; png_size_t length;
-
-; /* Skip invalid input entries */
-; if (entries->name == NULL || entries->entries == NULL)
-; {
-; /* png_handle_sPLT doesn't do this, so this is an app error */
-; png_app_error(png_ptr, "png_set_sPLT: invalid sPLT");
-; /* Just skip the invalid entry */
-; continue;
-; }
-
-; np->depth = entries->depth;
-
- ; In the event of out-of-memory just return - there's no point keeping
- ; on trying to add sPLT chunks.
-
-; length = strlen(entries->name) + 1;
-; np->name = png_malloc_base(png_ptr, length);
-
-; if (np->name == NULL)
-; break;
-
-; memcpy(np->name, entries->name, length);
-
- ; IMPORTANT: we have memory now that won't get freed if something else
- ; goes wrong; this code must free it. png_malloc_array produces no
- ; warnings; use a png_chunk_report (below) if there is an error.
-
-; np->entries = png_malloc_array(png_ptr,
-; entries->nentries, sizeof (png_sPLT_entry));
-
-; if (np->entries == NULL)
-; {
-; png_free(png_ptr, np->name);
-; np->name = NULL;
-; break;
-; }
-
-; np->nentries = entries->nentries;
- ; This multiply can't overflow because png_malloc_array has already
- ; checked it when doing the allocation.
-
-; memcpy(np->entries, entries->entries,
-; entries->nentries * sizeof (png_sPLT_entry));
-
- ; Note that 'continue' skips the advance of the out pointer and out
- ; count, so an invalid entry is not added.
-
-; info_ptr->valid |= PNG_INFO_sPLT;
-; ++(info_ptr->splt_palettes_num);
-; ++np;
-; }
-; while (++entries, --nentries);
-
-; if (nentries > 0)
-; png_chunk_report(png_ptr, "sPLT out of memory", PNG_CHUNK_WRITE_ERROR);
- ret
-endp
-;end if /* sPLT */
-
-;if PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
-;byte (png_structrp png_ptr, int location)
-align 4
-proc check_location, png_ptr:dword, location:dword
-; location &= (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT);
-
- ; New in 1.6.0; copy the location and check it. This is an API
- ; change; previously the app had to use the
- ; png_set_unknown_chunk_location API below for each chunk.
-
-; if (location == 0 && (png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
-; {
-; /* Write struct, so unknown chunks come from the app */
-; png_app_warning(png_ptr,
-; "png_set_unknown_chunks now expects a valid location");
-; /* Use the old behavior */
-; location = (byte)(png_ptr->mode &
-; (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT));
-; }
-
- ; This need not be an internal error - if the app calls
- ; png_set_unknown_chunks on a read pointer it must get the location right.
-
-; if (location == 0)
-; png_error(png_ptr, "invalid location in png_set_unknown_chunks");
-
- ; Now reduce the location to the top-most set bit by removing each least
- ; significant bit in turn.
-
-; while (location != (location & -location))
-; location &= ~(location & -location);
-
- ; The cast is safe because 'location' is a bit mask and only the low four
- ; bits are significant.
-
-; return (byte)location;
- ret
-endp
-
-;void (png_structrp png_ptr,
-; png_inforp info_ptr, png_unknown_chunkp unknowns, int num_unknowns)
-align 4
-proc png_set_unknown_chunks uses edi esi, png_ptr:dword, info_ptr:dword, unknowns:dword, num_unknowns:dword
-; png_unknown_chunkp np;
-
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f
- mov esi,[info_ptr]
- cmp esi,0
- je .end_f
- cmp dword[num_unknowns],0
- jle .end_f
- cmp dword[unknowns],0
- je .end_f ;if (..== 0 || ..== 0 || ..<=0 || ..==0) return
-
- ; Check for the failure cases where support has been disabled at compile
- ; time. This code is hardly ever compiled - it's here because
- ; STORE_UNKNOWN_CHUNKS is set by both read and write code (compiling in this
- ; code) but may be meaningless if the read or write handling of unknown
- ; chunks is not compiled in.
-
-;# if !defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) && \
-; defined(PNG_READ_SUPPORTED)
-; if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
-; {
-; png_app_error(png_ptr, "no unknown chunk support on read");
-;
-; return;
-; }
-;# endif
-;# if !defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) && \
-; defined(PNG_WRITE_SUPPORTED)
-; if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
-; {
-; png_app_error(png_ptr, "no unknown chunk support on write");
-;
-; return;
-; }
-;# endif
-
- ; Prior to 1.6.0 this code used png_malloc_warn; however, this meant that
- ; unknown critical chunks could be lost with just a warning resulting in
- ; undefined behavior. Now png_chunk_report is used to provide behavior
- ; appropriate to read or write.
-
-; np = png_realloc_array(png_ptr,
-; info_ptr->unknown_chunks, info_ptr->unknown_chunks_num, num_unknowns,
-; sizeof *np);
-
-; if (np == NULL)
-; {
-; png_chunk_report(png_ptr, "too many unknown chunks",
-; PNG_CHUNK_WRITE_ERROR);
-
-; return;
-; }
-
-; png_free(png_ptr, info_ptr->unknown_chunks);
-; info_ptr->unknown_chunks = np; /* safe because it is initialized */
-; info_ptr->free_me |= PNG_FREE_UNKN;
-
-; np += info_ptr->unknown_chunks_num;
-
- ; Increment unknown_chunks_num each time round the loop to protect the
- ; just-allocated chunk data.
-
-; for (; num_unknowns > 0; --num_unknowns, ++unknowns)
-; {
-; memcpy(np->name, unknowns->name, (sizeof np->name));
-; np->name[(sizeof np->name)-1] = '\0';
-; np->location = check_location(png_ptr, unknowns->location);
-
-; if (unknowns->size == 0)
-; {
-; np->data = NULL;
-; np->size = 0;
-; }
-
-; else
-; {
-; np->data = png_malloc_base(png_ptr, unknowns->size);
-
-; if (np->data == NULL)
-; {
-; png_chunk_report(png_ptr, "unknown chunk: out of memory",
-; PNG_CHUNK_WRITE_ERROR);
-; /* But just skip storing the unknown chunk */
-; continue;
-; }
-
-; memcpy(np->data, unknowns->data, unknowns->size);
-; np->size = unknowns->size;
-; }
-
- ; These increments are skipped on out-of-memory for the data - the
- ; unknown chunk entry gets overwritten if the png_chunk_report returns.
- ; This is correct in the read case (the chunk is just dropped.)
-
-; ++np;
-; ++(info_ptr->unknown_chunks_num);
-; }
-.end_f:
- ret
-endp
-
-;void (png_structrp png_ptr, png_inforp info_ptr, int chunk, int location)
-align 4
-proc png_set_unknown_chunk_location, png_ptr:dword, info_ptr:dword, chunk:dword, location:dword
- ; This API is pretty pointless in 1.6.0 because the location can be set
- ; before the call to png_set_unknown_chunks.
-
- ; TODO: add a png_app_warning in 1.7
-
-; if (png_ptr != NULL && info_ptr != NULL && chunk >= 0 &&
-; chunk < info_ptr->unknown_chunks_num)
-; {
-; if ((location & (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT)) == 0)
-; {
-; png_app_error(png_ptr, "invalid unknown chunk location");
- ; Fake out the pre 1.6.0 behavior:
-; if ((location & PNG_HAVE_IDAT) != 0) /* undocumented! */
-; location = PNG_AFTER_IDAT;
-
-; else
-; location = PNG_HAVE_IHDR; /* also undocumented */
-; }
-
-; info_ptr->unknown_chunks[chunk].location =
-; check_location(png_ptr, location);
-; }
- ret
-endp
-;end if /* STORE_UNKNOWN_CHUNKS */
-
-;uint_32 (png_structrp png_ptr, uint_32 mng_features)
-align 4
-proc png_permit_mng_features, png_ptr:dword, mng_features:dword
- png_debug 1, 'in png_permit_mng_features'
-
-; if (png_ptr == NULL)
-; return 0;
-
-; png_ptr->mng_features_permitted = mng_features & PNG_ALL_MNG_FEATURES;
-
-; return png_ptr->mng_features_permitted;
- ret
-endp
-
-;if PNG_HANDLE_AS_UNKNOWN_SUPPORTED
-;uint (bytep list, uint count, bytep add, int keep)
-align 4
-proc add_one_chunk, list:dword, count:dword, p3add:dword, keep:dword
-; uint i;
-
- ; Utility function: update the 'keep' state of a chunk if it is already in
- ; the list, otherwise add it to the list.
-
-; for (i=0; i= PNG_HANDLE_CHUNK_LAST)
-; {
-; png_app_error(png_ptr, "png_set_keep_unknown_chunks: invalid keep");
-
-; return;
-; }
-
-; if (num_chunks_in <= 0)
-; {
-; png_ptr->unknown_default = keep;
-
- ; '0' means just set the flags, so stop here
-; if (num_chunks_in == 0)
-; return;
-; }
-
-; if (num_chunks_in < 0)
-; {
- ; Ignore all unknown chunks and all chunks recognized by
- ; libpng except for IHDR, PLTE, tRNS, IDAT, and IEND
-
-; static byte chunks_to_ignore[] = {
-; 98, 75, 71, 68, '\0', /* bKGD */
-; 99, 72, 82, 77, '\0', /* cHRM */
-; 103, 65, 77, 65, '\0', /* gAMA */
-; 104, 73, 83, 84, '\0', /* hIST */
-; 105, 67, 67, 80, '\0', /* iCCP */
-; 105, 84, 88, 116, '\0', /* iTXt */
-; 111, 70, 70, 115, '\0', /* oFFs */
-; 112, 67, 65, 76, '\0', /* pCAL */
-; 112, 72, 89, 115, '\0', /* pHYs */
-; 115, 66, 73, 84, '\0', /* sBIT */
-; 115, 67, 65, 76, '\0', /* sCAL */
-; 115, 80, 76, 84, '\0', /* sPLT */
-; 115, 84, 69, 82, '\0', /* sTER */
-; 115, 82, 71, 66, '\0', /* sRGB */
-; 116, 69, 88, 116, '\0', /* tEXt */
-; 116, 73, 77, 69, '\0', /* tIME */
-; 122, 84, 88, 116, '\0' /* zTXt */
-; };
-
-; chunk_list = chunks_to_ignore;
-; num_chunks = (uint)/*SAFE*/(sizeof chunks_to_ignore)/5U;
-; }
-
-; else /* num_chunks_in > 0 */
-; {
-; if (chunk_list == NULL)
-; {
-; /* Prior to 1.6.0 this was silently ignored, now it is an app_error
- ; which can be switched off.
-
-; png_app_error(png_ptr, "png_set_keep_unknown_chunks: no chunk list");
-
-; return;
-; }
-
-; num_chunks = num_chunks_in;
-; }
-
-; old_num_chunks = png_ptr->num_chunk_list;
-; if (png_ptr->chunk_list == NULL)
-; old_num_chunks = 0;
-
- ; Since num_chunks is always restricted to UINT_MAX/5 this can't overflow.
-
-; if (num_chunks + old_num_chunks > UINT_MAX/5)
-; {
-; png_app_error(png_ptr, "png_set_keep_unknown_chunks: too many chunks");
-
-; return;
-; }
-
- ; If these chunks are being reset to the default then no more memory is
- ; required because add_one_chunk above doesn't extend the list if the 'keep'
- ; parameter is the default.
-
-; if (keep != 0)
-; {
-; new_list = png_malloc(png_ptr, 5 * (num_chunks + old_num_chunks));
-;
-; if (old_num_chunks > 0)
-; memcpy(new_list, png_ptr->chunk_list, 5*old_num_chunks);
-; }
-
-; else if (old_num_chunks > 0)
-; new_list = png_ptr->chunk_list;
-
-; else
-; new_list = NULL;
-
- ; Add the new chunks together with each one's handling code. If the chunk
- ; already exists the code is updated, otherwise the chunk is added to the
- ; end. (In libpng 1.6.0 order no longer matters because this code enforces
- ; the earlier convention that the last setting is the one that is used.)
-
-; if (new_list != NULL)
-; {
-; bytep inlist;
-; bytep outlist;
-; uint i;
-
-; for (i=0; ichunk_list != new_list)
-; png_free(png_ptr, new_list);
-;
-; new_list = NULL;
-; }
-; }
-;
-; else
-; num_chunks = 0;
-;
-; png_ptr->num_chunk_list = num_chunks;
-;
-; if (png_ptr->chunk_list != new_list)
-; {
-; if (png_ptr->chunk_list != NULL)
-; png_free(png_ptr, png_ptr->chunk_list);
-;
-; png_ptr->chunk_list = new_list;
-; }
-.end_f:
- ret
-endp
-;end if
-
-;void (png_structrp png_ptr, voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)
-align 4
-proc png_set_read_user_chunk_fn uses eax edi, png_ptr:dword, user_chunk_ptr:dword, read_user_chunk_fn:dword
- png_debug 1, 'in png_set_read_user_chunk_fn'
-
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f
-
- mov eax,[read_user_chunk_fn]
- mov [edi+png_struct.read_user_chunk_fn],eax
- mov eax,[user_chunk_ptr]
- mov [edi+png_struct.user_chunk_ptr],eax
-.end_f:
- ret
-endp
-
-;void (png_structrp png_ptr, png_inforp info_ptr, bytepp row_pointers)
-align 4
-proc png_set_rows uses eax edi esi, png_ptr:dword, info_ptr:dword, row_pointers:dword
- png_debug1 1, 'in %s storage function', 'rows'
-
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f
- mov esi,[info_ptr]
- cmp esi,0
- je .end_f ;if (..==0 || ..==0) return
-
- mov eax,[row_pointers]
- cmp dword[esi+png_info_def.row_pointers],0
- je @f
- cmp [esi+png_info_def.row_pointers],eax
- je @f ;if (..!=0 && ..!=..)
- stdcall png_free_data, edi, esi, PNG_FREE_ROWS, 0
- @@:
- mov [esi+png_info_def.row_pointers],eax
-
- cmp eax,0
- je .end_f ;if (..!=0)
- or dword[esi+png_info_def.valid],PNG_INFO_IDAT
-.end_f:
- ret
-endp
-
-;void (png_structrp png_ptr, png_size_t size)
-align 4
-proc png_set_compression_buffer_size uses edi, png_ptr:dword, size:dword
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f ;if (..==0) return
-
-; if (size == 0 || size > PNG_UINT_31_MAX)
-; png_error(png_ptr, "invalid compression buffer size");
-
-if PNG_SEQUENTIAL_READ_SUPPORTED eq 1
-; if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
-; {
-; png_ptr->IDAT_read_size = (uint_32)size; /* checked above */
-; return;
-; }
-end if
-
-if PNG_WRITE_SUPPORTED eq 1
-; if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
-; {
-; if (png_ptr->zowner != 0)
-; {
-; png_warning(png_ptr,
-; "Compression buffer size cannot be changed because it is in use");
-
-; return;
-; }
-
-;#ifndef __COVERITY__
- ; Some compilers complain that this is always false. However, it
- ; can be true when integer overflow happens.
-
-; if (size > ZLIB_IO_MAX)
-; {
-; png_warning(png_ptr,
-; "Compression buffer size limited to system maximum");
-; size = ZLIB_IO_MAX; /* must fit */
-; }
-;end if
-
-; if (size < 6)
-; {
- ; Deflate will potentially go into an infinite loop on a SYNC_FLUSH
- ; if this is permitted.
-
-; png_warning(png_ptr,
-; "Compression buffer size cannot be reduced below 6");
-
-; return;
-; }
-
-; if (png_ptr->zbuffer_size != size)
-; {
-; png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list);
-; png_ptr->zbuffer_size = (uInt)size;
-; }
-; }
-end if
-.end_f:
- ret
-endp
-
-;void (png_structrp png_ptr, png_inforp info_ptr, int mask)
-align 4
-proc png_set_invalid, png_ptr:dword, info_ptr:dword, mask:dword
-; if (png_ptr != NULL && info_ptr != NULL)
-; info_ptr->valid &= ~mask;
- ret
-endp
-
-; This function was added to libpng 1.2.6
-;void (png_structrp png_ptr, uint_32 user_width_max, uint_32 user_height_max)
-align 4
-proc png_set_user_limits uses eax edi, png_ptr:dword, user_width_max:dword, user_height_max:dword
- ; Images with dimensions larger than these limits will be
- ; rejected by png_set_IHDR(). To accept any PNG datastream
- ; regardless of dimensions, set both limits to 0x7fffffff.
-
- mov edi,[png_ptr]
- cmp edi,0
- je @f
- mov eax,[user_width_max]
- mov [edi+png_struct.user_width_max],eax
- mov eax,[user_height_max]
- mov [edi+png_struct.user_height_max],eax
- @@:
- ret
-endp
-
-; This function was added to libpng 1.4.0
-;void (png_structrp png_ptr, uint_32 user_chunk_cache_max)
-align 4
-proc png_set_chunk_cache_max, png_ptr:dword, user_chunk_cache_max:dword
-; if (png_ptr != NULL)
-; png_ptr->user_chunk_cache_max = user_chunk_cache_max;
- ret
-endp
-
-; This function was added to libpng 1.4.1
-;void (png_structrp png_ptr, png_alloc_size_t user_chunk_malloc_max)
-align 4
-proc png_set_chunk_malloc_max, png_ptr:dword, user_chunk_malloc_max:dword
-; if (png_ptr != NULL)
-; png_ptr->user_chunk_malloc_max = user_chunk_malloc_max;
- ret
-endp
-
-;void (png_structrp png_ptr, int allowed)
-align 4
-proc png_set_benign_errors uses edi, png_ptr:dword, allowed:dword
- png_debug 1, 'in png_set_benign_errors'
-
- ; If allowed is 1, png_benign_error() is treated as a warning.
- ; If allowed is 0, png_benign_error() is treated as an error (which
- ; is the default behavior if png_set_benign_errors() is not called).
-
- mov edi,[png_ptr]
- cmp dword[allowed],0
- je @f ;if (..!=0)
- or dword[edi+png_struct.flags], PNG_FLAG_BENIGN_ERRORS_WARN or PNG_FLAG_APP_WARNINGS_WARN or PNG_FLAG_APP_ERRORS_WARN
- jmp .end0
- @@: ;else
- and dword[edi+png_struct.flags], not (PNG_FLAG_BENIGN_ERRORS_WARN or PNG_FLAG_APP_WARNINGS_WARN or PNG_FLAG_APP_ERRORS_WARN)
- .end0:
- ret
-endp
-
-; Whether to report invalid palette index; added at libng-1.5.10.
-; It is possible for an indexed (color-type==3) PNG file to contain
-; pixels with invalid (out-of-range) indexes if the PLTE chunk has
-; fewer entries than the image's bit-depth would allow. We recover
-; from this gracefully by filling any incomplete palette with zeros
-; (opaque black). By default, when this occurs libpng will issue
-; a benign error. This API can be used to override that behavior.
-
-;void (png_structrp png_ptr, int allowed)
-align 4
-proc png_set_check_for_invalid_index, png_ptr:dword, allowed:dword
- png_debug 1, 'in png_set_check_for_invalid_index'
-
-; if (allowed > 0)
-; png_ptr->num_palette_max = 0;
-
-; else
-; png_ptr->num_palette_max = -1;
- ret
-endp
-
-; Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
-; and if invalid, correct the keyword rather than discarding the entire
-; chunk. The PNG 1.0 specification requires keywords 1-79 characters in
-; length, forbids leading or trailing whitespace, multiple internal spaces,
-; and the non-break space (0x80) from ISO 8859-1. Returns keyword length.
-
-; The 'new_key' buffer must be 80 characters in size (for the keyword plus a
-; trailing '\0'). If this routine returns 0 then there was no keyword, or a
-; valid one could not be generated, and the caller must png_error.
-
-;uint_32 (png_structrp png_ptr, charp key, bytep new_key)
-align 4
-proc png_check_keyword, png_ptr:dword, key:dword, new_key:dword
-;if PNG_WARNINGS_SUPPORTED
-; charp orig_key = key;
-;end if
-; uint_32 key_len = 0;
-; int bad_character = 0;
-; int space = 1;
-
- png_debug 1, 'in png_check_keyword'
-
-; if (key == NULL)
-; {
-; *new_key = 0;
-; return 0;
-; }
-
-; while (*key && key_len < 79)
-; {
-; byte ch = (byte)*key++;
-
-; if ((ch > 32 && ch <= 126) || (ch >= 161 /*&& ch <= 255*/))
-; *new_key++ = ch, ++key_len, space = 0;
-
-; else if (space == 0)
-; {
- ; A space or an invalid character when one wasn't seen immediately
- ; before; output just a space.
-
-; *new_key++ = 32, ++key_len, space = 1;
-
-; /* If the character was not a space then it is invalid. */
-; if (ch != 32)
-; bad_character = ch;
-; }
-
-; else if (bad_character == 0)
-; bad_character = ch; /* just skip it, record the first error */
-; }
-
-; if (key_len > 0 && space != 0) /* trailing space */
-; {
-; --key_len, --new_key;
-; if (bad_character == 0)
-; bad_character = 32;
-; }
-
- ; Terminate the keyword
-; *new_key = 0;
-
-; if (key_len == 0)
-; return 0;
-
-if PNG_WARNINGS_SUPPORTED eq 1
- ; Try to only output one warning per keyword:
-; if (*key != 0) /* keyword too long */
-; png_warning(png_ptr, "keyword truncated");
-
-; else if (bad_character != 0)
-; {
-; PNG_WARNING_PARAMETERS(p)
-
-; png_warning_parameter(p, 1, orig_key);
-; png_warning_parameter_signed(p, 2, PNG_NUMBER_FORMAT_02x, bad_character);
-
-; png_formatted_warning(png_ptr, p, "keyword \"@1\": bad character '0x@2'");
-; }
-end if ;!WARNINGS
-
-; return key_len;
- ret
-endp
-
+
+; pngset.asm - storage of image information into info struct
+
+; Last changed in libpng 1.6.24 [August 4, 2016]
+; Copyright (c) 1998-2016 Glenn Randers-Pehrson
+; (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+; (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+
+; This code is released under the libpng license.
+; For conditions of distribution and use, see the disclaimer
+; and license in png.inc
+
+; The functions here are used during reads to store data from the file
+; into the info struct, and during writes to store application data
+; into the info struct for writing into the file. This abstracts the
+; info struct and allows us to change the structure in the future.
+
+
+;void (png_structrp png_ptr, png_inforp info_ptr, png_color_16p background)
+align 4
+proc png_set_bKGD uses ecx edi esi, png_ptr:dword, info_ptr:dword, background:dword
+ png_debug1 1, 'in %s storage function', 'bKGD'
+
+ cmp dword[png_ptr],0
+ je .end_f
+ mov edi,[info_ptr]
+ cmp edi,0
+ je .end_f
+ mov esi,[background]
+ cmp esi,0
+ je .end_f ;if (..==0 || ..==0 || ..==0) return
+
+ or dword[edi+png_info_def.valid],PNG_INFO_bKGD
+ add edi,png_info_def.background
+ mov ecx,sizeof.png_color_16
+ rep movsb
+.end_f:
+ ret
+endp
+
+;void (png_structrp png_ptr, png_inforp info_ptr,
+; png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x,
+; png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y,
+; png_fixed_point blue_x, png_fixed_point blue_y)
+align 4
+proc png_set_cHRM_fixed, png_ptr:dword, info_ptr:dword,\
+ white_x:dword, white_y:dword, red_x:dword, red_y:dword,\
+ green_x:dword, green_y:dword, blue_x:dword, blue_y:dword
+; png_xy xy;
+
+ png_debug1 1, 'in %s storage function', 'cHRM fixed'
+
+; if (png_ptr == NULL || info_ptr == NULL)
+; return;
+
+; xy.redx = red_x;
+; xy.redy = red_y;
+; xy.greenx = green_x;
+; xy.greeny = green_y;
+; xy.bluex = blue_x;
+; xy.bluey = blue_y;
+; xy.whitex = white_x;
+; xy.whitey = white_y;
+
+; if (png_colorspace_set_chromaticities(png_ptr, &info_ptr->colorspace, &xy,
+; 2/* override with app values*/) != 0)
+; info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM;
+
+; png_colorspace_sync_info(png_ptr, info_ptr);
+.end_f:
+ ret
+endp
+
+;void (png_structrp png_ptr, png_inforp info_ptr,
+; png_fixed_point int_red_X, png_fixed_point int_red_Y,
+; png_fixed_point int_red_Z, png_fixed_point int_green_X,
+; png_fixed_point int_green_Y, png_fixed_point int_green_Z,
+; png_fixed_point int_blue_X, png_fixed_point int_blue_Y,
+; png_fixed_point int_blue_Z)
+align 4
+proc png_set_cHRM_XYZ_fixed uses edi esi, png_ptr:dword, info_ptr:dword,\
+ int_red_X:dword, int_red_Y:dword, int_red_Z:dword,\
+ int_green_X:dword, int_green_Y:dword, int_green_Z:dword,\
+ int_blue_X:dword, int_blue_Y:dword, int_blue_Z:dword
+; png_XYZ XYZ;
+
+ png_debug1 1, 'in %s storage function', 'cHRM XYZ fixed'
+
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f
+ mov esi,[info_ptr]
+ cmp esi,0
+ je .end_f ;if (..==0 || ..==0) return
+
+; XYZ.red_X = int_red_X;
+; XYZ.red_Y = int_red_Y;
+; XYZ.red_Z = int_red_Z;
+; XYZ.green_X = int_green_X;
+; XYZ.green_Y = int_green_Y;
+; XYZ.green_Z = int_green_Z;
+; XYZ.blue_X = int_blue_X;
+; XYZ.blue_Y = int_blue_Y;
+; XYZ.blue_Z = int_blue_Z;
+
+; if (png_colorspace_set_endpoints(png_ptr, &info_ptr->colorspace,
+; &XYZ, 2) != 0)
+; info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM;
+
+ stdcall png_colorspace_sync_info, edi, esi
+.end_f:
+ ret
+endp
+
+;void (png_structrp png_ptr, png_inforp info_ptr,
+; double white_x, double white_y, double red_x, double red_y,
+; double green_x, double green_y, double blue_x, double blue_y)
+align 4
+proc png_set_cHRM, png_ptr:dword, info_ptr:dword,\
+ white_x:dword, white_y:dword, red_x:dword, red_y:dword,\
+ green_x:dword, green_y:dword, blue_x:dword, blue_y:dword
+; png_set_cHRM_fixed(png_ptr, info_ptr,
+; png_fixed(png_ptr, white_x, "cHRM White X"),
+; png_fixed(png_ptr, white_y, "cHRM White Y"),
+; png_fixed(png_ptr, red_x, "cHRM Red X"),
+; png_fixed(png_ptr, red_y, "cHRM Red Y"),
+; png_fixed(png_ptr, green_x, "cHRM Green X"),
+; png_fixed(png_ptr, green_y, "cHRM Green Y"),
+; png_fixed(png_ptr, blue_x, "cHRM Blue X"),
+; png_fixed(png_ptr, blue_y, "cHRM Blue Y"));
+ ret
+endp
+
+;void (png_structrp png_ptr, png_inforp info_ptr, double red_X,
+; double red_Y, double red_Z, double green_X, double green_Y, double green_Z,
+; double blue_X, double blue_Y, double blue_Z)
+align 4
+proc png_set_cHRM_XYZ, png_ptr:dword, info_ptr:dword, red_X:dword, red_Y:dword, red_Z:dword, green_X:dword, green_Y:dword, green_Z:dword, blue_X:dword, blue_Y:dword, blue_Z:dword
+; png_set_cHRM_XYZ_fixed(png_ptr, info_ptr,
+; png_fixed(png_ptr, red_X, "cHRM Red X"),
+; png_fixed(png_ptr, red_Y, "cHRM Red Y"),
+; png_fixed(png_ptr, red_Z, "cHRM Red Z"),
+; png_fixed(png_ptr, green_X, "cHRM Green X"),
+; png_fixed(png_ptr, green_Y, "cHRM Green Y"),
+; png_fixed(png_ptr, green_Z, "cHRM Green Z"),
+; png_fixed(png_ptr, blue_X, "cHRM Blue X"),
+; png_fixed(png_ptr, blue_Y, "cHRM Blue Y"),
+; png_fixed(png_ptr, blue_Z, "cHRM Blue Z"));
+ ret
+endp
+
+;void (png_structrp png_ptr, png_inforp info_ptr, png_fixed_point file_gamma)
+align 4
+proc png_set_gAMA_fixed uses eax edi esi, png_ptr:dword, info_ptr:dword, file_gamma:dword
+ png_debug1 1, 'in %s storage function', 'gAMA'
+
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f
+ mov esi,[info_ptr]
+ cmp esi,0
+ je .end_f ;if (..== 0 || ..== 0) return
+
+ mov eax,esi
+ add eax,png_info_def.colorspace
+ stdcall png_colorspace_set_gamma, edi, eax, [file_gamma]
+ stdcall png_colorspace_sync_info, edi, esi
+.end_f:
+ ret
+endp
+
+;void (png_structrp png_ptr, png_inforp info_ptr, double file_gamma)
+align 4
+proc png_set_gAMA uses eax, png_ptr:dword, info_ptr:dword, file_gamma:dword
+ cStr ,'png_set_gAMA'
+ stdcall png_fixed, [png_ptr], [file_gamma], eax
+ stdcall png_set_gAMA_fixed, [png_ptr], [info_ptr], eax
+ ret
+endp
+
+;void (png_structrp png_ptr, png_inforp info_ptr, png_uint_16p hist)
+align 4
+proc png_set_hIST uses edi esi, png_ptr:dword, info_ptr:dword, hist:dword
+; int i;
+
+ png_debug1 1, 'in %s storage function', 'hIST'
+
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f
+ mov esi,[info_ptr]
+ cmp esi,0
+ je .end_f ;if (..== 0 || ..== 0) return
+
+; if (info_ptr->num_palette == 0 || info_ptr->num_palette
+; > PNG_MAX_PALETTE_LENGTH)
+; {
+; png_warning(png_ptr,
+; "Invalid palette size, hIST allocation skipped");
+
+; return;
+; }
+
+; png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0);
+
+ ; Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in
+ ; version 1.2.1
+
+; info_ptr->hist = png_malloc_warn(png_ptr,
+; PNG_MAX_PALETTE_LENGTH * (sizeof (uint_16)));
+
+; if (info_ptr->hist == NULL)
+; {
+; png_warning(png_ptr, "Insufficient memory for hIST chunk data");
+
+; return;
+; }
+
+; info_ptr->free_me |= PNG_FREE_HIST;
+
+; for (i = 0; i < info_ptr->num_palette; i++)
+; info_ptr->hist[i] = hist[i];
+
+ or dword[esi+png_info_def.valid], PNG_INFO_hIST
+.end_f:
+ ret
+endp
+
+;void (png_structrp png_ptr, png_inforp info_ptr,
+; uint_32 width, uint_32 height, int bit_depth,
+; int color_type, int interlace_type, int compression_type, int filter_type)
+align 4
+proc png_set_IHDR, png_ptr:dword, info_ptr:dword,\
+ width:dword, height:dword, bit_depth:dword, color_type:dword,\
+ interlace_type:dword, compression_type:dword, filter_type:dword
+ png_debug1 1, 'in %s storage function', 'IHDR'
+pushad
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f
+ mov esi,[info_ptr]
+ cmp esi,0
+ je .end_f ;if (..== 0 || ..== 0) return
+
+ mov eax,[width]
+ mov [esi+png_info_def.width],eax
+ mov eax,[height]
+ mov [esi+png_info_def.height],eax
+ movzx eax,byte[filter_type]
+ mov [esi+png_info_def.filter_type],al
+ push eax
+ movzx eax,byte[compression_type]
+ mov [esi+png_info_def.compression_type],al
+ push eax
+ movzx eax,byte[interlace_type]
+ mov [esi+png_info_def.interlace_type],al
+ push eax
+ movzx ebx,byte[color_type]
+ mov [esi+png_info_def.color_type],bl
+ push ebx
+ movzx ecx,byte[bit_depth]
+ mov [esi+png_info_def.bit_depth],cl
+
+ stdcall png_check_IHDR, edi, dword[esi+png_info_def.width], dword[esi+png_info_def.height], ecx
+ ;, color_type, interlace_type, compression_type, filter_type
+
+ cmp ebx,PNG_COLOR_TYPE_PALETTE
+ jne @f ;if (..==..)
+ mov byte[esi+png_info_def.channels], 1
+ jmp .end0
+ @@:
+ mov eax,ebx
+ and eax,PNG_COLOR_MASK_COLOR
+ cmp eax,0
+ je @f ;else if (..!=0)
+ mov byte[esi+png_info_def.channels], 3
+ jmp .end0
+ @@: ;else
+ mov byte[esi+png_info_def.channels], 1
+ .end0:
+
+ mov eax,ebx
+ and eax,PNG_COLOR_MASK_ALPHA
+ cmp eax,0
+ je @f ;else if (..!=0)
+ inc byte[esi+png_info_def.channels]
+ @@:
+
+ movzx eax,byte[esi+png_info_def.channels]
+ imul eax,ecx
+ mov byte[esi+png_info_def.pixel_depth],al ;channels * bit_depth
+
+ PNG_ROWBYTES eax, [width]
+ mov [esi+png_info_def.rowbytes], eax
+.end_f:
+popad
+ ret
+endp
+
+;if PNG_oFFs_SUPPORTED
+;void (png_structrp png_ptr, png_inforp info_ptr,
+; int_32 offset_x, int_32 offset_y, int unit_type)
+align 4
+proc png_set_oFFs uses eax esi, png_ptr:dword, info_ptr:dword, offset_x:dword, offset_y:dword, unit_type:dword
+ png_debug1 1, 'in %s storage function', 'oFFs'
+
+ cmp dword[png_ptr],0
+ je @f
+ mov esi,[info_ptr]
+ cmp esi,0
+ je @f ;if (..==0 || ..==0) return
+
+ mov eax,[offset_x]
+ mov [esi+png_info_def.x_offset],eax
+ mov eax,[offset_y]
+ mov [esi+png_info_def.y_offset],eax
+ mov al,[unit_type]
+ mov [esi+png_info_def.offset_unit_type],al
+ or dword[esi+png_info_def.valid], PNG_INFO_oFFs
+ @@:
+ ret
+endp
+
+;void (png_structrp png_ptr, png_inforp info_ptr,
+; charp purpose, int_32 X0, int_32 X1, int type,
+; int nparams, charp units, charpp params)
+align 4
+proc png_set_pCAL uses edi esi, png_ptr:dword, info_ptr:dword, purpose:dword, X0:dword, X1:dword, type:dword, nparams:dword, units:dword, params:dword
+; png_size_t length;
+; int i;
+
+ png_debug1 1, 'in %s storage function', 'pCAL'
+
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f
+ mov esi,[info_ptr]
+ cmp esi,0
+ je .end_f
+ cmp dword[purpose],0
+ je .end_f
+ cmp dword[units],0
+ je .end_f
+ cmp dword[nparams],0
+ jle @f
+ cmp dword[params],0
+ jne @f
+ jmp .end_f
+ @@: ;if (..==0 || ..==0 || ..==0 || ..==0 || (nparams > 0 && params == 0)) return
+
+; length = strlen(purpose) + 1;
+ png_debug1 3, 'allocating purpose for info (%lu bytes)','(unsigned long)length'
+
+ ; TODO: validate format of calibration name and unit name
+
+ ; Check that the type matches the specification.
+ cmp dword[type],0
+ jl @f
+ cmp dword[type],3
+ jle .end0 ;if (..<0 || ..>3)
+ @@:
+ png_error edi, 'Invalid pCAL equation type'
+ .end0:
+
+ cmp dword[nparams],0
+ jl @f
+ cmp dword[nparams],255
+ jle .end1 ;if (..<0 || ..>255)
+ @@:
+ png_error edi, 'Invalid pCAL parameter count'
+ .end1:
+
+ ; Validate params[nparams]
+; for (i=0; ipcal_purpose = png_malloc_warn(png_ptr, length);
+
+; if (info_ptr->pcal_purpose == NULL)
+; {
+; png_warning(png_ptr, "Insufficient memory for pCAL purpose");
+
+; return;
+; }
+
+; memcpy(info_ptr->pcal_purpose, purpose, length);
+
+ png_debug 3, 'storing X0, X1, type, and nparams in info'
+; info_ptr->pcal_X0 = X0;
+; info_ptr->pcal_X1 = X1;
+; info_ptr->pcal_type = (byte)type;
+; info_ptr->pcal_nparams = (byte)nparams;
+
+; length = strlen(units) + 1;
+ png_debug1 3, 'allocating units for info (%lu bytes)','(unsigned long)length'
+
+; info_ptr->pcal_units = png_malloc_warn(png_ptr, length);
+
+; if (info_ptr->pcal_units == NULL)
+; {
+; png_warning(png_ptr, "Insufficient memory for pCAL units");
+
+; return;
+; }
+
+; memcpy(info_ptr->pcal_units, units, length);
+
+; info_ptr->pcal_params = png_malloc_warn(png_ptr,
+; (png_size_t)((nparams + 1) * (sizeof (charp))));
+
+; if (info_ptr->pcal_params == NULL)
+; {
+; png_warning(png_ptr, "Insufficient memory for pCAL params");
+
+; return;
+; }
+
+; memset(info_ptr->pcal_params, 0, (nparams + 1) * (sizeof (charp)));
+
+; for (i = 0; i < nparams; i++)
+; {
+; length = strlen(params[i]) + 1;
+; png_debug2(3, "allocating parameter %d for info (%lu bytes)", i,
+; (unsigned long)length);
+
+; info_ptr->pcal_params[i] = (charp)png_malloc_warn(png_ptr, length);
+
+; if (info_ptr->pcal_params[i] == NULL)
+; {
+; png_warning(png_ptr, "Insufficient memory for pCAL parameter");
+
+; return;
+; }
+
+; memcpy(info_ptr->pcal_params[i], params[i], length);
+; }
+
+ or dword[esi+png_info_def.valid],PNG_INFO_pCAL
+ or dword[esi+png_info_def.free_me],PNG_FREE_PCAL
+.end_f:
+ ret
+endp
+
+;void (png_structrp png_ptr, png_inforp info_ptr,
+; int unit, charp swidth, charp sheight)
+align 4
+proc png_set_sCAL_s, png_ptr:dword, info_ptr:dword, unit:dword, swidth:dword, sheight:dword
+; png_size_t lengthw = 0, lengthh = 0;
+
+ png_debug1 1, 'in %s storage function', 'sCAL'
+
+; if (png_ptr == NULL || info_ptr == NULL)
+; return;
+
+ ; Double check the unit (should never get here with an invalid
+ ; unit unless this is an API call.)
+
+; if (unit != 1 && unit != 2)
+; png_error(png_ptr, "Invalid sCAL unit");
+
+; if (swidth == NULL || (lengthw = strlen(swidth)) == 0 ||
+; swidth[0] == 45 /* '-' */ || !png_check_fp_string(swidth, lengthw))
+; png_error(png_ptr, "Invalid sCAL width");
+
+; if (sheight == NULL || (lengthh = strlen(sheight)) == 0 ||
+; sheight[0] == 45 /* '-' */ || !png_check_fp_string(sheight, lengthh))
+; png_error(png_ptr, "Invalid sCAL height");
+
+; info_ptr->scal_unit = (byte)unit;
+
+; ++lengthw;
+
+; png_debug1(3, "allocating unit for info (%u bytes)", (uint)lengthw);
+
+; info_ptr->scal_s_width = png_malloc_warn(png_ptr, lengthw);
+
+; if (info_ptr->scal_s_width == NULL)
+; {
+; png_warning(png_ptr, "Memory allocation failed while processing sCAL");
+
+; return;
+; }
+
+; memcpy(info_ptr->scal_s_width, swidth, lengthw);
+
+; ++lengthh;
+
+; png_debug1(3, "allocating unit for info (%u bytes)", (uint)lengthh);
+
+; info_ptr->scal_s_height = png_malloc_warn(png_ptr, lengthh);
+
+; if (info_ptr->scal_s_height == NULL)
+; {
+; png_free (png_ptr, info_ptr->scal_s_width);
+; info_ptr->scal_s_width = NULL;
+
+; png_warning(png_ptr, "Memory allocation failed while processing sCAL");
+
+; return;
+; }
+
+; memcpy(info_ptr->scal_s_height, sheight, lengthh);
+;
+; info_ptr->valid |= PNG_INFO_sCAL;
+; info_ptr->free_me |= PNG_FREE_SCAL;
+ ret
+endp
+
+;void (png_structrp png_ptr, png_inforp info_ptr, int unit,
+; double width, double height)
+align 4
+proc png_set_sCAL, png_ptr:dword, info_ptr:dword, unit:dword, width:dword, height:dword
+ png_debug1 1, 'in %s storage function', 'sCAL'
+
+ ; Check the arguments.
+; if (width <= 0)
+; png_warning(png_ptr, "Invalid sCAL width ignored");
+
+; else if (height <= 0)
+; png_warning(png_ptr, "Invalid sCAL height ignored");
+
+; else
+; {
+ ; Convert 'width' and 'height' to ASCII.
+; char swidth[PNG_sCAL_MAX_DIGITS+1];
+; char sheight[PNG_sCAL_MAX_DIGITS+1];
+
+; png_ascii_from_fp(png_ptr, swidth, (sizeof swidth), width,
+; PNG_sCAL_PRECISION);
+; png_ascii_from_fp(png_ptr, sheight, (sizeof sheight), height,
+; PNG_sCAL_PRECISION);
+
+; png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight);
+; }
+ ret
+endp
+
+;void (png_structrp png_ptr, png_inforp info_ptr, int unit,
+; png_fixed_point width, png_fixed_point height)
+align 4
+proc png_set_sCAL_fixed uses ebx ecx edi, png_ptr:dword, info_ptr:dword, unit:dword, width:dword, height:dword
+locals
+ swidth rb PNG_sCAL_MAX_DIGITS+1 ;char[]
+ sheight rb PNG_sCAL_MAX_DIGITS+1 ;char[]
+endl
+ png_debug1 1, 'in %s storage function', 'sCAL'
+ mov edi,[png_ptr]
+
+ ; Check the arguments.
+ cmp dword[width],0
+ jg @f ;if (..<=0)
+ png_warning edi, 'Invalid sCAL width ignored'
+ jmp .end0
+ @@:
+ cmp dword[height],0
+ jg @f ;else if (..<=0)
+ png_warning edi, 'Invalid sCAL height ignored'
+ jmp .end0
+ @@: ;else
+ ; Convert 'width' and 'height' to ASCII.
+ mov ebx,ebp
+ sub ebx,PNG_sCAL_MAX_DIGITS+1 ;sheight
+ mov ecx,ebx
+ sub ecx,PNG_sCAL_MAX_DIGITS+1 ;swidth
+
+ stdcall png_ascii_from_fixed, edi, ecx, PNG_sCAL_MAX_DIGITS+1, [width]
+ stdcall png_ascii_from_fixed, edi, ebx, PNG_sCAL_MAX_DIGITS+1, [height]
+
+ stdcall png_set_sCAL_s, edi, [info_ptr], [unit], ecx, ebx
+ .end0:
+ ret
+endp
+
+;void (png_structrp png_ptr, png_inforp info_ptr,
+; uint_32 res_x, uint_32 res_y, int unit_type)
+align 4
+proc png_set_pHYs, png_ptr:dword, info_ptr:dword, res_x:dword, res_y:dword, unit_type:dword
+ png_debug1 1, 'in %s storage function', 'pHYs'
+
+; if (png_ptr == NULL || info_ptr == NULL)
+; return;
+
+; info_ptr->x_pixels_per_unit = res_x;
+; info_ptr->y_pixels_per_unit = res_y;
+; info_ptr->phys_unit_type = (byte)unit_type;
+; info_ptr->valid |= PNG_INFO_pHYs;
+ ret
+endp
+
+;void (png_structrp png_ptr, png_inforp info_ptr, png_colorp palette, int num_palette)
+align 4
+proc png_set_PLTE uses eax edi esi, png_ptr:dword, info_ptr:dword, palette:dword, num_palette:dword
+; uint_32 max_palette_length;
+
+ png_debug1 1, 'in %s storage function', 'PLTE'
+
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f
+ mov esi,[info_ptr]
+ cmp esi,0
+ je .end_f ;if (..==0 || ..==0) return
+
+; max_palette_length = (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ?
+; (1 << info_ptr->bit_depth) : PNG_MAX_PALETTE_LENGTH;
+
+; if (num_palette < 0 || num_palette > (int) max_palette_length)
+; {
+; if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+; png_error(png_ptr, "Invalid palette length");
+
+; else
+; {
+; png_warning(png_ptr, "Invalid palette length");
+
+; return;
+; }
+; }
+
+; if ((num_palette > 0 && palette == NULL) ||
+; (num_palette == 0
+if PNG_MNG_FEATURES_SUPPORTED eq 1
+; && (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0
+end if
+; ))
+; {
+; png_error(png_ptr, "Invalid palette");
+; }
+
+ ; It may not actually be necessary to set png_ptr->palette here;
+ ; we do it for backward compatibility with the way the png_handle_tRNS
+ ; function used to do the allocation.
+
+ ; 1.6.0: the above statement appears to be incorrect; something has to set
+ ; the palette inside png_struct on read.
+
+ stdcall png_free_data, edi, esi, PNG_FREE_PLTE, 0
+
+ ; Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead
+ ; of num_palette entries, in case of an invalid PNG file or incorrect
+ ; call to png_set_PLTE() with too-large sample values.
+
+; png_ptr->palette = png_calloc(png_ptr,
+; PNG_MAX_PALETTE_LENGTH * (sizeof (png_color)));
+
+; if (num_palette > 0)
+; memcpy(png_ptr->palette, palette, num_palette * (sizeof (png_color)));
+ mov eax,[edi+png_struct.palette]
+ mov [esi+png_info_def.palette],eax
+; info_ptr->num_palette = png_ptr->num_palette = (uint_16)num_palette;
+
+ or dword[esi+png_info_def.free_me], PNG_FREE_PLTE
+ or dword[esi+png_info_def.valid], PNG_INFO_PLTE
+.end_f:
+ ret
+endp
+
+;void (png_structrp png_ptr, png_inforp info_ptr, png_color_8p sig_bit)
+align 4
+proc png_set_sBIT, png_ptr:dword, info_ptr:dword, sig_bit:dword
+ png_debug1 1, 'in %s storage function', 'sBIT'
+
+; if (png_ptr == NULL || info_ptr == NULL || sig_bit == NULL)
+; return;
+
+; info_ptr->sig_bit = *sig_bit;
+; info_ptr->valid |= PNG_INFO_sBIT;
+.end_f:
+ ret
+endp
+
+;void (png_structrp png_ptr, png_inforp info_ptr, int srgb_intent)
+align 4
+proc png_set_sRGB uses eax edi esi, png_ptr:dword, info_ptr:dword, srgb_intent:dword
+ png_debug1 1, 'in %s storage function', 'sRGB'
+
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f
+ mov esi,[info_ptr]
+ cmp esi,0
+ je .end_f ;if (..==0 || ..==0)
+
+ mov eax,esi
+ add eax,png_info_def.colorspace
+ stdcall png_colorspace_set_sRGB, edi, eax, [srgb_intent]
+ stdcall png_colorspace_sync_info, edi, esi
+.end_f:
+ ret
+endp
+
+;void (png_structrp png_ptr, png_inforp info_ptr, int srgb_intent)
+align 4
+proc png_set_sRGB_gAMA_and_cHRM, png_ptr:dword, info_ptr:dword, srgb_intent:dword
+ png_debug1 1, 'in %s storage function', 'sRGB_gAMA_and_cHRM'
+
+; if (png_ptr == NULL || info_ptr == NULL)
+; return;
+
+; if (png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace,
+; srgb_intent) != 0)
+; {
+ ; This causes the gAMA and cHRM to be written too
+; info_ptr->colorspace.flags |=
+; PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM;
+; }
+
+; png_colorspace_sync_info(png_ptr, info_ptr);
+.end_f:
+ ret
+endp
+
+;void (const_structrp png_ptr, png_inforp info_ptr,
+; charp name, int compression_type, bytep profile, uint_32 proflen)
+align 4
+proc png_set_iCCP uses edi esi, png_ptr:dword, info_ptr:dword, name:dword, compression_type:dword, profile:dword, proflen:dword
+; charp new_iccp_name;
+; bytep new_iccp_profile;
+; png_size_t length;
+
+ png_debug1 1, 'in %s storage function', 'iCCP'
+
+ mov esi,[info_ptr]
+; if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL)
+; return;
+
+; if (compression_type != PNG_COMPRESSION_TYPE_BASE)
+; png_app_error(png_ptr, "Invalid iCCP compression method");
+
+ ; Set the colorspace first because this validates the profile; do not
+ ; override previously set app cHRM or gAMA here (because likely as not the
+ ; application knows better than libpng what the correct values are.) Pass
+ ; the info_ptr color_type field to png_colorspace_set_ICC because in the
+ ; write case it has not yet been stored in png_ptr.
+
+; {
+; int result = png_colorspace_set_ICC(png_ptr, &info_ptr->colorspace, name,
+; proflen, profile, info_ptr->color_type);
+
+; png_colorspace_sync_info(png_ptr, info_ptr);
+
+ ; Don't do any of the copying if the profile was bad, or inconsistent.
+; if (result == 0)
+; return;
+
+ ; But do write the gAMA and cHRM chunks from the profile.
+; info_ptr->colorspace.flags |=
+; PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM;
+; }
+
+; length = strlen(name)+1;
+; new_iccp_name = png_malloc_warn(png_ptr, length);
+
+; if (new_iccp_name == NULL)
+; {
+; png_benign_error(png_ptr, "Insufficient memory to process iCCP chunk");
+; return;
+; }
+
+; memcpy(new_iccp_name, name, length);
+; new_iccp_profile = png_malloc_warn(png_ptr, proflen);
+
+; if (new_iccp_profile == NULL)
+; {
+; png_free(png_ptr, new_iccp_name);
+; png_benign_error(png_ptr,
+; "Insufficient memory to process iCCP profile");
+; return;
+; }
+
+; memcpy(new_iccp_profile, profile, proflen);
+
+; png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0);
+
+; info_ptr->iccp_proflen = proflen;
+; info_ptr->iccp_name = new_iccp_name;
+; info_ptr->iccp_profile = new_iccp_profile;
+ or dword[esi+png_info_def.free_me],PNG_FREE_ICCP
+ or dword[esi+png_info_def.valid],PNG_INFO_iCCP
+ ret
+endp
+
+;void (png_structrp png_ptr, png_inforp info_ptr, png_textp text_ptr, int num_text)
+align 4
+proc png_set_text uses eax edi, png_ptr:dword, info_ptr:dword, text_ptr:dword, num_text:dword
+ mov edi,[png_ptr]
+ stdcall png_set_text_2, edi, [info_ptr], [text_ptr], [num_text]
+
+ cmp eax,0
+ je @f ;if (..!=0)
+ png_error edi, 'Insufficient memory to store text'
+ @@:
+ ret
+endp
+
+;int (png_structrp png_ptr, png_inforp info_ptr,
+; png_textp text_ptr, int num_text)
+align 4
+proc png_set_text_2, png_ptr:dword, info_ptr:dword, text_ptr:dword, num_text:dword
+; int i;
+
+ png_debug1 1, 'in %lx storage function', 'png_ptr == NULL ? 0xabadca11 : (unsigned long)png_ptr->chunk_name'
+
+; if (png_ptr == NULL || info_ptr == NULL || num_text <= 0 || text_ptr == NULL)
+; return(0);
+
+ ; Make sure we have enough space in the "text" array in info_struct
+ ; to hold all of the incoming text_ptr objects. This compare can't overflow
+ ; because max_text >= num_text (anyway, subtract of two positive integers
+ ; can't overflow in any case.)
+
+; if (num_text > info_ptr->max_text - info_ptr->num_text)
+; {
+; int old_num_text = info_ptr->num_text;
+; int max_text;
+; png_textp new_text = NULL;
+
+; /* Calculate an appropriate max_text, checking for overflow. */
+; max_text = old_num_text;
+; if (num_text <= INT_MAX - max_text)
+; {
+; max_text += num_text;
+
+; /* Round up to a multiple of 8 */
+; if (max_text < INT_MAX-8)
+; max_text = (max_text + 8) & ~0x7;
+
+; else
+; max_text = INT_MAX;
+
+ ; Now allocate a new array and copy the old members in; this does all
+ ; the overflow checks.
+
+; new_text = png_realloc_array(png_ptr,
+; info_ptr->text, old_num_text, max_text-old_num_text,
+; sizeof *new_text);
+; }
+
+; if (new_text == NULL)
+; {
+; png_chunk_report(png_ptr, "too many text chunks",
+; PNG_CHUNK_WRITE_ERROR);
+
+; return 1;
+; }
+
+; png_free(png_ptr, info_ptr->text);
+
+; info_ptr->text = new_text;
+; info_ptr->free_me |= PNG_FREE_TEXT;
+; info_ptr->max_text = max_text;
+; /* num_text is adjusted below as the entries are copied in */
+
+; png_debug1(3, "allocated %d entries for info_ptr->text", max_text);
+; }
+
+; for (i = 0; i < num_text; i++)
+; {
+; size_t text_length, key_len;
+; size_t lang_len, lang_key_len;
+; png_textp textp = &(info_ptr->text[info_ptr->num_text]);
+
+; if (text_ptr[i].key == NULL)
+; continue;
+
+; if (text_ptr[i].compression < PNG_TEXT_COMPRESSION_NONE ||
+; text_ptr[i].compression >= PNG_TEXT_COMPRESSION_LAST)
+; {
+; png_chunk_report(png_ptr, "text compression mode is out of range",
+; PNG_CHUNK_WRITE_ERROR);
+; continue;
+; }
+
+; key_len = strlen(text_ptr[i].key);
+
+; if (text_ptr[i].compression <= 0)
+; {
+; lang_len = 0;
+; lang_key_len = 0;
+; }
+
+; else
+if PNG_iTXt_SUPPORTED eq 1
+; {
+; /* Set iTXt data */
+
+; if (text_ptr[i].lang != NULL)
+; lang_len = strlen(text_ptr[i].lang);
+;
+; else
+; lang_len = 0;
+
+; if (text_ptr[i].lang_key != NULL)
+; lang_key_len = strlen(text_ptr[i].lang_key);
+
+; else
+; lang_key_len = 0;
+; }
+else ;iTXt
+; {
+; png_chunk_report(png_ptr, "iTXt chunk not supported",
+; PNG_CHUNK_WRITE_ERROR);
+; continue;
+; }
+end if
+
+; if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0')
+; {
+; text_length = 0;
+if PNG_iTXt_SUPPORTED eq 1
+; if (text_ptr[i].compression > 0)
+; textp->compression = PNG_ITXT_COMPRESSION_NONE;
+
+; else
+end if
+; textp->compression = PNG_TEXT_COMPRESSION_NONE;
+; }
+
+; else
+; {
+; text_length = strlen(text_ptr[i].text);
+; textp->compression = text_ptr[i].compression;
+; }
+
+; textp->key = png_malloc_base(png_ptr,
+; key_len + text_length + lang_len + lang_key_len + 4);
+
+; if (textp->key == NULL)
+; {
+; png_chunk_report(png_ptr, "text chunk: out of memory",
+; PNG_CHUNK_WRITE_ERROR);
+
+; return 1;
+; }
+
+; png_debug2(2, "Allocated %lu bytes at %p in png_set_text",
+; (unsigned long)(uint_32)
+; (key_len + lang_len + lang_key_len + text_length + 4),
+; textp->key);
+
+; memcpy(textp->key, text_ptr[i].key, key_len);
+; *(textp->key + key_len) = '\0';
+
+; if (text_ptr[i].compression > 0)
+; {
+; textp->lang = textp->key + key_len + 1;
+; memcpy(textp->lang, text_ptr[i].lang, lang_len);
+; *(textp->lang + lang_len) = '\0';
+; textp->lang_key = textp->lang + lang_len + 1;
+; memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len);
+; *(textp->lang_key + lang_key_len) = '\0';
+; textp->text = textp->lang_key + lang_key_len + 1;
+; }
+
+; else
+; {
+; textp->lang=NULL;
+; textp->lang_key=NULL;
+; textp->text = textp->key + key_len + 1;
+; }
+
+; if (text_length != 0)
+; memcpy(textp->text, text_ptr[i].text, text_length);
+
+; *(textp->text + text_length) = '\0';
+
+if PNG_iTXt_SUPPORTED eq 1
+; if (textp->compression > 0)
+; {
+; textp->text_length = 0;
+; textp->itxt_length = text_length;
+; }
+
+; else
+end if
+; {
+; textp->text_length = text_length;
+; textp->itxt_length = 0;
+; }
+
+; info_ptr->num_text++;
+; png_debug1(3, "transferred text chunk %d", info_ptr->num_text);
+; }
+
+ xor eax,eax
+.end_f:
+ ret
+endp
+
+;void (png_structrp png_ptr, png_inforp info_ptr, png_timep mod_time)
+align 4
+proc png_set_tIME uses eax ebx ecx edi esi, png_ptr:dword, info_ptr:dword, mod_time:dword
+ png_debug1 1, 'in %s storage function', 'tIME'
+
+ mov ebx,[png_ptr]
+ cmp ebx,0
+ je .end_f
+ mov edi,[info_ptr]
+ cmp edi,0
+ je .end_f
+ mov esi,[mod_time]
+ cmp esi,0
+ je .end_f
+ mov eax,[ebx+png_struct.mode]
+ and eax,PNG_WROTE_tIME
+ cmp eax,0
+ jne .end_f ;if (..==0 || ..==0 || ..==0 || ..!=0) return
+
+ cmp byte[esi+png_time.month],0
+ je @f
+ cmp byte[esi+png_time.month],12
+ jg @f
+ cmp byte[esi+png_time.day],0
+ je @f
+ cmp byte[esi+png_time.day],31
+ jg @f
+ cmp byte[esi+png_time.hour],23
+ jg @f
+ cmp byte[esi+png_time.minute],59
+ jg @f
+ cmp byte[esi+png_time.second],60
+ jle .end0
+ @@: ;if (..==0 || ..>.. || ..==0 || ..>.. || ..>.. || ..>.. || ..>..)
+ png_warning ebx, 'Ignoring invalid time value'
+ jmp .end_f
+ .end0:
+
+ mov ecx,sizeof.png_time
+ push edi
+ add edi,png_info_def.mod_time
+ rep movsb
+ pop edi
+ or dword[edi+png_info_def.valid],PNG_INFO_tIME
+.end_f:
+ ret
+endp
+
+;void (png_structrp png_ptr, png_inforp info_ptr,
+; bytep trans_alpha, int num_trans, png_color_16p trans_color)
+align 4
+proc png_set_tRNS, png_ptr:dword, info_ptr:dword, trans_alpha:dword, num_trans:dword, trans_color:dword
+ png_debug1 1, 'in %s storage function', 'tRNS'
+
+; if (png_ptr == NULL || info_ptr == NULL)
+; return;
+
+; if (trans_alpha != NULL)
+; {
+ ; It may not actually be necessary to set png_ptr->trans_alpha here;
+ ; we do it for backward compatibility with the way the png_handle_tRNS
+ ; function used to do the allocation.
+
+ ; 1.6.0: The above statement is incorrect; png_handle_tRNS effectively
+ ; relies on png_set_tRNS storing the information in png_struct
+ ; (otherwise it won't be there for the code in pngrtran.c).
+
+
+; png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);
+
+; if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH)
+; {
+ ; Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1
+; info_ptr->trans_alpha = png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH);
+; memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans);
+; }
+; png_ptr->trans_alpha = info_ptr->trans_alpha;
+; }
+
+; if (trans_color != NULL)
+; {
+if PNG_WARNINGS_SUPPORTED eq 1
+; if (info_ptr->bit_depth < 16)
+; {
+; int sample_max = (1 << info_ptr->bit_depth) - 1;
+;
+; if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY &&
+; trans_color->gray > sample_max) ||
+; (info_ptr->color_type == PNG_COLOR_TYPE_RGB &&
+; (trans_color->red > sample_max ||
+; trans_color->green > sample_max ||
+; trans_color->blue > sample_max)))
+; png_warning(png_ptr,
+; "tRNS chunk has out-of-range samples for bit_depth");
+; }
+end if
+
+; info_ptr->trans_color = *trans_color;
+
+; if (num_trans == 0)
+; num_trans = 1;
+; }
+
+; info_ptr->num_trans = (uint_16)num_trans;
+
+; if (num_trans != 0)
+; {
+; info_ptr->valid |= PNG_INFO_tRNS;
+; info_ptr->free_me |= PNG_FREE_TRNS;
+; }
+ ret
+endp
+
+;if PNG_sPLT_SUPPORTED
+;void (png_structrp png_ptr,
+; png_inforp info_ptr, png_sPLT_tp entries, int nentries)
+
+; entries - array of png_sPLT_t structures
+; to be added to the list of palettes
+; in the info structure.
+
+; nentries - number of palette structures to be
+; added.
+
+align 4
+proc png_set_sPLT, png_ptr:dword, info_ptr:dword, entries:dword, nentries:dword
+; png_sPLT_tp np;
+
+; if (png_ptr == NULL || info_ptr == NULL || nentries <= 0 || entries == NULL)
+; return;
+
+ ; Use the internal realloc function, which checks for all the possible
+ ; overflows. Notice that the parameters are (int) and (size_t)
+
+; np = png_realloc_array(png_ptr,
+; info_ptr->splt_palettes, info_ptr->splt_palettes_num, nentries,
+; sizeof *np);
+
+; if (np == NULL)
+; {
+; /* Out of memory or too many chunks */
+; png_chunk_report(png_ptr, "too many sPLT chunks", PNG_CHUNK_WRITE_ERROR);
+
+; return;
+; }
+
+; png_free(png_ptr, info_ptr->splt_palettes);
+; info_ptr->splt_palettes = np;
+; info_ptr->free_me |= PNG_FREE_SPLT;
+
+; np += info_ptr->splt_palettes_num;
+
+; do
+; {
+; png_size_t length;
+
+; /* Skip invalid input entries */
+; if (entries->name == NULL || entries->entries == NULL)
+; {
+; /* png_handle_sPLT doesn't do this, so this is an app error */
+; png_app_error(png_ptr, "png_set_sPLT: invalid sPLT");
+; /* Just skip the invalid entry */
+; continue;
+; }
+
+; np->depth = entries->depth;
+
+ ; In the event of out-of-memory just return - there's no point keeping
+ ; on trying to add sPLT chunks.
+
+; length = strlen(entries->name) + 1;
+; np->name = png_malloc_base(png_ptr, length);
+
+; if (np->name == NULL)
+; break;
+
+; memcpy(np->name, entries->name, length);
+
+ ; IMPORTANT: we have memory now that won't get freed if something else
+ ; goes wrong; this code must free it. png_malloc_array produces no
+ ; warnings; use a png_chunk_report (below) if there is an error.
+
+; np->entries = png_malloc_array(png_ptr,
+; entries->nentries, sizeof (png_sPLT_entry));
+
+; if (np->entries == NULL)
+; {
+; png_free(png_ptr, np->name);
+; np->name = NULL;
+; break;
+; }
+
+; np->nentries = entries->nentries;
+ ; This multiply can't overflow because png_malloc_array has already
+ ; checked it when doing the allocation.
+
+; memcpy(np->entries, entries->entries,
+; entries->nentries * sizeof (png_sPLT_entry));
+
+ ; Note that 'continue' skips the advance of the out pointer and out
+ ; count, so an invalid entry is not added.
+
+; info_ptr->valid |= PNG_INFO_sPLT;
+; ++(info_ptr->splt_palettes_num);
+; ++np;
+; }
+; while (++entries, --nentries);
+
+; if (nentries > 0)
+; png_chunk_report(png_ptr, "sPLT out of memory", PNG_CHUNK_WRITE_ERROR);
+ ret
+endp
+;end if /* sPLT */
+
+;if PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
+;byte (png_structrp png_ptr, int location)
+align 4
+proc check_location, png_ptr:dword, location:dword
+; location &= (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT);
+
+ ; New in 1.6.0; copy the location and check it. This is an API
+ ; change; previously the app had to use the
+ ; png_set_unknown_chunk_location API below for each chunk.
+
+; if (location == 0 && (png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
+; {
+; /* Write struct, so unknown chunks come from the app */
+; png_app_warning(png_ptr,
+; "png_set_unknown_chunks now expects a valid location");
+; /* Use the old behavior */
+; location = (byte)(png_ptr->mode &
+; (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT));
+; }
+
+ ; This need not be an internal error - if the app calls
+ ; png_set_unknown_chunks on a read pointer it must get the location right.
+
+; if (location == 0)
+; png_error(png_ptr, "invalid location in png_set_unknown_chunks");
+
+ ; Now reduce the location to the top-most set bit by removing each least
+ ; significant bit in turn.
+
+; while (location != (location & -location))
+; location &= ~(location & -location);
+
+ ; The cast is safe because 'location' is a bit mask and only the low four
+ ; bits are significant.
+
+; return (byte)location;
+ ret
+endp
+
+;void (png_structrp png_ptr,
+; png_inforp info_ptr, png_unknown_chunkp unknowns, int num_unknowns)
+align 4
+proc png_set_unknown_chunks uses edi esi, png_ptr:dword, info_ptr:dword, unknowns:dword, num_unknowns:dword
+; png_unknown_chunkp np;
+
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f
+ mov esi,[info_ptr]
+ cmp esi,0
+ je .end_f
+ cmp dword[num_unknowns],0
+ jle .end_f
+ cmp dword[unknowns],0
+ je .end_f ;if (..== 0 || ..== 0 || ..<=0 || ..==0) return
+
+ ; Check for the failure cases where support has been disabled at compile
+ ; time. This code is hardly ever compiled - it's here because
+ ; STORE_UNKNOWN_CHUNKS is set by both read and write code (compiling in this
+ ; code) but may be meaningless if the read or write handling of unknown
+ ; chunks is not compiled in.
+
+;# if !defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) && \
+; defined(PNG_READ_SUPPORTED)
+; if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
+; {
+; png_app_error(png_ptr, "no unknown chunk support on read");
+;
+; return;
+; }
+;# endif
+;# if !defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) && \
+; defined(PNG_WRITE_SUPPORTED)
+; if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
+; {
+; png_app_error(png_ptr, "no unknown chunk support on write");
+;
+; return;
+; }
+;# endif
+
+ ; Prior to 1.6.0 this code used png_malloc_warn; however, this meant that
+ ; unknown critical chunks could be lost with just a warning resulting in
+ ; undefined behavior. Now png_chunk_report is used to provide behavior
+ ; appropriate to read or write.
+
+; np = png_realloc_array(png_ptr,
+; info_ptr->unknown_chunks, info_ptr->unknown_chunks_num, num_unknowns,
+; sizeof *np);
+
+; if (np == NULL)
+; {
+; png_chunk_report(png_ptr, "too many unknown chunks",
+; PNG_CHUNK_WRITE_ERROR);
+
+; return;
+; }
+
+; png_free(png_ptr, info_ptr->unknown_chunks);
+; info_ptr->unknown_chunks = np; /* safe because it is initialized */
+; info_ptr->free_me |= PNG_FREE_UNKN;
+
+; np += info_ptr->unknown_chunks_num;
+
+ ; Increment unknown_chunks_num each time round the loop to protect the
+ ; just-allocated chunk data.
+
+; for (; num_unknowns > 0; --num_unknowns, ++unknowns)
+; {
+; memcpy(np->name, unknowns->name, (sizeof np->name));
+; np->name[(sizeof np->name)-1] = '\0';
+; np->location = check_location(png_ptr, unknowns->location);
+
+; if (unknowns->size == 0)
+; {
+; np->data = NULL;
+; np->size = 0;
+; }
+
+; else
+; {
+; np->data = png_malloc_base(png_ptr, unknowns->size);
+
+; if (np->data == NULL)
+; {
+; png_chunk_report(png_ptr, "unknown chunk: out of memory",
+; PNG_CHUNK_WRITE_ERROR);
+; /* But just skip storing the unknown chunk */
+; continue;
+; }
+
+; memcpy(np->data, unknowns->data, unknowns->size);
+; np->size = unknowns->size;
+; }
+
+ ; These increments are skipped on out-of-memory for the data - the
+ ; unknown chunk entry gets overwritten if the png_chunk_report returns.
+ ; This is correct in the read case (the chunk is just dropped.)
+
+; ++np;
+; ++(info_ptr->unknown_chunks_num);
+; }
+.end_f:
+ ret
+endp
+
+;void (png_structrp png_ptr, png_inforp info_ptr, int chunk, int location)
+align 4
+proc png_set_unknown_chunk_location, png_ptr:dword, info_ptr:dword, chunk:dword, location:dword
+ ; This API is pretty pointless in 1.6.0 because the location can be set
+ ; before the call to png_set_unknown_chunks.
+
+ ; TODO: add a png_app_warning in 1.7
+
+; if (png_ptr != NULL && info_ptr != NULL && chunk >= 0 &&
+; chunk < info_ptr->unknown_chunks_num)
+; {
+; if ((location & (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT)) == 0)
+; {
+; png_app_error(png_ptr, "invalid unknown chunk location");
+ ; Fake out the pre 1.6.0 behavior:
+; if ((location & PNG_HAVE_IDAT) != 0) /* undocumented! */
+; location = PNG_AFTER_IDAT;
+
+; else
+; location = PNG_HAVE_IHDR; /* also undocumented */
+; }
+
+; info_ptr->unknown_chunks[chunk].location =
+; check_location(png_ptr, location);
+; }
+ ret
+endp
+;end if /* STORE_UNKNOWN_CHUNKS */
+
+;uint_32 (png_structrp png_ptr, uint_32 mng_features)
+align 4
+proc png_permit_mng_features, png_ptr:dword, mng_features:dword
+ png_debug 1, 'in png_permit_mng_features'
+
+; if (png_ptr == NULL)
+; return 0;
+
+; png_ptr->mng_features_permitted = mng_features & PNG_ALL_MNG_FEATURES;
+
+; return png_ptr->mng_features_permitted;
+ ret
+endp
+
+;if PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+;uint (bytep list, uint count, bytep add, int keep)
+align 4
+proc add_one_chunk, list:dword, count:dword, p3add:dword, keep:dword
+; uint i;
+
+ ; Utility function: update the 'keep' state of a chunk if it is already in
+ ; the list, otherwise add it to the list.
+
+; for (i=0; i= PNG_HANDLE_CHUNK_LAST)
+; {
+; png_app_error(png_ptr, "png_set_keep_unknown_chunks: invalid keep");
+
+; return;
+; }
+
+; if (num_chunks_in <= 0)
+; {
+; png_ptr->unknown_default = keep;
+
+ ; '0' means just set the flags, so stop here
+; if (num_chunks_in == 0)
+; return;
+; }
+
+; if (num_chunks_in < 0)
+; {
+ ; Ignore all unknown chunks and all chunks recognized by
+ ; libpng except for IHDR, PLTE, tRNS, IDAT, and IEND
+
+; static byte chunks_to_ignore[] = {
+; 98, 75, 71, 68, '\0', /* bKGD */
+; 99, 72, 82, 77, '\0', /* cHRM */
+; 103, 65, 77, 65, '\0', /* gAMA */
+; 104, 73, 83, 84, '\0', /* hIST */
+; 105, 67, 67, 80, '\0', /* iCCP */
+; 105, 84, 88, 116, '\0', /* iTXt */
+; 111, 70, 70, 115, '\0', /* oFFs */
+; 112, 67, 65, 76, '\0', /* pCAL */
+; 112, 72, 89, 115, '\0', /* pHYs */
+; 115, 66, 73, 84, '\0', /* sBIT */
+; 115, 67, 65, 76, '\0', /* sCAL */
+; 115, 80, 76, 84, '\0', /* sPLT */
+; 115, 84, 69, 82, '\0', /* sTER */
+; 115, 82, 71, 66, '\0', /* sRGB */
+; 116, 69, 88, 116, '\0', /* tEXt */
+; 116, 73, 77, 69, '\0', /* tIME */
+; 122, 84, 88, 116, '\0' /* zTXt */
+; };
+
+; chunk_list = chunks_to_ignore;
+; num_chunks = (uint)/*SAFE*/(sizeof chunks_to_ignore)/5U;
+; }
+
+; else /* num_chunks_in > 0 */
+; {
+; if (chunk_list == NULL)
+; {
+; /* Prior to 1.6.0 this was silently ignored, now it is an app_error
+ ; which can be switched off.
+
+; png_app_error(png_ptr, "png_set_keep_unknown_chunks: no chunk list");
+
+; return;
+; }
+
+; num_chunks = num_chunks_in;
+; }
+
+; old_num_chunks = png_ptr->num_chunk_list;
+; if (png_ptr->chunk_list == NULL)
+; old_num_chunks = 0;
+
+ ; Since num_chunks is always restricted to UINT_MAX/5 this can't overflow.
+
+; if (num_chunks + old_num_chunks > UINT_MAX/5)
+; {
+; png_app_error(png_ptr, "png_set_keep_unknown_chunks: too many chunks");
+
+; return;
+; }
+
+ ; If these chunks are being reset to the default then no more memory is
+ ; required because add_one_chunk above doesn't extend the list if the 'keep'
+ ; parameter is the default.
+
+; if (keep != 0)
+; {
+; new_list = png_malloc(png_ptr, 5 * (num_chunks + old_num_chunks));
+;
+; if (old_num_chunks > 0)
+; memcpy(new_list, png_ptr->chunk_list, 5*old_num_chunks);
+; }
+
+; else if (old_num_chunks > 0)
+; new_list = png_ptr->chunk_list;
+
+; else
+; new_list = NULL;
+
+ ; Add the new chunks together with each one's handling code. If the chunk
+ ; already exists the code is updated, otherwise the chunk is added to the
+ ; end. (In libpng 1.6.0 order no longer matters because this code enforces
+ ; the earlier convention that the last setting is the one that is used.)
+
+; if (new_list != NULL)
+; {
+; bytep inlist;
+; bytep outlist;
+; uint i;
+
+; for (i=0; ichunk_list != new_list)
+; png_free(png_ptr, new_list);
+;
+; new_list = NULL;
+; }
+; }
+;
+; else
+; num_chunks = 0;
+;
+; png_ptr->num_chunk_list = num_chunks;
+;
+; if (png_ptr->chunk_list != new_list)
+; {
+; if (png_ptr->chunk_list != NULL)
+; png_free(png_ptr, png_ptr->chunk_list);
+;
+; png_ptr->chunk_list = new_list;
+; }
+.end_f:
+ ret
+endp
+;end if
+
+;void (png_structrp png_ptr, voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)
+align 4
+proc png_set_read_user_chunk_fn uses eax edi, png_ptr:dword, user_chunk_ptr:dword, read_user_chunk_fn:dword
+ png_debug 1, 'in png_set_read_user_chunk_fn'
+
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f
+
+ mov eax,[read_user_chunk_fn]
+ mov [edi+png_struct.read_user_chunk_fn],eax
+ mov eax,[user_chunk_ptr]
+ mov [edi+png_struct.user_chunk_ptr],eax
+.end_f:
+ ret
+endp
+
+;void (png_structrp png_ptr, png_inforp info_ptr, bytepp row_pointers)
+align 4
+proc png_set_rows uses eax edi esi, png_ptr:dword, info_ptr:dword, row_pointers:dword
+ png_debug1 1, 'in %s storage function', 'rows'
+
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f
+ mov esi,[info_ptr]
+ cmp esi,0
+ je .end_f ;if (..==0 || ..==0) return
+
+ mov eax,[row_pointers]
+ cmp dword[esi+png_info_def.row_pointers],0
+ je @f
+ cmp [esi+png_info_def.row_pointers],eax
+ je @f ;if (..!=0 && ..!=..)
+ stdcall png_free_data, edi, esi, PNG_FREE_ROWS, 0
+ @@:
+ mov [esi+png_info_def.row_pointers],eax
+
+ cmp eax,0
+ je .end_f ;if (..!=0)
+ or dword[esi+png_info_def.valid],PNG_INFO_IDAT
+.end_f:
+ ret
+endp
+
+;void (png_structrp png_ptr, png_size_t size)
+align 4
+proc png_set_compression_buffer_size uses edi, png_ptr:dword, size:dword
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f ;if (..==0) return
+
+; if (size == 0 || size > PNG_UINT_31_MAX)
+; png_error(png_ptr, "invalid compression buffer size");
+
+if PNG_SEQUENTIAL_READ_SUPPORTED eq 1
+; if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
+; {
+; png_ptr->IDAT_read_size = (uint_32)size; /* checked above */
+; return;
+; }
+end if
+
+if PNG_WRITE_SUPPORTED eq 1
+; if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
+; {
+; if (png_ptr->zowner != 0)
+; {
+; png_warning(png_ptr,
+; "Compression buffer size cannot be changed because it is in use");
+
+; return;
+; }
+
+;#ifndef __COVERITY__
+ ; Some compilers complain that this is always false. However, it
+ ; can be true when integer overflow happens.
+
+; if (size > ZLIB_IO_MAX)
+; {
+; png_warning(png_ptr,
+; "Compression buffer size limited to system maximum");
+; size = ZLIB_IO_MAX; /* must fit */
+; }
+;end if
+
+; if (size < 6)
+; {
+ ; Deflate will potentially go into an infinite loop on a SYNC_FLUSH
+ ; if this is permitted.
+
+; png_warning(png_ptr,
+; "Compression buffer size cannot be reduced below 6");
+
+; return;
+; }
+
+; if (png_ptr->zbuffer_size != size)
+; {
+; png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list);
+; png_ptr->zbuffer_size = (uInt)size;
+; }
+; }
+end if
+.end_f:
+ ret
+endp
+
+;void (png_structrp png_ptr, png_inforp info_ptr, int mask)
+align 4
+proc png_set_invalid, png_ptr:dword, info_ptr:dword, mask:dword
+; if (png_ptr != NULL && info_ptr != NULL)
+; info_ptr->valid &= ~mask;
+ ret
+endp
+
+; This function was added to libpng 1.2.6
+;void (png_structrp png_ptr, uint_32 user_width_max, uint_32 user_height_max)
+align 4
+proc png_set_user_limits uses eax edi, png_ptr:dword, user_width_max:dword, user_height_max:dword
+ ; Images with dimensions larger than these limits will be
+ ; rejected by png_set_IHDR(). To accept any PNG datastream
+ ; regardless of dimensions, set both limits to 0x7fffffff.
+
+ mov edi,[png_ptr]
+ cmp edi,0
+ je @f
+ mov eax,[user_width_max]
+ mov [edi+png_struct.user_width_max],eax
+ mov eax,[user_height_max]
+ mov [edi+png_struct.user_height_max],eax
+ @@:
+ ret
+endp
+
+; This function was added to libpng 1.4.0
+;void (png_structrp png_ptr, uint_32 user_chunk_cache_max)
+align 4
+proc png_set_chunk_cache_max, png_ptr:dword, user_chunk_cache_max:dword
+; if (png_ptr != NULL)
+; png_ptr->user_chunk_cache_max = user_chunk_cache_max;
+ ret
+endp
+
+; This function was added to libpng 1.4.1
+;void (png_structrp png_ptr, png_alloc_size_t user_chunk_malloc_max)
+align 4
+proc png_set_chunk_malloc_max, png_ptr:dword, user_chunk_malloc_max:dword
+; if (png_ptr != NULL)
+; png_ptr->user_chunk_malloc_max = user_chunk_malloc_max;
+ ret
+endp
+
+;void (png_structrp png_ptr, int allowed)
+align 4
+proc png_set_benign_errors uses edi, png_ptr:dword, allowed:dword
+ png_debug 1, 'in png_set_benign_errors'
+
+ ; If allowed is 1, png_benign_error() is treated as a warning.
+ ; If allowed is 0, png_benign_error() is treated as an error (which
+ ; is the default behavior if png_set_benign_errors() is not called).
+
+ mov edi,[png_ptr]
+ cmp dword[allowed],0
+ je @f ;if (..!=0)
+ or dword[edi+png_struct.flags], PNG_FLAG_BENIGN_ERRORS_WARN or PNG_FLAG_APP_WARNINGS_WARN or PNG_FLAG_APP_ERRORS_WARN
+ jmp .end0
+ @@: ;else
+ and dword[edi+png_struct.flags], not (PNG_FLAG_BENIGN_ERRORS_WARN or PNG_FLAG_APP_WARNINGS_WARN or PNG_FLAG_APP_ERRORS_WARN)
+ .end0:
+ ret
+endp
+
+; Whether to report invalid palette index; added at libng-1.5.10.
+; It is possible for an indexed (color-type==3) PNG file to contain
+; pixels with invalid (out-of-range) indexes if the PLTE chunk has
+; fewer entries than the image's bit-depth would allow. We recover
+; from this gracefully by filling any incomplete palette with zeros
+; (opaque black). By default, when this occurs libpng will issue
+; a benign error. This API can be used to override that behavior.
+
+;void (png_structrp png_ptr, int allowed)
+align 4
+proc png_set_check_for_invalid_index, png_ptr:dword, allowed:dword
+ png_debug 1, 'in png_set_check_for_invalid_index'
+
+; if (allowed > 0)
+; png_ptr->num_palette_max = 0;
+
+; else
+; png_ptr->num_palette_max = -1;
+ ret
+endp
+
+; Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
+; and if invalid, correct the keyword rather than discarding the entire
+; chunk. The PNG 1.0 specification requires keywords 1-79 characters in
+; length, forbids leading or trailing whitespace, multiple internal spaces,
+; and the non-break space (0x80) from ISO 8859-1. Returns keyword length.
+
+; The 'new_key' buffer must be 80 characters in size (for the keyword plus a
+; trailing '\0'). If this routine returns 0 then there was no keyword, or a
+; valid one could not be generated, and the caller must png_error.
+
+;uint_32 (png_structrp png_ptr, charp key, bytep new_key)
+align 4
+proc png_check_keyword, png_ptr:dword, key:dword, new_key:dword
+;if PNG_WARNINGS_SUPPORTED
+; charp orig_key = key;
+;end if
+; uint_32 key_len = 0;
+; int bad_character = 0;
+; int space = 1;
+
+ png_debug 1, 'in png_check_keyword'
+
+; if (key == NULL)
+; {
+; *new_key = 0;
+; return 0;
+; }
+
+; while (*key && key_len < 79)
+; {
+; byte ch = (byte)*key++;
+
+; if ((ch > 32 && ch <= 126) || (ch >= 161 /*&& ch <= 255*/))
+; *new_key++ = ch, ++key_len, space = 0;
+
+; else if (space == 0)
+; {
+ ; A space or an invalid character when one wasn't seen immediately
+ ; before; output just a space.
+
+; *new_key++ = 32, ++key_len, space = 1;
+
+; /* If the character was not a space then it is invalid. */
+; if (ch != 32)
+; bad_character = ch;
+; }
+
+; else if (bad_character == 0)
+; bad_character = ch; /* just skip it, record the first error */
+; }
+
+; if (key_len > 0 && space != 0) /* trailing space */
+; {
+; --key_len, --new_key;
+; if (bad_character == 0)
+; bad_character = 32;
+; }
+
+ ; Terminate the keyword
+; *new_key = 0;
+
+; if (key_len == 0)
+; return 0;
+
+if PNG_WARNINGS_SUPPORTED eq 1
+ ; Try to only output one warning per keyword:
+; if (*key != 0) /* keyword too long */
+; png_warning(png_ptr, "keyword truncated");
+
+; else if (bad_character != 0)
+; {
+; PNG_WARNING_PARAMETERS(p)
+
+; png_warning_parameter(p, 1, orig_key);
+; png_warning_parameter_signed(p, 2, PNG_NUMBER_FORMAT_02x, bad_character);
+
+; png_formatted_warning(png_ptr, p, "keyword \"@1\": bad character '0x@2'");
+; }
+end if ;!WARNINGS
+
+; return key_len;
+ ret
+endp
+
diff --git a/programs/develop/libraries/libs-dev/libimg/png/libpng/pngstruct.inc b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngstruct.inc
index 278551b9c..95771d022 100644
--- a/programs/develop/libraries/libs-dev/libimg/png/libpng/pngstruct.inc
+++ b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngstruct.inc
@@ -1,453 +1,453 @@
-
-; pngstruct.inc - header file for PNG reference library
-
-; Last changed in libpng 1.6.24 [August 4, 2016]
-; Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
-; (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
-; (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
-
-; This code is released under the libpng license.
-; For conditions of distribution and use, see the disclaimer
-; and license in png.inc
-
-
-; The structure that holds the information to read and write PNG files.
-; The only people who need to care about what is inside of this are the
-; people who will be modifying the library for their own special needs.
-; It should NOT be accessed directly by an application.
-
-
-; zlib.inc defines the structure z_stream, an instance of which is included
-; in this structure and is required for decompressing the LZ compressed
-; data in PNG files.
-
-include '../../../../../../fs/kfar/trunk/zlib/zlib.inc'
-
-; zlib.inc declares a magic type 'uInt' that limits the amount of data that zlib
-; can handle at once. This type need be no larger than 16 bits (so maximum of
-; 65535), this define allows us to discover how big it is, but limited by the
-; maximuum for png_size_t. The value can be overriden in a library build
-; (pngusr.h, or set it in CPPFLAGS) and it works to set it to a considerably
-; lower value (e.g. 255 works). A lower value may help memory usage (slightly)
-; and may even improve performance on some systems (and degrade it on others.)
-
-
-ZLIB_IO_MAX equ 0xffff ;-1 ;uInt
-
-
-; The type of a compression buffer list used by the write code.
-struct png_compression_buffer
- next dd ? ;struct png_compression_buffer *
- output db ? ;byte[1] ;actually zbuf_size
-ends
-
-macro PNG_COMPRESSION_BUFFER_SIZE pp
-{
- mov eax,png_compression_buffer.output
- add eax,[pp+png_struct.zbuffer_size]
-}
-
-; Colorspace support; structures used in png_struct, png_info and in internal
-; functions to hold and communicate information about the color space.
-
-; PNG_COLORSPACE_SUPPORTED is only required if the application will perform
-; colorspace corrections, otherwise all the colorspace information can be
-; skipped and the size of libpng can be reduced (significantly) by compiling
-; out the colorspace support.
-
-if PNG_COLORSPACE_SUPPORTED eq 1
-; The chromaticities of the red, green and blue colorants and the chromaticity
-; of the corresponding white point (i.e. of rgb(1.0,1.0,1.0)).
-
-struct png_xy
- redx dd ? ;png_fixed_point
- redy dd ?
- greenx dd ?
- greeny dd ?
- bluex dd ?
- bluey dd ?
- whitex dd ?
- whitey dd ?
-ends
-
-; The same data as above but encoded as CIE XYZ values. When this data comes
-; from chromaticities the sum of the Y values is assumed to be 1.0
-
-struct png_XYZ
- red_X dd ? ;png_fixed_point
- red_Y dd ?
- red_Z dd ?
- green_X dd ?
- green_Y dd ?
- green_Z dd ?
- blue_X dd ?
- blue_Y dd ?
- blue_Z dd ?
-ends
-end if ;COLORSPACE
-
-if (PNG_COLORSPACE_SUPPORTED eq 1) | (PNG_GAMMA_SUPPORTED eq 1)
-; A colorspace is all the above plus, potentially, profile information;
-; however at present libpng does not use the profile internally so it is only
-; stored in the png_info struct (if iCCP is supported.) The rendering intent
-; is retained here and is checked.
-
-; The file gamma encoding information is also stored here and gamma correction
-; is done by libpng, whereas color correction must currently be done by the
-; application.
-
-struct png_colorspace
-if PNG_GAMMA_SUPPORTED eq 1
- gamma dd ? ;png_fixed_point ;File gamma
-end if
-
-if PNG_COLORSPACE_SUPPORTED eq 1
- end_points_xy png_xy ;End points as chromaticities
- end_points_XYZ png_XYZ ;End points as CIE XYZ colorant values
- rendering_intent dw ? ;uint_16 ;Rendering intent of a profile
-end if
-
- ; Flags are always defined to simplify the code.
- flags dw ? ;uint_16 ;As defined below
-ends
-
-; General flags for the 'flags' field
-PNG_COLORSPACE_HAVE_GAMMA equ 0x0001
-PNG_COLORSPACE_HAVE_ENDPOINTS equ 0x0002
-PNG_COLORSPACE_HAVE_INTENT equ 0x0004
-PNG_COLORSPACE_FROM_gAMA equ 0x0008
-PNG_COLORSPACE_FROM_cHRM equ 0x0010
-PNG_COLORSPACE_FROM_sRGB equ 0x0020
-PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB equ 0x0040
-PNG_COLORSPACE_MATCHES_sRGB equ 0x0080 ;exact match on profile
-PNG_COLORSPACE_INVALID equ 0x8000
-macro PNG_COLORSPACE_CANCEL flags {(0xffff xor (flags))}
-end if ;COLORSPACE || GAMMA
-
-struct png_struct
-if PNG_SETJMP_SUPPORTED eq 1
- jmp_buf_local rb 64 ;jmp_buf ;New name in 1.6.0 for jmp_buf in png_struct
- longjmp_fn dd ? ;png_longjmp_ptr ;setjmp non-local goto function.
- jmp_buf_ptr dd ? ;jmp_buf * ;passed to longjmp_fn
- jmp_buf_size dd ? ;size_t ;size of the above, if allocated
-end if
- error_fn dd ? ;png_error_ptr ;function for printing errors and aborting
-if PNG_WARNINGS_SUPPORTED eq 1
- warning_fn dd ? ;png_error_ptr ;function for printing warnings
-end if
- error_ptr dd ? ;voidp ;user supplied struct for error functions
- write_data_fn dd ? ;png_rw_ptr ;function for writing output data
- read_data_fn dd ? ;png_rw_ptr ;function for reading input data
- io_ptr dd ? ;voidp ;ptr to application struct for I/O functions
-
-if PNG_READ_USER_TRANSFORM_SUPPORTED eq 1
- read_user_transform_fn dd ? ;png_user_transform_ptr ;user read transform
-end if
-
-if PNG_WRITE_USER_TRANSFORM_SUPPORTED eq 1
- write_user_transform_fn dd ? ;png_user_transform_ptr ; user write transform
-end if
-
-; These were added in libpng-1.0.2
-if PNG_USER_TRANSFORM_PTR_SUPPORTED eq 1
-if (PNG_READ_USER_TRANSFORM_SUPPORTED eq 1) | (PNG_WRITE_USER_TRANSFORM_SUPPORTED eq 1)
- user_transform_ptr dd ? ;voidp ;user supplied struct for user transform
- user_transform_depth db ? ;byte ;bit depth of user transformed pixels
- user_transform_channels db ? ;byte ;channels in user transformed pixels
- rb 2 ;align
-end if
-end if
-
- mode dd ? ;uint_32 ;tells us where we are in the PNG file
- flags dd ? ;uint_32 ;flags indicating various things to libpng
- transformations dd ? ;uint_32 ;which transformations to perform
-
- zowner dd ? ;uint_32 ;ID (chunk type) of zstream owner, 0 if none
- zstream z_stream ;decompression structure
-
- zbuffer_list dd ? ;png_compression_bufferp ;Created on demand during write
- zbuffer_size dd ? ;uInt ;size of the actual buffer
-
- zlib_level dd ? ;int ;holds zlib compression level
- zlib_method dd ? ;int ;holds zlib compression method
- zlib_window_bits dd ? ;int ;holds zlib compression window bits
- zlib_mem_level dd ? ;int ;holds zlib compression memory level
- zlib_strategy dd ? ;int ;holds zlib compression strategy
-; Added at libpng 1.5.4
-if PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED eq 1
- zlib_text_level dd ? ;int ;holds zlib compression level
- zlib_text_method dd ? ;int ;holds zlib compression method
- zlib_text_window_bits dd ? ;int ;holds zlib compression window bits
- zlib_text_mem_level dd ? ;int ;holds zlib compression memory level
- zlib_text_strategy dd ? ;int ;holds zlib compression strategy
-end if
-;End of material added at libpng 1.5.4
-;Added at libpng 1.6.0
- zlib_set_level dd ? ;int ;Actual values set into the zstream on write
- zlib_set_method dd ? ;int
- zlib_set_window_bits dd ? ;int
- zlib_set_mem_level dd ? ;int
- zlib_set_strategy dd ? ;int
-
- width dd ? ;uint_32 ;width of image in pixels
- height dd ? ;uint_32 ;height of image in pixels
- num_rows dd ? ;uint_32 ;number of rows in current pass
- usr_width dd ? ;uint_32 ;width of row at start of write
- rowbytes dd ? ;png_size_t ;size of row in bytes
- iwidth dd ? ;uint_32 ;width of current interlaced row in pixels
- row_number dd ? ;uint_32 ;current row in interlace pass
- chunk_name dd ? ;uint_32 ;PNG_CHUNK() id of current chunk
- prev_row dd ? ;bytep ;buffer to save previous (unfiltered) row.
- ;While reading this is a pointer into
- ;big_prev_row; while writing it is separately
- ;allocated if needed.
-
- row_buf dd ? ;bytep ;buffer to save current (unfiltered) row.
- ;While reading, this is a pointer into
- ;big_row_buf; while writing it is separately
- ;allocated.
-
-if PNG_WRITE_FILTER_SUPPORTED eq 1
- try_row dd ? ;bytep ;buffer to save trial row when filtering
- tst_row dd ? ;bytep ;buffer to save best trial row when filtering
-end if
- info_rowbytes dd ? ;png_size_t ;Added in 1.5.4: cache of updated row bytes
-
- idat_size dd ? ;uint_32 ;current IDAT size for read
- crc dd ? ;uint_32 ;current chunk CRC value
- palette dd ? ;png_colorp ;palette from the input file
- num_palette dw ? ;uint_16 ;number of color entries in palette
- rb 2 ;align
-; Added at libpng-1.5.10
-if PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED eq 1
- num_palette_max dd ? ;int ;maximum palette index found in IDAT
-end if
-
- num_trans dw ? ;uint_16 ;number of transparency values
- compression db ? ;byte ;file compression type (always 0)
- filter db ? ;byte ;file filter type (always 0)
- interlaced db ? ;byte ;PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7
- pass db ? ;byte ;current interlace pass (0 - 6)
- do_filter db ? ;byte ;row filter flags (see PNG_FILTER_ in png.inc)
- color_type db ? ;byte ;color type of file
- bit_depth db ? ;byte ;bit depth of file
- usr_bit_depth db ? ;byte ;bit depth of users row: write only
- pixel_depth db ? ;byte ;number of bits per pixel
- channels db ? ;byte ;number of channels in file
- usr_channels db ? ;byte ;channels at start of write: write only
- sig_bytes db ? ;byte ;magic bytes read/written from start of file
- maximum_pixel_depth db ? ;byte ;pixel depth used for the row buffers
- transformed_pixel_depth db ? ;byte ;pixel depth after read/write transforms
-;if PNG_ZLIB_VERNUM >= 0x1240
- ;zstream_start db 1 ;byte ;at start of an input zlib stream
-;end if ;Zlib >= 1.2.4
-if (PNG_READ_FILLER_SUPPORTED eq 1) | (PNG_WRITE_FILLER_SUPPORTED eq 1)
- filler dw ? ;uint_16 ;filler bytes for pixel expansion
-end if
-
-if (PNG_bKGD_SUPPORTED eq 1) | (PNG_READ_BACKGROUND_SUPPORTED eq 1) | \
- (PNG_READ_ALPHA_MODE_SUPPORTED eq 1)
- background_gamma_type db ? ;byte
- rb 1 ;align
- background_gamma dd ? ;png_fixed_point
- background png_color_16 ;background color in screen gamma space
- rb 1 ;align
-if PNG_READ_GAMMA_SUPPORTED eq 1
- background_1 png_color_16 ;background normalized to gamma 1.0
- rb 1 ;align
-end if
-end if ;bKGD
-
-if PNG_WRITE_FLUSH_SUPPORTED eq 1
- output_flush_fn dd ? ;png_flush_ptr ;Function for flushing output
- flush_dist dd ? ;uint_32 ;how many rows apart to flush, 0 - no flush
- flush_rows dd ? ;uint_32 ;number of rows written since last flush
-end if
-
-if PNG_READ_GAMMA_SUPPORTED eq 1
- gamma_shift dd ? ;int ;number of "insignificant" bits in 16-bit gamma
- screen_gamma dd ? ;png_fixed_point ;screen gamma value (display_exponent)
-
- gamma_table dd ? ;bytep ;gamma table for 8-bit depth files
- gamma_16_table dd ? ;uint_16pp ;gamma table for 16-bit depth files
-if (PNG_READ_BACKGROUND_SUPPORTED eq 1) | \
- (PNG_READ_ALPHA_MODE_SUPPORTED eq 1) | \
- (PNG_READ_RGB_TO_GRAY_SUPPORTED eq 1)
- gamma_from_1 dd ? ;bytep ;converts from 1.0 to screen
- gamma_to_1 dd ? ;bytep ;converts from file to 1.0
- gamma_16_from_1 dd ? ;uint_16pp ;converts from 1.0 to screen
- gamma_16_to_1 dd ? ;uint_16pp ;converts from file to 1.0
-end if ;READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY
-end if
-
-if (PNG_READ_GAMMA_SUPPORTED eq 1) | (PNG_sBIT_SUPPORTED eq 1)
- sig_bit png_color_8 ;significant bits in each available channel
-end if
-
-if (PNG_READ_SHIFT_SUPPORTED eq 1) | (PNG_WRITE_SHIFT_SUPPORTED eq 1)
- shift png_color_8 ;shift for significant bit tranformation
- rb 2 ;align
-end if
-
-if (PNG_tRNS_SUPPORTED eq 1) | (PNG_READ_BACKGROUND_SUPPORTED eq 1) \
- | (PNG_READ_EXPAND_SUPPORTED eq 1) | (PNG_READ_BACKGROUND_SUPPORTED eq 1)
- trans_alpha dd ? ;bytep ;alpha values for paletted files
- trans_color png_color_16 ;transparent color for non-paletted files
- rb 3 ;align
-end if
-
- read_row_fn dd ? ;png_read_status_ptr ;called after each row is decoded
- write_row_fn dd ? ;png_write_status_ptr ;called after each row is encoded
-if PNG_PROGRESSIVE_READ_SUPPORTED eq 1
- info_fn dd ? ;png_progressive_info_ptr ;called after header data fully read
- row_fn dd ? ;png_progressive_row_ptr ;called after a prog. row is decoded
- end_fn dd ? ;png_progressive_end_ptr ;called after image is complete
- save_buffer_ptr dd ? ;bytep ;current location in save_buffer
- save_buffer dd ? ;bytep ;buffer for previously read data
- current_buffer_ptr dd ? ;bytep ;current location in current_buffer
- current_buffer dd ? ;bytep ;buffer for recently used data
- push_length dd ? ;uint_32 ;size of current input chunk
- skip_length dd ? ;uint_32 ;bytes to skip in input data
- save_buffer_size dd ? ;png_size_t ;amount of data now in save_buffer
- save_buffer_max dd ? ;png_size_t ;total size of save_buffer
- buffer_size dd ? ;png_size_t ;total amount of available input data
- current_buffer_size dd ? ;png_size_t ;amount of data now in current_buffer
- process_mode dd ? ;int ;what push library is currently doing
- cur_palette dd ? ;int ;current push library palette index
-
-end if ;PROGRESSIVE_READ
-
-if PNG_READ_QUANTIZE_SUPPORTED eq 1
- palette_lookup dd ? ;bytep ;lookup table for quantizing
- quantize_index dd ? ;bytep ;index translation for palette files
-end if
-
-; Options
-if PNG_SET_OPTION_SUPPORTED eq 1
- options db ? ;byte ;On/off state (up to 4 options)
-end if
-
-;#if PNG_LIBPNG_VER < 10700
-; To do: remove this from libpng-1.7
-if PNG_TIME_RFC1123_SUPPORTED eq 1
- time_buffer rb 29 ;char[29] ;String to hold RFC 1123 time text
- rb 2 ;align
-end if
-;end if
-
-; New members added in libpng-1.0.6
-
- free_me dd ? ;uint_32 ;flags items libpng is responsible for freeing
-
-if PNG_USER_CHUNKS_SUPPORTED eq 1
- user_chunk_ptr dd ? ;voidp
-if PNG_READ_USER_CHUNKS_SUPPORTED eq 1
- read_user_chunk_fn dd ? ;png_user_chunk_ptr ;user read chunk handler
-end if
-end if
-
-if PNG_SET_UNKNOWN_CHUNKS_SUPPORTED eq 1
- unknown_default dd ? ;int ; As PNG_HANDLE_*
- num_chunk_list dd ? ;unsigned int ; Number of entries in the list
- chunk_list dd ? ;bytep ; List of byte[5]; the textual chunk name
- ; followed by a PNG_HANDLE_* byte
-end if
-
-; New members added in libpng-1.0.3
-if PNG_READ_RGB_TO_GRAY_SUPPORTED eq 1
- rgb_to_gray_status db ? ;byte
- ; Added in libpng 1.5.5 to record setting of coefficients:
- rgb_to_gray_coefficients_set db ? ;byte
- ; These were changed from byte in libpng-1.0.6
- rgb_to_gray_red_coeff dw ? ;uint_16
- rgb_to_gray_green_coeff dw ? ;uint_16
- ; deleted in 1.5.5: rgb_to_gray_blue_coeff;
- rb 2 ;align
-end if
-
-if PNG_MNG_FEATURES_SUPPORTED eq 1
-; New member added in libpng-1.0.4 (renamed in 1.0.9)
-; Changed from byte to uint_32 at version 1.2.0
- mng_features_permitted dd ? ;uint_32
-
-; New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0
- filter_type db ? ;byte
- rb 3 ;align
-end if
-
-; New members added in libpng-1.2.0
-
-; New members added in libpng-1.0.2 but first enabled by default in 1.2.0
-if PNG_USER_MEM_SUPPORTED eq 1
- mem_ptr dd ? ;voidp ;user supplied struct for mem functions
- malloc_fn dd ? ;malloc_ptr ;function for allocating memory
- free_fn dd ? ;free_ptr ;function for freeing memory
-end if
-
-; New member added in libpng-1.0.13 and 1.2.0
- big_row_buf dd ? ;bytep ;buffer to save current (unfiltered) row
-
-if PNG_READ_QUANTIZE_SUPPORTED eq 1
-; The following three members were added at version 1.0.14 and 1.2.4
- quantize_sort dd ? ;bytep ;working sort array
- index_to_palette dd ? ;bytep ;where the original index currently is in the palette
- palette_to_index dd ? ;bytep ;which original index points to this palette color
-end if
-
-; New members added in libpng-1.0.16 and 1.2.6
- compression_type db ? ;byte
- rb 3 ;align
-
-if PNG_USER_LIMITS_SUPPORTED eq 1
- user_width_max dd ? ;uint_32
- user_height_max dd ? ;uint_32
-
- ; Added in libpng-1.4.0: Total number of sPLT, text, and unknown
- ; chunks that can be stored (0 means unlimited).
-
- user_chunk_cache_max dd ? ;uint_32
-
- ; Total memory that a zTXt, sPLT, iTXt, iCCP, or unknown chunk
- ; can occupy when decompressed. 0 means unlimited.
-
- user_chunk_malloc_max dd ? ;png_alloc_size_t
-end if
-
-; New member added in libpng-1.0.25 and 1.2.17
-if PNG_READ_UNKNOWN_CHUNKS_SUPPORTED eq 1
- ; Temporary storage for unknown chunk that the library doesn't recognize,
- ; used while reading the chunk.
-
- unknown_chunk png_unknown_chunk
- rb 3 ;align
-end if
-
-; New member added in libpng-1.2.26
- old_big_row_buf_size dd ? ;png_size_t
-
-if PNG_READ_SUPPORTED eq 1
-; New member added in libpng-1.2.30
- read_buffer dd ? ;bytep ;buffer for reading chunk data
- read_buffer_size dd ? ;png_alloc_size_t ;current size of the buffer
-end if
-if PNG_SEQUENTIAL_READ_SUPPORTED eq 1
- IDAT_read_size dd ? ;uInt ;limit on read buffer size for IDAT
-end if
-
-if PNG_IO_STATE_SUPPORTED eq 1
-; New member added in libpng-1.4.0
- io_state dd ? ;uint_32
-end if
-
- ; New member added in libpng-1.5.6
- big_prev_row dd ? ;bytep
-
- ; New member added in libpng-1.5.7
- read_filter rd PNG_FILTER_VALUE_LAST-1
-
-if PNG_READ_SUPPORTED eq 1
-if (PNG_COLORSPACE_SUPPORTED eq 1) | (PNG_GAMMA_SUPPORTED eq 1)
- colorspace png_colorspace
-end if
-end if
-ends
+
+; pngstruct.inc - header file for PNG reference library
+
+; Last changed in libpng 1.6.24 [August 4, 2016]
+; Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
+; (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+; (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+
+; This code is released under the libpng license.
+; For conditions of distribution and use, see the disclaimer
+; and license in png.inc
+
+
+; The structure that holds the information to read and write PNG files.
+; The only people who need to care about what is inside of this are the
+; people who will be modifying the library for their own special needs.
+; It should NOT be accessed directly by an application.
+
+
+; zlib.inc defines the structure z_stream, an instance of which is included
+; in this structure and is required for decompressing the LZ compressed
+; data in PNG files.
+
+include '../../../../../../fs/kfar/trunk/zlib/zlib.inc'
+
+; zlib.inc declares a magic type 'uInt' that limits the amount of data that zlib
+; can handle at once. This type need be no larger than 16 bits (so maximum of
+; 65535), this define allows us to discover how big it is, but limited by the
+; maximuum for png_size_t. The value can be overriden in a library build
+; (pngusr.h, or set it in CPPFLAGS) and it works to set it to a considerably
+; lower value (e.g. 255 works). A lower value may help memory usage (slightly)
+; and may even improve performance on some systems (and degrade it on others.)
+
+
+ZLIB_IO_MAX equ 0xffff ;-1 ;uInt
+
+
+; The type of a compression buffer list used by the write code.
+struct png_compression_buffer
+ next dd ? ;struct png_compression_buffer *
+ output db ? ;byte[1] ;actually zbuf_size
+ends
+
+macro PNG_COMPRESSION_BUFFER_SIZE pp
+{
+ mov eax,png_compression_buffer.output
+ add eax,[pp+png_struct.zbuffer_size]
+}
+
+; Colorspace support; structures used in png_struct, png_info and in internal
+; functions to hold and communicate information about the color space.
+
+; PNG_COLORSPACE_SUPPORTED is only required if the application will perform
+; colorspace corrections, otherwise all the colorspace information can be
+; skipped and the size of libpng can be reduced (significantly) by compiling
+; out the colorspace support.
+
+if PNG_COLORSPACE_SUPPORTED eq 1
+; The chromaticities of the red, green and blue colorants and the chromaticity
+; of the corresponding white point (i.e. of rgb(1.0,1.0,1.0)).
+
+struct png_xy
+ redx dd ? ;png_fixed_point
+ redy dd ?
+ greenx dd ?
+ greeny dd ?
+ bluex dd ?
+ bluey dd ?
+ whitex dd ?
+ whitey dd ?
+ends
+
+; The same data as above but encoded as CIE XYZ values. When this data comes
+; from chromaticities the sum of the Y values is assumed to be 1.0
+
+struct png_XYZ
+ red_X dd ? ;png_fixed_point
+ red_Y dd ?
+ red_Z dd ?
+ green_X dd ?
+ green_Y dd ?
+ green_Z dd ?
+ blue_X dd ?
+ blue_Y dd ?
+ blue_Z dd ?
+ends
+end if ;COLORSPACE
+
+if (PNG_COLORSPACE_SUPPORTED eq 1) | (PNG_GAMMA_SUPPORTED eq 1)
+; A colorspace is all the above plus, potentially, profile information;
+; however at present libpng does not use the profile internally so it is only
+; stored in the png_info struct (if iCCP is supported.) The rendering intent
+; is retained here and is checked.
+
+; The file gamma encoding information is also stored here and gamma correction
+; is done by libpng, whereas color correction must currently be done by the
+; application.
+
+struct png_colorspace
+if PNG_GAMMA_SUPPORTED eq 1
+ gamma dd ? ;png_fixed_point ;File gamma
+end if
+
+if PNG_COLORSPACE_SUPPORTED eq 1
+ end_points_xy png_xy ;End points as chromaticities
+ end_points_XYZ png_XYZ ;End points as CIE XYZ colorant values
+ rendering_intent dw ? ;uint_16 ;Rendering intent of a profile
+end if
+
+ ; Flags are always defined to simplify the code.
+ flags dw ? ;uint_16 ;As defined below
+ends
+
+; General flags for the 'flags' field
+PNG_COLORSPACE_HAVE_GAMMA equ 0x0001
+PNG_COLORSPACE_HAVE_ENDPOINTS equ 0x0002
+PNG_COLORSPACE_HAVE_INTENT equ 0x0004
+PNG_COLORSPACE_FROM_gAMA equ 0x0008
+PNG_COLORSPACE_FROM_cHRM equ 0x0010
+PNG_COLORSPACE_FROM_sRGB equ 0x0020
+PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB equ 0x0040
+PNG_COLORSPACE_MATCHES_sRGB equ 0x0080 ;exact match on profile
+PNG_COLORSPACE_INVALID equ 0x8000
+macro PNG_COLORSPACE_CANCEL flags {(0xffff xor (flags))}
+end if ;COLORSPACE || GAMMA
+
+struct png_struct
+if PNG_SETJMP_SUPPORTED eq 1
+ jmp_buf_local rb 64 ;jmp_buf ;New name in 1.6.0 for jmp_buf in png_struct
+ longjmp_fn dd ? ;png_longjmp_ptr ;setjmp non-local goto function.
+ jmp_buf_ptr dd ? ;jmp_buf * ;passed to longjmp_fn
+ jmp_buf_size dd ? ;size_t ;size of the above, if allocated
+end if
+ error_fn dd ? ;png_error_ptr ;function for printing errors and aborting
+if PNG_WARNINGS_SUPPORTED eq 1
+ warning_fn dd ? ;png_error_ptr ;function for printing warnings
+end if
+ error_ptr dd ? ;voidp ;user supplied struct for error functions
+ write_data_fn dd ? ;png_rw_ptr ;function for writing output data
+ read_data_fn dd ? ;png_rw_ptr ;function for reading input data
+ io_ptr dd ? ;voidp ;ptr to application struct for I/O functions
+
+if PNG_READ_USER_TRANSFORM_SUPPORTED eq 1
+ read_user_transform_fn dd ? ;png_user_transform_ptr ;user read transform
+end if
+
+if PNG_WRITE_USER_TRANSFORM_SUPPORTED eq 1
+ write_user_transform_fn dd ? ;png_user_transform_ptr ; user write transform
+end if
+
+; These were added in libpng-1.0.2
+if PNG_USER_TRANSFORM_PTR_SUPPORTED eq 1
+if (PNG_READ_USER_TRANSFORM_SUPPORTED eq 1) | (PNG_WRITE_USER_TRANSFORM_SUPPORTED eq 1)
+ user_transform_ptr dd ? ;voidp ;user supplied struct for user transform
+ user_transform_depth db ? ;byte ;bit depth of user transformed pixels
+ user_transform_channels db ? ;byte ;channels in user transformed pixels
+ rb 2 ;align
+end if
+end if
+
+ mode dd ? ;uint_32 ;tells us where we are in the PNG file
+ flags dd ? ;uint_32 ;flags indicating various things to libpng
+ transformations dd ? ;uint_32 ;which transformations to perform
+
+ zowner dd ? ;uint_32 ;ID (chunk type) of zstream owner, 0 if none
+ zstream z_stream ;decompression structure
+
+ zbuffer_list dd ? ;png_compression_bufferp ;Created on demand during write
+ zbuffer_size dd ? ;uInt ;size of the actual buffer
+
+ zlib_level dd ? ;int ;holds zlib compression level
+ zlib_method dd ? ;int ;holds zlib compression method
+ zlib_window_bits dd ? ;int ;holds zlib compression window bits
+ zlib_mem_level dd ? ;int ;holds zlib compression memory level
+ zlib_strategy dd ? ;int ;holds zlib compression strategy
+; Added at libpng 1.5.4
+if PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED eq 1
+ zlib_text_level dd ? ;int ;holds zlib compression level
+ zlib_text_method dd ? ;int ;holds zlib compression method
+ zlib_text_window_bits dd ? ;int ;holds zlib compression window bits
+ zlib_text_mem_level dd ? ;int ;holds zlib compression memory level
+ zlib_text_strategy dd ? ;int ;holds zlib compression strategy
+end if
+;End of material added at libpng 1.5.4
+;Added at libpng 1.6.0
+ zlib_set_level dd ? ;int ;Actual values set into the zstream on write
+ zlib_set_method dd ? ;int
+ zlib_set_window_bits dd ? ;int
+ zlib_set_mem_level dd ? ;int
+ zlib_set_strategy dd ? ;int
+
+ width dd ? ;uint_32 ;width of image in pixels
+ height dd ? ;uint_32 ;height of image in pixels
+ num_rows dd ? ;uint_32 ;number of rows in current pass
+ usr_width dd ? ;uint_32 ;width of row at start of write
+ rowbytes dd ? ;png_size_t ;size of row in bytes
+ iwidth dd ? ;uint_32 ;width of current interlaced row in pixels
+ row_number dd ? ;uint_32 ;current row in interlace pass
+ chunk_name dd ? ;uint_32 ;PNG_CHUNK() id of current chunk
+ prev_row dd ? ;bytep ;buffer to save previous (unfiltered) row.
+ ;While reading this is a pointer into
+ ;big_prev_row; while writing it is separately
+ ;allocated if needed.
+
+ row_buf dd ? ;bytep ;buffer to save current (unfiltered) row.
+ ;While reading, this is a pointer into
+ ;big_row_buf; while writing it is separately
+ ;allocated.
+
+if PNG_WRITE_FILTER_SUPPORTED eq 1
+ try_row dd ? ;bytep ;buffer to save trial row when filtering
+ tst_row dd ? ;bytep ;buffer to save best trial row when filtering
+end if
+ info_rowbytes dd ? ;png_size_t ;Added in 1.5.4: cache of updated row bytes
+
+ idat_size dd ? ;uint_32 ;current IDAT size for read
+ crc dd ? ;uint_32 ;current chunk CRC value
+ palette dd ? ;png_colorp ;palette from the input file
+ num_palette dw ? ;uint_16 ;number of color entries in palette
+ rb 2 ;align
+; Added at libpng-1.5.10
+if PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED eq 1
+ num_palette_max dd ? ;int ;maximum palette index found in IDAT
+end if
+
+ num_trans dw ? ;uint_16 ;number of transparency values
+ compression db ? ;byte ;file compression type (always 0)
+ filter db ? ;byte ;file filter type (always 0)
+ interlaced db ? ;byte ;PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7
+ pass db ? ;byte ;current interlace pass (0 - 6)
+ do_filter db ? ;byte ;row filter flags (see PNG_FILTER_ in png.inc)
+ color_type db ? ;byte ;color type of file
+ bit_depth db ? ;byte ;bit depth of file
+ usr_bit_depth db ? ;byte ;bit depth of users row: write only
+ pixel_depth db ? ;byte ;number of bits per pixel
+ channels db ? ;byte ;number of channels in file
+ usr_channels db ? ;byte ;channels at start of write: write only
+ sig_bytes db ? ;byte ;magic bytes read/written from start of file
+ maximum_pixel_depth db ? ;byte ;pixel depth used for the row buffers
+ transformed_pixel_depth db ? ;byte ;pixel depth after read/write transforms
+;if PNG_ZLIB_VERNUM >= 0x1240
+ ;zstream_start db 1 ;byte ;at start of an input zlib stream
+;end if ;Zlib >= 1.2.4
+if (PNG_READ_FILLER_SUPPORTED eq 1) | (PNG_WRITE_FILLER_SUPPORTED eq 1)
+ filler dw ? ;uint_16 ;filler bytes for pixel expansion
+end if
+
+if (PNG_bKGD_SUPPORTED eq 1) | (PNG_READ_BACKGROUND_SUPPORTED eq 1) | \
+ (PNG_READ_ALPHA_MODE_SUPPORTED eq 1)
+ background_gamma_type db ? ;byte
+ rb 1 ;align
+ background_gamma dd ? ;png_fixed_point
+ background png_color_16 ;background color in screen gamma space
+ rb 1 ;align
+if PNG_READ_GAMMA_SUPPORTED eq 1
+ background_1 png_color_16 ;background normalized to gamma 1.0
+ rb 1 ;align
+end if
+end if ;bKGD
+
+if PNG_WRITE_FLUSH_SUPPORTED eq 1
+ output_flush_fn dd ? ;png_flush_ptr ;Function for flushing output
+ flush_dist dd ? ;uint_32 ;how many rows apart to flush, 0 - no flush
+ flush_rows dd ? ;uint_32 ;number of rows written since last flush
+end if
+
+if PNG_READ_GAMMA_SUPPORTED eq 1
+ gamma_shift dd ? ;int ;number of "insignificant" bits in 16-bit gamma
+ screen_gamma dd ? ;png_fixed_point ;screen gamma value (display_exponent)
+
+ gamma_table dd ? ;bytep ;gamma table for 8-bit depth files
+ gamma_16_table dd ? ;uint_16pp ;gamma table for 16-bit depth files
+if (PNG_READ_BACKGROUND_SUPPORTED eq 1) | \
+ (PNG_READ_ALPHA_MODE_SUPPORTED eq 1) | \
+ (PNG_READ_RGB_TO_GRAY_SUPPORTED eq 1)
+ gamma_from_1 dd ? ;bytep ;converts from 1.0 to screen
+ gamma_to_1 dd ? ;bytep ;converts from file to 1.0
+ gamma_16_from_1 dd ? ;uint_16pp ;converts from 1.0 to screen
+ gamma_16_to_1 dd ? ;uint_16pp ;converts from file to 1.0
+end if ;READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY
+end if
+
+if (PNG_READ_GAMMA_SUPPORTED eq 1) | (PNG_sBIT_SUPPORTED eq 1)
+ sig_bit png_color_8 ;significant bits in each available channel
+end if
+
+if (PNG_READ_SHIFT_SUPPORTED eq 1) | (PNG_WRITE_SHIFT_SUPPORTED eq 1)
+ shift png_color_8 ;shift for significant bit tranformation
+ rb 2 ;align
+end if
+
+if (PNG_tRNS_SUPPORTED eq 1) | (PNG_READ_BACKGROUND_SUPPORTED eq 1) \
+ | (PNG_READ_EXPAND_SUPPORTED eq 1) | (PNG_READ_BACKGROUND_SUPPORTED eq 1)
+ trans_alpha dd ? ;bytep ;alpha values for paletted files
+ trans_color png_color_16 ;transparent color for non-paletted files
+ rb 3 ;align
+end if
+
+ read_row_fn dd ? ;png_read_status_ptr ;called after each row is decoded
+ write_row_fn dd ? ;png_write_status_ptr ;called after each row is encoded
+if PNG_PROGRESSIVE_READ_SUPPORTED eq 1
+ info_fn dd ? ;png_progressive_info_ptr ;called after header data fully read
+ row_fn dd ? ;png_progressive_row_ptr ;called after a prog. row is decoded
+ end_fn dd ? ;png_progressive_end_ptr ;called after image is complete
+ save_buffer_ptr dd ? ;bytep ;current location in save_buffer
+ save_buffer dd ? ;bytep ;buffer for previously read data
+ current_buffer_ptr dd ? ;bytep ;current location in current_buffer
+ current_buffer dd ? ;bytep ;buffer for recently used data
+ push_length dd ? ;uint_32 ;size of current input chunk
+ skip_length dd ? ;uint_32 ;bytes to skip in input data
+ save_buffer_size dd ? ;png_size_t ;amount of data now in save_buffer
+ save_buffer_max dd ? ;png_size_t ;total size of save_buffer
+ buffer_size dd ? ;png_size_t ;total amount of available input data
+ current_buffer_size dd ? ;png_size_t ;amount of data now in current_buffer
+ process_mode dd ? ;int ;what push library is currently doing
+ cur_palette dd ? ;int ;current push library palette index
+
+end if ;PROGRESSIVE_READ
+
+if PNG_READ_QUANTIZE_SUPPORTED eq 1
+ palette_lookup dd ? ;bytep ;lookup table for quantizing
+ quantize_index dd ? ;bytep ;index translation for palette files
+end if
+
+; Options
+if PNG_SET_OPTION_SUPPORTED eq 1
+ options db ? ;byte ;On/off state (up to 4 options)
+end if
+
+;#if PNG_LIBPNG_VER < 10700
+; To do: remove this from libpng-1.7
+if PNG_TIME_RFC1123_SUPPORTED eq 1
+ time_buffer rb 29 ;char[29] ;String to hold RFC 1123 time text
+ rb 2 ;align
+end if
+;end if
+
+; New members added in libpng-1.0.6
+
+ free_me dd ? ;uint_32 ;flags items libpng is responsible for freeing
+
+if PNG_USER_CHUNKS_SUPPORTED eq 1
+ user_chunk_ptr dd ? ;voidp
+if PNG_READ_USER_CHUNKS_SUPPORTED eq 1
+ read_user_chunk_fn dd ? ;png_user_chunk_ptr ;user read chunk handler
+end if
+end if
+
+if PNG_SET_UNKNOWN_CHUNKS_SUPPORTED eq 1
+ unknown_default dd ? ;int ; As PNG_HANDLE_*
+ num_chunk_list dd ? ;unsigned int ; Number of entries in the list
+ chunk_list dd ? ;bytep ; List of byte[5]; the textual chunk name
+ ; followed by a PNG_HANDLE_* byte
+end if
+
+; New members added in libpng-1.0.3
+if PNG_READ_RGB_TO_GRAY_SUPPORTED eq 1
+ rgb_to_gray_status db ? ;byte
+ ; Added in libpng 1.5.5 to record setting of coefficients:
+ rgb_to_gray_coefficients_set db ? ;byte
+ ; These were changed from byte in libpng-1.0.6
+ rgb_to_gray_red_coeff dw ? ;uint_16
+ rgb_to_gray_green_coeff dw ? ;uint_16
+ ; deleted in 1.5.5: rgb_to_gray_blue_coeff;
+ rb 2 ;align
+end if
+
+if PNG_MNG_FEATURES_SUPPORTED eq 1
+; New member added in libpng-1.0.4 (renamed in 1.0.9)
+; Changed from byte to uint_32 at version 1.2.0
+ mng_features_permitted dd ? ;uint_32
+
+; New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0
+ filter_type db ? ;byte
+ rb 3 ;align
+end if
+
+; New members added in libpng-1.2.0
+
+; New members added in libpng-1.0.2 but first enabled by default in 1.2.0
+if PNG_USER_MEM_SUPPORTED eq 1
+ mem_ptr dd ? ;voidp ;user supplied struct for mem functions
+ malloc_fn dd ? ;malloc_ptr ;function for allocating memory
+ free_fn dd ? ;free_ptr ;function for freeing memory
+end if
+
+; New member added in libpng-1.0.13 and 1.2.0
+ big_row_buf dd ? ;bytep ;buffer to save current (unfiltered) row
+
+if PNG_READ_QUANTIZE_SUPPORTED eq 1
+; The following three members were added at version 1.0.14 and 1.2.4
+ quantize_sort dd ? ;bytep ;working sort array
+ index_to_palette dd ? ;bytep ;where the original index currently is in the palette
+ palette_to_index dd ? ;bytep ;which original index points to this palette color
+end if
+
+; New members added in libpng-1.0.16 and 1.2.6
+ compression_type db ? ;byte
+ rb 3 ;align
+
+if PNG_USER_LIMITS_SUPPORTED eq 1
+ user_width_max dd ? ;uint_32
+ user_height_max dd ? ;uint_32
+
+ ; Added in libpng-1.4.0: Total number of sPLT, text, and unknown
+ ; chunks that can be stored (0 means unlimited).
+
+ user_chunk_cache_max dd ? ;uint_32
+
+ ; Total memory that a zTXt, sPLT, iTXt, iCCP, or unknown chunk
+ ; can occupy when decompressed. 0 means unlimited.
+
+ user_chunk_malloc_max dd ? ;png_alloc_size_t
+end if
+
+; New member added in libpng-1.0.25 and 1.2.17
+if PNG_READ_UNKNOWN_CHUNKS_SUPPORTED eq 1
+ ; Temporary storage for unknown chunk that the library doesn't recognize,
+ ; used while reading the chunk.
+
+ unknown_chunk png_unknown_chunk
+ rb 3 ;align
+end if
+
+; New member added in libpng-1.2.26
+ old_big_row_buf_size dd ? ;png_size_t
+
+if PNG_READ_SUPPORTED eq 1
+; New member added in libpng-1.2.30
+ read_buffer dd ? ;bytep ;buffer for reading chunk data
+ read_buffer_size dd ? ;png_alloc_size_t ;current size of the buffer
+end if
+if PNG_SEQUENTIAL_READ_SUPPORTED eq 1
+ IDAT_read_size dd ? ;uInt ;limit on read buffer size for IDAT
+end if
+
+if PNG_IO_STATE_SUPPORTED eq 1
+; New member added in libpng-1.4.0
+ io_state dd ? ;uint_32
+end if
+
+ ; New member added in libpng-1.5.6
+ big_prev_row dd ? ;bytep
+
+ ; New member added in libpng-1.5.7
+ read_filter rd PNG_FILTER_VALUE_LAST-1
+
+if PNG_READ_SUPPORTED eq 1
+if (PNG_COLORSPACE_SUPPORTED eq 1) | (PNG_GAMMA_SUPPORTED eq 1)
+ colorspace png_colorspace
+end if
+end if
+ends
diff --git a/programs/develop/libraries/libs-dev/libimg/png/libpng/pngtokos.inc b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngtokos.inc
index 46d01916b..cc4363eef 100644
--- a/programs/develop/libraries/libs-dev/libimg/png/libpng/pngtokos.inc
+++ b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngtokos.inc
@@ -1,299 +1,299 @@
-
-txt_zv db '*',0
-txt_sp db ' ',0
-txt_buf db '1234',0
- rd 1
-
-buf_param rb 80
-
-macro cStr dest,txt
-{
-local .end_t
-local .m_txt
-jmp .end_t
-align 4
- .m_txt db txt,0
-align 4
-.end_t:
-if dest eq
- mov eax,.m_txt
-else
- mov dest,.m_txt
-end if
-}
-
-align 4
-proc f_png_warning, h:dword, m_txt:dword
- stdcall hex_in_str,txt_buf,[h],5
- mov byte[txt_buf+5],0
- stdcall dbg_print,txt_buf,[m_txt]
- ret
-endp
-
-align 4
-proc f_png_error, h:dword, m_txt:dword
- stdcall hex_in_str,txt_buf,[h],5
- mov byte[txt_buf+5],0
- stdcall dbg_print,txt_buf,[m_txt]
- ret
-endp
-
-align 4
-proc f_png_debug, n:dword, m_txt:dword
- stdcall dbg_print,txt_sp,[m_txt]
- ret
-endp
-
-align 4
-proc dbg_print, fun:dword, mes:dword
-pushad
- mov eax,SF_BOARD
- mov ebx,SSF_DEBUG_WRITE
-
- mov esi,[fun]
- cmp esi,0
- je .end0
- @@:
- mov cl,byte[esi]
- int 0x40
- inc esi
- cmp byte[esi],0
- jne @b
- mov cl,':'
- int 0x40
- mov cl,' '
- int 0x40
- .end0:
- mov esi,[mes]
- cmp esi,0
- je .end_f
- @@:
- mov cl,byte[esi]
- cmp cl,0
- je .end_f
- int 0x40
- inc esi
- jmp @b
- .end_f:
-popad
- ret
-endp
-
-;input:
-; zif - 1...8
-align 4
-proc hex_in_str, buf:dword,val:dword,zif:dword
-pushad
- mov edi,dword[buf]
- mov ecx,dword[zif]
- add edi,ecx
- dec edi
- mov ebx,dword[val]
-
- .cycle:
- mov al,bl
- and al,0xf
- cmp al,10
- jl @f
- add al,'a'-'0'-10
- @@:
- add al,'0'
- mov byte[edi],al
- dec edi
- shr ebx,4
- loop .cycle
-popad
- ret
-endp
-
-;---
-
-macro png_warning h,txt
-{
-if txt eqtype ''
- local .end_t
- local .m_txt
- jmp .end_t
- .m_txt db txt,13,10,0
- .end_t:
- stdcall f_png_warning,h,.m_txt
-else
- stdcall f_png_warning,h,txt
- push eax ebx ecx
- mcall SF_BOARD,SSF_DEBUG_WRITE,13
- mcall ,,10
- pop ecx ebx eax
-end if
-}
-
-macro png_app_warning h,txt
-{
- png_warning h,
-}
-
-macro png_error h,txt
-{
-if txt eqtype ''
- local .end_t
- local .m_txt
- jmp .end_t
- .m_txt db txt,13,10,0
- .end_t:
- stdcall f_png_error,h,.m_txt
-else
- stdcall f_png_error,h,txt
- push eax ebx ecx
- mcall SF_BOARD,SSF_DEBUG_WRITE,13
- mcall ,,10
- pop ecx ebx eax
-end if
-}
-
-macro png_debug n,txt
-{
-if DEBUG eq 1
-local .end_t
-local .m_txt
-jmp .end_t
- .m_txt db txt,13,10,0
-align 4
-.end_t:
-stdcall f_png_debug,n,.m_txt
-end if
-}
-
-macro png_debug1 n,fmt,p1
-{
-if DEBUG eq 1
-local .end_t
-
-if p1 eqtype ''
-local .m_txt1
-local .m_txt2
-jmp .end_t
- .m_txt1 db fmt,0
- .m_txt2 db p1,13,10,0
-align 4
-.end_t:
-stdcall dbg_print,.m_txt1,.m_txt2
-
-else
-local .m_fmt
-jmp .end_t
- .m_fmt db fmt,13,10,0
-align 4
-.end_t:
- stdcall str_format_dbg, buf_param,.m_fmt,p1
-
-end if
-end if
-}
-
-;output:
-; eax = strlen
-align 4
-proc strlen, str1:dword
- mov eax,[str1]
- @@:
- cmp byte[eax],0
- je @f
- inc eax
- jmp @b
- @@:
- sub eax,[str1]
- ret
-endp
-
-align 4
-proc str_format_dbg, buf:dword, fmt:dword, p1:dword
-pushad
- mov esi,[fmt]
- mov edi,[buf]
- mov ecx,80-1
- .cycle0:
- lodsb
- cmp al,'%'
- jne .no_param
- lodsb
- dec ecx
- cmp al,0
- je .cycle0end
- cmp al,'d'
- je @f
- cmp al,'u'
- je @f
- cmp al,'l'
- je .end1
- jmp .end0
- .end1: ;%lu %lx
- lodsb
- dec ecx
- cmp al,'u'
- jne .end0
- @@:
- mov eax,[p1]
- stdcall convert_int_to_str,ecx
- xor al,al
- repne scasb
- dec edi
- .end0:
- loop .cycle0
- .no_param:
- stosb
- cmp al,0
- je .cycle0end
- loop .cycle0
- .cycle0end:
- xor al,al
- stosb
- stdcall dbg_print,txt_sp,[buf]
-popad
- ret
-endp
-
-;input:
-; eax - число
-; edi - буфер для строки
-; len - длинна буфера
-;output:
-align 4
-proc convert_int_to_str, len:dword
-pushad
- mov esi,[len]
- add esi,edi
- dec esi
- call .str
-popad
- ret
-endp
-
-align 4
-.str:
- mov ecx,0x0a
- cmp eax,ecx
- jb @f
- xor edx,edx
- div ecx
- push edx
- call .str
- pop eax
- @@:
- cmp edi,esi
- jge @f
- or al,0x30
- stosb
- mov byte[edi],0
- @@:
- ret
-
-macro std_png_image_error n,txt
-{
-local .end_t
-local .m_txt
-jmp .end_t
- .m_txt db txt,13,10,0
-align 4
-.end_t:
-stdcall png_image_error,n,.m_txt
-}
-
+
+txt_zv db '*',0
+txt_sp db ' ',0
+txt_buf db '1234',0
+ rd 1
+
+buf_param rb 80
+
+macro cStr dest,txt
+{
+local .end_t
+local .m_txt
+jmp .end_t
+align 4
+ .m_txt db txt,0
+align 4
+.end_t:
+if dest eq
+ mov eax,.m_txt
+else
+ mov dest,.m_txt
+end if
+}
+
+align 4
+proc f_png_warning, h:dword, m_txt:dword
+ stdcall hex_in_str,txt_buf,[h],5
+ mov byte[txt_buf+5],0
+ stdcall dbg_print,txt_buf,[m_txt]
+ ret
+endp
+
+align 4
+proc f_png_error, h:dword, m_txt:dword
+ stdcall hex_in_str,txt_buf,[h],5
+ mov byte[txt_buf+5],0
+ stdcall dbg_print,txt_buf,[m_txt]
+ ret
+endp
+
+align 4
+proc f_png_debug, n:dword, m_txt:dword
+ stdcall dbg_print,txt_sp,[m_txt]
+ ret
+endp
+
+align 4
+proc dbg_print, fun:dword, mes:dword
+pushad
+ mov eax,SF_BOARD
+ mov ebx,SSF_DEBUG_WRITE
+
+ mov esi,[fun]
+ cmp esi,0
+ je .end0
+ @@:
+ mov cl,byte[esi]
+ int 0x40
+ inc esi
+ cmp byte[esi],0
+ jne @b
+ mov cl,':'
+ int 0x40
+ mov cl,' '
+ int 0x40
+ .end0:
+ mov esi,[mes]
+ cmp esi,0
+ je .end_f
+ @@:
+ mov cl,byte[esi]
+ cmp cl,0
+ je .end_f
+ int 0x40
+ inc esi
+ jmp @b
+ .end_f:
+popad
+ ret
+endp
+
+;input:
+; zif - 1...8
+align 4
+proc hex_in_str, buf:dword,val:dword,zif:dword
+pushad
+ mov edi,dword[buf]
+ mov ecx,dword[zif]
+ add edi,ecx
+ dec edi
+ mov ebx,dword[val]
+
+ .cycle:
+ mov al,bl
+ and al,0xf
+ cmp al,10
+ jl @f
+ add al,'a'-'0'-10
+ @@:
+ add al,'0'
+ mov byte[edi],al
+ dec edi
+ shr ebx,4
+ loop .cycle
+popad
+ ret
+endp
+
+;---
+
+macro png_warning h,txt
+{
+if txt eqtype ''
+ local .end_t
+ local .m_txt
+ jmp .end_t
+ .m_txt db txt,13,10,0
+ .end_t:
+ stdcall f_png_warning,h,.m_txt
+else
+ stdcall f_png_warning,h,txt
+ push eax ebx ecx
+ mcall SF_BOARD,SSF_DEBUG_WRITE,13
+ mcall ,,10
+ pop ecx ebx eax
+end if
+}
+
+macro png_app_warning h,txt
+{
+ png_warning h,
+}
+
+macro png_error h,txt
+{
+if txt eqtype ''
+ local .end_t
+ local .m_txt
+ jmp .end_t
+ .m_txt db txt,13,10,0
+ .end_t:
+ stdcall f_png_error,h,.m_txt
+else
+ stdcall f_png_error,h,txt
+ push eax ebx ecx
+ mcall SF_BOARD,SSF_DEBUG_WRITE,13
+ mcall ,,10
+ pop ecx ebx eax
+end if
+}
+
+macro png_debug n,txt
+{
+if DEBUG eq 1
+local .end_t
+local .m_txt
+jmp .end_t
+ .m_txt db txt,13,10,0
+align 4
+.end_t:
+stdcall f_png_debug,n,.m_txt
+end if
+}
+
+macro png_debug1 n,fmt,p1
+{
+if DEBUG eq 1
+local .end_t
+
+if p1 eqtype ''
+local .m_txt1
+local .m_txt2
+jmp .end_t
+ .m_txt1 db fmt,0
+ .m_txt2 db p1,13,10,0
+align 4
+.end_t:
+stdcall dbg_print,.m_txt1,.m_txt2
+
+else
+local .m_fmt
+jmp .end_t
+ .m_fmt db fmt,13,10,0
+align 4
+.end_t:
+ stdcall str_format_dbg, buf_param,.m_fmt,p1
+
+end if
+end if
+}
+
+;output:
+; eax = strlen
+align 4
+proc strlen, str1:dword
+ mov eax,[str1]
+ @@:
+ cmp byte[eax],0
+ je @f
+ inc eax
+ jmp @b
+ @@:
+ sub eax,[str1]
+ ret
+endp
+
+align 4
+proc str_format_dbg, buf:dword, fmt:dword, p1:dword
+pushad
+ mov esi,[fmt]
+ mov edi,[buf]
+ mov ecx,80-1
+ .cycle0:
+ lodsb
+ cmp al,'%'
+ jne .no_param
+ lodsb
+ dec ecx
+ cmp al,0
+ je .cycle0end
+ cmp al,'d'
+ je @f
+ cmp al,'u'
+ je @f
+ cmp al,'l'
+ je .end1
+ jmp .end0
+ .end1: ;%lu %lx
+ lodsb
+ dec ecx
+ cmp al,'u'
+ jne .end0
+ @@:
+ mov eax,[p1]
+ stdcall convert_int_to_str,ecx
+ xor al,al
+ repne scasb
+ dec edi
+ .end0:
+ loop .cycle0
+ .no_param:
+ stosb
+ cmp al,0
+ je .cycle0end
+ loop .cycle0
+ .cycle0end:
+ xor al,al
+ stosb
+ stdcall dbg_print,txt_sp,[buf]
+popad
+ ret
+endp
+
+;input:
+; eax - число
+; edi - буфер для строки
+; len - длинна буфера
+;output:
+align 4
+proc convert_int_to_str, len:dword
+pushad
+ mov esi,[len]
+ add esi,edi
+ dec esi
+ call .str
+popad
+ ret
+endp
+
+align 4
+.str:
+ mov ecx,0x0a
+ cmp eax,ecx
+ jb @f
+ xor edx,edx
+ div ecx
+ push edx
+ call .str
+ pop eax
+ @@:
+ cmp edi,esi
+ jge @f
+ or al,0x30
+ stosb
+ mov byte[edi],0
+ @@:
+ ret
+
+macro std_png_image_error n,txt
+{
+local .end_t
+local .m_txt
+jmp .end_t
+ .m_txt db txt,13,10,0
+align 4
+.end_t:
+stdcall png_image_error,n,.m_txt
+}
+
diff --git a/programs/develop/libraries/libs-dev/libimg/png/libpng/pngtrans.asm b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngtrans.asm
index 9260424ed..ec805ef39 100644
--- a/programs/develop/libraries/libs-dev/libimg/png/libpng/pngtrans.asm
+++ b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngtrans.asm
@@ -1,909 +1,909 @@
-
-; pngtrans.asm - transforms the data in a row (used by both readers and writers)
-
-; Last changed in libpng 1.6.24 [August 4, 2016]
-; Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
-; (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
-; (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
-
-; This code is released under the libpng license.
-; For conditions of distribution and use, see the disclaimer
-; and license in png.inc
-
-
-if (PNG_READ_SUPPORTED eq 1) | (PNG_WRITE_SUPPORTED eq 1)
-
-; Turn on BGR-to-RGB mapping
-;void (png_structrp png_ptr)
-align 4
-proc png_set_bgr uses edi, png_ptr:dword
- png_debug 1, 'in png_set_bgr'
-
- mov edi,[png_ptr]
- test edi,edi
- jz @f ;if (..==0) return
- or dword[edi+png_struct.transformations], PNG_BGR
- @@:
- ret
-endp
-
-; Turn on 16-bit byte swapping
-;void (png_structrp png_ptr)
-align 4
-proc png_set_swap uses edi, png_ptr:dword
- png_debug 1, 'in png_set_swap'
-
- mov edi,[png_ptr]
- test edi,edi
- jz @f ;if (..==0) return
-
- cmp byte[edi+png_struct.bit_depth],16
- jne @f ;if (..==..)
- or dword[edi+png_struct.transformations], PNG_SWAP_BYTES
- @@:
- ret
-endp
-
-; Turn on pixel packing
-;void (png_structrp png_ptr)
-align 4
-proc png_set_packing uses edi, png_ptr:dword
- png_debug 1, 'in png_set_packing'
-
- mov edi,[png_ptr]
- test edi,edi
- jz @f ;if (..==0) return
-
- cmp byte[edi+png_struct.bit_depth],8
- jge @f ;if (..<..)
- or dword[edi+png_struct.transformations], PNG_PACK
-if PNG_WRITE_SUPPORTED eq 1
- mov byte[edi+png_struct.usr_bit_depth],8
-end if
- @@:
- ret
-endp
-
-; Turn on packed pixel swapping
-;void (png_structrp png_ptr)
-align 4
-proc png_set_packswap uses edi, png_ptr:dword
- png_debug 1, 'in png_set_packswap'
-
- mov edi,[png_ptr]
- test edi,edi
- jz @f ;if (..==0) return
-
- cmp byte[edi+png_struct.bit_depth],8
- jge @f ;if (..<..)
- or dword[edi+png_struct.transformations], PNG_PACKSWAP
- @@:
- ret
-endp
-
-;void (png_structrp png_ptr, png_color_8p true_bits)
-align 4
-proc png_set_shift uses ecx edi, png_ptr:dword, true_bits:dword
- png_debug 1, 'in png_set_shift'
-
- mov edi,[png_ptr]
- test edi,edi
- jz @f ;if (..==0) return
-
- or dword[edi+png_struct.transformations], PNG_SHIFT
- mov ecx,sizeof.png_color_8
- mov edi,[edi+png_struct.shift]
- mov esi,[true_bits]
- rep movsb
- @@:
- ret
-endp
-
-;int (png_structrp png_ptr)
-align 4
-proc png_set_interlace_handling uses edi, png_ptr:dword
- png_debug 1, 'in png_set_interlace handling'
-
- mov edi,[png_ptr]
- test edi,edi
- jz @f
- cmp byte[edi+png_struct.interlaced],0
- je @f ;if(..!=0 && ..!=0)
- or dword[edi+png_struct.transformations], PNG_INTERLACE
- mov eax,7
- jmp .end_f
- @@:
-
- xor eax,eax
- inc eax
-.end_f:
- ret
-endp
-
-; Add a filler byte on read, or remove a filler or alpha byte on write.
-; The filler type has changed in v0.95 to allow future 2-byte fillers
-; for 48-bit input data, as well as to avoid problems with some compilers
-; that don't like bytes as parameters.
-
-;void (png_structrp png_ptr, uint_32 filler, int filler_loc)
-align 4
-proc png_set_filler uses eax edi, png_ptr:dword, filler:dword, filler_loc:dword
- png_debug 1, 'in png_set_filler'
-
- mov edi,[png_ptr]
- test edi,edi
- jz .end_f ;if (..==0) return
-
- ; In libpng 1.6 it is possible to determine whether this is a read or write
- ; operation and therefore to do more checking here for a valid call.
-
- mov eax,[edi+png_struct.mode]
- and eax,PNG_IS_READ_STRUCT
- jz @f ;if (..!=0)
-if PNG_READ_FILLER_SUPPORTED eq 1
- ; On read png_set_filler is always valid, regardless of the base PNG
- ; format, because other transformations can give a format where the
- ; filler code can execute (basically an 8 or 16-bit component RGB or G
- ; format.)
-
- ; NOTE: usr_channels is not used by the read code! (This has led to
- ; confusion in the past.) The filler is only used in the read code.
-
- mov eax,[filler]
- mov [edi+png_struct.filler],ax
- jmp .end0
-else
- cStr ,'png_set_filler not supported on read'
- stdcall png_app_error, edi, eax
- jmp .end_f
-end if
- @@: ;else ;write
-if PNG_WRITE_FILLER_SUPPORTED eq 1
- ; On write the usr_channels parameter must be set correctly at the
- ; start to record the number of channels in the app-supplied data.
-
-; switch (png_ptr->color_type)
-; {
-; case PNG_COLOR_TYPE_RGB:
-; png_ptr->usr_channels = 4;
-; break;
-
-; case PNG_COLOR_TYPE_GRAY:
-; if (png_ptr->bit_depth >= 8)
-; {
-; png_ptr->usr_channels = 2;
-; break;
-; }
-
-; else
-; {
- ; There simply isn't any code in libpng to strip out bits
- ; from bytes when the components are less than a byte in
- ; size!
-
-; png_app_error(png_ptr,
-; "png_set_filler is invalid for"
-; " low bit depth gray output");
-; return;
-; }
-
-; default:
-; png_app_error(png_ptr,
-; "png_set_filler: inappropriate color type");
-; return;
-; }
-else
- cStr ,'png_set_filler not supported on write'
- stdcall png_app_error, edi, eax
- jmp .end_f
-end if
- .end0:
-
- ; Here on success - libpng supports the operation, set the transformation
- ; and the flag to say where the filler channel is.
-
- or dword[edi+png_struct.transformations],PNG_FILLER
-
- cmp dword[filler_loc],PNG_FILLER_AFTER
- jne @f ;if (..==..)
- or dword[edi+png_struct.flags],PNG_FLAG_FILLER_AFTER
- jmp .end_f
- @@: ;else
- and dword[edi+png_struct.flags],not PNG_FLAG_FILLER_AFTER
-.end_f:
- ret
-endp
-
-; Added to libpng-1.2.7
-;void (png_structrp png_ptr, uint_32 filler, int filler_loc)
-align 4
-proc png_set_add_alpha uses eax edi, png_ptr:dword, filler:dword, filler_loc:dword
- png_debug 1, 'in png_set_add_alpha'
-
- mov edi,[png_ptr]
- test edi,edi
- jz .end_f ;if (..==0) return
-
- stdcall png_set_filler, edi, [filler], [filler_loc]
- ; The above may fail to do anything.
- mov eax,[edi+png_struct.transformations]
- and eax,PNG_FILLER
- jz .end_f ;if (..!=0)
- or dword[edi+png_struct.transformations],PNG_ADD_ALPHA
-.end_f:
- ret
-endp
-
-;void (png_structrp png_ptr)
-align 4
-proc png_set_swap_alpha uses edi, png_ptr:dword
- png_debug 1, 'in png_set_swap_alpha'
-
- mov edi,[png_ptr]
- test edi,edi
- jz .end_f ;if (..==0) return
- or dword[edi+png_struct.transformations], PNG_SWAP_ALPHA
-.end_f:
- ret
-endp
-
-
-;void (png_structrp png_ptr)
-align 4
-proc png_set_invert_alpha uses edi, png_ptr:dword
- png_debug 1, 'in png_set_invert_alpha'
-
- mov edi,[png_ptr]
- test edi,edi
- jz .end_f ;if (..==0) return
- or dword[edi+png_struct.transformations], PNG_INVERT_ALPHA
-.end_f:
- ret
-endp
-
-;void (png_structrp png_ptr)
-align 4
-proc png_set_invert_mono uses edi, png_ptr:dword
- png_debug 1, 'in png_set_invert_mono'
-
- mov edi,[png_ptr]
- test edi,edi
- jz .end_f ;if (..==0) return
- or dword[edi+png_struct.transformations], PNG_INVERT_MONO
-.end_f:
- ret
-endp
-
-; Invert monochrome grayscale data
-;void (png_row_infop row_info, bytep row)
-align 4
-proc png_do_invert uses eax ebx ecx edx, row_info:dword, row:dword
- ;ecx - i
- ;eax - rp
- ;edx - istop
- png_debug 1, 'in png_do_invert'
-
- mov ebx,[row_info]
- cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_GRAY
- jne .end0
- mov eax,[row]
- mov edx,[ebx+png_row_info.rowbytes]
- xor ecx,ecx
- jmp @f
-align 4
- .cycle0:
- inc ecx
- @@:
- cmp ecx,edx
- jae .end_f
- not byte[eax]
- inc eax
- jmp .cycle0
-.end0:
- cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_GRAY_ALPHA
- jne .end1
- cmp byte[ebx+png_row_info.bit_depth],8
- jne .end1
- mov eax,[row]
- mov edx,[ebx+png_row_info.rowbytes]
- xor ecx,ecx
- jmp @f
-align 4
- .cycle1:
- add ecx,2
- @@:
- cmp ecx,edx
- jae .end_f
- not byte[eax]
- add eax,2
- jmp .cycle1
-.end1:
-if PNG_16BIT_SUPPORTED eq 1
- cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_GRAY_ALPHA
- jne .end_f
- cmp byte[ebx+png_row_info.bit_depth],16
- jne .end_f
- mov eax,[row]
- mov edx,[ebx+png_row_info.rowbytes]
- xor ecx,ecx
- jmp @f
-align 4
- .cycle2:
- add ecx,4
- @@:
- cmp ecx,edx
- jae .end_f
- not word[eax]
- add eax,4
- jmp .cycle2
-end if
-.end_f:
- ret
-endp
-
-; Swaps byte order on 16-bit depth images
-;void (png_row_infop row_info, bytep row)
-align 4
-proc png_do_swap, row_info:dword, row:dword
- png_debug 1, 'in png_do_swap'
-
-; if (row_info->bit_depth == 16)
-; {
-; bytep rp = row;
-; uint_32 i;
-; uint_32 istop= row_info->width * row_info->channels;
-
-; for (i = 0; i < istop; i++, rp += 2)
-; {
-if PNG_BUILTIN_BSWAP16_SUPPORTED eq 1
- ; Feature added to libpng-1.6.11 for testing purposes, not
- ; enabled by default.
-
-; *(uint_16*)rp = __builtin_bswap16(*(uint_16*)rp);
-else
-; byte t = *rp;
-; *rp = *(rp + 1);
-; *(rp + 1) = t;
-end if
-; }
-; }
- ret
-endp
-
-if (PNG_READ_PACKSWAP_SUPPORTED eq 1) | (PNG_WRITE_PACKSWAP_SUPPORTED eq 1)
-align 4
-onebppswaptable db 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,\
- 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,\
- 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,\
- 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,\
- 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,\
- 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,\
- 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,\
- 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,\
- 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,\
- 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,\
- 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,\
- 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,\
- 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,\
- 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,\
- 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,\
- 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,\
- 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,\
- 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,\
- 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,\
- 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,\
- 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,\
- 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,\
- 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,\
- 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,\
- 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,\
- 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,\
- 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,\
- 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,\
- 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,\
- 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,\
- 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,\
- 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
-
-align 4
-twobppswaptable db 0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0,\
- 0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0,\
- 0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4,\
- 0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4,\
- 0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8,\
- 0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8,\
- 0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC,\
- 0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC,\
- 0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1,\
- 0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1,\
- 0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5,\
- 0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5,\
- 0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9,\
- 0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9,\
- 0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD,\
- 0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD,\
- 0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2,\
- 0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2,\
- 0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6,\
- 0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6,\
- 0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA,\
- 0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA,\
- 0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE,\
- 0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE,\
- 0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3,\
- 0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3,\
- 0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7,\
- 0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7,\
- 0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB,\
- 0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB,\
- 0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF,\
- 0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF
-
-align 4
-fourbppswaptable db 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,\
- 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,\
- 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,\
- 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,\
- 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72,\
- 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2,\
- 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73,\
- 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3,\
- 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74,\
- 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4,\
- 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75,\
- 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5,\
- 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76,\
- 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6,\
- 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77,\
- 0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7,\
- 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78,\
- 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8,\
- 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79,\
- 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9,\
- 0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A,\
- 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA,\
- 0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B,\
- 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB,\
- 0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C,\
- 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC,\
- 0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D,\
- 0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD,\
- 0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E,\
- 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE,\
- 0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F,\
- 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF
-end if ;PACKSWAP || WRITE_PACKSWAP
-
-; Swaps pixel packing order within bytes
-;void (png_row_infop row_info, bytep row)
-align 4
-proc png_do_packswap uses eax edx edi esi, row_info:dword, row:dword
- png_debug 1, 'in png_do_packswap'
-
- mov eax,[row_info]
- cmp byte[eax+png_row_info.bit_depth],8
- jge .end_f ;if (..<..)
- ;edi = rp
- ;esi = table
-
- mov edx,[eax+png_row_info.rowbytes]
- mov edi,[row]
- add edx,edi
-
- cmp byte[eax+png_row_info.bit_depth],1
- jne @f ;if (..==..)
- mov esi,onebppswaptable
- jmp .cycle0
- @@:
- cmp byte[eax+png_row_info.bit_depth],2
- jne @f ;else if (..==..)
- mov esi,twobppswaptable
- jmp .cycle0
- @@:
- cmp byte[eax+png_row_info.bit_depth],4
- jne .end_f ;else if (..==..)
- mov esi,fourbppswaptable
-align 4
- .cycle0: ;for (..=..;..<..;..)
- cmp edi,edx
- jge .end_f
- movzx eax,byte[edi]
- mov al,byte[esi+eax]
- stosb ;*rp = table[*rp]
- jmp .cycle0
-.end_f:
- ret
-endp
-
-; Remove a channel - this used to be 'png_do_strip_filler' but it used a
-; somewhat weird combination of flags to determine what to do. All the calls
-; to png_do_strip_filler are changed in 1.5.2 to call this instead with the
-; correct arguments.
-
-; The routine isn't general - the channel must be the channel at the start or
-; end (not in the middle) of each pixel.
-
-;void (png_row_infop row_info, bytep row, int at_start)
-align 4
-proc png_do_strip_channel, row_info:dword, row:dword, at_start:dword
-; bytep sp = row; /* source pointer */
-; bytep dp = row; /* destination pointer */
-; bytep ep = row + row_info->rowbytes; /* One beyond end of row */
-
- ; At the start sp will point to the first byte to copy and dp to where
- ; it is copied to. ep always points just beyond the end of the row, so
- ; the loop simply copies (channels-1) channels until sp reaches ep.
-
- ; at_start: 0 -- convert AG, XG, ARGB, XRGB, AAGG, XXGG, etc.
- ; nonzero -- convert GA, GX, RGBA, RGBX, GGAA, RRGGBBXX, etc.
-
-
- ; GA, GX, XG cases
-; if (row_info->channels == 2)
-; {
-; if (row_info->bit_depth == 8)
-; {
-; if (at_start != 0) /* Skip initial filler */
-; ++sp;
-; else /* Skip initial channel and, for sp, the filler */
-; sp += 2, ++dp;
-
- ; For a 1 pixel wide image there is nothing to do
-; while (sp < ep)
-; *dp++ = *sp, sp += 2;
-
-; row_info->pixel_depth = 8;
-; }
-
-; else if (row_info->bit_depth == 16)
-; {
-; if (at_start != 0) /* Skip initial filler */
-; sp += 2;
-; else /* Skip initial channel and, for sp, the filler */
-; sp += 4, dp += 2;
-
-; while (sp < ep)
-; *dp++ = *sp++, *dp++ = *sp, sp += 3;
-
-; row_info->pixel_depth = 16;
-; }
-
-; else
-; return; /* bad bit depth */
-
-; row_info->channels = 1;
-
- ; Finally fix the color type if it records an alpha channel
-; if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
-; row_info->color_type = PNG_COLOR_TYPE_GRAY;
-; }
-
- ; RGBA, RGBX, XRGB cases
-; else if (row_info->channels == 4)
-; {
-; if (row_info->bit_depth == 8)
-; {
-; if (at_start != 0) /* Skip initial filler */
-; ++sp;
-; else /* Skip initial channels and, for sp, the filler */
-; sp += 4, dp += 3;
-
- ; Note that the loop adds 3 to dp and 4 to sp each time.
-; while (sp < ep)
-; *dp++ = *sp++, *dp++ = *sp++, *dp++ = *sp, sp += 2;
-
-; row_info->pixel_depth = 24;
-; }
-
-; else if (row_info->bit_depth == 16)
-; {
-; if (at_start != 0) /* Skip initial filler */
-; sp += 2;
-; else /* Skip initial channels and, for sp, the filler */
-; sp += 8, dp += 6;
-
-; while (sp < ep)
-; {
-; /* Copy 6 bytes, skip 2 */
-; *dp++ = *sp++, *dp++ = *sp++;
-; *dp++ = *sp++, *dp++ = *sp++;
-; *dp++ = *sp++, *dp++ = *sp, sp += 3;
-; }
-
-; row_info->pixel_depth = 48;
-; }
-
-; else
-; return; /* bad bit depth */
-
-; row_info->channels = 3;
-
- ; Finally fix the color type if it records an alpha channel
-; if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
-; row_info->color_type = PNG_COLOR_TYPE_RGB;
-; }
-
-; else
-; return; /* The filler channel has gone already */
-
- ; Fix the rowbytes value.
-; row_info->rowbytes = dp-row;
- ret
-endp
-
-; Swaps red and blue bytes within a pixel
-;void (png_row_infop row_info, bytep row)
-align 4
-proc png_do_bgr, row_info:dword, row:dword
- png_debug 1, 'in png_do_bgr'
- ;ebx - rp
- ;ecx - i
- ;esi - row_width
-pushad
- mov edi,[row_info]
- movzx eax,byte[edi+png_row_info.color_type]
- and eax,PNG_COLOR_MASK_COLOR
- je .end_f
- mov esi,[edi+png_row_info.width]
- cmp byte[edi+png_row_info.bit_depth],8
- jne .end0
- cmp byte[edi+png_row_info.color_type],PNG_COLOR_TYPE_RGB
- jne .end1
- xor ecx,ecx
- mov ebx,[row]
- jmp @f
-align 4
- .cycle0:
- inc ecx
- add ebx,3
- @@:
- cmp ecx,esi
- jae .end_f
- mov dl,[ebx]
- mov al,[ebx+2]
- mov [ebx],al
- mov [ebx+2],dl
- jmp .cycle0
-.end1:
- cmp byte[edi+png_row_info.color_type],PNG_COLOR_TYPE_RGB_ALPHA
- jne .end_f
- xor ecx,ecx
- mov ebx,[row]
- jmp @f
-align 4
- .cycle1:
- inc ecx
- add ebx,4
- @@:
- cmp ecx,esi
- jae .end_f
- mov dl,[ebx]
- mov al,[ebx+2]
- mov [ebx],al
- mov [ebx+2],dl
- jmp .cycle1
-.end0:
-if PNG_16BIT_SUPPORTED eq 1
- cmp byte[edi+png_row_info.bit_depth],16
- jne .end_f
- cmp byte[edi+png_row_info.color_type],PNG_COLOR_TYPE_RGB
- jne .end2
- xor ecx,ecx
- mov ebx,[row]
- jmp @f
-align 4
- .cycle2:
- inc ecx
- add ebx,6
- @@:
- cmp ecx,esi
- jae .end_f
- mov dx,[ebx]
- mov ax,[ebx+4]
- mov [ebx],ax
- mov [ebx+4],dx
- jmp .cycle2
-.end2:
- cmp byte[edi+png_row_info.color_type],PNG_COLOR_TYPE_RGB_ALPHA
- jne .end_f
- xor ecx,ecx
- mov ebx,[row]
- jmp @f
-align 4
- .cycle3:
- inc ecx
- add ebx,8
- @@:
- cmp ecx,esi
- jae .end_f
- mov dx,[ebx]
- mov ax,[ebx+4]
- mov [ebx],ax
- mov [ebx+4],dx
- jmp .cycle3
-end if
-.end_f:
-popad
- ret
-endp
-
-; Added at libpng-1.5.10
-;void (png_structrp png_ptr, png_row_infop row_info)
-align 4
-proc png_do_check_palette_indexes, png_ptr:dword, row_info:dword
-; if (png_ptr->num_palette < (1 << row_info->bit_depth) &&
-; png_ptr->num_palette > 0) /* num_palette can be 0 in MNG files */
-; {
- ; Calculations moved outside switch in an attempt to stop different
- ; compiler warnings. 'padding' is in *bits* within the last byte, it is
- ; an 'int' because pixel_depth becomes an 'int' in the expression below,
- ; and this calculation is used because it avoids warnings that other
- ; forms produced on either GCC or MSVC.
-
-; int padding = (-row_info->pixel_depth * row_info->width) & 7;
-; bytep rp = png_ptr->row_buf + row_info->rowbytes;
-
-; switch (row_info->bit_depth)
-; {
-; case 1:
-; {
-; /* in this case, all bytes must be 0 so we don't need
- ; to unpack the pixels except for the rightmost one.
-
-; for (; rp > png_ptr->row_buf; rp--)
-; {
-; if ((*rp >> padding) != 0)
-; png_ptr->num_palette_max = 1;
-; padding = 0;
-; }
-
-; break;
-; }
-
-; case 2:
-; {
-; for (; rp > png_ptr->row_buf; rp--)
-; {
-; int i = ((*rp >> padding) & 0x03);
-
-; if (i > png_ptr->num_palette_max)
-; png_ptr->num_palette_max = i;
-
-; i = (((*rp >> padding) >> 2) & 0x03);
-
-; if (i > png_ptr->num_palette_max)
-; png_ptr->num_palette_max = i;
-
-; i = (((*rp >> padding) >> 4) & 0x03);
-
-; if (i > png_ptr->num_palette_max)
-; png_ptr->num_palette_max = i;
-
-; i = (((*rp >> padding) >> 6) & 0x03);
-
-; if (i > png_ptr->num_palette_max)
-; png_ptr->num_palette_max = i;
-
-; padding = 0;
-; }
-
-; break;
-; }
-
-; case 4:
-; {
-; for (; rp > png_ptr->row_buf; rp--)
-; {
-; int i = ((*rp >> padding) & 0x0f);
-
-; if (i > png_ptr->num_palette_max)
-; png_ptr->num_palette_max = i;
-
-; i = (((*rp >> padding) >> 4) & 0x0f);
-
-; if (i > png_ptr->num_palette_max)
-; png_ptr->num_palette_max = i;
-
-; padding = 0;
-; }
-
-; break;
-; }
-
-; case 8:
-; {
-; for (; rp > png_ptr->row_buf; rp--)
-; {
-; if (*rp > png_ptr->num_palette_max)
-; png_ptr->num_palette_max = (int) *rp;
-; }
-
-; break;
-; }
-
-; default:
-; break;
-; }
-; }
- ret
-endp
-
-;void (png_structrp png_ptr, voidp user_transform_ptr, int user_transform_depth, int user_transform_channels)
-align 4
-proc png_set_user_transform_info uses eax edi, png_ptr:dword, user_transform_ptr:dword, user_transform_depth:dword, user_transform_channels:dword
- png_debug 1, 'in png_set_user_transform_info'
-
- mov edi,[png_ptr]
- test edi,edi
- jz .end_f
-
-if PNG_READ_USER_TRANSFORM_SUPPORTED eq 1
- mov eax,[edi+png_struct.mode]
- and eax,PNG_IS_READ_STRUCT
- jz @f
- mov eax,[edi+png_struct.flags]
- and eax,PNG_FLAG_ROW_INIT
- jz @f ;if (..!=0 && ..!=0)
- cStr ,'info change after png_start_read_image or png_read_update_info'
- stdcall png_app_error, edi, eax
- jmp .end_f
- @@:
-end if
-
- mov eax,[user_transform_ptr]
- mov [edi+png_struct.user_transform_ptr],eax
- mov eax,[user_transform_depth]
- mov [edi+png_struct.user_transform_depth],al
- mov eax,[user_transform_channels]
- mov [edi+png_struct.user_transform_channels],al
-.end_f:
- ret
-endp
-
-; This function returns a pointer to the user_transform_ptr associated with
-; the user transform functions. The application should free any memory
-; associated with this pointer before png_write_destroy and png_read_destroy
-; are called.
-
-;voidp (png_structrp png_ptr)
-align 4
-proc png_get_user_transform_ptr, png_ptr:dword
- mov eax,[png_ptr]
- cmp eax,0
- je @f
- mov eax,[eax+png_struct.user_transform_ptr]
- @@:
- ret
-endp
-
-;uint_32 (png_structrp png_ptr)
-align 4
-proc png_get_current_row_number, png_ptr:dword
- ; See the comments in png.inc - this is the sub-image row when reading an
- ; interlaced image.
-
- mov eax,[png_ptr]
- cmp eax,0
- je @f ;if (..!=0)
- mov eax,[eax+png_struct.row_number]
- jmp .end_f
- @@:
- mov eax,PNG_UINT_32_MAX ;help the app not to fail silently
-.end_f:
- ret
-endp
-
-;byte (png_structrp png_ptr)
-align 4
-proc png_get_current_pass_number, png_ptr:dword
- mov eax,[png_ptr]
- cmp eax,0
- je @f ;if (..!=0)
- mov eax,[eax+png_struct.pass]
- jmp .end_f
- @@:
- mov eax,8 ;invalid
-.end_f:
- ret
-endp
-end if
+
+; pngtrans.asm - transforms the data in a row (used by both readers and writers)
+
+; Last changed in libpng 1.6.24 [August 4, 2016]
+; Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
+; (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+; (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+
+; This code is released under the libpng license.
+; For conditions of distribution and use, see the disclaimer
+; and license in png.inc
+
+
+if (PNG_READ_SUPPORTED eq 1) | (PNG_WRITE_SUPPORTED eq 1)
+
+; Turn on BGR-to-RGB mapping
+;void (png_structrp png_ptr)
+align 4
+proc png_set_bgr uses edi, png_ptr:dword
+ png_debug 1, 'in png_set_bgr'
+
+ mov edi,[png_ptr]
+ test edi,edi
+ jz @f ;if (..==0) return
+ or dword[edi+png_struct.transformations], PNG_BGR
+ @@:
+ ret
+endp
+
+; Turn on 16-bit byte swapping
+;void (png_structrp png_ptr)
+align 4
+proc png_set_swap uses edi, png_ptr:dword
+ png_debug 1, 'in png_set_swap'
+
+ mov edi,[png_ptr]
+ test edi,edi
+ jz @f ;if (..==0) return
+
+ cmp byte[edi+png_struct.bit_depth],16
+ jne @f ;if (..==..)
+ or dword[edi+png_struct.transformations], PNG_SWAP_BYTES
+ @@:
+ ret
+endp
+
+; Turn on pixel packing
+;void (png_structrp png_ptr)
+align 4
+proc png_set_packing uses edi, png_ptr:dword
+ png_debug 1, 'in png_set_packing'
+
+ mov edi,[png_ptr]
+ test edi,edi
+ jz @f ;if (..==0) return
+
+ cmp byte[edi+png_struct.bit_depth],8
+ jge @f ;if (..<..)
+ or dword[edi+png_struct.transformations], PNG_PACK
+if PNG_WRITE_SUPPORTED eq 1
+ mov byte[edi+png_struct.usr_bit_depth],8
+end if
+ @@:
+ ret
+endp
+
+; Turn on packed pixel swapping
+;void (png_structrp png_ptr)
+align 4
+proc png_set_packswap uses edi, png_ptr:dword
+ png_debug 1, 'in png_set_packswap'
+
+ mov edi,[png_ptr]
+ test edi,edi
+ jz @f ;if (..==0) return
+
+ cmp byte[edi+png_struct.bit_depth],8
+ jge @f ;if (..<..)
+ or dword[edi+png_struct.transformations], PNG_PACKSWAP
+ @@:
+ ret
+endp
+
+;void (png_structrp png_ptr, png_color_8p true_bits)
+align 4
+proc png_set_shift uses ecx edi, png_ptr:dword, true_bits:dword
+ png_debug 1, 'in png_set_shift'
+
+ mov edi,[png_ptr]
+ test edi,edi
+ jz @f ;if (..==0) return
+
+ or dword[edi+png_struct.transformations], PNG_SHIFT
+ mov ecx,sizeof.png_color_8
+ mov edi,[edi+png_struct.shift]
+ mov esi,[true_bits]
+ rep movsb
+ @@:
+ ret
+endp
+
+;int (png_structrp png_ptr)
+align 4
+proc png_set_interlace_handling uses edi, png_ptr:dword
+ png_debug 1, 'in png_set_interlace handling'
+
+ mov edi,[png_ptr]
+ test edi,edi
+ jz @f
+ cmp byte[edi+png_struct.interlaced],0
+ je @f ;if(..!=0 && ..!=0)
+ or dword[edi+png_struct.transformations], PNG_INTERLACE
+ mov eax,7
+ jmp .end_f
+ @@:
+
+ xor eax,eax
+ inc eax
+.end_f:
+ ret
+endp
+
+; Add a filler byte on read, or remove a filler or alpha byte on write.
+; The filler type has changed in v0.95 to allow future 2-byte fillers
+; for 48-bit input data, as well as to avoid problems with some compilers
+; that don't like bytes as parameters.
+
+;void (png_structrp png_ptr, uint_32 filler, int filler_loc)
+align 4
+proc png_set_filler uses eax edi, png_ptr:dword, filler:dword, filler_loc:dword
+ png_debug 1, 'in png_set_filler'
+
+ mov edi,[png_ptr]
+ test edi,edi
+ jz .end_f ;if (..==0) return
+
+ ; In libpng 1.6 it is possible to determine whether this is a read or write
+ ; operation and therefore to do more checking here for a valid call.
+
+ mov eax,[edi+png_struct.mode]
+ and eax,PNG_IS_READ_STRUCT
+ jz @f ;if (..!=0)
+if PNG_READ_FILLER_SUPPORTED eq 1
+ ; On read png_set_filler is always valid, regardless of the base PNG
+ ; format, because other transformations can give a format where the
+ ; filler code can execute (basically an 8 or 16-bit component RGB or G
+ ; format.)
+
+ ; NOTE: usr_channels is not used by the read code! (This has led to
+ ; confusion in the past.) The filler is only used in the read code.
+
+ mov eax,[filler]
+ mov [edi+png_struct.filler],ax
+ jmp .end0
+else
+ cStr ,'png_set_filler not supported on read'
+ stdcall png_app_error, edi, eax
+ jmp .end_f
+end if
+ @@: ;else ;write
+if PNG_WRITE_FILLER_SUPPORTED eq 1
+ ; On write the usr_channels parameter must be set correctly at the
+ ; start to record the number of channels in the app-supplied data.
+
+; switch (png_ptr->color_type)
+; {
+; case PNG_COLOR_TYPE_RGB:
+; png_ptr->usr_channels = 4;
+; break;
+
+; case PNG_COLOR_TYPE_GRAY:
+; if (png_ptr->bit_depth >= 8)
+; {
+; png_ptr->usr_channels = 2;
+; break;
+; }
+
+; else
+; {
+ ; There simply isn't any code in libpng to strip out bits
+ ; from bytes when the components are less than a byte in
+ ; size!
+
+; png_app_error(png_ptr,
+; "png_set_filler is invalid for"
+; " low bit depth gray output");
+; return;
+; }
+
+; default:
+; png_app_error(png_ptr,
+; "png_set_filler: inappropriate color type");
+; return;
+; }
+else
+ cStr ,'png_set_filler not supported on write'
+ stdcall png_app_error, edi, eax
+ jmp .end_f
+end if
+ .end0:
+
+ ; Here on success - libpng supports the operation, set the transformation
+ ; and the flag to say where the filler channel is.
+
+ or dword[edi+png_struct.transformations],PNG_FILLER
+
+ cmp dword[filler_loc],PNG_FILLER_AFTER
+ jne @f ;if (..==..)
+ or dword[edi+png_struct.flags],PNG_FLAG_FILLER_AFTER
+ jmp .end_f
+ @@: ;else
+ and dword[edi+png_struct.flags],not PNG_FLAG_FILLER_AFTER
+.end_f:
+ ret
+endp
+
+; Added to libpng-1.2.7
+;void (png_structrp png_ptr, uint_32 filler, int filler_loc)
+align 4
+proc png_set_add_alpha uses eax edi, png_ptr:dword, filler:dword, filler_loc:dword
+ png_debug 1, 'in png_set_add_alpha'
+
+ mov edi,[png_ptr]
+ test edi,edi
+ jz .end_f ;if (..==0) return
+
+ stdcall png_set_filler, edi, [filler], [filler_loc]
+ ; The above may fail to do anything.
+ mov eax,[edi+png_struct.transformations]
+ and eax,PNG_FILLER
+ jz .end_f ;if (..!=0)
+ or dword[edi+png_struct.transformations],PNG_ADD_ALPHA
+.end_f:
+ ret
+endp
+
+;void (png_structrp png_ptr)
+align 4
+proc png_set_swap_alpha uses edi, png_ptr:dword
+ png_debug 1, 'in png_set_swap_alpha'
+
+ mov edi,[png_ptr]
+ test edi,edi
+ jz .end_f ;if (..==0) return
+ or dword[edi+png_struct.transformations], PNG_SWAP_ALPHA
+.end_f:
+ ret
+endp
+
+
+;void (png_structrp png_ptr)
+align 4
+proc png_set_invert_alpha uses edi, png_ptr:dword
+ png_debug 1, 'in png_set_invert_alpha'
+
+ mov edi,[png_ptr]
+ test edi,edi
+ jz .end_f ;if (..==0) return
+ or dword[edi+png_struct.transformations], PNG_INVERT_ALPHA
+.end_f:
+ ret
+endp
+
+;void (png_structrp png_ptr)
+align 4
+proc png_set_invert_mono uses edi, png_ptr:dword
+ png_debug 1, 'in png_set_invert_mono'
+
+ mov edi,[png_ptr]
+ test edi,edi
+ jz .end_f ;if (..==0) return
+ or dword[edi+png_struct.transformations], PNG_INVERT_MONO
+.end_f:
+ ret
+endp
+
+; Invert monochrome grayscale data
+;void (png_row_infop row_info, bytep row)
+align 4
+proc png_do_invert uses eax ebx ecx edx, row_info:dword, row:dword
+ ;ecx - i
+ ;eax - rp
+ ;edx - istop
+ png_debug 1, 'in png_do_invert'
+
+ mov ebx,[row_info]
+ cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_GRAY
+ jne .end0
+ mov eax,[row]
+ mov edx,[ebx+png_row_info.rowbytes]
+ xor ecx,ecx
+ jmp @f
+align 4
+ .cycle0:
+ inc ecx
+ @@:
+ cmp ecx,edx
+ jae .end_f
+ not byte[eax]
+ inc eax
+ jmp .cycle0
+.end0:
+ cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_GRAY_ALPHA
+ jne .end1
+ cmp byte[ebx+png_row_info.bit_depth],8
+ jne .end1
+ mov eax,[row]
+ mov edx,[ebx+png_row_info.rowbytes]
+ xor ecx,ecx
+ jmp @f
+align 4
+ .cycle1:
+ add ecx,2
+ @@:
+ cmp ecx,edx
+ jae .end_f
+ not byte[eax]
+ add eax,2
+ jmp .cycle1
+.end1:
+if PNG_16BIT_SUPPORTED eq 1
+ cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_GRAY_ALPHA
+ jne .end_f
+ cmp byte[ebx+png_row_info.bit_depth],16
+ jne .end_f
+ mov eax,[row]
+ mov edx,[ebx+png_row_info.rowbytes]
+ xor ecx,ecx
+ jmp @f
+align 4
+ .cycle2:
+ add ecx,4
+ @@:
+ cmp ecx,edx
+ jae .end_f
+ not word[eax]
+ add eax,4
+ jmp .cycle2
+end if
+.end_f:
+ ret
+endp
+
+; Swaps byte order on 16-bit depth images
+;void (png_row_infop row_info, bytep row)
+align 4
+proc png_do_swap, row_info:dword, row:dword
+ png_debug 1, 'in png_do_swap'
+
+; if (row_info->bit_depth == 16)
+; {
+; bytep rp = row;
+; uint_32 i;
+; uint_32 istop= row_info->width * row_info->channels;
+
+; for (i = 0; i < istop; i++, rp += 2)
+; {
+if PNG_BUILTIN_BSWAP16_SUPPORTED eq 1
+ ; Feature added to libpng-1.6.11 for testing purposes, not
+ ; enabled by default.
+
+; *(uint_16*)rp = __builtin_bswap16(*(uint_16*)rp);
+else
+; byte t = *rp;
+; *rp = *(rp + 1);
+; *(rp + 1) = t;
+end if
+; }
+; }
+ ret
+endp
+
+if (PNG_READ_PACKSWAP_SUPPORTED eq 1) | (PNG_WRITE_PACKSWAP_SUPPORTED eq 1)
+align 4
+onebppswaptable db 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,\
+ 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,\
+ 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,\
+ 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,\
+ 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,\
+ 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,\
+ 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,\
+ 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,\
+ 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,\
+ 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,\
+ 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,\
+ 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,\
+ 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,\
+ 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,\
+ 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,\
+ 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,\
+ 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,\
+ 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,\
+ 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,\
+ 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,\
+ 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,\
+ 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,\
+ 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,\
+ 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,\
+ 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,\
+ 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,\
+ 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,\
+ 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,\
+ 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,\
+ 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,\
+ 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,\
+ 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
+
+align 4
+twobppswaptable db 0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0,\
+ 0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0,\
+ 0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4,\
+ 0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4,\
+ 0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8,\
+ 0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8,\
+ 0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC,\
+ 0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC,\
+ 0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1,\
+ 0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1,\
+ 0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5,\
+ 0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5,\
+ 0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9,\
+ 0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9,\
+ 0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD,\
+ 0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD,\
+ 0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2,\
+ 0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2,\
+ 0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6,\
+ 0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6,\
+ 0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA,\
+ 0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA,\
+ 0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE,\
+ 0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE,\
+ 0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3,\
+ 0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3,\
+ 0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7,\
+ 0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7,\
+ 0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB,\
+ 0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB,\
+ 0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF,\
+ 0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF
+
+align 4
+fourbppswaptable db 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,\
+ 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,\
+ 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,\
+ 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,\
+ 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72,\
+ 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2,\
+ 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73,\
+ 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3,\
+ 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74,\
+ 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4,\
+ 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75,\
+ 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5,\
+ 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76,\
+ 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6,\
+ 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77,\
+ 0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7,\
+ 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78,\
+ 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8,\
+ 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79,\
+ 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9,\
+ 0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A,\
+ 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA,\
+ 0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B,\
+ 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB,\
+ 0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C,\
+ 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC,\
+ 0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D,\
+ 0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD,\
+ 0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E,\
+ 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE,\
+ 0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F,\
+ 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF
+end if ;PACKSWAP || WRITE_PACKSWAP
+
+; Swaps pixel packing order within bytes
+;void (png_row_infop row_info, bytep row)
+align 4
+proc png_do_packswap uses eax edx edi esi, row_info:dword, row:dword
+ png_debug 1, 'in png_do_packswap'
+
+ mov eax,[row_info]
+ cmp byte[eax+png_row_info.bit_depth],8
+ jge .end_f ;if (..<..)
+ ;edi = rp
+ ;esi = table
+
+ mov edx,[eax+png_row_info.rowbytes]
+ mov edi,[row]
+ add edx,edi
+
+ cmp byte[eax+png_row_info.bit_depth],1
+ jne @f ;if (..==..)
+ mov esi,onebppswaptable
+ jmp .cycle0
+ @@:
+ cmp byte[eax+png_row_info.bit_depth],2
+ jne @f ;else if (..==..)
+ mov esi,twobppswaptable
+ jmp .cycle0
+ @@:
+ cmp byte[eax+png_row_info.bit_depth],4
+ jne .end_f ;else if (..==..)
+ mov esi,fourbppswaptable
+align 4
+ .cycle0: ;for (..=..;..<..;..)
+ cmp edi,edx
+ jge .end_f
+ movzx eax,byte[edi]
+ mov al,byte[esi+eax]
+ stosb ;*rp = table[*rp]
+ jmp .cycle0
+.end_f:
+ ret
+endp
+
+; Remove a channel - this used to be 'png_do_strip_filler' but it used a
+; somewhat weird combination of flags to determine what to do. All the calls
+; to png_do_strip_filler are changed in 1.5.2 to call this instead with the
+; correct arguments.
+
+; The routine isn't general - the channel must be the channel at the start or
+; end (not in the middle) of each pixel.
+
+;void (png_row_infop row_info, bytep row, int at_start)
+align 4
+proc png_do_strip_channel, row_info:dword, row:dword, at_start:dword
+; bytep sp = row; /* source pointer */
+; bytep dp = row; /* destination pointer */
+; bytep ep = row + row_info->rowbytes; /* One beyond end of row */
+
+ ; At the start sp will point to the first byte to copy and dp to where
+ ; it is copied to. ep always points just beyond the end of the row, so
+ ; the loop simply copies (channels-1) channels until sp reaches ep.
+
+ ; at_start: 0 -- convert AG, XG, ARGB, XRGB, AAGG, XXGG, etc.
+ ; nonzero -- convert GA, GX, RGBA, RGBX, GGAA, RRGGBBXX, etc.
+
+
+ ; GA, GX, XG cases
+; if (row_info->channels == 2)
+; {
+; if (row_info->bit_depth == 8)
+; {
+; if (at_start != 0) /* Skip initial filler */
+; ++sp;
+; else /* Skip initial channel and, for sp, the filler */
+; sp += 2, ++dp;
+
+ ; For a 1 pixel wide image there is nothing to do
+; while (sp < ep)
+; *dp++ = *sp, sp += 2;
+
+; row_info->pixel_depth = 8;
+; }
+
+; else if (row_info->bit_depth == 16)
+; {
+; if (at_start != 0) /* Skip initial filler */
+; sp += 2;
+; else /* Skip initial channel and, for sp, the filler */
+; sp += 4, dp += 2;
+
+; while (sp < ep)
+; *dp++ = *sp++, *dp++ = *sp, sp += 3;
+
+; row_info->pixel_depth = 16;
+; }
+
+; else
+; return; /* bad bit depth */
+
+; row_info->channels = 1;
+
+ ; Finally fix the color type if it records an alpha channel
+; if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+; row_info->color_type = PNG_COLOR_TYPE_GRAY;
+; }
+
+ ; RGBA, RGBX, XRGB cases
+; else if (row_info->channels == 4)
+; {
+; if (row_info->bit_depth == 8)
+; {
+; if (at_start != 0) /* Skip initial filler */
+; ++sp;
+; else /* Skip initial channels and, for sp, the filler */
+; sp += 4, dp += 3;
+
+ ; Note that the loop adds 3 to dp and 4 to sp each time.
+; while (sp < ep)
+; *dp++ = *sp++, *dp++ = *sp++, *dp++ = *sp, sp += 2;
+
+; row_info->pixel_depth = 24;
+; }
+
+; else if (row_info->bit_depth == 16)
+; {
+; if (at_start != 0) /* Skip initial filler */
+; sp += 2;
+; else /* Skip initial channels and, for sp, the filler */
+; sp += 8, dp += 6;
+
+; while (sp < ep)
+; {
+; /* Copy 6 bytes, skip 2 */
+; *dp++ = *sp++, *dp++ = *sp++;
+; *dp++ = *sp++, *dp++ = *sp++;
+; *dp++ = *sp++, *dp++ = *sp, sp += 3;
+; }
+
+; row_info->pixel_depth = 48;
+; }
+
+; else
+; return; /* bad bit depth */
+
+; row_info->channels = 3;
+
+ ; Finally fix the color type if it records an alpha channel
+; if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+; row_info->color_type = PNG_COLOR_TYPE_RGB;
+; }
+
+; else
+; return; /* The filler channel has gone already */
+
+ ; Fix the rowbytes value.
+; row_info->rowbytes = dp-row;
+ ret
+endp
+
+; Swaps red and blue bytes within a pixel
+;void (png_row_infop row_info, bytep row)
+align 4
+proc png_do_bgr, row_info:dword, row:dword
+ png_debug 1, 'in png_do_bgr'
+ ;ebx - rp
+ ;ecx - i
+ ;esi - row_width
+pushad
+ mov edi,[row_info]
+ movzx eax,byte[edi+png_row_info.color_type]
+ and eax,PNG_COLOR_MASK_COLOR
+ je .end_f
+ mov esi,[edi+png_row_info.width]
+ cmp byte[edi+png_row_info.bit_depth],8
+ jne .end0
+ cmp byte[edi+png_row_info.color_type],PNG_COLOR_TYPE_RGB
+ jne .end1
+ xor ecx,ecx
+ mov ebx,[row]
+ jmp @f
+align 4
+ .cycle0:
+ inc ecx
+ add ebx,3
+ @@:
+ cmp ecx,esi
+ jae .end_f
+ mov dl,[ebx]
+ mov al,[ebx+2]
+ mov [ebx],al
+ mov [ebx+2],dl
+ jmp .cycle0
+.end1:
+ cmp byte[edi+png_row_info.color_type],PNG_COLOR_TYPE_RGB_ALPHA
+ jne .end_f
+ xor ecx,ecx
+ mov ebx,[row]
+ jmp @f
+align 4
+ .cycle1:
+ inc ecx
+ add ebx,4
+ @@:
+ cmp ecx,esi
+ jae .end_f
+ mov dl,[ebx]
+ mov al,[ebx+2]
+ mov [ebx],al
+ mov [ebx+2],dl
+ jmp .cycle1
+.end0:
+if PNG_16BIT_SUPPORTED eq 1
+ cmp byte[edi+png_row_info.bit_depth],16
+ jne .end_f
+ cmp byte[edi+png_row_info.color_type],PNG_COLOR_TYPE_RGB
+ jne .end2
+ xor ecx,ecx
+ mov ebx,[row]
+ jmp @f
+align 4
+ .cycle2:
+ inc ecx
+ add ebx,6
+ @@:
+ cmp ecx,esi
+ jae .end_f
+ mov dx,[ebx]
+ mov ax,[ebx+4]
+ mov [ebx],ax
+ mov [ebx+4],dx
+ jmp .cycle2
+.end2:
+ cmp byte[edi+png_row_info.color_type],PNG_COLOR_TYPE_RGB_ALPHA
+ jne .end_f
+ xor ecx,ecx
+ mov ebx,[row]
+ jmp @f
+align 4
+ .cycle3:
+ inc ecx
+ add ebx,8
+ @@:
+ cmp ecx,esi
+ jae .end_f
+ mov dx,[ebx]
+ mov ax,[ebx+4]
+ mov [ebx],ax
+ mov [ebx+4],dx
+ jmp .cycle3
+end if
+.end_f:
+popad
+ ret
+endp
+
+; Added at libpng-1.5.10
+;void (png_structrp png_ptr, png_row_infop row_info)
+align 4
+proc png_do_check_palette_indexes, png_ptr:dword, row_info:dword
+; if (png_ptr->num_palette < (1 << row_info->bit_depth) &&
+; png_ptr->num_palette > 0) /* num_palette can be 0 in MNG files */
+; {
+ ; Calculations moved outside switch in an attempt to stop different
+ ; compiler warnings. 'padding' is in *bits* within the last byte, it is
+ ; an 'int' because pixel_depth becomes an 'int' in the expression below,
+ ; and this calculation is used because it avoids warnings that other
+ ; forms produced on either GCC or MSVC.
+
+; int padding = (-row_info->pixel_depth * row_info->width) & 7;
+; bytep rp = png_ptr->row_buf + row_info->rowbytes;
+
+; switch (row_info->bit_depth)
+; {
+; case 1:
+; {
+; /* in this case, all bytes must be 0 so we don't need
+ ; to unpack the pixels except for the rightmost one.
+
+; for (; rp > png_ptr->row_buf; rp--)
+; {
+; if ((*rp >> padding) != 0)
+; png_ptr->num_palette_max = 1;
+; padding = 0;
+; }
+
+; break;
+; }
+
+; case 2:
+; {
+; for (; rp > png_ptr->row_buf; rp--)
+; {
+; int i = ((*rp >> padding) & 0x03);
+
+; if (i > png_ptr->num_palette_max)
+; png_ptr->num_palette_max = i;
+
+; i = (((*rp >> padding) >> 2) & 0x03);
+
+; if (i > png_ptr->num_palette_max)
+; png_ptr->num_palette_max = i;
+
+; i = (((*rp >> padding) >> 4) & 0x03);
+
+; if (i > png_ptr->num_palette_max)
+; png_ptr->num_palette_max = i;
+
+; i = (((*rp >> padding) >> 6) & 0x03);
+
+; if (i > png_ptr->num_palette_max)
+; png_ptr->num_palette_max = i;
+
+; padding = 0;
+; }
+
+; break;
+; }
+
+; case 4:
+; {
+; for (; rp > png_ptr->row_buf; rp--)
+; {
+; int i = ((*rp >> padding) & 0x0f);
+
+; if (i > png_ptr->num_palette_max)
+; png_ptr->num_palette_max = i;
+
+; i = (((*rp >> padding) >> 4) & 0x0f);
+
+; if (i > png_ptr->num_palette_max)
+; png_ptr->num_palette_max = i;
+
+; padding = 0;
+; }
+
+; break;
+; }
+
+; case 8:
+; {
+; for (; rp > png_ptr->row_buf; rp--)
+; {
+; if (*rp > png_ptr->num_palette_max)
+; png_ptr->num_palette_max = (int) *rp;
+; }
+
+; break;
+; }
+
+; default:
+; break;
+; }
+; }
+ ret
+endp
+
+;void (png_structrp png_ptr, voidp user_transform_ptr, int user_transform_depth, int user_transform_channels)
+align 4
+proc png_set_user_transform_info uses eax edi, png_ptr:dword, user_transform_ptr:dword, user_transform_depth:dword, user_transform_channels:dword
+ png_debug 1, 'in png_set_user_transform_info'
+
+ mov edi,[png_ptr]
+ test edi,edi
+ jz .end_f
+
+if PNG_READ_USER_TRANSFORM_SUPPORTED eq 1
+ mov eax,[edi+png_struct.mode]
+ and eax,PNG_IS_READ_STRUCT
+ jz @f
+ mov eax,[edi+png_struct.flags]
+ and eax,PNG_FLAG_ROW_INIT
+ jz @f ;if (..!=0 && ..!=0)
+ cStr ,'info change after png_start_read_image or png_read_update_info'
+ stdcall png_app_error, edi, eax
+ jmp .end_f
+ @@:
+end if
+
+ mov eax,[user_transform_ptr]
+ mov [edi+png_struct.user_transform_ptr],eax
+ mov eax,[user_transform_depth]
+ mov [edi+png_struct.user_transform_depth],al
+ mov eax,[user_transform_channels]
+ mov [edi+png_struct.user_transform_channels],al
+.end_f:
+ ret
+endp
+
+; This function returns a pointer to the user_transform_ptr associated with
+; the user transform functions. The application should free any memory
+; associated with this pointer before png_write_destroy and png_read_destroy
+; are called.
+
+;voidp (png_structrp png_ptr)
+align 4
+proc png_get_user_transform_ptr, png_ptr:dword
+ mov eax,[png_ptr]
+ cmp eax,0
+ je @f
+ mov eax,[eax+png_struct.user_transform_ptr]
+ @@:
+ ret
+endp
+
+;uint_32 (png_structrp png_ptr)
+align 4
+proc png_get_current_row_number, png_ptr:dword
+ ; See the comments in png.inc - this is the sub-image row when reading an
+ ; interlaced image.
+
+ mov eax,[png_ptr]
+ cmp eax,0
+ je @f ;if (..!=0)
+ mov eax,[eax+png_struct.row_number]
+ jmp .end_f
+ @@:
+ mov eax,PNG_UINT_32_MAX ;help the app not to fail silently
+.end_f:
+ ret
+endp
+
+;byte (png_structrp png_ptr)
+align 4
+proc png_get_current_pass_number, png_ptr:dword
+ mov eax,[png_ptr]
+ cmp eax,0
+ je @f ;if (..!=0)
+ mov eax,[eax+png_struct.pass]
+ jmp .end_f
+ @@:
+ mov eax,8 ;invalid
+.end_f:
+ ret
+endp
+end if
diff --git a/programs/develop/libraries/libs-dev/libimg/png/libpng/pngwio.asm b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngwio.asm
index 956e74d69..acd6e3a21 100644
--- a/programs/develop/libraries/libs-dev/libimg/png/libpng/pngwio.asm
+++ b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngwio.asm
@@ -1,165 +1,165 @@
-
-; pngwio.asm - functions for data output
-
-; Last changed in libpng 1.6.24 [August 4, 2016]
-; Copyright (c) 1998-2002,2004,2006-2014,2016 Glenn Randers-Pehrson
-; (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
-; (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
-
-; This code is released under the libpng license.
-; For conditions of distribution and use, see the disclaimer
-; and license in png.inc
-
-; This file provides a location for all output. Users who need
-; special handling are expected to write functions that have the same
-; arguments as these and perform similar functions, but that possibly
-; use different output methods. Note that you shouldn't change these
-; functions, but rather write replacement functions and then change
-; them at run time with png_set_write_fn(...).
-
-
-; Write the data to whatever output you are using. The default routine
-; writes to a file pointer. Note that this routine sometimes gets called
-; with very small lengths, so you should implement some kind of simple
-; buffering if you are using unbuffered writes. This should never be asked
-; to write more than 64K on a 16-bit machine.
-
-;void (png_structrp png_ptr, bytep data, png_size_t length)
-align 4
-proc png_write_data uses edi, png_ptr:dword, p2data:dword, length:dword
- ; NOTE: write_data_fn must not change the buffer!
- mov edi,[png_ptr]
- cmp dword[edi+png_struct.write_data_fn],0
- je @f ;if (..!=0)
- stdcall dword[edi+png_struct.write_data_fn], edi, [p2data], [length]
- jmp .end_f
- @@: ;else
- png_error edi, 'Call to NULL write function'
- .end_f:
- ret
-endp
-
-; This is the function that does the actual writing of data. If you are
-; not writing to a standard C stream, you should create a replacement
-; write_data function and use it at run time with png_set_write_fn(), rather
-; than changing the library.
-
-;void (png_structp png_ptr, bytep data, png_size_t length)
-align 4
-proc png_default_write_data uses eax edi, png_ptr:dword, p2data:dword, length:dword
-; png_size_t check;
-
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f ;if (..==0) return
-
-; check = fwrite(p2data, 1, length, (png_FILE_p)(png_ptr->io_ptr));
-
-; if (check != length)
-; png_error(png_ptr, "Write Error");
-.end_f:
- ret
-endp
-
-; This function is called to output any data pending writing (normally
-; to disk). After png_flush is called, there should be no data pending
-; writing in any buffers.
-
-;void (png_structrp png_ptr)
-align 4
-proc png_flush uses edi, png_ptr:dword
- mov edi,[png_ptr]
- cmp dword[edi+png_struct.output_flush_fn],0
- je @f ;if (..!=..)
- stdcall dword[edi+png_struct.output_flush_fn],edi
- @@:
- ret
-endp
-
-;void (png_structp png_ptr)
-align 4
-proc png_default_flush uses eax edi, png_ptr:dword
- mov edi,[png_ptr]
- cmp edi,0
- je @f ;if (..==0) return
-;;; stdcall fflush, [edi+png_struct.io_ptr]
- @@:
- ret
-endp
-
-; This function allows the application to supply new output functions for
-; libpng if standard C streams aren't being used.
-
-; This function takes as its arguments:
-; png_ptr - pointer to a png output data structure
-; io_ptr - pointer to user supplied structure containing info about
-; the output functions. May be NULL.
-; write_data_fn - pointer to a new output function that takes as its
-; arguments a pointer to a png_struct, a pointer to
-; data to be written, and a 32-bit unsigned int that is
-; the number of bytes to be written. The new write
-; function should call png_error(png_ptr, "Error msg")
-; to exit and output any fatal error messages. May be
-; NULL, in which case libpng's default function will
-; be used.
-; flush_data_fn - pointer to a new flush function that takes as its
-; arguments a pointer to a png_struct. After a call to
-; the flush function, there should be no data in any buffers
-; or pending transmission. If the output method doesn't do
-; any buffering of output, a function prototype must still be
-; supplied although it doesn't have to do anything. If
-; PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile
-; time, output_flush_fn will be ignored, although it must be
-; supplied for compatibility. May be NULL, in which case
-; libpng's default function will be used, if
-; PNG_WRITE_FLUSH_SUPPORTED is defined. This is not
-; a good idea if io_ptr does not point to a standard
-; *FILE structure.
-
-;void (png_structrp png_ptr, voidp io_ptr,
-; png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)
-align 4
-proc png_set_write_fn uses eax edi, png_ptr:dword, io_ptr:dword, write_data_fn:dword, output_flush_fn:dword
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f ;if (..==0) return
-
- mov eax,[io_ptr]
- mov [edi+png_struct.io_ptr],eax
-
-if PNG_STDIO_SUPPORTED eq 1
- mov eax,png_default_write_data ;else
- cmp dword[write_data_fn],0
- je @f ;if (..!=0)
- mov eax,[write_data_fn]
- @@:
-else
- mov eax,[write_data_fn]
-end if
- mov [edi+png_struct.write_data_fn],eax
-
-if PNG_WRITE_FLUSH_SUPPORTED eq 1
- if PNG_STDIO_SUPPORTED eq 1
- mov eax,[png_default_flush] ;else
- cmp dword[output_flush_fn],0
- je @f ;if (..!=0)
- mov eax,[output_flush_fn]
- @@:
- else
- mov eax,[output_flush_fn]
- end if
- mov [edi+png_struct.output_flush_fn],eax
-end if ;WRITE_FLUSH
-
-if PNG_READ_SUPPORTED eq 1
- ; It is an error to read while writing a png file
- cmp dword[edi+png_struct.read_data_fn],0
- je @f ;if (..!=0)
- mov dword[edi+png_struct.read_data_fn], 0
-
- png_warning edi, <'Can',39,'t set both read_data_fn and write_data_fn in the same structure'>
- @@:
-end if
-.end_f:
- ret
-endp
+
+; pngwio.asm - functions for data output
+
+; Last changed in libpng 1.6.24 [August 4, 2016]
+; Copyright (c) 1998-2002,2004,2006-2014,2016 Glenn Randers-Pehrson
+; (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+; (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+
+; This code is released under the libpng license.
+; For conditions of distribution and use, see the disclaimer
+; and license in png.inc
+
+; This file provides a location for all output. Users who need
+; special handling are expected to write functions that have the same
+; arguments as these and perform similar functions, but that possibly
+; use different output methods. Note that you shouldn't change these
+; functions, but rather write replacement functions and then change
+; them at run time with png_set_write_fn(...).
+
+
+; Write the data to whatever output you are using. The default routine
+; writes to a file pointer. Note that this routine sometimes gets called
+; with very small lengths, so you should implement some kind of simple
+; buffering if you are using unbuffered writes. This should never be asked
+; to write more than 64K on a 16-bit machine.
+
+;void (png_structrp png_ptr, bytep data, png_size_t length)
+align 4
+proc png_write_data uses edi, png_ptr:dword, p2data:dword, length:dword
+ ; NOTE: write_data_fn must not change the buffer!
+ mov edi,[png_ptr]
+ cmp dword[edi+png_struct.write_data_fn],0
+ je @f ;if (..!=0)
+ stdcall dword[edi+png_struct.write_data_fn], edi, [p2data], [length]
+ jmp .end_f
+ @@: ;else
+ png_error edi, 'Call to NULL write function'
+ .end_f:
+ ret
+endp
+
+; This is the function that does the actual writing of data. If you are
+; not writing to a standard C stream, you should create a replacement
+; write_data function and use it at run time with png_set_write_fn(), rather
+; than changing the library.
+
+;void (png_structp png_ptr, bytep data, png_size_t length)
+align 4
+proc png_default_write_data uses eax edi, png_ptr:dword, p2data:dword, length:dword
+; png_size_t check;
+
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f ;if (..==0) return
+
+; check = fwrite(p2data, 1, length, (png_FILE_p)(png_ptr->io_ptr));
+
+; if (check != length)
+; png_error(png_ptr, "Write Error");
+.end_f:
+ ret
+endp
+
+; This function is called to output any data pending writing (normally
+; to disk). After png_flush is called, there should be no data pending
+; writing in any buffers.
+
+;void (png_structrp png_ptr)
+align 4
+proc png_flush uses edi, png_ptr:dword
+ mov edi,[png_ptr]
+ cmp dword[edi+png_struct.output_flush_fn],0
+ je @f ;if (..!=..)
+ stdcall dword[edi+png_struct.output_flush_fn],edi
+ @@:
+ ret
+endp
+
+;void (png_structp png_ptr)
+align 4
+proc png_default_flush uses eax edi, png_ptr:dword
+ mov edi,[png_ptr]
+ cmp edi,0
+ je @f ;if (..==0) return
+;;; stdcall fflush, [edi+png_struct.io_ptr]
+ @@:
+ ret
+endp
+
+; This function allows the application to supply new output functions for
+; libpng if standard C streams aren't being used.
+
+; This function takes as its arguments:
+; png_ptr - pointer to a png output data structure
+; io_ptr - pointer to user supplied structure containing info about
+; the output functions. May be NULL.
+; write_data_fn - pointer to a new output function that takes as its
+; arguments a pointer to a png_struct, a pointer to
+; data to be written, and a 32-bit unsigned int that is
+; the number of bytes to be written. The new write
+; function should call png_error(png_ptr, "Error msg")
+; to exit and output any fatal error messages. May be
+; NULL, in which case libpng's default function will
+; be used.
+; flush_data_fn - pointer to a new flush function that takes as its
+; arguments a pointer to a png_struct. After a call to
+; the flush function, there should be no data in any buffers
+; or pending transmission. If the output method doesn't do
+; any buffering of output, a function prototype must still be
+; supplied although it doesn't have to do anything. If
+; PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile
+; time, output_flush_fn will be ignored, although it must be
+; supplied for compatibility. May be NULL, in which case
+; libpng's default function will be used, if
+; PNG_WRITE_FLUSH_SUPPORTED is defined. This is not
+; a good idea if io_ptr does not point to a standard
+; *FILE structure.
+
+;void (png_structrp png_ptr, voidp io_ptr,
+; png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)
+align 4
+proc png_set_write_fn uses eax edi, png_ptr:dword, io_ptr:dword, write_data_fn:dword, output_flush_fn:dword
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f ;if (..==0) return
+
+ mov eax,[io_ptr]
+ mov [edi+png_struct.io_ptr],eax
+
+if PNG_STDIO_SUPPORTED eq 1
+ mov eax,png_default_write_data ;else
+ cmp dword[write_data_fn],0
+ je @f ;if (..!=0)
+ mov eax,[write_data_fn]
+ @@:
+else
+ mov eax,[write_data_fn]
+end if
+ mov [edi+png_struct.write_data_fn],eax
+
+if PNG_WRITE_FLUSH_SUPPORTED eq 1
+ if PNG_STDIO_SUPPORTED eq 1
+ mov eax,[png_default_flush] ;else
+ cmp dword[output_flush_fn],0
+ je @f ;if (..!=0)
+ mov eax,[output_flush_fn]
+ @@:
+ else
+ mov eax,[output_flush_fn]
+ end if
+ mov [edi+png_struct.output_flush_fn],eax
+end if ;WRITE_FLUSH
+
+if PNG_READ_SUPPORTED eq 1
+ ; It is an error to read while writing a png file
+ cmp dword[edi+png_struct.read_data_fn],0
+ je @f ;if (..!=0)
+ mov dword[edi+png_struct.read_data_fn], 0
+
+ png_warning edi, <'Can',39,'t set both read_data_fn and write_data_fn in the same structure'>
+ @@:
+end if
+.end_f:
+ ret
+endp
diff --git a/programs/develop/libraries/libs-dev/libimg/png/libpng/pngwrite.asm b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngwrite.asm
index 3f1fc8f68..016fab235 100644
--- a/programs/develop/libraries/libs-dev/libimg/png/libpng/pngwrite.asm
+++ b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngwrite.asm
@@ -1,3297 +1,3297 @@
-
-; pngwrite.asm - general routines to write a PNG file
-
-; Last changed in libpng 1.6.24 [August 4, 2016]
-; Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
-; (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
-; (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
-
-; This code is released under the libpng license.
-; For conditions of distribution and use, see the disclaimer
-; and license in png.inc
-
-; Write out all the unknown chunks for the current given location
-;void (png_structrp png_ptr, png_const_inforp info_ptr, unsigned int where)
-align 4
-proc write_unknown_chunks, png_ptr:dword, info_ptr:dword, where:dword
-pushad
- mov esi,[info_ptr]
- cmp dword[esi+png_info_def.unknown_chunks_num],0
- je .end_f ;if(..!=0)
- mov edi,[png_ptr]
- ;ecx = up
-
- png_debug 5, 'writing extra chunks'
-
- mov ecx,[esi+png_info_def.unknown_chunks]
- mov edx,[esi+png_info_def.unknown_chunks_num]
- imul edx,sizeof.png_unknown_chunk
- add edx,ecx
- .cycle0: ;for (..;..<..;..)
- cmp ecx,edx
- jge .end_f
- movzx eax,byte[ecx+png_unknown_chunk.location]
- and eax,[where]
- jz .end0 ;if (..!=0)
- ; If per-chunk unknown chunk handling is enabled use it, otherwise
- ; just write the chunks the application has set.
-
-if PNG_SET_UNKNOWN_CHUNKS_SUPPORTED eq 1
- mov eax,ecx
- add eax,png_unknown_chunk.name
- stdcall png_handle_as_unknown, edi, eax
-
- ; NOTE: this code is radically different from the read side in the
- ; matter of handling an ancillary unknown chunk. In the read side
- ; the default behavior is to discard it, in the code below the default
- ; behavior is to write it. Critical chunks are, however, only
- ; written if explicitly listed or if the default is set to write all
- ; unknown chunks.
-
- ; The default handling is also slightly weird - it is not possible to
- ; stop the writing of all unsafe-to-copy chunks!
-
- ; TODO: REVIEW: this would seem to be a bug.
-
- cmp eax,PNG_HANDLE_CHUNK_NEVER
- je .end0
- mov bl,byte[ecx+png_unknown_chunk.name+3]
- and bl,0x20
- cmp bl,0
- jne .beg0
- cmp eax,PNG_HANDLE_CHUNK_ALWAYS
- je .beg0
- cmp eax,PNG_HANDLE_CHUNK_AS_DEFAULT
- jne .end0
- cmp dword[edi+png_struct.unknown_default],PNG_HANDLE_CHUNK_ALWAYS
- jne .end0
-end if
- .beg0: ;if (..!=.. && (.. safe-to-copy overrides everything || ..==.. || (..==.. && ..==..)))
- ; TODO: review, what is wrong with a zero length unknown chunk?
- cmp dword[ecx+png_unknown_chunk.size],0
- jne @f ;if (..==0)
- png_warning [png_ptr], 'Writing zero-length unknown chunk'
- @@:
- mov eax,dword[ecx+png_unknown_chunk.name]
- stdcall png_write_chunk, edi, eax, [ecx+png_unknown_chunk.podata], [ecx+png_unknown_chunk.size]
- .end0:
- add ecx,sizeof.png_unknown_chunk
- jmp .cycle0
- ;.cycle0end:
-.end_f:
-popad
- ret
-endp
-
-; Writes all the PNG information. This is the suggested way to use the
-; library. If you have a new chunk to add, make a function to write it,
-; and put it in the correct location here. If you want the chunk written
-; after the image data, put it in png_write_end(). I strongly encourage
-; you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing
-; the chunk, as that will keep the code from breaking if you want to just
-; write a plain PNG file. If you have long comments, I suggest writing
-; them in png_write_end(), and compressing them.
-
-;void (png_structrp png_ptr, png_const_inforp info_ptr)
-align 4
-proc png_write_info_before_PLTE, png_ptr:dword, info_ptr:dword
- png_debug 1, 'in png_write_info_before_PLTE'
-
-pushad
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f
- mov esi,[info_ptr]
- cmp esi,0
- je .end_f ;if(..==0 || ..==0) return
-
- mov eax,[edi+png_struct.mode]
- and eax,PNG_WROTE_INFO_BEFORE_PLTE
- jnz .end_f ;if (..==0)
-
- ; Write PNG signature
- stdcall png_write_sig, edi
-
-if PNG_MNG_FEATURES_SUPPORTED eq 1
- mov eax,[edi+png_struct.mode]
- and eax,PNG_HAVE_PNG_SIGNATURE
- jz @f
- cmp dword[edi+png_struct.mng_features_permitted],0
- je @f ;if(..!=0 && ..!=0)
- png_warning edi, 'MNG features are not allowed in a PNG datastream'
- mov dword[edi+png_struct.mng_features_permitted],0
- @@:
-end if
-
- ; Write IHDR information.
-if PNG_WRITE_INTERLACING_SUPPORTED eq 1
- movzx eax,byte[esi+png_info_def.interlace_type]
- push eax
-else
- push dword 0
-end if
- movzx eax,byte[esi+png_info_def.filter_type]
- push eax
- movzx eax,byte[esi+png_info_def.compression_type]
- push eax
- movzx eax,byte[esi+png_info_def.color_type]
- push eax
- movzx eax,byte[esi+png_info_def.bit_depth]
- stdcall png_write_IHDR, edi,\
- dword[esi+png_info_def.width], dword[esi+png_info_def.height], eax
-
-; The rest of these check to see if the valid field has the appropriate
-; flag set, and if it does, writes the chunk.
-
-; 1.6.0: COLORSPACE support controls the writing of these chunks too, and
-; the chunks will be written if the WRITE routine is there and
-; information * is available in the COLORSPACE. (See
-; png_colorspace_sync_info in png.c for where the valid flags get set.)
-
-; Under certain circumstances the colorspace can be invalidated without
-; syncing the info_struct 'valid' flags; this happens if libpng detects
-; an error and calls png_error while the color space is being set, yet
-; the application continues writing the PNG. So check the 'invalid'
-; flag here too.
-
-if PNG_GAMMA_SUPPORTED eq 1
-if PNG_WRITE_gAMA_SUPPORTED eq 1
- movzx eax,word[esi+png_info_def.colorspace.flags]
- and eax,PNG_COLORSPACE_INVALID
- jnz @f
- movzx eax,word[esi+png_info_def.colorspace.flags]
- and eax,PNG_COLORSPACE_FROM_gAMA
- jz @f
- mov eax,[esi+png_info_def.valid]
- and eax,PNG_INFO_gAMA
- jz @f ;if (..==0 && ..!=0 && ..!=0)
- stdcall png_write_gAMA_fixed, edi, [esi+png_info_def.colorspace.gamma]
- @@:
-end if
-end if
-
-if PNG_COLORSPACE_SUPPORTED eq 1
- ; Write only one of sRGB or an ICC profile. If a profile was supplied
- ; and it matches one of the known sRGB ones issue a warning.
-
-if PNG_WRITE_iCCP_SUPPORTED eq 1
- movzx eax,word[esi+png_info_def.colorspace.flags]
- and eax,PNG_COLORSPACE_INVALID
- jnz .end0
- mov eax,[esi+png_info_def.valid]
- and eax,PNG_INFO_iCCP
- jz .end0 ;if (..==0 && ..!=0)
-if PNG_WRITE_sRGB_SUPPORTED eq 1
- mov eax,[esi+png_info_def.valid]
- and eax,PNG_INFO_sRGB
- jz @f ;if (..!=0)
- png_app_warning edi, 'profile matches sRGB but writing iCCP instead'
- @@:
-end if
- stdcall png_write_iCCP, edi, [esi+png_info_def.iccp_name],\
- [esi+png_info_def.iccp_profile]
-if PNG_WRITE_sRGB_SUPPORTED eq 1
- jmp .end1
-end if
- .end0: ;else
-end if
-
-if PNG_WRITE_sRGB_SUPPORTED eq 1
- movzx eax,word[esi+png_info_def.colorspace.flags]
- and eax,PNG_COLORSPACE_INVALID
- jnz .end1
- mov eax,[esi+png_info_def.valid]
- and eax,PNG_INFO_sRGB
- jz .end1 ;if (..==0 && ..!=0)
- movzx eax,word[esi+png_info_def.colorspace.rendering_intent]
- stdcall png_write_sRGB, edi, eax
- .end1:
-end if ;sRGB
-end if ;COLORSPACE
-
-if PNG_WRITE_sBIT_SUPPORTED eq 1
- mov eax,[esi+png_info_def.valid]
- and eax,PNG_INFO_sBIT
- jz @f ;if (..!=0)
- movzx eax,byte[esi+png_info_def.color_type]
- push eax
- mov eax,esi
- add eax,png_info_def.sig_bit
- stdcall png_write_sBIT, edi, eax ;, ...color_type
- @@:
-end if
-
-if PNG_COLORSPACE_SUPPORTED eq 1
-if PNG_WRITE_cHRM_SUPPORTED eq 1
- movzx eax,word[esi+png_info_def.colorspace.flags]
- and eax,PNG_COLORSPACE_INVALID
- jnz @f
- movzx eax,word[esi+png_info_def.colorspace.flags]
- and eax,PNG_COLORSPACE_FROM_cHRM
- jz @f
- mov eax,[esi+png_info_def.valid]
- and eax,PNG_INFO_cHRM
- jz @f ;if (..==0 && ..!=0 && ..!=0)
- stdcall png_write_cHRM_fixed, edi, [esi+png_info_def.colorspace.end_points_xy]
- @@:
-end if
-end if
-
-if PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED eq 1
- stdcall write_unknown_chunks, edi, esi, PNG_HAVE_IHDR
-end if
- or dword[edi+png_struct.mode],PNG_WROTE_INFO_BEFORE_PLTE
- .end_f:
-popad
- ret
-endp
-
-;void (png_structrp png_ptr, png_const_inforp info_ptr)
-align 4
-proc png_write_info, png_ptr:dword, info_ptr:dword
-if (PNG_WRITE_TEXT_SUPPORTED eq 1) | (PNG_WRITE_sPLT_SUPPORTED eq 1)
-; int i;
-end if
-pushad
- png_debug 1, 'in png_write_info'
-
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f
- mov esi,[info_ptr]
- cmp esi,0
- je .end_f ;if (..==0 || ..==0) return
-
- stdcall png_write_info_before_PLTE, edi, esi
-
- mov eax,[esi+png_info_def.valid]
- and eax,PNG_INFO_PLTE
- jz @f ;if (..!=0)
- movzx eax,word[esi+png_info_def.num_palette]
- stdcall png_write_PLTE, edi, [esi+png_info_def.palette], eax
- jmp .end_0
- @@:
- mov al,byte[esi+png_info_def.color_type]
- cmp al,PNG_COLOR_TYPE_PALETTE
- jne .end_0 ;else if (..==..)
- png_error edi, 'Valid palette required for paletted images'
- .end_0:
-
-if PNG_WRITE_tRNS_SUPPORTED eq 1
- mov eax,[esi+png_info_def.valid]
- and eax,PNG_INFO_tRNS
- jz .end_1 ;if (..!=0)
-if PNG_WRITE_INVERT_ALPHA_SUPPORTED eq 1
- ; Invert the alpha channel (in tRNS)
-; if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0 &&
-; info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
-; {
-; int j, jend;
-
-; jend = info_ptr->num_trans;
-; if (jend > PNG_MAX_PALETTE_LENGTH)
-; jend = PNG_MAX_PALETTE_LENGTH;
-
-; for (j = 0; jtrans_alpha[j] =
-; (byte)(255 - info_ptr->trans_alpha[j]);
-; }
-end if
- mov eax,esi
- add eax,png_info_def.trans_color
- movzx ebx,word[esi+png_info_def.num_trans]
- movzx ecx,byte[esi+png_info_def.color_type]
- stdcall png_write_tRNS, edi, dword[esi+png_info_def.trans_alpha], eax, ebx, ecx
- .end_1:
-end if
-if PNG_WRITE_bKGD_SUPPORTED eq 1
- mov eax,[esi+png_info_def.valid]
- and eax,PNG_INFO_bKGD
- jz @f ;if (..!=0)
- mov eax,esi
- add eax,png_info_def.background
- movzx ebx,byte[esi+png_info_def.color_type]
- stdcall png_write_bKGD, edi, eax, ebx
- @@:
-end if
-
-if PNG_WRITE_hIST_SUPPORTED eq 1
- mov eax,[esi+png_info_def.valid]
- and eax,PNG_INFO_hIST
- jz @f ;if (..!=0)
- movzx ebx,word[esi+png_info_def.num_palette]
- stdcall png_write_hIST, edi, [esi+png_info_def.hist], ebx
- @@:
-end if
-
-if PNG_WRITE_oFFs_SUPPORTED eq 1
- mov eax,[esi+png_info_def.valid]
- and eax,PNG_INFO_oFFs
- jz @f ;if (..!=0)
- movzx ebx,byte[esi+png_info_def.offset_unit_type]
- stdcall png_write_oFFs, edi, [esi+png_info_def.x_offset], [esi+png_info_def.y_offset], ebx
- @@:
-end if
-
-if PNG_WRITE_pCAL_SUPPORTED eq 1
- mov eax,[esi+png_info_def.valid]
- and eax,PNG_INFO_pCAL
- jz @f ;if (..!=0)
- movzx ebx,byte[esi+png_info_def.pcal_type]
- movzx ecx,byte[esi+png_info_def.pcal_nparams]
- stdcall png_write_pCAL, edi, [esi+png_info_def.pcal_purpose], [esi+png_info_def.pcal_X0], [esi+png_info_def.pcal_X1], ebx, ecx, [esi+png_info_def.pcal_units], [esi+png_info_def.pcal_params]
- @@:
-end if
-
-if PNG_WRITE_sCAL_SUPPORTED eq 1
- mov eax,[esi+png_info_def.valid]
- and eax,PNG_INFO_sCAL
- jz @f ;if (..!=0)
- movzx ebx,byte[esi+png_info_def.scal_unit]
- stdcall png_write_sCAL_s, edi, ebx, [esi+png_info_def.scal_s_width], [esi+png_info_def.scal_s_height]
- @@:
-end if ;sCAL
-
-if PNG_WRITE_pHYs_SUPPORTED eq 1
- mov eax,[esi+png_info_def.valid]
- and eax,PNG_INFO_pHYs
- jz @f ;if (..!=0)
- movzx ebx,byte[esi+png_info_def.phys_unit_type]
- stdcall png_write_pHYs, edi, [esi+png_info_def.x_pixels_per_unit], [esi+png_info_def.y_pixels_per_unit], ebx
- @@:
-end if ;pHYs
-
-if PNG_WRITE_tIME_SUPPORTED eq 1
- mov eax,[esi+png_info_def.valid]
- and eax,PNG_INFO_tIME
- jz @f ;if (..!=0)
- mov eax,esi
- add eax,png_info_def.mod_time
- stdcall png_write_tIME, edi, eax
- or [edi+png_struct.mode],PNG_WROTE_tIME
- @@:
-end if ;tIME
-
-if PNG_WRITE_sPLT_SUPPORTED eq 1
- mov eax,[esi+png_info_def.valid]
- and eax,PNG_INFO_sPLT
- jz @f ;if (..!=0)
- mov eax,[esi+png_info_def.splt_palettes]
- mov ecx,[esi+png_info_def.splt_palettes_num]
- cmp ecx,1
- jl @f
- .cycle0:
- stdcall png_write_sPLT, edi, eax
- add eax,4
- loop .cycle0
- @@:
-end if ;sPLT
-
-if PNG_WRITE_TEXT_SUPPORTED eq 1
- ; Check to see if we need to write text chunks
-; for (i = 0; i < info_ptr->num_text; i++)
-; {
-; png_debug2(2, "Writing header text chunk %d, type %d", i,
-; info_ptr->text[i].compression);
- ; An internationalized chunk?
-; if (info_ptr->text[i].compression > 0)
-; {
-if PNG_WRITE_iTXt_SUPPORTED eq 1
- ; Write international chunk
-; png_write_iTXt(png_ptr,
-; info_ptr->text[i].compression,
-; info_ptr->text[i].key,
-; info_ptr->text[i].lang,
-; info_ptr->text[i].lang_key,
-; info_ptr->text[i].text);
- ; Mark this chunk as written
-; if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
-; info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
-; else
-; info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
-else
- png_warning edi, 'Unable to write international text'
-end if
-; }
-
- ; If we want a compressed text chunk
-; else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt)
-; {
-if PNG_WRITE_zTXt_SUPPORTED eq 1
- ; Write compressed chunk
-; png_write_zTXt(png_ptr, info_ptr->text[i].key,
-; info_ptr->text[i].text, info_ptr->text[i].compression);
- ; Mark this chunk as written
-; info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
-else
- png_warning edi, 'Unable to write compressed text'
-end if
-; }
-
-; else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
-; {
-if PNG_WRITE_tEXt_SUPPORTED eq 1
- ; Write uncompressed chunk
-; png_write_tEXt(png_ptr, info_ptr->text[i].key,
-; info_ptr->text[i].text,
-; 0);
- ; Mark this chunk as written
-; info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
-else
- ; Can't get here
- png_warning edi, 'Unable to write uncompressed text'
-end if
-; }
-; }
-end if ;tEXt
-
-if PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED eq 1
- stdcall write_unknown_chunks, edi, esi, PNG_HAVE_PLTE
-end if
- .end_f:
-popad
- ret
-endp
-
-; Writes the end of the PNG file. If you don't want to write comments or
-; time information, you can pass NULL for info. If you already wrote these
-; in png_write_info(), do not write them again here. If you have long
-; comments, I suggest writing them here, and compressing them.
-
-;void (png_structrp png_ptr, png_inforp info_ptr)
-align 4
-proc png_write_end, png_ptr:dword, info_ptr:dword
-pushad
- png_debug 1, 'in png_write_end'
-
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f ;if (..==0) return
-
- mov eax,[edi+png_struct.mode]
- and eax,PNG_HAVE_IDAT
- jnz @f ;if (..==0)
- png_error edi, 'No IDATs written into file'
- @@:
-
-if PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED eq 1
- mov eax,[edi+png_struct.num_palette_max]
- cmp ax,[edi+png_struct.num_palette]
- jle @f ;if (..>..)
- png_benign_error edi, 'Wrote palette index exceeding num_palette'
- @@:
-end if
-
- ; See if user wants us to write information chunks
- mov esi,[info_ptr]
- cmp esi,0
- je .end0 ;if (..!=0)
-if PNG_WRITE_TEXT_SUPPORTED eq 1
-; int i; /* local index variable */
-end if
-if PNG_WRITE_tIME_SUPPORTED eq 1
- ; Check to see if user has supplied a time chunk
- mov eax,[esi+png_info_def.valid]
- and eax,PNG_INFO_tIME
- jz @f
- mov eax,[edi+png_struct.mode]
- and eax,PNG_WROTE_tIME
- jnz @f ;if (..!=0 && ..==0)
- mov eax,esi
- add eax,png_info_def.mod_time
- stdcall png_write_tIME, edi, eax
- @@:
-
-end if
-if PNG_WRITE_TEXT_SUPPORTED eq 1
- ; Loop through comment chunks
- cmp dword[esi+png_info_def.num_text],0
- jle .cycle0end
- xor ecx,ecx
-align 4
- .cycle0: ;for (i = 0; i < info_ptr->num_text; i++)
-
-; png_debug2(2, "Writing trailer text chunk %d, type %d", i,
-; info_ptr->text[i].compression);
- ; An internationalized chunk?
- mov eax,ecx
- shl eax,2
- add eax,[esi+png_info_def.text] ;eax = info_ptr.text[i]
- cmp dword[eax+png_text.compression],0
- jle .end1 ;if (info_ptr.text[i].compression > 0)
-if PNG_WRITE_iTXt_SUPPORTED eq 1
- ; Write international chunk
- stdcall png_write_iTXt, edi,\
- [eax+png_text.compression],\
- [eax+png_text.key],\
- [eax+png_text.lang],\
- [eax+png_text.lang_key],\
- [eax+png_text.text]
- ; Mark this chunk as written
- mov ebx,PNG_TEXT_COMPRESSION_zTXt_WR
- cmp dword[eax+png_text.compression],PNG_TEXT_COMPRESSION_NONE
- jne @f
- mov ebx,PNG_TEXT_COMPRESSION_NONE_WR
- @@:
- mov dword[eax+png_text.compression],ebx
-else
- png_warning edi, 'Unable to write international text'
-end if
- jmp .end3
- .end1:
- cmp dword[eax+png_text.compression],PNG_TEXT_COMPRESSION_zTXt
- jl .end2 ;else if (info_ptr.text[i].compression >= ..)
-if PNG_WRITE_zTXt_SUPPORTED eq 1
- ; Write compressed chunk
- stdcall png_write_zTXt, edi, [eax+png_text.key],\
- [eax+png_text.text], [eax+png_text.compression]
- ; Mark this chunk as written
- mov dword[eax+png_text.compression],PNG_TEXT_COMPRESSION_zTXt_WR
-else
- png_warning edi, 'Unable to write compressed text'
-end if
- jmp .end3
- .end2:
- cmp dword[eax+png_text.compression],PNG_TEXT_COMPRESSION_NONE
- jl .end3 ;else if (info_ptr.text[i].compression == ..)
-if PNG_WRITE_tEXt_SUPPORTED eq 1
- ; Write uncompressed chunk
- stdcall png_write_tEXt, edi, [eax+png_text.key],\
- [eax+png_text.text], 0
- ; Mark this chunk as written
- mov dword[eax+png_text.compression],PNG_TEXT_COMPRESSION_NONE_WR
-else
- png_warning edi, 'Unable to write uncompressed text'
-end if
- .end3:
-
- inc ecx
- cmp ecx,[esi+png_info_def.num_text]
- jl .cycle0
- .cycle0end:
-end if
-if PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED eq 1
- stdcall write_unknown_chunks, edi, esi, PNG_AFTER_IDAT
-end if
- .end0:
-
- or dword[edi+png_struct.mode], PNG_AFTER_IDAT
-
- ; Write end of PNG file
- stdcall png_write_IEND, edi
-
-; This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03,
-; and restored again in libpng-1.2.30, may cause some applications that
-; do not set png_ptr->output_flush_fn to crash. If your application
-; experiences a problem, please try building libpng with
-; PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED defined, and report the event to
-; png-mng-implement at lists.sf.net .
-
-if PNG_WRITE_FLUSH_SUPPORTED eq 1
-if PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED eq 1
- stdcall png_flush, edi
-end if
-end if
-.end_f:
-popad
- ret
-endp
-
-;void (png_timep ptime, struct tm * ttime)
-align 4
-proc png_convert_from_struct_tm, ptime:dword, ttime:dword
- png_debug 1, 'in png_convert_from_struct_tm'
-
-; ptime->year = (uint_16)(1900 + ttime->tm_year);
-; ptime->month = (byte)(ttime->tm_mon + 1);
-; ptime->day = (byte)ttime->tm_mday;
-; ptime->hour = (byte)ttime->tm_hour;
-; ptime->minute = (byte)ttime->tm_min;
-; ptime->second = (byte)ttime->tm_sec;
- ret
-endp
-
-;void (png_timep ptime, time_t ttime)
-align 4
-proc png_convert_from_time_t, ptime:dword, ttime:dword
-; struct tm *tbuf;
-
- png_debug 1, 'in png_convert_from_time_t'
-
-; tbuf = gmtime(&ttime);
-; png_convert_from_struct_tm(ptime, tbuf);
- ret
-endp
-
-; Initialize png_ptr structure, and allocate any memory needed
-;png_structp (charp user_png_ver, voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn)
-align 4
-proc png_create_write_struct, user_png_ver:dword, error_ptr:dword, error_fn:dword, warn_fn:dword
-if PNG_USER_MEM_SUPPORTED eq 1
- stdcall png_create_png_struct, [user_png_ver], [error_ptr], [error_fn], [warn_fn], 0, 0, 0
- ;eax = png_ptr
-end if ;USER_MEM
- test eax,eax
- jz .end0 ;if (..!=0)
- ; Set the zlib control values to defaults; they can be overridden by the
- ; application after the struct has been created.
-
- mov dword[eax+png_struct.zbuffer_size], PNG_ZBUF_SIZE
-
- ; The 'zlib_strategy' setting is irrelevant because png_default_claim in
- ; pngwutil.asm defaults it according to whether or not filters will be
- ; used, and ignores this setting.
-
- mov dword[eax+png_struct.zlib_strategy], PNG_Z_DEFAULT_STRATEGY
- mov dword[eax+png_struct.zlib_level], PNG_Z_DEFAULT_COMPRESSION
- mov dword[eax+png_struct.zlib_mem_level], 8
- mov dword[eax+png_struct.zlib_window_bits], 15
- mov dword[eax+png_struct.zlib_method], 8
-
-if PNG_WRITE_COMPRESSED_TEXT_SUPPORTED eq 1
- mov dword[eax+png_struct.zlib_text_strategy], PNG_TEXT_Z_DEFAULT_STRATEGY
- mov dword[eax+png_struct.zlib_text_level], PNG_TEXT_Z_DEFAULT_COMPRESSION
- mov dword[eax+png_struct.zlib_text_mem_level], 8
- mov dword[eax+png_struct.zlib_text_window_bits], 15
- mov dword[eax+png_struct.zlib_text_method], 8
-end if
- ; This is a highly dubious configuration option; by default it is off,
- ; but it may be appropriate for private builds that are testing
- ; extensions not conformant to the current specification, or of
- ; applications that must not fail to write at all costs!
-
-if PNG_BENIGN_WRITE_ERRORS_SUPPORTED eq 1
- ; In stable builds only warn if an application error can be completely
- ; handled.
-
- or dword[eax+png_struct.flags], PNG_FLAG_BENIGN_ERRORS_WARN
-end if
- ; App warnings are warnings in release (or release candidate) builds but
- ; are errors during development.
-
-if PNG_RELEASE_BUILD eq 1
- or dword[eax+png_struct.flags], PNG_FLAG_APP_WARNINGS_WARN
-end if
- ; TODO: delay this, it can be done in png_init_io() (if the app doesn't
- ; do it itself) avoiding setting the default function if it is not
- ; required.
-
- stdcall png_set_write_fn, eax, 0, 0, 0
- .end0:
- ret
-endp
-
-
-; Write a few rows of image data. If the image is interlaced,
-; either you will have to write the 7 sub images, or, if you
-; have called png_set_interlace_handling(), you will have to
-; "write" the image seven times.
-
-;void (png_structrp png_ptr, bytepp row, uint_32 num_rows)
-align 4
-proc png_write_rows uses ebx ecx edi, png_ptr:dword, row:dword, num_rows:dword
-;locals
- ;i dd ? ;uint_32 ;row counter
- ;rp dd ? ;bytepp ;row pointer
-;endl
- png_debug 1, 'in png_write_rows'
-
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f ;if(..==0) return
-
- ; Loop through the rows
- mov ecx,[num_rows]
- cmp ecx,1
- jl .end_f
- mov ebx,[row]
- @@: ;for (i = 0, rp = row; i < num_rows; i++, rp++)
- stdcall png_write_row, edi, [ebx]
- add ebx,4
- loop @b
-.end_f:
- ret
-endp
-
-; Write the image. You only need to call this function once, even
-; if you are writing an interlaced image.
-
-;void (png_structrp png_ptr, bytepp image)
-align 4
-proc png_write_image, png_ptr:dword, image:dword
-pushad
-;ebx ;bytepp ;points to current row
-;ecx ;uint_32 ;row index
-;edx ;int ;pass
-;esi ;int ;num_pass
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f ;if (..==0) return
-
- png_debug 1, 'in png_write_image'
-
-if PNG_WRITE_INTERLACING_SUPPORTED eq 1
- ; Initialize interlace handling. If image is not interlaced,
- ; this will set pass to 1
-
- stdcall png_set_interlace_handling, edi
- mov esi,eax
-else
- xor esi,esi
- inc esi
-end if
- ; Loop through passes
- xor edx,edx
- .cycle0: ;for (edx = 0; edx < esi; edx++)
- cmp edx,esi
- jge .cycle0end
- ; Loop through image
- mov ebx,[image]
- xor ecx,ecx
- .cycle1: ;for (ecx = 0, ebx = image; ecx < png_ptr.height; ecx++, ebx++)
- stdcall png_write_row, edi,[ebx]
- inc ecx
- add ebx,4
- cmp ecx,[edi+png_struct.height]
- jl .cycle1
- ;.cycle1end:
- inc edx
- jmp .cycle0
- .cycle0end:
-.end_f:
-popad
- ret
-endp
-
-; Performs intrapixel differencing
-;void (png_row_infop row_info, bytep row)
-align 4
-proc png_do_write_intrapixel uses eax ebx ecx edx edi, row_info:dword, row:dword
- png_debug 1, 'in png_do_write_intrapixel'
-
- mov ebx,[row_info]
- movzx eax,byte[ebx+png_row_info.color_type]
- and eax,PNG_COLOR_MASK_COLOR
- jz .end_f ;if (..!=0)
- ;edx = bytes_per_pixel
- mov ecx,[ebx+png_row_info.width] ;ecx = row_width
- cmp byte[ebx+png_row_info.bit_depth],8 ;if (..==8)
- jne .end0
-; bytep rp;
-; uint_32 i;
-
- cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_RGB
- jne @f ;if (..==..)
- mov edx,3-1 ;(-1) for stosb
- jmp .end2
- @@:
- cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_RGB_ALPHA
- jne @f ;else if (..==..)
- mov edx,4-1 ;(-1) for stosb
- jmp .end2
- @@:
- jmp .end_f ;else return
- .end2:
-
- mov edi,[row]
-align 4
- .cycle0: ;for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
- mov ax,word[edi]
- sub al,ah
- stosb ;*(rp) = (byte)(*rp - *(rp + 1))
- mov ax,word[edi]
- sub ah,al
- mov byte[edi+1],ah ;*(rp + 2) = (byte)(*(rp + 2) - *(rp + 1))
- add edi,edx
- loop .cycle0
- .cycle0end:
- jmp .end_f
- .end0:
-
-if PNG_WRITE_16BIT_SUPPORTED eq 1
- cmp byte[ebx+png_row_info.bit_depth],16 ;else if (..==16)
- jne .end1
-; bytep rp;
-; uint_32 i;
-
- cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_RGB
- jne @f ;if (..==..)
- mov edx,6
- jmp .end3
- @@:
- cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_RGB_ALPHA
- jne @f ;else if (..==..)
- mov edx,8
- jmp .end3
- @@:
- jmp .end_f ;else return
- .end3:
-
- mov edi,[row]
-align 4
- .cycle1: ;for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
-; uint_32 s0 = (*(rp ) << 8) | *(rp + 1);
-; uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3);
-; uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5);
-; uint_32 red = (uint_32)((s0 - s1) & 0xffffL);
-; uint_32 blue = (uint_32)((s2 - s1) & 0xffffL);
-; *(rp ) = (byte)(red >> 8);
-; *(rp + 1) = (byte)red;
-; *(rp + 4) = (byte)(blue >> 8);
-; *(rp + 5) = (byte)blue;
- add edi,edx
- loop .cycle1
- .cycle1end:
- .end1:
-end if ;WRITE_16BIT
-.end_f:
- ret
-endp
-
-; Called by user to write a row of image data
-;void (png_structrp png_ptr, bytep row)
-align 4
-proc png_write_row, png_ptr:dword, row:dword
-locals
- ; 1.5.6: moved from png_struct to be a local structure:
- row_info png_row_info
-endl
-pushad
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f ;if(..==0) return
-
-; png_debug2(1, "in png_write_row (row %u, pass %d)",
-; png_ptr->row_number, png_ptr->pass);
-png_debug1 1, 'in png_write_row (row %u)',[edi+png_struct.row_number]
-
- ; Initialize transformations and other stuff if first time
- cmp dword[edi+png_struct.row_number],0
- jne .end0
- cmp byte[edi+png_struct.pass],0
- jne .end0 ;if(..==0 && ..==0)
-
- ; Make sure we wrote the header info
- mov eax,[edi+png_struct.mode]
- and eax,PNG_WROTE_INFO_BEFORE_PLTE
- jnz @f ;if(..==0)
- png_error edi, 'png_write_info was never called before png_write_row'
- @@:
-
- ; Check for transforms that have been set but were defined out
-if (PNG_WRITE_INVERT_SUPPORTED eq 0) & (PNG_READ_INVERT_SUPPORTED eq 1)
- mov eax,[edi+png_struct.transformations]
- and eax,PNG_INVERT_MONO
- jz @f ;if(..!=0)
- png_warning edi, 'PNG_WRITE_INVERT_SUPPORTED is not defined'
- @@:
-end if
-
-if (PNG_WRITE_FILLER_SUPPORTED eq 0) & (PNG_READ_FILLER_SUPPORTED eq 1)
- mov eax,[edi+png_struct.transformations]
- and eax,PNG_FILLER
- jz @f ;if(..!=0)
- png_warning edi, 'PNG_WRITE_FILLER_SUPPORTED is not defined'
- @@:
-end if
-
-if (PNG_WRITE_PACKSWAP_SUPPORTED eq 0) & (PNG_READ_PACKSWAP_SUPPORTED eq 1)
- mov eax,[edi+png_struct.transformations]
- and eax,PNG_PACKSWAP
- jz @f ;if(..!=0)
- png_warning edi, 'PNG_WRITE_PACKSWAP_SUPPORTED is not defined'
- @@:
-end if
-
-if (PNG_WRITE_PACK_SUPPORTED eq 0) & (PNG_READ_PACK_SUPPORTED eq 1)
- mov eax,[edi+png_struct.transformations]
- and eax,PNG_PACK
- jz @f ;if(..!=0)
- png_warning edi, 'PNG_WRITE_PACK_SUPPORTED is not defined'
- @@:
-end if
-
-if (PNG_WRITE_SHIFT_SUPPORTED eq 0) & (PNG_READ_SHIFT_SUPPORTED eq 1)
- mov eax,[edi+png_struct.transformations]
- and eax,PNG_SHIFT
- jz @f ;if(..!=0)
- png_warning edi, 'PNG_WRITE_SHIFT_SUPPORTED is not defined'
- @@:
-end if
-
-if (PNG_WRITE_BGR_SUPPORTED eq 0) & (PNG_READ_BGR_SUPPORTED eq 1)
- mov eax,[edi+png_struct.transformations]
- and eax,PNG_BGR
- jz @f ;if(..!=0)
- png_warning edi, 'PNG_WRITE_BGR_SUPPORTED is not defined'
- @@:
-end if
-
-if (PNG_WRITE_SWAP_SUPPORTED eq 0) & (PNG_READ_SWAP_SUPPORTED eq 1)
- mov eax,[edi+png_struct.transformations]
- and eax,PNG_SWAP_BYTES
- jz @f ;if(..!=0)
- png_warning edi, 'PNG_WRITE_SWAP_SUPPORTED is not defined'
- @@:
-end if
-
- stdcall png_write_start_row, edi
- .end0:
-
-if PNG_WRITE_INTERLACING_SUPPORTED eq 1
- ; If interlaced and not interested in row, return
- cmp byte[edi+png_struct.interlaced],0
- je .end1
- mov eax,[edi+png_struct.transformations]
- and eax,PNG_INTERLACE
- jz .end1 ;if(..!=0 && ..!=0)
- cmp byte[edi+png_struct.pass],0
- jne @f
- mov eax,[edi+png_struct.row_number]
- and eax,0x07
- jz .end1 ;if (..!=0)
- stdcall png_write_finish_row, edi
- jmp .end_f
- @@:
- cmp byte[edi+png_struct.pass],1
- jne @f
- mov eax,[edi+png_struct.row_number]
- and eax,0x07
- jnz .end2
- cmp dword[edi+png_struct.width],5
- jge .end1 ;if (..!=0 || ..<..)
- .end2:
- stdcall png_write_finish_row, edi
- jmp .end_f
- @@:
- cmp byte[edi+png_struct.pass],2
- jne @f
- mov eax,[edi+png_struct.row_number]
- and eax,0x07
- cmp eax,4
- je .end1 ;if (..!=..)
- stdcall png_write_finish_row, edi
- jmp .end_f
- @@:
- cmp byte[edi+png_struct.pass],3
- jne @f
- mov eax,[edi+png_struct.row_number]
- and eax,0x03
- jnz .end3
- cmp dword[edi+png_struct.width],3
- jge .end1 ;if (..!=0 || ..<..)
- .end3:
- stdcall png_write_finish_row, edi
- jmp .end_f
- @@:
- cmp byte[edi+png_struct.pass],4
- jne @f
- mov eax,[edi+png_struct.row_number]
- and eax,0x03
- cmp eax,2
- je .end1 ;if (..!=..)
- stdcall png_write_finish_row, edi
- jmp .end_f
- @@:
- cmp byte[edi+png_struct.pass],5
- jne @f
- mov eax,[edi+png_struct.row_number]
- and eax,0x01
- jnz .end4
- cmp dword[edi+png_struct.width],2
- jge .end1 ;if (..!=0 || ..<..)
- .end4:
- stdcall png_write_finish_row, edi
- jmp .end_f
- @@:
- cmp byte[edi+png_struct.pass],6
- jne .end1
- mov eax,[edi+png_struct.row_number]
- and eax,0x01
- jnz .end1 ;if (..==0)
- stdcall png_write_finish_row, edi
- jmp .end_f
- .end1:
-end if
-
- ; Set up row info for transformations
- mov ebx,ebp
- sub ebx,sizeof.png_row_info
- mov al,byte[edi+png_struct.color_type]
- mov byte[ebx+png_row_info.color_type],al
- mov eax,[edi+png_struct.usr_width]
- mov [ebx+png_row_info.width],eax
- movzx eax,byte[edi+png_struct.usr_channels]
- mov byte[ebx+png_row_info.channels],al
- movzx ecx,byte[edi+png_struct.usr_bit_depth]
- mov byte[ebx+png_row_info.bit_depth],cl
- imul eax,ecx ;.bit_depth * .channels
- mov byte[ebx+png_row_info.pixel_depth],al
- PNG_ROWBYTES eax, [ebx+png_row_info.width]
- mov [ebx+png_row_info.rowbytes], eax
-
- push eax
- movzx eax,byte[ebx+png_row_info.color_type]
- png_debug1 3, 'row_info->color_type = %d', eax
- png_debug1 3, 'row_info->width = %u', [ebx+png_row_info.width]
- movzx eax,byte[ebx+png_row_info.channels]
- png_debug1 3, 'row_info->channels = %d', eax
- movzx eax,byte[ebx+png_row_info.bit_depth]
- png_debug1 3, 'row_info->bit_depth = %d', eax
- movzx eax,byte[ebx+png_row_info.pixel_depth]
- png_debug1 3, 'row_info->pixel_depth = %d', eax
- png_debug1 3, 'row_info->rowbytes = %lu', [ebx+png_row_info.rowbytes]
- pop eax
-
- ; Copy user's row into buffer, leaving room for filter byte.
- push edi
- mov edi,[edi+png_struct.row_buf]
- inc edi
- mov esi,[row]
- mov ecx,eax
- rep movsb ;memcpy(...
- pop edi
-
-if PNG_WRITE_INTERLACING_SUPPORTED eq 1
- ; Handle interlacing
- cmp byte[edi+png_struct.interlaced],0
- je @f
- cmp byte[edi+png_struct.pass],6
- jge @f
- mov eax,[edi+png_struct.transformations]
- and eax,PNG_INTERLACE
- jz @f ;if (.. && ..<.. && ..!=0)
- movzx eax,byte[edi+png_struct.pass]
- push eax
- mov eax,[edi+png_struct.row_buf]
- inc eax
- stdcall png_do_write_interlace, ebx, eax ;, ...pass
- ; This should always get caught above, but still ...
- cmp dword[ebx+png_row_info.width],0
- jne @f ;if (..==0)
- stdcall png_write_finish_row, edi
- jmp .end_f
- @@:
-end if
-
-if PNG_WRITE_TRANSFORMS_SUPPORTED eq 1
- ; Handle other transformations
- cmp dword[edi+png_struct.transformations],0
- je @f ;if (..!=0)
- stdcall png_do_write_transformations, edi, ebx
- @@:
-end if
-
- ; At this point the row_info pixel depth must match the 'transformed' depth,
- ; which is also the output depth.
-
- mov al,[ebx+png_row_info.pixel_depth]
- cmp al,[edi+png_struct.pixel_depth]
- jne @f
- cmp al,[edi+png_struct.transformed_pixel_depth]
- je .end5
- @@: ;if (..!=.. || ..!=..)
- png_error edi, 'internal write transform logic error'
- .end5:
-
-if PNG_MNG_FEATURES_SUPPORTED eq 1
- ; Write filter_method 64 (intrapixel differencing) only if
- ; 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
- ; 2. Libpng did not write a PNG signature (this filter_method is only
- ; used in PNG datastreams that are embedded in MNG datastreams) and
- ; 3. The application called png_permit_mng_features with a mask that
- ; included PNG_FLAG_MNG_FILTER_64 and
- ; 4. The filter_method is 64 and
- ; 5. The color_type is RGB or RGBA
-
- mov eax,[edi+png_struct.mng_features_permitted]
- and eax,PNG_FLAG_MNG_FILTER_64
- jz @f
- cmp byte[edi+png_struct.filter_type],PNG_INTRAPIXEL_DIFFERENCING
- jne @f ;if (..!=0 && ..==..)
- ; Intrapixel differencing
- mov eax,[edi+png_struct.row_buf]
- inc eax
- stdcall png_do_write_intrapixel, ebx, eax
- @@:
-end if
-
-; Added at libpng-1.5.10
-if PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED eq 1
- ; Check for out-of-range palette index
- cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_PALETTE
- jne @f
- cmp dword[edi+png_struct.num_palette_max],0
- jl @f ;if (..==.. && ..>=0)
- stdcall png_do_check_palette_indexes, edi, ebx
- @@:
-end if
-
- ; Find a filter if necessary, filter the row and write it out.
- mov ebx,ebp
- sub ebx,sizeof.png_row_info
- stdcall png_write_find_filter, edi, ebx
-
- cmp dword[edi+png_struct.write_row_fn],0
- je .end_f ;if (..!=0)
- movzx eax,byte[edi+png_struct.pass]
- stdcall dword[edi+png_struct.write_row_fn], edi, [edi+png_struct.row_number], eax
-.end_f:
-popad
- ret
-endp
-
-; Set the automatic flush interval or 0 to turn flushing off
-;void (png_structrp png_ptr, int nrows)
-align 4
-proc png_set_flush uses eax edi, png_ptr:dword, nrows:dword
- png_debug 1, 'in png_set_flush'
-
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f ;if (..==0) return
-
- mov eax,[nrows]
- cmp eax,0
- jge @f ;(nrows < 0 ? 0 : nrows)
- xor eax,eax
- @@:
- mov [edi+png_struct.flush_dist],eax
-.end_f:
- ret
-endp
-
-; Flush the current output buffers now
-;void (png_structrp png_ptr)
-align 4
-proc png_write_flush uses eax edi, png_ptr:dword
- png_debug 1, 'in png_write_flush'
-
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f ;if (..==0) return
-
- ; We have already written out all of the data
- mov eax,[edi+png_struct.num_rows]
- cmp [edi+png_struct.row_number],eax
- jge .end_f ;if (..>=..) return
-
- stdcall png_compress_IDAT, 0, 0, Z_SYNC_FLUSH
- mov dword[edi+png_struct.flush_rows],0
- stdcall png_flush, edi
-.end_f:
-popad
- ret
-endp
-
-; Free any memory used in png_ptr struct without freeing the struct itself.
-;void (png_structrp png_ptr)
-align 4
-proc png_write_destroy uses eax edi, png_ptr:dword
- png_debug 1, 'in png_write_destroy'
-
- ; Free any memory zlib uses
- mov edi,[png_ptr]
- mov eax,[edi+png_struct.flags]
- and eax,PNG_FLAG_ZSTREAM_INITIALIZED
- jz @f ;if (..!=0)
- mov eax,edi
- add eax,png_struct.zstream
- stdcall [deflateEnd], eax
- @@:
-
- ; Free our memory. png_free checks NULL for us.
- mov eax,edi
- add eax,png_struct.zbuffer_list
- stdcall png_free_buffer_list, edi, eax
- stdcall png_free, edi, [edi+png_struct.row_buf]
- mov dword[edi+png_struct.row_buf],0
-if PNG_WRITE_FILTER_SUPPORTED eq 1
- stdcall png_free, edi, [edi+png_struct.prev_row]
- stdcall png_free, edi, [edi+png_struct.try_row]
- stdcall png_free, edi, [edi+png_struct.tst_row]
- mov dword[edi+png_struct.prev_row],0
- mov dword[edi+png_struct.try_row],0
- mov dword[edi+png_struct.tst_row],0
-end if
-
-if PNG_SET_UNKNOWN_CHUNKS_SUPPORTED eq 1
- stdcall png_free, edi, [edi+png_struct.chunk_list]
- mov dword[edi+png_struct.chunk_list],0
-end if
-
- ; The error handling and memory handling information is left intact at this
- ; point: the jmp_buf may still have to be freed. See png_destroy_png_struct
- ; for how this happens.
- ret
-endp
-
-; Free all memory used by the write.
-; In libpng 1.6.0 this API changed quietly to no longer accept a NULL value for
-; *png_ptr_ptr. Prior to 1.6.0 it would accept such a value and it would free
-; the passed in info_structs but it would quietly fail to free any of the data
-; inside them. In 1.6.0 it quietly does nothing (it has to be quiet because it
-; has no png_ptr.)
-
-;void (png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
-align 4
-proc png_destroy_write_struct uses edi esi, png_ptr_ptr:dword, info_ptr_ptr:dword
- png_debug 1, 'in png_destroy_write_struct'
-
- mov esi,[png_ptr_ptr]
- cmp esi,0
- je @f ;if (..!=0)
- mov edi,[esi]
-
- cmp edi,0
- je @f ;if (..!=0) ;added in libpng 1.6.0
- stdcall png_destroy_info_struct, edi, [info_ptr_ptr]
-
- mov dword[esi],0
- stdcall png_write_destroy, edi
- stdcall png_destroy_png_struct, edi
- @@:
- ret
-endp
-
-; Allow the application to select one or more row filters to use.
-;void (png_structrp png_ptr, int method, int filters)
-align 4
-proc png_set_filter uses eax ebx ecx edi, png_ptr:dword, method:dword, filters:dword
- png_debug 1, 'in png_set_filter'
-pushad
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f ;if (..==0) return
-
-if PNG_MNG_FEATURES_SUPPORTED eq 1
- mov eax,[edi+png_struct.mng_features_permitted]
- and eax,PNG_FLAG_MNG_FILTER_64
- je @f
- cmp dword[method], PNG_INTRAPIXEL_DIFFERENCING
- jne @f ;if (..!=0 && ..==..)
- mov dword[method], PNG_FILTER_TYPE_BASE
- @@:
-end if
- cmp dword[method], PNG_FILTER_TYPE_BASE
- jne .end0 ;if (..==..)
- mov ebx,[filters]
- and ebx,PNG_ALL_FILTERS or 0x07 ;switch (..)
-
-if PNG_WRITE_FILTER_SUPPORTED eq 1
- cmp ebx,5
- je .end2
- cmp ebx,6
- je .end2
- cmp ebx,7
- je .end2
- jmp @f
- .end2:
- cStr ,'Unknown row filter for method 0'
- stdcall png_app_error, edi, eax
- ; FALL THROUGH
- @@:
-end if ;WRITE_FILTER
- cmp ebx,PNG_FILTER_VALUE_NONE
- jne @f
- mov byte[edi+png_struct.do_filter],PNG_FILTER_NONE
- jmp .end1
- @@:
-if PNG_WRITE_FILTER_SUPPORTED eq 1
- cmp ebx,PNG_FILTER_VALUE_SUB
- jne @f
- mov byte[edi+png_struct.do_filter],PNG_FILTER_SUB
- jmp .end1
- @@:
- cmp ebx,PNG_FILTER_VALUE_UP
- jne @f
- mov byte[edi+png_struct.do_filter],PNG_FILTER_UP
- jmp .end1
- @@:
- cmp ebx,PNG_FILTER_VALUE_AVG
- jne @f
- mov byte[edi+png_struct.do_filter],PNG_FILTER_AVG
- jmp .end1
- @@:
- cmp ebx,PNG_FILTER_VALUE_PAETH
- jne @f
- mov byte[edi+png_struct.do_filter],PNG_FILTER_PAETH
- jmp .end1
- @@: ;default:
- mov eax,[filters]
- mov byte[edi+png_struct.do_filter],al
- jmp .end1
-else
- @@: ;default:
- cStr ,'Unknown row filter for method 0'
- stdcall png_app_error edi, eax
-end if ;WRITE_FILTER
- .end1:
-
-if PNG_WRITE_FILTER_SUPPORTED eq 1
- ; If we have allocated the row_buf, this means we have already started
- ; with the image and we should have allocated all of the filter buffers
- ; that have been selected. If prev_row isn't already allocated, then
- ; it is too late to start using the filters that need it, since we
- ; will be missing the data in the previous row. If an application
- ; wants to start and stop using particular filters during compression,
- ; it should start out with all of the filters, and then remove them
- ; or add them back after the start of compression.
-
- ; NOTE: this is a nasty constraint on the code, because it means that the
- ; prev_row buffer must be maintained even if there are currently no
- ; 'prev_row' requiring filters active.
-
- cmp dword[edi+png_struct.row_buf],0
- je .end3 ;if (..!=0)
- ;ebx = num_filters
- ;ecx = buf_size
-
- ; Repeat the checks in png_write_start_row; 1 pixel high or wide
- ; images cannot benefit from certain filters. If this isn't done here
- ; the check below will fire on 1 pixel high images.
-
- cmp dword[edi+png_struct.height],1
- jne @f ;if (..==..)
- and dword[filters],not (PNG_FILTER_UP or PNG_FILTER_AVG or PNG_FILTER_PAETH)
- @@:
- cmp dword[edi+png_struct.width],1
- jne @f ;if (..==..)
- and dword[filters],not (PNG_FILTER_SUB or PNG_FILTER_AVG or PNG_FILTER_PAETH)
- @@:
- mov eax,[filters]
- and eax,PNG_FILTER_UP or PNG_FILTER_AVG or PNG_FILTER_PAETH
- jz @f
- cmp dword[edi+png_struct.prev_row],0
- je @f;if (..!=0 && ..==0)
- ; This is the error case, however it is benign - the previous row
- ; is not available so the filter can't be used. Just warn here.
-
- png_app_warning edi, 'png_set_filter: UP/AVG/PAETH cannot be added after start'
- and dword[filters],not (PNG_FILTER_UP or PNG_FILTER_AVG or PNG_FILTER_PAETH)
- @@:
-
- xor ebx,ebx
-
- mov eax,[filters]
- and eax,PNG_FILTER_SUB
- jz @f ;if (..)
- inc ebx
- @@:
- mov eax,[filters]
- and eax,PNG_FILTER_UP
- jz @f ;if (..)
- inc ebx
- @@:
- mov eax,[filters]
- and eax,PNG_FILTER_AVG
- jz @f ;if (..)
- inc ebx
- @@:
- mov eax,[filters]
- and eax,PNG_FILTER_PAETH
- jz @f ;if (..)
- inc ebx
- @@:
- ; Allocate needed row buffers if they have not already been
- ; allocated.
-
- movzx eax,byte[edi+png_struct.usr_channels]
- movzx ecx,byte[edi+png_struct.usr_bit_depth]
- imul eax,ecx ;.bit_depth * .channels
- mov ecx,[edi+png_struct.width]
- inc ecx
- PNG_ROWBYTES eax, ecx
- mov ecx, eax
-
- cmp dword[edi+png_struct.try_row],0
- jne @f ;if (..==0)
- stdcall png_malloc, edi, ecx
- mov [edi+png_struct.try_row],eax
- @@:
-
- cmp ebx,1
- jle .end3 ;if (..>..)
- cmp dword[edi+png_struct.tst_row],0
- jne .end3 ;if (..==0)
- stdcall png_malloc, edi, ecx
- mov [edi+png_struct.tst_row],eax
- .end3:
- mov eax,[filters]
- mov byte[edi+png_struct.do_filter],al
-end if
- jmp .end_f
- .end0: ;else
- png_error edi, 'Unknown custom filter method'
-.end_f:
-popad
- ret
-endp
-
-; Provide floating and fixed point APIs
-;void (png_structrp png_ptr, int heuristic_method,
-; int num_weights, png_const_doublep filter_weights, png_const_doublep filter_costs)
-align 4
-proc png_set_filter_heuristics, png_ptr:dword, heuristic_method:dword, num_weights:dword, filter_weights:dword, filter_costs:dword
- ret
-endp
-
-;void (png_structrp png_ptr, int heuristic_method,
-; int num_weights, png_const_fixed_point_p filter_weights,
-; png_const_fixed_point_p filter_costs)
-align 4
-proc png_set_filter_heuristics_fixed, png_ptr:dword, heuristic_method:dword, num_weights:dword, filter_weights:dword, filter_costs:dword
- ret
-endp
-
-;void (png_structrp png_ptr, int level)
-align 4
-proc png_set_compression_level uses edi, png_ptr:dword, level:dword
- png_debug 1, 'in png_set_compression_level'
-
- mov edi,[png_ptr]
- cmp edi,0
- je @f ;if (..==0) return
-
- m2m [edi+png_struct.zlib_level], [level]
- @@:
- ret
-endp
-
-;void (png_structrp png_ptr, int mem_level)
-align 4
-proc png_set_compression_mem_level uses edi, png_ptr:dword, mem_level:dword
- png_debug 1, 'in png_set_compression_mem_level'
-
- mov edi,[png_ptr]
- cmp edi,0
- je @f ;if (..==0) return
-
- m2m [edi+png_struct.zlib_mem_level], [mem_level]
- @@:
- ret
-endp
-
-;void (png_structrp png_ptr, int strategy)
-align 4
-proc png_set_compression_strategy uses edi, png_ptr:dword, strategy:dword
- png_debug 1, 'in png_set_compression_strategy'
-
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f ;if (..==0) return
-
- ; The flag setting here prevents the libpng dynamic selection of strategy.
-
- or dword[edi+png_struct.flags], PNG_FLAG_ZLIB_CUSTOM_STRATEGY
- m2m [edi+png_struct.zlib_strategy], [strategy]
-.end_f:
- ret
-endp
-
-; If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a
-; smaller value of window_bits if it can do so safely.
-
-;void (png_structrp png_ptr, int window_bits)
-align 4
-proc png_set_compression_window_bits uses eax edi, png_ptr:dword, window_bits:dword
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f ;if (..==0) return
-
- ; Prior to 1.6.0 this would warn but then set the window_bits value. This
- ; meant that negative window bits values could be selected that would cause
- ; libpng to write a non-standard PNG file with raw deflate or gzip
- ; compressed IDAT or ancillary chunks. Such files can be read and there is
- ; no warning on read, so this seems like a very bad idea.
-
- mov eax,[window_bits]
- cmp eax,15
- jle @f ;if (..>..)
- png_warning edi, 'Only compression windows <= 32k supported by PNG'
- mov eax,15
- jmp .end0
- @@: ;else if (..<..)
- cmp eax,8
- jge @f
- png_warning edi, 'Only compression windows >= 256 supported by PNG'
- mov eax,8
- .end0:
-
- mov [edi+png_struct.zlib_window_bits],eax
-.end_f:
- ret
-endp
-
-;void (png_structrp png_ptr, int method)
-align 4
-proc png_set_compression_method uses eax edi, png_ptr:dword, method:dword
- png_debug 1, 'in png_set_compression_method'
-
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f ;if (..==0) return
-
- ; This would produce an invalid PNG file if it worked, but it doesn't and
- ; deflate will fault it, so it is harmless to just warn here.
-
- mov eax,[method]
- cmp eax,8
- je @f ;if (..!=..)
- png_warning edi, 'Only compression method 8 is supported by PNG'
- @@:
- mov [edi+png_struct.zlib_method],eax
-.end_f:
- ret
-endp
-
-; The following were added to libpng-1.5.4
-if PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED eq 1
-;void (png_structrp png_ptr, int level)
-align 4
-proc png_set_text_compression_level uses edi, png_ptr:dword, level:dword
- png_debug 1, 'in png_set_text_compression_level'
-
- mov edi,[png_ptr]
- cmp edi,0
- je @f ;if (..==0) return
-
- m2m [edi+png_struct.zlib_text_level], [level]
- @@:
- ret
-endp
-
-;void (png_structrp png_ptr, int mem_level)
-align 4
-proc png_set_text_compression_mem_level uses edi, png_ptr:dword, mem_level:dword
- png_debug 1, 'in png_set_text_compression_mem_level'
-
- mov edi,[png_ptr]
- cmp edi,0
- je @f ;if (..==0) return
-
- m2m [edi+png_struct.zlib_text_mem_level], [mem_level]
- @@:
- ret
-endp
-
-;void (png_structrp png_ptr, int strategy)
-align 4
-proc png_set_text_compression_strategy uses edi, png_ptr:dword, strategy:dword
- png_debug 1, 'in png_set_text_compression_strategy'
-
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f ;if (..==0) return
-
- m2m [edi+png_struct.zlib_text_strategy], [strategy]
-.end_f:
- ret
-endp
-
-; If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a
-; smaller value of window_bits if it can do so safely.
-
-;void (png_structrp png_ptr, int window_bits)
-align 4
-proc png_set_text_compression_window_bits uses eax edi, png_ptr:dword, window_bits:dword
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f ;if (..==0) return
-
- mov eax,[window_bits]
- cmp eax,15
- jle @f ;if (..>..)
- png_warning edi, 'Only compression windows <= 32k supported by PNG'
- mov eax,15
- jmp .end0
- @@: ;else if (..<..)
- cmp eax,8
- jge @f
- png_warning edi, 'Only compression windows >= 256 supported by PNG'
- mov eax,8
- .end0:
-
- mov [edi+png_struct.zlib_text_window_bits],eax
-.end_f:
- ret
-endp
-
-;void (png_structrp png_ptr, int method)
-align 4
-proc png_set_text_compression_method uses edi, png_ptr:dword, method:dword
- png_debug 1, 'in png_set_text_compression_method'
-
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f ;if (..==0) return
-
- cmp dword[method],8
- je @f ;if (..!=..)
- png_warning edi, 'Only compression method 8 is supported by PNG'
- @@:
- m2m [edi+png_struct.zlib_text_method], [method]
-.end_f:
- ret
-endp
-end if ;WRITE_CUSTOMIZE_ZTXT_COMPRESSION
-; end of API added to libpng-1.5.4
-
-;void (png_structrp png_ptr, png_write_status_ptr write_row_fn)
-align 4
-proc png_set_write_status_fn uses edi, png_ptr:dword, write_row_fn:dword
- mov edi,[png_ptr]
- cmp edi,0
- je @f ;if (..==0) return
- m2m [edi+png_struct.write_row_fn], [write_row_fn]
- @@:
- ret
-endp
-
-;void (png_structrp png_ptr, png_user_transform_ptr write_user_transform_fn)
-align 4
-proc png_set_write_user_transform_fn uses edi, png_ptr:dword, write_user_transform_fn:dword
- png_debug 1, 'in png_set_write_user_transform_fn'
-
- mov edi,[png_ptr]
- cmp edi,0
- je @f ;if (..==0) return
- or dword[edi+png_struct.transformations], PNG_USER_TRANSFORM
- m2m [edi+png_struct.write_user_transform_fn], [write_user_transform_fn]
- @@:
- ret
-endp
-
-;void (png_structrp png_ptr, png_inforp info_ptr, int transforms, voidp params)
-align 4
-proc png_write_png, png_ptr:dword, info_ptr:dword, transforms:dword, params:dword
-pushad
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f
- mov esi,[info_ptr]
- cmp esi,0
- je .end_f ;if(..==0 || ..==0) return
-
- and dword[esi+png_info_def.valid],PNG_INFO_IDAT
- cmp esi,0 ;if(..==0)
- jne @f
- cStr ,'no rows for png_write_image to write'
- stdcall png_app_error edi, eax
- jmp .end_f ;return
- @@:
-
- ; Write the file header information.
- stdcall png_write_info, edi, esi
-
- ; ------ these transformations don't touch the info structure -------
-
- ; Invert monochrome pixels
- mov eax,[transforms]
- and eax,PNG_TRANSFORM_INVERT_MONO
- jz @f ;if(..!=0)
-if PNG_WRITE_INVERT_SUPPORTED eq 1
- stdcall png_set_invert_mono,edi
-else
- cStr ,'PNG_TRANSFORM_INVERT_MONO not supported'
- stdcall png_app_error edi, eax
-end if
- @@:
-
- ; Shift the pixels up to a legal bit depth and fill in
- ; as appropriate to correctly scale the image.
-
- mov eax,[transforms]
- and eax,PNG_TRANSFORM_SHIFT
- jz @f ;if(..!=0)
-if PNG_WRITE_SHIFT_SUPPORTED eq 1
- mov eax,[esi+png_info_def.valid]
- and eax,PNG_INFO_sBIT
- jz @f ;if(..!=0)
- mov eax,esi
- add eax,png_info_def.sig_bit
- stdcall png_set_shift, edi, eax
-else
- cStr ,'PNG_TRANSFORM_SHIFT not supported'
- stdcall png_app_error edi, eax
-end if
- @@:
-
- ; Pack pixels into bytes
- mov eax,[transforms]
- and eax,PNG_TRANSFORM_PACKING
- jz @f ;if(..!=0)
-if PNG_WRITE_PACK_SUPPORTED eq 1
- stdcall png_set_packing, edi
-else
- cStr ,'PNG_TRANSFORM_PACKING not supported'
- stdcall png_app_error edi, eax
-end if
- @@:
-
- ; Swap location of alpha bytes from ARGB to RGBA
- mov eax,[transforms]
- and eax,PNG_TRANSFORM_SWAP_ALPHA
- jz @f ;if(..!=0)
-if PNG_WRITE_SWAP_ALPHA_SUPPORTED eq 1
- stdcall png_set_swap_alpha, edi
-else
- cStr ,'PNG_TRANSFORM_SWAP_ALPHA not supported'
- stdcall png_app_error edi, eax
-end if
- @@:
-
- ; Remove a filler (X) from XRGB/RGBX/AG/GA into to convert it into
- ; RGB, note that the code expects the input color type to be G or RGB; no
- ; alpha channel.
-
- mov eax,[transforms]
- and eax,PNG_TRANSFORM_STRIP_FILLER_AFTER or PNG_TRANSFORM_STRIP_FILLER_BEFORE
- jz .end_0 ;if(..!=0)
-if PNG_WRITE_FILLER_SUPPORTED eq 1
- and eax,PNG_TRANSFORM_STRIP_FILLER_AFTER
- jz .end_1 ;if(..!=0)
- mov eax,[transforms]
- and eax,PNG_TRANSFORM_STRIP_FILLER_BEFORE
- jz @f ;if(..!=0)
- cStr ,'PNG_TRANSFORM_STRIP_FILLER: BEFORE+AFTER not supported'
- stdcall png_app_error edi, eax
- @@:
-
- ; Continue if ignored - this is the pre-1.6.10 behavior
- stdcall png_set_filler, edi, 0, PNG_FILLER_AFTER
- jmp .end_0
- .end_1: ;else if ((transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) != 0)
- stdcall png_set_filler, edi, 0, PNG_FILLER_BEFORE
-else
- cStr ,'PNG_TRANSFORM_STRIP_FILLER not supported'
- stdcall png_app_error edi, eax
-end if
- .end_0:
-
- ; Flip BGR pixels to RGB
- mov eax,[transforms]
- and eax,PNG_TRANSFORM_BGR
- jz @f ;if(..!=0)
-if PNG_WRITE_BGR_SUPPORTED eq 1
- stdcall png_set_bgr, edi
-else
- cStr ,'PNG_TRANSFORM_BGR not supported'
- stdcall png_app_error edi, eax
-end if
- @@:
-
- ; Swap bytes of 16-bit files to most significant byte first
- mov eax,[transforms]
- and eax,PNG_TRANSFORM_SWAP_ENDIAN
- jz @f ;if(..!=0)
-if PNG_WRITE_SWAP_SUPPORTED eq 1
- stdcall png_set_swap, edi
-else
- cStr ,'PNG_TRANSFORM_SWAP_ENDIAN not supported'
- stdcall png_app_error edi, eax
-end if
- @@:
-
- ; Swap bits of 1-bit, 2-bit, 4-bit packed pixel formats
- mov eax,[transforms]
- and eax,PNG_TRANSFORM_PACKSWAP
- jz @f ;if(..!=0)
-if PNG_WRITE_PACKSWAP_SUPPORTED eq 1
- stdcall png_set_packswap, edi
-else
- cStr ,'PNG_TRANSFORM_PACKSWAP not supported'
- stdcall png_app_error edi, eax
-end if
- @@:
-
- ; Invert the alpha channel from opacity to transparency
- mov eax,[transforms]
- and eax,PNG_TRANSFORM_INVERT_ALPHA
- jz @f ;if(..!=0)
-if PNG_WRITE_INVERT_ALPHA_SUPPORTED eq 1
- stdcall png_set_invert_alpha, edi
-else
- cStr ,'PNG_TRANSFORM_INVERT_ALPHA not supported'
- stdcall png_app_error edi, eax
-end if
- @@:
-
- ; ----------------------- end of transformations -------------------
-
- ; Write the bits
- stdcall png_write_image, edi, dword[esi+png_info_def.row_pointers]
-
- ; It is REQUIRED to call this to finish writing the rest of the file
- stdcall png_write_end, edi, esi
-
-.end_f:
-popad
- ret
-endp
-
-if PNG_SIMPLIFIED_WRITE_SUPPORTED eq 1
-; Initialize the write structure - general purpose utility.
-;int (png_imagep image)
-align 4
-proc png_image_write_init uses ebx ecx edx edi esi, image:dword
- mov ebx,[image]
- stdcall png_create_write_struct, PNG_LIBPNG_VER_STRING, ebx, png_safe_error, png_safe_warning
- ;eax = png_ptr
-
- test eax,eax
- jz .end0 ;if (..!=0)
- mov edi,eax
- or dword[eax+png_struct.transformations],PNG_BGR ;transformation rgb for KoliriOS
- stdcall png_create_info_struct, edi
- ;eax = info_ptr
-
- test eax,eax
- jz .end1 ;if (..!=0)
- mov esi,eax
- stdcall png_malloc_warn, edi, sizeof.png_control
- ;control = eax
-
- test eax,eax
- jz .end2 ;if (..!=0)
- push eax
- mov edx,edi ; edx = png_ptr
- mov ecx,sizeof.png_control
- mov edi,eax
- xor eax,eax
- rep stosb ;memset(control, 0, (sizeof.control))
- pop eax
-
- mov [eax+png_control.png_ptr], edx
- mov [eax+png_control.info_ptr], esi
- mov [eax+png_control.for_write], 1
-
- mov [ebx+png_image.opaque], eax
- xor eax,eax
- inc eax
- jmp .end_f
- .end2:
-
- ; Error clean up
- push esi
- mov esi,esp
- stdcall png_destroy_info_struct, edi, esi
- add esp,4
- .end1:
-
- push edi
- mov edi,esp
- stdcall png_destroy_write_struct, edi, 0
- add esp,4
- .end0:
-
- std_png_image_error ebx, 'png_image_write_: out of memory'
-.end_f:
- ret
-endp
-
-; Arguments to png_image_write_main:
-struct png_image_write_control
- ; Arguments:
- image dd ? ;png_imagep
- buffer dd ? ;png_const_voidp
- row_stride dd ? ;int_32
- colormap dd ? ;png_const_voidp
- convert_to_8bit dd ? ;int
- ; Local variables:
- first_row dd ? ;png_const_voidp
- row_bytes dd ? ;ptrdiff_t
- local_row dd ? ;voidp
- ; Byte count for memory writing
- memory dd ? ;bytep
- memory_bytes dd ? ;png_alloc_size_t ;not used for STDIO
- output_bytes dd ? ;png_alloc_size_t ;running total
-ends
-
-; Write uint_16 input to a 16-bit PNG; the png_ptr has already been set to
-; do any necessary byte swapping. The component order is defined by the
-; png_image format value.
-
-;int (voidp argument)
-align 4
-proc png_write_image_16bit uses ebx ecx edx, argument:dword
-locals
- display dd ? ;png_image_write_control* ;= argument
- image dd ? ;png_imagep ;= display->image
- png_ptr dd ? ;png_structrp ;= image->opaque->png_ptr
- input_row dd ? ;const_uint_16p ;= display->first_row
- output_row dd ? ;uint_16p ;= display->local_row
- row_end dd ? ;uint_16p
- channels dd ? ;const int ;= (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1;
- aindex dd 0 ;int ;= 0
- y dd ? ;uint_32 ;= image->height
-endl
- mov ebx,[argument]
- mov [display],ebx
- mov edx,[ebx+png_image_write_control.image]
- mov [image],edx
- mov ecx,[edx+png_image.opaque]
- mov ecx,[ecx+png_control.png_ptr]
- mov [png_ptr],ecx
- mov ecx,[ebx+png_image_write_control.first_row]
- mov [input_row],ecx
- mov ecx,[ebx+png_image_write_control.local_row]
- mov [output_row],ecx
-
- mov ecx,1
- mov eax,[edx+png_image.format]
- and eax,PNG_FORMAT_FLAG_COLOR
- jz @f
- mov ecx,3
- @@:
- mov [channels],ecx
- mov eax,[edx+png_image.height]
- mov [y],eax
-
- mov eax,[edx+png_image.format]
- and eax,PNG_FORMAT_FLAG_ALPHA
- jz .end0 ;if (..!=0)
-if PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED eq 1
- mov eax,[edx+png_image.format]
- and eax,PNG_FORMAT_FLAG_AFIRST
- jz @f ;if (..!=0)
- mov dword[aindex],-1
- inc dword[input_row] ;To point to the first component
- inc dword[output_row]
- jmp .end1
- @@: ;else
-end if
- mov eax,[channels]
- mov [aindex],eax
- jmp .end1
- .end0: ;else
- png_error [png_ptr], 'png_write_image: internal call error'
- .end1:
-
- ; Work out the output row end and count over this, note that the increment
- ; above to 'row' means that row_end can actually be beyond the end of the
- ; row; this is correct.
-
- mov eax,[channels]
- inc eax
- imul eax,[edx+png_image.width]
- add eax,[output_row]
- mov [row_end],eax
-
-; while (y-- > 0)
-; {
-; const_uint_16p in_ptr = input_row;
-; uint_16p out_ptr = output_row;
-
-; while (out_ptr < row_end)
-; {
-; const uint_16 alpha = in_ptr[aindex];
-; uint_32 reciprocal = 0;
-; int c;
-
-; out_ptr[aindex] = alpha;
-
- ; Calculate a reciprocal. The correct calculation is simply
- ; component/alpha*65535 << 15. (I.e. 15 bits of precision); this
- ; allows correct rounding by adding .5 before the shift. 'reciprocal'
- ; is only initialized when required.
-
-; if (alpha > 0 && alpha < 65535)
-; reciprocal = ((0xffff<<15)+(alpha>>1))/alpha;
-
-; c = channels;
-; do /* always at least one channel */
-; {
-; uint_16 component = *in_ptr++;
-
- ; The following gives 65535 for an alpha of 0, which is fine,
- ; otherwise if 0/0 is represented as some other value there is more
- ; likely to be a discontinuity which will probably damage
- ; compression when moving from a fully transparent area to a
- ; nearly transparent one. (The assumption here is that opaque
- ; areas tend not to be 0 intensity.)
-
-; if (component >= alpha)
-; component = 65535;
-
- ; component 0 && alpha < 65535)
-; {
-; uint_32 calc = component * reciprocal;
-; calc += 16384; /* round to nearest */
-; component = (uint_16)(calc >> 15);
-; }
-
-; *out_ptr++ = component;
-; }
-; while (--c > 0);
-
- ; Skip to next component (skip the intervening alpha channel)
-; ++in_ptr;
-; ++out_ptr;
-; }
-
-; png_write_row(png_ptr, display->local_row);
-; input_row += display->row_bytes/(sizeof (uint_16));
-; }
-
- xor eax,eax
- inc eax ;return 1
- ret
-endp
-
-; Given 16-bit input (1 to 4 channels) write 8-bit output. If an alpha channel
-; is present it must be removed from the components, the components are then
-; written in sRGB encoding. No components are added or removed.
-
-; Calculate an alpha reciprocal to reverse pre-multiplication. As above the
-; calculation can be done to 15 bits of accuracy; however, the output needs to
-; be scaled in the range 0..255*65535, so include that scaling here.
-
-;# define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+(alpha>>1))/alpha)
-
-;byte (uint_32 component, uint_32 alpha, uint_32 reciprocal/*from the above macro*/)
-align 4
-proc png_unpremultiply, component:dword, alpha:dword, reciprocal:dword
- ; The following gives 1.0 for an alpha of 0, which is fine, otherwise if 0/0
- ; is represented as some other value there is more likely to be a
- ; discontinuity which will probably damage compression when moving from a
- ; fully transparent area to a nearly transparent one. (The assumption here
- ; is that opaque areas tend not to be 0 intensity.)
-
- ; There is a rounding problem here; if alpha is less than 128 it will end up
- ; as 0 when scaled to 8 bits. To avoid introducing spurious colors into the
- ; output change for this too.
-
- mov eax,[alpha]
- cmp [component],eax
- jge @f
- cmp eax,128
- jge .end0
- @@: ;if (..>=.. || ..<..)
- mov eax,255
- jmp .end_f
- ; component 0)
- cmp dword[component],0
- jle .end1
- ; The test is that alpha/257 (rounded) is less than 255, the first value
- ; that becomes 255 is 65407.
- ; NOTE: this must agree with the PNG_DIV257 macro (which must, therefore,
- ; be exact!) [Could also test reciprocal != 0]
-
-; if (alpha < 65407)
-; {
-; component *= reciprocal;
-; component += 64; /* round to nearest */
-; component >>= 7;
-; }
-
-; else
-; component *= 255;
-
- ; Convert the component to sRGB.
- PNG_sRGB_FROM_LINEAR [component]
- and eax,0xff
- jmp .end_f
- .end1: ;else
- xor eax,eax
-.end_f:
- ret
-endp
-
-;int (voidp argument)
-align 4
-proc png_write_image_8bit uses ebx ecx edx edi esi, argument:dword
-locals
- display dd ? ;png_image_write_control* ;= argument
- image dd ? ;png_imagep ;= display->image
- png_ptr dd ? ;png_structrp ;= image->opaque->png_ptr
- input_row dd ? ;const_uint_16p ;= display->first_row
- output_row dd ? ;uint_16p ;= display->local_row
- row_end dd ? ;uint_16p
- channels dd ? ;const int ;= (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1;
- aindex dd 0 ;int ;= 0
- y dd ? ;uint_32 ;= image->height
- component dd ? ;uint_32
-endl
- mov ebx,[argument]
- mov [display],ebx
- mov edx,[ebx+png_image_write_control.image]
- mov [image],edx
- mov ecx,[edx+png_image.opaque]
- mov ecx,[ecx+png_control.png_ptr]
- mov [png_ptr],ecx
- mov ecx,[ebx+png_image_write_control.first_row]
- mov [input_row],ecx
- mov ecx,[ebx+png_image_write_control.local_row]
- mov [output_row],ecx
-
- mov ecx,1
- mov eax,[edx+png_image.format]
- and eax,PNG_FORMAT_FLAG_COLOR
- jz @f
- mov ecx,3
- @@:
- mov [channels],ecx
- mov eax,[edx+png_image.height]
- mov [y],eax
-
- mov eax,[edx+png_image.format]
- and eax,PNG_FORMAT_FLAG_ALPHA
- jz .end0 ;if (..!=0)
-
-if PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED eq 1
- mov eax,[edx+png_image.format]
- and eax,PNG_FORMAT_FLAG_AFIRST
- jz .end2 ;if (..!=0)
- mov [aindex],-1
- inc [input_row] ; To point to the first component
- inc [output_row]
- jmp @f
- .end2: ;else
-end if
- mov eax,[channels]
- mov [aindex],eax
- .@@:
-
- ; Use row_end in place of a loop counter:
- mov ecx,[channels]
- inc ecx
- imul ecx,[edx+png_image.width]
- add ecx,[output_row]
- ;ecx = row_end
-
-; while (y-- > 0)
-; {
-; const_uint_16p in_ptr = input_row;
-; bytep out_ptr = output_row;
-
-; while (out_ptr < row_end)
-; {
-; uint_16 alpha = in_ptr[aindex];
-; byte alphabyte = (byte)PNG_DIV257(alpha);
-; uint_32 reciprocal = 0;
-; int c;
-
- ; Scale and write the alpha channel.
-; out_ptr[aindex] = alphabyte;
-
-; if (alphabyte > 0 && alphabyte < 255)
-; reciprocal = UNP_RECIPROCAL(alpha);
-
-; c = channels;
-; do /* always at least one channel */
-; *out_ptr++ = png_unpremultiply(*in_ptr++, alpha, reciprocal);
-; while (--c > 0);
-
- ; Skip to next component (skip the intervening alpha channel)
-; ++in_ptr;
-; ++out_ptr;
-; } /* while out_ptr < row_end */
-
-; png_write_row(png_ptr, display->local_row);
-; input_row += display->row_bytes/(sizeof (uint_16));
-; } /* while y */
- jmp .end1
- .end0: ;else
- ; No alpha channel, so the row_end really is the end of the row and it
- ; is sufficient to loop over the components one by one.
-
- mov ecx,[edx+png_image.width]
- imul ecx,[channels]
- add ecx,[output_row]
- ;ecx = row_end
-
- .cycle2: ;while (y-- > 0)
- cmp dword[y],0
- jle .cycle2end
- mov esi,[input_row]
- mov edi,[output_row]
- ;esi = in_ptr
- ;edi = out_ptr
-
- .cycle3: ;while (..<..)
- cmp edi,ecx
- jge .cycle3end
- xor eax,eax
- lodsw
-
- imul eax,255
- mov [component],eax
- PNG_sRGB_FROM_LINEAR [component]
- stosb
- jmp .cycle3
-align 4
- .cycle3end:
-
- stdcall png_write_row, [png_ptr], [output_row]
- mov eax,[ebx+png_image_write_control.row_bytes]
- shr eax,1 ;sizeof.uint_16
- add [input_row],eax
- dec dword[y]
- jmp .cycle2
-align 4
- .cycle2end:
- .end1:
-
- xor eax,eax
- inc eax
- ret
-endp
-
-;void (png_image_write_control *display)
-align 4
-proc png_image_set_PLTE, display:dword
-locals
- image dd ? ;png_imagep ;= display->image
- cmap dd ? ;void * ;= display->colormap
- entries dd ? ;int
-
- ; NOTE: the caller must check for cmap != NULL and entries != 0
- format dd ? ;uint_32 ;= image->format
- channels dd ? ;int
- afirst dd 0
- bgr dd 0
- num_trans dd 0
- palette rb 256*sizeof.png_color
- tRNS rb 256 ;byte[]
-endl
-pushad
- mov edx,[display]
- mov ebx,[edx+png_image_write_control.image]
- mov [image],ebx
- mov eax,[edx+png_image_write_control.colormap]
- mov [cmap],eax
- mov eax,[ebx+png_image.colormap_entries]
- cmp eax,256
- jle @f
- mov eax,256
- @@:
- mov [entries],eax
- mov ecx,[ebx+png_image.format]
- mov [format],ecx
- PNG_IMAGE_SAMPLE_CHANNELS ecx
- mov [channels],eax
-
-if (PNG_FORMAT_BGR_SUPPORTED eq 1) & (PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED eq 1)
- mov eax,ecx
- and eax,PNG_FORMAT_FLAG_AFIRST
- jz @f
- mov eax,ecx
- and eax,PNG_FORMAT_FLAG_ALPHA
- jz @f
- mov dword[afirst],-1
- @@:
-end if
-
-if PNG_FORMAT_BGR_SUPPORTED eq 1
- mov eax,ecx
- and eax,PNG_FORMAT_FLAG_BGR
- jz @f
- mov dword[bgr],2
- @@:
-end if
-
-; int i;
-
- xor eax,eax
- mov ecx,(256*sizeof.png_color)/4
- mov edi,ebp
- sub edi,256+256*sizeof.png_color
- rep stosd ;memset(palette, 0, ...
- not eax
- mov ecx,256/4
- ;;mov edi,ebp ;if 'tRNS' after 'palette' this code can be comment
- ;;sub edi,256
- rep stosd ;memset(tRNS, 255, ...
-
-
-; for (i=num_trans=0; i= 3) /* RGB */
-; {
-; palette[i].blue = (byte)PNG_sRGB_FROM_LINEAR(255 *
-; entry[(2 ^ bgr)]);
-; palette[i].green = (byte)PNG_sRGB_FROM_LINEAR(255 *
-; entry[1]);
-; palette[i].red = (byte)PNG_sRGB_FROM_LINEAR(255 *
-; entry[bgr]);
-; }
-
-; else /* Gray */
-; palette[i].blue = palette[i].red = palette[i].green =
-; (byte)PNG_sRGB_FROM_LINEAR(255 * *entry);
-; }
-
-; else /* alpha */
-; {
-; uint_16 alpha = entry[afirst ? 0 : channels-1];
-; byte alphabyte = (byte)PNG_DIV257(alpha);
-; uint_32 reciprocal = 0;
-
- ; Calculate a reciprocal, as in the png_write_image_8bit code above
- ; this is designed to produce a value scaled to 255*65535 when
- ; divided by 128 (i.e. asr 7).
-
-; if (alphabyte > 0 && alphabyte < 255)
-; reciprocal = (((0xffff*0xff)<<7)+(alpha>>1))/alpha;
-
-; tRNS[i] = alphabyte;
-; if (alphabyte < 255)
-; num_trans = i+1;
-
-; if (channels >= 3) /* RGB */
-; {
-; palette[i].blue = png_unpremultiply(entry[afirst + (2 ^ bgr)],
-; alpha, reciprocal);
-; palette[i].green = png_unpremultiply(entry[afirst + 1], alpha,
-; reciprocal);
-; palette[i].red = png_unpremultiply(entry[afirst + bgr], alpha,
-; reciprocal);
-; }
-
-; else /* gray */
-; palette[i].blue = palette[i].red = palette[i].green =
-; png_unpremultiply(entry[afirst], alpha, reciprocal);
-; }
-; }
-
-; else /* Color-map has sRGB values */
-; {
-; bytep entry = cmap;
-
-; entry += i * channels;
-
-; switch (channels)
-; {
-; case 4:
-; tRNS[i] = entry[afirst ? 0 : 3];
-; if (tRNS[i] < 255)
-; num_trans = i+1;
-; /* FALL THROUGH */
-; case 3:
-; palette[i].blue = entry[afirst + (2 ^ bgr)];
-; palette[i].green = entry[afirst + 1];
-; palette[i].red = entry[afirst + bgr];
-; break;
-
-; case 2:
-; tRNS[i] = entry[1 ^ afirst];
-; if (tRNS[i] < 255)
-; num_trans = i+1;
-; /* FALL THROUGH */
-; case 1:
-; palette[i].blue = palette[i].red = palette[i].green =
-; entry[afirst];
-; break;
-
-; default:
-; break;
-; }
-; }
-; }
-
- mov ecx,[ebx+png_image.opaque]
- mov eax,ebp
- sub eax,256+256*sizeof.png_color
- stdcall png_set_PLTE, [ecx+png_control.png_ptr], [ecx+png_control.info_ptr], eax, [entries]
-
- cmp dword[num_trans],0
- jle @f ;if (..>0)
- mov eax,ebp
- sub eax,256
- stdcall png_set_tRNS, [ecx+png_control.png_ptr], [ecx+png_control.info_ptr], eax, [num_trans], 0
- @@:
-
- mov eax,[entries]
- mov [ebx+png_image.colormap_entries],eax
-popad
- ret
-endp
-
-;int (voidp argument)
-align 4
-proc png_image_write_main uses ebx ecx edx esi edi, argument:dword
-locals
- display dd ? ;= png_image_write_control * = argument
- image dd ? ;= display->image
- png_ptr dd ? ;= image->opaque->png_ptr
- info_ptr dd ? ;= image->opaque->info_ptr
- format dd ? ;= image->format
-
- colormap dd ?
- linear dd ?
- alpha dd ?
- write_16bit dd ? ;= linear && !colormap && (display->convert_to_8bit == 0)
-endl
- mov edx,[argument]
- mov [display],edx
- mov ebx,[edx+png_image_write_control.image]
- mov [image],ebx
- mov ecx,[ebx+png_image.format]
- mov [format],ecx
- mov eax,[ebx+png_image.opaque]
- mov edi,[eax+png_control.png_ptr]
- mov [png_ptr],edi
- mov esi,[eax+png_control.info_ptr]
- mov [info_ptr],esi
-
- ; The following four ints are actually booleans
- and ecx,PNG_FORMAT_FLAG_COLORMAP
- mov [colormap],ecx
- not ecx
- mov eax,[format]
- and eax,PNG_FORMAT_FLAG_LINEAR
- mov [linear],eax
- mov eax,[format]
- and eax,ecx
- and eax,PNG_FORMAT_FLAG_ALPHA
- and eax,ecx
- mov [alpha],eax
- xor eax,eax ;false
- cmp dword[edx+png_image_write_control.convert_to_8bit],0
- jne @f
- not eax ;true
- @@:
- and eax,[linear]
- and eax,ecx
- mov [write_16bit],eax
-
-if PNG_BENIGN_ERRORS_SUPPORTED eq 1
- ; Make sure we error out on any bad situation
- stdcall png_set_benign_errors, edi, 0 ;error
-end if
-
- ; Default the 'row_stride' parameter if required, also check the row stride
- ; and total image size to ensure that they are within the system limits.
-
- PNG_IMAGE_PIXEL_CHANNELS [ebx+png_image.format]
- ;eax = channels
-
- push edx
- mov ecx,eax
- mov eax,0x7FFFFFFF
- xor edx,edx
- div ecx
- pop edx
- cmp [ebx+png_image.width],eax
- jg .end0 ;if (..<=..) ;no overflow
- imul ecx,[ebx+png_image.width]
-
- cmp dword[edx+png_image_write_control.row_stride],0
- jne @f ;if (..==0)
- mov [edx+png_image_write_control.row_stride],ecx
- @@:
- mov eax,[edx+png_image_write_control.row_stride]
- cmp eax,0
- jge .end2 ;if (..<0)
- neg eax
- inc eax
- .end2:
-
- cmp eax,ecx
- jl .end3 ;if (..>=..)
- ; Now check for overflow of the image buffer calculation; this
- ; limits the whole image size to 32 bits for API compatibility with
- ; the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro.
-
- push edx
- mov eax,0xFFFFFFFF
- xor edx,edx
- div ecx
- pop edx
- cmp [ebx+png_image.height],eax
- jle @f ;if (..>..)
- mov eax,[ebx+png_image.opaque]
- mov eax,[eax+png_control.png_ptr]
- png_error eax, 'memory image too large'
- @@:
- jmp .end1
- .end3: ;else
- mov eax,[ebx+png_image.opaque]
- mov eax,[eax+png_control.png_ptr]
- png_error eax, 'supplied row stride too small'
- jmp .end1
- .end0: ;else
- mov eax,[ebx+png_image.opaque]
- mov eax,[eax+png_control.png_ptr]
- png_error eax, 'image row stride too large'
- .end1:
-
- ; Set the required transforms then write the rows in the correct order.
- mov eax,[format]
- and eax,PNG_FORMAT_FLAG_COLORMAP
- jz .end4 ;if (..!=0)
- cmp dword[edx+png_image_write_control.colormap],0
- je .end6
- mov eax,[ebx+png_image.colormap_entries]
- cmp eax,0
- jle .end6 ;if (..!=0 && ..>0)
- ;eax = entries
- xor ecx,ecx
- inc ecx ;=1
- cmp eax,2
- jle @f
- shl ecx,1 ;=2
- cmp eax,4
- jle @f
- shl ecx,1 ;=4
- cmp eax,16
- jle @f
- shl ecx,1 ;=8
- @@:
- stdcall png_set_IHDR, edi, esi, [ebx+png_image.width], [ebx+png_image.height],\
- ecx, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,\
- PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE
-
- stdcall png_image_set_PLTE, edx
- jmp .end5
- .end6: ;else
- mov eax,[ebx+png_image.opaque]
- mov eax,[eax+png_control.png_ptr]
- png_error eax, 'no color-map for color-mapped image'
- jmp .end5
- .end4: ;else
- xor ecx,ecx
- mov eax,[format]
- and eax,PNG_FORMAT_FLAG_COLOR
- jz @f
- or ecx,PNG_COLOR_MASK_COLOR
- @@:
- mov eax,[format]
- and eax,PNG_FORMAT_FLAG_ALPHA
- jz @f
- or ecx,PNG_COLOR_MASK_ALPHA
- @@:
- mov eax,8
- cmp dword[write_16bit],0
- je @f
- mov eax,16
- @@:
- stdcall png_set_IHDR, edi, esi, [ebx+png_image.width], [ebx+png_image.height],\
- eax, ecx, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE
- .end5:
-
- ; Counter-intuitively the data transformations must be called *after*
- ; png_write_info, not before as in the read code, but the 'set' functions
- ; must still be called before. Just set the color space information, never
- ; write an interlaced image.
-
- cmp dword[write_16bit],0
- je @f ;if (..!=0)
- ; The gamma here is 1.0 (linear) and the cHRM chunk matches sRGB.
- stdcall png_set_gAMA_fixed, edi, esi, PNG_GAMMA_LINEAR
-
- mov eax,[ebx+png_image.flags]
- and eax,PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB
- jnz @f ;if (..==0)
- stdcall png_set_cHRM_fixed, edi, esi,\
- 31270, 32900,\ ;white
- 64000, 33000,\ ;red
- 30000, 60000,\ ;green
- 15000, 6000 ;blue
- jmp .end7
- @@:
- mov eax,[ebx+png_image.flags]
- and eax,PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB
- jnz @f ;else if (..==0)
- stdcall png_set_sRGB, edi, esi, PNG_sRGB_INTENT_PERCEPTUAL
- jmp .end7
- @@: ;else
- ; Else writing an 8-bit file and the *colors* aren't sRGB, but the 8-bit
- ; space must still be gamma encoded.
- stdcall png_set_gAMA_fixed, edi, esi, PNG_GAMMA_sRGB_INVERSE
- .end7:
-
- ; Write the file header.
- stdcall png_write_info, edi, esi
-
- ; Now set up the data transformations (*after* the header is written),
- ; remove the handled transformations from the 'format' flags for checking.
-
- ; First check for a little endian system if writing 16-bit files.
-
- cmp dword[write_16bit],0
- je @f ;if (..!=0)
-; uint_16 le = 0x0001;
-
-; if ((*(bytep) & le) != 0)
- stdcall png_set_swap, edi
- @@:
-
-if PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED eq 1
- mov eax,[format]
- and eax,PNG_FORMAT_FLAG_BGR
- jz .end12 ;if (..!=0)
- cmp dword[colormap],0
- jne @f
- mov eax,[format]
- and eax,PNG_FORMAT_FLAG_COLOR
- jz @f ;if (..==0 && ..!=0)
- stdcall png_set_bgr, edi
- @@:
- and dword[format], not PNG_FORMAT_FLAG_BGR
- .end12:
-end if
-
-if PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED eq 1
- mov eax,[format]
- and eax,PNG_FORMAT_FLAG_AFIRST
- jz .end13 ;if (..!=0)
- cmp dword[colormap],0
- jne @f
- mov eax,[format]
- and eax,PNG_FORMAT_FLAG_ALPHA
- jz @f ;if (..==0 && ..!=0)
- stdcall png_set_swap_alpha, edi
- @@:
- and dword[format], not PNG_FORMAT_FLAG_AFIRST
- .end13:
-end if
-
- ; If there are 16 or fewer color-map entries we wrote a lower bit depth
- ; above, but the application data is still byte packed.
-
- cmp dword[colormap],0
- je @f
- cmp dword[ebx+png_image.colormap_entries],16
- jg @f ;if (..!=0 && ..<=16)
- stdcall png_set_packing, edi
- @@:
-
- ; That should have handled all (both) the transforms.
- mov eax,[format]
- and eax, not (PNG_FORMAT_FLAG_COLOR or PNG_FORMAT_FLAG_LINEAR or PNG_FORMAT_FLAG_ALPHA or PNG_FORMAT_FLAG_COLORMAP)
- jz @f ;if (..!=0)
- png_error edi, 'png_write_image: unsupported transformation'
- @@:
-
- push esi
- ;ecx - row ;bytep
- ;esi - row_bytes
- mov ecx,[edx+png_image_write_control.buffer]
- mov esi,[edx+png_image_write_control.row_stride]
-
- cmp dword[linear],0
- je @f ;if (..!=0)
- shl esi,1 ;*= sizeof.uint_16
- @@:
- cmp esi,0
- jge @f ;if (..<0)
- mov eax,[ebx+png_image.height]
- dec eax
- imul eax,esi
- sub ecx,eax
- @@:
- mov [edx+png_image_write_control.first_row],ecx
- mov [edx+png_image_write_control.row_bytes],esi
- pop esi
-
- ; Apply 'fast' options if the flag is set.
- mov eax,[ebx+png_image.flags]
- and eax,PNG_IMAGE_FLAG_FAST
- jz @f ;if (..!=0)
- stdcall png_set_filter, edi, PNG_FILTER_TYPE_BASE, PNG_NO_FILTERS
- ; NOTE: determined by experiment using pngstest, this reflects some
- ; balance between the time to write the image once and the time to read
- ; it about 50 times. The speed-up in pngstest was about 10-20% of the
- ; total (user) time on a heavily loaded system.
-
-if PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED eq 1
- stdcall png_set_compression_level, edi, 3
-end if
- @@:
-
- ; Check for the cases that currently require a pre-transform on the row
- ; before it is written. This only applies when the input is 16-bit and
- ; either there is an alpha channel or it is converted to 8-bit.
-
- cmp dword[linear],0
- je @f
- cmp dword[alpha],0
- je @f
- jmp .end10
- @@:
- cmp dword[colormap],0
- jne .end9
- cmp dword[edx+png_image_write_control.convert_to_8bit],0
- je .end9
- .end10: ;if ((..!=0 && ..!=0 ) || (..==0 && ..!=0))
- stdcall png_get_rowbytes, edi, esi
- stdcall png_malloc, edi, eax
- mov ecx,eax ;ecx = row
-
- mov [edx+png_image_write_control.local_row],ecx
- cmp dword[write_16bit],0
- je @f ;if (..!=0)
- stdcall png_safe_execute, ebx, png_write_image_16bit, edx
- jmp .end11
- @@: ;else
- stdcall png_safe_execute, ebx, png_write_image_8bit, edx
- .end11:
- mov dword[edx+png_image_write_control.local_row],0
-
- stdcall png_free, edi, ecx
-
- ; Skip the 'write_end' on error:
- test eax,eax
- jz .end_f ;if (..==0) return 0
- jmp .end8
-
- ; Otherwise this is the case where the input is in a format currently
- ; supported by the rest of the libpng write code; call it directly.
-
- .end9: ;else
-if 1 ;;; IDAT compress all (only 24 bit)
- cmp dword[ebx+png_image.height],1
- jl .end8
- mov ecx,[edx+png_image_write_control.row_bytes]
- inc ecx
- imul ecx,[ebx+png_image.height]
- stdcall create_compress_IDAT, edi, [edx+png_image_write_control.first_row], ecx, [ebx+png_image.width], [ebx+png_image.height]
-else ;;; IDAT compress by lines
- mov ecx,[ebx+png_image.height]
- cmp ecx,1
- jl .end8
- mov eax,[edx+png_image_write_control.first_row]
- mov ebx,[edx+png_image_write_control.row_bytes]
- @@:
- stdcall png_write_row, edi, eax
- add eax, ebx
- loop @b
-end if
- .end8:
-
- stdcall png_write_end, edi, esi
- xor eax,eax
- inc eax
-.end_f:
- ret
-endp
-
-align 16
-proc create_compress_IDAT, png_ptr:dword, buf:dword, len:dword, width:dword, height:dword
-locals
- m1 dd ? ;memory for compress IDAT
- buf_f dd ? ;memory for IDAT
- mins dd ? ;minimum sum
-endl
-pushad
- mov edi,[png_ptr]
-png_debug 1, 'IDAT compress all'
-
- ;create buffer with filters
- stdcall png_zalloc, edi, 1, [len]
- test eax,eax
- jz .end_f
- mov [buf_f],eax
-
- mov eax,ZLIB_IO_MAX
- cmp eax,[len]
- jge @f
- mov eax,[len]
- @@:
- stdcall png_zalloc, edi, 1, eax
- test eax,eax
- jz .end0
- mov [m1],eax
-
- ;init buffer with filters
- mov ebx,[width]
- mov edx,[height]
- mov edi,[buf_f]
- mov esi,[buf]
- .cycle0:
- cmp edx,1
- jl .cycle0end
- mov ecx,ebx
- xor al,al
- stosb ;insert filter (0 - none)
-align 4
- .cycle1:
- lodsb ;1
- inc edi ;
- movsb ;2
- stosb ;3
- lodsb ;
- mov [edi-3],al
- loop .cycle1
- dec edx
- jmp .cycle0
- .cycle0end:
-
- ;make filters
- mov edx,[height]
- mov esi,[width]
- imul esi,3 ;esi - rowbytes
-
- inc esi
- mov edi,[png_ptr]
- cmp dword[edi+png_struct.try_row],0
- jne @f ;if (..==0)
- stdcall png_malloc, edi, esi
- mov [edi+png_struct.try_row],eax
- @@:
- cmp dword[edi+png_struct.tst_row],0
- jne @f ;if (..==0)
- stdcall png_malloc, edi, esi
- mov [edi+png_struct.tst_row],eax
- @@:
- dec esi
-
- mov edi,[buf_f]
- add edi,[len]
- .cycle3:
- dec edx
- cmp edx,1
- jl .cycle3end
- sub edi,esi
- dec edi ;move in perv row
-
- ;init pointers for function png_setup_up_row
- mov ebx,[png_ptr]
- mov [ebx+png_struct.row_buf],edi
- mov [ebx+png_struct.prev_row],edi
- sub [ebx+png_struct.prev_row],esi
- dec dword[ebx+png_struct.prev_row]
-
- ;calculate start minimum sum
- push esi
- xor eax,eax
- xor ebx,ebx
- mov ecx,esi
- mov esi,edi
- inc esi
- .cycle2:
- lodsb
- png_setup_abs ebx
- loop .cycle2
- pop esi
- mov [mins],ebx
-
- push edx
- mov edx,[png_ptr]
- mov eax,[edx+png_struct.tst_row]
- mov byte[eax],0 ;not filter
-
- ; Up filter
- stdcall png_setup_up_row, edx, esi, [mins]
- cmp eax,[mins]
- jge @f ;if (..<..)
- mov [mins],eax
- stdcall copy_row_mins, [edx+png_struct.tst_row], [edx+png_struct.try_row]
- @@:
-
- ; Find out how many bytes offset each pixel is
- movzx ebx,byte[edx+png_struct.pixel_depth]
- add ebx,7
- shr ebx,3
-
- ; Sub filter
- stdcall png_setup_sub_row, edx, ebx, esi, [mins]
- cmp eax,[mins]
- jge @f ;if (..<..)
- mov [mins],eax
- stdcall copy_row_mins, [edx+png_struct.tst_row], [edx+png_struct.try_row]
- @@:
-
- ; Avg filter
- stdcall png_setup_avg_row, edx, ebx, esi, [mins]
- cmp eax,[mins]
- jge @f ;if (..<..)
- mov [mins],eax
- stdcall copy_row_mins, [edx+png_struct.tst_row], [edx+png_struct.try_row]
- @@:
-
- ; Paeth filter
- stdcall png_setup_paeth_row, edx, ebx, esi, [mins]
- cmp eax,[mins]
- jge @f ;if (..<..)
- mov [mins],eax
- stdcall copy_row_mins, [edx+png_struct.tst_row], [edx+png_struct.try_row]
- @@:
-
- ; Copy best row
- mov eax,[edx+png_struct.tst_row]
- cmp byte[eax],0
- je @f
- stdcall copy_row_mins, edi, [edx+png_struct.tst_row]
- @@:
- pop edx
- jmp .cycle3
- .cycle3end:
-
- mov edi,[png_ptr]
- mov esi,edi
- add esi,png_struct.zstream
- stdcall [deflateInit2], esi,\
- -1, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY
-
- mov eax,[buf_f]
- mov [edi+png_struct.zstream.next_in],eax
- mov eax,[len]
- mov [edi+png_struct.zstream.avail_in],eax
- mov eax,[m1]
- mov [edi+png_struct.zstream.next_out],eax
- xor ecx,ecx
-align 4
- .cycle4:
- mov dword[edi+png_struct.zstream.avail_out],16*1024
-
- stdcall [deflate], esi, Z_FINISH ;Z_NO_FLUSH
- cmp eax,Z_STREAM_ERROR
- je .end1
-
- add ecx,16*1024
- sub ecx,[edi+png_struct.zstream.avail_out]
- cmp dword[edi+png_struct.zstream.avail_out],0
- je .cycle4 ;while (strm.avail_out == 0)
-if 0
- mov dword[edi+png_struct.zstream.avail_out],16*1024
- stdcall [deflate], esi, Z_FINISH
- add ecx,16*1024
- sub ecx,[edi+png_struct.zstream.avail_out]
- cmp eax,Z_STREAM_ERROR
- je .end1
-end if
- stdcall [deflateEnd], esi
-
-if PNG_WRITE_OPTIMIZE_CMF_SUPPORTED eq 1
- mov eax,[edi+png_struct.mode]
- and eax,PNG_HAVE_IDAT
- jnz @f
- cmp byte[edi+png_struct.compression_type],PNG_COMPRESSION_TYPE_BASE
- jne @f ;if (..==0 && ..==..)
- stdcall png_image_size, edi
- stdcall optimize_cmf, [m1], eax
- @@:
-end if
- stdcall png_write_complete_chunk, edi, png_IDAT, [m1], ecx
- or dword[edi+png_struct.mode],PNG_HAVE_IDAT
-
- jmp @f
- .end1:
- png_debug 1, 'Z_STREAM_ERROR'
- @@:
-
- ;free memory
- cmp dword[edi+png_struct.try_row],0
- je @f ;if (..!=0)
- stdcall png_free, edi, [edi+png_struct.try_row]
- mov dword[edi+png_struct.try_row],0
- @@:
- cmp dword[edi+png_struct.tst_row],0
- je @f ;if (..!=0)
- stdcall png_free, edi, [edi+png_struct.tst_row]
- mov dword[edi+png_struct.tst_row],0
- @@:
- stdcall png_free, edi, [m1]
-.end0:
- stdcall png_free, edi, [buf_f]
-.end_f:
-popad
- ret
-endp
-
-;input:
-; esi - rowbytes
-align 4
-proc copy_row_mins uses edi esi, dest:dword, sour:dword
- mov ecx,esi
- inc ecx
- mov edi,[dest]
- mov esi,[sour]
- rep movsb
- ret
-endp
-
-;void (png_structp png_ptr, bytep/*const*/ data, png_size_t size)
-align 4
-proc image_memory_write uses eax ebx ecx edi esi, png_ptr:dword, p2data:dword, size:dword
- mov edi,[png_ptr]
- mov esi,[edi+png_struct.io_ptr] ;esi = png_image_write_control *display
- mov ebx,[esi+png_image_write_control.output_bytes] ;ebx = ob
-
- ; Check for overflow; this should never happen:
- mov eax,PNG_SIZE_MAX
- sub eax,ebx
- mov ecx,[size]
- cmp ecx,eax
- jg .end1 ;if (..<=..)
- ; I don't think libpng ever does this, but just in case:
- cmp ecx,0
- jle .end0 ;if (..>0)
- mov eax,ebx
- add eax,ecx
- cmp [esi+png_image_write_control.memory_bytes],eax
- jl @f ;if (..>=..) ;writing
- push esi
- mov edi,[esi+png_image_write_control.memory]
- add edi,ebx
- mov esi,[p2data]
- rep movsb ;memcpy(...
- pop esi
- @@:
-
- ; Always update the size:
- add ebx,[size]
- mov [esi+png_image_write_control.output_bytes],ebx
- .end0:
- jmp .end2
- .end1: ;else
- png_error edi, 'png_image_write_to_memory: PNG too big'
- .end2:
- ret
-endp
-
-;void (png_structp png_ptr)
-align 4
-proc image_memory_flush, png_ptr:dword
- ret
-endp
-
-;int (voidp argument)
-align 4
-proc png_image_write_memory uses ebx, argument:dword
- ; The rest of the memory-specific init and write_main in an error protected
- ; environment. This case needs to use callbacks for the write operations
- ; since libpng has no built in support for writing to memory.
-
- mov eax,[argument]
- mov ebx,[eax+png_image_write_control.image]
- mov ebx,[ebx+png_image.opaque]
- stdcall png_set_write_fn, [ebx+png_control.png_ptr], eax, image_memory_write, image_memory_flush
-
- stdcall png_image_write_main, [argument]
- ret
-endp
-
-;int (png_imagep image, void *memory,
-; png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8bit,
-; const void *buffer, int_32 row_stride, const void *colormap)
-align 4
-proc png_image_write_to_memory uses ebx ecx edx edi esi, image:dword, memory:dword,\
- memory_bytes:dword, convert_to_8bit:dword, buffer:dword, row_stride:dword, colormap:dword
-locals
- display png_image_write_control ;local struct
-endl
-;edi - display png_image_write_control
-
- ; Write the image to the given buffer, or count the bytes if it is NULL
- mov ebx,[image]
- cmp ebx,0
- je .end0
- cmp dword[ebx+png_image.version],PNG_IMAGE_VERSION
- jne .end0 ;if (..!=0 && ..==..)
- cmp dword[memory_bytes],0
- je .end2
- cmp dword[buffer],0
- je .end2 ;if (..!=0 && ..!=0)
- ; This is to give the caller an easier error detection in the NULL
- ; case and guard against uninitialized variable problems:
-
- cmp dword[memory],0
- jne @f ;if(..==0)
- mov eax,[memory_bytes]
- mov dword[eax],0
- @@:
-
- stdcall png_image_write_init, ebx
- test eax,eax
- jz .end3 ;if (..!=0)
- mov ecx,sizeof.png_image_write_control
- mov edi,ebp
- sub edi,ecx
- xor eax,eax
- rep stosb ;memset(&display, 0, sizeof.display))
- sub edi,sizeof.png_image_write_control
- mov [edi+png_image_write_control.image],ebx
- mov eax,[buffer]
- mov [edi+png_image_write_control.buffer],eax
- mov eax,[row_stride]
- mov [edi+png_image_write_control.row_stride],eax
- mov eax,[colormap]
- mov [edi+png_image_write_control.colormap],eax
- mov eax,[convert_to_8bit]
- mov [edi+png_image_write_control.convert_to_8bit],eax
- mov eax,[memory]
- mov [edi+png_image_write_control.memory],eax
- mov eax,[memory_bytes]
- mov eax,[eax]
- mov [edi+png_image_write_control.memory_bytes],eax
- mov dword[edi+png_image_write_control.output_bytes], 0
-
- stdcall png_safe_execute, ebx, png_image_write_memory, edi
- mov ecx,eax ;ecx = result
- stdcall png_image_free, ebx
-
- ; write_memory returns true even if we ran out of buffer.
- cmp ecx,0 ;if (..)
- je .end4
- ; On out-of-buffer this function returns '0' but still updates
- ; memory_bytes:
-
- mov edx,[edi+png_image_write_control.output_bytes]
- mov eax,[memory_bytes]
- cmp dword[memory],0
- je @f ;if (..!=0 && ..>..)
- cmp edx,[eax]
- jle @f
- xor ecx,ecx
- @@:
- mov [eax],edx
- .end4:
-
- mov eax,ecx
- jmp .end_f
- .end3: ;else
- xor eax,eax
- jmp .end_f
- .end2: ;else
- std_png_image_error ebx, 'png_image_write_to_memory: invalid argument'
- jmp .end_f
- .end0:
- cmp ebx,0
- je .end1 ;else if (..!=0)
- std_png_image_error ebx, 'png_image_write_to_memory: incorrect PNG_IMAGE_VERSION'
- jmp .end_f
- .end1: ;else
- xor eax,eax
-.end_f:
- ret
-endp
-
-;int (png_imagep image, FILE *file, int convert_to_8bit,
-; const void *buffer, int_32 row_stride, const void *colormap)
-align 4
-proc png_image_write_to_stdio, image:dword, file:dword, convert_to_8bit:dword, buffer:dword, row_stride:dword, colormap:dword
- ; Write the image to the given (FILE*).
-; if (image != NULL && image->version == PNG_IMAGE_VERSION)
-; {
-; if (file != NULL && buffer != NULL)
-; {
-; if (png_image_write_init(image) != 0)
-; {
-; png_image_write_control display;
-; int result;
-
- ; This is slightly evil, but png_init_io doesn't do anything other
- ; than this and we haven't changed the standard IO functions so
- ; this saves a 'safe' function.
-
-; image->opaque->png_ptr->io_ptr = file;
-
-; memset(&display, 0, (sizeof display));
-; display.image = image;
-; display.buffer = buffer;
-; display.row_stride = row_stride;
-; display.colormap = colormap;
-; display.convert_to_8bit = convert_to_8bit;
-
-; result = png_safe_execute(image, png_image_write_main, &display);
-; png_image_free(image);
-; return result;
-; }
-
-; else
-; return 0;
-; }
-
-; else
-; return png_image_error(image,
-; "png_image_write_to_stdio: invalid argument");
-; }
-
-; else if (image != NULL)
-; return png_image_error(image,
-; "png_image_write_to_stdio: incorrect PNG_IMAGE_VERSION");
-
-; else
-; return 0;
- ret
-endp
-
-;int (png_imagep image, const char *file_name,
-; int convert_to_8bit, const void *buffer, int_32 row_stride,
-; const void *colormap)
-align 4
-proc png_image_write_to_file, image:dword, file_name:dword, convert_to_8bit:dword, buffer:dword, row_stride:dword, colormap:dword
- ; Write the image to the named file.
-; if (image != NULL && image->version == PNG_IMAGE_VERSION)
-; {
-; if (file_name != NULL && buffer != NULL)
-; {
-; FILE *fp = fopen(file_name, "wb");
-
-; if (fp != NULL)
-; {
-; if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer,
-; row_stride, colormap) != 0)
-; {
-; int error; /* from fflush/fclose */
-
- ; Make sure the file is flushed correctly.
-; if (fflush(fp) == 0 && ferror(fp) == 0)
-; {
-; if (fclose(fp) == 0)
-; return 1;
-
-; error = errno; /* from fclose */
-; }
-
-; else
-; {
-; error = errno; /* from fflush or ferror */
-; (void)fclose(fp);
-; }
-
-; (void)remove(file_name);
- ; The image has already been cleaned up; this is just used to
- ; set the error (because the original write succeeded).
-
-; return png_image_error(image, strerror(error));
-; }
-
-; else
-; {
- ; Clean up: just the opened file.
-; (void)fclose(fp);
-; (void)remove(file_name);
-; return 0;
-; }
-; }
-
-; else
-; return png_image_error(image, strerror(errno));
-; }
-
-; else
-; return png_image_error(image,
-; "png_image_write_to_file: invalid argument");
-; }
-
-; else if (image != NULL)
-; return png_image_error(image,
-; "png_image_write_to_file: incorrect PNG_IMAGE_VERSION");
-
-; else
-; return 0;
- ret
-endp
-end if ;SIMPLIFIED_WRITE
+
+; pngwrite.asm - general routines to write a PNG file
+
+; Last changed in libpng 1.6.24 [August 4, 2016]
+; Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
+; (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+; (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+
+; This code is released under the libpng license.
+; For conditions of distribution and use, see the disclaimer
+; and license in png.inc
+
+; Write out all the unknown chunks for the current given location
+;void (png_structrp png_ptr, png_const_inforp info_ptr, unsigned int where)
+align 4
+proc write_unknown_chunks, png_ptr:dword, info_ptr:dword, where:dword
+pushad
+ mov esi,[info_ptr]
+ cmp dword[esi+png_info_def.unknown_chunks_num],0
+ je .end_f ;if(..!=0)
+ mov edi,[png_ptr]
+ ;ecx = up
+
+ png_debug 5, 'writing extra chunks'
+
+ mov ecx,[esi+png_info_def.unknown_chunks]
+ mov edx,[esi+png_info_def.unknown_chunks_num]
+ imul edx,sizeof.png_unknown_chunk
+ add edx,ecx
+ .cycle0: ;for (..;..<..;..)
+ cmp ecx,edx
+ jge .end_f
+ movzx eax,byte[ecx+png_unknown_chunk.location]
+ and eax,[where]
+ jz .end0 ;if (..!=0)
+ ; If per-chunk unknown chunk handling is enabled use it, otherwise
+ ; just write the chunks the application has set.
+
+if PNG_SET_UNKNOWN_CHUNKS_SUPPORTED eq 1
+ mov eax,ecx
+ add eax,png_unknown_chunk.name
+ stdcall png_handle_as_unknown, edi, eax
+
+ ; NOTE: this code is radically different from the read side in the
+ ; matter of handling an ancillary unknown chunk. In the read side
+ ; the default behavior is to discard it, in the code below the default
+ ; behavior is to write it. Critical chunks are, however, only
+ ; written if explicitly listed or if the default is set to write all
+ ; unknown chunks.
+
+ ; The default handling is also slightly weird - it is not possible to
+ ; stop the writing of all unsafe-to-copy chunks!
+
+ ; TODO: REVIEW: this would seem to be a bug.
+
+ cmp eax,PNG_HANDLE_CHUNK_NEVER
+ je .end0
+ mov bl,byte[ecx+png_unknown_chunk.name+3]
+ and bl,0x20
+ cmp bl,0
+ jne .beg0
+ cmp eax,PNG_HANDLE_CHUNK_ALWAYS
+ je .beg0
+ cmp eax,PNG_HANDLE_CHUNK_AS_DEFAULT
+ jne .end0
+ cmp dword[edi+png_struct.unknown_default],PNG_HANDLE_CHUNK_ALWAYS
+ jne .end0
+end if
+ .beg0: ;if (..!=.. && (.. safe-to-copy overrides everything || ..==.. || (..==.. && ..==..)))
+ ; TODO: review, what is wrong with a zero length unknown chunk?
+ cmp dword[ecx+png_unknown_chunk.size],0
+ jne @f ;if (..==0)
+ png_warning [png_ptr], 'Writing zero-length unknown chunk'
+ @@:
+ mov eax,dword[ecx+png_unknown_chunk.name]
+ stdcall png_write_chunk, edi, eax, [ecx+png_unknown_chunk.podata], [ecx+png_unknown_chunk.size]
+ .end0:
+ add ecx,sizeof.png_unknown_chunk
+ jmp .cycle0
+ ;.cycle0end:
+.end_f:
+popad
+ ret
+endp
+
+; Writes all the PNG information. This is the suggested way to use the
+; library. If you have a new chunk to add, make a function to write it,
+; and put it in the correct location here. If you want the chunk written
+; after the image data, put it in png_write_end(). I strongly encourage
+; you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing
+; the chunk, as that will keep the code from breaking if you want to just
+; write a plain PNG file. If you have long comments, I suggest writing
+; them in png_write_end(), and compressing them.
+
+;void (png_structrp png_ptr, png_const_inforp info_ptr)
+align 4
+proc png_write_info_before_PLTE, png_ptr:dword, info_ptr:dword
+ png_debug 1, 'in png_write_info_before_PLTE'
+
+pushad
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f
+ mov esi,[info_ptr]
+ cmp esi,0
+ je .end_f ;if(..==0 || ..==0) return
+
+ mov eax,[edi+png_struct.mode]
+ and eax,PNG_WROTE_INFO_BEFORE_PLTE
+ jnz .end_f ;if (..==0)
+
+ ; Write PNG signature
+ stdcall png_write_sig, edi
+
+if PNG_MNG_FEATURES_SUPPORTED eq 1
+ mov eax,[edi+png_struct.mode]
+ and eax,PNG_HAVE_PNG_SIGNATURE
+ jz @f
+ cmp dword[edi+png_struct.mng_features_permitted],0
+ je @f ;if(..!=0 && ..!=0)
+ png_warning edi, 'MNG features are not allowed in a PNG datastream'
+ mov dword[edi+png_struct.mng_features_permitted],0
+ @@:
+end if
+
+ ; Write IHDR information.
+if PNG_WRITE_INTERLACING_SUPPORTED eq 1
+ movzx eax,byte[esi+png_info_def.interlace_type]
+ push eax
+else
+ push dword 0
+end if
+ movzx eax,byte[esi+png_info_def.filter_type]
+ push eax
+ movzx eax,byte[esi+png_info_def.compression_type]
+ push eax
+ movzx eax,byte[esi+png_info_def.color_type]
+ push eax
+ movzx eax,byte[esi+png_info_def.bit_depth]
+ stdcall png_write_IHDR, edi,\
+ dword[esi+png_info_def.width], dword[esi+png_info_def.height], eax
+
+; The rest of these check to see if the valid field has the appropriate
+; flag set, and if it does, writes the chunk.
+
+; 1.6.0: COLORSPACE support controls the writing of these chunks too, and
+; the chunks will be written if the WRITE routine is there and
+; information * is available in the COLORSPACE. (See
+; png_colorspace_sync_info in png.c for where the valid flags get set.)
+
+; Under certain circumstances the colorspace can be invalidated without
+; syncing the info_struct 'valid' flags; this happens if libpng detects
+; an error and calls png_error while the color space is being set, yet
+; the application continues writing the PNG. So check the 'invalid'
+; flag here too.
+
+if PNG_GAMMA_SUPPORTED eq 1
+if PNG_WRITE_gAMA_SUPPORTED eq 1
+ movzx eax,word[esi+png_info_def.colorspace.flags]
+ and eax,PNG_COLORSPACE_INVALID
+ jnz @f
+ movzx eax,word[esi+png_info_def.colorspace.flags]
+ and eax,PNG_COLORSPACE_FROM_gAMA
+ jz @f
+ mov eax,[esi+png_info_def.valid]
+ and eax,PNG_INFO_gAMA
+ jz @f ;if (..==0 && ..!=0 && ..!=0)
+ stdcall png_write_gAMA_fixed, edi, [esi+png_info_def.colorspace.gamma]
+ @@:
+end if
+end if
+
+if PNG_COLORSPACE_SUPPORTED eq 1
+ ; Write only one of sRGB or an ICC profile. If a profile was supplied
+ ; and it matches one of the known sRGB ones issue a warning.
+
+if PNG_WRITE_iCCP_SUPPORTED eq 1
+ movzx eax,word[esi+png_info_def.colorspace.flags]
+ and eax,PNG_COLORSPACE_INVALID
+ jnz .end0
+ mov eax,[esi+png_info_def.valid]
+ and eax,PNG_INFO_iCCP
+ jz .end0 ;if (..==0 && ..!=0)
+if PNG_WRITE_sRGB_SUPPORTED eq 1
+ mov eax,[esi+png_info_def.valid]
+ and eax,PNG_INFO_sRGB
+ jz @f ;if (..!=0)
+ png_app_warning edi, 'profile matches sRGB but writing iCCP instead'
+ @@:
+end if
+ stdcall png_write_iCCP, edi, [esi+png_info_def.iccp_name],\
+ [esi+png_info_def.iccp_profile]
+if PNG_WRITE_sRGB_SUPPORTED eq 1
+ jmp .end1
+end if
+ .end0: ;else
+end if
+
+if PNG_WRITE_sRGB_SUPPORTED eq 1
+ movzx eax,word[esi+png_info_def.colorspace.flags]
+ and eax,PNG_COLORSPACE_INVALID
+ jnz .end1
+ mov eax,[esi+png_info_def.valid]
+ and eax,PNG_INFO_sRGB
+ jz .end1 ;if (..==0 && ..!=0)
+ movzx eax,word[esi+png_info_def.colorspace.rendering_intent]
+ stdcall png_write_sRGB, edi, eax
+ .end1:
+end if ;sRGB
+end if ;COLORSPACE
+
+if PNG_WRITE_sBIT_SUPPORTED eq 1
+ mov eax,[esi+png_info_def.valid]
+ and eax,PNG_INFO_sBIT
+ jz @f ;if (..!=0)
+ movzx eax,byte[esi+png_info_def.color_type]
+ push eax
+ mov eax,esi
+ add eax,png_info_def.sig_bit
+ stdcall png_write_sBIT, edi, eax ;, ...color_type
+ @@:
+end if
+
+if PNG_COLORSPACE_SUPPORTED eq 1
+if PNG_WRITE_cHRM_SUPPORTED eq 1
+ movzx eax,word[esi+png_info_def.colorspace.flags]
+ and eax,PNG_COLORSPACE_INVALID
+ jnz @f
+ movzx eax,word[esi+png_info_def.colorspace.flags]
+ and eax,PNG_COLORSPACE_FROM_cHRM
+ jz @f
+ mov eax,[esi+png_info_def.valid]
+ and eax,PNG_INFO_cHRM
+ jz @f ;if (..==0 && ..!=0 && ..!=0)
+ stdcall png_write_cHRM_fixed, edi, [esi+png_info_def.colorspace.end_points_xy]
+ @@:
+end if
+end if
+
+if PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED eq 1
+ stdcall write_unknown_chunks, edi, esi, PNG_HAVE_IHDR
+end if
+ or dword[edi+png_struct.mode],PNG_WROTE_INFO_BEFORE_PLTE
+ .end_f:
+popad
+ ret
+endp
+
+;void (png_structrp png_ptr, png_const_inforp info_ptr)
+align 4
+proc png_write_info, png_ptr:dword, info_ptr:dword
+if (PNG_WRITE_TEXT_SUPPORTED eq 1) | (PNG_WRITE_sPLT_SUPPORTED eq 1)
+; int i;
+end if
+pushad
+ png_debug 1, 'in png_write_info'
+
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f
+ mov esi,[info_ptr]
+ cmp esi,0
+ je .end_f ;if (..==0 || ..==0) return
+
+ stdcall png_write_info_before_PLTE, edi, esi
+
+ mov eax,[esi+png_info_def.valid]
+ and eax,PNG_INFO_PLTE
+ jz @f ;if (..!=0)
+ movzx eax,word[esi+png_info_def.num_palette]
+ stdcall png_write_PLTE, edi, [esi+png_info_def.palette], eax
+ jmp .end_0
+ @@:
+ mov al,byte[esi+png_info_def.color_type]
+ cmp al,PNG_COLOR_TYPE_PALETTE
+ jne .end_0 ;else if (..==..)
+ png_error edi, 'Valid palette required for paletted images'
+ .end_0:
+
+if PNG_WRITE_tRNS_SUPPORTED eq 1
+ mov eax,[esi+png_info_def.valid]
+ and eax,PNG_INFO_tRNS
+ jz .end_1 ;if (..!=0)
+if PNG_WRITE_INVERT_ALPHA_SUPPORTED eq 1
+ ; Invert the alpha channel (in tRNS)
+; if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0 &&
+; info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+; {
+; int j, jend;
+
+; jend = info_ptr->num_trans;
+; if (jend > PNG_MAX_PALETTE_LENGTH)
+; jend = PNG_MAX_PALETTE_LENGTH;
+
+; for (j = 0; jtrans_alpha[j] =
+; (byte)(255 - info_ptr->trans_alpha[j]);
+; }
+end if
+ mov eax,esi
+ add eax,png_info_def.trans_color
+ movzx ebx,word[esi+png_info_def.num_trans]
+ movzx ecx,byte[esi+png_info_def.color_type]
+ stdcall png_write_tRNS, edi, dword[esi+png_info_def.trans_alpha], eax, ebx, ecx
+ .end_1:
+end if
+if PNG_WRITE_bKGD_SUPPORTED eq 1
+ mov eax,[esi+png_info_def.valid]
+ and eax,PNG_INFO_bKGD
+ jz @f ;if (..!=0)
+ mov eax,esi
+ add eax,png_info_def.background
+ movzx ebx,byte[esi+png_info_def.color_type]
+ stdcall png_write_bKGD, edi, eax, ebx
+ @@:
+end if
+
+if PNG_WRITE_hIST_SUPPORTED eq 1
+ mov eax,[esi+png_info_def.valid]
+ and eax,PNG_INFO_hIST
+ jz @f ;if (..!=0)
+ movzx ebx,word[esi+png_info_def.num_palette]
+ stdcall png_write_hIST, edi, [esi+png_info_def.hist], ebx
+ @@:
+end if
+
+if PNG_WRITE_oFFs_SUPPORTED eq 1
+ mov eax,[esi+png_info_def.valid]
+ and eax,PNG_INFO_oFFs
+ jz @f ;if (..!=0)
+ movzx ebx,byte[esi+png_info_def.offset_unit_type]
+ stdcall png_write_oFFs, edi, [esi+png_info_def.x_offset], [esi+png_info_def.y_offset], ebx
+ @@:
+end if
+
+if PNG_WRITE_pCAL_SUPPORTED eq 1
+ mov eax,[esi+png_info_def.valid]
+ and eax,PNG_INFO_pCAL
+ jz @f ;if (..!=0)
+ movzx ebx,byte[esi+png_info_def.pcal_type]
+ movzx ecx,byte[esi+png_info_def.pcal_nparams]
+ stdcall png_write_pCAL, edi, [esi+png_info_def.pcal_purpose], [esi+png_info_def.pcal_X0], [esi+png_info_def.pcal_X1], ebx, ecx, [esi+png_info_def.pcal_units], [esi+png_info_def.pcal_params]
+ @@:
+end if
+
+if PNG_WRITE_sCAL_SUPPORTED eq 1
+ mov eax,[esi+png_info_def.valid]
+ and eax,PNG_INFO_sCAL
+ jz @f ;if (..!=0)
+ movzx ebx,byte[esi+png_info_def.scal_unit]
+ stdcall png_write_sCAL_s, edi, ebx, [esi+png_info_def.scal_s_width], [esi+png_info_def.scal_s_height]
+ @@:
+end if ;sCAL
+
+if PNG_WRITE_pHYs_SUPPORTED eq 1
+ mov eax,[esi+png_info_def.valid]
+ and eax,PNG_INFO_pHYs
+ jz @f ;if (..!=0)
+ movzx ebx,byte[esi+png_info_def.phys_unit_type]
+ stdcall png_write_pHYs, edi, [esi+png_info_def.x_pixels_per_unit], [esi+png_info_def.y_pixels_per_unit], ebx
+ @@:
+end if ;pHYs
+
+if PNG_WRITE_tIME_SUPPORTED eq 1
+ mov eax,[esi+png_info_def.valid]
+ and eax,PNG_INFO_tIME
+ jz @f ;if (..!=0)
+ mov eax,esi
+ add eax,png_info_def.mod_time
+ stdcall png_write_tIME, edi, eax
+ or [edi+png_struct.mode],PNG_WROTE_tIME
+ @@:
+end if ;tIME
+
+if PNG_WRITE_sPLT_SUPPORTED eq 1
+ mov eax,[esi+png_info_def.valid]
+ and eax,PNG_INFO_sPLT
+ jz @f ;if (..!=0)
+ mov eax,[esi+png_info_def.splt_palettes]
+ mov ecx,[esi+png_info_def.splt_palettes_num]
+ cmp ecx,1
+ jl @f
+ .cycle0:
+ stdcall png_write_sPLT, edi, eax
+ add eax,4
+ loop .cycle0
+ @@:
+end if ;sPLT
+
+if PNG_WRITE_TEXT_SUPPORTED eq 1
+ ; Check to see if we need to write text chunks
+; for (i = 0; i < info_ptr->num_text; i++)
+; {
+; png_debug2(2, "Writing header text chunk %d, type %d", i,
+; info_ptr->text[i].compression);
+ ; An internationalized chunk?
+; if (info_ptr->text[i].compression > 0)
+; {
+if PNG_WRITE_iTXt_SUPPORTED eq 1
+ ; Write international chunk
+; png_write_iTXt(png_ptr,
+; info_ptr->text[i].compression,
+; info_ptr->text[i].key,
+; info_ptr->text[i].lang,
+; info_ptr->text[i].lang_key,
+; info_ptr->text[i].text);
+ ; Mark this chunk as written
+; if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
+; info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
+; else
+; info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
+else
+ png_warning edi, 'Unable to write international text'
+end if
+; }
+
+ ; If we want a compressed text chunk
+; else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt)
+; {
+if PNG_WRITE_zTXt_SUPPORTED eq 1
+ ; Write compressed chunk
+; png_write_zTXt(png_ptr, info_ptr->text[i].key,
+; info_ptr->text[i].text, info_ptr->text[i].compression);
+ ; Mark this chunk as written
+; info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
+else
+ png_warning edi, 'Unable to write compressed text'
+end if
+; }
+
+; else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
+; {
+if PNG_WRITE_tEXt_SUPPORTED eq 1
+ ; Write uncompressed chunk
+; png_write_tEXt(png_ptr, info_ptr->text[i].key,
+; info_ptr->text[i].text,
+; 0);
+ ; Mark this chunk as written
+; info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
+else
+ ; Can't get here
+ png_warning edi, 'Unable to write uncompressed text'
+end if
+; }
+; }
+end if ;tEXt
+
+if PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED eq 1
+ stdcall write_unknown_chunks, edi, esi, PNG_HAVE_PLTE
+end if
+ .end_f:
+popad
+ ret
+endp
+
+; Writes the end of the PNG file. If you don't want to write comments or
+; time information, you can pass NULL for info. If you already wrote these
+; in png_write_info(), do not write them again here. If you have long
+; comments, I suggest writing them here, and compressing them.
+
+;void (png_structrp png_ptr, png_inforp info_ptr)
+align 4
+proc png_write_end, png_ptr:dword, info_ptr:dword
+pushad
+ png_debug 1, 'in png_write_end'
+
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f ;if (..==0) return
+
+ mov eax,[edi+png_struct.mode]
+ and eax,PNG_HAVE_IDAT
+ jnz @f ;if (..==0)
+ png_error edi, 'No IDATs written into file'
+ @@:
+
+if PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED eq 1
+ mov eax,[edi+png_struct.num_palette_max]
+ cmp ax,[edi+png_struct.num_palette]
+ jle @f ;if (..>..)
+ png_benign_error edi, 'Wrote palette index exceeding num_palette'
+ @@:
+end if
+
+ ; See if user wants us to write information chunks
+ mov esi,[info_ptr]
+ cmp esi,0
+ je .end0 ;if (..!=0)
+if PNG_WRITE_TEXT_SUPPORTED eq 1
+; int i; /* local index variable */
+end if
+if PNG_WRITE_tIME_SUPPORTED eq 1
+ ; Check to see if user has supplied a time chunk
+ mov eax,[esi+png_info_def.valid]
+ and eax,PNG_INFO_tIME
+ jz @f
+ mov eax,[edi+png_struct.mode]
+ and eax,PNG_WROTE_tIME
+ jnz @f ;if (..!=0 && ..==0)
+ mov eax,esi
+ add eax,png_info_def.mod_time
+ stdcall png_write_tIME, edi, eax
+ @@:
+
+end if
+if PNG_WRITE_TEXT_SUPPORTED eq 1
+ ; Loop through comment chunks
+ cmp dword[esi+png_info_def.num_text],0
+ jle .cycle0end
+ xor ecx,ecx
+align 4
+ .cycle0: ;for (i = 0; i < info_ptr->num_text; i++)
+
+; png_debug2(2, "Writing trailer text chunk %d, type %d", i,
+; info_ptr->text[i].compression);
+ ; An internationalized chunk?
+ mov eax,ecx
+ shl eax,2
+ add eax,[esi+png_info_def.text] ;eax = info_ptr.text[i]
+ cmp dword[eax+png_text.compression],0
+ jle .end1 ;if (info_ptr.text[i].compression > 0)
+if PNG_WRITE_iTXt_SUPPORTED eq 1
+ ; Write international chunk
+ stdcall png_write_iTXt, edi,\
+ [eax+png_text.compression],\
+ [eax+png_text.key],\
+ [eax+png_text.lang],\
+ [eax+png_text.lang_key],\
+ [eax+png_text.text]
+ ; Mark this chunk as written
+ mov ebx,PNG_TEXT_COMPRESSION_zTXt_WR
+ cmp dword[eax+png_text.compression],PNG_TEXT_COMPRESSION_NONE
+ jne @f
+ mov ebx,PNG_TEXT_COMPRESSION_NONE_WR
+ @@:
+ mov dword[eax+png_text.compression],ebx
+else
+ png_warning edi, 'Unable to write international text'
+end if
+ jmp .end3
+ .end1:
+ cmp dword[eax+png_text.compression],PNG_TEXT_COMPRESSION_zTXt
+ jl .end2 ;else if (info_ptr.text[i].compression >= ..)
+if PNG_WRITE_zTXt_SUPPORTED eq 1
+ ; Write compressed chunk
+ stdcall png_write_zTXt, edi, [eax+png_text.key],\
+ [eax+png_text.text], [eax+png_text.compression]
+ ; Mark this chunk as written
+ mov dword[eax+png_text.compression],PNG_TEXT_COMPRESSION_zTXt_WR
+else
+ png_warning edi, 'Unable to write compressed text'
+end if
+ jmp .end3
+ .end2:
+ cmp dword[eax+png_text.compression],PNG_TEXT_COMPRESSION_NONE
+ jl .end3 ;else if (info_ptr.text[i].compression == ..)
+if PNG_WRITE_tEXt_SUPPORTED eq 1
+ ; Write uncompressed chunk
+ stdcall png_write_tEXt, edi, [eax+png_text.key],\
+ [eax+png_text.text], 0
+ ; Mark this chunk as written
+ mov dword[eax+png_text.compression],PNG_TEXT_COMPRESSION_NONE_WR
+else
+ png_warning edi, 'Unable to write uncompressed text'
+end if
+ .end3:
+
+ inc ecx
+ cmp ecx,[esi+png_info_def.num_text]
+ jl .cycle0
+ .cycle0end:
+end if
+if PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED eq 1
+ stdcall write_unknown_chunks, edi, esi, PNG_AFTER_IDAT
+end if
+ .end0:
+
+ or dword[edi+png_struct.mode], PNG_AFTER_IDAT
+
+ ; Write end of PNG file
+ stdcall png_write_IEND, edi
+
+; This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03,
+; and restored again in libpng-1.2.30, may cause some applications that
+; do not set png_ptr->output_flush_fn to crash. If your application
+; experiences a problem, please try building libpng with
+; PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED defined, and report the event to
+; png-mng-implement at lists.sf.net .
+
+if PNG_WRITE_FLUSH_SUPPORTED eq 1
+if PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED eq 1
+ stdcall png_flush, edi
+end if
+end if
+.end_f:
+popad
+ ret
+endp
+
+;void (png_timep ptime, struct tm * ttime)
+align 4
+proc png_convert_from_struct_tm, ptime:dword, ttime:dword
+ png_debug 1, 'in png_convert_from_struct_tm'
+
+; ptime->year = (uint_16)(1900 + ttime->tm_year);
+; ptime->month = (byte)(ttime->tm_mon + 1);
+; ptime->day = (byte)ttime->tm_mday;
+; ptime->hour = (byte)ttime->tm_hour;
+; ptime->minute = (byte)ttime->tm_min;
+; ptime->second = (byte)ttime->tm_sec;
+ ret
+endp
+
+;void (png_timep ptime, time_t ttime)
+align 4
+proc png_convert_from_time_t, ptime:dword, ttime:dword
+; struct tm *tbuf;
+
+ png_debug 1, 'in png_convert_from_time_t'
+
+; tbuf = gmtime(&ttime);
+; png_convert_from_struct_tm(ptime, tbuf);
+ ret
+endp
+
+; Initialize png_ptr structure, and allocate any memory needed
+;png_structp (charp user_png_ver, voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn)
+align 4
+proc png_create_write_struct, user_png_ver:dword, error_ptr:dword, error_fn:dword, warn_fn:dword
+if PNG_USER_MEM_SUPPORTED eq 1
+ stdcall png_create_png_struct, [user_png_ver], [error_ptr], [error_fn], [warn_fn], 0, 0, 0
+ ;eax = png_ptr
+end if ;USER_MEM
+ test eax,eax
+ jz .end0 ;if (..!=0)
+ ; Set the zlib control values to defaults; they can be overridden by the
+ ; application after the struct has been created.
+
+ mov dword[eax+png_struct.zbuffer_size], PNG_ZBUF_SIZE
+
+ ; The 'zlib_strategy' setting is irrelevant because png_default_claim in
+ ; pngwutil.asm defaults it according to whether or not filters will be
+ ; used, and ignores this setting.
+
+ mov dword[eax+png_struct.zlib_strategy], PNG_Z_DEFAULT_STRATEGY
+ mov dword[eax+png_struct.zlib_level], PNG_Z_DEFAULT_COMPRESSION
+ mov dword[eax+png_struct.zlib_mem_level], 8
+ mov dword[eax+png_struct.zlib_window_bits], 15
+ mov dword[eax+png_struct.zlib_method], 8
+
+if PNG_WRITE_COMPRESSED_TEXT_SUPPORTED eq 1
+ mov dword[eax+png_struct.zlib_text_strategy], PNG_TEXT_Z_DEFAULT_STRATEGY
+ mov dword[eax+png_struct.zlib_text_level], PNG_TEXT_Z_DEFAULT_COMPRESSION
+ mov dword[eax+png_struct.zlib_text_mem_level], 8
+ mov dword[eax+png_struct.zlib_text_window_bits], 15
+ mov dword[eax+png_struct.zlib_text_method], 8
+end if
+ ; This is a highly dubious configuration option; by default it is off,
+ ; but it may be appropriate for private builds that are testing
+ ; extensions not conformant to the current specification, or of
+ ; applications that must not fail to write at all costs!
+
+if PNG_BENIGN_WRITE_ERRORS_SUPPORTED eq 1
+ ; In stable builds only warn if an application error can be completely
+ ; handled.
+
+ or dword[eax+png_struct.flags], PNG_FLAG_BENIGN_ERRORS_WARN
+end if
+ ; App warnings are warnings in release (or release candidate) builds but
+ ; are errors during development.
+
+if PNG_RELEASE_BUILD eq 1
+ or dword[eax+png_struct.flags], PNG_FLAG_APP_WARNINGS_WARN
+end if
+ ; TODO: delay this, it can be done in png_init_io() (if the app doesn't
+ ; do it itself) avoiding setting the default function if it is not
+ ; required.
+
+ stdcall png_set_write_fn, eax, 0, 0, 0
+ .end0:
+ ret
+endp
+
+
+; Write a few rows of image data. If the image is interlaced,
+; either you will have to write the 7 sub images, or, if you
+; have called png_set_interlace_handling(), you will have to
+; "write" the image seven times.
+
+;void (png_structrp png_ptr, bytepp row, uint_32 num_rows)
+align 4
+proc png_write_rows uses ebx ecx edi, png_ptr:dword, row:dword, num_rows:dword
+;locals
+ ;i dd ? ;uint_32 ;row counter
+ ;rp dd ? ;bytepp ;row pointer
+;endl
+ png_debug 1, 'in png_write_rows'
+
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f ;if(..==0) return
+
+ ; Loop through the rows
+ mov ecx,[num_rows]
+ cmp ecx,1
+ jl .end_f
+ mov ebx,[row]
+ @@: ;for (i = 0, rp = row; i < num_rows; i++, rp++)
+ stdcall png_write_row, edi, [ebx]
+ add ebx,4
+ loop @b
+.end_f:
+ ret
+endp
+
+; Write the image. You only need to call this function once, even
+; if you are writing an interlaced image.
+
+;void (png_structrp png_ptr, bytepp image)
+align 4
+proc png_write_image, png_ptr:dword, image:dword
+pushad
+;ebx ;bytepp ;points to current row
+;ecx ;uint_32 ;row index
+;edx ;int ;pass
+;esi ;int ;num_pass
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f ;if (..==0) return
+
+ png_debug 1, 'in png_write_image'
+
+if PNG_WRITE_INTERLACING_SUPPORTED eq 1
+ ; Initialize interlace handling. If image is not interlaced,
+ ; this will set pass to 1
+
+ stdcall png_set_interlace_handling, edi
+ mov esi,eax
+else
+ xor esi,esi
+ inc esi
+end if
+ ; Loop through passes
+ xor edx,edx
+ .cycle0: ;for (edx = 0; edx < esi; edx++)
+ cmp edx,esi
+ jge .cycle0end
+ ; Loop through image
+ mov ebx,[image]
+ xor ecx,ecx
+ .cycle1: ;for (ecx = 0, ebx = image; ecx < png_ptr.height; ecx++, ebx++)
+ stdcall png_write_row, edi,[ebx]
+ inc ecx
+ add ebx,4
+ cmp ecx,[edi+png_struct.height]
+ jl .cycle1
+ ;.cycle1end:
+ inc edx
+ jmp .cycle0
+ .cycle0end:
+.end_f:
+popad
+ ret
+endp
+
+; Performs intrapixel differencing
+;void (png_row_infop row_info, bytep row)
+align 4
+proc png_do_write_intrapixel uses eax ebx ecx edx edi, row_info:dword, row:dword
+ png_debug 1, 'in png_do_write_intrapixel'
+
+ mov ebx,[row_info]
+ movzx eax,byte[ebx+png_row_info.color_type]
+ and eax,PNG_COLOR_MASK_COLOR
+ jz .end_f ;if (..!=0)
+ ;edx = bytes_per_pixel
+ mov ecx,[ebx+png_row_info.width] ;ecx = row_width
+ cmp byte[ebx+png_row_info.bit_depth],8 ;if (..==8)
+ jne .end0
+; bytep rp;
+; uint_32 i;
+
+ cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_RGB
+ jne @f ;if (..==..)
+ mov edx,3-1 ;(-1) for stosb
+ jmp .end2
+ @@:
+ cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_RGB_ALPHA
+ jne @f ;else if (..==..)
+ mov edx,4-1 ;(-1) for stosb
+ jmp .end2
+ @@:
+ jmp .end_f ;else return
+ .end2:
+
+ mov edi,[row]
+align 4
+ .cycle0: ;for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
+ mov ax,word[edi]
+ sub al,ah
+ stosb ;*(rp) = (byte)(*rp - *(rp + 1))
+ mov ax,word[edi]
+ sub ah,al
+ mov byte[edi+1],ah ;*(rp + 2) = (byte)(*(rp + 2) - *(rp + 1))
+ add edi,edx
+ loop .cycle0
+ .cycle0end:
+ jmp .end_f
+ .end0:
+
+if PNG_WRITE_16BIT_SUPPORTED eq 1
+ cmp byte[ebx+png_row_info.bit_depth],16 ;else if (..==16)
+ jne .end1
+; bytep rp;
+; uint_32 i;
+
+ cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_RGB
+ jne @f ;if (..==..)
+ mov edx,6
+ jmp .end3
+ @@:
+ cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_RGB_ALPHA
+ jne @f ;else if (..==..)
+ mov edx,8
+ jmp .end3
+ @@:
+ jmp .end_f ;else return
+ .end3:
+
+ mov edi,[row]
+align 4
+ .cycle1: ;for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
+; uint_32 s0 = (*(rp ) << 8) | *(rp + 1);
+; uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3);
+; uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5);
+; uint_32 red = (uint_32)((s0 - s1) & 0xffffL);
+; uint_32 blue = (uint_32)((s2 - s1) & 0xffffL);
+; *(rp ) = (byte)(red >> 8);
+; *(rp + 1) = (byte)red;
+; *(rp + 4) = (byte)(blue >> 8);
+; *(rp + 5) = (byte)blue;
+ add edi,edx
+ loop .cycle1
+ .cycle1end:
+ .end1:
+end if ;WRITE_16BIT
+.end_f:
+ ret
+endp
+
+; Called by user to write a row of image data
+;void (png_structrp png_ptr, bytep row)
+align 4
+proc png_write_row, png_ptr:dword, row:dword
+locals
+ ; 1.5.6: moved from png_struct to be a local structure:
+ row_info png_row_info
+endl
+pushad
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f ;if(..==0) return
+
+; png_debug2(1, "in png_write_row (row %u, pass %d)",
+; png_ptr->row_number, png_ptr->pass);
+png_debug1 1, 'in png_write_row (row %u)',[edi+png_struct.row_number]
+
+ ; Initialize transformations and other stuff if first time
+ cmp dword[edi+png_struct.row_number],0
+ jne .end0
+ cmp byte[edi+png_struct.pass],0
+ jne .end0 ;if(..==0 && ..==0)
+
+ ; Make sure we wrote the header info
+ mov eax,[edi+png_struct.mode]
+ and eax,PNG_WROTE_INFO_BEFORE_PLTE
+ jnz @f ;if(..==0)
+ png_error edi, 'png_write_info was never called before png_write_row'
+ @@:
+
+ ; Check for transforms that have been set but were defined out
+if (PNG_WRITE_INVERT_SUPPORTED eq 0) & (PNG_READ_INVERT_SUPPORTED eq 1)
+ mov eax,[edi+png_struct.transformations]
+ and eax,PNG_INVERT_MONO
+ jz @f ;if(..!=0)
+ png_warning edi, 'PNG_WRITE_INVERT_SUPPORTED is not defined'
+ @@:
+end if
+
+if (PNG_WRITE_FILLER_SUPPORTED eq 0) & (PNG_READ_FILLER_SUPPORTED eq 1)
+ mov eax,[edi+png_struct.transformations]
+ and eax,PNG_FILLER
+ jz @f ;if(..!=0)
+ png_warning edi, 'PNG_WRITE_FILLER_SUPPORTED is not defined'
+ @@:
+end if
+
+if (PNG_WRITE_PACKSWAP_SUPPORTED eq 0) & (PNG_READ_PACKSWAP_SUPPORTED eq 1)
+ mov eax,[edi+png_struct.transformations]
+ and eax,PNG_PACKSWAP
+ jz @f ;if(..!=0)
+ png_warning edi, 'PNG_WRITE_PACKSWAP_SUPPORTED is not defined'
+ @@:
+end if
+
+if (PNG_WRITE_PACK_SUPPORTED eq 0) & (PNG_READ_PACK_SUPPORTED eq 1)
+ mov eax,[edi+png_struct.transformations]
+ and eax,PNG_PACK
+ jz @f ;if(..!=0)
+ png_warning edi, 'PNG_WRITE_PACK_SUPPORTED is not defined'
+ @@:
+end if
+
+if (PNG_WRITE_SHIFT_SUPPORTED eq 0) & (PNG_READ_SHIFT_SUPPORTED eq 1)
+ mov eax,[edi+png_struct.transformations]
+ and eax,PNG_SHIFT
+ jz @f ;if(..!=0)
+ png_warning edi, 'PNG_WRITE_SHIFT_SUPPORTED is not defined'
+ @@:
+end if
+
+if (PNG_WRITE_BGR_SUPPORTED eq 0) & (PNG_READ_BGR_SUPPORTED eq 1)
+ mov eax,[edi+png_struct.transformations]
+ and eax,PNG_BGR
+ jz @f ;if(..!=0)
+ png_warning edi, 'PNG_WRITE_BGR_SUPPORTED is not defined'
+ @@:
+end if
+
+if (PNG_WRITE_SWAP_SUPPORTED eq 0) & (PNG_READ_SWAP_SUPPORTED eq 1)
+ mov eax,[edi+png_struct.transformations]
+ and eax,PNG_SWAP_BYTES
+ jz @f ;if(..!=0)
+ png_warning edi, 'PNG_WRITE_SWAP_SUPPORTED is not defined'
+ @@:
+end if
+
+ stdcall png_write_start_row, edi
+ .end0:
+
+if PNG_WRITE_INTERLACING_SUPPORTED eq 1
+ ; If interlaced and not interested in row, return
+ cmp byte[edi+png_struct.interlaced],0
+ je .end1
+ mov eax,[edi+png_struct.transformations]
+ and eax,PNG_INTERLACE
+ jz .end1 ;if(..!=0 && ..!=0)
+ cmp byte[edi+png_struct.pass],0
+ jne @f
+ mov eax,[edi+png_struct.row_number]
+ and eax,0x07
+ jz .end1 ;if (..!=0)
+ stdcall png_write_finish_row, edi
+ jmp .end_f
+ @@:
+ cmp byte[edi+png_struct.pass],1
+ jne @f
+ mov eax,[edi+png_struct.row_number]
+ and eax,0x07
+ jnz .end2
+ cmp dword[edi+png_struct.width],5
+ jge .end1 ;if (..!=0 || ..<..)
+ .end2:
+ stdcall png_write_finish_row, edi
+ jmp .end_f
+ @@:
+ cmp byte[edi+png_struct.pass],2
+ jne @f
+ mov eax,[edi+png_struct.row_number]
+ and eax,0x07
+ cmp eax,4
+ je .end1 ;if (..!=..)
+ stdcall png_write_finish_row, edi
+ jmp .end_f
+ @@:
+ cmp byte[edi+png_struct.pass],3
+ jne @f
+ mov eax,[edi+png_struct.row_number]
+ and eax,0x03
+ jnz .end3
+ cmp dword[edi+png_struct.width],3
+ jge .end1 ;if (..!=0 || ..<..)
+ .end3:
+ stdcall png_write_finish_row, edi
+ jmp .end_f
+ @@:
+ cmp byte[edi+png_struct.pass],4
+ jne @f
+ mov eax,[edi+png_struct.row_number]
+ and eax,0x03
+ cmp eax,2
+ je .end1 ;if (..!=..)
+ stdcall png_write_finish_row, edi
+ jmp .end_f
+ @@:
+ cmp byte[edi+png_struct.pass],5
+ jne @f
+ mov eax,[edi+png_struct.row_number]
+ and eax,0x01
+ jnz .end4
+ cmp dword[edi+png_struct.width],2
+ jge .end1 ;if (..!=0 || ..<..)
+ .end4:
+ stdcall png_write_finish_row, edi
+ jmp .end_f
+ @@:
+ cmp byte[edi+png_struct.pass],6
+ jne .end1
+ mov eax,[edi+png_struct.row_number]
+ and eax,0x01
+ jnz .end1 ;if (..==0)
+ stdcall png_write_finish_row, edi
+ jmp .end_f
+ .end1:
+end if
+
+ ; Set up row info for transformations
+ mov ebx,ebp
+ sub ebx,sizeof.png_row_info
+ mov al,byte[edi+png_struct.color_type]
+ mov byte[ebx+png_row_info.color_type],al
+ mov eax,[edi+png_struct.usr_width]
+ mov [ebx+png_row_info.width],eax
+ movzx eax,byte[edi+png_struct.usr_channels]
+ mov byte[ebx+png_row_info.channels],al
+ movzx ecx,byte[edi+png_struct.usr_bit_depth]
+ mov byte[ebx+png_row_info.bit_depth],cl
+ imul eax,ecx ;.bit_depth * .channels
+ mov byte[ebx+png_row_info.pixel_depth],al
+ PNG_ROWBYTES eax, [ebx+png_row_info.width]
+ mov [ebx+png_row_info.rowbytes], eax
+
+ push eax
+ movzx eax,byte[ebx+png_row_info.color_type]
+ png_debug1 3, 'row_info->color_type = %d', eax
+ png_debug1 3, 'row_info->width = %u', [ebx+png_row_info.width]
+ movzx eax,byte[ebx+png_row_info.channels]
+ png_debug1 3, 'row_info->channels = %d', eax
+ movzx eax,byte[ebx+png_row_info.bit_depth]
+ png_debug1 3, 'row_info->bit_depth = %d', eax
+ movzx eax,byte[ebx+png_row_info.pixel_depth]
+ png_debug1 3, 'row_info->pixel_depth = %d', eax
+ png_debug1 3, 'row_info->rowbytes = %lu', [ebx+png_row_info.rowbytes]
+ pop eax
+
+ ; Copy user's row into buffer, leaving room for filter byte.
+ push edi
+ mov edi,[edi+png_struct.row_buf]
+ inc edi
+ mov esi,[row]
+ mov ecx,eax
+ rep movsb ;memcpy(...
+ pop edi
+
+if PNG_WRITE_INTERLACING_SUPPORTED eq 1
+ ; Handle interlacing
+ cmp byte[edi+png_struct.interlaced],0
+ je @f
+ cmp byte[edi+png_struct.pass],6
+ jge @f
+ mov eax,[edi+png_struct.transformations]
+ and eax,PNG_INTERLACE
+ jz @f ;if (.. && ..<.. && ..!=0)
+ movzx eax,byte[edi+png_struct.pass]
+ push eax
+ mov eax,[edi+png_struct.row_buf]
+ inc eax
+ stdcall png_do_write_interlace, ebx, eax ;, ...pass
+ ; This should always get caught above, but still ...
+ cmp dword[ebx+png_row_info.width],0
+ jne @f ;if (..==0)
+ stdcall png_write_finish_row, edi
+ jmp .end_f
+ @@:
+end if
+
+if PNG_WRITE_TRANSFORMS_SUPPORTED eq 1
+ ; Handle other transformations
+ cmp dword[edi+png_struct.transformations],0
+ je @f ;if (..!=0)
+ stdcall png_do_write_transformations, edi, ebx
+ @@:
+end if
+
+ ; At this point the row_info pixel depth must match the 'transformed' depth,
+ ; which is also the output depth.
+
+ mov al,[ebx+png_row_info.pixel_depth]
+ cmp al,[edi+png_struct.pixel_depth]
+ jne @f
+ cmp al,[edi+png_struct.transformed_pixel_depth]
+ je .end5
+ @@: ;if (..!=.. || ..!=..)
+ png_error edi, 'internal write transform logic error'
+ .end5:
+
+if PNG_MNG_FEATURES_SUPPORTED eq 1
+ ; Write filter_method 64 (intrapixel differencing) only if
+ ; 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
+ ; 2. Libpng did not write a PNG signature (this filter_method is only
+ ; used in PNG datastreams that are embedded in MNG datastreams) and
+ ; 3. The application called png_permit_mng_features with a mask that
+ ; included PNG_FLAG_MNG_FILTER_64 and
+ ; 4. The filter_method is 64 and
+ ; 5. The color_type is RGB or RGBA
+
+ mov eax,[edi+png_struct.mng_features_permitted]
+ and eax,PNG_FLAG_MNG_FILTER_64
+ jz @f
+ cmp byte[edi+png_struct.filter_type],PNG_INTRAPIXEL_DIFFERENCING
+ jne @f ;if (..!=0 && ..==..)
+ ; Intrapixel differencing
+ mov eax,[edi+png_struct.row_buf]
+ inc eax
+ stdcall png_do_write_intrapixel, ebx, eax
+ @@:
+end if
+
+; Added at libpng-1.5.10
+if PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED eq 1
+ ; Check for out-of-range palette index
+ cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_PALETTE
+ jne @f
+ cmp dword[edi+png_struct.num_palette_max],0
+ jl @f ;if (..==.. && ..>=0)
+ stdcall png_do_check_palette_indexes, edi, ebx
+ @@:
+end if
+
+ ; Find a filter if necessary, filter the row and write it out.
+ mov ebx,ebp
+ sub ebx,sizeof.png_row_info
+ stdcall png_write_find_filter, edi, ebx
+
+ cmp dword[edi+png_struct.write_row_fn],0
+ je .end_f ;if (..!=0)
+ movzx eax,byte[edi+png_struct.pass]
+ stdcall dword[edi+png_struct.write_row_fn], edi, [edi+png_struct.row_number], eax
+.end_f:
+popad
+ ret
+endp
+
+; Set the automatic flush interval or 0 to turn flushing off
+;void (png_structrp png_ptr, int nrows)
+align 4
+proc png_set_flush uses eax edi, png_ptr:dword, nrows:dword
+ png_debug 1, 'in png_set_flush'
+
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f ;if (..==0) return
+
+ mov eax,[nrows]
+ cmp eax,0
+ jge @f ;(nrows < 0 ? 0 : nrows)
+ xor eax,eax
+ @@:
+ mov [edi+png_struct.flush_dist],eax
+.end_f:
+ ret
+endp
+
+; Flush the current output buffers now
+;void (png_structrp png_ptr)
+align 4
+proc png_write_flush uses eax edi, png_ptr:dword
+ png_debug 1, 'in png_write_flush'
+
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f ;if (..==0) return
+
+ ; We have already written out all of the data
+ mov eax,[edi+png_struct.num_rows]
+ cmp [edi+png_struct.row_number],eax
+ jge .end_f ;if (..>=..) return
+
+ stdcall png_compress_IDAT, 0, 0, Z_SYNC_FLUSH
+ mov dword[edi+png_struct.flush_rows],0
+ stdcall png_flush, edi
+.end_f:
+popad
+ ret
+endp
+
+; Free any memory used in png_ptr struct without freeing the struct itself.
+;void (png_structrp png_ptr)
+align 4
+proc png_write_destroy uses eax edi, png_ptr:dword
+ png_debug 1, 'in png_write_destroy'
+
+ ; Free any memory zlib uses
+ mov edi,[png_ptr]
+ mov eax,[edi+png_struct.flags]
+ and eax,PNG_FLAG_ZSTREAM_INITIALIZED
+ jz @f ;if (..!=0)
+ mov eax,edi
+ add eax,png_struct.zstream
+ stdcall [deflateEnd], eax
+ @@:
+
+ ; Free our memory. png_free checks NULL for us.
+ mov eax,edi
+ add eax,png_struct.zbuffer_list
+ stdcall png_free_buffer_list, edi, eax
+ stdcall png_free, edi, [edi+png_struct.row_buf]
+ mov dword[edi+png_struct.row_buf],0
+if PNG_WRITE_FILTER_SUPPORTED eq 1
+ stdcall png_free, edi, [edi+png_struct.prev_row]
+ stdcall png_free, edi, [edi+png_struct.try_row]
+ stdcall png_free, edi, [edi+png_struct.tst_row]
+ mov dword[edi+png_struct.prev_row],0
+ mov dword[edi+png_struct.try_row],0
+ mov dword[edi+png_struct.tst_row],0
+end if
+
+if PNG_SET_UNKNOWN_CHUNKS_SUPPORTED eq 1
+ stdcall png_free, edi, [edi+png_struct.chunk_list]
+ mov dword[edi+png_struct.chunk_list],0
+end if
+
+ ; The error handling and memory handling information is left intact at this
+ ; point: the jmp_buf may still have to be freed. See png_destroy_png_struct
+ ; for how this happens.
+ ret
+endp
+
+; Free all memory used by the write.
+; In libpng 1.6.0 this API changed quietly to no longer accept a NULL value for
+; *png_ptr_ptr. Prior to 1.6.0 it would accept such a value and it would free
+; the passed in info_structs but it would quietly fail to free any of the data
+; inside them. In 1.6.0 it quietly does nothing (it has to be quiet because it
+; has no png_ptr.)
+
+;void (png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
+align 4
+proc png_destroy_write_struct uses edi esi, png_ptr_ptr:dword, info_ptr_ptr:dword
+ png_debug 1, 'in png_destroy_write_struct'
+
+ mov esi,[png_ptr_ptr]
+ cmp esi,0
+ je @f ;if (..!=0)
+ mov edi,[esi]
+
+ cmp edi,0
+ je @f ;if (..!=0) ;added in libpng 1.6.0
+ stdcall png_destroy_info_struct, edi, [info_ptr_ptr]
+
+ mov dword[esi],0
+ stdcall png_write_destroy, edi
+ stdcall png_destroy_png_struct, edi
+ @@:
+ ret
+endp
+
+; Allow the application to select one or more row filters to use.
+;void (png_structrp png_ptr, int method, int filters)
+align 4
+proc png_set_filter uses eax ebx ecx edi, png_ptr:dword, method:dword, filters:dword
+ png_debug 1, 'in png_set_filter'
+pushad
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f ;if (..==0) return
+
+if PNG_MNG_FEATURES_SUPPORTED eq 1
+ mov eax,[edi+png_struct.mng_features_permitted]
+ and eax,PNG_FLAG_MNG_FILTER_64
+ je @f
+ cmp dword[method], PNG_INTRAPIXEL_DIFFERENCING
+ jne @f ;if (..!=0 && ..==..)
+ mov dword[method], PNG_FILTER_TYPE_BASE
+ @@:
+end if
+ cmp dword[method], PNG_FILTER_TYPE_BASE
+ jne .end0 ;if (..==..)
+ mov ebx,[filters]
+ and ebx,PNG_ALL_FILTERS or 0x07 ;switch (..)
+
+if PNG_WRITE_FILTER_SUPPORTED eq 1
+ cmp ebx,5
+ je .end2
+ cmp ebx,6
+ je .end2
+ cmp ebx,7
+ je .end2
+ jmp @f
+ .end2:
+ cStr ,'Unknown row filter for method 0'
+ stdcall png_app_error, edi, eax
+ ; FALL THROUGH
+ @@:
+end if ;WRITE_FILTER
+ cmp ebx,PNG_FILTER_VALUE_NONE
+ jne @f
+ mov byte[edi+png_struct.do_filter],PNG_FILTER_NONE
+ jmp .end1
+ @@:
+if PNG_WRITE_FILTER_SUPPORTED eq 1
+ cmp ebx,PNG_FILTER_VALUE_SUB
+ jne @f
+ mov byte[edi+png_struct.do_filter],PNG_FILTER_SUB
+ jmp .end1
+ @@:
+ cmp ebx,PNG_FILTER_VALUE_UP
+ jne @f
+ mov byte[edi+png_struct.do_filter],PNG_FILTER_UP
+ jmp .end1
+ @@:
+ cmp ebx,PNG_FILTER_VALUE_AVG
+ jne @f
+ mov byte[edi+png_struct.do_filter],PNG_FILTER_AVG
+ jmp .end1
+ @@:
+ cmp ebx,PNG_FILTER_VALUE_PAETH
+ jne @f
+ mov byte[edi+png_struct.do_filter],PNG_FILTER_PAETH
+ jmp .end1
+ @@: ;default:
+ mov eax,[filters]
+ mov byte[edi+png_struct.do_filter],al
+ jmp .end1
+else
+ @@: ;default:
+ cStr ,'Unknown row filter for method 0'
+ stdcall png_app_error edi, eax
+end if ;WRITE_FILTER
+ .end1:
+
+if PNG_WRITE_FILTER_SUPPORTED eq 1
+ ; If we have allocated the row_buf, this means we have already started
+ ; with the image and we should have allocated all of the filter buffers
+ ; that have been selected. If prev_row isn't already allocated, then
+ ; it is too late to start using the filters that need it, since we
+ ; will be missing the data in the previous row. If an application
+ ; wants to start and stop using particular filters during compression,
+ ; it should start out with all of the filters, and then remove them
+ ; or add them back after the start of compression.
+
+ ; NOTE: this is a nasty constraint on the code, because it means that the
+ ; prev_row buffer must be maintained even if there are currently no
+ ; 'prev_row' requiring filters active.
+
+ cmp dword[edi+png_struct.row_buf],0
+ je .end3 ;if (..!=0)
+ ;ebx = num_filters
+ ;ecx = buf_size
+
+ ; Repeat the checks in png_write_start_row; 1 pixel high or wide
+ ; images cannot benefit from certain filters. If this isn't done here
+ ; the check below will fire on 1 pixel high images.
+
+ cmp dword[edi+png_struct.height],1
+ jne @f ;if (..==..)
+ and dword[filters],not (PNG_FILTER_UP or PNG_FILTER_AVG or PNG_FILTER_PAETH)
+ @@:
+ cmp dword[edi+png_struct.width],1
+ jne @f ;if (..==..)
+ and dword[filters],not (PNG_FILTER_SUB or PNG_FILTER_AVG or PNG_FILTER_PAETH)
+ @@:
+ mov eax,[filters]
+ and eax,PNG_FILTER_UP or PNG_FILTER_AVG or PNG_FILTER_PAETH
+ jz @f
+ cmp dword[edi+png_struct.prev_row],0
+ je @f;if (..!=0 && ..==0)
+ ; This is the error case, however it is benign - the previous row
+ ; is not available so the filter can't be used. Just warn here.
+
+ png_app_warning edi, 'png_set_filter: UP/AVG/PAETH cannot be added after start'
+ and dword[filters],not (PNG_FILTER_UP or PNG_FILTER_AVG or PNG_FILTER_PAETH)
+ @@:
+
+ xor ebx,ebx
+
+ mov eax,[filters]
+ and eax,PNG_FILTER_SUB
+ jz @f ;if (..)
+ inc ebx
+ @@:
+ mov eax,[filters]
+ and eax,PNG_FILTER_UP
+ jz @f ;if (..)
+ inc ebx
+ @@:
+ mov eax,[filters]
+ and eax,PNG_FILTER_AVG
+ jz @f ;if (..)
+ inc ebx
+ @@:
+ mov eax,[filters]
+ and eax,PNG_FILTER_PAETH
+ jz @f ;if (..)
+ inc ebx
+ @@:
+ ; Allocate needed row buffers if they have not already been
+ ; allocated.
+
+ movzx eax,byte[edi+png_struct.usr_channels]
+ movzx ecx,byte[edi+png_struct.usr_bit_depth]
+ imul eax,ecx ;.bit_depth * .channels
+ mov ecx,[edi+png_struct.width]
+ inc ecx
+ PNG_ROWBYTES eax, ecx
+ mov ecx, eax
+
+ cmp dword[edi+png_struct.try_row],0
+ jne @f ;if (..==0)
+ stdcall png_malloc, edi, ecx
+ mov [edi+png_struct.try_row],eax
+ @@:
+
+ cmp ebx,1
+ jle .end3 ;if (..>..)
+ cmp dword[edi+png_struct.tst_row],0
+ jne .end3 ;if (..==0)
+ stdcall png_malloc, edi, ecx
+ mov [edi+png_struct.tst_row],eax
+ .end3:
+ mov eax,[filters]
+ mov byte[edi+png_struct.do_filter],al
+end if
+ jmp .end_f
+ .end0: ;else
+ png_error edi, 'Unknown custom filter method'
+.end_f:
+popad
+ ret
+endp
+
+; Provide floating and fixed point APIs
+;void (png_structrp png_ptr, int heuristic_method,
+; int num_weights, png_const_doublep filter_weights, png_const_doublep filter_costs)
+align 4
+proc png_set_filter_heuristics, png_ptr:dword, heuristic_method:dword, num_weights:dword, filter_weights:dword, filter_costs:dword
+ ret
+endp
+
+;void (png_structrp png_ptr, int heuristic_method,
+; int num_weights, png_const_fixed_point_p filter_weights,
+; png_const_fixed_point_p filter_costs)
+align 4
+proc png_set_filter_heuristics_fixed, png_ptr:dword, heuristic_method:dword, num_weights:dword, filter_weights:dword, filter_costs:dword
+ ret
+endp
+
+;void (png_structrp png_ptr, int level)
+align 4
+proc png_set_compression_level uses edi, png_ptr:dword, level:dword
+ png_debug 1, 'in png_set_compression_level'
+
+ mov edi,[png_ptr]
+ cmp edi,0
+ je @f ;if (..==0) return
+
+ m2m [edi+png_struct.zlib_level], [level]
+ @@:
+ ret
+endp
+
+;void (png_structrp png_ptr, int mem_level)
+align 4
+proc png_set_compression_mem_level uses edi, png_ptr:dword, mem_level:dword
+ png_debug 1, 'in png_set_compression_mem_level'
+
+ mov edi,[png_ptr]
+ cmp edi,0
+ je @f ;if (..==0) return
+
+ m2m [edi+png_struct.zlib_mem_level], [mem_level]
+ @@:
+ ret
+endp
+
+;void (png_structrp png_ptr, int strategy)
+align 4
+proc png_set_compression_strategy uses edi, png_ptr:dword, strategy:dword
+ png_debug 1, 'in png_set_compression_strategy'
+
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f ;if (..==0) return
+
+ ; The flag setting here prevents the libpng dynamic selection of strategy.
+
+ or dword[edi+png_struct.flags], PNG_FLAG_ZLIB_CUSTOM_STRATEGY
+ m2m [edi+png_struct.zlib_strategy], [strategy]
+.end_f:
+ ret
+endp
+
+; If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a
+; smaller value of window_bits if it can do so safely.
+
+;void (png_structrp png_ptr, int window_bits)
+align 4
+proc png_set_compression_window_bits uses eax edi, png_ptr:dword, window_bits:dword
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f ;if (..==0) return
+
+ ; Prior to 1.6.0 this would warn but then set the window_bits value. This
+ ; meant that negative window bits values could be selected that would cause
+ ; libpng to write a non-standard PNG file with raw deflate or gzip
+ ; compressed IDAT or ancillary chunks. Such files can be read and there is
+ ; no warning on read, so this seems like a very bad idea.
+
+ mov eax,[window_bits]
+ cmp eax,15
+ jle @f ;if (..>..)
+ png_warning edi, 'Only compression windows <= 32k supported by PNG'
+ mov eax,15
+ jmp .end0
+ @@: ;else if (..<..)
+ cmp eax,8
+ jge @f
+ png_warning edi, 'Only compression windows >= 256 supported by PNG'
+ mov eax,8
+ .end0:
+
+ mov [edi+png_struct.zlib_window_bits],eax
+.end_f:
+ ret
+endp
+
+;void (png_structrp png_ptr, int method)
+align 4
+proc png_set_compression_method uses eax edi, png_ptr:dword, method:dword
+ png_debug 1, 'in png_set_compression_method'
+
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f ;if (..==0) return
+
+ ; This would produce an invalid PNG file if it worked, but it doesn't and
+ ; deflate will fault it, so it is harmless to just warn here.
+
+ mov eax,[method]
+ cmp eax,8
+ je @f ;if (..!=..)
+ png_warning edi, 'Only compression method 8 is supported by PNG'
+ @@:
+ mov [edi+png_struct.zlib_method],eax
+.end_f:
+ ret
+endp
+
+; The following were added to libpng-1.5.4
+if PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED eq 1
+;void (png_structrp png_ptr, int level)
+align 4
+proc png_set_text_compression_level uses edi, png_ptr:dword, level:dword
+ png_debug 1, 'in png_set_text_compression_level'
+
+ mov edi,[png_ptr]
+ cmp edi,0
+ je @f ;if (..==0) return
+
+ m2m [edi+png_struct.zlib_text_level], [level]
+ @@:
+ ret
+endp
+
+;void (png_structrp png_ptr, int mem_level)
+align 4
+proc png_set_text_compression_mem_level uses edi, png_ptr:dword, mem_level:dword
+ png_debug 1, 'in png_set_text_compression_mem_level'
+
+ mov edi,[png_ptr]
+ cmp edi,0
+ je @f ;if (..==0) return
+
+ m2m [edi+png_struct.zlib_text_mem_level], [mem_level]
+ @@:
+ ret
+endp
+
+;void (png_structrp png_ptr, int strategy)
+align 4
+proc png_set_text_compression_strategy uses edi, png_ptr:dword, strategy:dword
+ png_debug 1, 'in png_set_text_compression_strategy'
+
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f ;if (..==0) return
+
+ m2m [edi+png_struct.zlib_text_strategy], [strategy]
+.end_f:
+ ret
+endp
+
+; If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a
+; smaller value of window_bits if it can do so safely.
+
+;void (png_structrp png_ptr, int window_bits)
+align 4
+proc png_set_text_compression_window_bits uses eax edi, png_ptr:dword, window_bits:dword
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f ;if (..==0) return
+
+ mov eax,[window_bits]
+ cmp eax,15
+ jle @f ;if (..>..)
+ png_warning edi, 'Only compression windows <= 32k supported by PNG'
+ mov eax,15
+ jmp .end0
+ @@: ;else if (..<..)
+ cmp eax,8
+ jge @f
+ png_warning edi, 'Only compression windows >= 256 supported by PNG'
+ mov eax,8
+ .end0:
+
+ mov [edi+png_struct.zlib_text_window_bits],eax
+.end_f:
+ ret
+endp
+
+;void (png_structrp png_ptr, int method)
+align 4
+proc png_set_text_compression_method uses edi, png_ptr:dword, method:dword
+ png_debug 1, 'in png_set_text_compression_method'
+
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f ;if (..==0) return
+
+ cmp dword[method],8
+ je @f ;if (..!=..)
+ png_warning edi, 'Only compression method 8 is supported by PNG'
+ @@:
+ m2m [edi+png_struct.zlib_text_method], [method]
+.end_f:
+ ret
+endp
+end if ;WRITE_CUSTOMIZE_ZTXT_COMPRESSION
+; end of API added to libpng-1.5.4
+
+;void (png_structrp png_ptr, png_write_status_ptr write_row_fn)
+align 4
+proc png_set_write_status_fn uses edi, png_ptr:dword, write_row_fn:dword
+ mov edi,[png_ptr]
+ cmp edi,0
+ je @f ;if (..==0) return
+ m2m [edi+png_struct.write_row_fn], [write_row_fn]
+ @@:
+ ret
+endp
+
+;void (png_structrp png_ptr, png_user_transform_ptr write_user_transform_fn)
+align 4
+proc png_set_write_user_transform_fn uses edi, png_ptr:dword, write_user_transform_fn:dword
+ png_debug 1, 'in png_set_write_user_transform_fn'
+
+ mov edi,[png_ptr]
+ cmp edi,0
+ je @f ;if (..==0) return
+ or dword[edi+png_struct.transformations], PNG_USER_TRANSFORM
+ m2m [edi+png_struct.write_user_transform_fn], [write_user_transform_fn]
+ @@:
+ ret
+endp
+
+;void (png_structrp png_ptr, png_inforp info_ptr, int transforms, voidp params)
+align 4
+proc png_write_png, png_ptr:dword, info_ptr:dword, transforms:dword, params:dword
+pushad
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f
+ mov esi,[info_ptr]
+ cmp esi,0
+ je .end_f ;if(..==0 || ..==0) return
+
+ and dword[esi+png_info_def.valid],PNG_INFO_IDAT
+ cmp esi,0 ;if(..==0)
+ jne @f
+ cStr ,'no rows for png_write_image to write'
+ stdcall png_app_error edi, eax
+ jmp .end_f ;return
+ @@:
+
+ ; Write the file header information.
+ stdcall png_write_info, edi, esi
+
+ ; ------ these transformations don't touch the info structure -------
+
+ ; Invert monochrome pixels
+ mov eax,[transforms]
+ and eax,PNG_TRANSFORM_INVERT_MONO
+ jz @f ;if(..!=0)
+if PNG_WRITE_INVERT_SUPPORTED eq 1
+ stdcall png_set_invert_mono,edi
+else
+ cStr ,'PNG_TRANSFORM_INVERT_MONO not supported'
+ stdcall png_app_error edi, eax
+end if
+ @@:
+
+ ; Shift the pixels up to a legal bit depth and fill in
+ ; as appropriate to correctly scale the image.
+
+ mov eax,[transforms]
+ and eax,PNG_TRANSFORM_SHIFT
+ jz @f ;if(..!=0)
+if PNG_WRITE_SHIFT_SUPPORTED eq 1
+ mov eax,[esi+png_info_def.valid]
+ and eax,PNG_INFO_sBIT
+ jz @f ;if(..!=0)
+ mov eax,esi
+ add eax,png_info_def.sig_bit
+ stdcall png_set_shift, edi, eax
+else
+ cStr ,'PNG_TRANSFORM_SHIFT not supported'
+ stdcall png_app_error edi, eax
+end if
+ @@:
+
+ ; Pack pixels into bytes
+ mov eax,[transforms]
+ and eax,PNG_TRANSFORM_PACKING
+ jz @f ;if(..!=0)
+if PNG_WRITE_PACK_SUPPORTED eq 1
+ stdcall png_set_packing, edi
+else
+ cStr ,'PNG_TRANSFORM_PACKING not supported'
+ stdcall png_app_error edi, eax
+end if
+ @@:
+
+ ; Swap location of alpha bytes from ARGB to RGBA
+ mov eax,[transforms]
+ and eax,PNG_TRANSFORM_SWAP_ALPHA
+ jz @f ;if(..!=0)
+if PNG_WRITE_SWAP_ALPHA_SUPPORTED eq 1
+ stdcall png_set_swap_alpha, edi
+else
+ cStr ,'PNG_TRANSFORM_SWAP_ALPHA not supported'
+ stdcall png_app_error edi, eax
+end if
+ @@:
+
+ ; Remove a filler (X) from XRGB/RGBX/AG/GA into to convert it into
+ ; RGB, note that the code expects the input color type to be G or RGB; no
+ ; alpha channel.
+
+ mov eax,[transforms]
+ and eax,PNG_TRANSFORM_STRIP_FILLER_AFTER or PNG_TRANSFORM_STRIP_FILLER_BEFORE
+ jz .end_0 ;if(..!=0)
+if PNG_WRITE_FILLER_SUPPORTED eq 1
+ and eax,PNG_TRANSFORM_STRIP_FILLER_AFTER
+ jz .end_1 ;if(..!=0)
+ mov eax,[transforms]
+ and eax,PNG_TRANSFORM_STRIP_FILLER_BEFORE
+ jz @f ;if(..!=0)
+ cStr ,'PNG_TRANSFORM_STRIP_FILLER: BEFORE+AFTER not supported'
+ stdcall png_app_error edi, eax
+ @@:
+
+ ; Continue if ignored - this is the pre-1.6.10 behavior
+ stdcall png_set_filler, edi, 0, PNG_FILLER_AFTER
+ jmp .end_0
+ .end_1: ;else if ((transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) != 0)
+ stdcall png_set_filler, edi, 0, PNG_FILLER_BEFORE
+else
+ cStr ,'PNG_TRANSFORM_STRIP_FILLER not supported'
+ stdcall png_app_error edi, eax
+end if
+ .end_0:
+
+ ; Flip BGR pixels to RGB
+ mov eax,[transforms]
+ and eax,PNG_TRANSFORM_BGR
+ jz @f ;if(..!=0)
+if PNG_WRITE_BGR_SUPPORTED eq 1
+ stdcall png_set_bgr, edi
+else
+ cStr ,'PNG_TRANSFORM_BGR not supported'
+ stdcall png_app_error edi, eax
+end if
+ @@:
+
+ ; Swap bytes of 16-bit files to most significant byte first
+ mov eax,[transforms]
+ and eax,PNG_TRANSFORM_SWAP_ENDIAN
+ jz @f ;if(..!=0)
+if PNG_WRITE_SWAP_SUPPORTED eq 1
+ stdcall png_set_swap, edi
+else
+ cStr ,'PNG_TRANSFORM_SWAP_ENDIAN not supported'
+ stdcall png_app_error edi, eax
+end if
+ @@:
+
+ ; Swap bits of 1-bit, 2-bit, 4-bit packed pixel formats
+ mov eax,[transforms]
+ and eax,PNG_TRANSFORM_PACKSWAP
+ jz @f ;if(..!=0)
+if PNG_WRITE_PACKSWAP_SUPPORTED eq 1
+ stdcall png_set_packswap, edi
+else
+ cStr ,'PNG_TRANSFORM_PACKSWAP not supported'
+ stdcall png_app_error edi, eax
+end if
+ @@:
+
+ ; Invert the alpha channel from opacity to transparency
+ mov eax,[transforms]
+ and eax,PNG_TRANSFORM_INVERT_ALPHA
+ jz @f ;if(..!=0)
+if PNG_WRITE_INVERT_ALPHA_SUPPORTED eq 1
+ stdcall png_set_invert_alpha, edi
+else
+ cStr ,'PNG_TRANSFORM_INVERT_ALPHA not supported'
+ stdcall png_app_error edi, eax
+end if
+ @@:
+
+ ; ----------------------- end of transformations -------------------
+
+ ; Write the bits
+ stdcall png_write_image, edi, dword[esi+png_info_def.row_pointers]
+
+ ; It is REQUIRED to call this to finish writing the rest of the file
+ stdcall png_write_end, edi, esi
+
+.end_f:
+popad
+ ret
+endp
+
+if PNG_SIMPLIFIED_WRITE_SUPPORTED eq 1
+; Initialize the write structure - general purpose utility.
+;int (png_imagep image)
+align 4
+proc png_image_write_init uses ebx ecx edx edi esi, image:dword
+ mov ebx,[image]
+ stdcall png_create_write_struct, PNG_LIBPNG_VER_STRING, ebx, png_safe_error, png_safe_warning
+ ;eax = png_ptr
+
+ test eax,eax
+ jz .end0 ;if (..!=0)
+ mov edi,eax
+ or dword[eax+png_struct.transformations],PNG_BGR ;transformation rgb for KoliriOS
+ stdcall png_create_info_struct, edi
+ ;eax = info_ptr
+
+ test eax,eax
+ jz .end1 ;if (..!=0)
+ mov esi,eax
+ stdcall png_malloc_warn, edi, sizeof.png_control
+ ;control = eax
+
+ test eax,eax
+ jz .end2 ;if (..!=0)
+ push eax
+ mov edx,edi ; edx = png_ptr
+ mov ecx,sizeof.png_control
+ mov edi,eax
+ xor eax,eax
+ rep stosb ;memset(control, 0, (sizeof.control))
+ pop eax
+
+ mov [eax+png_control.png_ptr], edx
+ mov [eax+png_control.info_ptr], esi
+ mov [eax+png_control.for_write], 1
+
+ mov [ebx+png_image.opaque], eax
+ xor eax,eax
+ inc eax
+ jmp .end_f
+ .end2:
+
+ ; Error clean up
+ push esi
+ mov esi,esp
+ stdcall png_destroy_info_struct, edi, esi
+ add esp,4
+ .end1:
+
+ push edi
+ mov edi,esp
+ stdcall png_destroy_write_struct, edi, 0
+ add esp,4
+ .end0:
+
+ std_png_image_error ebx, 'png_image_write_: out of memory'
+.end_f:
+ ret
+endp
+
+; Arguments to png_image_write_main:
+struct png_image_write_control
+ ; Arguments:
+ image dd ? ;png_imagep
+ buffer dd ? ;png_const_voidp
+ row_stride dd ? ;int_32
+ colormap dd ? ;png_const_voidp
+ convert_to_8bit dd ? ;int
+ ; Local variables:
+ first_row dd ? ;png_const_voidp
+ row_bytes dd ? ;ptrdiff_t
+ local_row dd ? ;voidp
+ ; Byte count for memory writing
+ memory dd ? ;bytep
+ memory_bytes dd ? ;png_alloc_size_t ;not used for STDIO
+ output_bytes dd ? ;png_alloc_size_t ;running total
+ends
+
+; Write uint_16 input to a 16-bit PNG; the png_ptr has already been set to
+; do any necessary byte swapping. The component order is defined by the
+; png_image format value.
+
+;int (voidp argument)
+align 4
+proc png_write_image_16bit uses ebx ecx edx, argument:dword
+locals
+ display dd ? ;png_image_write_control* ;= argument
+ image dd ? ;png_imagep ;= display->image
+ png_ptr dd ? ;png_structrp ;= image->opaque->png_ptr
+ input_row dd ? ;const_uint_16p ;= display->first_row
+ output_row dd ? ;uint_16p ;= display->local_row
+ row_end dd ? ;uint_16p
+ channels dd ? ;const int ;= (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1;
+ aindex dd 0 ;int ;= 0
+ y dd ? ;uint_32 ;= image->height
+endl
+ mov ebx,[argument]
+ mov [display],ebx
+ mov edx,[ebx+png_image_write_control.image]
+ mov [image],edx
+ mov ecx,[edx+png_image.opaque]
+ mov ecx,[ecx+png_control.png_ptr]
+ mov [png_ptr],ecx
+ mov ecx,[ebx+png_image_write_control.first_row]
+ mov [input_row],ecx
+ mov ecx,[ebx+png_image_write_control.local_row]
+ mov [output_row],ecx
+
+ mov ecx,1
+ mov eax,[edx+png_image.format]
+ and eax,PNG_FORMAT_FLAG_COLOR
+ jz @f
+ mov ecx,3
+ @@:
+ mov [channels],ecx
+ mov eax,[edx+png_image.height]
+ mov [y],eax
+
+ mov eax,[edx+png_image.format]
+ and eax,PNG_FORMAT_FLAG_ALPHA
+ jz .end0 ;if (..!=0)
+if PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED eq 1
+ mov eax,[edx+png_image.format]
+ and eax,PNG_FORMAT_FLAG_AFIRST
+ jz @f ;if (..!=0)
+ mov dword[aindex],-1
+ inc dword[input_row] ;To point to the first component
+ inc dword[output_row]
+ jmp .end1
+ @@: ;else
+end if
+ mov eax,[channels]
+ mov [aindex],eax
+ jmp .end1
+ .end0: ;else
+ png_error [png_ptr], 'png_write_image: internal call error'
+ .end1:
+
+ ; Work out the output row end and count over this, note that the increment
+ ; above to 'row' means that row_end can actually be beyond the end of the
+ ; row; this is correct.
+
+ mov eax,[channels]
+ inc eax
+ imul eax,[edx+png_image.width]
+ add eax,[output_row]
+ mov [row_end],eax
+
+; while (y-- > 0)
+; {
+; const_uint_16p in_ptr = input_row;
+; uint_16p out_ptr = output_row;
+
+; while (out_ptr < row_end)
+; {
+; const uint_16 alpha = in_ptr[aindex];
+; uint_32 reciprocal = 0;
+; int c;
+
+; out_ptr[aindex] = alpha;
+
+ ; Calculate a reciprocal. The correct calculation is simply
+ ; component/alpha*65535 << 15. (I.e. 15 bits of precision); this
+ ; allows correct rounding by adding .5 before the shift. 'reciprocal'
+ ; is only initialized when required.
+
+; if (alpha > 0 && alpha < 65535)
+; reciprocal = ((0xffff<<15)+(alpha>>1))/alpha;
+
+; c = channels;
+; do /* always at least one channel */
+; {
+; uint_16 component = *in_ptr++;
+
+ ; The following gives 65535 for an alpha of 0, which is fine,
+ ; otherwise if 0/0 is represented as some other value there is more
+ ; likely to be a discontinuity which will probably damage
+ ; compression when moving from a fully transparent area to a
+ ; nearly transparent one. (The assumption here is that opaque
+ ; areas tend not to be 0 intensity.)
+
+; if (component >= alpha)
+; component = 65535;
+
+ ; component 0 && alpha < 65535)
+; {
+; uint_32 calc = component * reciprocal;
+; calc += 16384; /* round to nearest */
+; component = (uint_16)(calc >> 15);
+; }
+
+; *out_ptr++ = component;
+; }
+; while (--c > 0);
+
+ ; Skip to next component (skip the intervening alpha channel)
+; ++in_ptr;
+; ++out_ptr;
+; }
+
+; png_write_row(png_ptr, display->local_row);
+; input_row += display->row_bytes/(sizeof (uint_16));
+; }
+
+ xor eax,eax
+ inc eax ;return 1
+ ret
+endp
+
+; Given 16-bit input (1 to 4 channels) write 8-bit output. If an alpha channel
+; is present it must be removed from the components, the components are then
+; written in sRGB encoding. No components are added or removed.
+
+; Calculate an alpha reciprocal to reverse pre-multiplication. As above the
+; calculation can be done to 15 bits of accuracy; however, the output needs to
+; be scaled in the range 0..255*65535, so include that scaling here.
+
+;# define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+(alpha>>1))/alpha)
+
+;byte (uint_32 component, uint_32 alpha, uint_32 reciprocal/*from the above macro*/)
+align 4
+proc png_unpremultiply, component:dword, alpha:dword, reciprocal:dword
+ ; The following gives 1.0 for an alpha of 0, which is fine, otherwise if 0/0
+ ; is represented as some other value there is more likely to be a
+ ; discontinuity which will probably damage compression when moving from a
+ ; fully transparent area to a nearly transparent one. (The assumption here
+ ; is that opaque areas tend not to be 0 intensity.)
+
+ ; There is a rounding problem here; if alpha is less than 128 it will end up
+ ; as 0 when scaled to 8 bits. To avoid introducing spurious colors into the
+ ; output change for this too.
+
+ mov eax,[alpha]
+ cmp [component],eax
+ jge @f
+ cmp eax,128
+ jge .end0
+ @@: ;if (..>=.. || ..<..)
+ mov eax,255
+ jmp .end_f
+ ; component 0)
+ cmp dword[component],0
+ jle .end1
+ ; The test is that alpha/257 (rounded) is less than 255, the first value
+ ; that becomes 255 is 65407.
+ ; NOTE: this must agree with the PNG_DIV257 macro (which must, therefore,
+ ; be exact!) [Could also test reciprocal != 0]
+
+; if (alpha < 65407)
+; {
+; component *= reciprocal;
+; component += 64; /* round to nearest */
+; component >>= 7;
+; }
+
+; else
+; component *= 255;
+
+ ; Convert the component to sRGB.
+ PNG_sRGB_FROM_LINEAR [component]
+ and eax,0xff
+ jmp .end_f
+ .end1: ;else
+ xor eax,eax
+.end_f:
+ ret
+endp
+
+;int (voidp argument)
+align 4
+proc png_write_image_8bit uses ebx ecx edx edi esi, argument:dword
+locals
+ display dd ? ;png_image_write_control* ;= argument
+ image dd ? ;png_imagep ;= display->image
+ png_ptr dd ? ;png_structrp ;= image->opaque->png_ptr
+ input_row dd ? ;const_uint_16p ;= display->first_row
+ output_row dd ? ;uint_16p ;= display->local_row
+ row_end dd ? ;uint_16p
+ channels dd ? ;const int ;= (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1;
+ aindex dd 0 ;int ;= 0
+ y dd ? ;uint_32 ;= image->height
+ component dd ? ;uint_32
+endl
+ mov ebx,[argument]
+ mov [display],ebx
+ mov edx,[ebx+png_image_write_control.image]
+ mov [image],edx
+ mov ecx,[edx+png_image.opaque]
+ mov ecx,[ecx+png_control.png_ptr]
+ mov [png_ptr],ecx
+ mov ecx,[ebx+png_image_write_control.first_row]
+ mov [input_row],ecx
+ mov ecx,[ebx+png_image_write_control.local_row]
+ mov [output_row],ecx
+
+ mov ecx,1
+ mov eax,[edx+png_image.format]
+ and eax,PNG_FORMAT_FLAG_COLOR
+ jz @f
+ mov ecx,3
+ @@:
+ mov [channels],ecx
+ mov eax,[edx+png_image.height]
+ mov [y],eax
+
+ mov eax,[edx+png_image.format]
+ and eax,PNG_FORMAT_FLAG_ALPHA
+ jz .end0 ;if (..!=0)
+
+if PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED eq 1
+ mov eax,[edx+png_image.format]
+ and eax,PNG_FORMAT_FLAG_AFIRST
+ jz .end2 ;if (..!=0)
+ mov [aindex],-1
+ inc [input_row] ; To point to the first component
+ inc [output_row]
+ jmp @f
+ .end2: ;else
+end if
+ mov eax,[channels]
+ mov [aindex],eax
+ .@@:
+
+ ; Use row_end in place of a loop counter:
+ mov ecx,[channels]
+ inc ecx
+ imul ecx,[edx+png_image.width]
+ add ecx,[output_row]
+ ;ecx = row_end
+
+; while (y-- > 0)
+; {
+; const_uint_16p in_ptr = input_row;
+; bytep out_ptr = output_row;
+
+; while (out_ptr < row_end)
+; {
+; uint_16 alpha = in_ptr[aindex];
+; byte alphabyte = (byte)PNG_DIV257(alpha);
+; uint_32 reciprocal = 0;
+; int c;
+
+ ; Scale and write the alpha channel.
+; out_ptr[aindex] = alphabyte;
+
+; if (alphabyte > 0 && alphabyte < 255)
+; reciprocal = UNP_RECIPROCAL(alpha);
+
+; c = channels;
+; do /* always at least one channel */
+; *out_ptr++ = png_unpremultiply(*in_ptr++, alpha, reciprocal);
+; while (--c > 0);
+
+ ; Skip to next component (skip the intervening alpha channel)
+; ++in_ptr;
+; ++out_ptr;
+; } /* while out_ptr < row_end */
+
+; png_write_row(png_ptr, display->local_row);
+; input_row += display->row_bytes/(sizeof (uint_16));
+; } /* while y */
+ jmp .end1
+ .end0: ;else
+ ; No alpha channel, so the row_end really is the end of the row and it
+ ; is sufficient to loop over the components one by one.
+
+ mov ecx,[edx+png_image.width]
+ imul ecx,[channels]
+ add ecx,[output_row]
+ ;ecx = row_end
+
+ .cycle2: ;while (y-- > 0)
+ cmp dword[y],0
+ jle .cycle2end
+ mov esi,[input_row]
+ mov edi,[output_row]
+ ;esi = in_ptr
+ ;edi = out_ptr
+
+ .cycle3: ;while (..<..)
+ cmp edi,ecx
+ jge .cycle3end
+ xor eax,eax
+ lodsw
+
+ imul eax,255
+ mov [component],eax
+ PNG_sRGB_FROM_LINEAR [component]
+ stosb
+ jmp .cycle3
+align 4
+ .cycle3end:
+
+ stdcall png_write_row, [png_ptr], [output_row]
+ mov eax,[ebx+png_image_write_control.row_bytes]
+ shr eax,1 ;sizeof.uint_16
+ add [input_row],eax
+ dec dword[y]
+ jmp .cycle2
+align 4
+ .cycle2end:
+ .end1:
+
+ xor eax,eax
+ inc eax
+ ret
+endp
+
+;void (png_image_write_control *display)
+align 4
+proc png_image_set_PLTE, display:dword
+locals
+ image dd ? ;png_imagep ;= display->image
+ cmap dd ? ;void * ;= display->colormap
+ entries dd ? ;int
+
+ ; NOTE: the caller must check for cmap != NULL and entries != 0
+ format dd ? ;uint_32 ;= image->format
+ channels dd ? ;int
+ afirst dd 0
+ bgr dd 0
+ num_trans dd 0
+ palette rb 256*sizeof.png_color
+ tRNS rb 256 ;byte[]
+endl
+pushad
+ mov edx,[display]
+ mov ebx,[edx+png_image_write_control.image]
+ mov [image],ebx
+ mov eax,[edx+png_image_write_control.colormap]
+ mov [cmap],eax
+ mov eax,[ebx+png_image.colormap_entries]
+ cmp eax,256
+ jle @f
+ mov eax,256
+ @@:
+ mov [entries],eax
+ mov ecx,[ebx+png_image.format]
+ mov [format],ecx
+ PNG_IMAGE_SAMPLE_CHANNELS ecx
+ mov [channels],eax
+
+if (PNG_FORMAT_BGR_SUPPORTED eq 1) & (PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED eq 1)
+ mov eax,ecx
+ and eax,PNG_FORMAT_FLAG_AFIRST
+ jz @f
+ mov eax,ecx
+ and eax,PNG_FORMAT_FLAG_ALPHA
+ jz @f
+ mov dword[afirst],-1
+ @@:
+end if
+
+if PNG_FORMAT_BGR_SUPPORTED eq 1
+ mov eax,ecx
+ and eax,PNG_FORMAT_FLAG_BGR
+ jz @f
+ mov dword[bgr],2
+ @@:
+end if
+
+; int i;
+
+ xor eax,eax
+ mov ecx,(256*sizeof.png_color)/4
+ mov edi,ebp
+ sub edi,256+256*sizeof.png_color
+ rep stosd ;memset(palette, 0, ...
+ not eax
+ mov ecx,256/4
+ ;;mov edi,ebp ;if 'tRNS' after 'palette' this code can be comment
+ ;;sub edi,256
+ rep stosd ;memset(tRNS, 255, ...
+
+
+; for (i=num_trans=0; i= 3) /* RGB */
+; {
+; palette[i].blue = (byte)PNG_sRGB_FROM_LINEAR(255 *
+; entry[(2 ^ bgr)]);
+; palette[i].green = (byte)PNG_sRGB_FROM_LINEAR(255 *
+; entry[1]);
+; palette[i].red = (byte)PNG_sRGB_FROM_LINEAR(255 *
+; entry[bgr]);
+; }
+
+; else /* Gray */
+; palette[i].blue = palette[i].red = palette[i].green =
+; (byte)PNG_sRGB_FROM_LINEAR(255 * *entry);
+; }
+
+; else /* alpha */
+; {
+; uint_16 alpha = entry[afirst ? 0 : channels-1];
+; byte alphabyte = (byte)PNG_DIV257(alpha);
+; uint_32 reciprocal = 0;
+
+ ; Calculate a reciprocal, as in the png_write_image_8bit code above
+ ; this is designed to produce a value scaled to 255*65535 when
+ ; divided by 128 (i.e. asr 7).
+
+; if (alphabyte > 0 && alphabyte < 255)
+; reciprocal = (((0xffff*0xff)<<7)+(alpha>>1))/alpha;
+
+; tRNS[i] = alphabyte;
+; if (alphabyte < 255)
+; num_trans = i+1;
+
+; if (channels >= 3) /* RGB */
+; {
+; palette[i].blue = png_unpremultiply(entry[afirst + (2 ^ bgr)],
+; alpha, reciprocal);
+; palette[i].green = png_unpremultiply(entry[afirst + 1], alpha,
+; reciprocal);
+; palette[i].red = png_unpremultiply(entry[afirst + bgr], alpha,
+; reciprocal);
+; }
+
+; else /* gray */
+; palette[i].blue = palette[i].red = palette[i].green =
+; png_unpremultiply(entry[afirst], alpha, reciprocal);
+; }
+; }
+
+; else /* Color-map has sRGB values */
+; {
+; bytep entry = cmap;
+
+; entry += i * channels;
+
+; switch (channels)
+; {
+; case 4:
+; tRNS[i] = entry[afirst ? 0 : 3];
+; if (tRNS[i] < 255)
+; num_trans = i+1;
+; /* FALL THROUGH */
+; case 3:
+; palette[i].blue = entry[afirst + (2 ^ bgr)];
+; palette[i].green = entry[afirst + 1];
+; palette[i].red = entry[afirst + bgr];
+; break;
+
+; case 2:
+; tRNS[i] = entry[1 ^ afirst];
+; if (tRNS[i] < 255)
+; num_trans = i+1;
+; /* FALL THROUGH */
+; case 1:
+; palette[i].blue = palette[i].red = palette[i].green =
+; entry[afirst];
+; break;
+
+; default:
+; break;
+; }
+; }
+; }
+
+ mov ecx,[ebx+png_image.opaque]
+ mov eax,ebp
+ sub eax,256+256*sizeof.png_color
+ stdcall png_set_PLTE, [ecx+png_control.png_ptr], [ecx+png_control.info_ptr], eax, [entries]
+
+ cmp dword[num_trans],0
+ jle @f ;if (..>0)
+ mov eax,ebp
+ sub eax,256
+ stdcall png_set_tRNS, [ecx+png_control.png_ptr], [ecx+png_control.info_ptr], eax, [num_trans], 0
+ @@:
+
+ mov eax,[entries]
+ mov [ebx+png_image.colormap_entries],eax
+popad
+ ret
+endp
+
+;int (voidp argument)
+align 4
+proc png_image_write_main uses ebx ecx edx esi edi, argument:dword
+locals
+ display dd ? ;= png_image_write_control * = argument
+ image dd ? ;= display->image
+ png_ptr dd ? ;= image->opaque->png_ptr
+ info_ptr dd ? ;= image->opaque->info_ptr
+ format dd ? ;= image->format
+
+ colormap dd ?
+ linear dd ?
+ alpha dd ?
+ write_16bit dd ? ;= linear && !colormap && (display->convert_to_8bit == 0)
+endl
+ mov edx,[argument]
+ mov [display],edx
+ mov ebx,[edx+png_image_write_control.image]
+ mov [image],ebx
+ mov ecx,[ebx+png_image.format]
+ mov [format],ecx
+ mov eax,[ebx+png_image.opaque]
+ mov edi,[eax+png_control.png_ptr]
+ mov [png_ptr],edi
+ mov esi,[eax+png_control.info_ptr]
+ mov [info_ptr],esi
+
+ ; The following four ints are actually booleans
+ and ecx,PNG_FORMAT_FLAG_COLORMAP
+ mov [colormap],ecx
+ not ecx
+ mov eax,[format]
+ and eax,PNG_FORMAT_FLAG_LINEAR
+ mov [linear],eax
+ mov eax,[format]
+ and eax,ecx
+ and eax,PNG_FORMAT_FLAG_ALPHA
+ and eax,ecx
+ mov [alpha],eax
+ xor eax,eax ;false
+ cmp dword[edx+png_image_write_control.convert_to_8bit],0
+ jne @f
+ not eax ;true
+ @@:
+ and eax,[linear]
+ and eax,ecx
+ mov [write_16bit],eax
+
+if PNG_BENIGN_ERRORS_SUPPORTED eq 1
+ ; Make sure we error out on any bad situation
+ stdcall png_set_benign_errors, edi, 0 ;error
+end if
+
+ ; Default the 'row_stride' parameter if required, also check the row stride
+ ; and total image size to ensure that they are within the system limits.
+
+ PNG_IMAGE_PIXEL_CHANNELS [ebx+png_image.format]
+ ;eax = channels
+
+ push edx
+ mov ecx,eax
+ mov eax,0x7FFFFFFF
+ xor edx,edx
+ div ecx
+ pop edx
+ cmp [ebx+png_image.width],eax
+ jg .end0 ;if (..<=..) ;no overflow
+ imul ecx,[ebx+png_image.width]
+
+ cmp dword[edx+png_image_write_control.row_stride],0
+ jne @f ;if (..==0)
+ mov [edx+png_image_write_control.row_stride],ecx
+ @@:
+ mov eax,[edx+png_image_write_control.row_stride]
+ cmp eax,0
+ jge .end2 ;if (..<0)
+ neg eax
+ inc eax
+ .end2:
+
+ cmp eax,ecx
+ jl .end3 ;if (..>=..)
+ ; Now check for overflow of the image buffer calculation; this
+ ; limits the whole image size to 32 bits for API compatibility with
+ ; the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro.
+
+ push edx
+ mov eax,0xFFFFFFFF
+ xor edx,edx
+ div ecx
+ pop edx
+ cmp [ebx+png_image.height],eax
+ jle @f ;if (..>..)
+ mov eax,[ebx+png_image.opaque]
+ mov eax,[eax+png_control.png_ptr]
+ png_error eax, 'memory image too large'
+ @@:
+ jmp .end1
+ .end3: ;else
+ mov eax,[ebx+png_image.opaque]
+ mov eax,[eax+png_control.png_ptr]
+ png_error eax, 'supplied row stride too small'
+ jmp .end1
+ .end0: ;else
+ mov eax,[ebx+png_image.opaque]
+ mov eax,[eax+png_control.png_ptr]
+ png_error eax, 'image row stride too large'
+ .end1:
+
+ ; Set the required transforms then write the rows in the correct order.
+ mov eax,[format]
+ and eax,PNG_FORMAT_FLAG_COLORMAP
+ jz .end4 ;if (..!=0)
+ cmp dword[edx+png_image_write_control.colormap],0
+ je .end6
+ mov eax,[ebx+png_image.colormap_entries]
+ cmp eax,0
+ jle .end6 ;if (..!=0 && ..>0)
+ ;eax = entries
+ xor ecx,ecx
+ inc ecx ;=1
+ cmp eax,2
+ jle @f
+ shl ecx,1 ;=2
+ cmp eax,4
+ jle @f
+ shl ecx,1 ;=4
+ cmp eax,16
+ jle @f
+ shl ecx,1 ;=8
+ @@:
+ stdcall png_set_IHDR, edi, esi, [ebx+png_image.width], [ebx+png_image.height],\
+ ecx, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,\
+ PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE
+
+ stdcall png_image_set_PLTE, edx
+ jmp .end5
+ .end6: ;else
+ mov eax,[ebx+png_image.opaque]
+ mov eax,[eax+png_control.png_ptr]
+ png_error eax, 'no color-map for color-mapped image'
+ jmp .end5
+ .end4: ;else
+ xor ecx,ecx
+ mov eax,[format]
+ and eax,PNG_FORMAT_FLAG_COLOR
+ jz @f
+ or ecx,PNG_COLOR_MASK_COLOR
+ @@:
+ mov eax,[format]
+ and eax,PNG_FORMAT_FLAG_ALPHA
+ jz @f
+ or ecx,PNG_COLOR_MASK_ALPHA
+ @@:
+ mov eax,8
+ cmp dword[write_16bit],0
+ je @f
+ mov eax,16
+ @@:
+ stdcall png_set_IHDR, edi, esi, [ebx+png_image.width], [ebx+png_image.height],\
+ eax, ecx, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE
+ .end5:
+
+ ; Counter-intuitively the data transformations must be called *after*
+ ; png_write_info, not before as in the read code, but the 'set' functions
+ ; must still be called before. Just set the color space information, never
+ ; write an interlaced image.
+
+ cmp dword[write_16bit],0
+ je @f ;if (..!=0)
+ ; The gamma here is 1.0 (linear) and the cHRM chunk matches sRGB.
+ stdcall png_set_gAMA_fixed, edi, esi, PNG_GAMMA_LINEAR
+
+ mov eax,[ebx+png_image.flags]
+ and eax,PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB
+ jnz @f ;if (..==0)
+ stdcall png_set_cHRM_fixed, edi, esi,\
+ 31270, 32900,\ ;white
+ 64000, 33000,\ ;red
+ 30000, 60000,\ ;green
+ 15000, 6000 ;blue
+ jmp .end7
+ @@:
+ mov eax,[ebx+png_image.flags]
+ and eax,PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB
+ jnz @f ;else if (..==0)
+ stdcall png_set_sRGB, edi, esi, PNG_sRGB_INTENT_PERCEPTUAL
+ jmp .end7
+ @@: ;else
+ ; Else writing an 8-bit file and the *colors* aren't sRGB, but the 8-bit
+ ; space must still be gamma encoded.
+ stdcall png_set_gAMA_fixed, edi, esi, PNG_GAMMA_sRGB_INVERSE
+ .end7:
+
+ ; Write the file header.
+ stdcall png_write_info, edi, esi
+
+ ; Now set up the data transformations (*after* the header is written),
+ ; remove the handled transformations from the 'format' flags for checking.
+
+ ; First check for a little endian system if writing 16-bit files.
+
+ cmp dword[write_16bit],0
+ je @f ;if (..!=0)
+; uint_16 le = 0x0001;
+
+; if ((*(bytep) & le) != 0)
+ stdcall png_set_swap, edi
+ @@:
+
+if PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED eq 1
+ mov eax,[format]
+ and eax,PNG_FORMAT_FLAG_BGR
+ jz .end12 ;if (..!=0)
+ cmp dword[colormap],0
+ jne @f
+ mov eax,[format]
+ and eax,PNG_FORMAT_FLAG_COLOR
+ jz @f ;if (..==0 && ..!=0)
+ stdcall png_set_bgr, edi
+ @@:
+ and dword[format], not PNG_FORMAT_FLAG_BGR
+ .end12:
+end if
+
+if PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED eq 1
+ mov eax,[format]
+ and eax,PNG_FORMAT_FLAG_AFIRST
+ jz .end13 ;if (..!=0)
+ cmp dword[colormap],0
+ jne @f
+ mov eax,[format]
+ and eax,PNG_FORMAT_FLAG_ALPHA
+ jz @f ;if (..==0 && ..!=0)
+ stdcall png_set_swap_alpha, edi
+ @@:
+ and dword[format], not PNG_FORMAT_FLAG_AFIRST
+ .end13:
+end if
+
+ ; If there are 16 or fewer color-map entries we wrote a lower bit depth
+ ; above, but the application data is still byte packed.
+
+ cmp dword[colormap],0
+ je @f
+ cmp dword[ebx+png_image.colormap_entries],16
+ jg @f ;if (..!=0 && ..<=16)
+ stdcall png_set_packing, edi
+ @@:
+
+ ; That should have handled all (both) the transforms.
+ mov eax,[format]
+ and eax, not (PNG_FORMAT_FLAG_COLOR or PNG_FORMAT_FLAG_LINEAR or PNG_FORMAT_FLAG_ALPHA or PNG_FORMAT_FLAG_COLORMAP)
+ jz @f ;if (..!=0)
+ png_error edi, 'png_write_image: unsupported transformation'
+ @@:
+
+ push esi
+ ;ecx - row ;bytep
+ ;esi - row_bytes
+ mov ecx,[edx+png_image_write_control.buffer]
+ mov esi,[edx+png_image_write_control.row_stride]
+
+ cmp dword[linear],0
+ je @f ;if (..!=0)
+ shl esi,1 ;*= sizeof.uint_16
+ @@:
+ cmp esi,0
+ jge @f ;if (..<0)
+ mov eax,[ebx+png_image.height]
+ dec eax
+ imul eax,esi
+ sub ecx,eax
+ @@:
+ mov [edx+png_image_write_control.first_row],ecx
+ mov [edx+png_image_write_control.row_bytes],esi
+ pop esi
+
+ ; Apply 'fast' options if the flag is set.
+ mov eax,[ebx+png_image.flags]
+ and eax,PNG_IMAGE_FLAG_FAST
+ jz @f ;if (..!=0)
+ stdcall png_set_filter, edi, PNG_FILTER_TYPE_BASE, PNG_NO_FILTERS
+ ; NOTE: determined by experiment using pngstest, this reflects some
+ ; balance between the time to write the image once and the time to read
+ ; it about 50 times. The speed-up in pngstest was about 10-20% of the
+ ; total (user) time on a heavily loaded system.
+
+if PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED eq 1
+ stdcall png_set_compression_level, edi, 3
+end if
+ @@:
+
+ ; Check for the cases that currently require a pre-transform on the row
+ ; before it is written. This only applies when the input is 16-bit and
+ ; either there is an alpha channel or it is converted to 8-bit.
+
+ cmp dword[linear],0
+ je @f
+ cmp dword[alpha],0
+ je @f
+ jmp .end10
+ @@:
+ cmp dword[colormap],0
+ jne .end9
+ cmp dword[edx+png_image_write_control.convert_to_8bit],0
+ je .end9
+ .end10: ;if ((..!=0 && ..!=0 ) || (..==0 && ..!=0))
+ stdcall png_get_rowbytes, edi, esi
+ stdcall png_malloc, edi, eax
+ mov ecx,eax ;ecx = row
+
+ mov [edx+png_image_write_control.local_row],ecx
+ cmp dword[write_16bit],0
+ je @f ;if (..!=0)
+ stdcall png_safe_execute, ebx, png_write_image_16bit, edx
+ jmp .end11
+ @@: ;else
+ stdcall png_safe_execute, ebx, png_write_image_8bit, edx
+ .end11:
+ mov dword[edx+png_image_write_control.local_row],0
+
+ stdcall png_free, edi, ecx
+
+ ; Skip the 'write_end' on error:
+ test eax,eax
+ jz .end_f ;if (..==0) return 0
+ jmp .end8
+
+ ; Otherwise this is the case where the input is in a format currently
+ ; supported by the rest of the libpng write code; call it directly.
+
+ .end9: ;else
+if 1 ;;; IDAT compress all (only 24 bit)
+ cmp dword[ebx+png_image.height],1
+ jl .end8
+ mov ecx,[edx+png_image_write_control.row_bytes]
+ inc ecx
+ imul ecx,[ebx+png_image.height]
+ stdcall create_compress_IDAT, edi, [edx+png_image_write_control.first_row], ecx, [ebx+png_image.width], [ebx+png_image.height]
+else ;;; IDAT compress by lines
+ mov ecx,[ebx+png_image.height]
+ cmp ecx,1
+ jl .end8
+ mov eax,[edx+png_image_write_control.first_row]
+ mov ebx,[edx+png_image_write_control.row_bytes]
+ @@:
+ stdcall png_write_row, edi, eax
+ add eax, ebx
+ loop @b
+end if
+ .end8:
+
+ stdcall png_write_end, edi, esi
+ xor eax,eax
+ inc eax
+.end_f:
+ ret
+endp
+
+align 16
+proc create_compress_IDAT, png_ptr:dword, buf:dword, len:dword, width:dword, height:dword
+locals
+ m1 dd ? ;memory for compress IDAT
+ buf_f dd ? ;memory for IDAT
+ mins dd ? ;minimum sum
+endl
+pushad
+ mov edi,[png_ptr]
+png_debug 1, 'IDAT compress all'
+
+ ;create buffer with filters
+ stdcall png_zalloc, edi, 1, [len]
+ test eax,eax
+ jz .end_f
+ mov [buf_f],eax
+
+ mov eax,ZLIB_IO_MAX
+ cmp eax,[len]
+ jge @f
+ mov eax,[len]
+ @@:
+ stdcall png_zalloc, edi, 1, eax
+ test eax,eax
+ jz .end0
+ mov [m1],eax
+
+ ;init buffer with filters
+ mov ebx,[width]
+ mov edx,[height]
+ mov edi,[buf_f]
+ mov esi,[buf]
+ .cycle0:
+ cmp edx,1
+ jl .cycle0end
+ mov ecx,ebx
+ xor al,al
+ stosb ;insert filter (0 - none)
+align 4
+ .cycle1:
+ lodsb ;1
+ inc edi ;
+ movsb ;2
+ stosb ;3
+ lodsb ;
+ mov [edi-3],al
+ loop .cycle1
+ dec edx
+ jmp .cycle0
+ .cycle0end:
+
+ ;make filters
+ mov edx,[height]
+ mov esi,[width]
+ imul esi,3 ;esi - rowbytes
+
+ inc esi
+ mov edi,[png_ptr]
+ cmp dword[edi+png_struct.try_row],0
+ jne @f ;if (..==0)
+ stdcall png_malloc, edi, esi
+ mov [edi+png_struct.try_row],eax
+ @@:
+ cmp dword[edi+png_struct.tst_row],0
+ jne @f ;if (..==0)
+ stdcall png_malloc, edi, esi
+ mov [edi+png_struct.tst_row],eax
+ @@:
+ dec esi
+
+ mov edi,[buf_f]
+ add edi,[len]
+ .cycle3:
+ dec edx
+ cmp edx,1
+ jl .cycle3end
+ sub edi,esi
+ dec edi ;move in perv row
+
+ ;init pointers for function png_setup_up_row
+ mov ebx,[png_ptr]
+ mov [ebx+png_struct.row_buf],edi
+ mov [ebx+png_struct.prev_row],edi
+ sub [ebx+png_struct.prev_row],esi
+ dec dword[ebx+png_struct.prev_row]
+
+ ;calculate start minimum sum
+ push esi
+ xor eax,eax
+ xor ebx,ebx
+ mov ecx,esi
+ mov esi,edi
+ inc esi
+ .cycle2:
+ lodsb
+ png_setup_abs ebx
+ loop .cycle2
+ pop esi
+ mov [mins],ebx
+
+ push edx
+ mov edx,[png_ptr]
+ mov eax,[edx+png_struct.tst_row]
+ mov byte[eax],0 ;not filter
+
+ ; Up filter
+ stdcall png_setup_up_row, edx, esi, [mins]
+ cmp eax,[mins]
+ jge @f ;if (..<..)
+ mov [mins],eax
+ stdcall copy_row_mins, [edx+png_struct.tst_row], [edx+png_struct.try_row]
+ @@:
+
+ ; Find out how many bytes offset each pixel is
+ movzx ebx,byte[edx+png_struct.pixel_depth]
+ add ebx,7
+ shr ebx,3
+
+ ; Sub filter
+ stdcall png_setup_sub_row, edx, ebx, esi, [mins]
+ cmp eax,[mins]
+ jge @f ;if (..<..)
+ mov [mins],eax
+ stdcall copy_row_mins, [edx+png_struct.tst_row], [edx+png_struct.try_row]
+ @@:
+
+ ; Avg filter
+ stdcall png_setup_avg_row, edx, ebx, esi, [mins]
+ cmp eax,[mins]
+ jge @f ;if (..<..)
+ mov [mins],eax
+ stdcall copy_row_mins, [edx+png_struct.tst_row], [edx+png_struct.try_row]
+ @@:
+
+ ; Paeth filter
+ stdcall png_setup_paeth_row, edx, ebx, esi, [mins]
+ cmp eax,[mins]
+ jge @f ;if (..<..)
+ mov [mins],eax
+ stdcall copy_row_mins, [edx+png_struct.tst_row], [edx+png_struct.try_row]
+ @@:
+
+ ; Copy best row
+ mov eax,[edx+png_struct.tst_row]
+ cmp byte[eax],0
+ je @f
+ stdcall copy_row_mins, edi, [edx+png_struct.tst_row]
+ @@:
+ pop edx
+ jmp .cycle3
+ .cycle3end:
+
+ mov edi,[png_ptr]
+ mov esi,edi
+ add esi,png_struct.zstream
+ stdcall [deflateInit2], esi,\
+ -1, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY
+
+ mov eax,[buf_f]
+ mov [edi+png_struct.zstream.next_in],eax
+ mov eax,[len]
+ mov [edi+png_struct.zstream.avail_in],eax
+ mov eax,[m1]
+ mov [edi+png_struct.zstream.next_out],eax
+ xor ecx,ecx
+align 4
+ .cycle4:
+ mov dword[edi+png_struct.zstream.avail_out],16*1024
+
+ stdcall [deflate], esi, Z_FINISH ;Z_NO_FLUSH
+ cmp eax,Z_STREAM_ERROR
+ je .end1
+
+ add ecx,16*1024
+ sub ecx,[edi+png_struct.zstream.avail_out]
+ cmp dword[edi+png_struct.zstream.avail_out],0
+ je .cycle4 ;while (strm.avail_out == 0)
+if 0
+ mov dword[edi+png_struct.zstream.avail_out],16*1024
+ stdcall [deflate], esi, Z_FINISH
+ add ecx,16*1024
+ sub ecx,[edi+png_struct.zstream.avail_out]
+ cmp eax,Z_STREAM_ERROR
+ je .end1
+end if
+ stdcall [deflateEnd], esi
+
+if PNG_WRITE_OPTIMIZE_CMF_SUPPORTED eq 1
+ mov eax,[edi+png_struct.mode]
+ and eax,PNG_HAVE_IDAT
+ jnz @f
+ cmp byte[edi+png_struct.compression_type],PNG_COMPRESSION_TYPE_BASE
+ jne @f ;if (..==0 && ..==..)
+ stdcall png_image_size, edi
+ stdcall optimize_cmf, [m1], eax
+ @@:
+end if
+ stdcall png_write_complete_chunk, edi, png_IDAT, [m1], ecx
+ or dword[edi+png_struct.mode],PNG_HAVE_IDAT
+
+ jmp @f
+ .end1:
+ png_debug 1, 'Z_STREAM_ERROR'
+ @@:
+
+ ;free memory
+ cmp dword[edi+png_struct.try_row],0
+ je @f ;if (..!=0)
+ stdcall png_free, edi, [edi+png_struct.try_row]
+ mov dword[edi+png_struct.try_row],0
+ @@:
+ cmp dword[edi+png_struct.tst_row],0
+ je @f ;if (..!=0)
+ stdcall png_free, edi, [edi+png_struct.tst_row]
+ mov dword[edi+png_struct.tst_row],0
+ @@:
+ stdcall png_free, edi, [m1]
+.end0:
+ stdcall png_free, edi, [buf_f]
+.end_f:
+popad
+ ret
+endp
+
+;input:
+; esi - rowbytes
+align 4
+proc copy_row_mins uses edi esi, dest:dword, sour:dword
+ mov ecx,esi
+ inc ecx
+ mov edi,[dest]
+ mov esi,[sour]
+ rep movsb
+ ret
+endp
+
+;void (png_structp png_ptr, bytep/*const*/ data, png_size_t size)
+align 4
+proc image_memory_write uses eax ebx ecx edi esi, png_ptr:dword, p2data:dword, size:dword
+ mov edi,[png_ptr]
+ mov esi,[edi+png_struct.io_ptr] ;esi = png_image_write_control *display
+ mov ebx,[esi+png_image_write_control.output_bytes] ;ebx = ob
+
+ ; Check for overflow; this should never happen:
+ mov eax,PNG_SIZE_MAX
+ sub eax,ebx
+ mov ecx,[size]
+ cmp ecx,eax
+ jg .end1 ;if (..<=..)
+ ; I don't think libpng ever does this, but just in case:
+ cmp ecx,0
+ jle .end0 ;if (..>0)
+ mov eax,ebx
+ add eax,ecx
+ cmp [esi+png_image_write_control.memory_bytes],eax
+ jl @f ;if (..>=..) ;writing
+ push esi
+ mov edi,[esi+png_image_write_control.memory]
+ add edi,ebx
+ mov esi,[p2data]
+ rep movsb ;memcpy(...
+ pop esi
+ @@:
+
+ ; Always update the size:
+ add ebx,[size]
+ mov [esi+png_image_write_control.output_bytes],ebx
+ .end0:
+ jmp .end2
+ .end1: ;else
+ png_error edi, 'png_image_write_to_memory: PNG too big'
+ .end2:
+ ret
+endp
+
+;void (png_structp png_ptr)
+align 4
+proc image_memory_flush, png_ptr:dword
+ ret
+endp
+
+;int (voidp argument)
+align 4
+proc png_image_write_memory uses ebx, argument:dword
+ ; The rest of the memory-specific init and write_main in an error protected
+ ; environment. This case needs to use callbacks for the write operations
+ ; since libpng has no built in support for writing to memory.
+
+ mov eax,[argument]
+ mov ebx,[eax+png_image_write_control.image]
+ mov ebx,[ebx+png_image.opaque]
+ stdcall png_set_write_fn, [ebx+png_control.png_ptr], eax, image_memory_write, image_memory_flush
+
+ stdcall png_image_write_main, [argument]
+ ret
+endp
+
+;int (png_imagep image, void *memory,
+; png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8bit,
+; const void *buffer, int_32 row_stride, const void *colormap)
+align 4
+proc png_image_write_to_memory uses ebx ecx edx edi esi, image:dword, memory:dword,\
+ memory_bytes:dword, convert_to_8bit:dword, buffer:dword, row_stride:dword, colormap:dword
+locals
+ display png_image_write_control ;local struct
+endl
+;edi - display png_image_write_control
+
+ ; Write the image to the given buffer, or count the bytes if it is NULL
+ mov ebx,[image]
+ cmp ebx,0
+ je .end0
+ cmp dword[ebx+png_image.version],PNG_IMAGE_VERSION
+ jne .end0 ;if (..!=0 && ..==..)
+ cmp dword[memory_bytes],0
+ je .end2
+ cmp dword[buffer],0
+ je .end2 ;if (..!=0 && ..!=0)
+ ; This is to give the caller an easier error detection in the NULL
+ ; case and guard against uninitialized variable problems:
+
+ cmp dword[memory],0
+ jne @f ;if(..==0)
+ mov eax,[memory_bytes]
+ mov dword[eax],0
+ @@:
+
+ stdcall png_image_write_init, ebx
+ test eax,eax
+ jz .end3 ;if (..!=0)
+ mov ecx,sizeof.png_image_write_control
+ mov edi,ebp
+ sub edi,ecx
+ xor eax,eax
+ rep stosb ;memset(&display, 0, sizeof.display))
+ sub edi,sizeof.png_image_write_control
+ mov [edi+png_image_write_control.image],ebx
+ mov eax,[buffer]
+ mov [edi+png_image_write_control.buffer],eax
+ mov eax,[row_stride]
+ mov [edi+png_image_write_control.row_stride],eax
+ mov eax,[colormap]
+ mov [edi+png_image_write_control.colormap],eax
+ mov eax,[convert_to_8bit]
+ mov [edi+png_image_write_control.convert_to_8bit],eax
+ mov eax,[memory]
+ mov [edi+png_image_write_control.memory],eax
+ mov eax,[memory_bytes]
+ mov eax,[eax]
+ mov [edi+png_image_write_control.memory_bytes],eax
+ mov dword[edi+png_image_write_control.output_bytes], 0
+
+ stdcall png_safe_execute, ebx, png_image_write_memory, edi
+ mov ecx,eax ;ecx = result
+ stdcall png_image_free, ebx
+
+ ; write_memory returns true even if we ran out of buffer.
+ cmp ecx,0 ;if (..)
+ je .end4
+ ; On out-of-buffer this function returns '0' but still updates
+ ; memory_bytes:
+
+ mov edx,[edi+png_image_write_control.output_bytes]
+ mov eax,[memory_bytes]
+ cmp dword[memory],0
+ je @f ;if (..!=0 && ..>..)
+ cmp edx,[eax]
+ jle @f
+ xor ecx,ecx
+ @@:
+ mov [eax],edx
+ .end4:
+
+ mov eax,ecx
+ jmp .end_f
+ .end3: ;else
+ xor eax,eax
+ jmp .end_f
+ .end2: ;else
+ std_png_image_error ebx, 'png_image_write_to_memory: invalid argument'
+ jmp .end_f
+ .end0:
+ cmp ebx,0
+ je .end1 ;else if (..!=0)
+ std_png_image_error ebx, 'png_image_write_to_memory: incorrect PNG_IMAGE_VERSION'
+ jmp .end_f
+ .end1: ;else
+ xor eax,eax
+.end_f:
+ ret
+endp
+
+;int (png_imagep image, FILE *file, int convert_to_8bit,
+; const void *buffer, int_32 row_stride, const void *colormap)
+align 4
+proc png_image_write_to_stdio, image:dword, file:dword, convert_to_8bit:dword, buffer:dword, row_stride:dword, colormap:dword
+ ; Write the image to the given (FILE*).
+; if (image != NULL && image->version == PNG_IMAGE_VERSION)
+; {
+; if (file != NULL && buffer != NULL)
+; {
+; if (png_image_write_init(image) != 0)
+; {
+; png_image_write_control display;
+; int result;
+
+ ; This is slightly evil, but png_init_io doesn't do anything other
+ ; than this and we haven't changed the standard IO functions so
+ ; this saves a 'safe' function.
+
+; image->opaque->png_ptr->io_ptr = file;
+
+; memset(&display, 0, (sizeof display));
+; display.image = image;
+; display.buffer = buffer;
+; display.row_stride = row_stride;
+; display.colormap = colormap;
+; display.convert_to_8bit = convert_to_8bit;
+
+; result = png_safe_execute(image, png_image_write_main, &display);
+; png_image_free(image);
+; return result;
+; }
+
+; else
+; return 0;
+; }
+
+; else
+; return png_image_error(image,
+; "png_image_write_to_stdio: invalid argument");
+; }
+
+; else if (image != NULL)
+; return png_image_error(image,
+; "png_image_write_to_stdio: incorrect PNG_IMAGE_VERSION");
+
+; else
+; return 0;
+ ret
+endp
+
+;int (png_imagep image, const char *file_name,
+; int convert_to_8bit, const void *buffer, int_32 row_stride,
+; const void *colormap)
+align 4
+proc png_image_write_to_file, image:dword, file_name:dword, convert_to_8bit:dword, buffer:dword, row_stride:dword, colormap:dword
+ ; Write the image to the named file.
+; if (image != NULL && image->version == PNG_IMAGE_VERSION)
+; {
+; if (file_name != NULL && buffer != NULL)
+; {
+; FILE *fp = fopen(file_name, "wb");
+
+; if (fp != NULL)
+; {
+; if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer,
+; row_stride, colormap) != 0)
+; {
+; int error; /* from fflush/fclose */
+
+ ; Make sure the file is flushed correctly.
+; if (fflush(fp) == 0 && ferror(fp) == 0)
+; {
+; if (fclose(fp) == 0)
+; return 1;
+
+; error = errno; /* from fclose */
+; }
+
+; else
+; {
+; error = errno; /* from fflush or ferror */
+; (void)fclose(fp);
+; }
+
+; (void)remove(file_name);
+ ; The image has already been cleaned up; this is just used to
+ ; set the error (because the original write succeeded).
+
+; return png_image_error(image, strerror(error));
+; }
+
+; else
+; {
+ ; Clean up: just the opened file.
+; (void)fclose(fp);
+; (void)remove(file_name);
+; return 0;
+; }
+; }
+
+; else
+; return png_image_error(image, strerror(errno));
+; }
+
+; else
+; return png_image_error(image,
+; "png_image_write_to_file: invalid argument");
+; }
+
+; else if (image != NULL)
+; return png_image_error(image,
+; "png_image_write_to_file: incorrect PNG_IMAGE_VERSION");
+
+; else
+; return 0;
+ ret
+endp
+end if ;SIMPLIFIED_WRITE
diff --git a/programs/develop/libraries/libs-dev/libimg/png/libpng/pngwtran.asm b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngwtran.asm
index c5d3cc269..c13ba8165 100644
--- a/programs/develop/libraries/libs-dev/libimg/png/libpng/pngwtran.asm
+++ b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngwtran.asm
@@ -1,600 +1,600 @@
-
-; pngwtran.asm - transforms the data in a row for PNG writers
-
-; Last changed in libpng 1.6.24 [August 4, 2016]
-; Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
-; (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
-; (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
-
-; This code is released under the libpng license.
-; For conditions of distribution and use, see the disclaimer
-; and license in png.inc
-
-
-; Pack pixels into bytes. Pass the true bit depth in bit_depth. The
-; row_info bit depth should be 8 (one pixel per byte). The channels
-; should be 1 (this only happens on grayscale and paletted images).
-
-;void (png_row_infop row_info, bytep row, uint_32 bit_depth)
-align 4
-proc png_do_pack, row_info:dword, row:dword, bit_depth:dword
- png_debug 1, 'in png_do_pack'
-
-; if (row_info->bit_depth == 8 &&
-; row_info->channels == 1)
-; {
-; switch ((int)bit_depth)
-; {
-; case 1:
-; {
-; bytep sp, dp;
-; int mask, v;
-; uint_32 i;
-; uint_32 row_width = row_info->width;
-
-; sp = row;
-; dp = row;
-; mask = 0x80;
-; v = 0;
-
-; for (i = 0; i < row_width; i++)
-; {
-; if (*sp != 0)
-; v |= mask;
-
-; sp++;
-
-; if (mask > 1)
-; mask >>= 1;
-
-; else
-; {
-; mask = 0x80;
-; *dp = (byte)v;
-; dp++;
-; v = 0;
-; }
-; }
-
-; if (mask != 0x80)
-; *dp = (byte)v;
-
-; break;
-; }
-
-; case 2:
-; {
-; bytep sp, dp;
-; unsigned int shift;
-; int v;
-; uint_32 i;
-; uint_32 row_width = row_info->width;
-
-; sp = row;
-; dp = row;
-; shift = 6;
-; v = 0;
-
-; for (i = 0; i < row_width; i++)
-; {
-; byte value;
-
-; value = (byte)(*sp & 0x03);
-; v |= (value << shift);
-
-; if (shift == 0)
-; {
-; shift = 6;
-; *dp = (byte)v;
-; dp++;
-; v = 0;
-; }
-
-; else
-; shift -= 2;
-;
-; sp++;
-; }
-
-; if (shift != 6)
-; *dp = (byte)v;
-
-; break;
-; }
-
-; case 4:
-; {
-; bytep sp, dp;
-; unsigned int shift;
-; int v;
-; uint_32 i;
-; uint_32 row_width = row_info->width;
-
-; sp = row;
-; dp = row;
-; shift = 4;
-; v = 0;
-
-; for (i = 0; i < row_width; i++)
-; {
-; byte value;
-
-; value = (byte)(*sp & 0x0f);
-; v |= (value << shift);
-
-; if (shift == 0)
-; {
-; shift = 4;
-; *dp = (byte)v;
-; dp++;
-; v = 0;
-; }
-
-; else
-; shift -= 4;
-;
-; sp++;
-; }
-
-; if (shift != 4)
-; *dp = (byte)v;
-
-; break;
-; }
-
-; default:
-; break;
-; }
-
-; row_info->bit_depth = (byte)bit_depth;
-; row_info->pixel_depth = (byte)(bit_depth * row_info->channels);
-; row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
-; row_info->width);
-; }
- ret
-endp
-
-; Shift pixel values to take advantage of whole range. Pass the
-; true number of bits in bit_depth. The row should be packed
-; according to row_info->bit_depth. Thus, if you had a row of
-; bit depth 4, but the pixels only had values from 0 to 7, you
-; would pass 3 as bit_depth, and this routine would translate the
-; data to 0 to 15.
-
-;void (png_row_infop row_info, bytep row, png_const_color_8p bit_depth)
-align 4
-proc png_do_shift, row_info:dword, row:dword, bit_depth:dword
- png_debug 1, 'in png_do_shift'
-
-; if (row_info->color_type != PNG_COLOR_TYPE_PALETTE)
-; {
-; int shift_start[4], shift_dec[4];
-; int channels = 0;
-
-; if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
-; {
-; shift_start[channels] = row_info->bit_depth - bit_depth->red;
-; shift_dec[channels] = bit_depth->red;
-; channels++;
-
-; shift_start[channels] = row_info->bit_depth - bit_depth->green;
-; shift_dec[channels] = bit_depth->green;
-; channels++;
-
-; shift_start[channels] = row_info->bit_depth - bit_depth->blue;
-; shift_dec[channels] = bit_depth->blue;
-; channels++;
-; }
-
-; else
-; {
-; shift_start[channels] = row_info->bit_depth - bit_depth->gray;
-; shift_dec[channels] = bit_depth->gray;
-; channels++;
-; }
-
-; if ((row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
-; {
-; shift_start[channels] = row_info->bit_depth - bit_depth->alpha;
-; shift_dec[channels] = bit_depth->alpha;
-; channels++;
-; }
-
- ; With low row depths, could only be grayscale, so one channel
-; if (row_info->bit_depth < 8)
-; {
-; bytep bp = row;
-; png_size_t i;
-; unsigned int mask;
-; png_size_t row_bytes = row_info->rowbytes;
-
-; if (bit_depth->gray == 1 && row_info->bit_depth == 2)
-; mask = 0x55;
-
-; else if (row_info->bit_depth == 4 && bit_depth->gray == 3)
-; mask = 0x11;
-
-; else
-; mask = 0xff;
-
-; for (i = 0; i < row_bytes; i++, bp++)
-; {
-; int j;
-; unsigned int v, out;
-
-; v = *bp;
-; out = 0;
-
-; for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0])
-; {
-; if (j > 0)
-; out |= v << j;
-
-; else
-; out |= (v >> (-j)) & mask;
-; }
-
-; *bp = (byte)(out & 0xff);
-; }
-; }
-
-; else if (row_info->bit_depth == 8)
-; {
-; bytep bp = row;
-; uint_32 i;
-; uint_32 istop = channels * row_info->width;
-
-; for (i = 0; i < istop; i++, bp++)
-; {
-
-; const unsigned int c = i%channels;
-; int j;
-; unsigned int v, out;
-
-; v = *bp;
-; out = 0;
-
-; for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
-; {
-; if (j > 0)
-; out |= v << j;
-
-; else
-; out |= v >> (-j);
-; }
-
-; *bp = (byte)(out & 0xff);
-; }
-; }
-
-; else
-; {
-; bytep bp;
-; uint_32 i;
-; uint_32 istop = channels * row_info->width;
-
-; for (bp = row, i = 0; i < istop; i++)
-; {
-; const unsigned int c = i%channels;
-; int j;
-; unsigned int value, v;
-
-; v = png_get_uint_16(bp);
-; value = 0;
-
-; for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
-; {
-; if (j > 0)
-; value |= v << j;
-
-; else
-; value |= v >> (-j);
-; }
-; *bp++ = (byte)((value >> 8) & 0xff);
-; *bp++ = (byte)(value & 0xff);
-; }
-; }
-; }
- ret
-endp
-
-;void (png_row_infop row_info, bytep row)
-align 4
-proc png_do_write_swap_alpha, row_info:dword, row:dword
- png_debug 1, 'in png_do_write_swap_alpha'
-
-; {
-; if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
-; {
-; if (row_info->bit_depth == 8)
-; {
- ; This converts from ARGB to RGBA
-; bytep sp, dp;
-; uint_32 i;
-; uint_32 row_width = row_info->width;
-
-; for (i = 0, sp = dp = row; i < row_width; i++)
-; {
-; byte save = *(sp++);
-; *(dp++) = *(sp++);
-; *(dp++) = *(sp++);
-; *(dp++) = *(sp++);
-; *(dp++) = save;
-; }
-; }
-
-if PNG_WRITE_16BIT_SUPPORTED eq 1
-; else
-; {
- ; This converts from AARRGGBB to RRGGBBAA
-; bytep sp, dp;
-; uint_32 i;
-; uint_32 row_width = row_info->width;
-;
-; for (i = 0, sp = dp = row; i < row_width; i++)
-; {
-; byte save[2];
-; save[0] = *(sp++);
-; save[1] = *(sp++);
-; *(dp++) = *(sp++);
-; *(dp++) = *(sp++);
-; *(dp++) = *(sp++);
-; *(dp++) = *(sp++);
-; *(dp++) = *(sp++);
-; *(dp++) = *(sp++);
-; *(dp++) = save[0];
-; *(dp++) = save[1];
-; }
-; }
-end if ;WRITE_16BIT
-; }
-;
-; else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
-; {
-; if (row_info->bit_depth == 8)
-; {
- ; This converts from AG to GA
-; bytep sp, dp;
-; uint_32 i;
-; uint_32 row_width = row_info->width;
-
-; for (i = 0, sp = dp = row; i < row_width; i++)
-; {
-; byte save = *(sp++);
-; *(dp++) = *(sp++);
-; *(dp++) = save;
-; }
-; }
-
-if PNG_WRITE_16BIT_SUPPORTED eq 1
-; else
-; {
- ; This converts from AAGG to GGAA
-; bytep sp, dp;
-; uint_32 i;
-; uint_32 row_width = row_info->width;
-
-; for (i = 0, sp = dp = row; i < row_width; i++)
-; {
-; byte save[2];
-; save[0] = *(sp++);
-; save[1] = *(sp++);
-; *(dp++) = *(sp++);
-; *(dp++) = *(sp++);
-; *(dp++) = save[0];
-; *(dp++) = save[1];
-; }
-; }
-end if ;WRITE_16BIT
-; }
-; }
- ret
-endp
-
-;void (png_row_infop row_info, bytep row)
-align 4
-proc png_do_write_invert_alpha, row_info:dword, row:dword
- png_debug 1, 'in png_do_write_invert_alpha'
-
-; if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
-; {
-; if (row_info->bit_depth == 8)
-; {
- ; This inverts the alpha channel in RGBA
-; bytep sp, dp;
-; uint_32 i;
-; uint_32 row_width = row_info->width;
-
-; for (i = 0, sp = dp = row; i < row_width; i++)
-; {
- ; Does nothing
- ;*(dp++) = *(sp++);
- ;*(dp++) = *(sp++);
- ;*(dp++) = *(sp++);
-
-; sp+=3; dp = sp;
-; *dp = (byte)(255 - *(sp++));
-; }
-; }
-
-;if PNG_WRITE_16BIT_SUPPORTED
-; else
-; {
- ; This inverts the alpha channel in RRGGBBAA
-; bytep sp, dp;
-; uint_32 i;
-; uint_32 row_width = row_info->width;
-
-; for (i = 0, sp = dp = row; i < row_width; i++)
-; {
- ; Does nothing
- ;*(dp++) = *(sp++);
- ;*(dp++) = *(sp++);
- ;*(dp++) = *(sp++);
- ;*(dp++) = *(sp++);
- ;*(dp++) = *(sp++);
- ;*(dp++) = *(sp++);
-
-; sp+=6; dp = sp;
-; *(dp++) = (byte)(255 - *(sp++));
-; *dp = (byte)(255 - *(sp++));
-; }
-; }
-;end if /* WRITE_16BIT */
-; }
-
-; else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
-; {
-; if (row_info->bit_depth == 8)
-; {
- ; This inverts the alpha channel in GA
-; bytep sp, dp;
-; uint_32 i;
-; uint_32 row_width = row_info->width;
-;
-; for (i = 0, sp = dp = row; i < row_width; i++)
-; {
-; *(dp++) = *(sp++);
-; *(dp++) = (byte)(255 - *(sp++));
-; }
-; }
-
-if PNG_WRITE_16BIT_SUPPORTED eq 1
-; else
-; {
- ; This inverts the alpha channel in GGAA
-; bytep sp, dp;
-; uint_32 i;
-; uint_32 row_width = row_info->width;
-;
-; for (i = 0, sp = dp = row; i < row_width; i++)
-; {
- ; Does nothing
- ;*(dp++) = *(sp++);
- ;*(dp++) = *(sp++);
-
-; sp+=2; dp = sp;
-; *(dp++) = (byte)(255 - *(sp++));
-; *dp = (byte)(255 - *(sp++));
-; }
-; }
-end if ;WRITE_16BIT
-; }
- ret
-endp
-
-; Transform the data according to the user's wishes. The order of
-; transformations is significant.
-
-;void (png_structrp png_ptr, png_row_infop row_info)
-align 4
-proc png_do_write_transformations uses eax ebx edi esi, png_ptr:dword, row_info:dword
- png_debug 1, 'in png_do_write_transformations'
-
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f ;if (..==0) return
- mov esi,[row_info]
- mov ebx,[edi+png_struct.row_buf]
- inc ebx ;start of pixel data for row
-
-if PNG_WRITE_USER_TRANSFORM_SUPPORTED eq 1
- mov eax,[edi+png_struct.transformations]
- and eax,PNG_USER_TRANSFORM
- jz @f ;if (..!=0)
- mov eax,[edi+png_struct.write_user_transform_fn]
- test eax,eax
- jz @f ;if (..!=0)
- stdcall eax, edi, esi, ebx ;User write transform function
- ; row_info:
- ; uint_32 width ;width of row
- ; png_size_t rowbytes ;number of bytes in row
- ; byte color_type ;color type of pixels
- ; byte bit_depth ;bit depth of samples
- ; byte channels ;number of channels (1-4)
- ; byte pixel_depth ;bits per pixel (depth*channels)
- @@:
-end if
-
-if PNG_WRITE_FILLER_SUPPORTED eq 1
- mov eax,[edi+png_struct.transformations]
- and eax,PNG_FILLER
- jz @f ;if (..!=0)
- mov eax,[edi+png_struct.flags]
- and eax,PNG_FLAG_FILLER_AFTER
- not eax
- stdcall png_do_strip_channel, esi, ebx, eax
- @@:
-end if
-
-if PNG_WRITE_PACKSWAP_SUPPORTED eq 1
- mov eax,[edi+png_struct.transformations]
- and eax,PNG_PACKSWAP
- jz @f ;if (..!=0)
- stdcall png_do_packswap, esi, ebx
- @@:
-end if
-
-if PNG_WRITE_PACK_SUPPORTED eq 1
- mov eax,[edi+png_struct.transformations]
- and eax,PNG_PACK
- jz @f ;if (..!=0)
- movzx eax,byte[edi+png_struct.bit_depth]
- stdcall png_do_pack, esi, ebx, eax
- @@:
-end if
-
-if PNG_WRITE_SWAP_SUPPORTED eq 1
-if PNG_16BIT_SUPPORTED eq 1
- mov eax,[edi+png_struct.transformations]
- and eax,PNG_SWAP_BYTES
- jz @f ;if (..!=0)
- stdcall png_do_swap, esi, ebx
- @@:
-end if
-end if
-
-if PNG_WRITE_SHIFT_SUPPORTED eq 1
- mov eax,[edi+png_struct.transformations]
- and eax,PNG_SHIFT
- jz @f ;if (..!=0)
- mov eax,edi
- add eax,png_struct.shift
- stdcall png_do_shift, esi, ebx, eax
- @@:
-end if
-
-if PNG_WRITE_SWAP_ALPHA_SUPPORTED eq 1
- mov eax,[edi+png_struct.transformations]
- and eax,PNG_SWAP_ALPHA
- jz @f ;if (..!=0)
- stdcall png_do_write_swap_alpha, esi, ebx
- @@:
-end if
-
-if PNG_WRITE_INVERT_ALPHA_SUPPORTED eq 1
- mov eax,[edi+png_struct.transformations]
- and eax,PNG_INVERT_ALPHA
- jz @f ;if (..!=0)
- stdcall png_do_write_invert_alpha, esi, ebx
- @@:
-end if
-
-if PNG_WRITE_BGR_SUPPORTED eq 1
- mov eax,[edi+png_struct.transformations]
- and eax,PNG_BGR
- jz @f ;if (..!=0)
- stdcall png_do_bgr, esi, ebx
- @@:
-end if
-
-if PNG_WRITE_INVERT_SUPPORTED eq 1
- mov eax,[edi+png_struct.transformations]
- and eax,PNG_INVERT_MONO
- jz @f ;if (..!=0)
- stdcall png_do_invert, esi, ebx
- @@:
-end if
-.end_f:
- ret
-endp
+
+; pngwtran.asm - transforms the data in a row for PNG writers
+
+; Last changed in libpng 1.6.24 [August 4, 2016]
+; Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
+; (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+; (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+
+; This code is released under the libpng license.
+; For conditions of distribution and use, see the disclaimer
+; and license in png.inc
+
+
+; Pack pixels into bytes. Pass the true bit depth in bit_depth. The
+; row_info bit depth should be 8 (one pixel per byte). The channels
+; should be 1 (this only happens on grayscale and paletted images).
+
+;void (png_row_infop row_info, bytep row, uint_32 bit_depth)
+align 4
+proc png_do_pack, row_info:dword, row:dword, bit_depth:dword
+ png_debug 1, 'in png_do_pack'
+
+; if (row_info->bit_depth == 8 &&
+; row_info->channels == 1)
+; {
+; switch ((int)bit_depth)
+; {
+; case 1:
+; {
+; bytep sp, dp;
+; int mask, v;
+; uint_32 i;
+; uint_32 row_width = row_info->width;
+
+; sp = row;
+; dp = row;
+; mask = 0x80;
+; v = 0;
+
+; for (i = 0; i < row_width; i++)
+; {
+; if (*sp != 0)
+; v |= mask;
+
+; sp++;
+
+; if (mask > 1)
+; mask >>= 1;
+
+; else
+; {
+; mask = 0x80;
+; *dp = (byte)v;
+; dp++;
+; v = 0;
+; }
+; }
+
+; if (mask != 0x80)
+; *dp = (byte)v;
+
+; break;
+; }
+
+; case 2:
+; {
+; bytep sp, dp;
+; unsigned int shift;
+; int v;
+; uint_32 i;
+; uint_32 row_width = row_info->width;
+
+; sp = row;
+; dp = row;
+; shift = 6;
+; v = 0;
+
+; for (i = 0; i < row_width; i++)
+; {
+; byte value;
+
+; value = (byte)(*sp & 0x03);
+; v |= (value << shift);
+
+; if (shift == 0)
+; {
+; shift = 6;
+; *dp = (byte)v;
+; dp++;
+; v = 0;
+; }
+
+; else
+; shift -= 2;
+;
+; sp++;
+; }
+
+; if (shift != 6)
+; *dp = (byte)v;
+
+; break;
+; }
+
+; case 4:
+; {
+; bytep sp, dp;
+; unsigned int shift;
+; int v;
+; uint_32 i;
+; uint_32 row_width = row_info->width;
+
+; sp = row;
+; dp = row;
+; shift = 4;
+; v = 0;
+
+; for (i = 0; i < row_width; i++)
+; {
+; byte value;
+
+; value = (byte)(*sp & 0x0f);
+; v |= (value << shift);
+
+; if (shift == 0)
+; {
+; shift = 4;
+; *dp = (byte)v;
+; dp++;
+; v = 0;
+; }
+
+; else
+; shift -= 4;
+;
+; sp++;
+; }
+
+; if (shift != 4)
+; *dp = (byte)v;
+
+; break;
+; }
+
+; default:
+; break;
+; }
+
+; row_info->bit_depth = (byte)bit_depth;
+; row_info->pixel_depth = (byte)(bit_depth * row_info->channels);
+; row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
+; row_info->width);
+; }
+ ret
+endp
+
+; Shift pixel values to take advantage of whole range. Pass the
+; true number of bits in bit_depth. The row should be packed
+; according to row_info->bit_depth. Thus, if you had a row of
+; bit depth 4, but the pixels only had values from 0 to 7, you
+; would pass 3 as bit_depth, and this routine would translate the
+; data to 0 to 15.
+
+;void (png_row_infop row_info, bytep row, png_const_color_8p bit_depth)
+align 4
+proc png_do_shift, row_info:dword, row:dword, bit_depth:dword
+ png_debug 1, 'in png_do_shift'
+
+; if (row_info->color_type != PNG_COLOR_TYPE_PALETTE)
+; {
+; int shift_start[4], shift_dec[4];
+; int channels = 0;
+
+; if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
+; {
+; shift_start[channels] = row_info->bit_depth - bit_depth->red;
+; shift_dec[channels] = bit_depth->red;
+; channels++;
+
+; shift_start[channels] = row_info->bit_depth - bit_depth->green;
+; shift_dec[channels] = bit_depth->green;
+; channels++;
+
+; shift_start[channels] = row_info->bit_depth - bit_depth->blue;
+; shift_dec[channels] = bit_depth->blue;
+; channels++;
+; }
+
+; else
+; {
+; shift_start[channels] = row_info->bit_depth - bit_depth->gray;
+; shift_dec[channels] = bit_depth->gray;
+; channels++;
+; }
+
+; if ((row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
+; {
+; shift_start[channels] = row_info->bit_depth - bit_depth->alpha;
+; shift_dec[channels] = bit_depth->alpha;
+; channels++;
+; }
+
+ ; With low row depths, could only be grayscale, so one channel
+; if (row_info->bit_depth < 8)
+; {
+; bytep bp = row;
+; png_size_t i;
+; unsigned int mask;
+; png_size_t row_bytes = row_info->rowbytes;
+
+; if (bit_depth->gray == 1 && row_info->bit_depth == 2)
+; mask = 0x55;
+
+; else if (row_info->bit_depth == 4 && bit_depth->gray == 3)
+; mask = 0x11;
+
+; else
+; mask = 0xff;
+
+; for (i = 0; i < row_bytes; i++, bp++)
+; {
+; int j;
+; unsigned int v, out;
+
+; v = *bp;
+; out = 0;
+
+; for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0])
+; {
+; if (j > 0)
+; out |= v << j;
+
+; else
+; out |= (v >> (-j)) & mask;
+; }
+
+; *bp = (byte)(out & 0xff);
+; }
+; }
+
+; else if (row_info->bit_depth == 8)
+; {
+; bytep bp = row;
+; uint_32 i;
+; uint_32 istop = channels * row_info->width;
+
+; for (i = 0; i < istop; i++, bp++)
+; {
+
+; const unsigned int c = i%channels;
+; int j;
+; unsigned int v, out;
+
+; v = *bp;
+; out = 0;
+
+; for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
+; {
+; if (j > 0)
+; out |= v << j;
+
+; else
+; out |= v >> (-j);
+; }
+
+; *bp = (byte)(out & 0xff);
+; }
+; }
+
+; else
+; {
+; bytep bp;
+; uint_32 i;
+; uint_32 istop = channels * row_info->width;
+
+; for (bp = row, i = 0; i < istop; i++)
+; {
+; const unsigned int c = i%channels;
+; int j;
+; unsigned int value, v;
+
+; v = png_get_uint_16(bp);
+; value = 0;
+
+; for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
+; {
+; if (j > 0)
+; value |= v << j;
+
+; else
+; value |= v >> (-j);
+; }
+; *bp++ = (byte)((value >> 8) & 0xff);
+; *bp++ = (byte)(value & 0xff);
+; }
+; }
+; }
+ ret
+endp
+
+;void (png_row_infop row_info, bytep row)
+align 4
+proc png_do_write_swap_alpha, row_info:dword, row:dword
+ png_debug 1, 'in png_do_write_swap_alpha'
+
+; {
+; if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+; {
+; if (row_info->bit_depth == 8)
+; {
+ ; This converts from ARGB to RGBA
+; bytep sp, dp;
+; uint_32 i;
+; uint_32 row_width = row_info->width;
+
+; for (i = 0, sp = dp = row; i < row_width; i++)
+; {
+; byte save = *(sp++);
+; *(dp++) = *(sp++);
+; *(dp++) = *(sp++);
+; *(dp++) = *(sp++);
+; *(dp++) = save;
+; }
+; }
+
+if PNG_WRITE_16BIT_SUPPORTED eq 1
+; else
+; {
+ ; This converts from AARRGGBB to RRGGBBAA
+; bytep sp, dp;
+; uint_32 i;
+; uint_32 row_width = row_info->width;
+;
+; for (i = 0, sp = dp = row; i < row_width; i++)
+; {
+; byte save[2];
+; save[0] = *(sp++);
+; save[1] = *(sp++);
+; *(dp++) = *(sp++);
+; *(dp++) = *(sp++);
+; *(dp++) = *(sp++);
+; *(dp++) = *(sp++);
+; *(dp++) = *(sp++);
+; *(dp++) = *(sp++);
+; *(dp++) = save[0];
+; *(dp++) = save[1];
+; }
+; }
+end if ;WRITE_16BIT
+; }
+;
+; else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+; {
+; if (row_info->bit_depth == 8)
+; {
+ ; This converts from AG to GA
+; bytep sp, dp;
+; uint_32 i;
+; uint_32 row_width = row_info->width;
+
+; for (i = 0, sp = dp = row; i < row_width; i++)
+; {
+; byte save = *(sp++);
+; *(dp++) = *(sp++);
+; *(dp++) = save;
+; }
+; }
+
+if PNG_WRITE_16BIT_SUPPORTED eq 1
+; else
+; {
+ ; This converts from AAGG to GGAA
+; bytep sp, dp;
+; uint_32 i;
+; uint_32 row_width = row_info->width;
+
+; for (i = 0, sp = dp = row; i < row_width; i++)
+; {
+; byte save[2];
+; save[0] = *(sp++);
+; save[1] = *(sp++);
+; *(dp++) = *(sp++);
+; *(dp++) = *(sp++);
+; *(dp++) = save[0];
+; *(dp++) = save[1];
+; }
+; }
+end if ;WRITE_16BIT
+; }
+; }
+ ret
+endp
+
+;void (png_row_infop row_info, bytep row)
+align 4
+proc png_do_write_invert_alpha, row_info:dword, row:dword
+ png_debug 1, 'in png_do_write_invert_alpha'
+
+; if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+; {
+; if (row_info->bit_depth == 8)
+; {
+ ; This inverts the alpha channel in RGBA
+; bytep sp, dp;
+; uint_32 i;
+; uint_32 row_width = row_info->width;
+
+; for (i = 0, sp = dp = row; i < row_width; i++)
+; {
+ ; Does nothing
+ ;*(dp++) = *(sp++);
+ ;*(dp++) = *(sp++);
+ ;*(dp++) = *(sp++);
+
+; sp+=3; dp = sp;
+; *dp = (byte)(255 - *(sp++));
+; }
+; }
+
+;if PNG_WRITE_16BIT_SUPPORTED
+; else
+; {
+ ; This inverts the alpha channel in RRGGBBAA
+; bytep sp, dp;
+; uint_32 i;
+; uint_32 row_width = row_info->width;
+
+; for (i = 0, sp = dp = row; i < row_width; i++)
+; {
+ ; Does nothing
+ ;*(dp++) = *(sp++);
+ ;*(dp++) = *(sp++);
+ ;*(dp++) = *(sp++);
+ ;*(dp++) = *(sp++);
+ ;*(dp++) = *(sp++);
+ ;*(dp++) = *(sp++);
+
+; sp+=6; dp = sp;
+; *(dp++) = (byte)(255 - *(sp++));
+; *dp = (byte)(255 - *(sp++));
+; }
+; }
+;end if /* WRITE_16BIT */
+; }
+
+; else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+; {
+; if (row_info->bit_depth == 8)
+; {
+ ; This inverts the alpha channel in GA
+; bytep sp, dp;
+; uint_32 i;
+; uint_32 row_width = row_info->width;
+;
+; for (i = 0, sp = dp = row; i < row_width; i++)
+; {
+; *(dp++) = *(sp++);
+; *(dp++) = (byte)(255 - *(sp++));
+; }
+; }
+
+if PNG_WRITE_16BIT_SUPPORTED eq 1
+; else
+; {
+ ; This inverts the alpha channel in GGAA
+; bytep sp, dp;
+; uint_32 i;
+; uint_32 row_width = row_info->width;
+;
+; for (i = 0, sp = dp = row; i < row_width; i++)
+; {
+ ; Does nothing
+ ;*(dp++) = *(sp++);
+ ;*(dp++) = *(sp++);
+
+; sp+=2; dp = sp;
+; *(dp++) = (byte)(255 - *(sp++));
+; *dp = (byte)(255 - *(sp++));
+; }
+; }
+end if ;WRITE_16BIT
+; }
+ ret
+endp
+
+; Transform the data according to the user's wishes. The order of
+; transformations is significant.
+
+;void (png_structrp png_ptr, png_row_infop row_info)
+align 4
+proc png_do_write_transformations uses eax ebx edi esi, png_ptr:dword, row_info:dword
+ png_debug 1, 'in png_do_write_transformations'
+
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f ;if (..==0) return
+ mov esi,[row_info]
+ mov ebx,[edi+png_struct.row_buf]
+ inc ebx ;start of pixel data for row
+
+if PNG_WRITE_USER_TRANSFORM_SUPPORTED eq 1
+ mov eax,[edi+png_struct.transformations]
+ and eax,PNG_USER_TRANSFORM
+ jz @f ;if (..!=0)
+ mov eax,[edi+png_struct.write_user_transform_fn]
+ test eax,eax
+ jz @f ;if (..!=0)
+ stdcall eax, edi, esi, ebx ;User write transform function
+ ; row_info:
+ ; uint_32 width ;width of row
+ ; png_size_t rowbytes ;number of bytes in row
+ ; byte color_type ;color type of pixels
+ ; byte bit_depth ;bit depth of samples
+ ; byte channels ;number of channels (1-4)
+ ; byte pixel_depth ;bits per pixel (depth*channels)
+ @@:
+end if
+
+if PNG_WRITE_FILLER_SUPPORTED eq 1
+ mov eax,[edi+png_struct.transformations]
+ and eax,PNG_FILLER
+ jz @f ;if (..!=0)
+ mov eax,[edi+png_struct.flags]
+ and eax,PNG_FLAG_FILLER_AFTER
+ not eax
+ stdcall png_do_strip_channel, esi, ebx, eax
+ @@:
+end if
+
+if PNG_WRITE_PACKSWAP_SUPPORTED eq 1
+ mov eax,[edi+png_struct.transformations]
+ and eax,PNG_PACKSWAP
+ jz @f ;if (..!=0)
+ stdcall png_do_packswap, esi, ebx
+ @@:
+end if
+
+if PNG_WRITE_PACK_SUPPORTED eq 1
+ mov eax,[edi+png_struct.transformations]
+ and eax,PNG_PACK
+ jz @f ;if (..!=0)
+ movzx eax,byte[edi+png_struct.bit_depth]
+ stdcall png_do_pack, esi, ebx, eax
+ @@:
+end if
+
+if PNG_WRITE_SWAP_SUPPORTED eq 1
+if PNG_16BIT_SUPPORTED eq 1
+ mov eax,[edi+png_struct.transformations]
+ and eax,PNG_SWAP_BYTES
+ jz @f ;if (..!=0)
+ stdcall png_do_swap, esi, ebx
+ @@:
+end if
+end if
+
+if PNG_WRITE_SHIFT_SUPPORTED eq 1
+ mov eax,[edi+png_struct.transformations]
+ and eax,PNG_SHIFT
+ jz @f ;if (..!=0)
+ mov eax,edi
+ add eax,png_struct.shift
+ stdcall png_do_shift, esi, ebx, eax
+ @@:
+end if
+
+if PNG_WRITE_SWAP_ALPHA_SUPPORTED eq 1
+ mov eax,[edi+png_struct.transformations]
+ and eax,PNG_SWAP_ALPHA
+ jz @f ;if (..!=0)
+ stdcall png_do_write_swap_alpha, esi, ebx
+ @@:
+end if
+
+if PNG_WRITE_INVERT_ALPHA_SUPPORTED eq 1
+ mov eax,[edi+png_struct.transformations]
+ and eax,PNG_INVERT_ALPHA
+ jz @f ;if (..!=0)
+ stdcall png_do_write_invert_alpha, esi, ebx
+ @@:
+end if
+
+if PNG_WRITE_BGR_SUPPORTED eq 1
+ mov eax,[edi+png_struct.transformations]
+ and eax,PNG_BGR
+ jz @f ;if (..!=0)
+ stdcall png_do_bgr, esi, ebx
+ @@:
+end if
+
+if PNG_WRITE_INVERT_SUPPORTED eq 1
+ mov eax,[edi+png_struct.transformations]
+ and eax,PNG_INVERT_MONO
+ jz @f ;if (..!=0)
+ stdcall png_do_invert, esi, ebx
+ @@:
+end if
+.end_f:
+ ret
+endp
diff --git a/programs/develop/libraries/libs-dev/libimg/png/libpng/pngwutil.asm b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngwutil.asm
index 41ca686b4..63b62b713 100644
--- a/programs/develop/libraries/libs-dev/libimg/png/libpng/pngwutil.asm
+++ b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngwutil.asm
@@ -1,3479 +1,3479 @@
-
-; pngwutil.asm - utilities to write a PNG file
-
-; Last changed in libpng 1.6.24 [August 4, 2016]
-; Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
-; (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
-; (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
-
-; This code is released under the libpng license.
-; For conditions of distribution and use, see the disclaimer
-; and license in png.inc
-
-; Place a 32-bit number into a buffer in PNG byte order. We work
-; with unsigned numbers for convenience, although one supported
-; ancillary chunk uses signed (two's complement) numbers.
-
-;void (bytep buf, uint_32 i)
-align 4
-proc png_save_uint_32 uses eax edi, buf:dword, i:dword
- mov eax,[i]
- bswap eax
- mov edi,[buf]
- stosd
- ret
-endp
-
-; Place a 16-bit number into a buffer in PNG byte order.
-; The parameter is declared unsigned int, not uint_16,
-; just to avoid potential problems on pre-ANSI C compilers.
-
-;void (bytep buf, unsigned int i)
-align 4
-proc png_save_uint_16 uses eax edi, buf:dword, i:dword
- mov eax,[i]
- ror eax,16
- bswap eax
- mov edi,[buf]
- stosw
- ret
-endp
-
-; Simple function to write the signature. If we have already written
-; the magic bytes of the signature, or more likely, the PNG stream is
-; being embedded into another stream and doesn't need its own signature,
-; we should call png_set_sig_bytes() to tell libpng how many of the
-; bytes have already been written.
-
-align 4
-png_signature db 137, 80, 78, 71, 13, 10, 26, 10
-
-;void (png_structrp png_ptr)
-align 4
-proc png_write_sig uses eax ebx edi, png_ptr:dword
-if PNG_IO_STATE_SUPPORTED eq 1
- ; Inform the I/O callback that the signature is being written
- mov edi,[png_ptr]
- mov dword[edi+png_struct.io_state], PNG_IO_WRITING or PNG_IO_SIGNATURE
-end if
-
- ; Write the rest of the 8 byte signature
- movzx eax,byte[edi+png_struct.sig_bytes]
- mov ebx,8
- sub ebx,eax
- add eax,png_signature
- stdcall png_write_data, edi, eax, ebx
-
- cmp byte[edi+png_struct.sig_bytes], 3 ;if(..<3)
- jge @f
- or dword[edi+png_struct.mode], PNG_HAVE_PNG_SIGNATURE
- @@:
- ret
-endp
-
-; Write the start of a PNG chunk. The type is the chunk type.
-; The total_length is the sum of the lengths of all the data you will be
-; passing in png_write_chunk_data().
-
-;void (png_structrp png_ptr, uint_32 chunk_name, uint_32 length)
-align 4
-proc png_write_chunk_header uses ebx edi, png_ptr:dword, chunk_name:dword, length:dword
-locals
- buf rb 8 ;ebp-8
-endl
-
-if (PNG_DEBUG eq 1) & (PNG_DEBUG > 0)
-; PNG_CSTRING_FROM_CHUNK(buf, chunk_name);
-; png_debug2(0, "Writing %s chunk, length = %lu", buf, (unsigned long)length);
-end if
-
- mov edi,[png_ptr]
- test edi,edi
- jz .end_f ;if (..==0) return
-
-if PNG_IO_STATE_SUPPORTED eq 1
- ; Inform the I/O callback that the chunk header is being written.
- ; PNG_IO_CHUNK_HDR requires a single I/O call.
-
- mov dword[edi+png_struct.io_state], PNG_IO_WRITING or PNG_IO_CHUNK_HDR
-end if
-
- ; Write the length and the chunk name
- lea ebx,[ebp-8]
- stdcall png_save_uint_32, ebx, [length]
- m2m dword[ebx+4],dword[chunk_name]
- stdcall png_write_data, edi, ebx, 8
-
- ; Put the chunk name into png_ptr->chunk_name
- m2m dword[edi+png_struct.chunk_name],dword[chunk_name]
-
- ; Reset the crc and run it over the chunk name
- stdcall png_reset_crc, edi
- lea ebx,[ebp-4] ;buf + 4
- stdcall png_calculate_crc, edi, ebx, 4
-
-if PNG_IO_STATE_SUPPORTED eq 1
- ; Inform the I/O callback that chunk data will (possibly) be written.
- ; PNG_IO_CHUNK_DATA does NOT require a specific number of I/O calls.
-
- mov dword[edi+png_struct.io_state], PNG_IO_WRITING or PNG_IO_CHUNK_DATA
-end if
-.end_f:
- ret
-endp
-
-;void (png_structrp png_ptr, bytep chunk_string, uint_32 length)
-align 4
-proc png_write_chunk_start uses eax, png_ptr:dword, chunk_string:dword, length:dword
- mov eax,[chunk_string]
- stdcall png_write_chunk_header, [png_ptr], [eax], [length]
- ret
-endp
-
-; Write the data of a PNG chunk started with png_write_chunk_header().
-; Note that multiple calls to this function are allowed, and that the
-; sum of the lengths from these calls *must* add up to the total_length
-; given to png_write_chunk_header().
-
-;void (png_structrp png_ptr, bytep data, png_size_t length)
-align 4
-proc png_write_chunk_data uses edi, png_ptr:dword, p2data:dword, length:dword
- ; Write the data, and run the CRC over it
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f ;if (..==0) return
-
- cmp dword[p2data],0
- je .end_f
- cmp dword[length],0
- jle .end_f ;if (..!=0 && ..>0)
- stdcall png_write_data, edi, [p2data], [length]
- ; Update the CRC after writing the data,
- ; in case the user I/O routine alters it.
- stdcall png_calculate_crc, edi, [p2data], [length]
-.end_f:
- ret
-endp
-
-; Finish a chunk started with png_write_chunk_header().
-;void (png_structrp png_ptr)
-align 4
-proc png_write_chunk_end uses ebx edi, png_ptr:dword
-locals
- buf rb 4 ;ebp-4
-endl
- mov edi,[png_ptr]
- cmp edi,0
- je .end_f ;if (..==0) return
-
-if PNG_IO_STATE_SUPPORTED eq 1
- ; Inform the I/O callback that the chunk CRC is being written.
- ; PNG_IO_CHUNK_CRC requires a single I/O function call.
-
- mov dword[edi+png_struct.io_state], PNG_IO_WRITING or PNG_IO_CHUNK_CRC
-end if
-
- ; Write the crc in a single operation
- lea ebx,[ebp-4]
- stdcall png_save_uint_32, ebx, [edi+png_struct.crc]
-
- stdcall png_write_data, edi, ebx, 4
-.end_f:
- ret
-endp
-
-; Write a PNG chunk all at once. The type is an array of ASCII characters
-; representing the chunk name. The array must be at least 4 bytes in
-; length, and does not need to be null terminated. To be safe, pass the
-; pre-defined chunk names here, and if you need a new one, define it
-; where the others are defined. The length is the length of the data.
-; All the data must be present. If that is not possible, use the
-; png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end()
-; functions instead.
-
-;void (png_structrp png_ptr, uint_32 chunk_name, bytep data, png_size_t length)
-align 4
-proc png_write_complete_chunk uses edi, png_ptr:dword, chunk_name:dword, p3data:dword, length:dword
- mov edi,[png_ptr]
- test edi,edi
- jz .end_f ;if (..==0) return
-
- ; On 64-bit architectures 'length' may not fit in a uint_32.
- cmp dword[length],PNG_UINT_31_MAX ;if(..>..)
- jle @f
- png_error edi, 'length exceeds PNG maximum'
- @@:
- stdcall png_write_chunk_header, edi, [chunk_name], [length]
- stdcall png_write_chunk_data, edi, [p3data], [length]
- stdcall png_write_chunk_end, edi
-.end_f:
- ret
-endp
-
-; This is the API that calls the internal function above.
-;void (png_structrp png_ptr, bytep chunk_string, bytep data, png_size_t length)
-align 4
-proc png_write_chunk, png_ptr:dword, chunk_string:dword, p3data:dword, length:dword
- stdcall png_write_complete_chunk, [png_ptr], [chunk_string], [p3data], [length]
- ret
-endp
-
-; This is used below to find the size of an image to pass to png_deflate_claim,
-; so it only needs to be accurate if the size is less than 16384 bytes (the
-; point at which a lower LZ window size can be used.)
-
-;png_alloc_size_t (png_structrp png_ptr)
-align 4
-proc png_image_size uses ebx ecx edx edi esi, png_ptr:dword
-; Only return sizes up to the maximum of a uint_32; do this by limiting
-; the width and height used to 15 bits.
-
- mov edi,[png_ptr]
- mov ebx,[edi+png_struct.height]
-
- cmp dword[edi+png_struct.rowbytes],32768
- jge .end0
- cmp ebx,32768
- jge .end0 ;if (..<.. && ..<..)
- cmp byte[edi+png_struct.interlaced],0
- je .end1 ;if (..!=0)
- ; Interlacing makes the image larger because of the replication of
- ; both the filter byte and the padding to a byte boundary.
-
- xor esi,esi
- xor ecx,ecx
- .cycle0:
- PNG_PASS_COLS [edi+png_struct.width], ecx
- ;eax = pw
-
- cmp eax,0
- jle @f ;if (..>0)
- mov edx,eax
- movzx eax,byte[edi+png_struct.pixel_depth]
- PNG_ROWBYTES eax, edx
- inc eax
- mov edx,eax
- PNG_PASS_ROWS ebx, ecx
- imul eax,edx
- add esi,eax
- @@:
- inc ecx
- cmp ecx,6
- jle .cycle0
-
- mov eax,esi
- jmp .end_f
- .end1: ;else
- mov eax,[edi+png_struct.rowbytes]
- inc eax
- imul eax,ebx
- jmp .end_f
- .end0: ;else
- mov eax,0xffffffff
-.end_f:
- ret
-endp
-
-; This is the code to hack the first two bytes of the deflate stream (the
-; deflate header) to correct the windowBits value to match the actual data
-; size. Note that the second argument is the *uncompressed* size but the
-; first argument is the *compressed* data (and it must be deflate
-; compressed.)
-
-;void (bytep data, png_alloc_size_t data_size)
-align 4
-proc optimize_cmf, p1data:dword, data_size:dword
-; Optimize the CMF field in the zlib stream. The resultant zlib stream is
-; still compliant to the stream specification.
- png_debug 1, 'optimize_cmf'
-pushad
- cmp dword[data_size],16384
- jg .end_f ;if (..<=..) ;else windowBits must be 15
- mov esi,[p1data]
- movzx ebx,byte[esi]
- ;ebx = z_cmf ;zlib compression method and flags
-
- mov eax,ebx
- and eax,0x0f
- cmp eax,8
- jne .end_f
- mov eax,ebx
- and eax,0xf0
- cmp eax,0x70
- jg .end_f ;if (..==.. && ..<=..)
- ;ecx = z_cinfo
- ;edi = half_z_window_size
-
- mov ecx,ebx
- shr ecx,4
- xor edi,edi
- inc edi
- shl edi,7
- shl edi,cl
-
- cmp [data_size],edi
- jg .end_f ;if (..<=..) ;else no change
- .cycle0: ;do
- shr edi,1
- dec ecx
- cmp ecx,0
- jle @f
- cmp [data_size],edi
- jle .cycle0
- @@: ;while (..>0 && ..<=..);
-
- and ebx,0x0f
- mov eax,ecx
- shl eax,4
- or ebx,eax
-
- mov byte[esi],bl
- movzx eax,byte[esi+1]
- and eax,0xe0
- shl ebx,8
- add ebx,eax
- add eax,0x1f
- xchg eax,ebx
- xor edx,edx
- mov ecx,0x1f
- div ecx
- sub ebx,edx
- mov byte[esi+1],bl
-.end_f:
-popad
- ret
-endp
-
-; Initialize the compressor for the appropriate type of compression.
-;int (png_structrp png_ptr, uint_32 owner, png_alloc_size_t data_size)
-;input:
-; edi - png_ptr
-align 4
-proc png_deflate_claim uses ebx ecx, owner:dword, data_size:dword
-locals
- level dd ? ;int
- method dd ? ;int
- windowBits dd ? ;int
- memLevel dd ? ;int
- strategy dd ? ;int
- msg rb 64 ;char[64]
-endl
- png_debug 1, 'in png_deflate_claim'
-
- cmp dword[edi+png_struct.zowner],0
- je .end0 ;if (..!=0)
- mov ebx,ebp
- sub ebx,64
-if (PNG_WARNINGS_SUPPORTED eq 1) | (PNG_ERROR_TEXT_SUPPORTED eq 1)
- mov eax,[owner]
- mov [ebx],eax
- mov word[ebx+4],': '
- mov eax,[edi+png_struct.zowner]
- mov [ebx+6],eax
- ; So the message that results is " using zstream"; this is an
- ; internal error, but is very useful for debugging. i18n requirements
- ; are minimal.
-
- cStr ,' using zstream'
- stdcall png_safecat, ebx, 64, 10, eax
-end if
-if PNG_RELEASE_BUILD eq 1
- png_warning edi, ebx
-
- ; Attempt sane error recovery
- cmp dword[edi+png_struct.zowner],png_IDAT
- jne @f ;if (..==.) ;don't steal from IDAT
- cStr dword[edi+png_struct.zstream.msg],'in use by IDAT'
- mov eax,Z_STREAM_ERROR
- jmp .end_f
- @@:
- mov dword[edi+png_struct.zowner],0
-else
- png_error edi, ebx
-end if
- .end0:
-
- mov eax,[edi+png_struct.zlib_level]
- mov [level],eax
- mov eax,[edi+png_struct.zlib_method]
- mov [method],eax
- mov eax,[edi+png_struct.zlib_window_bits]
- mov [windowBits],eax
- mov eax,[edi+png_struct.zlib_mem_level]
- mov [memLevel],eax
-
- cmp dword[owner],png_IDAT
- jne .end1 ;if (..==..)
- mov eax,[edi+png_struct.flags]
- and eax,PNG_FLAG_ZLIB_CUSTOM_STRATEGY
- jz @f ;if (..!=0)
- mov eax,[edi+png_struct.zlib_strategy]
- mov dword[strategy],eax
- jmp .end2
- @@:
- cmp byte[edi+png_struct.do_filter],PNG_FILTER_NONE
- je @f ;else if (..!=..)
- mov dword[strategy],PNG_Z_DEFAULT_STRATEGY
- jmp .end2
- @@: ;else
- mov dword[strategy],PNG_Z_DEFAULT_NOFILTER_STRATEGY
- jmp .end2
- .end1: ;else
-if PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED eq 1
- mov eax,[edi+png_struct.zlib_text_level]
- mov [level],eax
- mov eax,[edi+png_struct.zlib_text_method]
- mov [method],eax
- mov eax,[edi+png_struct.zlib_text_window_bits]
- mov [windowBits],eax
- mov eax,[edi+png_struct.zlib_text_mem_level]
- mov [memLevel],eax
- mov eax,[edi+png_struct.zlib_text_strategy]
- mov [strategy],eax
-else
- ; If customization is not supported the values all come from the
- ; IDAT values except for the strategy, which is fixed to the
- ; default. (This is the pre-1.6.0 behavior too, although it was
- ; implemented in a very different way.)
-
- mov dword[strategy],Z_DEFAULT_STRATEGY
-end if
- .end2:
-
- ; Adjust 'windowBits' down if larger than 'data_size'; to stop this
- ; happening just pass 32768 as the data_size parameter. Notice that zlib
- ; requires an extra 262 bytes in the window in addition to the data to be
- ; able to see the whole of the data, so if data_size+262 takes us to the
- ; next windowBits size we need to fix up the value later. (Because even
- ; though deflate needs the extra window, inflate does not!)
-
- cmp dword[data_size],16384
- jg .end3 ;if (..<=..)
- ; IMPLEMENTATION NOTE: this 'half_window_size' stuff is only here to
- ; work round a Microsoft Visual C misbehavior which, contrary to C-90,
- ; widens the result of the following shift to 64-bits if (and,
- ; apparently, only if) it is used in a test.
-
- mov ecx,[windowBits]
- dec ecx
- xor eax,eax
- inc eax
- shl eax,cl ;eax = half_window_size
- mov ecx,[data_size]
- add ecx,262
- @@: ;while (..<=..)
- cmp ecx,eax
- jg .end3
- shr eax,1
- dec dword[windowBits]
- jmp @b
- .end3:
-
- ; Check against the previous initialized values, if any.
- mov eax,[edi+png_struct.flags]
- and eax,PNG_FLAG_ZSTREAM_INITIALIZED
- jz .end4
- mov eax,[level]
- cmp [edi+png_struct.zlib_set_level],eax
- jne @f
- mov eax,[method]
- cmp [edi+png_struct.zlib_set_method],eax
- jne @f
- mov eax,[windowBits]
- cmp [edi+png_struct.zlib_set_window_bits],eax
- jne @f
- mov eax,[memLevel]
- cmp [edi+png_struct.zlib_set_mem_level],eax
- jne @f
- mov eax,[strategy]
- cmp [edi+png_struct.zlib_set_strategy],eax
- je .end4
- @@: ;if (..!=0 && (..!=.. || ..!=.. || ..!=.. || ..!=.. || ..!=..))
- mov eax,edi
- add eax,png_struct.zstream
- stdcall [deflateEnd], eax
- cmp eax,Z_OK
- je @f ;if (..!=..)
- png_warning edi, 'deflateEnd failed (ignored)'
- @@:
- and dword[edi+png_struct.flags], not PNG_FLAG_ZSTREAM_INITIALIZED
- .end4:
-
- ; For safety clear out the input and output pointers (currently zlib
- ; doesn't use them on Init, but it might in the future).
-
- mov dword[edi+png_struct.zstream.next_in],0
- mov dword[edi+png_struct.zstream.avail_in],0
- mov dword[edi+png_struct.zstream.next_out],0
- mov dword[edi+png_struct.zstream.avail_out],0
-
- ; Now initialize if required, setting the new parameters, otherwise just
- ; to a simple reset to the previous parameters.
-
- mov ecx,edi
- add ecx,png_struct.zstream
- mov eax,[edi+png_struct.flags]
- and eax,PNG_FLAG_ZSTREAM_INITIALIZED
- jz @f ;if (..!=0)
- stdcall [deflateReset], ecx
- jmp .end5
- @@: ;else
- stdcall [deflateInit2], ecx, [level], [method], [windowBits],\
- [memLevel], [strategy]
-
- cmp eax,Z_OK
- je .end5 ;if (..==..)
- or dword[edi+png_struct.flags],PNG_FLAG_ZSTREAM_INITIALIZED
- .end5:
-
- ; The return code is from either deflateReset or deflateInit2; they have
- ; pretty much the same set of error codes.
-
- cmp eax,Z_OK
- jne @f ;if (..==..)
- mov ecx,[owner]
- mov [edi+png_struct.zowner],ecx
- jmp .end_f
- @@: ;else
- stdcall png_zstream_error, edi, eax
-
-.end_f:
- ret
-endp
-
-; Clean up (or trim) a linked list of compression buffers.
-;void (png_structrp png_ptr, png_compression_bufferp *listp)
-align 4
-proc png_free_buffer_list uses eax ebx ecx edi, png_ptr:dword, listp:dword
- mov eax,[listp]
- mov ebx,[eax]
- ;eax = png_compression_bufferp list
-
- cmp ebx,0
- je @f ;if (..!=0)
- mov dword[eax],0
- .cycle0: ;do
- mov ecx,[ebx+png_compression_buffer.next]
- stdcall png_free, edi, ebx
- mov ebx,ecx
- cmp ebx,0
- jne .cycle0 ;while (..!=0)
- @@:
- ret
-endp
-
-if PNG_WRITE_COMPRESSED_TEXT_SUPPORTED eq 1
-; This pair of functions encapsulates the operation of (a) compressing a
-; text string, and (b) issuing it later as a series of chunk data writes.
-; The compression_state structure is shared context for these functions
-; set up by the caller to allow access to the relevant local variables.
-
-; compression_buffer (new in 1.6.0) is just a linked list of zbuffer_size
-; temporary buffers. From 1.6.0 it is retained in png_struct so that it will
-; be correctly freed in the event of a write error (previous implementations
-; just leaked memory.)
-
-struct compression_state
- input dd ? ;bytep ;The uncompressed input data
- input_len dd ? ;png_alloc_size_t ;Its length
- output_len dd ? ;uint_32 ;Final compressed length
- output rb 1024 ;byte[1024] ;First block of output
-ends
-
-;void (compression_state *comp, bytep input, png_alloc_size_t input_len)
-align 4
-proc png_text_compress_init uses eax ebx, comp:dword, input:dword, input_len:dword
- mov ebx,[comp]
- mov eax,[input]
- mov [ebx+compression_state.input],eax
- mov eax,[input_len]
- mov [ebx+compression_state.input_len],eax
- mov dword[ebx+compression_state.output_len],0
- ret
-endp
-
-; Compress the data in the compression state input
-;int (png_structrp png_ptr, uint_32 chunk_name, compression_state *comp, uint_32 prefix_len)
-align 4
-proc png_text_compress uses ebx ecx edx edi esi, png_ptr:dword, chunk_name:dword, comp:dword, prefix_len:dword
-locals
- output_len dd ? ;uint_32
- avail_in dd ? ;uInt
- next dd ? ;png_compression_buffer*
-endl
- ; To find the length of the output it is necessary to first compress the
- ; input. The result is buffered rather than using the two-pass algorithm
- ; that is used on the inflate side; deflate is assumed to be slower and a
- ; PNG writer is assumed to have more memory available than a PNG reader.
-
- ; IMPLEMENTATION NOTE: the zlib API deflateBound() can be used to find an
- ; upper limit on the output size, but it is always bigger than the input
- ; size so it is likely to be more efficient to use this linked-list
- ; approach.
-
- mov ebx,[comp]
- mov edi,[png_ptr]
- stdcall png_deflate_claim, [chunk_name], [ebx+compression_state.input_len]
-
- cmp eax,Z_OK
- jne .end_f ;if (..!=Z_OK) return ..
-
- ; Set up the compression buffers, we need a loop here to avoid overflowing a
- ; uInt. Use ZLIB_IO_MAX to limit the input. The output is always limited
- ; by the output buffer size, so there is no need to check that. Since this
- ; is ANSI-C we know that an 'int', hence a uInt, is always at least 16 bits
- ; in size.
-
- mov edx,edi
- add edx,png_struct.zbuffer_list
- mov ecx,[ebx+compression_state.input_len] ;may be zero!
- ;ecx = input_len
- ;edx = end
- ;esi = ret
-
- ; zlib updates these for us:
- mov eax,[ebx+compression_state.input]
- mov [edi+png_struct.zstream.next_in],eax
- mov dword[edi+png_struct.zstream.avail_in],0 ;Set below
- mov eax,ebx
- add eax,compression_state.output
- mov [edi+png_struct.zstream.next_out],eax
- mov eax,sizeof.compression_state.output ;1024
- mov [edi+png_struct.zstream.avail_out],eax
-
- mov [output_len],eax
-
- .cycle0: ;do
- mov dword[avail_in],ZLIB_IO_MAX
-
- cmp [avail_in],ecx
- jle @f ;if (..>..)
- mov [avail_in],ecx
- @@:
- sub ecx,[avail_in]
-
- mov eax,[avail_in]
- mov [edi+png_struct.zstream.avail_in],eax
-
- cmp dword[edi+png_struct.zstream.avail_out],0
- jne .end0 ;if (..==0)
- ; Chunk data is limited to 2^31 bytes in length, so the prefix
- ; length must be counted here.
-
- mov eax,[output_len]
- add eax,[prefix_len]
- cmp eax,PNG_UINT_31_MAX
- jle @f ;if (..>..)
- mov esi,Z_MEM_ERROR
- jmp .cycle0end
- @@:
-
- ; Need a new (malloc'ed) buffer, but there may be one present
- ; already.
-
- mov eax,[edx]
- mov [next],eax
-
- test eax,eax
- jnz .end1 ;if (..==0)
- PNG_COMPRESSION_BUFFER_SIZE edi
- stdcall png_malloc, edi, eax
- mov [next],eax
-
- test eax,eax
- jnz @f ;if (..==0)
- mov esi,Z_MEM_ERROR
- jmp .cycle0end
- @@:
-
- ; Link in this buffer (so that it will be freed later)
- mov dword[eax+png_compression_buffer.next],0
- mov [edx],eax
- .end1:
-
- mov eax,[next]
- mov eax,[eax+png_compression_buffer.output]
- mov [edi+png_struct.zstream.next_out],eax
- mov eax,[edi+png_struct.zbuffer_size]
- mov [edi+png_struct.zstream.avail_out],eax
- add [output_len],eax
-
- ; Move 'end' to the next buffer pointer.
- mov eax,[next]
- add eax,png_compression_buffer.next
- mov edx,eax
- .end0:
-
- ; Compress the data
- mov eax,Z_FINISH
- cmp dword[input_len],0
- jle @f
- mov eax,Z_NO_FLUSH
- @@:
- push eax
- mov eax,edi
- add eax,png_struct.zstream
- stdcall [deflate], eax ;, ...
- mov esi,eax
-
- ; Claw back input data that was not consumed (because avail_in is
- ; reset above every time round the loop).
-
- mov eax,[edi+png_struct.zstream.avail_in]
- add [input_len],eax
- mov dword[edi+png_struct.zstream.avail_in],0 ;safety
- cmp esi,Z_OK
- je .cycle0 ;while (..==..)
- .cycle0end:
-
- ; There may be some space left in the last output buffer. This needs to
- ; be subtracted from output_len.
-
- mov eax,[edi+png_struct.zstream.avail_out]
- sub [output_len],eax
- mov dword[edi+png_struct.zstream.avail_out],0 ;safety
- mov eax,[output_len]
- mov [ebx+compression_state.output_len],eax
-
- ; Now double check the output length, put in a custom message if it is
- ; too long. Otherwise ensure the z_stream::msg pointer is set to
- ; something.
-
- mov eax,[output_len]
- add eax,[prefix_len]
- cmp eax,PNG_UINT_31_MAX
- jl @f ;if (..>=..)
- cStr dword[edi+png_struct.zstream.msg],'compressed data too long'
- mov esi,Z_MEM_ERROR
- jmp .end2
- @@: ;else
- stdcall png_zstream_error, edi, esi
- .end2:
-
- ; Reset zlib for another zTXt/iTXt or image data
- mov dword[edi+png_struct.zowner],0
-
- ; The only success case is Z_STREAM_END, input_len must be 0; if not this
- ; is an internal error.
-
- cmp esi,Z_STREAM_END
- jne @f
- cmp dword[input_len],0
- jne @f ;if (..==.. && ..==0)
-if PNG_WRITE_OPTIMIZE_CMF_SUPPORTED eq 1
- ; Fix up the deflate header, if required
- mov eax,ebx
- add eax,compression_state.output
- stdcall optimize_cmf, eax, [ebx+compression_state.input_len]
-end if
- ; But Z_OK is returned, not Z_STREAM_END; this allows the claim
- ; function above to return Z_STREAM_END on an error (though it never
- ; does in the current versions of zlib.)
-
- mov eax,Z_OK
- jmp .end_f
- @@: ;else
- mov eax,esi
-.end_f:
- ret
-endp
-
-; Ship the compressed text out via chunk writes
-;void (png_structrp png_ptr, compression_state *comp)
-align 4
-proc png_write_compressed_data_out uses ebx edi, png_ptr:dword, comp:dword
-locals
- output_len dd ? ;uint_32 ;= comp.output_len
- output dd ? ;bytep ;= comp.output
- avail dd ? ;uint_32 ;= sizeof.comp.output
- next dd ? ;png_compression_buffer* ;= png_ptr.zbuffer_list
-endl
- mov ebx,[comp]
- mov eax,[ebx+compression_state.output_len]
- mov [output_len],eax
- mov eax,ebx
- add eax,compression_state.output
- mov [output],eax
- mov [avail],sizeof.compression_state.output ;1024
- mov edi,[png_ptr]
- mov eax,[edi+png_struct.zbuffer_list]
- mov [next],eax
-
- .cycle0: ;for (;;)
- mov eax,[output_len]
- cmp [avail],eax
- jle @f ;if (..>..)
- mov [avail],eax
- @@:
-
- stdcall png_write_chunk_data, edi, [output], [avail]
-
- mov [avail],eax
- sub [output_len],eax
-
- cmp dword[output_len],0
- je .cycle0end
- cmp dword[next],0
- je .cycle0end ;if (..==0 || ..==0) break
-
- mov eax,[edi+png_struct.zbuffer_size]
- mov [avail],eax
- mov eax,[next]
- add eax,png_compression_buffer.output
- mov [output],eax
- mov eax,[next]
- mov eax,[eax+png_compression_buffer.next]
- mov [next],eax
- jmp .cycle0
- .cycle0end:
-
- ; This is an internal error; 'next' must have been NULL!
- cmp dword[output_len],0
- jle @f ;if (..>0)
- png_error edi, 'error writing ancillary chunked compressed data'
- @@:
- ret
-endp
-end if ;WRITE_COMPRESSED_TEXT
-
-; Write the IHDR chunk, and update the png_struct with the necessary
-; information. Note that the rest of this code depends upon this
-; information being correct.
-
-;void (png_structrp png_ptr, uint_32 width, uint_32 height,
-; int bit_depth, int color_type, int compression_type, int filter_type, int interlace_type)
-align 4
-proc png_write_IHDR, png_ptr:dword, width:dword, height:dword, bit_depth:dword,\
- color_type:dword, compression_type:dword, filter_type:dword, interlace_type:dword
-locals
- buf rb 13 ;byte[13] ;Buffer to store the IHDR info
-endl
- png_debug 1, 'in png_write_IHDR'
-pushad
- ; Check that we have valid input data from the application info
- mov edi,[png_ptr]
- movzx ebx,byte[color_type]
- cmp ebx,PNG_COLOR_TYPE_GRAY
- jne .end_0
- cmp byte[bit_depth],1
- je @f
- cmp byte[bit_depth],2
- je @f
- cmp byte[bit_depth],4
- je @f
- cmp byte[bit_depth],8
- je @f
-if PNG_WRITE_16BIT_SUPPORTED eq 1
- cmp byte[bit_depth],16
- je @f
-end if
- jmp .def_0
- @@:
- mov byte[edi+png_struct.channels], 1
- jmp .end_s0
- .def_0: ;default
- png_error edi, 'Invalid bit depth for grayscale image'
- jmp .end_s0
- .end_0:
-
- cmp ebx,PNG_COLOR_TYPE_RGB
- jne .end_1
- cmp byte[bit_depth],8
- je @f ;if (..!=8)
-if PNG_WRITE_16BIT_SUPPORTED eq 1
- cmp byte[bit_depth],16
- je @f ;if (..!=16)
-end if
- png_error edi, 'Invalid bit depth for RGB image'
- @@:
- mov byte[edi+png_struct.channels], 3
- jmp .end_s0
- .end_1:
-
- cmp ebx,PNG_COLOR_TYPE_PALETTE
- jne .end_2
- cmp byte[bit_depth],1
- je @f
- cmp byte[bit_depth],2
- je @f
- cmp byte[bit_depth],4
- je @f
- cmp byte[bit_depth],8
- je @f
- jmp .def_1
- @@:
- mov byte[edi+png_struct.channels], 1
- jmp .end_s0
- .def_1: ;default
- png_error edi, 'Invalid bit depth for paletted image'
- jmp .end_s0
- .end_2:
-
- cmp ebx,PNG_COLOR_TYPE_GRAY_ALPHA
- jne .end_3
- cmp byte[bit_depth],8
- je @f ;if (..!=8)
- cmp byte[bit_depth],16
- je @f ;if (..!=16)
- png_error edi, 'Invalid bit depth for grayscale+alpha image'
- @@:
- mov byte[edi+png_struct.channels], 2
- jmp .end_s0
- .end_3:
-
- cmp ebx,PNG_COLOR_TYPE_RGB_ALPHA
- jne .end_4
- cmp byte[bit_depth],8
- je @f ;if (..!=8)
-if PNG_WRITE_16BIT_SUPPORTED eq 1
- cmp byte[bit_depth],16
- je @f ;if (..!=16)
-end if
- png_error edi, 'Invalid bit depth for RGBA image'
- @@:
- mov byte[edi+png_struct.channels], 4
- jmp .end_s0
- .end_4:
-
- ;default:
- png_error edi, 'Invalid image color type specified'
- .end_s0:
-
- cmp byte[compression_type], PNG_COMPRESSION_TYPE_BASE
- je @f ;if (..!=..)
- png_warning edi, 'Invalid compression type specified'
- mov dword[compression_type], PNG_COMPRESSION_TYPE_BASE
- @@:
-
- ; Write filter_method 64 (intrapixel differencing) only if
- ; 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
- ; 2. Libpng did not write a PNG signature (this filter_method is only
- ; used in PNG datastreams that are embedded in MNG datastreams) and
- ; 3. The application called png_permit_mng_features with a mask that
- ; included PNG_FLAG_MNG_FILTER_64 and
- ; 4. The filter_method is 64 and
- ; 5. The color_type is RGB or RGBA
-
-; if (
-if PNG_MNG_FEATURES_SUPPORTED eq 1
-; !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
-; ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) == 0) &&
-; (color_type == PNG_COLOR_TYPE_RGB ||
-; color_type == PNG_COLOR_TYPE_RGB_ALPHA) &&
-; (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) &&
-end if
- cmp dword[filter_type],PNG_FILTER_TYPE_BASE
- je @f ;if (..!=..)
- png_warning edi, 'Invalid filter type specified'
- mov dword[filter_type], PNG_FILTER_TYPE_BASE
- @@:
-
-if PNG_WRITE_INTERLACING_SUPPORTED eq 1
- cmp dword[interlace_type],PNG_INTERLACE_NONE
- je @f ;if (..!=..)
- cmp dword[interlace_type],PNG_INTERLACE_ADAM7
- je @f ;if (..!=..)
- png_warning edi, 'Invalid interlace type specified'
- mov dword[interlace_type], PNG_INTERLACE_ADAM7
- @@:
-else
- mov dword[interlace_type], PNG_INTERLACE_NONE
-end if
-
- ; Save the relevant information
- mov al,byte[bit_depth]
- mov byte[edi+png_struct.bit_depth],al
- mov al,byte[color_type]
- mov byte[edi+png_struct.color_type],al
- mov al,byte[interlace_type]
- mov byte[edi+png_struct.interlaced],al
-if PNG_MNG_FEATURES_SUPPORTED eq 1
- mov al,byte[filter_type]
- mov byte[edi+png_struct.filter_type],al
-end if
- mov al,byte[compression_type]
- mov byte[edi+png_struct.compression_type],al
- mov eax,[width]
- mov [edi+png_struct.width],eax
- mov eax,[height]
- mov [edi+png_struct.height],eax
-
- movzx eax,byte[edi+png_struct.channels]
- imul ax,word[bit_depth]
- mov byte[edi+png_struct.pixel_depth],al
- PNG_ROWBYTES eax, [width]
- mov [edi+png_struct.rowbytes],eax
- ; Set the usr info, so any transformations can modify it
- mov eax,[edi+png_struct.width]
- mov [edi+png_struct.usr_width],eax
- mov al,[edi+png_struct.bit_depth]
- mov [edi+png_struct.usr_bit_depth],al
- mov al,[edi+png_struct.channels]
- mov [edi+png_struct.usr_channels],al
-
- ; Pack the header information into the buffer
- mov ebx,ebp
- sub ebx,13
- stdcall png_save_uint_32, ebx, [width]
- add ebx,4
- stdcall png_save_uint_32, ebx, [height]
- add ebx,4
- mov al,byte[bit_depth]
- mov byte[ebx],al ;buf[8] = (byte)bit_depth
- inc ebx
- mov al,byte[color_type]
- mov byte[ebx],al ;buf[9] = (byte)color_type
- inc ebx
- mov al,byte[compression_type]
- mov byte[ebx],al ;buf[10] = (byte)compression_type
- inc ebx
- mov al,byte[filter_type]
- mov byte[ebx],al ;buf[11] = (byte)filter_type
- inc ebx
- mov al,byte[interlace_type]
- mov byte[ebx],al ;buf[12] = (byte)interlace_type
- sub ebx,12
-
- ; Write the chunk
- stdcall png_write_complete_chunk, edi, png_IHDR, ebx, dword 13
-
- cmp byte[edi+png_struct.do_filter],PNG_NO_FILTERS
- jne .end_5 ;if (..==..)
-
- cmp byte[edi+png_struct.color_type],PNG_COLOR_TYPE_PALETTE
- je @f
- cmp byte[edi+png_struct.bit_depth],8
- jl @f ;if ((..==..)||(..<..))
- jmp .els_5
- @@:
- mov byte[edi+png_struct.do_filter], PNG_FILTER_NONE
- jmp .end_5
- .els_5: ;else
- mov byte[edi+png_struct.do_filter], PNG_ALL_FILTERS
- .end_5:
-
- mov dword[edi+png_struct.mode], PNG_HAVE_IHDR ;not READY_FOR_ZTXT
-popad
- ret
-endp
-
-; Write the palette. We are careful not to trust png_color to be in the
-; correct order for PNG, so people can redefine it to any convenient
-; structure.
-
-;void (png_structrp png_ptr, png_const_colorp palette, uint_32 num_pal)
-align 4
-proc png_write_PLTE, png_ptr:dword, palette:dword, num_pal:dword
-locals
- ;max_palette_length dd ? ;uint_32
- i dd ?
- pal_ptr dd ? ;png_const_colorp
- buf rb 3 ;byte[3]
-endl
- png_debug 1, 'in png_write_PLTE'
-
-pushad
- mov edi,[png_ptr]
- movzx eax,byte[edi+png_struct.color_type]
- cmp eax,PNG_COLOR_TYPE_PALETTE
- je @f ;if (..==..)
- ;mov dword[max_palette_length],PNG_MAX_PALETTE_LENGTH
- mov eax,PNG_MAX_PALETTE_LENGTH
- jmp .end0
- @@:
- mov cl,byte[edi+png_struct.bit_depth]
- xor eax,eax
- inc eax
- shl eax,cl
- ;mov [max_palette_length],eax
- .end0:
-
-if PNG_MNG_FEATURES_SUPPORTED eq 1
- cmp [num_pal],eax
- jg @f
- mov eax,[edi+png_struct.mng_features_permitted]
- and eax,PNG_FLAG_MNG_EMPTY_PLTE
- jnz .end1
- cmp [num_pal],0
- jne .end1
- @@:
-end if
-
- cmp byte[edi+png_struct.color_type],PNG_COLOR_TYPE_PALETTE ;if (..==..)
- jne @f
- png_error edi, 'Invalid number of colors in palette'
- jmp .end1
- @@: ;else
- png_warning edi, 'Invalid number of colors in palette'
- jmp .end_f
- .end1:
-
- movzx eax,byte[edi+png_struct.color_type]
- and eax,PNG_COLOR_MASK_COLOR
- jnz @f ;if (..==0)
- png_warning edi, 'Ignoring request to write a PLTE chunk in grayscale PNG'
- jmp .end_f
- @@:
-
- movzx eax,word[num_pal]
- mov word[edi+png_struct.num_palette],ax
- png_debug1 3, 'num_palette = %d', eax
-
- imul eax,3
- stdcall png_write_chunk_header, edi, png_PLTE, eax
-if PNG_POINTER_INDEXING_SUPPORTED eq 1
-
-; for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++)
-; {
-; buf[0] = pal_ptr->red;
-; buf[1] = pal_ptr->green;
-; buf[2] = pal_ptr->blue;
-; png_write_chunk_data(png_ptr, buf, (png_size_t)3);
-; }
-
-else
- ; This is a little slower but some buggy compilers need to do this
- ; instead
-
-; pal_ptr=palette;
-
-; for (i = 0; i < num_pal; i++)
-; {
-; buf[0] = pal_ptr[i].red;
-; buf[1] = pal_ptr[i].green;
-; buf[2] = pal_ptr[i].blue;
-; png_write_chunk_data(png_ptr, buf, (png_size_t)3);
-; }
-
-end if
- stdcall png_write_chunk_end, edi
- or dword[edi+png_struct.mode], PNG_HAVE_PLTE
-.end_f:
-popad
- ret
-endp
-
-; This is similar to png_text_compress, above, except that it does not require
-; all of the data at once and, instead of buffering the compressed result,
-; writes it as IDAT chunks. Unlike png_text_compress it *can* png_error out
-; because it calls the write interface. As a result it does its own error
-; reporting and does not return an error code. In the event of error it will
-; just call png_error. The input data length may exceed 32-bits. The 'flush'
-; parameter is exactly the same as that to deflate, with the following
-; meanings:
-
-; Z_NO_FLUSH: normal incremental output of compressed data
-; Z_SYNC_FLUSH: do a SYNC_FLUSH, used by png_write_flush
-; Z_FINISH: this is the end of the input, do a Z_FINISH and clean up
-
-; The routine manages the acquire and release of the png_ptr->zstream by
-; checking and (at the end) clearing png_ptr->zowner; it does some sanity
-; checks on the 'mode' flags while doing this.
-
-;void (png_structrp png_ptr, bytep input, png_alloc_size_t input_len, int flush)
-;input:
-; edi - png_ptr
-align 4
-proc png_compress_IDAT uses eax ebx ecx edx, input:dword, input_len:dword, flush:dword
- png_debug 1, 'in png_compress_IDAT'
-
- cmp dword[edi+png_struct.zowner],png_IDAT
- je .end0 ;if (..!=..)
- ; First time. Ensure we have a temporary buffer for compression and
- ; trim the buffer list if it has more than one entry to free memory.
- ; If 'WRITE_COMPRESSED_TEXT' is not set the list will never have been
- ; created at this point, but the check here is quick and safe.
-
- cmp dword[edi+png_struct.zbuffer_list],0
- jne @f ;if (..==0)
- PNG_COMPRESSION_BUFFER_SIZE edi
- stdcall png_malloc, edi, eax
- mov [edi+png_struct.zbuffer_list],eax
- mov dword[eax+png_compression_buffer.next],0
- jmp .end1
- @@: ;else
- mov eax,[edi+png_struct.zbuffer_list]
- add eax,png_compression_buffer.next
- ;eax = &...next
- stdcall png_free_buffer_list, edi, eax
- .end1:
-
- ;It is a terminal error if we can't claim the zstream.
- stdcall png_image_size, edi
- stdcall png_deflate_claim, png_IDAT, eax
- cmp eax,Z_OK
- je @f ;if (..!=..)
- png_error edi, [edi+png_struct.zstream.msg]
- @@:
-
- ; The output state is maintained in png_ptr->zstream, so it must be
- ; initialized here after the claim.
-
- mov eax,[edi+png_struct.zbuffer_list]
- add eax,png_compression_buffer.output
- mov [edi+png_struct.zstream.next_out],eax
- mov eax,[edi+png_struct.zbuffer_size]
- mov [edi+png_struct.zstream.avail_out],eax
- .end0:
-
- ; Now loop reading and writing until all the input is consumed or an error
- ; terminates the operation. The _out values are maintained across calls to
- ; this function, but the input must be reset each time.
-
- mov eax,[input]
- mov [edi+png_struct.zstream.next_in],eax
- mov dword[edi+png_struct.zstream.avail_in],0 ;set below
-align 4
- .cycle0:
- ;INPUT: from the row data
- mov eax,ZLIB_IO_MAX
-
- cmp eax,[input_len]
- jbe @f ;if (..>..)
- mov eax,[input_len] ;safe because of the check
- @@:
-
- mov [edi+png_struct.zstream.avail_in],eax
- sub [input_len],eax
-
- mov eax,[flush]
- cmp dword[input_len],0
- jle @f
- mov eax,Z_NO_FLUSH
- @@:
- mov ecx,edi
- add ecx,png_struct.zstream
- stdcall [deflate], ecx, eax
- mov ebx,eax
-
- ;Include as-yet unconsumed input
- mov eax,[edi+png_struct.zstream.avail_in]
- add [input_len],eax
- mov dword[edi+png_struct.zstream.avail_in],0
-
- ; OUTPUT: write complete IDAT chunks when avail_out drops to zero. Note
- ; that these two zstream fields are preserved across the calls, therefore
- ; there is no need to set these up on entry to the loop.
-
- cmp dword[edi+png_struct.zstream.avail_out],0
- jne .end2 ;if (..==0)
- mov edx,[edi+png_struct.zbuffer_list]
- add edx,png_compression_buffer.output
- mov ecx,[edi+png_struct.zbuffer_size]
- ;edx = data
- ;ecx = size
- ; Write an IDAT containing the data then reset the buffer. The
- ; first IDAT may need deflate header optimization.
-
-if PNG_WRITE_OPTIMIZE_CMF_SUPPORTED eq 1
- mov eax,[edi+png_struct.mode]
- and eax,PNG_HAVE_IDAT
- jnz @f
- cmp byte[edi+png_struct.compression_type],PNG_COMPRESSION_TYPE_BASE
- jne @f ;if (..==0 && ..==..)
- stdcall png_image_size, edi
- stdcall optimize_cmf, edx, eax
- @@:
-end if
-
- stdcall png_write_complete_chunk, edi, png_IDAT, edx, ecx
- or dword[edi+png_struct.mode],PNG_HAVE_IDAT
-
- mov [edi+png_struct.zstream.next_out],edx
- mov [edi+png_struct.zstream.avail_out],ecx
-
- ; For SYNC_FLUSH or FINISH it is essential to keep calling zlib with
- ; the same flush parameter until it has finished output, for NO_FLUSH
- ; it doesn't matter.
-
- cmp ebx,Z_OK
- jne .end2
- cmp dword[flush],Z_NO_FLUSH
- jne .cycle0 ;if (..==.. && ..!=..) continue
- .end2:
-
- ; The order of these checks doesn't matter much; it just affects which
- ; possible error might be detected if multiple things go wrong at once.
-
- cmp ebx,Z_OK
- jne .end3 ;if (..==..) ;most likely return code!
- ; If all the input has been consumed then just return. If Z_FINISH
- ; was used as the flush parameter something has gone wrong if we get
- ; here.
-
- cmp dword[input_len],0
- jne .cycle0 ;if (..==0)
- cmp dword[flush],Z_FINISH
- jne .cycle0end ;if (..==..)
- png_error edi, 'Z_OK on Z_FINISH with output space'
- jmp .cycle0end
- .end3:
- cmp ebx,Z_STREAM_END
- jne .end4
- cmp dword[flush],Z_FINISH
- jne .end4 ;else if (..==.. && ..==..)
- ; This is the end of the IDAT data; any pending output must be
- ; flushed. For small PNG files we may still be at the beginning.
-
- mov edx,[edi+png_struct.zbuffer_list]
- add edx,png_compression_buffer.output
- mov ecx,[edi+png_struct.zbuffer_size]
- mov eax,[edi+png_struct.zstream.avail_out]
- sub ecx,eax
- ;edx = data
- ;ecx = size
-
-if PNG_WRITE_OPTIMIZE_CMF_SUPPORTED eq 1
- mov eax,[edi+png_struct.mode]
- and eax,PNG_HAVE_IDAT
- jnz @f
- cmp byte[edi+png_struct.compression_type],PNG_COMPRESSION_TYPE_BASE
- jne @f ;if (..==0 && ..==..)
- stdcall png_image_size, edi
- stdcall optimize_cmf, edx, eax
- @@:
-end if
- stdcall png_write_complete_chunk, edi, png_IDAT, edx, ecx
- mov dword[edi+png_struct.zstream.avail_out],0
- mov dword[edi+png_struct.zstream.next_out],0
- or dword[edi+png_struct.mode], PNG_HAVE_IDAT or PNG_AFTER_IDAT
-
- mov dword[edi+png_struct.zowner],0 ;Release the stream
- jmp .cycle0end
- .end4: ;else
- ; This is an error condition.
- stdcall png_zstream_error, edi, ebx
- png_error edi, [edi+png_struct.zstream.msg]
- jmp .cycle0
- .cycle0end:
- ret
-endp
-
-; Write an IEND chunk
-;void (png_structrp png_ptr)
-align 4
-proc png_write_IEND uses edi, png_ptr:dword
- png_debug 1, 'in png_write_IEND'
-
- mov edi,[png_ptr]
- stdcall png_write_complete_chunk, edi, png_IEND, 0, 0
- or dword[edi+png_struct.mode], PNG_HAVE_IEND
- ret
-endp
-
-; Write a gAMA chunk
-;void (png_structrp png_ptr, png_fixed_point file_gamma)
-align 4
-proc png_write_gAMA_fixed uses ebx, png_ptr:dword, file_gamma:dword
-locals
- buf rb 4 ;byte[4]
-endl
- png_debug 1, 'in png_write_gAMA'
-
- ; file_gamma is saved in 1/100,000ths
- mov ebx,ebp
- sub ebx,4
- stdcall png_save_uint_32 ,ebx, [file_gamma]
- stdcall png_write_complete_chunk, [png_ptr], png_gAMA, ebx, 4
- ret
-endp
-
-; Write a sRGB chunk
-;void (png_structrp png_ptr, int srgb_intent)
-align 4
-proc png_write_sRGB uses eax ebx, png_ptr:dword, srgb_intent:dword
-locals
- buf db ? ;byte[1]
-endl
- png_debug 1, 'in png_write_sRGB'
-
- cmp dword[srgb_intent], PNG_sRGB_INTENT_LAST ;if (..>=..)
- jl @f
- png_warning [png_ptr], 'Invalid sRGB rendering intent specified'
- @@:
-
- mov al,byte[srgb_intent]
- mov ebx,ebp
- dec ebx
- mov byte[ebx],al ;buf[0]=(byte)srgb_intent
- stdcall png_write_complete_chunk, [png_ptr], png_sRGB, ebx, 1
- ret
-endp
-
-; Write an iCCP chunk
-;void (png_structrp png_ptr, charp name, bytep profile)
-align 4
-proc png_write_iCCP uses eax ebx ecx edi, png_ptr:dword, name:dword, profile:dword
-locals
- name_len dd ? ;uint_32
- profile_len dd ? ;uint_32
- temp dd ? ;uint_32
- new_name rb 81 ;byte[81] ;1 byte for the compression byte
- comp compression_state
-endl
- png_debug 1, 'in png_write_iCCP'
-
- ; These are all internal problems: the profile should have been checked
- ; before when it was stored.
-
- mov edi,[png_ptr]
- cmp dword[profile],0
- jne @f ;if (..==0)
- png_error edi, 'No profile for iCCP chunk' ;internal error
- @@:
-
- stdcall png_get_uint_32,[profile]
- mov [profile_len],eax
-
- cmp eax,132
- jge @f ;if (..<..)
- png_error edi, 'ICC profile too short'
- @@:
-
-; temp = (uint_32) (*(profile+8));
-; if (temp > 3 && (profile_len & 0x03))
-; png_error(png_ptr, "ICC profile length invalid (not a multiple of 4)");
-
-; {
-; uint_32 embedded_profile_len = png_get_uint_32(profile);
-
-; if (profile_len != embedded_profile_len)
-; png_error(png_ptr, "Profile length does not match profile");
-; }
-
- mov ebx,ebp
- sub ebx,sizeof.compression_state
- mov ecx,ebx ;ecx = &comp
- sub ebx,81 ;ebx = &new_name
- stdcall png_check_keyword, edi, [name], ebx
- mov [name_len],eax
-
- test eax,eax
- jnz @f ;if (..==0)
- png_error edi, 'iCCP: invalid keyword'
- @@:
-
- inc dword[name_len]
- mov eax,[name_len]
- add eax,ebx
- mov byte[eax], PNG_COMPRESSION_TYPE_BASE
-
- ; Make sure we include the NULL after the name and the compression type
- inc dword[name_len]
-
- stdcall png_text_compress_init, ecx, [profile], [profile_len]
-
- ; Allow for keyword terminator and compression byte
-; if (png_text_compress(png_ptr, png_iCCP, &comp, name_len) != Z_OK)
-; png_error(png_ptr, png_ptr->zstream.msg);
-
-; png_write_chunk_header(png_ptr, png_iCCP, name_len + comp.output_len);
-
- stdcall png_write_chunk_data, edi, ebx, [name_len]
-
- stdcall png_write_compressed_data_out, edi, ecx
-
- stdcall png_write_chunk_end, edi
- ret
-endp
-
-; Write a sPLT chunk
-;void (png_structrp png_ptr, png_const_sPLT_tp spalette)
-align 4
-proc png_write_sPLT, png_ptr:dword, spalette:dword
-; uint_32 name_len;
-; byte new_name[80];
-; byte entrybuf[10];
-; png_size_t entry_size = (spalette->depth == 8 ? 6 : 10);
-; png_size_t palette_size = entry_size * spalette->nentries;
-; png_sPLT_entryp ep;
-if PNG_POINTER_INDEXING_SUPPORTED eq
-; int i;
-end if
-
- png_debug 1, 'in png_write_sPLT'
-
-; name_len = png_check_keyword(png_ptr, spalette->name, new_name);
-
-; if (name_len == 0)
-; png_error(png_ptr, "sPLT: invalid keyword");
-
- ; Make sure we include the NULL after the name
-; png_write_chunk_header(png_ptr, png_sPLT,
-; (uint_32)(name_len + 2 + palette_size));
-
-; png_write_chunk_data(png_ptr, (bytep)new_name,
-; (png_size_t)(name_len + 1));
-
-; png_write_chunk_data(png_ptr, &spalette->depth, (png_size_t)1);
-
- ; Loop through each palette entry, writing appropriately
-if PNG_POINTER_INDEXING_SUPPORTED eq 1
-; for (ep = spalette->entries; epentries + spalette->nentries; ep++)
-; {
-; if (spalette->depth == 8)
-; {
-; entrybuf[0] = (byte)ep->red;
-; entrybuf[1] = (byte)ep->green;
-; entrybuf[2] = (byte)ep->blue;
-; entrybuf[3] = (byte)ep->alpha;
-; png_save_uint_16(entrybuf + 4, ep->frequency);
-; }
-
-; else
-; {
-; png_save_uint_16(entrybuf + 0, ep->red);
-; png_save_uint_16(entrybuf + 2, ep->green);
-; png_save_uint_16(entrybuf + 4, ep->blue);
-; png_save_uint_16(entrybuf + 6, ep->alpha);
-; png_save_uint_16(entrybuf + 8, ep->frequency);
-; }
-
-; png_write_chunk_data(png_ptr, entrybuf, entry_size);
-; }
-else
-; ep=spalette->entries;
-; for (i = 0; i>spalette->nentries; i++)
-; {
-; if (spalette->depth == 8)
-; {
-; entrybuf[0] = (byte)ep[i].red;
-; entrybuf[1] = (byte)ep[i].green;
-; entrybuf[2] = (byte)ep[i].blue;
-; entrybuf[3] = (byte)ep[i].alpha;
-; png_save_uint_16(entrybuf + 4, ep[i].frequency);
-; }
-
-; else
-; {
-; png_save_uint_16(entrybuf + 0, ep[i].red);
-; png_save_uint_16(entrybuf + 2, ep[i].green);
-; png_save_uint_16(entrybuf + 4, ep[i].blue);
-; png_save_uint_16(entrybuf + 6, ep[i].alpha);
-; png_save_uint_16(entrybuf + 8, ep[i].frequency);
-; }
-
-; png_write_chunk_data(png_ptr, entrybuf, entry_size);
-; }
-end if
-
-; png_write_chunk_end(png_ptr);
- ret
-endp
-
-; Write the sBIT chunk
-;void (png_structrp png_ptr, png_const_color_8p sbit, int color_type)
-align 4
-proc png_write_sBIT uses eax edi, png_ptr:dword, sbit:dword, color_type:dword
-locals
- size dd ? ;png_size_t
- buf rb 4 ;byte[4]
-endl
- png_debug 1, 'in png_write_sBIT'
-
- ; Make sure we don't depend upon the order of PNG_COLOR_8
-; if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
-; {
-; byte maxbits;
-
-; maxbits = (byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 :
-; png_ptr->usr_bit_depth);
-
-; if (sbit->red == 0 || sbit->red > maxbits ||
-; sbit->green == 0 || sbit->green > maxbits ||
-; sbit->blue == 0 || sbit->blue > maxbits)
-; {
-; png_warning(png_ptr, "Invalid sBIT depth specified");
-; return;
-; }
-
-; buf[0] = sbit->red;
-; buf[1] = sbit->green;
-; buf[2] = sbit->blue;
-; size = 3;
-; }
-
-; else
-; {
-; if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth)
-; {
-; png_warning(png_ptr, "Invalid sBIT depth specified");
-; return;
-; }
-
-; buf[0] = sbit->gray;
-; size = 1;
-; }
-
-; if ((color_type & PNG_COLOR_MASK_ALPHA) != 0)
-; {
-; if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth)
-; {
-; png_warning(png_ptr, "Invalid sBIT depth specified");
-; return;
-; }
-
-; buf[size++] = sbit->alpha;
-; }
-
-; png_write_complete_chunk(png_ptr, png_sBIT, buf, size);
-.end_f:
- ret
-endp
-
-; Write the cHRM chunk
-;void (png_structrp png_ptr, const png_xy *xy)
-align 4
-proc png_write_cHRM_fixed uses eax ebx, png_ptr:dword, xy:dword
-locals
- buf rb 32 ;byte[32]
-endl
- png_debug 1, 'in png_write_cHRM'
-
- ; Each value is saved in 1/100,000ths
- mov eax,[xy]
- mov ebx,ebp
- sub ebx,32
-; png_save_int_32(buf, xy->whitex);
-; png_save_int_32(buf + 4, xy->whitey);
-
-; png_save_int_32(buf + 8, xy->redx);
-; png_save_int_32(buf + 12, xy->redy);
-
-; png_save_int_32(buf + 16, xy->greenx);
-; png_save_int_32(buf + 20, xy->greeny);
-
-; png_save_int_32(buf + 24, xy->bluex);
-; png_save_int_32(buf + 28, xy->bluey);
-
- stdcall png_write_complete_chunk, [png_ptr], png_cHRM, ebx, 32
- ret
-endp
-
-; Write the tRNS chunk
-;void (png_structrp png_ptr, bytep trans_alpha, png_color_16p tran, int num_trans, int color_type)
-align 4
-proc png_write_tRNS uses eax ebx ecx edi, png_ptr:dword, trans_alpha:dword, tran:dword, num_trans:dword, color_type:dword
-locals
- buf rb 6 ;byte[6]
-endl
- png_debug 1, 'in png_write_tRNS'
-
- mov edi,[png_ptr]
- cmp byte[color_type],PNG_COLOR_TYPE_PALETTE
- jne .end0 ;if (..==..)
- cmp dword[num_trans],0
- jle @f
- movzx eax,word[edi+png_struct.num_palette]
- cmp [num_trans],eax
- jle .end1
- @@: ;if (..<=0 || ..>..)
- png_app_warning edi, 'Invalid number of transparent colors specified'
- jmp .end_f
- .end1:
-
- ; Write the chunk out as it is
- stdcall png_write_complete_chunk, edi, png_tRNS, [trans_alpha], [num_trans]
- jmp .end_f
- .end0:
-
- cmp dword[color_type],PNG_COLOR_TYPE_GRAY
- jne .end2 ;else if (..==..)
- ; One 16-bit value
- mov cl,[edi+png_struct.bit_depth]
- xor eax,eax
- inc eax
- shl eax,cl
- mov ecx,[tran]
- cmp word[ecx+png_color_16.gray],ax
- jl @f ;if (..>=..)
- png_app_warning edi, 'Ignoring attempt to write tRNS chunk out-of-range for bit_depth'
- jmp .end_f
- @@:
- movzx eax,word[ecx+png_color_16.gray]
- mov ebx,ebp
- sub ebx,6
- stdcall png_save_uint_16, ebx, eax
- stdcall png_write_complete_chunk, edi, png_tRNS, ebx, 2
- jmp .end_f
- .end2:
-
- cmp dword[color_type],PNG_COLOR_TYPE_RGB
- jne .end3 ;else if (..== ..)
- ; Three 16-bit values
- mov ebx,ebp
- sub ebx,6
- mov ecx,[tran]
- movzx eax,word[ecx+png_color_16.red]
- stdcall png_save_uint_16, ebx, eax
- add ebx,2
- movzx eax,word[ecx+png_color_16.green]
- stdcall png_save_uint_16, ebx, eax
- add ebx,2
- movzx eax,word[ecx+png_color_16.blue]
- stdcall png_save_uint_16, ebx, eax
- sub ebx,4
-if PNG_WRITE_16BIT_SUPPORTED eq 1
- cmp byte[edi+png_struct.bit_depth],8
- jne @f ;if (..==.. && ...
-end if
- mov al,[ebx]
- or al,[ebx+2]
- or al,[ebx+4]
- cmp al,0
- je @f ;if (..|..|..!=0)
- png_app_warning edi, 'Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8'
- jmp .end_f
- @@:
- stdcall png_write_complete_chunk, edi, png_tRNS, ebx, 6
- jmp .end_f
- .end3: ;else
- cStr ,<'Can',39,'t write tRNS with an alpha channel'>
- png_app_warning edi, eax
-.end_f:
- ret
-endp
-
-; Write the background chunk
-;void (png_structrp png_ptr, png_const_color_16p back, int color_type)
-align 4
-proc png_write_bKGD, png_ptr:dword, back:dword, color_type:dword
-locals
- buf rb 6 ;byte[6]
-endl
- png_debug 1, 'in png_write_bKGD'
-
-; if (color_type == PNG_COLOR_TYPE_PALETTE)
-; {
-; if (
-if PNG_MNG_FEATURES_SUPPORTED eq 1
-; (png_ptr->num_palette != 0 ||
-; (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0) &&
-end if
-; back->index >= png_ptr->num_palette)
-; {
-; png_warning(png_ptr, "Invalid background palette index");
-; return;
-; }
-
-; buf[0] = back->index;
-; png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)1);
-; }
-
-; else if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
-; {
-; png_save_uint_16(buf, back->red);
-; png_save_uint_16(buf + 2, back->green);
-; png_save_uint_16(buf + 4, back->blue);
-if PNG_WRITE_16BIT_SUPPORTED eq 1
-; if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]) != 0)
-else
-; if ((buf[0] | buf[2] | buf[4]) != 0)
-end if
-; {
-; png_warning(png_ptr,
-; "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8");
-
-; return;
-; }
-
-; png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)6);
-; }
-
-; else
-; {
-; if (back->gray >= (1 << png_ptr->bit_depth))
-; {
-; png_warning(png_ptr,
-; "Ignoring attempt to write bKGD chunk out-of-range for bit_depth");
-
-; return;
-; }
-
-; png_save_uint_16(buf, back->gray);
-; png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)2);
-; }
- ret
-endp
-
-; Write the histogram
-;void (png_structrp png_ptr, png_const_uint_16p hist, int num_hist)
-align 4
-proc png_write_hIST, png_ptr:dword, hist:dword, num_hist:dword
-locals
- i dd ? ;int
- buf rb 3 ;byte[3]
-endl
- png_debug 1, 'in png_write_hIST'
-pushad
-
- mov edi,[png_ptr]
- movzx eax,word[edi+png_struct.num_palette]
- cmp [num_hist],eax
- jle @f ;if (..>..)
-; png_debug2(3, "num_hist = %d, num_palette = %d", num_hist,
-; png_ptr->num_palette);
-
- png_warning edi, 'Invalid number of histogram entries specified'
- jmp .end_f
- @@:
-
- mov eax,[num_hist]
- shl eax,1
- stdcall png_write_chunk_header, edi, png_hIST, eax
-
-; for (i = 0; i < num_hist; i++)
-; {
-; png_save_uint_16(buf, hist[i]);
-; png_write_chunk_data(png_ptr, buf, (png_size_t)2);
-; }
-
- stdcall png_write_chunk_end, edi
-.end_f:
-popad
- ret
-endp
-
-; Write a tEXt chunk
-;void (png_structrp png_ptr, charp key, charp text, png_size_t text_len)
-align 4
-proc png_write_tEXt uses eax edi, png_ptr:dword, key:dword, text:dword, text_len:dword
-locals
- key_len dd ? ;uint_32
- new_key rb 80 ;byte[80]
-endl
- png_debug 1, 'in png_write_tEXt'
-
-; key_len = png_check_keyword(png_ptr, key, new_key);
-
-; if (key_len == 0)
-; png_error(png_ptr, "tEXt: invalid keyword");
-
-; if (text == NULL || *text == '\0')
-; text_len = 0;
-
-; else
-; text_len = strlen(text);
-
-; if (text_len > PNG_UINT_31_MAX - (key_len+1))
-; png_error(png_ptr, "tEXt: text too long");
-
- ; Make sure we include the 0 after the key
-; png_write_chunk_header(png_ptr, png_tEXt,
-; (uint_32)/*checked above*/(key_len + text_len + 1));
-
- ; We leave it to the application to meet PNG-1.0 requirements on the
- ; contents of the text. PNG-1.0 through PNG-1.2 discourage the use of
- ; any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them.
- ; The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
-
-; png_write_chunk_data(png_ptr, new_key, key_len + 1);
-
-; if (text_len != 0)
-; png_write_chunk_data(png_ptr, (bytep)text, text_len);
-
-; png_write_chunk_end(png_ptr);
- ret
-endp
-
-if PNG_WRITE_zTXt_SUPPORTED eq 1
-; Write a compressed text chunk
-;void (png_structrp png_ptr, charp key, charp text, int compression)
-align 4
-proc png_write_zTXt uses eax edi, png_ptr:dword, key:dword, text:dword, compression:dword
-locals
- key_len dd ? ;uint_32
- new_key rb 81 ;byte[81]
- comp compression_state
-endl
- png_debug 1, 'in png_write_zTXt'
-
- mov edi,[png_ptr]
- cmp dword[compression],PNG_TEXT_COMPRESSION_NONE
- jne @f ;if (..==..)
- stdcall png_write_tEXt, edi, [key], [text], 0
- jmp .end_f
- @@:
-
-; if (compression != PNG_TEXT_COMPRESSION_zTXt)
-; png_error(png_ptr, "zTXt: invalid compression type");
-
-; key_len = png_check_keyword(png_ptr, key, new_key);
-
-; if (key_len == 0)
-; png_error(png_ptr, "zTXt: invalid keyword");
-
- ; Add the compression method and 1 for the keyword separator.
-; new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE;
-; ++key_len;
-
- ; Compute the compressed data; do it now for the length
-; png_text_compress_init(&comp, (bytep)text,
-; text == NULL ? 0 : strlen(text));
-
-; if (png_text_compress(png_ptr, png_zTXt, &comp, key_len) != Z_OK)
-; png_error(png_ptr, png_ptr->zstream.msg);
-
- ; Write start of chunk
-; png_write_chunk_header(png_ptr, png_zTXt, key_len + comp.output_len);
-
- ; Write key
-; png_write_chunk_data(png_ptr, new_key, key_len);
-
- ; Write the compressed data
-; png_write_compressed_data_out(png_ptr, &comp);
-
- ; Close the chunk
- stdcall png_write_chunk_end, edi
-.end_f:
- ret
-endp
-end if
-
-if PNG_WRITE_iTXt_SUPPORTED eq 1
-; Write an iTXt chunk
-;void (png_structrp png_ptr, int compression, charp key,
-; charp lang, charp lang_key, charp text)
-align 4
-proc png_write_iTXt, png_ptr:dword, compression:dword, key:dword, lang:dword, lang_key:dword, text:dword
-locals
- key_len dd ? ;uint_32
- prefix_len dd ?
- ;png_size_t lang_len, lang_key_len;
- new_key rb 82 ;byte[82]
- comp compression_state
-endl
-
- png_debug 1, 'in png_write_iTXt'
-pushad
- mov edi,[png_ptr]
- mov ebx,ebp
- sub ebx,82+sizeof.compression_state
- stdcall png_check_keyword, edi, [key], ebx
- mov [key_len],eax
-
- test eax,eax
- jnz @f ;if (..==0)
- png_error edi, 'iTXt: invalid keyword'
- @@:
-
- ; Set the compression flag
-; switch (compression)
-; {
-; case PNG_ITXT_COMPRESSION_NONE:
-; case PNG_TEXT_COMPRESSION_NONE:
-; compression = new_key[++key_len] = 0; /* no compression */
-; break;
-
-; case PNG_TEXT_COMPRESSION_zTXt:
-; case PNG_ITXT_COMPRESSION_zTXt:
-; compression = new_key[++key_len] = 1; /* compressed */
-; break;
-
-; default:
-; png_error(png_ptr, "iTXt: invalid compression");
-; }
-
-; new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE;
-; ++key_len; /* for the keywod separator */
-
- ; We leave it to the application to meet PNG-1.0 requirements on the
- ; contents of the text. PNG-1.0 through PNG-1.2 discourage the use of
- ; any non-Latin-1 characters except for NEWLINE. ISO PNG, however,
- ; specifies that the text is UTF-8 and this really doesn't require any
- ; checking.
-
- ; The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
-
- ; TODO: validate the language tag correctly (see the spec.)
-
-; if (lang == NULL) lang = ""; /* empty language is valid */
-; lang_len = strlen(lang)+1;
-; if (lang_key == NULL) lang_key = ""; /* may be empty */
-; lang_key_len = strlen(lang_key)+1;
-; if (text == NULL) text = ""; /* may be empty */
-
- mov eax,[key_len]
- mov [prefix_len],eax
-; if (lang_len > PNG_UINT_31_MAX-prefix_len)
-; prefix_len = PNG_UINT_31_MAX;
-; else
-; prefix_len = (uint_32)(prefix_len + lang_len);
-
-; if (lang_key_len > PNG_UINT_31_MAX-prefix_len)
-; prefix_len = PNG_UINT_31_MAX;
-; else
-; prefix_len = (uint_32)(prefix_len + lang_key_len);
-
-; png_text_compress_init(&comp, (bytep)text, strlen(text));
-
-; if (compression != 0)
-; {
-; if (png_text_compress(png_ptr, png_iTXt, &comp, prefix_len) != Z_OK)
-; png_error(png_ptr, png_ptr->zstream.msg);
-; }
-
-; else
-; {
-; if (comp.input_len > PNG_UINT_31_MAX-prefix_len)
-; png_error(png_ptr, "iTXt: uncompressed text too long");
-
- ; So the string will fit in a chunk:
-; comp.output_len = (uint_32)/*SAFE*/comp.input_len;
-; }
-
-; png_write_chunk_header(png_ptr, png_iTXt, comp.output_len + prefix_len);
-
-; png_write_chunk_data(png_ptr, new_key, key_len);
-
-; png_write_chunk_data(png_ptr, (bytep)lang, lang_len);
-
-; png_write_chunk_data(png_ptr, (bytep)lang_key, lang_key_len);
-
-; if (compression != 0)
-; png_write_compressed_data_out(png_ptr, &comp);
-
-; else
-; png_write_chunk_data(png_ptr, (bytep)text, comp.output_len);
-
- stdcall png_write_chunk_end, edi
-popad
- ret
-endp
-end if
-
-; Write the oFFs chunk
-;void (png_structrp png_ptr, int_32 x_offset, int_32 y_offset, int unit_type)
-align 4
-proc png_write_oFFs uses eax ebx edi, png_ptr:dword, x_offset:dword, y_offset:dword, unit_type:dword
-locals
- buf rb 9 ;byte[9]
-endl
- png_debug 1, 'in png_write_oFFs'
-
- mov edi,[png_ptr]
- cmp dword[unit_type],PNG_OFFSET_LAST
- jl @f ;if (..>=..)
- png_warning edi, 'Unrecognized unit type for oFFs chunk'
- @@:
-
- mov ebx,ebp
- sub ebx,9
- stdcall png_save_int_32, ebx, [x_offset]
- add ebx,4
- stdcall png_save_int_32, ebx, [y_offset]
- add ebx,4
- mov eax,[unit_type]
- mov [ebx],al
- sub ebx,8
-
- stdcall png_write_complete_chunk, edi, png_oFFs, ebx, 9
- ret
-endp
-
-; Write the pCAL chunk (described in the PNG extensions document)
-;void (png_structrp png_ptr, charp purpose, int_32 X0,
-; int_32 X1, int type, int nparams, charp units, charpp params)
-align 4
-proc png_write_pCAL, png_ptr:dword, purpose:dword, X0:dword, X1:dword, type:dword,\
- nparams:dword, units:dword, params:dword
-locals
- purpose_len dd ? ;uint_32
- units_len dd ?
- total_len dd ? ;png_size_t
- params_len dd ? ;png_size_tp
- buf rb 10 ;byte[10]
- new_purpose rb 80 ;byte[80]
- i dd ? ;int
-endl
-pushad
- png_debug1 1, 'in png_write_pCAL (%d parameters)', [nparams]
- mov edi,[png_ptr]
-
- cmp dword[type],PNG_EQUATION_LAST
- jl @f ;if (..>=..)
- png_error edi, 'Unrecognized equation type for pCAL chunk'
- @@:
-
- mov ebx,ebp
- sub ebx,84 ;ebx = &new_purpose
- stdcall png_check_keyword, edi, [purpose], ebx
- mov [purpose_len],eax
-
- test eax,eax
- jnz @f ;if(..==0)
- png_error edi, 'pCAL: invalid keyword'
- @@:
-
- inc dword[purpose_len] ; terminator
-
- png_debug1 3, 'pCAL purpose length = %d', [purpose_len]
-; units_len = strlen(units) + (nparams == 0 ? 0 : 1);
- png_debug1 3, 'pCAL units length = %d', [units_len]
-; total_len = purpose_len + units_len + 10;
-
-; params_len = (png_size_tp)png_malloc(png_ptr,
-; (png_alloc_size_t)(nparams * (sizeof (png_size_t))));
-
- ; Find the length of each parameter, making sure we don't count the
- ; null terminator for the last parameter.
-
-; for (i = 0; i < nparams; i++)
-; {
-; params_len[i] = strlen(params[i]) + (i == nparams - 1 ? 0 : 1);
-; png_debug2(3, "pCAL parameter %d length = %lu", i,
-; (unsigned long)params_len[i]);
-; total_len += params_len[i];
-; }
-
- png_debug1 3, 'pCAL total length = %d', [total_len]
- stdcall png_write_chunk_header, edi, png_pCAL, [total_len]
- stdcall png_write_chunk_data, edi, ebx, [purpose_len]
- mov ebx,ebp
- sub ebx,94 ;ebx = &buf
- stdcall png_save_int_32, ebx, [X0]
- add ebx,4
- stdcall png_save_int_32, ebx, [X1]
- add ebx,4
- mov eax,[type]
- mov [ebx],al
- inc ebx
- mov eax,[nparams]
- mov [ebx],al
- sub ebx,9
- stdcall png_write_chunk_data, edi, ebx, 10
- stdcall png_write_chunk_data, edi, [units], [units_len]
-
-; for (i = 0; i < nparams; i++)
-; {
-; png_write_chunk_data(png_ptr, (bytep)params[i], params_len[i]);
-; }
-
- stdcall png_free, edi, [params_len]
- stdcall png_write_chunk_end, edi
-popad
- ret
-endp
-
-; Write the sCAL chunk
-;void (png_structrp png_ptr, int unit, charp width, charp height)
-align 4
-proc png_write_sCAL_s uses eax ebx ecx edi esi, png_ptr:dword, unit:dword, width:dword, height:dword
-locals
- total_len dd 2
- wlen dd ?
- hlen dd ?
- buf rb 64 ;byte[64]
-endl
- png_debug 1, 'in png_write_sCAL_s'
-
- stdcall strlen,[width]
- add [total_len],eax
- mov [wlen],eax
- stdcall strlen,[height]
- add [total_len],eax
- mov [hlen],eax
-
- cmp dword[total_len],64
- jle @f ;if (..>..)
- cStr ,<'Can',39,'t write sCAL (buffer too small)'>
- png_warning [png_ptr], eax
- jmp .end_f
- @@:
-
- mov ebx,ebp
- sub ebx,64
- mov eax,[unit]
- mov byte[ebx],al
- mov ecx,[wlen]
- inc ecx
- mov edi,ebx
- inc edi
- mov esi,[width]
- rep movsb ;Append the '\0' here
- mov ecx,[hlen]
- mov esi,[height]
- rep movsb ;Do NOT append the '\0' here
-
- png_debug1 3, 'sCAL total length = %u', [total_len]
- stdcall png_write_complete_chunk, [png_ptr], png_sCAL, ebx, [total_len]
-.end_f:
- ret
-endp
-
-; Write the pHYs chunk
-;void (png_structrp png_ptr, uint_32 x_pixels_per_unit,
-; uint_32 y_pixels_per_unit, int unit_type)
-align 4
-proc png_write_pHYs uses eax ebx, png_ptr:dword, x_pixels_per_unit:dword, y_pixels_per_unit:dword, unit_type:dword
-locals
- buf rb 9 ;byte[9]
-endl
- png_debug 1, 'in png_write_pHYs'
-
- cmp dword[unit_type],PNG_RESOLUTION_LAST
- jl @f ;if (..>=..)
- png_warning [png_ptr], 'Unrecognized unit type for pHYs chunk'
- @@:
-
- mov ebx,ebp
- sub ebx,9
- stdcall png_save_uint_32, ebx, [x_pixels_per_unit]
- add ebx,4
- stdcall png_save_uint_32, ebx, [y_pixels_per_unit]
- add ebx,4
- mov al,byte[unit_type]
- mov byte[ebx],al
- sub ebx,8
-
- stdcall png_write_complete_chunk, [png_ptr], png_pHYs, ebx, 9
- ret
-endp
-
-; Write the tIME chunk. Use either png_convert_from_struct_tm()
-; or png_convert_from_time_t(), or fill in the structure yourself.
-
-;void (png_structrp png_ptr, png_const_timep mod_time)
-align 4
-proc png_write_tIME uses eax ebx ecx, png_ptr:dword, mod_time:dword
-locals
- buf rb 7 ;byte[7]
-endl
- png_debug 1, 'in png_write_tIME'
-
- mov eax,[mod_time]
- mov cl,[eax+png_time.month]
- cmp cl,12
- jg @f
- cmp cl,1
- jl @f
- mov ch,[eax+png_time.day]
- cmp ch,31
- jg @f
- cmp ch,1
- jl @f
- cmp byte[eax+png_time.hour],23
- jg @f
- cmp byte[eax+png_time.second],60
- jg @f
- jmp .end0
- @@:
- png_warning [png_ptr], 'Invalid time specified for tIME chunk'
- jmp .end_f
- .end0:
-
- movzx ebx,word[eax+png_time.year]
- push ebx
- mov ebx,ebp
- sub ebx,7
- stdcall png_save_uint_16, ebx ;, year
- add ebx,2
- mov byte[ebx],cl ;month
- inc ebx
- mov byte[ebx],ch ;day
- inc ebx
- mov cl,[eax+png_time.hour]
- mov byte[ebx],cl ;hour
- inc ebx
- mov cl,[eax+png_time.minute]
- mov byte[ebx],cl ;minute
- inc ebx
- mov cl,[eax+png_time.second]
- mov byte[ebx],cl ;second
- sub ebx,6
-
- stdcall png_write_complete_chunk, [png_ptr], png_tIME, ebx, 7
-.end_f:
- ret
-endp
-
-if PNG_WRITE_INTERLACING_SUPPORTED eq 1
- ; Arrays to facilitate easy interlacing - use pass (0 - 6) as index
-
- ; Start of interlace block
- png_pass_start db 0, 4, 0, 2, 0, 1, 0
- ; Offset to next interlace block
- png_pass_inc db 8, 8, 4, 4, 2, 2, 1
- ; Start of interlace block in the y direction
- png_pass_ystart db 0, 0, 4, 0, 2, 0, 1
- ; Offset to next interlace block in the y direction
- png_pass_yinc db 8, 8, 8, 4, 4, 2, 2
-end if
-
-; Initializes the row writing capability of libpng
-;void (png_structrp png_ptr)
-align 4
-proc png_write_start_row uses eax ebx ecx edx edi, png_ptr:dword
-locals
- buf_size dd ? ;png_alloc_size_t
- usr_pixel_depth dd ? ;int
-if PNG_WRITE_FILTER_SUPPORTED eq 1
- filters db ? ;byte
-end if
-endl
- png_debug 1, 'in png_write_start_row'
-
- mov edi,[png_ptr]
- movzx eax,byte[edi+png_struct.usr_channels]
- movzx ebx,byte[edi+png_struct.usr_bit_depth]
- imul eax,ebx
- mov [usr_pixel_depth],eax
- PNG_ROWBYTES eax,[edi+png_struct.width]
- inc eax
- mov [buf_size],eax
-
- ; 1.5.6: added to allow checking in the row write code.
- mov al,[edi+png_struct.pixel_depth]
- mov [edi+png_struct.transformed_pixel_depth],al
-
- mov eax,[usr_pixel_depth]
- mov [edi+png_struct.maximum_pixel_depth],al
-
- ; Set up row buffer
- stdcall png_malloc, edi, [buf_size]
- mov [edi+png_struct.row_buf],eax
-
- mov byte[eax],PNG_FILTER_VALUE_NONE
-
-if PNG_WRITE_FILTER_SUPPORTED eq 1
- mov al,byte[edi+png_struct.do_filter]
-
- cmp dword[edi+png_struct.height],1
- jne @f ;if (..==1)
- and al, 0xff and not(PNG_FILTER_UP or PNG_FILTER_AVG or PNG_FILTER_PAETH)
- @@:
- cmp dword[edi+png_struct.width],1
- jne @f ;if (..==1)
- and al, 0xff and not(PNG_FILTER_SUB or PNG_FILTER_AVG or PNG_FILTER_PAETH)
- @@:
-
- cmp al,0
- jne @f ;if (..==0)
- mov al,PNG_FILTER_NONE
- @@:
-
- mov [filters],al
- mov byte[edi+png_struct.do_filter],al
-
- ;mov al,[filters]
- and al,PNG_FILTER_SUB or PNG_FILTER_UP or PNG_FILTER_AVG or PNG_FILTER_PAETH
- cmp al,0
- je .end0
- cmp dword[edi+png_struct.try_row],0
- jne .end0 ;if (..!=0) && ..==0)
- xor ebx,ebx
-
- stdcall png_malloc, edi, [buf_size]
- mov dword[edi+png_struct.try_row],eax
-
- mov al,[filters]
- and al,PNG_FILTER_SUB
- cmp al,0
- je @f
- inc ebx
- @@:
- mov al,[filters]
- and al,PNG_FILTER_UP
- cmp al,0
- je @f
- inc ebx
- @@:
- mov al,[filters]
- and al,PNG_FILTER_AVG
- cmp al,0
- je @f
- inc ebx
- @@:
- mov al,[filters]
- and al,PNG_FILTER_PAETH
- cmp al,0
- je @f
- inc ebx
- @@:
- cmp ebx,1
- jle .end0 ;if (..>1)
- stdcall png_malloc, edi, [buf_size]
- mov dword[edi+png_struct.tst_row],eax
- .end0:
-
- ; We only need to keep the previous row if we are using one of the following
- ; filters.
-
- mov al,[filters]
- and al,PNG_FILTER_AVG or PNG_FILTER_UP or PNG_FILTER_PAETH
- cmp al,0
- je @f ;if (..!=0)
- stdcall png_calloc, edi, [buf_size]
- mov dword[edi+png_struct.prev_row],eax
- @@:
-end if ;WRITE_FILTER
-
-if PNG_WRITE_INTERLACING_SUPPORTED eq 1
- ; If interlaced, we need to set up width and height of pass
- cmp byte[edi+png_struct.interlaced],0
- je @f
- mov eax,[edi+png_struct.transformations]
- and eax,PNG_INTERLACE
- jnz @f ;if(..!=0 && ..==0)
- movzx ecx,byte[png_pass_yinc]
- mov eax,[edi+png_struct.height]
- add eax,ecx
- dec eax
- movzx edx,byte[png_pass_ystart]
- sub eax,edx
- xor edx,edx
- div ecx
- mov [edi+png_struct.num_rows],eax
-
- movzx ecx,byte[png_pass_inc]
- mov eax,[edi+png_struct.width]
- add eax,ecx
- dec eax
- movzx edx,byte[png_pass_start]
- sub eax,edx
- xor edx,edx
- div ecx
- mov [edi+png_struct.usr_width],eax
- jmp .end1
- @@: ;else
-end if
- mov eax,[edi+png_struct.height]
- mov [edi+png_struct.num_rows],eax
- mov eax,[edi+png_struct.width]
- mov [edi+png_struct.usr_width],eax
- .end1:
- ret
-endp
-
-; Internal use only. Called when finished processing a row of data.
-;void (png_structrp png_ptr)
-align 4
-proc png_write_finish_row uses eax ecx edx edi, png_ptr:dword
- png_debug 1, 'in png_write_finish_row'
-
- mov edi,[png_ptr]
- ; Next row
- inc dword[edi+png_struct.row_number]
-
- ; See if we are done
- mov eax,[edi+png_struct.row_number]
- cmp eax,[edi+png_struct.num_rows]
- jl .end_f ;if (..<..) return
-
-if PNG_WRITE_INTERLACING_SUPPORTED eq 1
- ; If interlaced, go to next pass
- cmp byte[edi+png_struct.interlaced],0
- je .end0 ;if (..!=0)
- mov dword[edi+png_struct.row_number],0
- mov eax,[edi+png_struct.transformations]
- and eax,PNG_INTERLACE
- jz @f ;if (..!=0)
- inc byte[edi+png_struct.pass]
- jmp .end1
- @@: ;else
- ; Loop until we find a non-zero width or height pass
- .cycle0: ;do
- inc byte[edi+png_struct.pass]
- cmp byte[edi+png_struct.pass],7
- jge .cycle0end ;if (..>=..) break
-
- movzx ecx,byte[edi+png_struct.pass]
- add ecx,png_pass_inc
- movzx ecx,byte[ecx]
- mov eax,[edi+png_struct.width]
- add eax,ecx
- dec eax
- movzx edx,byte[edi+png_struct.pass]
- add edx,png_pass_start
- movzx edx,byte[edx]
- sub eax,edx
- xor edx,edx
- div ecx
- mov [edi+png_struct.usr_width],eax
-
- movzx ecx,byte[edi+png_struct.pass]
- add ecx,png_pass_yinc
- movzx ecx,byte[ecx]
- mov eax,[edi+png_struct.height]
- add eax,ecx
- dec eax
- movzx edx,byte[edi+png_struct.pass]
- add edx,png_pass_ystart
- movzx edx,byte[edx]
- sub eax,edx
- xor edx,edx
- div ecx
- mov [edi+png_struct.num_rows],eax
-
- mov eax,[edi+png_struct.transformations]
- and eax,PNG_INTERLACE
- jnz .cycle0end ;if(..!=0) break
-
- cmp dword[edi+png_struct.usr_width],0
- je .cycle0
- cmp dword[edi+png_struct.num_rows],0
- je .cycle0
- .cycle0end: ;while (..==0 || ..==0)
- .end1:
-
- ; Reset the row above the image for the next pass
- cmp byte[edi+png_struct.pass],7
- jge .end0 ;if (..<..)
- cmp dword[edi+png_struct.prev_row],0
- je .end_f ;if (..!=0)
- movzx eax,byte[edi+png_struct.usr_channels]
- movzx edx,byte[edi+png_struct.usr_bit_depth]
- imul eax,edx
- PNG_ROWBYTES eax, [edi+png_struct.width]
- inc eax
- push edi
- mov ecx,eax
- xor eax,eax
- mov edi,[edi+png_struct.prev_row]
- rep stosb ;memset(...
- pop edi
- jmp .end_f
- .end0:
-end if
-
- ; If we get here, we've just written the last row, so we need
- ; to flush the compressor
- stdcall png_compress_IDAT, 0, 0, Z_FINISH
-.end_f:
- ret
-endp
-
-; Pick out the correct pixels for the interlace pass.
-; The basic idea here is to go through the row with a source
-; pointer and a destination pointer (sp and dp), and copy the
-; correct pixels for the pass. As the row gets compacted,
-; sp will always be >= dp, so we should never overwrite anything.
-; See the default: case for the easiest code to understand.
-
-;void (png_row_infop row_info, bytep row, int pass)
-align 4
-proc png_do_write_interlace, row_info:dword, row:dword, pass:dword
- png_debug 1, 'in png_do_write_interlace'
-
- ; We don't have to do anything on the last pass (6)
- cmp dword[pass],6
- jge .end_f ;if (..<..)
- ; Each pixel depth is handled separately
-; switch (row_info->pixel_depth)
-; {
-; case 1:
-; {
-; bytep sp;
-; bytep dp;
-; unsigned int shift;
-; int d;
-; int value;
-; uint_32 i;
-; uint_32 row_width = row_info->width;
-
-; dp = row;
-; d = 0;
-; shift = 7;
-
-; for (i = png_pass_start[pass]; i < row_width;
-; i += png_pass_inc[pass])
-; {
-; sp = row + (png_size_t)(i >> 3);
-; value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01;
-; d |= (value << shift);
-
-; if (shift == 0)
-; {
-; shift = 7;
-; *dp++ = (byte)d;
-; d = 0;
-; }
-
-; else
-; shift--;
-
-; }
-; if (shift != 7)
-; *dp = (byte)d;
-
-; break;
-; }
-
-; case 2:
-; {
-; bytep sp;
-; bytep dp;
-; unsigned int shift;
-; int d;
-; int value;
-; uint_32 i;
-; uint_32 row_width = row_info->width;
-
-; dp = row;
-; shift = 6;
-; d = 0;
-
-; for (i = png_pass_start[pass]; i < row_width;
-; i += png_pass_inc[pass])
-; {
-; sp = row + (png_size_t)(i >> 2);
-; value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03;
-; d |= (value << shift);
-
-; if (shift == 0)
-; {
-; shift = 6;
-; *dp++ = (byte)d;
-; d = 0;
-; }
-
-; else
-; shift -= 2;
-; }
-; if (shift != 6)
-; *dp = (byte)d;
-
-; break;
-; }
-
-; case 4:
-; {
-; bytep sp;
-; bytep dp;
-; unsigned int shift;
-; int d;
-; int value;
-; uint_32 i;
-; uint_32 row_width = row_info->width;
-
-; dp = row;
-; shift = 4;
-; d = 0;
-; for (i = png_pass_start[pass]; i < row_width;
-; i += png_pass_inc[pass])
-; {
-; sp = row + (png_size_t)(i >> 1);
-; value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f;
-; d |= (value << shift);
-
-; if (shift == 0)
-; {
-; shift = 4;
-; *dp++ = (byte)d;
-; d = 0;
-; }
-
-; else
-; shift -= 4;
-; }
-; if (shift != 4)
-; *dp = (byte)d;
-
-; break;
-; }
-
-; default:
-; {
-; bytep sp;
-; bytep dp;
-; uint_32 i;
-; uint_32 row_width = row_info->width;
-; png_size_t pixel_bytes;
-
- ; Start at the beginning
-; dp = row;
-
- ; Find out how many bytes each pixel takes up
-; pixel_bytes = (row_info->pixel_depth >> 3);
-
- ; Loop through the row, only looking at the pixels that matter
-; for (i = png_pass_start[pass]; i < row_width;
-; i += png_pass_inc[pass])
-; {
- ; Find out where the original pixel is
-; sp = row + (png_size_t)i * pixel_bytes;
-
- ; Move the pixel
-; if (dp != sp)
-; memcpy(dp, sp, pixel_bytes);
-
- ; Next pixel
-; dp += pixel_bytes;
-; }
-; break;
-; }
-; }
- ; Set new row width
-; row_info->width = (row_info->width +
-; png_pass_inc[pass] - 1 -
-; png_pass_start[pass]) /
-; png_pass_inc[pass];
-
-; row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
-; row_info->width);
-.end_f:
- ret
-endp
-
-; This filters the row, chooses which filter to use, if it has not already
-; been specified by the application, and then writes the row out with the
-; chosen filter.
-
-;void png_write_filtered_row(png_structrp png_ptr, bytep filtered_row,
-; png_size_t row_bytes);
-
-;png_size_t (png_structrp png_ptr, const uint_32 bpp, const png_size_t row_bytes, const png_size_t lmins)
-align 4
-proc png_setup_sub_row uses ebx ecx edx edi esi, png_ptr:dword, bpp:dword, row_bytes:dword, lmins:dword
- mov ebx,[png_ptr]
- mov edi,[ebx+png_struct.try_row]
- mov byte[edi],PNG_FILTER_VALUE_SUB
-
- mov ecx,[bpp]
- inc edi
- mov esi,[ebx+png_struct.row_buf]
- inc esi
- xor eax,eax
- xor edx,edx
- .cycle0:
- lodsb
- stosb
- png_setup_abs edx
- loop .cycle0
-
- mov ecx,[row_bytes]
- sub ecx,[bpp]
- mov ebx,[ebx+png_struct.row_buf]
- inc ebx
- .cycle1:
- lodsb
- sub al,byte[ebx]
- stosb
- png_setup_abs edx
- cmp edx,[lmins]
- jg .cycle1end ;if (..>..) ;We are already worse, don't continue.
- inc ebx
- loop .cycle1
- .cycle1end:
- mov eax,edx
- ret
-endp
-
-;void (png_structrp png_ptr, const uint_32 bpp, const png_size_t row_bytes)
-align 4
-proc png_setup_sub_row_only, png_ptr:dword, bpp:dword, row_bytes:dword
-pushad
- mov ebx,[png_ptr]
- mov edi,[ebx+png_struct.try_row]
- mov byte[edi],PNG_FILTER_VALUE_SUB
-
- mov ecx,[bpp]
- inc edi
- mov esi,[ebx+png_struct.row_buf]
- inc esi
- rep movsb
-
- mov ecx,[row_bytes]
- sub ecx,[bpp]
- mov edx,[ebx+png_struct.row_buf]
- inc edx
-align 4
- .cycle0:
- lodsb
- sub al,byte[edx]
- stosb
- inc edx
- loop .cycle0
-popad
- ret
-endp
-
-;png_size_t (png_structrp png_ptr, const png_size_t row_bytes, const png_size_t lmins)
-align 4
-proc png_setup_up_row uses ebx ecx edx edi esi, png_ptr:dword, row_bytes:dword, lmins:dword
- mov ebx,[png_ptr]
- mov edi,[ebx+png_struct.try_row]
- mov byte[edi],PNG_FILTER_VALUE_UP
-
- mov ecx,[row_bytes]
- inc edi
- mov esi,[ebx+png_struct.row_buf]
- inc esi
- mov ebx,[ebx+png_struct.prev_row]
- inc ebx
- xor edx,edx
- .cycle0:
- lodsb
- sub al,byte[ebx]
- stosb
- png_setup_abs edx
- cmp edx,[lmins]
- jg .cycle0end ;if (..>..) ;We are already worse, don't continue.
- inc ebx
- loop .cycle0
- .cycle0end:
- mov eax,edx
- ret
-endp
-
-;void (png_structrp png_ptr, const png_size_t row_bytes)
-align 4
-proc png_setup_up_row_only, png_ptr:dword, row_bytes:dword
-pushad
- mov ebx,[png_ptr]
- mov edi,[ebx+png_struct.try_row]
- mov byte[edi],PNG_FILTER_VALUE_UP
-
- mov ecx,[row_bytes]
- inc edi
- mov esi,[ebx+png_struct.row_buf]
- inc esi
- mov ebx,[ebx+png_struct.prev_row]
- inc ebx
- .cycle0:
- lodsb
- sub al,byte[ebx]
- stosb
- inc ebx
- loop .cycle0
-popad
- ret
-endp
-
-;png_size_t (png_structrp png_ptr, const uint_32 bpp, const png_size_t row_bytes, const png_size_t lmins)
-align 4
-proc png_setup_avg_row uses ebx ecx edx edi esi, png_ptr:dword, bpp:dword, row_bytes:dword, lmins:dword
-locals
- sum dd 0 ;png_size_t
-endl
- mov ebx,[png_ptr]
- mov edi,[ebx+png_struct.try_row]
- mov byte[edi],PNG_FILTER_VALUE_AVG
-
- mov ecx,[bpp]
- inc edi
- mov esi,[ebx+png_struct.row_buf]
- inc esi
- mov ebx,[ebx+png_struct.prev_row]
- inc ebx
- .cycle0:
- lodsb
- mov ah,byte[ebx]
- shr ah,1
- sub al,ah
- stosb
- png_setup_abs dword[sum]
- inc ebx
- loop .cycle0
-
- mov ecx,[row_bytes]
- sub ecx,[bpp]
- mov eax,[png_ptr]
- mov edx,[eax+png_struct.row_buf]
- inc edx
- .cycle1:
- lodsb
- shl eax,24
- movzx ax,byte[ebx]
- add al,byte[edx]
- jnc @f
- mov ah,1
- @@:
- shr ax,1
- rol eax,8
- sub al,ah
- stosb
- png_setup_abs dword[sum]
- mov eax,[sum]
- cmp eax,[lmins]
- jg .cycle1end ;if (..>..) ;We are already worse, don't continue.
- inc ebx
- inc edx
- loop .cycle1
- .cycle1end:
- mov eax,[sum]
- ret
-endp
-
-;void (png_structrp png_ptr, const uint_32 bpp, const png_size_t row_bytes)
-align 4
-proc png_setup_avg_row_only, png_ptr:dword, bpp:dword, row_bytes:dword
-pushad
- mov ebx,[png_ptr]
- mov edi,[ebx+png_struct.try_row]
- mov byte[edi],PNG_FILTER_VALUE_AVG
-
- mov ecx,[bpp]
- inc edi
- mov esi,[ebx+png_struct.row_buf]
- inc esi
- mov ebx,[ebx+png_struct.prev_row]
- inc ebx
- .cycle0:
- lodsb
- mov ah,byte[ebx]
- shr ah,1
- sub al,ah
- stosb
- inc ebx
- loop .cycle0
-
- mov ecx,[row_bytes]
- sub ecx,[bpp]
- mov eax,[png_ptr]
- mov edx,[eax+png_struct.row_buf]
- inc edx
- .cycle1:
- lodsb
- mov ah,byte[ebx]
- shr ah,1
- sub al,ah
- mov ah,byte[edx]
- shr ah,1
- sub al,ah
- stosb
- inc ebx
- inc edx
- loop .cycle1
-popad
- ret
-endp
-
-;png_size_t (png_structrp png_ptr, const uint_32 bpp,
-; const png_size_t row_bytes, const png_size_t lmins)
-align 4
-proc png_setup_paeth_row uses ebx ecx edx edi esi, png_ptr:dword, bpp:dword, row_bytes:dword, lmins:dword
-locals
- pp dd ?
- sum dd ?
- v dd ?
- lp dd ?
- cp dd ?
- a dd ?
- b dd ?
- c dd ?
- p dd ?
- pa dd ?
- pb dd ?
- pc dd ?
-endl
- ;ecx - i
- ;edi - dp
- ;esi - rp
- mov dword[sum],0
- mov ebx,[png_ptr]
- mov eax,[ebx+png_struct.try_row]
- mov byte[eax],PNG_FILTER_VALUE_PAETH
- xor ecx,ecx
- mov esi,[ebx+png_struct.row_buf]
- inc esi
- mov edi,[ebx+png_struct.try_row]
- inc edi
- mov eax,[ebx+png_struct.prev_row]
- inc eax
- mov [pp],eax
- jmp @f
-
-align 4
-.cycle0:
- inc ecx
- @@:
- cmp ecx,[bpp]
- jae .cycle0end
- lodsb
- mov edx,[pp]
- movzx edx,byte[edx]
- sub al,dl
- stosb
- and eax,0xff
- mov [v],eax
- inc dword[pp]
- cmp eax,0x80
- jge @f
- add [sum],eax
- jmp .cycle0
- @@:
- mov eax,0x100
- sub eax,[v]
- add [sum],eax
- jmp .cycle0
-.cycle0end:
-
- mov eax,[ebx+png_struct.row_buf]
- inc eax
- mov [lp],eax
- mov eax,[ebx+png_struct.prev_row]
- inc eax
- mov [cp],eax
- jmp @f
-
-align 4
-.cycle1:
- inc ecx
- @@:
- cmp ecx,[row_bytes]
- jae .cycle1end
- mov eax,[pp]
- movzx ebx,byte[eax]
- mov [b],ebx
- inc dword[pp]
- mov eax,[cp]
- movzx ebx,byte[eax]
- mov [c],ebx
- inc dword[cp]
- mov eax,[lp]
- movzx ebx,byte[eax]
- mov [a],ebx
- inc dword[lp]
- mov eax,[b]
- sub eax,[c]
- mov [p],eax
- mov ebx,[a]
- sub ebx,[c]
- mov [pc],ebx
- mov eax,[p]
- cmp eax,0
- jge @f
- neg eax
- @@:
- mov [pa],eax
- mov eax,[pc]
- cmp eax,0
- jge @f
- neg eax
- @@:
- mov [pb],eax
- mov eax,[p]
- add eax,[pc]
- jns @f
- neg eax
- @@:
- mov [pc],eax
- mov eax,[pa]
- cmp eax,[pb]
- jg .end0
- cmp eax,[pc]
- jg .end0
- mov eax,[a]
- jmp .end1
- .end0:
- mov eax,[pb]
- cmp eax,[pc]
- jg .end2
- mov eax,[b]
- jmp .end1
- .end2:
- mov eax,[c]
- .end1:
- mov [p],eax
- movzx eax,byte[esi]
- sub eax,[p]
- and eax,0xff
- stosb
- mov [v],eax
- inc esi
- cmp dword[v],0x80
- jge .end3
- mov eax,[v]
- add [sum],eax
- jmp .end4
- .end3:
- mov eax,0x100
- sub eax,[v]
- add [sum],eax
- .end4:
- mov eax,[sum]
- cmp eax,[lmins] ;We are already worse, don't continue.
- jbe .cycle1
-.cycle1end:
- mov eax,[sum]
- ret
-endp
-
-;void (png_structrp png_ptr, const uint_32 bpp, const png_size_t row_bytes)
-align 4
-proc png_setup_paeth_row_only, png_ptr:dword, bpp:dword, row_bytes:dword
-locals
- pp dd ?
- lp dd ?
- cp dd ?
- a dd ?
- b dd ?
- c dd ?
- p dd ?
- pa dd ?
- pb dd ?
- pc dd ?
-endl
-pushad
- ;ecx - i
- ;edi - dp
- ;esi - rp
- mov eax,[png_ptr]
- mov ebx,[eax+png_struct.try_row]
- mov byte[ebx],4
- xor ecx,ecx
- mov edx,[png_ptr]
- mov eax,[edx+png_struct.row_buf]
- inc eax
- mov esi,eax
- mov ebx,[png_ptr]
- mov edx,[ebx+png_struct.try_row]
- inc edx
- mov edi,edx
- mov eax,[png_ptr]
- mov ebx,[eax+png_struct.prev_row]
- inc ebx
- mov [pp],ebx
- jmp @f
-
-align 4
-.cycle0:
- inc ecx
- @@:
- cmp ecx,[bpp]
- jae .cycle0end
- lodsb
- mov ebx,[pp]
- movzx ebx,byte[ebx]
- sub al,bl
- stosb
- inc dword[pp]
- jmp .cycle0
-.cycle0end:
-
- mov eax,[png_ptr]
- mov ebx,[eax+png_struct.row_buf]
- inc ebx
- mov [lp],ebx
- mov edx,[png_ptr]
- mov eax,[edx+png_struct.prev_row]
- inc eax
- mov [cp],eax
- jmp @f
-
-align 4
-.cycle1:
- inc ecx
- @@:
- cmp ecx,[row_bytes]
- jae .cycle1end
- mov eax,[pp]
- movzx ebx,byte[eax]
- mov [b],ebx
- inc dword[pp]
- mov eax,[cp]
- movzx ebx,byte[eax]
- mov [c],ebx
- inc dword[cp]
- mov eax,[lp]
- movzx ebx,byte[eax]
- mov [a],ebx
- inc dword[lp]
- mov eax,[b]
- sub eax,[c]
- mov [p],eax
- mov ebx,[a]
- sub ebx,[c]
- mov [pc],ebx
- mov eax,[p]
- cmp eax,0
- jge @f
- neg eax
- @@:
- mov [pa],eax
- mov eax,[pc]
- cmp eax,0
- jge @f
- neg eax
- @@:
- mov [pb],eax
- mov eax,[p]
- add eax,[pc]
- jns @f
- neg eax
- @@:
- mov [pc],eax
- mov eax,[pa]
- cmp eax,[pb]
- jg .end0
- cmp eax,[pc]
- jg .end0
- mov eax,[a]
- jmp .end1
- .end0:
- mov eax,[pb]
- cmp eax,[pc]
- jg .end2
- mov eax,[b]
- jmp .end1
- .end2:
- mov eax,[c]
- .end1:
- mov [p],eax
- movzx eax,byte[esi]
- sub eax,[p]
- and eax,0xff
- stosb
- inc esi
- jmp .cycle1
-.cycle1end:
-popad
- ret
-endp
-
-;void (png_structrp png_ptr, png_row_infop row_info)
-align 4
-proc png_write_find_filter, png_ptr:dword, row_info:dword
-locals
- filter_to_do dd ? ;unsigned int ;= png_ptr->do_filter
- row_buf dd ? ;bytep
- best_row dd ? ;bytep
- bpp dd ? ;uint_32
- mins dd ? ;png_size_t
- row_bytes dd ? ;png_size_t ;= row_info->rowbytes
-endl
-pushad
- mov edi,[png_ptr]
-if PNG_WRITE_FILTER_SUPPORTED eq 0
- mov eax,[edi+png_struct.rowbytes]
- inc eax
- stdcall png_write_filtered_row, edi, [edi+png_struct.row_buf], eax
-else
- mov esi,[row_info]
- movzx eax,byte[edi+png_struct.do_filter]
- mov [filter_to_do],eax
- mov eax,[esi+png_row_info.rowbytes]
- mov [row_bytes],eax
-
- png_debug 1, 'in png_write_find_filter'
-
- ; Find out how many bytes offset each pixel is
- movzx eax,byte[edi+png_struct.pixel_depth]
- add eax,7
- shr eax,3
- mov [bpp],eax
-
- mov eax,[edi+png_struct.row_buf]
- mov [row_buf],eax
- mov dword[mins], PNG_SIZE_MAX - 256 ;so we can detect potential overflow of the
- ;running sum
-
-; The prediction method we use is to find which method provides the
-; smallest value when summing the absolute values of the distances
-; from zero, using anything >= 128 as negative numbers. This is known
-; as the "minimum sum of absolute differences" heuristic. Other
-; heuristics are the "weighted minimum sum of absolute differences"
-; (experimental and can in theory improve compression), and the "zlib
-; predictive" method (not implemented yet), which does test compressions
-; of lines using different filter methods, and then chooses the
-; (series of) filter(s) that give minimum compressed data size (VERY
-; computationally expensive).
-
-; GRR 980525: consider also
-
-; (1) minimum sum of absolute differences from running average (i.e.,
-; keep running sum of non-absolute differences & count of bytes)
-; [track dispersion, too? restart average if dispersion too large?]
-
-; (1b) minimum sum of absolute differences from sliding average, probably
-; with window size <= deflate window (usually 32K)
-
-; (2) minimum sum of squared differences from zero or running average
-; (i.e., ~ root-mean-square approach)
-
-
-
-; We don't need to test the 'no filter' case if this is the only filter
-; that has been chosen, as it doesn't actually do anything to the data.
-
- mov eax,[edi+png_struct.row_buf]
- mov [best_row],eax
-
- cmp dword[row_bytes],PNG_SIZE_MAX/128
- jl @f ;if (..>=..)
- ; Overflow can occur in the calculation, just select the lowest set
- ; filter.
-
- xor eax,eax
- sub eax,[filter_to_do]
- and [filter_to_do],eax
- jmp .end0
- @@:
- mov eax,[filter_to_do]
- and eax,PNG_FILTER_NONE
- jz .end0
- cmp dword[filter_to_do],PNG_FILTER_NONE
- je .end0 ;else if (..!=0 && ..!=..)
- ; Overflow not possible and multiple filters in the list, including the
- ; 'none' filter.
-
- push esi
- xor eax,eax
- xor ebx,ebx
- mov ecx,[row_bytes]
- mov esi,[row_buf]
- .cycle0:
- lodsb
- png_setup_abs ebx
- loop .cycle0
- pop esi
- mov [mins],ebx
- .end0:
-
- ; Sub filter
- mov eax,[filter_to_do]
- cmp eax,PNG_FILTER_SUB
- jne @f ;if (..==..)
- ; It's the only filter so no testing is needed
- stdcall png_setup_sub_row_only, edi, [bpp], [row_bytes]
- mov eax,[edi+png_struct.try_row]
- mov [best_row],eax
- jmp .end1
- @@:
- and eax,PNG_FILTER_SUB
- jz .end1 ;else if (..!=0)
- stdcall png_setup_sub_row, edi, [bpp], [row_bytes], [mins]
- cmp eax,[mins]
- jge .end1 ;if (..<..)
- mov [mins],eax
- mov eax,[edi+png_struct.try_row]
- mov [best_row],eax
- test eax,eax
- jz .end1 ;if (..!=0)
- mov eax,[edi+png_struct.tst_row]
- mov [edi+png_struct.try_row],eax
- mov eax,[best_row]
- mov [edi+png_struct.tst_row],eax
- .end1:
-
- ; Up filter
- mov eax,[filter_to_do]
- cmp eax,PNG_FILTER_UP
- jne @f ;if (..==..)
- ; It's the only filter so no testing is needed
- stdcall png_setup_up_row_only, edi, [row_bytes]
- mov eax,[edi+png_struct.try_row]
- mov [best_row],eax
- jmp .end2
- @@:
- and eax,PNG_FILTER_UP
- jz .end2 ;else if (..!=0)
- stdcall png_setup_up_row, edi, [row_bytes], [mins]
- cmp eax,[mins]
- jge .end2 ;if (..<..)
- mov [mins],eax
- mov eax,[edi+png_struct.try_row]
- mov [best_row],eax
- test eax,eax
- jz .end2 ;if (..!=0)
- mov eax,[edi+png_struct.tst_row]
- mov [edi+png_struct.try_row],eax
- mov eax,[best_row]
- mov [edi+png_struct.tst_row],eax
- .end2:
-
- ; Avg filter
- mov eax,[filter_to_do]
- cmp eax,PNG_FILTER_AVG
- jne @f ;if (..==..)
- ; It's the only filter so no testing is needed
- stdcall png_setup_avg_row_only, edi, [bpp], [row_bytes]
- mov eax,[edi+png_struct.try_row]
- mov [best_row],eax
- jmp .end3
- @@:
- and eax,PNG_FILTER_AVG
- jz .end3 ;else if (..!=0)
- stdcall png_setup_avg_row, edi, [bpp], [row_bytes], [mins]
- cmp eax,[mins]
- jge .end3 ;if (..<..)
- mov [mins],eax
- mov eax,[edi+png_struct.try_row]
- mov [best_row],eax
- test eax,eax
- jz .end3 ;if (..!=0)
- mov eax,[edi+png_struct.tst_row]
- mov [edi+png_struct.try_row],eax
- mov eax,[best_row]
- mov [edi+png_struct.tst_row],eax
- .end3:
-
- ; Paeth filter
- mov eax,[filter_to_do]
- cmp eax,PNG_FILTER_PAETH
- jne @f ;if (..==..)
- ; It's the only filter so no testing is needed
- stdcall png_setup_paeth_row_only, edi, [bpp], [row_bytes]
- mov eax,[edi+png_struct.try_row]
- mov [best_row],eax
- jmp .end4
- @@:
- and eax,PNG_FILTER_PAETH
- jz .end4 ;else if (..!=0)
- stdcall png_setup_paeth_row, edi, [bpp], [row_bytes], [mins]
- cmp eax,[mins]
- jge .end4 ;if (..<..)
- mov [mins],eax
- mov eax,[edi+png_struct.try_row]
- mov [best_row],eax
- test eax,eax
- jz .end4 ;if (..!=0)
- mov eax,[edi+png_struct.tst_row]
- mov [edi+png_struct.try_row],eax
- mov eax,[best_row]
- mov [edi+png_struct.tst_row],eax
- .end4:
-
- ; Do the actual writing of the filtered row data from the chosen filter.
- mov eax,[esi+png_row_info.rowbytes]
- inc eax
- stdcall png_write_filtered_row, edi, [best_row], eax
-end if ;WRITE_FILTER
-popad
- ret
-endp
-
-
-; Do the actual writing of a previously filtered row.
-;void (png_structrp png_ptr, bytep filtered_row,
-; png_size_t full_row_length/*includes filter byte*/)
-align 4
-proc png_write_filtered_row uses eax ebx edi, png_ptr:dword, filtered_row:dword, full_row_length:dword
- png_debug 1, 'in png_write_filtered_row'
-
- mov eax,[filtered_row]
- movzx eax,byte[eax]
- png_debug1 2, 'filter = %d', eax
-
- mov edi,[png_ptr]
- stdcall png_compress_IDAT, [filtered_row], [full_row_length], Z_NO_FLUSH
-
-if PNG_WRITE_FILTER_SUPPORTED eq 1
- ; Swap the current and previous rows
- mov eax,[edi+png_struct.prev_row]
- test eax,eax
- jz @f ;if (..!=0)
- ;eax = tptr
- mov ebx,[edi+png_struct.row_buf]
- mov [edi+png_struct.prev_row],ebx
- mov [edi+png_struct.row_buf],eax
- @@:
-end if ;WRITE_FILTER
-
- ; Finish row - updates counters and flushes zlib if last row
- stdcall png_write_finish_row, edi
-
-if PNG_WRITE_FLUSH_SUPPORTED eq 1
- inc dword[edi+png_struct.flush_rows]
-
- mov eax,[edi+png_struct.flush_dist]
- cmp eax,0
- jle @f
- cmp [edi+png_struct.flush_rows],eax
- jl @f ;if (..>0 && ..>=..)
- stdcall png_write_flush, edi
- @@:
-end if ;WRITE_FLUSH
- ret
-endp
+
+; pngwutil.asm - utilities to write a PNG file
+
+; Last changed in libpng 1.6.24 [August 4, 2016]
+; Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
+; (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+; (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+
+; This code is released under the libpng license.
+; For conditions of distribution and use, see the disclaimer
+; and license in png.inc
+
+; Place a 32-bit number into a buffer in PNG byte order. We work
+; with unsigned numbers for convenience, although one supported
+; ancillary chunk uses signed (two's complement) numbers.
+
+;void (bytep buf, uint_32 i)
+align 4
+proc png_save_uint_32 uses eax edi, buf:dword, i:dword
+ mov eax,[i]
+ bswap eax
+ mov edi,[buf]
+ stosd
+ ret
+endp
+
+; Place a 16-bit number into a buffer in PNG byte order.
+; The parameter is declared unsigned int, not uint_16,
+; just to avoid potential problems on pre-ANSI C compilers.
+
+;void (bytep buf, unsigned int i)
+align 4
+proc png_save_uint_16 uses eax edi, buf:dword, i:dword
+ mov eax,[i]
+ ror eax,16
+ bswap eax
+ mov edi,[buf]
+ stosw
+ ret
+endp
+
+; Simple function to write the signature. If we have already written
+; the magic bytes of the signature, or more likely, the PNG stream is
+; being embedded into another stream and doesn't need its own signature,
+; we should call png_set_sig_bytes() to tell libpng how many of the
+; bytes have already been written.
+
+align 4
+png_signature db 137, 80, 78, 71, 13, 10, 26, 10
+
+;void (png_structrp png_ptr)
+align 4
+proc png_write_sig uses eax ebx edi, png_ptr:dword
+if PNG_IO_STATE_SUPPORTED eq 1
+ ; Inform the I/O callback that the signature is being written
+ mov edi,[png_ptr]
+ mov dword[edi+png_struct.io_state], PNG_IO_WRITING or PNG_IO_SIGNATURE
+end if
+
+ ; Write the rest of the 8 byte signature
+ movzx eax,byte[edi+png_struct.sig_bytes]
+ mov ebx,8
+ sub ebx,eax
+ add eax,png_signature
+ stdcall png_write_data, edi, eax, ebx
+
+ cmp byte[edi+png_struct.sig_bytes], 3 ;if(..<3)
+ jge @f
+ or dword[edi+png_struct.mode], PNG_HAVE_PNG_SIGNATURE
+ @@:
+ ret
+endp
+
+; Write the start of a PNG chunk. The type is the chunk type.
+; The total_length is the sum of the lengths of all the data you will be
+; passing in png_write_chunk_data().
+
+;void (png_structrp png_ptr, uint_32 chunk_name, uint_32 length)
+align 4
+proc png_write_chunk_header uses ebx edi, png_ptr:dword, chunk_name:dword, length:dword
+locals
+ buf rb 8 ;ebp-8
+endl
+
+if (PNG_DEBUG eq 1) & (PNG_DEBUG > 0)
+; PNG_CSTRING_FROM_CHUNK(buf, chunk_name);
+; png_debug2(0, "Writing %s chunk, length = %lu", buf, (unsigned long)length);
+end if
+
+ mov edi,[png_ptr]
+ test edi,edi
+ jz .end_f ;if (..==0) return
+
+if PNG_IO_STATE_SUPPORTED eq 1
+ ; Inform the I/O callback that the chunk header is being written.
+ ; PNG_IO_CHUNK_HDR requires a single I/O call.
+
+ mov dword[edi+png_struct.io_state], PNG_IO_WRITING or PNG_IO_CHUNK_HDR
+end if
+
+ ; Write the length and the chunk name
+ lea ebx,[ebp-8]
+ stdcall png_save_uint_32, ebx, [length]
+ m2m dword[ebx+4],dword[chunk_name]
+ stdcall png_write_data, edi, ebx, 8
+
+ ; Put the chunk name into png_ptr->chunk_name
+ m2m dword[edi+png_struct.chunk_name],dword[chunk_name]
+
+ ; Reset the crc and run it over the chunk name
+ stdcall png_reset_crc, edi
+ lea ebx,[ebp-4] ;buf + 4
+ stdcall png_calculate_crc, edi, ebx, 4
+
+if PNG_IO_STATE_SUPPORTED eq 1
+ ; Inform the I/O callback that chunk data will (possibly) be written.
+ ; PNG_IO_CHUNK_DATA does NOT require a specific number of I/O calls.
+
+ mov dword[edi+png_struct.io_state], PNG_IO_WRITING or PNG_IO_CHUNK_DATA
+end if
+.end_f:
+ ret
+endp
+
+;void (png_structrp png_ptr, bytep chunk_string, uint_32 length)
+align 4
+proc png_write_chunk_start uses eax, png_ptr:dword, chunk_string:dword, length:dword
+ mov eax,[chunk_string]
+ stdcall png_write_chunk_header, [png_ptr], [eax], [length]
+ ret
+endp
+
+; Write the data of a PNG chunk started with png_write_chunk_header().
+; Note that multiple calls to this function are allowed, and that the
+; sum of the lengths from these calls *must* add up to the total_length
+; given to png_write_chunk_header().
+
+;void (png_structrp png_ptr, bytep data, png_size_t length)
+align 4
+proc png_write_chunk_data uses edi, png_ptr:dword, p2data:dword, length:dword
+ ; Write the data, and run the CRC over it
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f ;if (..==0) return
+
+ cmp dword[p2data],0
+ je .end_f
+ cmp dword[length],0
+ jle .end_f ;if (..!=0 && ..>0)
+ stdcall png_write_data, edi, [p2data], [length]
+ ; Update the CRC after writing the data,
+ ; in case the user I/O routine alters it.
+ stdcall png_calculate_crc, edi, [p2data], [length]
+.end_f:
+ ret
+endp
+
+; Finish a chunk started with png_write_chunk_header().
+;void (png_structrp png_ptr)
+align 4
+proc png_write_chunk_end uses ebx edi, png_ptr:dword
+locals
+ buf rb 4 ;ebp-4
+endl
+ mov edi,[png_ptr]
+ cmp edi,0
+ je .end_f ;if (..==0) return
+
+if PNG_IO_STATE_SUPPORTED eq 1
+ ; Inform the I/O callback that the chunk CRC is being written.
+ ; PNG_IO_CHUNK_CRC requires a single I/O function call.
+
+ mov dword[edi+png_struct.io_state], PNG_IO_WRITING or PNG_IO_CHUNK_CRC
+end if
+
+ ; Write the crc in a single operation
+ lea ebx,[ebp-4]
+ stdcall png_save_uint_32, ebx, [edi+png_struct.crc]
+
+ stdcall png_write_data, edi, ebx, 4
+.end_f:
+ ret
+endp
+
+; Write a PNG chunk all at once. The type is an array of ASCII characters
+; representing the chunk name. The array must be at least 4 bytes in
+; length, and does not need to be null terminated. To be safe, pass the
+; pre-defined chunk names here, and if you need a new one, define it
+; where the others are defined. The length is the length of the data.
+; All the data must be present. If that is not possible, use the
+; png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end()
+; functions instead.
+
+;void (png_structrp png_ptr, uint_32 chunk_name, bytep data, png_size_t length)
+align 4
+proc png_write_complete_chunk uses edi, png_ptr:dword, chunk_name:dword, p3data:dword, length:dword
+ mov edi,[png_ptr]
+ test edi,edi
+ jz .end_f ;if (..==0) return
+
+ ; On 64-bit architectures 'length' may not fit in a uint_32.
+ cmp dword[length],PNG_UINT_31_MAX ;if(..>..)
+ jle @f
+ png_error edi, 'length exceeds PNG maximum'
+ @@:
+ stdcall png_write_chunk_header, edi, [chunk_name], [length]
+ stdcall png_write_chunk_data, edi, [p3data], [length]
+ stdcall png_write_chunk_end, edi
+.end_f:
+ ret
+endp
+
+; This is the API that calls the internal function above.
+;void (png_structrp png_ptr, bytep chunk_string, bytep data, png_size_t length)
+align 4
+proc png_write_chunk, png_ptr:dword, chunk_string:dword, p3data:dword, length:dword
+ stdcall png_write_complete_chunk, [png_ptr], [chunk_string], [p3data], [length]
+ ret
+endp
+
+; This is used below to find the size of an image to pass to png_deflate_claim,
+; so it only needs to be accurate if the size is less than 16384 bytes (the
+; point at which a lower LZ window size can be used.)
+
+;png_alloc_size_t (png_structrp png_ptr)
+align 4
+proc png_image_size uses ebx ecx edx edi esi, png_ptr:dword
+; Only return sizes up to the maximum of a uint_32; do this by limiting
+; the width and height used to 15 bits.
+
+ mov edi,[png_ptr]
+ mov ebx,[edi+png_struct.height]
+
+ cmp dword[edi+png_struct.rowbytes],32768
+ jge .end0
+ cmp ebx,32768
+ jge .end0 ;if (..<.. && ..<..)
+ cmp byte[edi+png_struct.interlaced],0
+ je .end1 ;if (..!=0)
+ ; Interlacing makes the image larger because of the replication of
+ ; both the filter byte and the padding to a byte boundary.
+
+ xor esi,esi
+ xor ecx,ecx
+ .cycle0:
+ PNG_PASS_COLS [edi+png_struct.width], ecx
+ ;eax = pw
+
+ cmp eax,0
+ jle @f ;if (..>0)
+ mov edx,eax
+ movzx eax,byte[edi+png_struct.pixel_depth]
+ PNG_ROWBYTES eax, edx
+ inc eax
+ mov edx,eax
+ PNG_PASS_ROWS ebx, ecx
+ imul eax,edx
+ add esi,eax
+ @@:
+ inc ecx
+ cmp ecx,6
+ jle .cycle0
+
+ mov eax,esi
+ jmp .end_f
+ .end1: ;else
+ mov eax,[edi+png_struct.rowbytes]
+ inc eax
+ imul eax,ebx
+ jmp .end_f
+ .end0: ;else
+ mov eax,0xffffffff
+.end_f:
+ ret
+endp
+
+; This is the code to hack the first two bytes of the deflate stream (the
+; deflate header) to correct the windowBits value to match the actual data
+; size. Note that the second argument is the *uncompressed* size but the
+; first argument is the *compressed* data (and it must be deflate
+; compressed.)
+
+;void (bytep data, png_alloc_size_t data_size)
+align 4
+proc optimize_cmf, p1data:dword, data_size:dword
+; Optimize the CMF field in the zlib stream. The resultant zlib stream is
+; still compliant to the stream specification.
+ png_debug 1, 'optimize_cmf'
+pushad
+ cmp dword[data_size],16384
+ jg .end_f ;if (..<=..) ;else windowBits must be 15
+ mov esi,[p1data]
+ movzx ebx,byte[esi]
+ ;ebx = z_cmf ;zlib compression method and flags
+
+ mov eax,ebx
+ and eax,0x0f
+ cmp eax,8
+ jne .end_f
+ mov eax,ebx
+ and eax,0xf0
+ cmp eax,0x70
+ jg .end_f ;if (..==.. && ..<=..)
+ ;ecx = z_cinfo
+ ;edi = half_z_window_size
+
+ mov ecx,ebx
+ shr ecx,4
+ xor edi,edi
+ inc edi
+ shl edi,7
+ shl edi,cl
+
+ cmp [data_size],edi
+ jg .end_f ;if (..<=..) ;else no change
+ .cycle0: ;do
+ shr edi,1
+ dec ecx
+ cmp ecx,0
+ jle @f
+ cmp [data_size],edi
+ jle .cycle0
+ @@: ;while (..>0 && ..<=..);
+
+ and ebx,0x0f
+ mov eax,ecx
+ shl eax,4
+ or ebx,eax
+
+ mov byte[esi],bl
+ movzx eax,byte[esi+1]
+ and eax,0xe0
+ shl ebx,8
+ add ebx,eax
+ add eax,0x1f
+ xchg eax,ebx
+ xor edx,edx
+ mov ecx,0x1f
+ div ecx
+ sub ebx,edx
+ mov byte[esi+1],bl
+.end_f:
+popad
+ ret
+endp
+
+; Initialize the compressor for the appropriate type of compression.
+;int (png_structrp png_ptr, uint_32 owner, png_alloc_size_t data_size)
+;input:
+; edi - png_ptr
+align 4
+proc png_deflate_claim uses ebx ecx, owner:dword, data_size:dword
+locals
+ level dd ? ;int
+ method dd ? ;int
+ windowBits dd ? ;int
+ memLevel dd ? ;int
+ strategy dd ? ;int
+ msg rb 64 ;char[64]
+endl
+ png_debug 1, 'in png_deflate_claim'
+
+ cmp dword[edi+png_struct.zowner],0
+ je .end0 ;if (..!=0)
+ mov ebx,ebp
+ sub ebx,64
+if (PNG_WARNINGS_SUPPORTED eq 1) | (PNG_ERROR_TEXT_SUPPORTED eq 1)
+ mov eax,[owner]
+ mov [ebx],eax
+ mov word[ebx+4],': '
+ mov eax,[edi+png_struct.zowner]
+ mov [ebx+6],eax
+ ; So the message that results is " using zstream"; this is an
+ ; internal error, but is very useful for debugging. i18n requirements
+ ; are minimal.
+
+ cStr ,' using zstream'
+ stdcall png_safecat, ebx, 64, 10, eax
+end if
+if PNG_RELEASE_BUILD eq 1
+ png_warning edi, ebx
+
+ ; Attempt sane error recovery
+ cmp dword[edi+png_struct.zowner],png_IDAT
+ jne @f ;if (..==.) ;don't steal from IDAT
+ cStr dword[edi+png_struct.zstream.msg],'in use by IDAT'
+ mov eax,Z_STREAM_ERROR
+ jmp .end_f
+ @@:
+ mov dword[edi+png_struct.zowner],0
+else
+ png_error edi, ebx
+end if
+ .end0:
+
+ mov eax,[edi+png_struct.zlib_level]
+ mov [level],eax
+ mov eax,[edi+png_struct.zlib_method]
+ mov [method],eax
+ mov eax,[edi+png_struct.zlib_window_bits]
+ mov [windowBits],eax
+ mov eax,[edi+png_struct.zlib_mem_level]
+ mov [memLevel],eax
+
+ cmp dword[owner],png_IDAT
+ jne .end1 ;if (..==..)
+ mov eax,[edi+png_struct.flags]
+ and eax,PNG_FLAG_ZLIB_CUSTOM_STRATEGY
+ jz @f ;if (..!=0)
+ mov eax,[edi+png_struct.zlib_strategy]
+ mov dword[strategy],eax
+ jmp .end2
+ @@:
+ cmp byte[edi+png_struct.do_filter],PNG_FILTER_NONE
+ je @f ;else if (..!=..)
+ mov dword[strategy],PNG_Z_DEFAULT_STRATEGY
+ jmp .end2
+ @@: ;else
+ mov dword[strategy],PNG_Z_DEFAULT_NOFILTER_STRATEGY
+ jmp .end2
+ .end1: ;else
+if PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED eq 1
+ mov eax,[edi+png_struct.zlib_text_level]
+ mov [level],eax
+ mov eax,[edi+png_struct.zlib_text_method]
+ mov [method],eax
+ mov eax,[edi+png_struct.zlib_text_window_bits]
+ mov [windowBits],eax
+ mov eax,[edi+png_struct.zlib_text_mem_level]
+ mov [memLevel],eax
+ mov eax,[edi+png_struct.zlib_text_strategy]
+ mov [strategy],eax
+else
+ ; If customization is not supported the values all come from the
+ ; IDAT values except for the strategy, which is fixed to the
+ ; default. (This is the pre-1.6.0 behavior too, although it was
+ ; implemented in a very different way.)
+
+ mov dword[strategy],Z_DEFAULT_STRATEGY
+end if
+ .end2:
+
+ ; Adjust 'windowBits' down if larger than 'data_size'; to stop this
+ ; happening just pass 32768 as the data_size parameter. Notice that zlib
+ ; requires an extra 262 bytes in the window in addition to the data to be
+ ; able to see the whole of the data, so if data_size+262 takes us to the
+ ; next windowBits size we need to fix up the value later. (Because even
+ ; though deflate needs the extra window, inflate does not!)
+
+ cmp dword[data_size],16384
+ jg .end3 ;if (..<=..)
+ ; IMPLEMENTATION NOTE: this 'half_window_size' stuff is only here to
+ ; work round a Microsoft Visual C misbehavior which, contrary to C-90,
+ ; widens the result of the following shift to 64-bits if (and,
+ ; apparently, only if) it is used in a test.
+
+ mov ecx,[windowBits]
+ dec ecx
+ xor eax,eax
+ inc eax
+ shl eax,cl ;eax = half_window_size
+ mov ecx,[data_size]
+ add ecx,262
+ @@: ;while (..<=..)
+ cmp ecx,eax
+ jg .end3
+ shr eax,1
+ dec dword[windowBits]
+ jmp @b
+ .end3:
+
+ ; Check against the previous initialized values, if any.
+ mov eax,[edi+png_struct.flags]
+ and eax,PNG_FLAG_ZSTREAM_INITIALIZED
+ jz .end4
+ mov eax,[level]
+ cmp [edi+png_struct.zlib_set_level],eax
+ jne @f
+ mov eax,[method]
+ cmp [edi+png_struct.zlib_set_method],eax
+ jne @f
+ mov eax,[windowBits]
+ cmp [edi+png_struct.zlib_set_window_bits],eax
+ jne @f
+ mov eax,[memLevel]
+ cmp [edi+png_struct.zlib_set_mem_level],eax
+ jne @f
+ mov eax,[strategy]
+ cmp [edi+png_struct.zlib_set_strategy],eax
+ je .end4
+ @@: ;if (..!=0 && (..!=.. || ..!=.. || ..!=.. || ..!=.. || ..!=..))
+ mov eax,edi
+ add eax,png_struct.zstream
+ stdcall [deflateEnd], eax
+ cmp eax,Z_OK
+ je @f ;if (..!=..)
+ png_warning edi, 'deflateEnd failed (ignored)'
+ @@:
+ and dword[edi+png_struct.flags], not PNG_FLAG_ZSTREAM_INITIALIZED
+ .end4:
+
+ ; For safety clear out the input and output pointers (currently zlib
+ ; doesn't use them on Init, but it might in the future).
+
+ mov dword[edi+png_struct.zstream.next_in],0
+ mov dword[edi+png_struct.zstream.avail_in],0
+ mov dword[edi+png_struct.zstream.next_out],0
+ mov dword[edi+png_struct.zstream.avail_out],0
+
+ ; Now initialize if required, setting the new parameters, otherwise just
+ ; to a simple reset to the previous parameters.
+
+ mov ecx,edi
+ add ecx,png_struct.zstream
+ mov eax,[edi+png_struct.flags]
+ and eax,PNG_FLAG_ZSTREAM_INITIALIZED
+ jz @f ;if (..!=0)
+ stdcall [deflateReset], ecx
+ jmp .end5
+ @@: ;else
+ stdcall [deflateInit2], ecx, [level], [method], [windowBits],\
+ [memLevel], [strategy]
+
+ cmp eax,Z_OK
+ je .end5 ;if (..==..)
+ or dword[edi+png_struct.flags],PNG_FLAG_ZSTREAM_INITIALIZED
+ .end5:
+
+ ; The return code is from either deflateReset or deflateInit2; they have
+ ; pretty much the same set of error codes.
+
+ cmp eax,Z_OK
+ jne @f ;if (..==..)
+ mov ecx,[owner]
+ mov [edi+png_struct.zowner],ecx
+ jmp .end_f
+ @@: ;else
+ stdcall png_zstream_error, edi, eax
+
+.end_f:
+ ret
+endp
+
+; Clean up (or trim) a linked list of compression buffers.
+;void (png_structrp png_ptr, png_compression_bufferp *listp)
+align 4
+proc png_free_buffer_list uses eax ebx ecx edi, png_ptr:dword, listp:dword
+ mov eax,[listp]
+ mov ebx,[eax]
+ ;eax = png_compression_bufferp list
+
+ cmp ebx,0
+ je @f ;if (..!=0)
+ mov dword[eax],0
+ .cycle0: ;do
+ mov ecx,[ebx+png_compression_buffer.next]
+ stdcall png_free, edi, ebx
+ mov ebx,ecx
+ cmp ebx,0
+ jne .cycle0 ;while (..!=0)
+ @@:
+ ret
+endp
+
+if PNG_WRITE_COMPRESSED_TEXT_SUPPORTED eq 1
+; This pair of functions encapsulates the operation of (a) compressing a
+; text string, and (b) issuing it later as a series of chunk data writes.
+; The compression_state structure is shared context for these functions
+; set up by the caller to allow access to the relevant local variables.
+
+; compression_buffer (new in 1.6.0) is just a linked list of zbuffer_size
+; temporary buffers. From 1.6.0 it is retained in png_struct so that it will
+; be correctly freed in the event of a write error (previous implementations
+; just leaked memory.)
+
+struct compression_state
+ input dd ? ;bytep ;The uncompressed input data
+ input_len dd ? ;png_alloc_size_t ;Its length
+ output_len dd ? ;uint_32 ;Final compressed length
+ output rb 1024 ;byte[1024] ;First block of output
+ends
+
+;void (compression_state *comp, bytep input, png_alloc_size_t input_len)
+align 4
+proc png_text_compress_init uses eax ebx, comp:dword, input:dword, input_len:dword
+ mov ebx,[comp]
+ mov eax,[input]
+ mov [ebx+compression_state.input],eax
+ mov eax,[input_len]
+ mov [ebx+compression_state.input_len],eax
+ mov dword[ebx+compression_state.output_len],0
+ ret
+endp
+
+; Compress the data in the compression state input
+;int (png_structrp png_ptr, uint_32 chunk_name, compression_state *comp, uint_32 prefix_len)
+align 4
+proc png_text_compress uses ebx ecx edx edi esi, png_ptr:dword, chunk_name:dword, comp:dword, prefix_len:dword
+locals
+ output_len dd ? ;uint_32
+ avail_in dd ? ;uInt
+ next dd ? ;png_compression_buffer*
+endl
+ ; To find the length of the output it is necessary to first compress the
+ ; input. The result is buffered rather than using the two-pass algorithm
+ ; that is used on the inflate side; deflate is assumed to be slower and a
+ ; PNG writer is assumed to have more memory available than a PNG reader.
+
+ ; IMPLEMENTATION NOTE: the zlib API deflateBound() can be used to find an
+ ; upper limit on the output size, but it is always bigger than the input
+ ; size so it is likely to be more efficient to use this linked-list
+ ; approach.
+
+ mov ebx,[comp]
+ mov edi,[png_ptr]
+ stdcall png_deflate_claim, [chunk_name], [ebx+compression_state.input_len]
+
+ cmp eax,Z_OK
+ jne .end_f ;if (..!=Z_OK) return ..
+
+ ; Set up the compression buffers, we need a loop here to avoid overflowing a
+ ; uInt. Use ZLIB_IO_MAX to limit the input. The output is always limited
+ ; by the output buffer size, so there is no need to check that. Since this
+ ; is ANSI-C we know that an 'int', hence a uInt, is always at least 16 bits
+ ; in size.
+
+ mov edx,edi
+ add edx,png_struct.zbuffer_list
+ mov ecx,[ebx+compression_state.input_len] ;may be zero!
+ ;ecx = input_len
+ ;edx = end
+ ;esi = ret
+
+ ; zlib updates these for us:
+ mov eax,[ebx+compression_state.input]
+ mov [edi+png_struct.zstream.next_in],eax
+ mov dword[edi+png_struct.zstream.avail_in],0 ;Set below
+ mov eax,ebx
+ add eax,compression_state.output
+ mov [edi+png_struct.zstream.next_out],eax
+ mov eax,sizeof.compression_state.output ;1024
+ mov [edi+png_struct.zstream.avail_out],eax
+
+ mov [output_len],eax
+
+ .cycle0: ;do
+ mov dword[avail_in],ZLIB_IO_MAX
+
+ cmp [avail_in],ecx
+ jle @f ;if (..>..)
+ mov [avail_in],ecx
+ @@:
+ sub ecx,[avail_in]
+
+ mov eax,[avail_in]
+ mov [edi+png_struct.zstream.avail_in],eax
+
+ cmp dword[edi+png_struct.zstream.avail_out],0
+ jne .end0 ;if (..==0)
+ ; Chunk data is limited to 2^31 bytes in length, so the prefix
+ ; length must be counted here.
+
+ mov eax,[output_len]
+ add eax,[prefix_len]
+ cmp eax,PNG_UINT_31_MAX
+ jle @f ;if (..>..)
+ mov esi,Z_MEM_ERROR
+ jmp .cycle0end
+ @@:
+
+ ; Need a new (malloc'ed) buffer, but there may be one present
+ ; already.
+
+ mov eax,[edx]
+ mov [next],eax
+
+ test eax,eax
+ jnz .end1 ;if (..==0)
+ PNG_COMPRESSION_BUFFER_SIZE edi
+ stdcall png_malloc, edi, eax
+ mov [next],eax
+
+ test eax,eax
+ jnz @f ;if (..==0)
+ mov esi,Z_MEM_ERROR
+ jmp .cycle0end
+ @@:
+
+ ; Link in this buffer (so that it will be freed later)
+ mov dword[eax+png_compression_buffer.next],0
+ mov [edx],eax
+ .end1:
+
+ mov eax,[next]
+ mov eax,[eax+png_compression_buffer.output]
+ mov [edi+png_struct.zstream.next_out],eax
+ mov eax,[edi+png_struct.zbuffer_size]
+ mov [edi+png_struct.zstream.avail_out],eax
+ add [output_len],eax
+
+ ; Move 'end' to the next buffer pointer.
+ mov eax,[next]
+ add eax,png_compression_buffer.next
+ mov edx,eax
+ .end0:
+
+ ; Compress the data
+ mov eax,Z_FINISH
+ cmp dword[input_len],0
+ jle @f
+ mov eax,Z_NO_FLUSH
+ @@:
+ push eax
+ mov eax,edi
+ add eax,png_struct.zstream
+ stdcall [deflate], eax ;, ...
+ mov esi,eax
+
+ ; Claw back input data that was not consumed (because avail_in is
+ ; reset above every time round the loop).
+
+ mov eax,[edi+png_struct.zstream.avail_in]
+ add [input_len],eax
+ mov dword[edi+png_struct.zstream.avail_in],0 ;safety
+ cmp esi,Z_OK
+ je .cycle0 ;while (..==..)
+ .cycle0end:
+
+ ; There may be some space left in the last output buffer. This needs to
+ ; be subtracted from output_len.
+
+ mov eax,[edi+png_struct.zstream.avail_out]
+ sub [output_len],eax
+ mov dword[edi+png_struct.zstream.avail_out],0 ;safety
+ mov eax,[output_len]
+ mov [ebx+compression_state.output_len],eax
+
+ ; Now double check the output length, put in a custom message if it is
+ ; too long. Otherwise ensure the z_stream::msg pointer is set to
+ ; something.
+
+ mov eax,[output_len]
+ add eax,[prefix_len]
+ cmp eax,PNG_UINT_31_MAX
+ jl @f ;if (..>=..)
+ cStr dword[edi+png_struct.zstream.msg],'compressed data too long'
+ mov esi,Z_MEM_ERROR
+ jmp .end2
+ @@: ;else
+ stdcall png_zstream_error, edi, esi
+ .end2:
+
+ ; Reset zlib for another zTXt/iTXt or image data
+ mov dword[edi+png_struct.zowner],0
+
+ ; The only success case is Z_STREAM_END, input_len must be 0; if not this
+ ; is an internal error.
+
+ cmp esi,Z_STREAM_END
+ jne @f
+ cmp dword[input_len],0
+ jne @f ;if (..==.. && ..==0)
+if PNG_WRITE_OPTIMIZE_CMF_SUPPORTED eq 1
+ ; Fix up the deflate header, if required
+ mov eax,ebx
+ add eax,compression_state.output
+ stdcall optimize_cmf, eax, [ebx+compression_state.input_len]
+end if
+ ; But Z_OK is returned, not Z_STREAM_END; this allows the claim
+ ; function above to return Z_STREAM_END on an error (though it never
+ ; does in the current versions of zlib.)
+
+ mov eax,Z_OK
+ jmp .end_f
+ @@: ;else
+ mov eax,esi
+.end_f:
+ ret
+endp
+
+; Ship the compressed text out via chunk writes
+;void (png_structrp png_ptr, compression_state *comp)
+align 4
+proc png_write_compressed_data_out uses ebx edi, png_ptr:dword, comp:dword
+locals
+ output_len dd ? ;uint_32 ;= comp.output_len
+ output dd ? ;bytep ;= comp.output
+ avail dd ? ;uint_32 ;= sizeof.comp.output
+ next dd ? ;png_compression_buffer* ;= png_ptr.zbuffer_list
+endl
+ mov ebx,[comp]
+ mov eax,[ebx+compression_state.output_len]
+ mov [output_len],eax
+ mov eax,ebx
+ add eax,compression_state.output
+ mov [output],eax
+ mov [avail],sizeof.compression_state.output ;1024
+ mov edi,[png_ptr]
+ mov eax,[edi+png_struct.zbuffer_list]
+ mov [next],eax
+
+ .cycle0: ;for (;;)
+ mov eax,[output_len]
+ cmp [avail],eax
+ jle @f ;if (..>..)
+ mov [avail],eax
+ @@:
+
+ stdcall png_write_chunk_data, edi, [output], [avail]
+
+ mov [avail],eax
+ sub [output_len],eax
+
+ cmp dword[output_len],0
+ je .cycle0end
+ cmp dword[next],0
+ je .cycle0end ;if (..==0 || ..==0) break
+
+ mov eax,[edi+png_struct.zbuffer_size]
+ mov [avail],eax
+ mov eax,[next]
+ add eax,png_compression_buffer.output
+ mov [output],eax
+ mov eax,[next]
+ mov eax,[eax+png_compression_buffer.next]
+ mov [next],eax
+ jmp .cycle0
+ .cycle0end:
+
+ ; This is an internal error; 'next' must have been NULL!
+ cmp dword[output_len],0
+ jle @f ;if (..>0)
+ png_error edi, 'error writing ancillary chunked compressed data'
+ @@:
+ ret
+endp
+end if ;WRITE_COMPRESSED_TEXT
+
+; Write the IHDR chunk, and update the png_struct with the necessary
+; information. Note that the rest of this code depends upon this
+; information being correct.
+
+;void (png_structrp png_ptr, uint_32 width, uint_32 height,
+; int bit_depth, int color_type, int compression_type, int filter_type, int interlace_type)
+align 4
+proc png_write_IHDR, png_ptr:dword, width:dword, height:dword, bit_depth:dword,\
+ color_type:dword, compression_type:dword, filter_type:dword, interlace_type:dword
+locals
+ buf rb 13 ;byte[13] ;Buffer to store the IHDR info
+endl
+ png_debug 1, 'in png_write_IHDR'
+pushad
+ ; Check that we have valid input data from the application info
+ mov edi,[png_ptr]
+ movzx ebx,byte[color_type]
+ cmp ebx,PNG_COLOR_TYPE_GRAY
+ jne .end_0
+ cmp byte[bit_depth],1
+ je @f
+ cmp byte[bit_depth],2
+ je @f
+ cmp byte[bit_depth],4
+ je @f
+ cmp byte[bit_depth],8
+ je @f
+if PNG_WRITE_16BIT_SUPPORTED eq 1
+ cmp byte[bit_depth],16
+ je @f
+end if
+ jmp .def_0
+ @@:
+ mov byte[edi+png_struct.channels], 1
+ jmp .end_s0
+ .def_0: ;default
+ png_error edi, 'Invalid bit depth for grayscale image'
+ jmp .end_s0
+ .end_0:
+
+ cmp ebx,PNG_COLOR_TYPE_RGB
+ jne .end_1
+ cmp byte[bit_depth],8
+ je @f ;if (..!=8)
+if PNG_WRITE_16BIT_SUPPORTED eq 1
+ cmp byte[bit_depth],16
+ je @f ;if (..!=16)
+end if
+ png_error edi, 'Invalid bit depth for RGB image'
+ @@:
+ mov byte[edi+png_struct.channels], 3
+ jmp .end_s0
+ .end_1:
+
+ cmp ebx,PNG_COLOR_TYPE_PALETTE
+ jne .end_2
+ cmp byte[bit_depth],1
+ je @f
+ cmp byte[bit_depth],2
+ je @f
+ cmp byte[bit_depth],4
+ je @f
+ cmp byte[bit_depth],8
+ je @f
+ jmp .def_1
+ @@:
+ mov byte[edi+png_struct.channels], 1
+ jmp .end_s0
+ .def_1: ;default
+ png_error edi, 'Invalid bit depth for paletted image'
+ jmp .end_s0
+ .end_2:
+
+ cmp ebx,PNG_COLOR_TYPE_GRAY_ALPHA
+ jne .end_3
+ cmp byte[bit_depth],8
+ je @f ;if (..!=8)
+ cmp byte[bit_depth],16
+ je @f ;if (..!=16)
+ png_error edi, 'Invalid bit depth for grayscale+alpha image'
+ @@:
+ mov byte[edi+png_struct.channels], 2
+ jmp .end_s0
+ .end_3:
+
+ cmp ebx,PNG_COLOR_TYPE_RGB_ALPHA
+ jne .end_4
+ cmp byte[bit_depth],8
+ je @f ;if (..!=8)
+if PNG_WRITE_16BIT_SUPPORTED eq 1
+ cmp byte[bit_depth],16
+ je @f ;if (..!=16)
+end if
+ png_error edi, 'Invalid bit depth for RGBA image'
+ @@:
+ mov byte[edi+png_struct.channels], 4
+ jmp .end_s0
+ .end_4:
+
+ ;default:
+ png_error edi, 'Invalid image color type specified'
+ .end_s0:
+
+ cmp byte[compression_type], PNG_COMPRESSION_TYPE_BASE
+ je @f ;if (..!=..)
+ png_warning edi, 'Invalid compression type specified'
+ mov dword[compression_type], PNG_COMPRESSION_TYPE_BASE
+ @@:
+
+ ; Write filter_method 64 (intrapixel differencing) only if
+ ; 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
+ ; 2. Libpng did not write a PNG signature (this filter_method is only
+ ; used in PNG datastreams that are embedded in MNG datastreams) and
+ ; 3. The application called png_permit_mng_features with a mask that
+ ; included PNG_FLAG_MNG_FILTER_64 and
+ ; 4. The filter_method is 64 and
+ ; 5. The color_type is RGB or RGBA
+
+; if (
+if PNG_MNG_FEATURES_SUPPORTED eq 1
+; !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
+; ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) == 0) &&
+; (color_type == PNG_COLOR_TYPE_RGB ||
+; color_type == PNG_COLOR_TYPE_RGB_ALPHA) &&
+; (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) &&
+end if
+ cmp dword[filter_type],PNG_FILTER_TYPE_BASE
+ je @f ;if (..!=..)
+ png_warning edi, 'Invalid filter type specified'
+ mov dword[filter_type], PNG_FILTER_TYPE_BASE
+ @@:
+
+if PNG_WRITE_INTERLACING_SUPPORTED eq 1
+ cmp dword[interlace_type],PNG_INTERLACE_NONE
+ je @f ;if (..!=..)
+ cmp dword[interlace_type],PNG_INTERLACE_ADAM7
+ je @f ;if (..!=..)
+ png_warning edi, 'Invalid interlace type specified'
+ mov dword[interlace_type], PNG_INTERLACE_ADAM7
+ @@:
+else
+ mov dword[interlace_type], PNG_INTERLACE_NONE
+end if
+
+ ; Save the relevant information
+ mov al,byte[bit_depth]
+ mov byte[edi+png_struct.bit_depth],al
+ mov al,byte[color_type]
+ mov byte[edi+png_struct.color_type],al
+ mov al,byte[interlace_type]
+ mov byte[edi+png_struct.interlaced],al
+if PNG_MNG_FEATURES_SUPPORTED eq 1
+ mov al,byte[filter_type]
+ mov byte[edi+png_struct.filter_type],al
+end if
+ mov al,byte[compression_type]
+ mov byte[edi+png_struct.compression_type],al
+ mov eax,[width]
+ mov [edi+png_struct.width],eax
+ mov eax,[height]
+ mov [edi+png_struct.height],eax
+
+ movzx eax,byte[edi+png_struct.channels]
+ imul ax,word[bit_depth]
+ mov byte[edi+png_struct.pixel_depth],al
+ PNG_ROWBYTES eax, [width]
+ mov [edi+png_struct.rowbytes],eax
+ ; Set the usr info, so any transformations can modify it
+ mov eax,[edi+png_struct.width]
+ mov [edi+png_struct.usr_width],eax
+ mov al,[edi+png_struct.bit_depth]
+ mov [edi+png_struct.usr_bit_depth],al
+ mov al,[edi+png_struct.channels]
+ mov [edi+png_struct.usr_channels],al
+
+ ; Pack the header information into the buffer
+ mov ebx,ebp
+ sub ebx,13
+ stdcall png_save_uint_32, ebx, [width]
+ add ebx,4
+ stdcall png_save_uint_32, ebx, [height]
+ add ebx,4
+ mov al,byte[bit_depth]
+ mov byte[ebx],al ;buf[8] = (byte)bit_depth
+ inc ebx
+ mov al,byte[color_type]
+ mov byte[ebx],al ;buf[9] = (byte)color_type
+ inc ebx
+ mov al,byte[compression_type]
+ mov byte[ebx],al ;buf[10] = (byte)compression_type
+ inc ebx
+ mov al,byte[filter_type]
+ mov byte[ebx],al ;buf[11] = (byte)filter_type
+ inc ebx
+ mov al,byte[interlace_type]
+ mov byte[ebx],al ;buf[12] = (byte)interlace_type
+ sub ebx,12
+
+ ; Write the chunk
+ stdcall png_write_complete_chunk, edi, png_IHDR, ebx, dword 13
+
+ cmp byte[edi+png_struct.do_filter],PNG_NO_FILTERS
+ jne .end_5 ;if (..==..)
+
+ cmp byte[edi+png_struct.color_type],PNG_COLOR_TYPE_PALETTE
+ je @f
+ cmp byte[edi+png_struct.bit_depth],8
+ jl @f ;if ((..==..)||(..<..))
+ jmp .els_5
+ @@:
+ mov byte[edi+png_struct.do_filter], PNG_FILTER_NONE
+ jmp .end_5
+ .els_5: ;else
+ mov byte[edi+png_struct.do_filter], PNG_ALL_FILTERS
+ .end_5:
+
+ mov dword[edi+png_struct.mode], PNG_HAVE_IHDR ;not READY_FOR_ZTXT
+popad
+ ret
+endp
+
+; Write the palette. We are careful not to trust png_color to be in the
+; correct order for PNG, so people can redefine it to any convenient
+; structure.
+
+;void (png_structrp png_ptr, png_const_colorp palette, uint_32 num_pal)
+align 4
+proc png_write_PLTE, png_ptr:dword, palette:dword, num_pal:dword
+locals
+ ;max_palette_length dd ? ;uint_32
+ i dd ?
+ pal_ptr dd ? ;png_const_colorp
+ buf rb 3 ;byte[3]
+endl
+ png_debug 1, 'in png_write_PLTE'
+
+pushad
+ mov edi,[png_ptr]
+ movzx eax,byte[edi+png_struct.color_type]
+ cmp eax,PNG_COLOR_TYPE_PALETTE
+ je @f ;if (..==..)
+ ;mov dword[max_palette_length],PNG_MAX_PALETTE_LENGTH
+ mov eax,PNG_MAX_PALETTE_LENGTH
+ jmp .end0
+ @@:
+ mov cl,byte[edi+png_struct.bit_depth]
+ xor eax,eax
+ inc eax
+ shl eax,cl
+ ;mov [max_palette_length],eax
+ .end0:
+
+if PNG_MNG_FEATURES_SUPPORTED eq 1
+ cmp [num_pal],eax
+ jg @f
+ mov eax,[edi+png_struct.mng_features_permitted]
+ and eax,PNG_FLAG_MNG_EMPTY_PLTE
+ jnz .end1
+ cmp [num_pal],0
+ jne .end1
+ @@:
+end if
+
+ cmp byte[edi+png_struct.color_type],PNG_COLOR_TYPE_PALETTE ;if (..==..)
+ jne @f
+ png_error edi, 'Invalid number of colors in palette'
+ jmp .end1
+ @@: ;else
+ png_warning edi, 'Invalid number of colors in palette'
+ jmp .end_f
+ .end1:
+
+ movzx eax,byte[edi+png_struct.color_type]
+ and eax,PNG_COLOR_MASK_COLOR
+ jnz @f ;if (..==0)
+ png_warning edi, 'Ignoring request to write a PLTE chunk in grayscale PNG'
+ jmp .end_f
+ @@:
+
+ movzx eax,word[num_pal]
+ mov word[edi+png_struct.num_palette],ax
+ png_debug1 3, 'num_palette = %d', eax
+
+ imul eax,3
+ stdcall png_write_chunk_header, edi, png_PLTE, eax
+if PNG_POINTER_INDEXING_SUPPORTED eq 1
+
+; for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++)
+; {
+; buf[0] = pal_ptr->red;
+; buf[1] = pal_ptr->green;
+; buf[2] = pal_ptr->blue;
+; png_write_chunk_data(png_ptr, buf, (png_size_t)3);
+; }
+
+else
+ ; This is a little slower but some buggy compilers need to do this
+ ; instead
+
+; pal_ptr=palette;
+
+; for (i = 0; i < num_pal; i++)
+; {
+; buf[0] = pal_ptr[i].red;
+; buf[1] = pal_ptr[i].green;
+; buf[2] = pal_ptr[i].blue;
+; png_write_chunk_data(png_ptr, buf, (png_size_t)3);
+; }
+
+end if
+ stdcall png_write_chunk_end, edi
+ or dword[edi+png_struct.mode], PNG_HAVE_PLTE
+.end_f:
+popad
+ ret
+endp
+
+; This is similar to png_text_compress, above, except that it does not require
+; all of the data at once and, instead of buffering the compressed result,
+; writes it as IDAT chunks. Unlike png_text_compress it *can* png_error out
+; because it calls the write interface. As a result it does its own error
+; reporting and does not return an error code. In the event of error it will
+; just call png_error. The input data length may exceed 32-bits. The 'flush'
+; parameter is exactly the same as that to deflate, with the following
+; meanings:
+
+; Z_NO_FLUSH: normal incremental output of compressed data
+; Z_SYNC_FLUSH: do a SYNC_FLUSH, used by png_write_flush
+; Z_FINISH: this is the end of the input, do a Z_FINISH and clean up
+
+; The routine manages the acquire and release of the png_ptr->zstream by
+; checking and (at the end) clearing png_ptr->zowner; it does some sanity
+; checks on the 'mode' flags while doing this.
+
+;void (png_structrp png_ptr, bytep input, png_alloc_size_t input_len, int flush)
+;input:
+; edi - png_ptr
+align 4
+proc png_compress_IDAT uses eax ebx ecx edx, input:dword, input_len:dword, flush:dword
+ png_debug 1, 'in png_compress_IDAT'
+
+ cmp dword[edi+png_struct.zowner],png_IDAT
+ je .end0 ;if (..!=..)
+ ; First time. Ensure we have a temporary buffer for compression and
+ ; trim the buffer list if it has more than one entry to free memory.
+ ; If 'WRITE_COMPRESSED_TEXT' is not set the list will never have been
+ ; created at this point, but the check here is quick and safe.
+
+ cmp dword[edi+png_struct.zbuffer_list],0
+ jne @f ;if (..==0)
+ PNG_COMPRESSION_BUFFER_SIZE edi
+ stdcall png_malloc, edi, eax
+ mov [edi+png_struct.zbuffer_list],eax
+ mov dword[eax+png_compression_buffer.next],0
+ jmp .end1
+ @@: ;else
+ mov eax,[edi+png_struct.zbuffer_list]
+ add eax,png_compression_buffer.next
+ ;eax = &...next
+ stdcall png_free_buffer_list, edi, eax
+ .end1:
+
+ ;It is a terminal error if we can't claim the zstream.
+ stdcall png_image_size, edi
+ stdcall png_deflate_claim, png_IDAT, eax
+ cmp eax,Z_OK
+ je @f ;if (..!=..)
+ png_error edi, [edi+png_struct.zstream.msg]
+ @@:
+
+ ; The output state is maintained in png_ptr->zstream, so it must be
+ ; initialized here after the claim.
+
+ mov eax,[edi+png_struct.zbuffer_list]
+ add eax,png_compression_buffer.output
+ mov [edi+png_struct.zstream.next_out],eax
+ mov eax,[edi+png_struct.zbuffer_size]
+ mov [edi+png_struct.zstream.avail_out],eax
+ .end0:
+
+ ; Now loop reading and writing until all the input is consumed or an error
+ ; terminates the operation. The _out values are maintained across calls to
+ ; this function, but the input must be reset each time.
+
+ mov eax,[input]
+ mov [edi+png_struct.zstream.next_in],eax
+ mov dword[edi+png_struct.zstream.avail_in],0 ;set below
+align 4
+ .cycle0:
+ ;INPUT: from the row data
+ mov eax,ZLIB_IO_MAX
+
+ cmp eax,[input_len]
+ jbe @f ;if (..>..)
+ mov eax,[input_len] ;safe because of the check
+ @@:
+
+ mov [edi+png_struct.zstream.avail_in],eax
+ sub [input_len],eax
+
+ mov eax,[flush]
+ cmp dword[input_len],0
+ jle @f
+ mov eax,Z_NO_FLUSH
+ @@:
+ mov ecx,edi
+ add ecx,png_struct.zstream
+ stdcall [deflate], ecx, eax
+ mov ebx,eax
+
+ ;Include as-yet unconsumed input
+ mov eax,[edi+png_struct.zstream.avail_in]
+ add [input_len],eax
+ mov dword[edi+png_struct.zstream.avail_in],0
+
+ ; OUTPUT: write complete IDAT chunks when avail_out drops to zero. Note
+ ; that these two zstream fields are preserved across the calls, therefore
+ ; there is no need to set these up on entry to the loop.
+
+ cmp dword[edi+png_struct.zstream.avail_out],0
+ jne .end2 ;if (..==0)
+ mov edx,[edi+png_struct.zbuffer_list]
+ add edx,png_compression_buffer.output
+ mov ecx,[edi+png_struct.zbuffer_size]
+ ;edx = data
+ ;ecx = size
+ ; Write an IDAT containing the data then reset the buffer. The
+ ; first IDAT may need deflate header optimization.
+
+if PNG_WRITE_OPTIMIZE_CMF_SUPPORTED eq 1
+ mov eax,[edi+png_struct.mode]
+ and eax,PNG_HAVE_IDAT
+ jnz @f
+ cmp byte[edi+png_struct.compression_type],PNG_COMPRESSION_TYPE_BASE
+ jne @f ;if (..==0 && ..==..)
+ stdcall png_image_size, edi
+ stdcall optimize_cmf, edx, eax
+ @@:
+end if
+
+ stdcall png_write_complete_chunk, edi, png_IDAT, edx, ecx
+ or dword[edi+png_struct.mode],PNG_HAVE_IDAT
+
+ mov [edi+png_struct.zstream.next_out],edx
+ mov [edi+png_struct.zstream.avail_out],ecx
+
+ ; For SYNC_FLUSH or FINISH it is essential to keep calling zlib with
+ ; the same flush parameter until it has finished output, for NO_FLUSH
+ ; it doesn't matter.
+
+ cmp ebx,Z_OK
+ jne .end2
+ cmp dword[flush],Z_NO_FLUSH
+ jne .cycle0 ;if (..==.. && ..!=..) continue
+ .end2:
+
+ ; The order of these checks doesn't matter much; it just affects which
+ ; possible error might be detected if multiple things go wrong at once.
+
+ cmp ebx,Z_OK
+ jne .end3 ;if (..==..) ;most likely return code!
+ ; If all the input has been consumed then just return. If Z_FINISH
+ ; was used as the flush parameter something has gone wrong if we get
+ ; here.
+
+ cmp dword[input_len],0
+ jne .cycle0 ;if (..==0)
+ cmp dword[flush],Z_FINISH
+ jne .cycle0end ;if (..==..)
+ png_error edi, 'Z_OK on Z_FINISH with output space'
+ jmp .cycle0end
+ .end3:
+ cmp ebx,Z_STREAM_END
+ jne .end4
+ cmp dword[flush],Z_FINISH
+ jne .end4 ;else if (..==.. && ..==..)
+ ; This is the end of the IDAT data; any pending output must be
+ ; flushed. For small PNG files we may still be at the beginning.
+
+ mov edx,[edi+png_struct.zbuffer_list]
+ add edx,png_compression_buffer.output
+ mov ecx,[edi+png_struct.zbuffer_size]
+ mov eax,[edi+png_struct.zstream.avail_out]
+ sub ecx,eax
+ ;edx = data
+ ;ecx = size
+
+if PNG_WRITE_OPTIMIZE_CMF_SUPPORTED eq 1
+ mov eax,[edi+png_struct.mode]
+ and eax,PNG_HAVE_IDAT
+ jnz @f
+ cmp byte[edi+png_struct.compression_type],PNG_COMPRESSION_TYPE_BASE
+ jne @f ;if (..==0 && ..==..)
+ stdcall png_image_size, edi
+ stdcall optimize_cmf, edx, eax
+ @@:
+end if
+ stdcall png_write_complete_chunk, edi, png_IDAT, edx, ecx
+ mov dword[edi+png_struct.zstream.avail_out],0
+ mov dword[edi+png_struct.zstream.next_out],0
+ or dword[edi+png_struct.mode], PNG_HAVE_IDAT or PNG_AFTER_IDAT
+
+ mov dword[edi+png_struct.zowner],0 ;Release the stream
+ jmp .cycle0end
+ .end4: ;else
+ ; This is an error condition.
+ stdcall png_zstream_error, edi, ebx
+ png_error edi, [edi+png_struct.zstream.msg]
+ jmp .cycle0
+ .cycle0end:
+ ret
+endp
+
+; Write an IEND chunk
+;void (png_structrp png_ptr)
+align 4
+proc png_write_IEND uses edi, png_ptr:dword
+ png_debug 1, 'in png_write_IEND'
+
+ mov edi,[png_ptr]
+ stdcall png_write_complete_chunk, edi, png_IEND, 0, 0
+ or dword[edi+png_struct.mode], PNG_HAVE_IEND
+ ret
+endp
+
+; Write a gAMA chunk
+;void (png_structrp png_ptr, png_fixed_point file_gamma)
+align 4
+proc png_write_gAMA_fixed uses ebx, png_ptr:dword, file_gamma:dword
+locals
+ buf rb 4 ;byte[4]
+endl
+ png_debug 1, 'in png_write_gAMA'
+
+ ; file_gamma is saved in 1/100,000ths
+ mov ebx,ebp
+ sub ebx,4
+ stdcall png_save_uint_32 ,ebx, [file_gamma]
+ stdcall png_write_complete_chunk, [png_ptr], png_gAMA, ebx, 4
+ ret
+endp
+
+; Write a sRGB chunk
+;void (png_structrp png_ptr, int srgb_intent)
+align 4
+proc png_write_sRGB uses eax ebx, png_ptr:dword, srgb_intent:dword
+locals
+ buf db ? ;byte[1]
+endl
+ png_debug 1, 'in png_write_sRGB'
+
+ cmp dword[srgb_intent], PNG_sRGB_INTENT_LAST ;if (..>=..)
+ jl @f
+ png_warning [png_ptr], 'Invalid sRGB rendering intent specified'
+ @@:
+
+ mov al,byte[srgb_intent]
+ mov ebx,ebp
+ dec ebx
+ mov byte[ebx],al ;buf[0]=(byte)srgb_intent
+ stdcall png_write_complete_chunk, [png_ptr], png_sRGB, ebx, 1
+ ret
+endp
+
+; Write an iCCP chunk
+;void (png_structrp png_ptr, charp name, bytep profile)
+align 4
+proc png_write_iCCP uses eax ebx ecx edi, png_ptr:dword, name:dword, profile:dword
+locals
+ name_len dd ? ;uint_32
+ profile_len dd ? ;uint_32
+ temp dd ? ;uint_32
+ new_name rb 81 ;byte[81] ;1 byte for the compression byte
+ comp compression_state
+endl
+ png_debug 1, 'in png_write_iCCP'
+
+ ; These are all internal problems: the profile should have been checked
+ ; before when it was stored.
+
+ mov edi,[png_ptr]
+ cmp dword[profile],0
+ jne @f ;if (..==0)
+ png_error edi, 'No profile for iCCP chunk' ;internal error
+ @@:
+
+ stdcall png_get_uint_32,[profile]
+ mov [profile_len],eax
+
+ cmp eax,132
+ jge @f ;if (..<..)
+ png_error edi, 'ICC profile too short'
+ @@:
+
+; temp = (uint_32) (*(profile+8));
+; if (temp > 3 && (profile_len & 0x03))
+; png_error(png_ptr, "ICC profile length invalid (not a multiple of 4)");
+
+; {
+; uint_32 embedded_profile_len = png_get_uint_32(profile);
+
+; if (profile_len != embedded_profile_len)
+; png_error(png_ptr, "Profile length does not match profile");
+; }
+
+ mov ebx,ebp
+ sub ebx,sizeof.compression_state
+ mov ecx,ebx ;ecx = &comp
+ sub ebx,81 ;ebx = &new_name
+ stdcall png_check_keyword, edi, [name], ebx
+ mov [name_len],eax
+
+ test eax,eax
+ jnz @f ;if (..==0)
+ png_error edi, 'iCCP: invalid keyword'
+ @@:
+
+ inc dword[name_len]
+ mov eax,[name_len]
+ add eax,ebx
+ mov byte[eax], PNG_COMPRESSION_TYPE_BASE
+
+ ; Make sure we include the NULL after the name and the compression type
+ inc dword[name_len]
+
+ stdcall png_text_compress_init, ecx, [profile], [profile_len]
+
+ ; Allow for keyword terminator and compression byte
+; if (png_text_compress(png_ptr, png_iCCP, &comp, name_len) != Z_OK)
+; png_error(png_ptr, png_ptr->zstream.msg);
+
+; png_write_chunk_header(png_ptr, png_iCCP, name_len + comp.output_len);
+
+ stdcall png_write_chunk_data, edi, ebx, [name_len]
+
+ stdcall png_write_compressed_data_out, edi, ecx
+
+ stdcall png_write_chunk_end, edi
+ ret
+endp
+
+; Write a sPLT chunk
+;void (png_structrp png_ptr, png_const_sPLT_tp spalette)
+align 4
+proc png_write_sPLT, png_ptr:dword, spalette:dword
+; uint_32 name_len;
+; byte new_name[80];
+; byte entrybuf[10];
+; png_size_t entry_size = (spalette->depth == 8 ? 6 : 10);
+; png_size_t palette_size = entry_size * spalette->nentries;
+; png_sPLT_entryp ep;
+if PNG_POINTER_INDEXING_SUPPORTED eq
+; int i;
+end if
+
+ png_debug 1, 'in png_write_sPLT'
+
+; name_len = png_check_keyword(png_ptr, spalette->name, new_name);
+
+; if (name_len == 0)
+; png_error(png_ptr, "sPLT: invalid keyword");
+
+ ; Make sure we include the NULL after the name
+; png_write_chunk_header(png_ptr, png_sPLT,
+; (uint_32)(name_len + 2 + palette_size));
+
+; png_write_chunk_data(png_ptr, (bytep)new_name,
+; (png_size_t)(name_len + 1));
+
+; png_write_chunk_data(png_ptr, &spalette->depth, (png_size_t)1);
+
+ ; Loop through each palette entry, writing appropriately
+if PNG_POINTER_INDEXING_SUPPORTED eq 1
+; for (ep = spalette->entries; epentries + spalette->nentries; ep++)
+; {
+; if (spalette->depth == 8)
+; {
+; entrybuf[0] = (byte)ep->red;
+; entrybuf[1] = (byte)ep->green;
+; entrybuf[2] = (byte)ep->blue;
+; entrybuf[3] = (byte)ep->alpha;
+; png_save_uint_16(entrybuf + 4, ep->frequency);
+; }
+
+; else
+; {
+; png_save_uint_16(entrybuf + 0, ep->red);
+; png_save_uint_16(entrybuf + 2, ep->green);
+; png_save_uint_16(entrybuf + 4, ep->blue);
+; png_save_uint_16(entrybuf + 6, ep->alpha);
+; png_save_uint_16(entrybuf + 8, ep->frequency);
+; }
+
+; png_write_chunk_data(png_ptr, entrybuf, entry_size);
+; }
+else
+; ep=spalette->entries;
+; for (i = 0; i>spalette->nentries; i++)
+; {
+; if (spalette->depth == 8)
+; {
+; entrybuf[0] = (byte)ep[i].red;
+; entrybuf[1] = (byte)ep[i].green;
+; entrybuf[2] = (byte)ep[i].blue;
+; entrybuf[3] = (byte)ep[i].alpha;
+; png_save_uint_16(entrybuf + 4, ep[i].frequency);
+; }
+
+; else
+; {
+; png_save_uint_16(entrybuf + 0, ep[i].red);
+; png_save_uint_16(entrybuf + 2, ep[i].green);
+; png_save_uint_16(entrybuf + 4, ep[i].blue);
+; png_save_uint_16(entrybuf + 6, ep[i].alpha);
+; png_save_uint_16(entrybuf + 8, ep[i].frequency);
+; }
+
+; png_write_chunk_data(png_ptr, entrybuf, entry_size);
+; }
+end if
+
+; png_write_chunk_end(png_ptr);
+ ret
+endp
+
+; Write the sBIT chunk
+;void (png_structrp png_ptr, png_const_color_8p sbit, int color_type)
+align 4
+proc png_write_sBIT uses eax edi, png_ptr:dword, sbit:dword, color_type:dword
+locals
+ size dd ? ;png_size_t
+ buf rb 4 ;byte[4]
+endl
+ png_debug 1, 'in png_write_sBIT'
+
+ ; Make sure we don't depend upon the order of PNG_COLOR_8
+; if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
+; {
+; byte maxbits;
+
+; maxbits = (byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 :
+; png_ptr->usr_bit_depth);
+
+; if (sbit->red == 0 || sbit->red > maxbits ||
+; sbit->green == 0 || sbit->green > maxbits ||
+; sbit->blue == 0 || sbit->blue > maxbits)
+; {
+; png_warning(png_ptr, "Invalid sBIT depth specified");
+; return;
+; }
+
+; buf[0] = sbit->red;
+; buf[1] = sbit->green;
+; buf[2] = sbit->blue;
+; size = 3;
+; }
+
+; else
+; {
+; if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth)
+; {
+; png_warning(png_ptr, "Invalid sBIT depth specified");
+; return;
+; }
+
+; buf[0] = sbit->gray;
+; size = 1;
+; }
+
+; if ((color_type & PNG_COLOR_MASK_ALPHA) != 0)
+; {
+; if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth)
+; {
+; png_warning(png_ptr, "Invalid sBIT depth specified");
+; return;
+; }
+
+; buf[size++] = sbit->alpha;
+; }
+
+; png_write_complete_chunk(png_ptr, png_sBIT, buf, size);
+.end_f:
+ ret
+endp
+
+; Write the cHRM chunk
+;void (png_structrp png_ptr, const png_xy *xy)
+align 4
+proc png_write_cHRM_fixed uses eax ebx, png_ptr:dword, xy:dword
+locals
+ buf rb 32 ;byte[32]
+endl
+ png_debug 1, 'in png_write_cHRM'
+
+ ; Each value is saved in 1/100,000ths
+ mov eax,[xy]
+ mov ebx,ebp
+ sub ebx,32
+; png_save_int_32(buf, xy->whitex);
+; png_save_int_32(buf + 4, xy->whitey);
+
+; png_save_int_32(buf + 8, xy->redx);
+; png_save_int_32(buf + 12, xy->redy);
+
+; png_save_int_32(buf + 16, xy->greenx);
+; png_save_int_32(buf + 20, xy->greeny);
+
+; png_save_int_32(buf + 24, xy->bluex);
+; png_save_int_32(buf + 28, xy->bluey);
+
+ stdcall png_write_complete_chunk, [png_ptr], png_cHRM, ebx, 32
+ ret
+endp
+
+; Write the tRNS chunk
+;void (png_structrp png_ptr, bytep trans_alpha, png_color_16p tran, int num_trans, int color_type)
+align 4
+proc png_write_tRNS uses eax ebx ecx edi, png_ptr:dword, trans_alpha:dword, tran:dword, num_trans:dword, color_type:dword
+locals
+ buf rb 6 ;byte[6]
+endl
+ png_debug 1, 'in png_write_tRNS'
+
+ mov edi,[png_ptr]
+ cmp byte[color_type],PNG_COLOR_TYPE_PALETTE
+ jne .end0 ;if (..==..)
+ cmp dword[num_trans],0
+ jle @f
+ movzx eax,word[edi+png_struct.num_palette]
+ cmp [num_trans],eax
+ jle .end1
+ @@: ;if (..<=0 || ..>..)
+ png_app_warning edi, 'Invalid number of transparent colors specified'
+ jmp .end_f
+ .end1:
+
+ ; Write the chunk out as it is
+ stdcall png_write_complete_chunk, edi, png_tRNS, [trans_alpha], [num_trans]
+ jmp .end_f
+ .end0:
+
+ cmp dword[color_type],PNG_COLOR_TYPE_GRAY
+ jne .end2 ;else if (..==..)
+ ; One 16-bit value
+ mov cl,[edi+png_struct.bit_depth]
+ xor eax,eax
+ inc eax
+ shl eax,cl
+ mov ecx,[tran]
+ cmp word[ecx+png_color_16.gray],ax
+ jl @f ;if (..>=..)
+ png_app_warning edi, 'Ignoring attempt to write tRNS chunk out-of-range for bit_depth'
+ jmp .end_f
+ @@:
+ movzx eax,word[ecx+png_color_16.gray]
+ mov ebx,ebp
+ sub ebx,6
+ stdcall png_save_uint_16, ebx, eax
+ stdcall png_write_complete_chunk, edi, png_tRNS, ebx, 2
+ jmp .end_f
+ .end2:
+
+ cmp dword[color_type],PNG_COLOR_TYPE_RGB
+ jne .end3 ;else if (..== ..)
+ ; Three 16-bit values
+ mov ebx,ebp
+ sub ebx,6
+ mov ecx,[tran]
+ movzx eax,word[ecx+png_color_16.red]
+ stdcall png_save_uint_16, ebx, eax
+ add ebx,2
+ movzx eax,word[ecx+png_color_16.green]
+ stdcall png_save_uint_16, ebx, eax
+ add ebx,2
+ movzx eax,word[ecx+png_color_16.blue]
+ stdcall png_save_uint_16, ebx, eax
+ sub ebx,4
+if PNG_WRITE_16BIT_SUPPORTED eq 1
+ cmp byte[edi+png_struct.bit_depth],8
+ jne @f ;if (..==.. && ...
+end if
+ mov al,[ebx]
+ or al,[ebx+2]
+ or al,[ebx+4]
+ cmp al,0
+ je @f ;if (..|..|..!=0)
+ png_app_warning edi, 'Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8'
+ jmp .end_f
+ @@:
+ stdcall png_write_complete_chunk, edi, png_tRNS, ebx, 6
+ jmp .end_f
+ .end3: ;else
+ cStr ,<'Can',39,'t write tRNS with an alpha channel'>
+ png_app_warning edi, eax
+.end_f:
+ ret
+endp
+
+; Write the background chunk
+;void (png_structrp png_ptr, png_const_color_16p back, int color_type)
+align 4
+proc png_write_bKGD, png_ptr:dword, back:dword, color_type:dword
+locals
+ buf rb 6 ;byte[6]
+endl
+ png_debug 1, 'in png_write_bKGD'
+
+; if (color_type == PNG_COLOR_TYPE_PALETTE)
+; {
+; if (
+if PNG_MNG_FEATURES_SUPPORTED eq 1
+; (png_ptr->num_palette != 0 ||
+; (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0) &&
+end if
+; back->index >= png_ptr->num_palette)
+; {
+; png_warning(png_ptr, "Invalid background palette index");
+; return;
+; }
+
+; buf[0] = back->index;
+; png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)1);
+; }
+
+; else if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
+; {
+; png_save_uint_16(buf, back->red);
+; png_save_uint_16(buf + 2, back->green);
+; png_save_uint_16(buf + 4, back->blue);
+if PNG_WRITE_16BIT_SUPPORTED eq 1
+; if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]) != 0)
+else
+; if ((buf[0] | buf[2] | buf[4]) != 0)
+end if
+; {
+; png_warning(png_ptr,
+; "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8");
+
+; return;
+; }
+
+; png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)6);
+; }
+
+; else
+; {
+; if (back->gray >= (1 << png_ptr->bit_depth))
+; {
+; png_warning(png_ptr,
+; "Ignoring attempt to write bKGD chunk out-of-range for bit_depth");
+
+; return;
+; }
+
+; png_save_uint_16(buf, back->gray);
+; png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)2);
+; }
+ ret
+endp
+
+; Write the histogram
+;void (png_structrp png_ptr, png_const_uint_16p hist, int num_hist)
+align 4
+proc png_write_hIST, png_ptr:dword, hist:dword, num_hist:dword
+locals
+ i dd ? ;int
+ buf rb 3 ;byte[3]
+endl
+ png_debug 1, 'in png_write_hIST'
+pushad
+
+ mov edi,[png_ptr]
+ movzx eax,word[edi+png_struct.num_palette]
+ cmp [num_hist],eax
+ jle @f ;if (..>..)
+; png_debug2(3, "num_hist = %d, num_palette = %d", num_hist,
+; png_ptr->num_palette);
+
+ png_warning edi, 'Invalid number of histogram entries specified'
+ jmp .end_f
+ @@:
+
+ mov eax,[num_hist]
+ shl eax,1
+ stdcall png_write_chunk_header, edi, png_hIST, eax
+
+; for (i = 0; i < num_hist; i++)
+; {
+; png_save_uint_16(buf, hist[i]);
+; png_write_chunk_data(png_ptr, buf, (png_size_t)2);
+; }
+
+ stdcall png_write_chunk_end, edi
+.end_f:
+popad
+ ret
+endp
+
+; Write a tEXt chunk
+;void (png_structrp png_ptr, charp key, charp text, png_size_t text_len)
+align 4
+proc png_write_tEXt uses eax edi, png_ptr:dword, key:dword, text:dword, text_len:dword
+locals
+ key_len dd ? ;uint_32
+ new_key rb 80 ;byte[80]
+endl
+ png_debug 1, 'in png_write_tEXt'
+
+; key_len = png_check_keyword(png_ptr, key, new_key);
+
+; if (key_len == 0)
+; png_error(png_ptr, "tEXt: invalid keyword");
+
+; if (text == NULL || *text == '\0')
+; text_len = 0;
+
+; else
+; text_len = strlen(text);
+
+; if (text_len > PNG_UINT_31_MAX - (key_len+1))
+; png_error(png_ptr, "tEXt: text too long");
+
+ ; Make sure we include the 0 after the key
+; png_write_chunk_header(png_ptr, png_tEXt,
+; (uint_32)/*checked above*/(key_len + text_len + 1));
+
+ ; We leave it to the application to meet PNG-1.0 requirements on the
+ ; contents of the text. PNG-1.0 through PNG-1.2 discourage the use of
+ ; any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them.
+ ; The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
+
+; png_write_chunk_data(png_ptr, new_key, key_len + 1);
+
+; if (text_len != 0)
+; png_write_chunk_data(png_ptr, (bytep)text, text_len);
+
+; png_write_chunk_end(png_ptr);
+ ret
+endp
+
+if PNG_WRITE_zTXt_SUPPORTED eq 1
+; Write a compressed text chunk
+;void (png_structrp png_ptr, charp key, charp text, int compression)
+align 4
+proc png_write_zTXt uses eax edi, png_ptr:dword, key:dword, text:dword, compression:dword
+locals
+ key_len dd ? ;uint_32
+ new_key rb 81 ;byte[81]
+ comp compression_state
+endl
+ png_debug 1, 'in png_write_zTXt'
+
+ mov edi,[png_ptr]
+ cmp dword[compression],PNG_TEXT_COMPRESSION_NONE
+ jne @f ;if (..==..)
+ stdcall png_write_tEXt, edi, [key], [text], 0
+ jmp .end_f
+ @@:
+
+; if (compression != PNG_TEXT_COMPRESSION_zTXt)
+; png_error(png_ptr, "zTXt: invalid compression type");
+
+; key_len = png_check_keyword(png_ptr, key, new_key);
+
+; if (key_len == 0)
+; png_error(png_ptr, "zTXt: invalid keyword");
+
+ ; Add the compression method and 1 for the keyword separator.
+; new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE;
+; ++key_len;
+
+ ; Compute the compressed data; do it now for the length
+; png_text_compress_init(&comp, (bytep)text,
+; text == NULL ? 0 : strlen(text));
+
+; if (png_text_compress(png_ptr, png_zTXt, &comp, key_len) != Z_OK)
+; png_error(png_ptr, png_ptr->zstream.msg);
+
+ ; Write start of chunk
+; png_write_chunk_header(png_ptr, png_zTXt, key_len + comp.output_len);
+
+ ; Write key
+; png_write_chunk_data(png_ptr, new_key, key_len);
+
+ ; Write the compressed data
+; png_write_compressed_data_out(png_ptr, &comp);
+
+ ; Close the chunk
+ stdcall png_write_chunk_end, edi
+.end_f:
+ ret
+endp
+end if
+
+if PNG_WRITE_iTXt_SUPPORTED eq 1
+; Write an iTXt chunk
+;void (png_structrp png_ptr, int compression, charp key,
+; charp lang, charp lang_key, charp text)
+align 4
+proc png_write_iTXt, png_ptr:dword, compression:dword, key:dword, lang:dword, lang_key:dword, text:dword
+locals
+ key_len dd ? ;uint_32
+ prefix_len dd ?
+ ;png_size_t lang_len, lang_key_len;
+ new_key rb 82 ;byte[82]
+ comp compression_state
+endl
+
+ png_debug 1, 'in png_write_iTXt'
+pushad
+ mov edi,[png_ptr]
+ mov ebx,ebp
+ sub ebx,82+sizeof.compression_state
+ stdcall png_check_keyword, edi, [key], ebx
+ mov [key_len],eax
+
+ test eax,eax
+ jnz @f ;if (..==0)
+ png_error edi, 'iTXt: invalid keyword'
+ @@:
+
+ ; Set the compression flag
+; switch (compression)
+; {
+; case PNG_ITXT_COMPRESSION_NONE:
+; case PNG_TEXT_COMPRESSION_NONE:
+; compression = new_key[++key_len] = 0; /* no compression */
+; break;
+
+; case PNG_TEXT_COMPRESSION_zTXt:
+; case PNG_ITXT_COMPRESSION_zTXt:
+; compression = new_key[++key_len] = 1; /* compressed */
+; break;
+
+; default:
+; png_error(png_ptr, "iTXt: invalid compression");
+; }
+
+; new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE;
+; ++key_len; /* for the keywod separator */
+
+ ; We leave it to the application to meet PNG-1.0 requirements on the
+ ; contents of the text. PNG-1.0 through PNG-1.2 discourage the use of
+ ; any non-Latin-1 characters except for NEWLINE. ISO PNG, however,
+ ; specifies that the text is UTF-8 and this really doesn't require any
+ ; checking.
+
+ ; The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
+
+ ; TODO: validate the language tag correctly (see the spec.)
+
+; if (lang == NULL) lang = ""; /* empty language is valid */
+; lang_len = strlen(lang)+1;
+; if (lang_key == NULL) lang_key = ""; /* may be empty */
+; lang_key_len = strlen(lang_key)+1;
+; if (text == NULL) text = ""; /* may be empty */
+
+ mov eax,[key_len]
+ mov [prefix_len],eax
+; if (lang_len > PNG_UINT_31_MAX-prefix_len)
+; prefix_len = PNG_UINT_31_MAX;
+; else
+; prefix_len = (uint_32)(prefix_len + lang_len);
+
+; if (lang_key_len > PNG_UINT_31_MAX-prefix_len)
+; prefix_len = PNG_UINT_31_MAX;
+; else
+; prefix_len = (uint_32)(prefix_len + lang_key_len);
+
+; png_text_compress_init(&comp, (bytep)text, strlen(text));
+
+; if (compression != 0)
+; {
+; if (png_text_compress(png_ptr, png_iTXt, &comp, prefix_len) != Z_OK)
+; png_error(png_ptr, png_ptr->zstream.msg);
+; }
+
+; else
+; {
+; if (comp.input_len > PNG_UINT_31_MAX-prefix_len)
+; png_error(png_ptr, "iTXt: uncompressed text too long");
+
+ ; So the string will fit in a chunk:
+; comp.output_len = (uint_32)/*SAFE*/comp.input_len;
+; }
+
+; png_write_chunk_header(png_ptr, png_iTXt, comp.output_len + prefix_len);
+
+; png_write_chunk_data(png_ptr, new_key, key_len);
+
+; png_write_chunk_data(png_ptr, (bytep)lang, lang_len);
+
+; png_write_chunk_data(png_ptr, (bytep)lang_key, lang_key_len);
+
+; if (compression != 0)
+; png_write_compressed_data_out(png_ptr, &comp);
+
+; else
+; png_write_chunk_data(png_ptr, (bytep)text, comp.output_len);
+
+ stdcall png_write_chunk_end, edi
+popad
+ ret
+endp
+end if
+
+; Write the oFFs chunk
+;void (png_structrp png_ptr, int_32 x_offset, int_32 y_offset, int unit_type)
+align 4
+proc png_write_oFFs uses eax ebx edi, png_ptr:dword, x_offset:dword, y_offset:dword, unit_type:dword
+locals
+ buf rb 9 ;byte[9]
+endl
+ png_debug 1, 'in png_write_oFFs'
+
+ mov edi,[png_ptr]
+ cmp dword[unit_type],PNG_OFFSET_LAST
+ jl @f ;if (..>=..)
+ png_warning edi, 'Unrecognized unit type for oFFs chunk'
+ @@:
+
+ mov ebx,ebp
+ sub ebx,9
+ stdcall png_save_int_32, ebx, [x_offset]
+ add ebx,4
+ stdcall png_save_int_32, ebx, [y_offset]
+ add ebx,4
+ mov eax,[unit_type]
+ mov [ebx],al
+ sub ebx,8
+
+ stdcall png_write_complete_chunk, edi, png_oFFs, ebx, 9
+ ret
+endp
+
+; Write the pCAL chunk (described in the PNG extensions document)
+;void (png_structrp png_ptr, charp purpose, int_32 X0,
+; int_32 X1, int type, int nparams, charp units, charpp params)
+align 4
+proc png_write_pCAL, png_ptr:dword, purpose:dword, X0:dword, X1:dword, type:dword,\
+ nparams:dword, units:dword, params:dword
+locals
+ purpose_len dd ? ;uint_32
+ units_len dd ?
+ total_len dd ? ;png_size_t
+ params_len dd ? ;png_size_tp
+ buf rb 10 ;byte[10]
+ new_purpose rb 80 ;byte[80]
+ i dd ? ;int
+endl
+pushad
+ png_debug1 1, 'in png_write_pCAL (%d parameters)', [nparams]
+ mov edi,[png_ptr]
+
+ cmp dword[type],PNG_EQUATION_LAST
+ jl @f ;if (..>=..)
+ png_error edi, 'Unrecognized equation type for pCAL chunk'
+ @@:
+
+ mov ebx,ebp
+ sub ebx,84 ;ebx = &new_purpose
+ stdcall png_check_keyword, edi, [purpose], ebx
+ mov [purpose_len],eax
+
+ test eax,eax
+ jnz @f ;if(..==0)
+ png_error edi, 'pCAL: invalid keyword'
+ @@:
+
+ inc dword[purpose_len] ; terminator
+
+ png_debug1 3, 'pCAL purpose length = %d', [purpose_len]
+; units_len = strlen(units) + (nparams == 0 ? 0 : 1);
+ png_debug1 3, 'pCAL units length = %d', [units_len]
+; total_len = purpose_len + units_len + 10;
+
+; params_len = (png_size_tp)png_malloc(png_ptr,
+; (png_alloc_size_t)(nparams * (sizeof (png_size_t))));
+
+ ; Find the length of each parameter, making sure we don't count the
+ ; null terminator for the last parameter.
+
+; for (i = 0; i < nparams; i++)
+; {
+; params_len[i] = strlen(params[i]) + (i == nparams - 1 ? 0 : 1);
+; png_debug2(3, "pCAL parameter %d length = %lu", i,
+; (unsigned long)params_len[i]);
+; total_len += params_len[i];
+; }
+
+ png_debug1 3, 'pCAL total length = %d', [total_len]
+ stdcall png_write_chunk_header, edi, png_pCAL, [total_len]
+ stdcall png_write_chunk_data, edi, ebx, [purpose_len]
+ mov ebx,ebp
+ sub ebx,94 ;ebx = &buf
+ stdcall png_save_int_32, ebx, [X0]
+ add ebx,4
+ stdcall png_save_int_32, ebx, [X1]
+ add ebx,4
+ mov eax,[type]
+ mov [ebx],al
+ inc ebx
+ mov eax,[nparams]
+ mov [ebx],al
+ sub ebx,9
+ stdcall png_write_chunk_data, edi, ebx, 10
+ stdcall png_write_chunk_data, edi, [units], [units_len]
+
+; for (i = 0; i < nparams; i++)
+; {
+; png_write_chunk_data(png_ptr, (bytep)params[i], params_len[i]);
+; }
+
+ stdcall png_free, edi, [params_len]
+ stdcall png_write_chunk_end, edi
+popad
+ ret
+endp
+
+; Write the sCAL chunk
+;void (png_structrp png_ptr, int unit, charp width, charp height)
+align 4
+proc png_write_sCAL_s uses eax ebx ecx edi esi, png_ptr:dword, unit:dword, width:dword, height:dword
+locals
+ total_len dd 2
+ wlen dd ?
+ hlen dd ?
+ buf rb 64 ;byte[64]
+endl
+ png_debug 1, 'in png_write_sCAL_s'
+
+ stdcall strlen,[width]
+ add [total_len],eax
+ mov [wlen],eax
+ stdcall strlen,[height]
+ add [total_len],eax
+ mov [hlen],eax
+
+ cmp dword[total_len],64
+ jle @f ;if (..>..)
+ cStr ,<'Can',39,'t write sCAL (buffer too small)'>
+ png_warning [png_ptr], eax
+ jmp .end_f
+ @@:
+
+ mov ebx,ebp
+ sub ebx,64
+ mov eax,[unit]
+ mov byte[ebx],al
+ mov ecx,[wlen]
+ inc ecx
+ mov edi,ebx
+ inc edi
+ mov esi,[width]
+ rep movsb ;Append the '\0' here
+ mov ecx,[hlen]
+ mov esi,[height]
+ rep movsb ;Do NOT append the '\0' here
+
+ png_debug1 3, 'sCAL total length = %u', [total_len]
+ stdcall png_write_complete_chunk, [png_ptr], png_sCAL, ebx, [total_len]
+.end_f:
+ ret
+endp
+
+; Write the pHYs chunk
+;void (png_structrp png_ptr, uint_32 x_pixels_per_unit,
+; uint_32 y_pixels_per_unit, int unit_type)
+align 4
+proc png_write_pHYs uses eax ebx, png_ptr:dword, x_pixels_per_unit:dword, y_pixels_per_unit:dword, unit_type:dword
+locals
+ buf rb 9 ;byte[9]
+endl
+ png_debug 1, 'in png_write_pHYs'
+
+ cmp dword[unit_type],PNG_RESOLUTION_LAST
+ jl @f ;if (..>=..)
+ png_warning [png_ptr], 'Unrecognized unit type for pHYs chunk'
+ @@:
+
+ mov ebx,ebp
+ sub ebx,9
+ stdcall png_save_uint_32, ebx, [x_pixels_per_unit]
+ add ebx,4
+ stdcall png_save_uint_32, ebx, [y_pixels_per_unit]
+ add ebx,4
+ mov al,byte[unit_type]
+ mov byte[ebx],al
+ sub ebx,8
+
+ stdcall png_write_complete_chunk, [png_ptr], png_pHYs, ebx, 9
+ ret
+endp
+
+; Write the tIME chunk. Use either png_convert_from_struct_tm()
+; or png_convert_from_time_t(), or fill in the structure yourself.
+
+;void (png_structrp png_ptr, png_const_timep mod_time)
+align 4
+proc png_write_tIME uses eax ebx ecx, png_ptr:dword, mod_time:dword
+locals
+ buf rb 7 ;byte[7]
+endl
+ png_debug 1, 'in png_write_tIME'
+
+ mov eax,[mod_time]
+ mov cl,[eax+png_time.month]
+ cmp cl,12
+ jg @f
+ cmp cl,1
+ jl @f
+ mov ch,[eax+png_time.day]
+ cmp ch,31
+ jg @f
+ cmp ch,1
+ jl @f
+ cmp byte[eax+png_time.hour],23
+ jg @f
+ cmp byte[eax+png_time.second],60
+ jg @f
+ jmp .end0
+ @@:
+ png_warning [png_ptr], 'Invalid time specified for tIME chunk'
+ jmp .end_f
+ .end0:
+
+ movzx ebx,word[eax+png_time.year]
+ push ebx
+ mov ebx,ebp
+ sub ebx,7
+ stdcall png_save_uint_16, ebx ;, year
+ add ebx,2
+ mov byte[ebx],cl ;month
+ inc ebx
+ mov byte[ebx],ch ;day
+ inc ebx
+ mov cl,[eax+png_time.hour]
+ mov byte[ebx],cl ;hour
+ inc ebx
+ mov cl,[eax+png_time.minute]
+ mov byte[ebx],cl ;minute
+ inc ebx
+ mov cl,[eax+png_time.second]
+ mov byte[ebx],cl ;second
+ sub ebx,6
+
+ stdcall png_write_complete_chunk, [png_ptr], png_tIME, ebx, 7
+.end_f:
+ ret
+endp
+
+if PNG_WRITE_INTERLACING_SUPPORTED eq 1
+ ; Arrays to facilitate easy interlacing - use pass (0 - 6) as index
+
+ ; Start of interlace block
+ png_pass_start db 0, 4, 0, 2, 0, 1, 0
+ ; Offset to next interlace block
+ png_pass_inc db 8, 8, 4, 4, 2, 2, 1
+ ; Start of interlace block in the y direction
+ png_pass_ystart db 0, 0, 4, 0, 2, 0, 1
+ ; Offset to next interlace block in the y direction
+ png_pass_yinc db 8, 8, 8, 4, 4, 2, 2
+end if
+
+; Initializes the row writing capability of libpng
+;void (png_structrp png_ptr)
+align 4
+proc png_write_start_row uses eax ebx ecx edx edi, png_ptr:dword
+locals
+ buf_size dd ? ;png_alloc_size_t
+ usr_pixel_depth dd ? ;int
+if PNG_WRITE_FILTER_SUPPORTED eq 1
+ filters db ? ;byte
+end if
+endl
+ png_debug 1, 'in png_write_start_row'
+
+ mov edi,[png_ptr]
+ movzx eax,byte[edi+png_struct.usr_channels]
+ movzx ebx,byte[edi+png_struct.usr_bit_depth]
+ imul eax,ebx
+ mov [usr_pixel_depth],eax
+ PNG_ROWBYTES eax,[edi+png_struct.width]
+ inc eax
+ mov [buf_size],eax
+
+ ; 1.5.6: added to allow checking in the row write code.
+ mov al,[edi+png_struct.pixel_depth]
+ mov [edi+png_struct.transformed_pixel_depth],al
+
+ mov eax,[usr_pixel_depth]
+ mov [edi+png_struct.maximum_pixel_depth],al
+
+ ; Set up row buffer
+ stdcall png_malloc, edi, [buf_size]
+ mov [edi+png_struct.row_buf],eax
+
+ mov byte[eax],PNG_FILTER_VALUE_NONE
+
+if PNG_WRITE_FILTER_SUPPORTED eq 1
+ mov al,byte[edi+png_struct.do_filter]
+
+ cmp dword[edi+png_struct.height],1
+ jne @f ;if (..==1)
+ and al, 0xff and not(PNG_FILTER_UP or PNG_FILTER_AVG or PNG_FILTER_PAETH)
+ @@:
+ cmp dword[edi+png_struct.width],1
+ jne @f ;if (..==1)
+ and al, 0xff and not(PNG_FILTER_SUB or PNG_FILTER_AVG or PNG_FILTER_PAETH)
+ @@:
+
+ cmp al,0
+ jne @f ;if (..==0)
+ mov al,PNG_FILTER_NONE
+ @@:
+
+ mov [filters],al
+ mov byte[edi+png_struct.do_filter],al
+
+ ;mov al,[filters]
+ and al,PNG_FILTER_SUB or PNG_FILTER_UP or PNG_FILTER_AVG or PNG_FILTER_PAETH
+ cmp al,0
+ je .end0
+ cmp dword[edi+png_struct.try_row],0
+ jne .end0 ;if (..!=0) && ..==0)
+ xor ebx,ebx
+
+ stdcall png_malloc, edi, [buf_size]
+ mov dword[edi+png_struct.try_row],eax
+
+ mov al,[filters]
+ and al,PNG_FILTER_SUB
+ cmp al,0
+ je @f
+ inc ebx
+ @@:
+ mov al,[filters]
+ and al,PNG_FILTER_UP
+ cmp al,0
+ je @f
+ inc ebx
+ @@:
+ mov al,[filters]
+ and al,PNG_FILTER_AVG
+ cmp al,0
+ je @f
+ inc ebx
+ @@:
+ mov al,[filters]
+ and al,PNG_FILTER_PAETH
+ cmp al,0
+ je @f
+ inc ebx
+ @@:
+ cmp ebx,1
+ jle .end0 ;if (..>1)
+ stdcall png_malloc, edi, [buf_size]
+ mov dword[edi+png_struct.tst_row],eax
+ .end0:
+
+ ; We only need to keep the previous row if we are using one of the following
+ ; filters.
+
+ mov al,[filters]
+ and al,PNG_FILTER_AVG or PNG_FILTER_UP or PNG_FILTER_PAETH
+ cmp al,0
+ je @f ;if (..!=0)
+ stdcall png_calloc, edi, [buf_size]
+ mov dword[edi+png_struct.prev_row],eax
+ @@:
+end if ;WRITE_FILTER
+
+if PNG_WRITE_INTERLACING_SUPPORTED eq 1
+ ; If interlaced, we need to set up width and height of pass
+ cmp byte[edi+png_struct.interlaced],0
+ je @f
+ mov eax,[edi+png_struct.transformations]
+ and eax,PNG_INTERLACE
+ jnz @f ;if(..!=0 && ..==0)
+ movzx ecx,byte[png_pass_yinc]
+ mov eax,[edi+png_struct.height]
+ add eax,ecx
+ dec eax
+ movzx edx,byte[png_pass_ystart]
+ sub eax,edx
+ xor edx,edx
+ div ecx
+ mov [edi+png_struct.num_rows],eax
+
+ movzx ecx,byte[png_pass_inc]
+ mov eax,[edi+png_struct.width]
+ add eax,ecx
+ dec eax
+ movzx edx,byte[png_pass_start]
+ sub eax,edx
+ xor edx,edx
+ div ecx
+ mov [edi+png_struct.usr_width],eax
+ jmp .end1
+ @@: ;else
+end if
+ mov eax,[edi+png_struct.height]
+ mov [edi+png_struct.num_rows],eax
+ mov eax,[edi+png_struct.width]
+ mov [edi+png_struct.usr_width],eax
+ .end1:
+ ret
+endp
+
+; Internal use only. Called when finished processing a row of data.
+;void (png_structrp png_ptr)
+align 4
+proc png_write_finish_row uses eax ecx edx edi, png_ptr:dword
+ png_debug 1, 'in png_write_finish_row'
+
+ mov edi,[png_ptr]
+ ; Next row
+ inc dword[edi+png_struct.row_number]
+
+ ; See if we are done
+ mov eax,[edi+png_struct.row_number]
+ cmp eax,[edi+png_struct.num_rows]
+ jl .end_f ;if (..<..) return
+
+if PNG_WRITE_INTERLACING_SUPPORTED eq 1
+ ; If interlaced, go to next pass
+ cmp byte[edi+png_struct.interlaced],0
+ je .end0 ;if (..!=0)
+ mov dword[edi+png_struct.row_number],0
+ mov eax,[edi+png_struct.transformations]
+ and eax,PNG_INTERLACE
+ jz @f ;if (..!=0)
+ inc byte[edi+png_struct.pass]
+ jmp .end1
+ @@: ;else
+ ; Loop until we find a non-zero width or height pass
+ .cycle0: ;do
+ inc byte[edi+png_struct.pass]
+ cmp byte[edi+png_struct.pass],7
+ jge .cycle0end ;if (..>=..) break
+
+ movzx ecx,byte[edi+png_struct.pass]
+ add ecx,png_pass_inc
+ movzx ecx,byte[ecx]
+ mov eax,[edi+png_struct.width]
+ add eax,ecx
+ dec eax
+ movzx edx,byte[edi+png_struct.pass]
+ add edx,png_pass_start
+ movzx edx,byte[edx]
+ sub eax,edx
+ xor edx,edx
+ div ecx
+ mov [edi+png_struct.usr_width],eax
+
+ movzx ecx,byte[edi+png_struct.pass]
+ add ecx,png_pass_yinc
+ movzx ecx,byte[ecx]
+ mov eax,[edi+png_struct.height]
+ add eax,ecx
+ dec eax
+ movzx edx,byte[edi+png_struct.pass]
+ add edx,png_pass_ystart
+ movzx edx,byte[edx]
+ sub eax,edx
+ xor edx,edx
+ div ecx
+ mov [edi+png_struct.num_rows],eax
+
+ mov eax,[edi+png_struct.transformations]
+ and eax,PNG_INTERLACE
+ jnz .cycle0end ;if(..!=0) break
+
+ cmp dword[edi+png_struct.usr_width],0
+ je .cycle0
+ cmp dword[edi+png_struct.num_rows],0
+ je .cycle0
+ .cycle0end: ;while (..==0 || ..==0)
+ .end1:
+
+ ; Reset the row above the image for the next pass
+ cmp byte[edi+png_struct.pass],7
+ jge .end0 ;if (..<..)
+ cmp dword[edi+png_struct.prev_row],0
+ je .end_f ;if (..!=0)
+ movzx eax,byte[edi+png_struct.usr_channels]
+ movzx edx,byte[edi+png_struct.usr_bit_depth]
+ imul eax,edx
+ PNG_ROWBYTES eax, [edi+png_struct.width]
+ inc eax
+ push edi
+ mov ecx,eax
+ xor eax,eax
+ mov edi,[edi+png_struct.prev_row]
+ rep stosb ;memset(...
+ pop edi
+ jmp .end_f
+ .end0:
+end if
+
+ ; If we get here, we've just written the last row, so we need
+ ; to flush the compressor
+ stdcall png_compress_IDAT, 0, 0, Z_FINISH
+.end_f:
+ ret
+endp
+
+; Pick out the correct pixels for the interlace pass.
+; The basic idea here is to go through the row with a source
+; pointer and a destination pointer (sp and dp), and copy the
+; correct pixels for the pass. As the row gets compacted,
+; sp will always be >= dp, so we should never overwrite anything.
+; See the default: case for the easiest code to understand.
+
+;void (png_row_infop row_info, bytep row, int pass)
+align 4
+proc png_do_write_interlace, row_info:dword, row:dword, pass:dword
+ png_debug 1, 'in png_do_write_interlace'
+
+ ; We don't have to do anything on the last pass (6)
+ cmp dword[pass],6
+ jge .end_f ;if (..<..)
+ ; Each pixel depth is handled separately
+; switch (row_info->pixel_depth)
+; {
+; case 1:
+; {
+; bytep sp;
+; bytep dp;
+; unsigned int shift;
+; int d;
+; int value;
+; uint_32 i;
+; uint_32 row_width = row_info->width;
+
+; dp = row;
+; d = 0;
+; shift = 7;
+
+; for (i = png_pass_start[pass]; i < row_width;
+; i += png_pass_inc[pass])
+; {
+; sp = row + (png_size_t)(i >> 3);
+; value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01;
+; d |= (value << shift);
+
+; if (shift == 0)
+; {
+; shift = 7;
+; *dp++ = (byte)d;
+; d = 0;
+; }
+
+; else
+; shift--;
+
+; }
+; if (shift != 7)
+; *dp = (byte)d;
+
+; break;
+; }
+
+; case 2:
+; {
+; bytep sp;
+; bytep dp;
+; unsigned int shift;
+; int d;
+; int value;
+; uint_32 i;
+; uint_32 row_width = row_info->width;
+
+; dp = row;
+; shift = 6;
+; d = 0;
+
+; for (i = png_pass_start[pass]; i < row_width;
+; i += png_pass_inc[pass])
+; {
+; sp = row + (png_size_t)(i >> 2);
+; value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03;
+; d |= (value << shift);
+
+; if (shift == 0)
+; {
+; shift = 6;
+; *dp++ = (byte)d;
+; d = 0;
+; }
+
+; else
+; shift -= 2;
+; }
+; if (shift != 6)
+; *dp = (byte)d;
+
+; break;
+; }
+
+; case 4:
+; {
+; bytep sp;
+; bytep dp;
+; unsigned int shift;
+; int d;
+; int value;
+; uint_32 i;
+; uint_32 row_width = row_info->width;
+
+; dp = row;
+; shift = 4;
+; d = 0;
+; for (i = png_pass_start[pass]; i < row_width;
+; i += png_pass_inc[pass])
+; {
+; sp = row + (png_size_t)(i >> 1);
+; value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f;
+; d |= (value << shift);
+
+; if (shift == 0)
+; {
+; shift = 4;
+; *dp++ = (byte)d;
+; d = 0;
+; }
+
+; else
+; shift -= 4;
+; }
+; if (shift != 4)
+; *dp = (byte)d;
+
+; break;
+; }
+
+; default:
+; {
+; bytep sp;
+; bytep dp;
+; uint_32 i;
+; uint_32 row_width = row_info->width;
+; png_size_t pixel_bytes;
+
+ ; Start at the beginning
+; dp = row;
+
+ ; Find out how many bytes each pixel takes up
+; pixel_bytes = (row_info->pixel_depth >> 3);
+
+ ; Loop through the row, only looking at the pixels that matter
+; for (i = png_pass_start[pass]; i < row_width;
+; i += png_pass_inc[pass])
+; {
+ ; Find out where the original pixel is
+; sp = row + (png_size_t)i * pixel_bytes;
+
+ ; Move the pixel
+; if (dp != sp)
+; memcpy(dp, sp, pixel_bytes);
+
+ ; Next pixel
+; dp += pixel_bytes;
+; }
+; break;
+; }
+; }
+ ; Set new row width
+; row_info->width = (row_info->width +
+; png_pass_inc[pass] - 1 -
+; png_pass_start[pass]) /
+; png_pass_inc[pass];
+
+; row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
+; row_info->width);
+.end_f:
+ ret
+endp
+
+; This filters the row, chooses which filter to use, if it has not already
+; been specified by the application, and then writes the row out with the
+; chosen filter.
+
+;void png_write_filtered_row(png_structrp png_ptr, bytep filtered_row,
+; png_size_t row_bytes);
+
+;png_size_t (png_structrp png_ptr, const uint_32 bpp, const png_size_t row_bytes, const png_size_t lmins)
+align 4
+proc png_setup_sub_row uses ebx ecx edx edi esi, png_ptr:dword, bpp:dword, row_bytes:dword, lmins:dword
+ mov ebx,[png_ptr]
+ mov edi,[ebx+png_struct.try_row]
+ mov byte[edi],PNG_FILTER_VALUE_SUB
+
+ mov ecx,[bpp]
+ inc edi
+ mov esi,[ebx+png_struct.row_buf]
+ inc esi
+ xor eax,eax
+ xor edx,edx
+ .cycle0:
+ lodsb
+ stosb
+ png_setup_abs edx
+ loop .cycle0
+
+ mov ecx,[row_bytes]
+ sub ecx,[bpp]
+ mov ebx,[ebx+png_struct.row_buf]
+ inc ebx
+ .cycle1:
+ lodsb
+ sub al,byte[ebx]
+ stosb
+ png_setup_abs edx
+ cmp edx,[lmins]
+ jg .cycle1end ;if (..>..) ;We are already worse, don't continue.
+ inc ebx
+ loop .cycle1
+ .cycle1end:
+ mov eax,edx
+ ret
+endp
+
+;void (png_structrp png_ptr, const uint_32 bpp, const png_size_t row_bytes)
+align 4
+proc png_setup_sub_row_only, png_ptr:dword, bpp:dword, row_bytes:dword
+pushad
+ mov ebx,[png_ptr]
+ mov edi,[ebx+png_struct.try_row]
+ mov byte[edi],PNG_FILTER_VALUE_SUB
+
+ mov ecx,[bpp]
+ inc edi
+ mov esi,[ebx+png_struct.row_buf]
+ inc esi
+ rep movsb
+
+ mov ecx,[row_bytes]
+ sub ecx,[bpp]
+ mov edx,[ebx+png_struct.row_buf]
+ inc edx
+align 4
+ .cycle0:
+ lodsb
+ sub al,byte[edx]
+ stosb
+ inc edx
+ loop .cycle0
+popad
+ ret
+endp
+
+;png_size_t (png_structrp png_ptr, const png_size_t row_bytes, const png_size_t lmins)
+align 4
+proc png_setup_up_row uses ebx ecx edx edi esi, png_ptr:dword, row_bytes:dword, lmins:dword
+ mov ebx,[png_ptr]
+ mov edi,[ebx+png_struct.try_row]
+ mov byte[edi],PNG_FILTER_VALUE_UP
+
+ mov ecx,[row_bytes]
+ inc edi
+ mov esi,[ebx+png_struct.row_buf]
+ inc esi
+ mov ebx,[ebx+png_struct.prev_row]
+ inc ebx
+ xor edx,edx
+ .cycle0:
+ lodsb
+ sub al,byte[ebx]
+ stosb
+ png_setup_abs edx
+ cmp edx,[lmins]
+ jg .cycle0end ;if (..>..) ;We are already worse, don't continue.
+ inc ebx
+ loop .cycle0
+ .cycle0end:
+ mov eax,edx
+ ret
+endp
+
+;void (png_structrp png_ptr, const png_size_t row_bytes)
+align 4
+proc png_setup_up_row_only, png_ptr:dword, row_bytes:dword
+pushad
+ mov ebx,[png_ptr]
+ mov edi,[ebx+png_struct.try_row]
+ mov byte[edi],PNG_FILTER_VALUE_UP
+
+ mov ecx,[row_bytes]
+ inc edi
+ mov esi,[ebx+png_struct.row_buf]
+ inc esi
+ mov ebx,[ebx+png_struct.prev_row]
+ inc ebx
+ .cycle0:
+ lodsb
+ sub al,byte[ebx]
+ stosb
+ inc ebx
+ loop .cycle0
+popad
+ ret
+endp
+
+;png_size_t (png_structrp png_ptr, const uint_32 bpp, const png_size_t row_bytes, const png_size_t lmins)
+align 4
+proc png_setup_avg_row uses ebx ecx edx edi esi, png_ptr:dword, bpp:dword, row_bytes:dword, lmins:dword
+locals
+ sum dd 0 ;png_size_t
+endl
+ mov ebx,[png_ptr]
+ mov edi,[ebx+png_struct.try_row]
+ mov byte[edi],PNG_FILTER_VALUE_AVG
+
+ mov ecx,[bpp]
+ inc edi
+ mov esi,[ebx+png_struct.row_buf]
+ inc esi
+ mov ebx,[ebx+png_struct.prev_row]
+ inc ebx
+ .cycle0:
+ lodsb
+ mov ah,byte[ebx]
+ shr ah,1
+ sub al,ah
+ stosb
+ png_setup_abs dword[sum]
+ inc ebx
+ loop .cycle0
+
+ mov ecx,[row_bytes]
+ sub ecx,[bpp]
+ mov eax,[png_ptr]
+ mov edx,[eax+png_struct.row_buf]
+ inc edx
+ .cycle1:
+ lodsb
+ shl eax,24
+ movzx ax,byte[ebx]
+ add al,byte[edx]
+ jnc @f
+ mov ah,1
+ @@:
+ shr ax,1
+ rol eax,8
+ sub al,ah
+ stosb
+ png_setup_abs dword[sum]
+ mov eax,[sum]
+ cmp eax,[lmins]
+ jg .cycle1end ;if (..>..) ;We are already worse, don't continue.
+ inc ebx
+ inc edx
+ loop .cycle1
+ .cycle1end:
+ mov eax,[sum]
+ ret
+endp
+
+;void (png_structrp png_ptr, const uint_32 bpp, const png_size_t row_bytes)
+align 4
+proc png_setup_avg_row_only, png_ptr:dword, bpp:dword, row_bytes:dword
+pushad
+ mov ebx,[png_ptr]
+ mov edi,[ebx+png_struct.try_row]
+ mov byte[edi],PNG_FILTER_VALUE_AVG
+
+ mov ecx,[bpp]
+ inc edi
+ mov esi,[ebx+png_struct.row_buf]
+ inc esi
+ mov ebx,[ebx+png_struct.prev_row]
+ inc ebx
+ .cycle0:
+ lodsb
+ mov ah,byte[ebx]
+ shr ah,1
+ sub al,ah
+ stosb
+ inc ebx
+ loop .cycle0
+
+ mov ecx,[row_bytes]
+ sub ecx,[bpp]
+ mov eax,[png_ptr]
+ mov edx,[eax+png_struct.row_buf]
+ inc edx
+ .cycle1:
+ lodsb
+ mov ah,byte[ebx]
+ shr ah,1
+ sub al,ah
+ mov ah,byte[edx]
+ shr ah,1
+ sub al,ah
+ stosb
+ inc ebx
+ inc edx
+ loop .cycle1
+popad
+ ret
+endp
+
+;png_size_t (png_structrp png_ptr, const uint_32 bpp,
+; const png_size_t row_bytes, const png_size_t lmins)
+align 4
+proc png_setup_paeth_row uses ebx ecx edx edi esi, png_ptr:dword, bpp:dword, row_bytes:dword, lmins:dword
+locals
+ pp dd ?
+ sum dd ?
+ v dd ?
+ lp dd ?
+ cp dd ?
+ a dd ?
+ b dd ?
+ c dd ?
+ p dd ?
+ pa dd ?
+ pb dd ?
+ pc dd ?
+endl
+ ;ecx - i
+ ;edi - dp
+ ;esi - rp
+ mov dword[sum],0
+ mov ebx,[png_ptr]
+ mov eax,[ebx+png_struct.try_row]
+ mov byte[eax],PNG_FILTER_VALUE_PAETH
+ xor ecx,ecx
+ mov esi,[ebx+png_struct.row_buf]
+ inc esi
+ mov edi,[ebx+png_struct.try_row]
+ inc edi
+ mov eax,[ebx+png_struct.prev_row]
+ inc eax
+ mov [pp],eax
+ jmp @f
+
+align 4
+.cycle0:
+ inc ecx
+ @@:
+ cmp ecx,[bpp]
+ jae .cycle0end
+ lodsb
+ mov edx,[pp]
+ movzx edx,byte[edx]
+ sub al,dl
+ stosb
+ and eax,0xff
+ mov [v],eax
+ inc dword[pp]
+ cmp eax,0x80
+ jge @f
+ add [sum],eax
+ jmp .cycle0
+ @@:
+ mov eax,0x100
+ sub eax,[v]
+ add [sum],eax
+ jmp .cycle0
+.cycle0end:
+
+ mov eax,[ebx+png_struct.row_buf]
+ inc eax
+ mov [lp],eax
+ mov eax,[ebx+png_struct.prev_row]
+ inc eax
+ mov [cp],eax
+ jmp @f
+
+align 4
+.cycle1:
+ inc ecx
+ @@:
+ cmp ecx,[row_bytes]
+ jae .cycle1end
+ mov eax,[pp]
+ movzx ebx,byte[eax]
+ mov [b],ebx
+ inc dword[pp]
+ mov eax,[cp]
+ movzx ebx,byte[eax]
+ mov [c],ebx
+ inc dword[cp]
+ mov eax,[lp]
+ movzx ebx,byte[eax]
+ mov [a],ebx
+ inc dword[lp]
+ mov eax,[b]
+ sub eax,[c]
+ mov [p],eax
+ mov ebx,[a]
+ sub ebx,[c]
+ mov [pc],ebx
+ mov eax,[p]
+ cmp eax,0
+ jge @f
+ neg eax
+ @@:
+ mov [pa],eax
+ mov eax,[pc]
+ cmp eax,0
+ jge @f
+ neg eax
+ @@:
+ mov [pb],eax
+ mov eax,[p]
+ add eax,[pc]
+ jns @f
+ neg eax
+ @@:
+ mov [pc],eax
+ mov eax,[pa]
+ cmp eax,[pb]
+ jg .end0
+ cmp eax,[pc]
+ jg .end0
+ mov eax,[a]
+ jmp .end1
+ .end0:
+ mov eax,[pb]
+ cmp eax,[pc]
+ jg .end2
+ mov eax,[b]
+ jmp .end1
+ .end2:
+ mov eax,[c]
+ .end1:
+ mov [p],eax
+ movzx eax,byte[esi]
+ sub eax,[p]
+ and eax,0xff
+ stosb
+ mov [v],eax
+ inc esi
+ cmp dword[v],0x80
+ jge .end3
+ mov eax,[v]
+ add [sum],eax
+ jmp .end4
+ .end3:
+ mov eax,0x100
+ sub eax,[v]
+ add [sum],eax
+ .end4:
+ mov eax,[sum]
+ cmp eax,[lmins] ;We are already worse, don't continue.
+ jbe .cycle1
+.cycle1end:
+ mov eax,[sum]
+ ret
+endp
+
+;void (png_structrp png_ptr, const uint_32 bpp, const png_size_t row_bytes)
+align 4
+proc png_setup_paeth_row_only, png_ptr:dword, bpp:dword, row_bytes:dword
+locals
+ pp dd ?
+ lp dd ?
+ cp dd ?
+ a dd ?
+ b dd ?
+ c dd ?
+ p dd ?
+ pa dd ?
+ pb dd ?
+ pc dd ?
+endl
+pushad
+ ;ecx - i
+ ;edi - dp
+ ;esi - rp
+ mov eax,[png_ptr]
+ mov ebx,[eax+png_struct.try_row]
+ mov byte[ebx],4
+ xor ecx,ecx
+ mov edx,[png_ptr]
+ mov eax,[edx+png_struct.row_buf]
+ inc eax
+ mov esi,eax
+ mov ebx,[png_ptr]
+ mov edx,[ebx+png_struct.try_row]
+ inc edx
+ mov edi,edx
+ mov eax,[png_ptr]
+ mov ebx,[eax+png_struct.prev_row]
+ inc ebx
+ mov [pp],ebx
+ jmp @f
+
+align 4
+.cycle0:
+ inc ecx
+ @@:
+ cmp ecx,[bpp]
+ jae .cycle0end
+ lodsb
+ mov ebx,[pp]
+ movzx ebx,byte[ebx]
+ sub al,bl
+ stosb
+ inc dword[pp]
+ jmp .cycle0
+.cycle0end:
+
+ mov eax,[png_ptr]
+ mov ebx,[eax+png_struct.row_buf]
+ inc ebx
+ mov [lp],ebx
+ mov edx,[png_ptr]
+ mov eax,[edx+png_struct.prev_row]
+ inc eax
+ mov [cp],eax
+ jmp @f
+
+align 4
+.cycle1:
+ inc ecx
+ @@:
+ cmp ecx,[row_bytes]
+ jae .cycle1end
+ mov eax,[pp]
+ movzx ebx,byte[eax]
+ mov [b],ebx
+ inc dword[pp]
+ mov eax,[cp]
+ movzx ebx,byte[eax]
+ mov [c],ebx
+ inc dword[cp]
+ mov eax,[lp]
+ movzx ebx,byte[eax]
+ mov [a],ebx
+ inc dword[lp]
+ mov eax,[b]
+ sub eax,[c]
+ mov [p],eax
+ mov ebx,[a]
+ sub ebx,[c]
+ mov [pc],ebx
+ mov eax,[p]
+ cmp eax,0
+ jge @f
+ neg eax
+ @@:
+ mov [pa],eax
+ mov eax,[pc]
+ cmp eax,0
+ jge @f
+ neg eax
+ @@:
+ mov [pb],eax
+ mov eax,[p]
+ add eax,[pc]
+ jns @f
+ neg eax
+ @@:
+ mov [pc],eax
+ mov eax,[pa]
+ cmp eax,[pb]
+ jg .end0
+ cmp eax,[pc]
+ jg .end0
+ mov eax,[a]
+ jmp .end1
+ .end0:
+ mov eax,[pb]
+ cmp eax,[pc]
+ jg .end2
+ mov eax,[b]
+ jmp .end1
+ .end2:
+ mov eax,[c]
+ .end1:
+ mov [p],eax
+ movzx eax,byte[esi]
+ sub eax,[p]
+ and eax,0xff
+ stosb
+ inc esi
+ jmp .cycle1
+.cycle1end:
+popad
+ ret
+endp
+
+;void (png_structrp png_ptr, png_row_infop row_info)
+align 4
+proc png_write_find_filter, png_ptr:dword, row_info:dword
+locals
+ filter_to_do dd ? ;unsigned int ;= png_ptr->do_filter
+ row_buf dd ? ;bytep
+ best_row dd ? ;bytep
+ bpp dd ? ;uint_32
+ mins dd ? ;png_size_t
+ row_bytes dd ? ;png_size_t ;= row_info->rowbytes
+endl
+pushad
+ mov edi,[png_ptr]
+if PNG_WRITE_FILTER_SUPPORTED eq 0
+ mov eax,[edi+png_struct.rowbytes]
+ inc eax
+ stdcall png_write_filtered_row, edi, [edi+png_struct.row_buf], eax
+else
+ mov esi,[row_info]
+ movzx eax,byte[edi+png_struct.do_filter]
+ mov [filter_to_do],eax
+ mov eax,[esi+png_row_info.rowbytes]
+ mov [row_bytes],eax
+
+ png_debug 1, 'in png_write_find_filter'
+
+ ; Find out how many bytes offset each pixel is
+ movzx eax,byte[edi+png_struct.pixel_depth]
+ add eax,7
+ shr eax,3
+ mov [bpp],eax
+
+ mov eax,[edi+png_struct.row_buf]
+ mov [row_buf],eax
+ mov dword[mins], PNG_SIZE_MAX - 256 ;so we can detect potential overflow of the
+ ;running sum
+
+; The prediction method we use is to find which method provides the
+; smallest value when summing the absolute values of the distances
+; from zero, using anything >= 128 as negative numbers. This is known
+; as the "minimum sum of absolute differences" heuristic. Other
+; heuristics are the "weighted minimum sum of absolute differences"
+; (experimental and can in theory improve compression), and the "zlib
+; predictive" method (not implemented yet), which does test compressions
+; of lines using different filter methods, and then chooses the
+; (series of) filter(s) that give minimum compressed data size (VERY
+; computationally expensive).
+
+; GRR 980525: consider also
+
+; (1) minimum sum of absolute differences from running average (i.e.,
+; keep running sum of non-absolute differences & count of bytes)
+; [track dispersion, too? restart average if dispersion too large?]
+
+; (1b) minimum sum of absolute differences from sliding average, probably
+; with window size <= deflate window (usually 32K)
+
+; (2) minimum sum of squared differences from zero or running average
+; (i.e., ~ root-mean-square approach)
+
+
+
+; We don't need to test the 'no filter' case if this is the only filter
+; that has been chosen, as it doesn't actually do anything to the data.
+
+ mov eax,[edi+png_struct.row_buf]
+ mov [best_row],eax
+
+ cmp dword[row_bytes],PNG_SIZE_MAX/128
+ jl @f ;if (..>=..)
+ ; Overflow can occur in the calculation, just select the lowest set
+ ; filter.
+
+ xor eax,eax
+ sub eax,[filter_to_do]
+ and [filter_to_do],eax
+ jmp .end0
+ @@:
+ mov eax,[filter_to_do]
+ and eax,PNG_FILTER_NONE
+ jz .end0
+ cmp dword[filter_to_do],PNG_FILTER_NONE
+ je .end0 ;else if (..!=0 && ..!=..)
+ ; Overflow not possible and multiple filters in the list, including the
+ ; 'none' filter.
+
+ push esi
+ xor eax,eax
+ xor ebx,ebx
+ mov ecx,[row_bytes]
+ mov esi,[row_buf]
+ .cycle0:
+ lodsb
+ png_setup_abs ebx
+ loop .cycle0
+ pop esi
+ mov [mins],ebx
+ .end0:
+
+ ; Sub filter
+ mov eax,[filter_to_do]
+ cmp eax,PNG_FILTER_SUB
+ jne @f ;if (..==..)
+ ; It's the only filter so no testing is needed
+ stdcall png_setup_sub_row_only, edi, [bpp], [row_bytes]
+ mov eax,[edi+png_struct.try_row]
+ mov [best_row],eax
+ jmp .end1
+ @@:
+ and eax,PNG_FILTER_SUB
+ jz .end1 ;else if (..!=0)
+ stdcall png_setup_sub_row, edi, [bpp], [row_bytes], [mins]
+ cmp eax,[mins]
+ jge .end1 ;if (..<..)
+ mov [mins],eax
+ mov eax,[edi+png_struct.try_row]
+ mov [best_row],eax
+ test eax,eax
+ jz .end1 ;if (..!=0)
+ mov eax,[edi+png_struct.tst_row]
+ mov [edi+png_struct.try_row],eax
+ mov eax,[best_row]
+ mov [edi+png_struct.tst_row],eax
+ .end1:
+
+ ; Up filter
+ mov eax,[filter_to_do]
+ cmp eax,PNG_FILTER_UP
+ jne @f ;if (..==..)
+ ; It's the only filter so no testing is needed
+ stdcall png_setup_up_row_only, edi, [row_bytes]
+ mov eax,[edi+png_struct.try_row]
+ mov [best_row],eax
+ jmp .end2
+ @@:
+ and eax,PNG_FILTER_UP
+ jz .end2 ;else if (..!=0)
+ stdcall png_setup_up_row, edi, [row_bytes], [mins]
+ cmp eax,[mins]
+ jge .end2 ;if (..<..)
+ mov [mins],eax
+ mov eax,[edi+png_struct.try_row]
+ mov [best_row],eax
+ test eax,eax
+ jz .end2 ;if (..!=0)
+ mov eax,[edi+png_struct.tst_row]
+ mov [edi+png_struct.try_row],eax
+ mov eax,[best_row]
+ mov [edi+png_struct.tst_row],eax
+ .end2:
+
+ ; Avg filter
+ mov eax,[filter_to_do]
+ cmp eax,PNG_FILTER_AVG
+ jne @f ;if (..==..)
+ ; It's the only filter so no testing is needed
+ stdcall png_setup_avg_row_only, edi, [bpp], [row_bytes]
+ mov eax,[edi+png_struct.try_row]
+ mov [best_row],eax
+ jmp .end3
+ @@:
+ and eax,PNG_FILTER_AVG
+ jz .end3 ;else if (..!=0)
+ stdcall png_setup_avg_row, edi, [bpp], [row_bytes], [mins]
+ cmp eax,[mins]
+ jge .end3 ;if (..<..)
+ mov [mins],eax
+ mov eax,[edi+png_struct.try_row]
+ mov [best_row],eax
+ test eax,eax
+ jz .end3 ;if (..!=0)
+ mov eax,[edi+png_struct.tst_row]
+ mov [edi+png_struct.try_row],eax
+ mov eax,[best_row]
+ mov [edi+png_struct.tst_row],eax
+ .end3:
+
+ ; Paeth filter
+ mov eax,[filter_to_do]
+ cmp eax,PNG_FILTER_PAETH
+ jne @f ;if (..==..)
+ ; It's the only filter so no testing is needed
+ stdcall png_setup_paeth_row_only, edi, [bpp], [row_bytes]
+ mov eax,[edi+png_struct.try_row]
+ mov [best_row],eax
+ jmp .end4
+ @@:
+ and eax,PNG_FILTER_PAETH
+ jz .end4 ;else if (..!=0)
+ stdcall png_setup_paeth_row, edi, [bpp], [row_bytes], [mins]
+ cmp eax,[mins]
+ jge .end4 ;if (..<..)
+ mov [mins],eax
+ mov eax,[edi+png_struct.try_row]
+ mov [best_row],eax
+ test eax,eax
+ jz .end4 ;if (..!=0)
+ mov eax,[edi+png_struct.tst_row]
+ mov [edi+png_struct.try_row],eax
+ mov eax,[best_row]
+ mov [edi+png_struct.tst_row],eax
+ .end4:
+
+ ; Do the actual writing of the filtered row data from the chosen filter.
+ mov eax,[esi+png_row_info.rowbytes]
+ inc eax
+ stdcall png_write_filtered_row, edi, [best_row], eax
+end if ;WRITE_FILTER
+popad
+ ret
+endp
+
+
+; Do the actual writing of a previously filtered row.
+;void (png_structrp png_ptr, bytep filtered_row,
+; png_size_t full_row_length/*includes filter byte*/)
+align 4
+proc png_write_filtered_row uses eax ebx edi, png_ptr:dword, filtered_row:dword, full_row_length:dword
+ png_debug 1, 'in png_write_filtered_row'
+
+ mov eax,[filtered_row]
+ movzx eax,byte[eax]
+ png_debug1 2, 'filter = %d', eax
+
+ mov edi,[png_ptr]
+ stdcall png_compress_IDAT, [filtered_row], [full_row_length], Z_NO_FLUSH
+
+if PNG_WRITE_FILTER_SUPPORTED eq 1
+ ; Swap the current and previous rows
+ mov eax,[edi+png_struct.prev_row]
+ test eax,eax
+ jz @f ;if (..!=0)
+ ;eax = tptr
+ mov ebx,[edi+png_struct.row_buf]
+ mov [edi+png_struct.prev_row],ebx
+ mov [edi+png_struct.row_buf],eax
+ @@:
+end if ;WRITE_FILTER
+
+ ; Finish row - updates counters and flushes zlib if last row
+ stdcall png_write_finish_row, edi
+
+if PNG_WRITE_FLUSH_SUPPORTED eq 1
+ inc dword[edi+png_struct.flush_rows]
+
+ mov eax,[edi+png_struct.flush_dist]
+ cmp eax,0
+ jle @f
+ cmp [edi+png_struct.flush_rows],eax
+ jl @f ;if (..>0 && ..>=..)
+ stdcall png_write_flush, edi
+ @@:
+end if ;WRITE_FLUSH
+ ret
+endp
diff --git a/programs/develop/libraries/libs-dev/libimg/png/png.asm b/programs/develop/libraries/libs-dev/libimg/png/png.asm
index 0e720dfe9..3f04d5c6d 100644
--- a/programs/develop/libraries/libs-dev/libimg/png/png.asm
+++ b/programs/develop/libraries/libs-dev/libimg/png/png.asm
@@ -1,1145 +1,1145 @@
-;;================================================================================================;;
-;;//// png.asm //// (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 ;;
-;; 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 'libpng/png.asm'
-
-;;================================================================================================;;
-;;proc img.is.png _data, _length ;////////////////////////////////////////////////////////////////;;
-img.is.png:
-;;------------------------------------------------------------------------------------------------;;
-;? Determine if raw data could be decoded (is in PNG format) ;;
-;;------------------------------------------------------------------------------------------------;;
-;> _data = raw data as read from file/stream ;;
-;> _length = data length ;;
-;;------------------------------------------------------------------------------------------------;;
-;< eax = false / true ;;
-;;================================================================================================;;
-; test 1 (length of data)
- cmp dword [esp+8], 8
- jb .nope
-; test 2: signature
- mov eax, [esp+4]
- cmp dword [eax], 0x474E5089
- jne .nope
- cmp dword [eax+4], 0x0A1A0A0D
- je .yep
-
- .nope:
- xor eax, eax
- ret 8
-
- .yep:
- xor eax, eax
- inc eax
- ret 8
-;endp
-
-;;================================================================================================;;
-;;proc img.decode.png _data, _length, _options ;//////////////////////////////////////////////////;;
-img.decode.png:
- xor eax, eax ; .image = 0
- pushad
- mov ebp, esp
-.localsize = 29*4
-virtual at ebp - .localsize
-.width dd ?
-.height dd ?
-.bit_depth dd ?
-.color_type dd ?
-.bytes_per_pixel dd ?
-.scanline_len dd ?
-.bits_per_pixel dd ?
-.size_rest dd ?
-.cur_chunk_ptr dd ?
-.cur_chunk_size dd ?
-.allocated dd ?
-.paeth_a dd ?
-.paeth_b dd ?
-.paeth_c dd ?
-.paeth_pa dd ?
-.paeth_pb dd ?
-.paeth_pc dd ?
-.i dd ?
-.j dd ?
-; variables to handle interlace
-.row_distance dd ? ; diff between two consecutives rows in destination
-.col_distance dd ? ; summand for moving to next row in source
-.row_increment dd ?
-.col_increment dd ?
-.block_height dd ?
-.block_width dd ?
-.interlace db ? ; 0 if not interlaced, 1 if interlaced
-.row_increment_shift db ?
-.col_increment_shift db ?
-.shift db ? ; shift for current src byte
-.starting_row dd ?
-.starting_col dd ?
-.idat_read dd ?
- rb 1Ch
-.image dd ?
- rd 1
-.data dd ?
-.length dd ?
-.options dd ?
-end virtual
- push eax ; .idat_read = 0
- push eax ; .starting_col = 0
- push eax ; .starting_row = 0
- push eax ; .col_increment_shift, .row_increment_shift
- inc eax
- push eax ; .block_width
- push eax ; .block_height
- push eax ; .col_increment
- push eax ; .row_increment
- sub esp, .localsize-32
-; load deflate unpacker, if not yet
-; acquire mutex
-@@:
- push 1
- pop eax
- xchg [deflate_loader_mutex], eax ; 'xchg' has an implicit 'lock' prefix
- test eax, eax
- jz @f
- mcall 5, 1
- jmp @b
-@@:
- cmp [deflate_unpack2], __deflate_unpack2_import_name__
- jnz .deflate_loaded
-; do loading
- invoke dll.load, @IMPORT
- test eax, eax
- jz .deflate_loaded
- add esp, .localsize
- popad
- mov [deflate_loader_mutex], eax
- ret 12
-.deflate_loaded:
-; release mutex
- mov [deflate_loader_mutex], 0
-; ok, continue
- mov esi, [.data] ; esi -> data
- mov ecx, [.length] ; ecx = length
-; the signature has been already checked in img.is.png
- lodsd
- lodsd
- sub ecx, 8
- xor ebx, ebx ; no image allocated
-.chunks_loop:
- sub ecx, 12
- jc .eof
- lodsd ; chunk length
- bswap eax
- sub ecx, eax
- jc .eof
- push ecx ; save length of data rest
- xchg eax, ecx ; ecx = size of data in the chunk
- lodsd ; chunk type
- cmp eax, 'IHDR'
- jz .ihdr
- cmp eax, 'IDAT'
- jz .idat
- cmp eax, 'IEND'
- jz .iend
- cmp eax, 'PLTE'
- jz .palette
-; unrecognized chunk, ignore
- lea esi, [esi+ecx+4]
- pop ecx
- jmp .chunks_loop
-; IHDR chunk
-.ihdr:
- cmp ecx, 13
- jnz .invalid_chunk
- cmp [.image], 0
- jnz .invalid_chunk
-; read image characteristics
- lodsd
- bswap eax
- mov [.width], eax
- lodsd
- bswap eax
- mov [.height], eax
- xor eax, eax
- lea ebx, [eax+1]
- lodsb
- cmp al, 16
- ja .invalid_chunk
- test al, al
- jz .invalid_chunk
- lea edx, [eax-1]
- test al, dl
- jnz .invalid_chunk
- mov [.bit_depth], eax
- lodsb
- test al, not 7
- jnz .invalid_chunk
- mov [.color_type], eax
- lodsb
- test al, al
- jnz .invalid_chunk ; only compression method 0 is defined
- lodsb
- test al, al
- jnz .invalid_chunk ; only filtering method 0 is defined
- lodsb
- cmp al, 1
- ja .invalid_chunk ; only interlacing methods 0 and 1 are defined
- mov [.interlace], al
-; check for correctness and calculate bytes_per_pixel and scanline_len
- mov eax, [.bit_depth]
- mov edx, [.color_type]
- dec edx
- js .grayscale1
- dec edx
- jz .rgb1
- dec edx
- jz .palette1
- dec edx
- jz .grayscale_alpha1
- dec edx
- dec edx
- jnz .invalid_chunk
-.rgb_alpha1:
- inc ebx
-.rgb1:
- inc ebx
-.grayscale_alpha1:
- inc ebx
- cmp al, 8
- jb .invalid_chunk
- jmp @f
-.palette1:
- cmp al, 8
- ja .invalid_chunk
-.grayscale1:
-@@:
- mul ebx
- mov [.bits_per_pixel], eax
- add eax, 7
- shr eax, 3
- mov [.bytes_per_pixel], eax
-; allocate image
- push Image.bpp24
- pop eax
- cmp [.color_type], 2
- jz @f
- mov al, Image.bpp32
- cmp [.color_type], 6
- jz @f
- mov al, Image.bpp8i
-@@:
- stdcall img.create, [.width], [.height], eax
- test eax, eax
- jz .invalid_chunk
- mov [.image], eax
- jmp .next_chunk
-.invalid_chunk:
-.iend:
- pop ecx
-.eof:
- add esp, .localsize
- popad
- ret 12
-; PLTE chunk
-.palette:
- mov eax, [.image]
- test eax, eax
- jz .invalid_chunk
- cmp [.color_type], 3
- jz .copy_palette
-.ignore_chunk:
- add esi, ecx
-.next_chunk:
- lodsd
- pop ecx
- jmp .chunks_loop
-.copy_palette:
- mov edi, [eax + Image.Palette]
- xor eax, eax
- cmp ecx, 256*3
- ja .next_chunk
-@@:
- sub ecx, 3
- jz @f
- js .invalid_chunk
- lodsd
- dec esi
- bswap eax
- shr eax, 8
- stosd
- jmp @b
-@@:
- lodsd
- dec esi
- bswap eax
- shr eax, 8
- stosd
- jmp .next_chunk
-.idat:
- jecxz .next_chunk
- cmp [.idat_read], 0
- jnz @f
- lodsb
- inc [.idat_read]
- and al, 0xF
- cmp al, 8
- jnz .invalid_chunk
- dec ecx
- jz .next_chunk
-@@:
- cmp [.idat_read], 1
- jnz @f
- lodsb
- inc [.idat_read]
- test al, 20h
- jnz .invalid_chunk
- dec ecx
- jz .next_chunk
-@@:
- mov [.cur_chunk_ptr], esi
- mov [.cur_chunk_size], ecx
- pop [.length]
- push eax
- push esp
- push ebp
- push .deflate_callback
- call [deflate_unpack2]
- pop ecx
- test eax, eax
- jz .invalid_chunk
-; convert PNG unpacked data to RAW data
- mov esi, eax
- mov [.allocated], eax
- mov [.size_rest], ecx
-; unfilter and deinterlace
-; .interlace_pass, .starting_row and .starting_col have been already set to 0
-; .block_width, .block_height, .col_increment, .row_increment were set
-; to values for non-interlaced images; correct if necessary
- cmp [.interlace], 0
- jz .deinterlace_loop
- push 8
- pop eax
- mov [.row_increment], eax
- mov [.col_increment], eax
- mov [.block_height], eax
- mov [.block_width], eax
- mov [.row_increment_shift], 3
- mov [.col_increment_shift], 3
-.deinterlace_loop:
- mov edx, [.height]
- cmp edx, [.starting_row]
- jbe .deinterlace_next
- mov ebx, [.width]
- sub ebx, [.starting_col]
- jbe .deinterlace_next
- mov cl, [.col_increment_shift]
- add ebx, [.col_increment]
- dec ebx
- shr ebx, cl
- mov eax, [.bits_per_pixel]
- imul eax, ebx
- add eax, 7
- shr eax, 3
- mov [.scanline_len], eax
- shl ebx, cl
- mov [.col_distance], ebx
-; Unfilter
- mov ecx, [.size_rest]
- push esi
-.unfilter_loop_e:
- mov ebx, [.scanline_len]
- sub ecx, 1
- jc .unfilter_abort
- sub ecx, ebx
- jc .unfilter_abort
- movzx eax, byte [esi]
- add esi, 1
- cmp eax, 4
- ja .next_scanline
- jmp dword [@f + eax*4]
-align 4
-@@:
- dd .unfilter_none
- dd .unfilter_sub
- dd .unfilter_up
- dd .unfilter_average
- dd .unfilter_paeth
-.unfilter_sub:
- mov edi, [.bytes_per_pixel]
- add esi, edi
- sub ebx, edi
- jbe .next_scanline
- neg edi
-@@:
- mov al, [esi+edi]
- add [esi], al
- add esi, 1
- sub ebx, 1
- jnz @b
- jmp .next_scanline
-.unfilter_up:
- cmp edx, [.height]
- jz .unfilter_none
- lea edi, [ebx+1]
- neg edi
-@@:
- mov al, [esi+edi]
- add [esi], al
- add esi, 1
- sub ebx, 1
- jnz @b
- jmp .next_scanline
-.unfilter_average:
- mov edi, [.bytes_per_pixel]
- cmp edx, [.height]
- jz .unfilter_average_firstline
- push edx
- lea edx, [ebx+1]
- neg edx
- sub ebx, edi
-@@:
- mov al, [esi+edx]
- shr al, 1
- add [esi], al
- add esi, 1
- sub edi, 1
- jnz @b
- mov edi, [.bytes_per_pixel]
- neg edi
- test ebx, ebx
- jz .unfilter_average_done
-@@:
- mov al, [esi+edx]
- add al, [esi+edi]
- rcr al, 1
- add [esi], al
- add esi, 1
- sub ebx, 1
- jnz @b
-.unfilter_average_done:
- pop edx
- jmp .next_scanline
-.unfilter_average_firstline:
- mov edi, [.bytes_per_pixel]
- add esi, edi
- sub ebx, edi
- jbe .next_scanline
- neg edi
-@@:
- mov al, [esi+edi]
- shr al, 1
- add [esi], al
- add esi, 1
- sub ebx, 1
- jnz @b
- jmp .unfilter_none
-.unfilter_paeth:
- cmp edx, [.height]
- jz .unfilter_sub
- push edx
- lea edx, [ebx+1]
- mov edi, [.bytes_per_pixel]
- neg edx
- sub ebx, edi
-@@:
- mov al, [esi+edx]
- add [esi], al
- add esi, 1
- sub edi, 1
- jnz @b
- mov edi, [.bytes_per_pixel]
- neg edi
- test ebx, ebx
- jz .unfilter_paeth_done
- push ecx
-@@:
- push ebx
-; PaethPredictor(Raw(x-bpp) = a, Prior(x) = b, Prior(x-bpp) = c)
- movzx eax, byte [esi+edi]
- mov [.paeth_a], eax
- movzx ecx, byte [esi+edx]
- add edi, edx
- mov [.paeth_b], ecx
- add ecx, eax
- movzx eax, byte [esi+edi]
- mov [.paeth_c], eax
- sub ecx, eax ; ecx = a + b - c = p
-; calculate pa = abs(p-a), pb = abs(p-b), pc = abs(p-c)
- mov ebx, ecx
- sub ebx, eax ; ebx = p - c
- cmp ebx, 80000000h
- sbb eax, eax ; eax = (p < c) ? 0 : 0xFFFFFFF
- not eax ; eax = (p < c) ? 0xFFFFFFFF : 0
- and eax, ebx ; eax = (p < c) ? p - c : 0
- sub ebx, eax
- sub ebx, eax ; ebx = abs(p-c)
- mov [.paeth_pc], ebx
- mov ebx, ecx
- sub ebx, [.paeth_a]
- cmp ebx, 80000000h
- sbb eax, eax
- not eax
- and eax, ebx
- sub ebx, eax
- sub ebx, eax
- mov [.paeth_pa], ebx
- mov ebx, ecx
- sub ebx, [.paeth_b]
- cmp ebx, 80000000h
- sbb eax, eax
- not eax
- and eax, ebx
- sub ebx, eax
- sub ebx, eax
- ;mov [.paeth_pb], ebx
-; select closest value
- push edx
- mov edx, [.paeth_b]
- sub edx, [.paeth_a]
- sub ebx, [.paeth_pa]
- sbb ecx, ecx ; ecx = (pa > pb) ? 0xFFFFFFFF : 0
- sbb eax, eax ; eax = (pa > pb) ? 0xFFFFFFFF : 0
- and ecx, ebx ; ecx = (pa > pb) ? pb - pa : 0
- and eax, edx ; eax = (pa > pb) ? b - a : 0
- add ecx, [.paeth_pa] ; ecx = (pa > pb) ? pb : pa = min(pa,pb)
- add eax, [.paeth_a] ; eax = (pa > pb) ? b : a
- mov edx, [.paeth_c]
- sub edx, eax
- sub [.paeth_pc], ecx
- sbb ebx, ebx ; ebx = (min(pa,pb) <= pc) ? 0 : 0xFFFFFFFF
- and ebx, edx ; ebx = (min(pa,pb) <= pc) ? 0 : c - eax
- add eax, ebx
- pop edx
- add [esi], al
- pop ebx
- sub edi, edx
- add esi, 1
- sub ebx, 1
- jnz @b
- pop ecx
-.unfilter_paeth_done:
- pop edx
- jmp .next_scanline
-.unfilter_none:
- add esi, ebx
-.next_scanline:
- sub edx, [.row_increment]
- jc .unfilter_done
- cmp edx, [.starting_row]
- jbe .unfilter_done
- jmp .unfilter_loop_e
-.unfilter_abort:
- xor ecx, ecx
-.unfilter_done:
-; unfiltering done, now convert to raw data
-; with deinterlacing if needed
- pop esi
- mov ebx, [.image]
- mov eax, [.width]
- call img._.get_scanline_len
- mov [.row_distance], eax
- mov eax, [.row_increment]
- mul [.width]
- sub eax, [.col_distance]
- call img._.get_scanline_len
- mov [.col_distance], eax
- mov edi, [ebx + Image.Data]
- mov eax, [.starting_row]
- mul [.width]
- add eax, [.starting_col]
- call img._.get_scanline_len
- add edi, eax
- mov eax, ebx
- mov ebx, [.size_rest]
- mov [.size_rest], ecx
- mov edx, [.height]
- sub edx, [.starting_row]
- mov [.j], edx
- cmp [.color_type], 0
- jz .grayscale2
- cmp [.color_type], 2
- jz .rgb2
- cmp [.color_type], 3
- jz .palette2
- cmp [.color_type], 4
- jz .grayscale_alpha2
-.rgb_alpha2:
- cmp [.bit_depth], 16
- jz .rgb_alpha2_16bit
-.rgb_alpha2.next:
- sub ebx, 1
- jc .convert_done
- add esi, 1
- sub ebx, [.scanline_len]
- jc .convert_done
- mov ecx, [.width]
- sub ecx, [.starting_col]
- mov [.i], ecx
-.rgb_alpha2.extloop:
-
-macro init_block
-{
- push ebx
- mov eax, [.col_increment]
- mov edx, [.j]
- cmp edx, [.block_height]
- jb @f
- mov edx, [.block_height]
-@@:
- mov ebx, [.i]
- cmp ebx, [.block_width]
- jb @f
- mov ebx, [.block_width]
-@@:
-}
-
- init_block
- lea eax, [edi+eax*4]
- push eax
-.rgb_alpha2.innloop1:
- push edi
- mov ecx, ebx
-.rgb_alpha2.innloop2:
- mov al, [esi+2]
- mov [edi], al
- mov al, [esi+1]
- mov [edi+1], al
- mov al, [esi]
- mov [edi+2], al
- mov al, [esi+3]
- mov [edi+3], al
- add edi, 4
- dec ecx
- jnz .rgb_alpha2.innloop2
- pop edi
- add edi, [.row_distance]
- dec edx
- jnz .rgb_alpha2.innloop1
- pop edi ebx
- add esi, 4
- mov eax, [.col_increment]
- sub [.i], eax
- ja .rgb_alpha2.extloop
- add edi, [.col_distance]
- mov eax, [.row_increment]
- sub [.j], eax
- ja .rgb_alpha2.next
- jmp .convert_done
-.rgb_alpha2_16bit:
- sub ebx, 1
- jc .convert_done
- add esi, 1
- sub ebx, [.scanline_len]
- jc .convert_done
- mov ecx, [.width]
- sub ecx, [.starting_col]
- mov [.i], ecx
-.rgb_alpha2_16bit.loop:
- init_block
- lea eax, [edi+eax*4]
- push eax
-
-; convert 16 bit sample to 8 bit sample
-macro convert_16_to_8
-{
-local .l1,.l2
- xor ah, 0x80
- js .l1
- cmp al, ah
- adc al, 0
- jmp .l2
-.l1:
- cmp ah, al
- sbb al, 0
-.l2:
-}
-
-.rgb_alpha2_16bit.innloop1:
- push edi
- mov ecx, ebx
-.rgb_alpha2_16bit.innloop2:
- mov ax, [esi+4]
- convert_16_to_8
- mov [edi], al
- mov ax, [esi+2]
- convert_16_to_8
- mov [edi+1], al
- mov ax, [esi]
- convert_16_to_8
- mov [edi+2], al
- ;mov ax, [esi+6]
- ;convert_16_to_8
- ;mov [edi+3], al
- add edi, 4
- dec ecx
- jnz .rgb_alpha2_16bit.innloop2
- pop edi
- add edi, [.row_distance]
- dec edx
- jnz .rgb_alpha2_16bit.innloop1
- pop edi ebx
- add esi, 8
- mov eax, [.col_increment]
- sub [.i], eax
- ja .rgb_alpha2_16bit.loop
- add edi, [.col_distance]
- mov eax, [.row_increment]
- sub [.j], eax
- ja .rgb_alpha2_16bit
- jmp .convert_done
-.grayscale2:
- call .create_grayscale_palette
- cmp [.bit_depth], 16
- jz .grayscale2_16bit
-.palette2:
- cmp [.bit_depth], 1
- jz .palette2_1bit
- cmp [.bit_depth], 2
- jz .palette2_2bit
- cmp [.bit_depth], 4
- jz .palette2_4bit
-.palette2_8bit:
- sub ebx, 1
- jc .convert_done
- add esi, 1
- sub ebx, [.scanline_len]
- jc .convert_done
- mov ecx, [.width]
- sub ecx, [.starting_col]
- mov [.i], ecx
-.palette2_8bit.extloop:
- init_block
- add eax, edi
- push eax
- mov al, [esi]
- inc esi
-macro block_byte_innerloop extloop
-{
-local .l1
-.l1:
- mov ecx, ebx
- rep stosb
- sub edi, ebx
- add edi, [.row_distance]
- dec edx
- jnz .l1
- pop edi ebx
- mov eax, [.col_increment]
- sub [.i], eax
- ja extloop
- add edi, [.col_distance]
- mov eax, [.row_increment]
- sub [.j], eax
-}
- block_byte_innerloop .palette2_8bit.extloop
- ja .palette2_8bit
- jmp .convert_done
-.palette2_4bit:
- sub ebx, 1
- jc .convert_done
- add esi, 1
- sub ebx, [.scanline_len]
- jc .convert_done
- mov ecx, [.width]
- sub ecx, [.starting_col]
- mov [.i], ecx
- mov [.shift], 0
-.palette2_4bit.extloop:
- init_block
- add eax, edi
- push eax
- xor [.shift], 1
- jz .palette2_4bit.shifted
- mov al, [esi]
- inc esi
- shr al, 4
- jmp @f
-.palette2_4bit.shifted:
- mov al, [esi-1]
- and al, 0xF
-@@:
- block_byte_innerloop .palette2_4bit.extloop
- ja .palette2_4bit
- jmp .convert_done
-.palette2_2bit:
- sub ebx, 1
- jc .convert_done
- add esi, 1
- sub ebx, [.scanline_len]
- jc .convert_done
- mov ecx, [.width]
- sub ecx, [.starting_col]
- mov [.i], ecx
- mov [.shift], 0
-.palette2_2bit.extloop:
- init_block
- add eax, edi
- push eax
- mov cl, [.shift]
- sub cl, 2
- jns .palette2_2bit.shifted
- mov cl, 6
- mov al, [esi]
- inc esi
- shr al, cl
- jmp @f
-.palette2_2bit.shifted:
- mov al, [esi-1]
- shr al, cl
- and al, 3
-@@:
- mov [.shift], cl
- block_byte_innerloop .palette2_2bit.extloop
- ja .palette2_2bit
- jmp .convert_done
-.palette2_1bit:
- sub ebx, 1
- jc .convert_done
- add esi, 1
- sub ebx, [.scanline_len]
- jc .convert_done
- mov ecx, [.width]
- sub ecx, [.starting_col]
- mov [.i], ecx
- mov [.shift], 0
-.palette2_1bit.extloop:
- init_block
- add eax, edi
- push eax
- mov cl, [.shift]
- dec cl
- jns .palette2_1bit.shifted
- mov cl, 7
- mov al, [esi]
- inc esi
- shr al, cl
- jmp @f
-.palette2_1bit.shifted:
- mov al, [esi-1]
- shr al, cl
- and al, 1
-@@:
- mov [.shift], cl
- block_byte_innerloop .palette2_1bit.extloop
- ja .palette2_1bit
- jmp .convert_done
-.grayscale2_16bit:
- sub ebx, 1
- jc .convert_done
- add esi, 1
- sub ebx, [.scanline_len]
- jc .convert_done
- mov ecx, [.width]
- sub ecx, [.starting_col]
- mov [.i], ecx
-.grayscale2_16bit.extloop:
- init_block
- add eax, edi
- push eax
- mov ax, [esi]
- add esi, 2
- convert_16_to_8
- block_byte_innerloop .grayscale2_16bit.extloop
- ja .grayscale2_16bit
- jmp .convert_done
-.rgb2:
- cmp [.bit_depth], 16
- jz .rgb2_16bit
-.rgb2.next:
- sub ebx, 1
- jc .convert_done
- add esi, 1
- sub ebx, [.scanline_len]
- jc .convert_done
- mov ecx, [.width]
- sub ecx, [.starting_col]
- mov [.i], ecx
-.rgb2.extloop:
- init_block
- lea eax, [eax*3]
- add eax, edi
- push eax
-.rgb2.innloop1:
- push edi
- mov ecx, ebx
-.rgb2.innloop2:
- mov al, [esi+2]
- mov [edi], al
- mov al, [esi+1]
- mov [edi+1], al
- mov al, [esi]
- mov [edi+2], al
- add edi, 3
- dec ecx
- jnz .rgb2.innloop2
- pop edi
- add edi, [.row_distance]
- dec edx
- jnz .rgb2.innloop1
- pop edi ebx
- add esi, 3
- mov eax, [.col_increment]
- sub [.i], eax
- ja .rgb2.extloop
- add edi, [.col_distance]
- mov eax, [.row_increment]
- sub [.j], eax
- ja .rgb2.next
- jmp .convert_done
-.rgb2_16bit:
- sub ebx, 1
- jc .convert_done
- add esi, 1
- sub ebx, [.scanline_len]
- jc .convert_done
- mov ecx, [.width]
- sub ecx, [.starting_col]
- mov [.i], ecx
-.rgb2_16bit.extloop:
- init_block
- lea eax, [eax*3]
- add eax, edi
- push eax
-.rgb2_16bit.innloop1:
- push edi
- mov ecx, ebx
-.rgb2_16bit.innloop2:
- mov ax, [esi+4]
- convert_16_to_8
- mov [edi], al
- mov ax, [esi+2]
- convert_16_to_8
- mov [edi+1], al
- mov ax, [esi]
- convert_16_to_8
- mov [edi+2], al
- add edi, 3
- dec ecx
- jnz .rgb2_16bit.innloop2
- pop edi
- add edi, [.row_distance]
- dec edx
- jnz .rgb2_16bit.innloop1
- pop edi ebx
- add esi, 6
- mov eax, [.col_increment]
- sub [.i], eax
- ja .rgb2_16bit.extloop
- add edi, [.col_distance]
- mov eax, [.row_increment]
- sub [.j], eax
- ja .rgb2_16bit
- jmp .convert_done
-.grayscale_alpha2:
- call .create_grayscale_palette
- cmp [.bit_depth], 16
- jz .grayscale_alpha2_16bit
-.grayscale_alpha2.next:
- sub ebx, 1
- jc .convert_done
- add esi, 1
- sub ebx, [.scanline_len]
- jc .convert_done
- mov ecx, [.width]
- sub ecx, [.starting_col]
- mov [.i], ecx
-.grayscale_alpha2.extloop:
- init_block
- add eax, edi
- push eax
- mov al, [esi]
- add esi, 2
- block_byte_innerloop .grayscale_alpha2.extloop
- ja .grayscale_alpha2.next
- jmp .convert_done
-.grayscale_alpha2_16bit:
- sub ebx, 1
- jc .convert_done
- add esi, 1
- sub ebx, [.scanline_len]
- jc .convert_done
- mov ecx, [.width]
- sub ecx, [.starting_col]
- mov [.i], ecx
-.grayscale_alpha2_16bit.extloop:
- init_block
- add eax, edi
- push eax
- mov ax, [esi]
- add esi, 4
- convert_16_to_8
- block_byte_innerloop .grayscale_alpha2_16bit.extloop
- ja .grayscale_alpha2_16bit
-.convert_done:
-; next interlace pass
-.deinterlace_next:
- mov eax, [.block_width]
- cmp eax, [.block_height]
- jz .deinterlace_dec_width
- mov [.block_height], eax
- mov [.col_increment], eax
- dec [.col_increment_shift]
- mov [.starting_row], eax
- and [.starting_col], 0
- jmp .deinterlace_loop
-.deinterlace_dec_width:
- shr eax, 1
- jz .deinterlace_done
- mov [.block_width], eax
- mov [.starting_col], eax
- add eax, eax
- and [.starting_row], 0
- mov [.row_increment], eax
- bsf eax, eax
- mov [.row_increment_shift], al
- jmp .deinterlace_loop
-.deinterlace_done:
- mcall 68, 13, [.allocated]
- mov esi, [.cur_chunk_ptr]
- add esi, [.cur_chunk_size]
- push [.length]
- jmp .next_chunk
-
-.deflate_callback:
- mov ebp, [esp+4]
- mov ebx, [esp+8]
- xor eax, eax
- mov esi, [.cur_chunk_size]
- mov [ebx], esi
- test esi, esi
- jz .deflate_callback.ret
- mov eax, [.cur_chunk_ptr]
- mov ecx, [.length]
- add esi, eax
- mov [.cur_chunk_ptr], esi
- and [.cur_chunk_size], 0
-@@:
- sub ecx, 12
- jb .deflate_callback.ret
- cmp dword [esi+4+4], 'IDAT'
- jnz .deflate_callback.ret
- mov edx, [esi+4]
- bswap edx
- sub ecx, edx
- jb .deflate_callback.ret
- add esi, 4+8
- test edx, edx
- jz @b
- mov [.cur_chunk_size], edx
- mov [.cur_chunk_ptr], esi
- mov [.length], ecx
-.deflate_callback.ret:
- ret 8
-
-.create_grayscale_palette:
- push edi edx
- mov edi, [eax + Image.Palette]
- mov ecx, [.bit_depth]
- cmp cl, 16
- jnz @f
- mov cl, 8
-@@:
- push 1
- pop eax
- shl eax, cl
- xchg eax, ecx
- mov edx, 0x010101
- cmp al, 8
- jz .graypal_common
- mov edx, 0x111111
- cmp al, 4
- jz .graypal_common
- mov edx, 0x555555
- cmp al, 2
- jz .graypal_common
- mov edx, 0xFFFFFF
-.graypal_common:
- xor eax, eax
-@@:
- stosd
- add eax, edx
- loop @b
- pop edx edi
- ret
-;endp
-
-
-
-;;================================================================================================;;
-align 4
-proc img.encode.png uses ebx edx, _img:dword, _common:dword, _specific:dword
-;;------------------------------------------------------------------------------------------------;;
-;? Encode image into raw data in png format ;;
-;;------------------------------------------------------------------------------------------------;;
-;> [_img] = pointer to image ;;
-;> [_common] = format independent options ;;
-;> [_specific] = 0 / pointer to the structure of format specific options ;;
-;;------------------------------------------------------------------------------------------------;;
-;< eax = 0 / pointer to encoded data ;;
-;< ecx = error code / the size of encoded data ;;
-;;================================================================================================;;
-locals
- encoded_file rd 1
- encoded_file_size rd 1
- simag png_image
-endl
- mov ebx,[_img]
- mov eax,[ebx+Image.Type]
- cmp eax,Image.bpp24
- je @f
- mov ecx,LIBIMG_ERROR_BIT_DEPTH
- jmp .error
- @@:
-
- mov edx,ebp
- sub edx,sizeof.png_image
- mov dword[edx+png_image.version],PNG_IMAGE_VERSION
- mov ecx,[ebx+Image.Width]
- mov [edx+png_image.width],ecx ;Image width in pixels (columns)
- mov eax,[ebx+Image.Height]
- mov [edx+png_image.height],eax ;Image height in pixels (rows)
- mov dword[edx+png_image.format],PNG_COLOR_TYPE_RGB
- ;mov dword[edx+png_image.flags],PNG_IMAGE_FLAG_???
-
- imul ecx,3
- mov edi,ecx
- imul edi,[ebx+Image.Height]
- cmp edi,4096
- jge @f
- mov edi,4096 ;minimum memory size
- @@:
- mov [encoded_file_size],edi
- stdcall [mem.alloc],edi
- test eax,eax
- jnz @f
- mov ecx,LIBIMG_ERROR_OUT_OF_MEMORY
- jmp .error
- @@:
- mov [encoded_file],eax
- mov edi,edx
- sub edi,4
- stdcall png_image_write_to_memory, edx,eax,edi,0,[ebx+Image.Data],ecx,0
- mov eax,[encoded_file]
- mov ecx,[encoded_file_size]
- jmp .quit
-
-.error:
- xor eax,eax
-.quit:
- ret
+;;================================================================================================;;
+;;//// png.asm //// (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 ;;
+;; 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 'libpng/png.asm'
+
+;;================================================================================================;;
+;;proc img.is.png _data, _length ;////////////////////////////////////////////////////////////////;;
+img.is.png:
+;;------------------------------------------------------------------------------------------------;;
+;? Determine if raw data could be decoded (is in PNG format) ;;
+;;------------------------------------------------------------------------------------------------;;
+;> _data = raw data as read from file/stream ;;
+;> _length = data length ;;
+;;------------------------------------------------------------------------------------------------;;
+;< eax = false / true ;;
+;;================================================================================================;;
+; test 1 (length of data)
+ cmp dword [esp+8], 8
+ jb .nope
+; test 2: signature
+ mov eax, [esp+4]
+ cmp dword [eax], 0x474E5089
+ jne .nope
+ cmp dword [eax+4], 0x0A1A0A0D
+ je .yep
+
+ .nope:
+ xor eax, eax
+ ret 8
+
+ .yep:
+ xor eax, eax
+ inc eax
+ ret 8
+;endp
+
+;;================================================================================================;;
+;;proc img.decode.png _data, _length, _options ;//////////////////////////////////////////////////;;
+img.decode.png:
+ xor eax, eax ; .image = 0
+ pushad
+ mov ebp, esp
+.localsize = 29*4
+virtual at ebp - .localsize
+.width dd ?
+.height dd ?
+.bit_depth dd ?
+.color_type dd ?
+.bytes_per_pixel dd ?
+.scanline_len dd ?
+.bits_per_pixel dd ?
+.size_rest dd ?
+.cur_chunk_ptr dd ?
+.cur_chunk_size dd ?
+.allocated dd ?
+.paeth_a dd ?
+.paeth_b dd ?
+.paeth_c dd ?
+.paeth_pa dd ?
+.paeth_pb dd ?
+.paeth_pc dd ?
+.i dd ?
+.j dd ?
+; variables to handle interlace
+.row_distance dd ? ; diff between two consecutives rows in destination
+.col_distance dd ? ; summand for moving to next row in source
+.row_increment dd ?
+.col_increment dd ?
+.block_height dd ?
+.block_width dd ?
+.interlace db ? ; 0 if not interlaced, 1 if interlaced
+.row_increment_shift db ?
+.col_increment_shift db ?
+.shift db ? ; shift for current src byte
+.starting_row dd ?
+.starting_col dd ?
+.idat_read dd ?
+ rb 1Ch
+.image dd ?
+ rd 1
+.data dd ?
+.length dd ?
+.options dd ?
+end virtual
+ push eax ; .idat_read = 0
+ push eax ; .starting_col = 0
+ push eax ; .starting_row = 0
+ push eax ; .col_increment_shift, .row_increment_shift
+ inc eax
+ push eax ; .block_width
+ push eax ; .block_height
+ push eax ; .col_increment
+ push eax ; .row_increment
+ sub esp, .localsize-32
+; load deflate unpacker, if not yet
+; acquire mutex
+@@:
+ push 1
+ pop eax
+ xchg [deflate_loader_mutex], eax ; 'xchg' has an implicit 'lock' prefix
+ test eax, eax
+ jz @f
+ mcall 5, 1
+ jmp @b
+@@:
+ cmp [deflate_unpack2], __deflate_unpack2_import_name__
+ jnz .deflate_loaded
+; do loading
+ invoke dll.load, @IMPORT
+ test eax, eax
+ jz .deflate_loaded
+ add esp, .localsize
+ popad
+ mov [deflate_loader_mutex], eax
+ ret 12
+.deflate_loaded:
+; release mutex
+ mov [deflate_loader_mutex], 0
+; ok, continue
+ mov esi, [.data] ; esi -> data
+ mov ecx, [.length] ; ecx = length
+; the signature has been already checked in img.is.png
+ lodsd
+ lodsd
+ sub ecx, 8
+ xor ebx, ebx ; no image allocated
+.chunks_loop:
+ sub ecx, 12
+ jc .eof
+ lodsd ; chunk length
+ bswap eax
+ sub ecx, eax
+ jc .eof
+ push ecx ; save length of data rest
+ xchg eax, ecx ; ecx = size of data in the chunk
+ lodsd ; chunk type
+ cmp eax, 'IHDR'
+ jz .ihdr
+ cmp eax, 'IDAT'
+ jz .idat
+ cmp eax, 'IEND'
+ jz .iend
+ cmp eax, 'PLTE'
+ jz .palette
+; unrecognized chunk, ignore
+ lea esi, [esi+ecx+4]
+ pop ecx
+ jmp .chunks_loop
+; IHDR chunk
+.ihdr:
+ cmp ecx, 13
+ jnz .invalid_chunk
+ cmp [.image], 0
+ jnz .invalid_chunk
+; read image characteristics
+ lodsd
+ bswap eax
+ mov [.width], eax
+ lodsd
+ bswap eax
+ mov [.height], eax
+ xor eax, eax
+ lea ebx, [eax+1]
+ lodsb
+ cmp al, 16
+ ja .invalid_chunk
+ test al, al
+ jz .invalid_chunk
+ lea edx, [eax-1]
+ test al, dl
+ jnz .invalid_chunk
+ mov [.bit_depth], eax
+ lodsb
+ test al, not 7
+ jnz .invalid_chunk
+ mov [.color_type], eax
+ lodsb
+ test al, al
+ jnz .invalid_chunk ; only compression method 0 is defined
+ lodsb
+ test al, al
+ jnz .invalid_chunk ; only filtering method 0 is defined
+ lodsb
+ cmp al, 1
+ ja .invalid_chunk ; only interlacing methods 0 and 1 are defined
+ mov [.interlace], al
+; check for correctness and calculate bytes_per_pixel and scanline_len
+ mov eax, [.bit_depth]
+ mov edx, [.color_type]
+ dec edx
+ js .grayscale1
+ dec edx
+ jz .rgb1
+ dec edx
+ jz .palette1
+ dec edx
+ jz .grayscale_alpha1
+ dec edx
+ dec edx
+ jnz .invalid_chunk
+.rgb_alpha1:
+ inc ebx
+.rgb1:
+ inc ebx
+.grayscale_alpha1:
+ inc ebx
+ cmp al, 8
+ jb .invalid_chunk
+ jmp @f
+.palette1:
+ cmp al, 8
+ ja .invalid_chunk
+.grayscale1:
+@@:
+ mul ebx
+ mov [.bits_per_pixel], eax
+ add eax, 7
+ shr eax, 3
+ mov [.bytes_per_pixel], eax
+; allocate image
+ push Image.bpp24
+ pop eax
+ cmp [.color_type], 2
+ jz @f
+ mov al, Image.bpp32
+ cmp [.color_type], 6
+ jz @f
+ mov al, Image.bpp8i
+@@:
+ stdcall img.create, [.width], [.height], eax
+ test eax, eax
+ jz .invalid_chunk
+ mov [.image], eax
+ jmp .next_chunk
+.invalid_chunk:
+.iend:
+ pop ecx
+.eof:
+ add esp, .localsize
+ popad
+ ret 12
+; PLTE chunk
+.palette:
+ mov eax, [.image]
+ test eax, eax
+ jz .invalid_chunk
+ cmp [.color_type], 3
+ jz .copy_palette
+.ignore_chunk:
+ add esi, ecx
+.next_chunk:
+ lodsd
+ pop ecx
+ jmp .chunks_loop
+.copy_palette:
+ mov edi, [eax + Image.Palette]
+ xor eax, eax
+ cmp ecx, 256*3
+ ja .next_chunk
+@@:
+ sub ecx, 3
+ jz @f
+ js .invalid_chunk
+ lodsd
+ dec esi
+ bswap eax
+ shr eax, 8
+ stosd
+ jmp @b
+@@:
+ lodsd
+ dec esi
+ bswap eax
+ shr eax, 8
+ stosd
+ jmp .next_chunk
+.idat:
+ jecxz .next_chunk
+ cmp [.idat_read], 0
+ jnz @f
+ lodsb
+ inc [.idat_read]
+ and al, 0xF
+ cmp al, 8
+ jnz .invalid_chunk
+ dec ecx
+ jz .next_chunk
+@@:
+ cmp [.idat_read], 1
+ jnz @f
+ lodsb
+ inc [.idat_read]
+ test al, 20h
+ jnz .invalid_chunk
+ dec ecx
+ jz .next_chunk
+@@:
+ mov [.cur_chunk_ptr], esi
+ mov [.cur_chunk_size], ecx
+ pop [.length]
+ push eax
+ push esp
+ push ebp
+ push .deflate_callback
+ call [deflate_unpack2]
+ pop ecx
+ test eax, eax
+ jz .invalid_chunk
+; convert PNG unpacked data to RAW data
+ mov esi, eax
+ mov [.allocated], eax
+ mov [.size_rest], ecx
+; unfilter and deinterlace
+; .interlace_pass, .starting_row and .starting_col have been already set to 0
+; .block_width, .block_height, .col_increment, .row_increment were set
+; to values for non-interlaced images; correct if necessary
+ cmp [.interlace], 0
+ jz .deinterlace_loop
+ push 8
+ pop eax
+ mov [.row_increment], eax
+ mov [.col_increment], eax
+ mov [.block_height], eax
+ mov [.block_width], eax
+ mov [.row_increment_shift], 3
+ mov [.col_increment_shift], 3
+.deinterlace_loop:
+ mov edx, [.height]
+ cmp edx, [.starting_row]
+ jbe .deinterlace_next
+ mov ebx, [.width]
+ sub ebx, [.starting_col]
+ jbe .deinterlace_next
+ mov cl, [.col_increment_shift]
+ add ebx, [.col_increment]
+ dec ebx
+ shr ebx, cl
+ mov eax, [.bits_per_pixel]
+ imul eax, ebx
+ add eax, 7
+ shr eax, 3
+ mov [.scanline_len], eax
+ shl ebx, cl
+ mov [.col_distance], ebx
+; Unfilter
+ mov ecx, [.size_rest]
+ push esi
+.unfilter_loop_e:
+ mov ebx, [.scanline_len]
+ sub ecx, 1
+ jc .unfilter_abort
+ sub ecx, ebx
+ jc .unfilter_abort
+ movzx eax, byte [esi]
+ add esi, 1
+ cmp eax, 4
+ ja .next_scanline
+ jmp dword [@f + eax*4]
+align 4
+@@:
+ dd .unfilter_none
+ dd .unfilter_sub
+ dd .unfilter_up
+ dd .unfilter_average
+ dd .unfilter_paeth
+.unfilter_sub:
+ mov edi, [.bytes_per_pixel]
+ add esi, edi
+ sub ebx, edi
+ jbe .next_scanline
+ neg edi
+@@:
+ mov al, [esi+edi]
+ add [esi], al
+ add esi, 1
+ sub ebx, 1
+ jnz @b
+ jmp .next_scanline
+.unfilter_up:
+ cmp edx, [.height]
+ jz .unfilter_none
+ lea edi, [ebx+1]
+ neg edi
+@@:
+ mov al, [esi+edi]
+ add [esi], al
+ add esi, 1
+ sub ebx, 1
+ jnz @b
+ jmp .next_scanline
+.unfilter_average:
+ mov edi, [.bytes_per_pixel]
+ cmp edx, [.height]
+ jz .unfilter_average_firstline
+ push edx
+ lea edx, [ebx+1]
+ neg edx
+ sub ebx, edi
+@@:
+ mov al, [esi+edx]
+ shr al, 1
+ add [esi], al
+ add esi, 1
+ sub edi, 1
+ jnz @b
+ mov edi, [.bytes_per_pixel]
+ neg edi
+ test ebx, ebx
+ jz .unfilter_average_done
+@@:
+ mov al, [esi+edx]
+ add al, [esi+edi]
+ rcr al, 1
+ add [esi], al
+ add esi, 1
+ sub ebx, 1
+ jnz @b
+.unfilter_average_done:
+ pop edx
+ jmp .next_scanline
+.unfilter_average_firstline:
+ mov edi, [.bytes_per_pixel]
+ add esi, edi
+ sub ebx, edi
+ jbe .next_scanline
+ neg edi
+@@:
+ mov al, [esi+edi]
+ shr al, 1
+ add [esi], al
+ add esi, 1
+ sub ebx, 1
+ jnz @b
+ jmp .unfilter_none
+.unfilter_paeth:
+ cmp edx, [.height]
+ jz .unfilter_sub
+ push edx
+ lea edx, [ebx+1]
+ mov edi, [.bytes_per_pixel]
+ neg edx
+ sub ebx, edi
+@@:
+ mov al, [esi+edx]
+ add [esi], al
+ add esi, 1
+ sub edi, 1
+ jnz @b
+ mov edi, [.bytes_per_pixel]
+ neg edi
+ test ebx, ebx
+ jz .unfilter_paeth_done
+ push ecx
+@@:
+ push ebx
+; PaethPredictor(Raw(x-bpp) = a, Prior(x) = b, Prior(x-bpp) = c)
+ movzx eax, byte [esi+edi]
+ mov [.paeth_a], eax
+ movzx ecx, byte [esi+edx]
+ add edi, edx
+ mov [.paeth_b], ecx
+ add ecx, eax
+ movzx eax, byte [esi+edi]
+ mov [.paeth_c], eax
+ sub ecx, eax ; ecx = a + b - c = p
+; calculate pa = abs(p-a), pb = abs(p-b), pc = abs(p-c)
+ mov ebx, ecx
+ sub ebx, eax ; ebx = p - c
+ cmp ebx, 80000000h
+ sbb eax, eax ; eax = (p < c) ? 0 : 0xFFFFFFF
+ not eax ; eax = (p < c) ? 0xFFFFFFFF : 0
+ and eax, ebx ; eax = (p < c) ? p - c : 0
+ sub ebx, eax
+ sub ebx, eax ; ebx = abs(p-c)
+ mov [.paeth_pc], ebx
+ mov ebx, ecx
+ sub ebx, [.paeth_a]
+ cmp ebx, 80000000h
+ sbb eax, eax
+ not eax
+ and eax, ebx
+ sub ebx, eax
+ sub ebx, eax
+ mov [.paeth_pa], ebx
+ mov ebx, ecx
+ sub ebx, [.paeth_b]
+ cmp ebx, 80000000h
+ sbb eax, eax
+ not eax
+ and eax, ebx
+ sub ebx, eax
+ sub ebx, eax
+ ;mov [.paeth_pb], ebx
+; select closest value
+ push edx
+ mov edx, [.paeth_b]
+ sub edx, [.paeth_a]
+ sub ebx, [.paeth_pa]
+ sbb ecx, ecx ; ecx = (pa > pb) ? 0xFFFFFFFF : 0
+ sbb eax, eax ; eax = (pa > pb) ? 0xFFFFFFFF : 0
+ and ecx, ebx ; ecx = (pa > pb) ? pb - pa : 0
+ and eax, edx ; eax = (pa > pb) ? b - a : 0
+ add ecx, [.paeth_pa] ; ecx = (pa > pb) ? pb : pa = min(pa,pb)
+ add eax, [.paeth_a] ; eax = (pa > pb) ? b : a
+ mov edx, [.paeth_c]
+ sub edx, eax
+ sub [.paeth_pc], ecx
+ sbb ebx, ebx ; ebx = (min(pa,pb) <= pc) ? 0 : 0xFFFFFFFF
+ and ebx, edx ; ebx = (min(pa,pb) <= pc) ? 0 : c - eax
+ add eax, ebx
+ pop edx
+ add [esi], al
+ pop ebx
+ sub edi, edx
+ add esi, 1
+ sub ebx, 1
+ jnz @b
+ pop ecx
+.unfilter_paeth_done:
+ pop edx
+ jmp .next_scanline
+.unfilter_none:
+ add esi, ebx
+.next_scanline:
+ sub edx, [.row_increment]
+ jc .unfilter_done
+ cmp edx, [.starting_row]
+ jbe .unfilter_done
+ jmp .unfilter_loop_e
+.unfilter_abort:
+ xor ecx, ecx
+.unfilter_done:
+; unfiltering done, now convert to raw data
+; with deinterlacing if needed
+ pop esi
+ mov ebx, [.image]
+ mov eax, [.width]
+ call img._.get_scanline_len
+ mov [.row_distance], eax
+ mov eax, [.row_increment]
+ mul [.width]
+ sub eax, [.col_distance]
+ call img._.get_scanline_len
+ mov [.col_distance], eax
+ mov edi, [ebx + Image.Data]
+ mov eax, [.starting_row]
+ mul [.width]
+ add eax, [.starting_col]
+ call img._.get_scanline_len
+ add edi, eax
+ mov eax, ebx
+ mov ebx, [.size_rest]
+ mov [.size_rest], ecx
+ mov edx, [.height]
+ sub edx, [.starting_row]
+ mov [.j], edx
+ cmp [.color_type], 0
+ jz .grayscale2
+ cmp [.color_type], 2
+ jz .rgb2
+ cmp [.color_type], 3
+ jz .palette2
+ cmp [.color_type], 4
+ jz .grayscale_alpha2
+.rgb_alpha2:
+ cmp [.bit_depth], 16
+ jz .rgb_alpha2_16bit
+.rgb_alpha2.next:
+ sub ebx, 1
+ jc .convert_done
+ add esi, 1
+ sub ebx, [.scanline_len]
+ jc .convert_done
+ mov ecx, [.width]
+ sub ecx, [.starting_col]
+ mov [.i], ecx
+.rgb_alpha2.extloop:
+
+macro init_block
+{
+ push ebx
+ mov eax, [.col_increment]
+ mov edx, [.j]
+ cmp edx, [.block_height]
+ jb @f
+ mov edx, [.block_height]
+@@:
+ mov ebx, [.i]
+ cmp ebx, [.block_width]
+ jb @f
+ mov ebx, [.block_width]
+@@:
+}
+
+ init_block
+ lea eax, [edi+eax*4]
+ push eax
+.rgb_alpha2.innloop1:
+ push edi
+ mov ecx, ebx
+.rgb_alpha2.innloop2:
+ mov al, [esi+2]
+ mov [edi], al
+ mov al, [esi+1]
+ mov [edi+1], al
+ mov al, [esi]
+ mov [edi+2], al
+ mov al, [esi+3]
+ mov [edi+3], al
+ add edi, 4
+ dec ecx
+ jnz .rgb_alpha2.innloop2
+ pop edi
+ add edi, [.row_distance]
+ dec edx
+ jnz .rgb_alpha2.innloop1
+ pop edi ebx
+ add esi, 4
+ mov eax, [.col_increment]
+ sub [.i], eax
+ ja .rgb_alpha2.extloop
+ add edi, [.col_distance]
+ mov eax, [.row_increment]
+ sub [.j], eax
+ ja .rgb_alpha2.next
+ jmp .convert_done
+.rgb_alpha2_16bit:
+ sub ebx, 1
+ jc .convert_done
+ add esi, 1
+ sub ebx, [.scanline_len]
+ jc .convert_done
+ mov ecx, [.width]
+ sub ecx, [.starting_col]
+ mov [.i], ecx
+.rgb_alpha2_16bit.loop:
+ init_block
+ lea eax, [edi+eax*4]
+ push eax
+
+; convert 16 bit sample to 8 bit sample
+macro convert_16_to_8
+{
+local .l1,.l2
+ xor ah, 0x80
+ js .l1
+ cmp al, ah
+ adc al, 0
+ jmp .l2
+.l1:
+ cmp ah, al
+ sbb al, 0
+.l2:
+}
+
+.rgb_alpha2_16bit.innloop1:
+ push edi
+ mov ecx, ebx
+.rgb_alpha2_16bit.innloop2:
+ mov ax, [esi+4]
+ convert_16_to_8
+ mov [edi], al
+ mov ax, [esi+2]
+ convert_16_to_8
+ mov [edi+1], al
+ mov ax, [esi]
+ convert_16_to_8
+ mov [edi+2], al
+ ;mov ax, [esi+6]
+ ;convert_16_to_8
+ ;mov [edi+3], al
+ add edi, 4
+ dec ecx
+ jnz .rgb_alpha2_16bit.innloop2
+ pop edi
+ add edi, [.row_distance]
+ dec edx
+ jnz .rgb_alpha2_16bit.innloop1
+ pop edi ebx
+ add esi, 8
+ mov eax, [.col_increment]
+ sub [.i], eax
+ ja .rgb_alpha2_16bit.loop
+ add edi, [.col_distance]
+ mov eax, [.row_increment]
+ sub [.j], eax
+ ja .rgb_alpha2_16bit
+ jmp .convert_done
+.grayscale2:
+ call .create_grayscale_palette
+ cmp [.bit_depth], 16
+ jz .grayscale2_16bit
+.palette2:
+ cmp [.bit_depth], 1
+ jz .palette2_1bit
+ cmp [.bit_depth], 2
+ jz .palette2_2bit
+ cmp [.bit_depth], 4
+ jz .palette2_4bit
+.palette2_8bit:
+ sub ebx, 1
+ jc .convert_done
+ add esi, 1
+ sub ebx, [.scanline_len]
+ jc .convert_done
+ mov ecx, [.width]
+ sub ecx, [.starting_col]
+ mov [.i], ecx
+.palette2_8bit.extloop:
+ init_block
+ add eax, edi
+ push eax
+ mov al, [esi]
+ inc esi
+macro block_byte_innerloop extloop
+{
+local .l1
+.l1:
+ mov ecx, ebx
+ rep stosb
+ sub edi, ebx
+ add edi, [.row_distance]
+ dec edx
+ jnz .l1
+ pop edi ebx
+ mov eax, [.col_increment]
+ sub [.i], eax
+ ja extloop
+ add edi, [.col_distance]
+ mov eax, [.row_increment]
+ sub [.j], eax
+}
+ block_byte_innerloop .palette2_8bit.extloop
+ ja .palette2_8bit
+ jmp .convert_done
+.palette2_4bit:
+ sub ebx, 1
+ jc .convert_done
+ add esi, 1
+ sub ebx, [.scanline_len]
+ jc .convert_done
+ mov ecx, [.width]
+ sub ecx, [.starting_col]
+ mov [.i], ecx
+ mov [.shift], 0
+.palette2_4bit.extloop:
+ init_block
+ add eax, edi
+ push eax
+ xor [.shift], 1
+ jz .palette2_4bit.shifted
+ mov al, [esi]
+ inc esi
+ shr al, 4
+ jmp @f
+.palette2_4bit.shifted:
+ mov al, [esi-1]
+ and al, 0xF
+@@:
+ block_byte_innerloop .palette2_4bit.extloop
+ ja .palette2_4bit
+ jmp .convert_done
+.palette2_2bit:
+ sub ebx, 1
+ jc .convert_done
+ add esi, 1
+ sub ebx, [.scanline_len]
+ jc .convert_done
+ mov ecx, [.width]
+ sub ecx, [.starting_col]
+ mov [.i], ecx
+ mov [.shift], 0
+.palette2_2bit.extloop:
+ init_block
+ add eax, edi
+ push eax
+ mov cl, [.shift]
+ sub cl, 2
+ jns .palette2_2bit.shifted
+ mov cl, 6
+ mov al, [esi]
+ inc esi
+ shr al, cl
+ jmp @f
+.palette2_2bit.shifted:
+ mov al, [esi-1]
+ shr al, cl
+ and al, 3
+@@:
+ mov [.shift], cl
+ block_byte_innerloop .palette2_2bit.extloop
+ ja .palette2_2bit
+ jmp .convert_done
+.palette2_1bit:
+ sub ebx, 1
+ jc .convert_done
+ add esi, 1
+ sub ebx, [.scanline_len]
+ jc .convert_done
+ mov ecx, [.width]
+ sub ecx, [.starting_col]
+ mov [.i], ecx
+ mov [.shift], 0
+.palette2_1bit.extloop:
+ init_block
+ add eax, edi
+ push eax
+ mov cl, [.shift]
+ dec cl
+ jns .palette2_1bit.shifted
+ mov cl, 7
+ mov al, [esi]
+ inc esi
+ shr al, cl
+ jmp @f
+.palette2_1bit.shifted:
+ mov al, [esi-1]
+ shr al, cl
+ and al, 1
+@@:
+ mov [.shift], cl
+ block_byte_innerloop .palette2_1bit.extloop
+ ja .palette2_1bit
+ jmp .convert_done
+.grayscale2_16bit:
+ sub ebx, 1
+ jc .convert_done
+ add esi, 1
+ sub ebx, [.scanline_len]
+ jc .convert_done
+ mov ecx, [.width]
+ sub ecx, [.starting_col]
+ mov [.i], ecx
+.grayscale2_16bit.extloop:
+ init_block
+ add eax, edi
+ push eax
+ mov ax, [esi]
+ add esi, 2
+ convert_16_to_8
+ block_byte_innerloop .grayscale2_16bit.extloop
+ ja .grayscale2_16bit
+ jmp .convert_done
+.rgb2:
+ cmp [.bit_depth], 16
+ jz .rgb2_16bit
+.rgb2.next:
+ sub ebx, 1
+ jc .convert_done
+ add esi, 1
+ sub ebx, [.scanline_len]
+ jc .convert_done
+ mov ecx, [.width]
+ sub ecx, [.starting_col]
+ mov [.i], ecx
+.rgb2.extloop:
+ init_block
+ lea eax, [eax*3]
+ add eax, edi
+ push eax
+.rgb2.innloop1:
+ push edi
+ mov ecx, ebx
+.rgb2.innloop2:
+ mov al, [esi+2]
+ mov [edi], al
+ mov al, [esi+1]
+ mov [edi+1], al
+ mov al, [esi]
+ mov [edi+2], al
+ add edi, 3
+ dec ecx
+ jnz .rgb2.innloop2
+ pop edi
+ add edi, [.row_distance]
+ dec edx
+ jnz .rgb2.innloop1
+ pop edi ebx
+ add esi, 3
+ mov eax, [.col_increment]
+ sub [.i], eax
+ ja .rgb2.extloop
+ add edi, [.col_distance]
+ mov eax, [.row_increment]
+ sub [.j], eax
+ ja .rgb2.next
+ jmp .convert_done
+.rgb2_16bit:
+ sub ebx, 1
+ jc .convert_done
+ add esi, 1
+ sub ebx, [.scanline_len]
+ jc .convert_done
+ mov ecx, [.width]
+ sub ecx, [.starting_col]
+ mov [.i], ecx
+.rgb2_16bit.extloop:
+ init_block
+ lea eax, [eax*3]
+ add eax, edi
+ push eax
+.rgb2_16bit.innloop1:
+ push edi
+ mov ecx, ebx
+.rgb2_16bit.innloop2:
+ mov ax, [esi+4]
+ convert_16_to_8
+ mov [edi], al
+ mov ax, [esi+2]
+ convert_16_to_8
+ mov [edi+1], al
+ mov ax, [esi]
+ convert_16_to_8
+ mov [edi+2], al
+ add edi, 3
+ dec ecx
+ jnz .rgb2_16bit.innloop2
+ pop edi
+ add edi, [.row_distance]
+ dec edx
+ jnz .rgb2_16bit.innloop1
+ pop edi ebx
+ add esi, 6
+ mov eax, [.col_increment]
+ sub [.i], eax
+ ja .rgb2_16bit.extloop
+ add edi, [.col_distance]
+ mov eax, [.row_increment]
+ sub [.j], eax
+ ja .rgb2_16bit
+ jmp .convert_done
+.grayscale_alpha2:
+ call .create_grayscale_palette
+ cmp [.bit_depth], 16
+ jz .grayscale_alpha2_16bit
+.grayscale_alpha2.next:
+ sub ebx, 1
+ jc .convert_done
+ add esi, 1
+ sub ebx, [.scanline_len]
+ jc .convert_done
+ mov ecx, [.width]
+ sub ecx, [.starting_col]
+ mov [.i], ecx
+.grayscale_alpha2.extloop:
+ init_block
+ add eax, edi
+ push eax
+ mov al, [esi]
+ add esi, 2
+ block_byte_innerloop .grayscale_alpha2.extloop
+ ja .grayscale_alpha2.next
+ jmp .convert_done
+.grayscale_alpha2_16bit:
+ sub ebx, 1
+ jc .convert_done
+ add esi, 1
+ sub ebx, [.scanline_len]
+ jc .convert_done
+ mov ecx, [.width]
+ sub ecx, [.starting_col]
+ mov [.i], ecx
+.grayscale_alpha2_16bit.extloop:
+ init_block
+ add eax, edi
+ push eax
+ mov ax, [esi]
+ add esi, 4
+ convert_16_to_8
+ block_byte_innerloop .grayscale_alpha2_16bit.extloop
+ ja .grayscale_alpha2_16bit
+.convert_done:
+; next interlace pass
+.deinterlace_next:
+ mov eax, [.block_width]
+ cmp eax, [.block_height]
+ jz .deinterlace_dec_width
+ mov [.block_height], eax
+ mov [.col_increment], eax
+ dec [.col_increment_shift]
+ mov [.starting_row], eax
+ and [.starting_col], 0
+ jmp .deinterlace_loop
+.deinterlace_dec_width:
+ shr eax, 1
+ jz .deinterlace_done
+ mov [.block_width], eax
+ mov [.starting_col], eax
+ add eax, eax
+ and [.starting_row], 0
+ mov [.row_increment], eax
+ bsf eax, eax
+ mov [.row_increment_shift], al
+ jmp .deinterlace_loop
+.deinterlace_done:
+ mcall 68, 13, [.allocated]
+ mov esi, [.cur_chunk_ptr]
+ add esi, [.cur_chunk_size]
+ push [.length]
+ jmp .next_chunk
+
+.deflate_callback:
+ mov ebp, [esp+4]
+ mov ebx, [esp+8]
+ xor eax, eax
+ mov esi, [.cur_chunk_size]
+ mov [ebx], esi
+ test esi, esi
+ jz .deflate_callback.ret
+ mov eax, [.cur_chunk_ptr]
+ mov ecx, [.length]
+ add esi, eax
+ mov [.cur_chunk_ptr], esi
+ and [.cur_chunk_size], 0
+@@:
+ sub ecx, 12
+ jb .deflate_callback.ret
+ cmp dword [esi+4+4], 'IDAT'
+ jnz .deflate_callback.ret
+ mov edx, [esi+4]
+ bswap edx
+ sub ecx, edx
+ jb .deflate_callback.ret
+ add esi, 4+8
+ test edx, edx
+ jz @b
+ mov [.cur_chunk_size], edx
+ mov [.cur_chunk_ptr], esi
+ mov [.length], ecx
+.deflate_callback.ret:
+ ret 8
+
+.create_grayscale_palette:
+ push edi edx
+ mov edi, [eax + Image.Palette]
+ mov ecx, [.bit_depth]
+ cmp cl, 16
+ jnz @f
+ mov cl, 8
+@@:
+ push 1
+ pop eax
+ shl eax, cl
+ xchg eax, ecx
+ mov edx, 0x010101
+ cmp al, 8
+ jz .graypal_common
+ mov edx, 0x111111
+ cmp al, 4
+ jz .graypal_common
+ mov edx, 0x555555
+ cmp al, 2
+ jz .graypal_common
+ mov edx, 0xFFFFFF
+.graypal_common:
+ xor eax, eax
+@@:
+ stosd
+ add eax, edx
+ loop @b
+ pop edx edi
+ ret
+;endp
+
+
+
+;;================================================================================================;;
+align 4
+proc img.encode.png uses ebx edx, _img:dword, _common:dword, _specific:dword
+;;------------------------------------------------------------------------------------------------;;
+;? Encode image into raw data in png format ;;
+;;------------------------------------------------------------------------------------------------;;
+;> [_img] = pointer to image ;;
+;> [_common] = format independent options ;;
+;> [_specific] = 0 / pointer to the structure of format specific options ;;
+;;------------------------------------------------------------------------------------------------;;
+;< eax = 0 / pointer to encoded data ;;
+;< ecx = error code / the size of encoded data ;;
+;;================================================================================================;;
+locals
+ encoded_file rd 1
+ encoded_file_size rd 1
+ simag png_image
+endl
+ mov ebx,[_img]
+ mov eax,[ebx+Image.Type]
+ cmp eax,Image.bpp24
+ je @f
+ mov ecx,LIBIMG_ERROR_BIT_DEPTH
+ jmp .error
+ @@:
+
+ mov edx,ebp
+ sub edx,sizeof.png_image
+ mov dword[edx+png_image.version],PNG_IMAGE_VERSION
+ mov ecx,[ebx+Image.Width]
+ mov [edx+png_image.width],ecx ;Image width in pixels (columns)
+ mov eax,[ebx+Image.Height]
+ mov [edx+png_image.height],eax ;Image height in pixels (rows)
+ mov dword[edx+png_image.format],PNG_COLOR_TYPE_RGB
+ ;mov dword[edx+png_image.flags],PNG_IMAGE_FLAG_???
+
+ imul ecx,3
+ mov edi,ecx
+ imul edi,[ebx+Image.Height]
+ cmp edi,4096
+ jge @f
+ mov edi,4096 ;minimum memory size
+ @@:
+ mov [encoded_file_size],edi
+ stdcall [mem.alloc],edi
+ test eax,eax
+ jnz @f
+ mov ecx,LIBIMG_ERROR_OUT_OF_MEMORY
+ jmp .error
+ @@:
+ mov [encoded_file],eax
+ mov edi,edx
+ sub edi,4
+ stdcall png_image_write_to_memory, edx,eax,edi,0,[ebx+Image.Data],ecx,0
+ mov eax,[encoded_file]
+ mov ecx,[encoded_file_size]
+ jmp .quit
+
+.error:
+ xor eax,eax
+.quit:
+ ret
endp
\ No newline at end of file
diff --git a/programs/develop/libraries/libs-dev/libimg/tga/tga.asm b/programs/develop/libraries/libs-dev/libimg/tga/tga.asm
index fa3954797..3d15c2092 100644
--- a/programs/develop/libraries/libs-dev/libimg/tga/tga.asm
+++ b/programs/develop/libraries/libs-dev/libimg/tga/tga.asm
@@ -1,288 +1,288 @@
-;;================================================================================================;;
-;;//// tga.asm //// (c) Nable, 2007-2008, (c) dunkaist, 2012 /////////////////////////////////////;;
-;;================================================================================================;;
-;; ;;
-;; This file is part of Common development libraries (Libs-Dev). ;;
-;; ;;
-;; Libs-Dev is free software: you can redistribute it and/or modify it under the terms of the GNU ;;
-;; Lesser General Public License as published by the Free Software Foundation, either version 2.1 ;;
-;; of the License, or (at your option) any later version. ;;
-;; ;;
-;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without ;;
-;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;
-;; Lesser General Public License for more details. ;;
-;; ;;
-;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;;
-;; If not, see . ;;
-;; ;;
-;;================================================================================================;;
-;; ;;
-;; References: ;;
-;; 1. Hiview 1.2 by Mohammad A. REZAEI ;;
-;; 2. Truevision TGA FILE FORMAT SPECIFICATION Version 2.0 ;;
-;; Technical Manual Version 2.2 January, 1991 ;;
-;; ;;
-;;================================================================================================;;
-
-include 'tga.inc'
-
-;;================================================================================================;;
-proc img.is.tga _data, _length ;//////////////////////////////////////////////////////////////////;;
-;;------------------------------------------------------------------------------------------------;;
-;? Determine if raw data could be decoded (is in Targa format) ;;
-;;------------------------------------------------------------------------------------------------;;
-;> _data = raw data as read from file/stream ;;
-;> _length = data length ;;
-;;------------------------------------------------------------------------------------------------;;
-;< eax = false / true ;;
-;;================================================================================================;;
- push ebx
- cmp [_length], 18
- jbe .nope
- mov ebx, [_data]
- mov eax, dword[ebx + tga_header.colormap_type]
- cmp al, 1
- ja .nope
- cmp ah, 11
- ja .nope
- cmp ah, 9
- jae .cont1
- cmp ah, 3
- ja .nope
- .cont1:
- mov eax, dword[ebx + tga_header.image_spec.depth]
- test eax, 111b ; bpp must be 8, 15, 16, 24 or 32
- jnz .maybe15
- shr al, 3
- cmp al, 4
- ja .nope
- jmp .cont2
- .maybe15:
- cmp al, 15
- jne .nope
- .cont2: ; continue testing
- movzx eax, byte[ebx + tga_header.colormap_spec.entry_size] ; palette bpp
- cmp eax, 0
- je .yep
- cmp eax, 16
- je .yep
- cmp eax, 24
- je .yep
- cmp eax, 32
- je .yep
- .nope:
- xor eax, eax
- pop ebx
- ret
-
- .yep:
- xor eax, eax
- inc eax
- pop ebx
- ret
-endp
-
-;;================================================================================================;;
-proc img.decode.tga _data, _length, _options ;////////////////////////////////////////////////////;;
-;;------------------------------------------------------------------------------------------------;;
-;? Decode data into image if it contains correctly formed raw data in Targa format ;;
-;;------------------------------------------------------------------------------------------------;;
-;> _data = raw data as read from file/stream ;;
-;> _length = data length ;;
-;;------------------------------------------------------------------------------------------------;;
-;< eax = 0 (error) or pointer to image ;;
-;;================================================================================================;;
-locals
- width dd ?
- height dd ?
- bytes_per_pixel dd ?
- retvalue dd ?
-endl
- push ebx esi edi
- mov ebx, [_data]
- movzx esi, byte[ebx]
- lea esi, [esi + ebx + sizeof.tga_header] ; skip comment and header
- mov edx, dword[ebx + tga_header.image_spec.width]
- movzx ecx, dx ; ecx = width
- shr edx, 16 ; edx = height
- mov [width], ecx
- mov [height], edx
- movzx eax, byte[ebx + tga_header.image_spec.depth]
- add eax, 7
- shr eax, 3
- mov [bytes_per_pixel], eax
- movzx eax, byte[ebx + tga_header.image_spec.depth]
-
- cmp eax, 8
- jne @f
- mov eax, Image.bpp8i
- jmp .type_defined
- @@:
- cmp eax, 15
- jne @f
- mov eax, Image.bpp15
- jmp .type_defined
- @@:
- cmp eax, 16
- jne @f
- mov eax, Image.bpp15 ; 16bpp tga images are really 15bpp ARGB
- jmp .type_defined
- @@:
- cmp eax, 24
- jne @f
- mov eax, Image.bpp24
- jmp .type_defined
- @@:
- cmp eax, 32
- jne @f
- mov eax, Image.bpp32
- jmp .type_defined
- @@:
- .type_defined:
- stdcall img.create, ecx, edx, eax
- mov [retvalue], eax
- test eax, eax ; failed to allocate?
- jz .done ; then exit
- mov ebx, eax
- cmp dword[ebx + Image.Type], Image.bpp8i
- jne .palette_parsed
- mov edi, [ebx + Image.Palette]
- mov ecx, [_data]
- cmp byte[ecx + tga_header.image_type], 3 ; we also have grayscale subtype
- jz .write_grayscale_palette ; that don't hold palette in file
- cmp byte[ecx + tga_header.image_type], 11
- jz .write_grayscale_palette
- movzx eax, byte[ecx + tga_header.colormap_spec.entry_size] ; size of colormap entries in bits
- movzx ecx, word[ecx + tga_header.colormap_spec.colormap_length] ; number of colormap entries
- cmp eax, 24
- je .24bpp_palette
- cmp eax, 16
- je .16bpp_palette
- rep movsd ; else they are 32 bpp
- jmp .palette_parsed
- .write_grayscale_palette:
- mov ecx, 0x100
- xor eax, eax
- @@:
- stosd
- add eax, 0x010101
- loop @b
- jmp .palette_parsed
- .16bpp_palette: ; FIXME: code copypasted from img.do_rgb, should use img.convert
- push ebx edx ebp
- @@:
- movzx eax, word[esi]
- mov ebx, eax
- add esi, 2
- and eax, (0x1F) or (0x1F shl 10)
- and ebx, 0x1F shl 5
- lea edx, [eax + eax]
- shr al, 2
- mov ebp, ebx
- shr ebx, 2
- shr ah, 4
- shl dl, 2
- shr ebp, 7
- add eax, edx
- add ebx, ebp
- mov [edi], al
- mov [edi + 1], bl
- mov [edi + 2], ah
- add edi, 4
- loop @b
- pop ebp edx ebx
- jmp .palette_parsed
-
- .24bpp_palette:
- @@:
- lodsd
- dec esi
- and eax, 0xffffff
- stosd
- loop @b
- .palette_parsed:
- mov edi, [ebx + Image.Data]
- mov ebx, [width]
- imul ebx, [height]
- mov edx, [bytes_per_pixel]
- mov eax, [_data]
- test byte[eax + tga_header.image_type], 0x08
- jz .uncompressed
- .next_rle_packet:
- xor eax, eax
- lodsb
- btr ax, 7 ; Run-length packet?
- jnc .raw_packet
- add eax, 1
- sub ebx, eax
- @@:
- mov ecx, edx
- rep movsb
- sub esi, edx
- sub eax, 1
- jnz @b
- add esi, edx
- test ebx, ebx
- jnz .next_rle_packet
- jmp .done
- .raw_packet:
- mov ecx, eax
- add ecx, 1
- sub ebx, ecx
- imul ecx, edx
- rep movsb
- test ebx, ebx
- jnz .next_rle_packet
- .uncompressed:
- imul edx, ebx
- mov ecx, edx
- rep movsb
- .done:
- xor ebx, ebx
- mov esi, [_data]
- test byte[esi + tga_header.image_spec.descriptor], TGA_START_TOP
- jnz @f
- or ebx, FLIP_VERTICAL
- @@:
- test byte[esi + tga_header.image_spec.descriptor], TGA_START_RIGHT
- jz @f
- or ebx, FLIP_HORIZONTAL
- @@:
- test ebx, ebx
- jz @f
- stdcall img.flip, [retvalue], ebx
- @@:
- pop edi esi ebx
- mov eax, [retvalue]
- ret
-endp
-
-;;================================================================================================;;
-proc img.encode.tga _img, _p_length, _options ;///////////////////////////////////////////////////;;
-;;------------------------------------------------------------------------------------------------;;
-;? Encode image into raw data in Targa format ;;
-;;------------------------------------------------------------------------------------------------;;
-;> _img = pointer to image ;;
-;;------------------------------------------------------------------------------------------------;;
-;< eax = 0 (error) or pointer to encoded data ;;
-;< _p_length = encoded data length ;;
-;;================================================================================================;;
- xor eax, eax
- ret
-endp
-
-;;================================================================================================;;
-;;////////////////////////////////////////////////////////////////////////////////////////////////;;
-;;================================================================================================;;
-;! Below are private procs you should never call directly from your code ;;
-;;================================================================================================;;
-;;////////////////////////////////////////////////////////////////////////////////////////////////;;
-;;================================================================================================;;
-
-;;================================================================================================;;
-;;////////////////////////////////////////////////////////////////////////////////////////////////;;
-;;================================================================================================;;
-;! Below is private data you should never use directly from your code ;;
-;;================================================================================================;;
-;;////////////////////////////////////////////////////////////////////////////////////////////////;;
-;;================================================================================================;;
+;;================================================================================================;;
+;;//// tga.asm //// (c) Nable, 2007-2008, (c) dunkaist, 2012 /////////////////////////////////////;;
+;;================================================================================================;;
+;; ;;
+;; This file is part of Common development libraries (Libs-Dev). ;;
+;; ;;
+;; Libs-Dev is free software: you can redistribute it and/or modify it under the terms of the GNU ;;
+;; Lesser General Public License as published by the Free Software Foundation, either version 2.1 ;;
+;; of the License, or (at your option) any later version. ;;
+;; ;;
+;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without ;;
+;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;
+;; Lesser General Public License for more details. ;;
+;; ;;
+;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;;
+;; If not, see . ;;
+;; ;;
+;;================================================================================================;;
+;; ;;
+;; References: ;;
+;; 1. Hiview 1.2 by Mohammad A. REZAEI ;;
+;; 2. Truevision TGA FILE FORMAT SPECIFICATION Version 2.0 ;;
+;; Technical Manual Version 2.2 January, 1991 ;;
+;; ;;
+;;================================================================================================;;
+
+include 'tga.inc'
+
+;;================================================================================================;;
+proc img.is.tga _data, _length ;//////////////////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? Determine if raw data could be decoded (is in Targa format) ;;
+;;------------------------------------------------------------------------------------------------;;
+;> _data = raw data as read from file/stream ;;
+;> _length = data length ;;
+;;------------------------------------------------------------------------------------------------;;
+;< eax = false / true ;;
+;;================================================================================================;;
+ push ebx
+ cmp [_length], 18
+ jbe .nope
+ mov ebx, [_data]
+ mov eax, dword[ebx + tga_header.colormap_type]
+ cmp al, 1
+ ja .nope
+ cmp ah, 11
+ ja .nope
+ cmp ah, 9
+ jae .cont1
+ cmp ah, 3
+ ja .nope
+ .cont1:
+ mov eax, dword[ebx + tga_header.image_spec.depth]
+ test eax, 111b ; bpp must be 8, 15, 16, 24 or 32
+ jnz .maybe15
+ shr al, 3
+ cmp al, 4
+ ja .nope
+ jmp .cont2
+ .maybe15:
+ cmp al, 15
+ jne .nope
+ .cont2: ; continue testing
+ movzx eax, byte[ebx + tga_header.colormap_spec.entry_size] ; palette bpp
+ cmp eax, 0
+ je .yep
+ cmp eax, 16
+ je .yep
+ cmp eax, 24
+ je .yep
+ cmp eax, 32
+ je .yep
+ .nope:
+ xor eax, eax
+ pop ebx
+ ret
+
+ .yep:
+ xor eax, eax
+ inc eax
+ pop ebx
+ ret
+endp
+
+;;================================================================================================;;
+proc img.decode.tga _data, _length, _options ;////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? Decode data into image if it contains correctly formed raw data in Targa format ;;
+;;------------------------------------------------------------------------------------------------;;
+;> _data = raw data as read from file/stream ;;
+;> _length = data length ;;
+;;------------------------------------------------------------------------------------------------;;
+;< eax = 0 (error) or pointer to image ;;
+;;================================================================================================;;
+locals
+ width dd ?
+ height dd ?
+ bytes_per_pixel dd ?
+ retvalue dd ?
+endl
+ push ebx esi edi
+ mov ebx, [_data]
+ movzx esi, byte[ebx]
+ lea esi, [esi + ebx + sizeof.tga_header] ; skip comment and header
+ mov edx, dword[ebx + tga_header.image_spec.width]
+ movzx ecx, dx ; ecx = width
+ shr edx, 16 ; edx = height
+ mov [width], ecx
+ mov [height], edx
+ movzx eax, byte[ebx + tga_header.image_spec.depth]
+ add eax, 7
+ shr eax, 3
+ mov [bytes_per_pixel], eax
+ movzx eax, byte[ebx + tga_header.image_spec.depth]
+
+ cmp eax, 8
+ jne @f
+ mov eax, Image.bpp8i
+ jmp .type_defined
+ @@:
+ cmp eax, 15
+ jne @f
+ mov eax, Image.bpp15
+ jmp .type_defined
+ @@:
+ cmp eax, 16
+ jne @f
+ mov eax, Image.bpp15 ; 16bpp tga images are really 15bpp ARGB
+ jmp .type_defined
+ @@:
+ cmp eax, 24
+ jne @f
+ mov eax, Image.bpp24
+ jmp .type_defined
+ @@:
+ cmp eax, 32
+ jne @f
+ mov eax, Image.bpp32
+ jmp .type_defined
+ @@:
+ .type_defined:
+ stdcall img.create, ecx, edx, eax
+ mov [retvalue], eax
+ test eax, eax ; failed to allocate?
+ jz .done ; then exit
+ mov ebx, eax
+ cmp dword[ebx + Image.Type], Image.bpp8i
+ jne .palette_parsed
+ mov edi, [ebx + Image.Palette]
+ mov ecx, [_data]
+ cmp byte[ecx + tga_header.image_type], 3 ; we also have grayscale subtype
+ jz .write_grayscale_palette ; that don't hold palette in file
+ cmp byte[ecx + tga_header.image_type], 11
+ jz .write_grayscale_palette
+ movzx eax, byte[ecx + tga_header.colormap_spec.entry_size] ; size of colormap entries in bits
+ movzx ecx, word[ecx + tga_header.colormap_spec.colormap_length] ; number of colormap entries
+ cmp eax, 24
+ je .24bpp_palette
+ cmp eax, 16
+ je .16bpp_palette
+ rep movsd ; else they are 32 bpp
+ jmp .palette_parsed
+ .write_grayscale_palette:
+ mov ecx, 0x100
+ xor eax, eax
+ @@:
+ stosd
+ add eax, 0x010101
+ loop @b
+ jmp .palette_parsed
+ .16bpp_palette: ; FIXME: code copypasted from img.do_rgb, should use img.convert
+ push ebx edx ebp
+ @@:
+ movzx eax, word[esi]
+ mov ebx, eax
+ add esi, 2
+ and eax, (0x1F) or (0x1F shl 10)
+ and ebx, 0x1F shl 5
+ lea edx, [eax + eax]
+ shr al, 2
+ mov ebp, ebx
+ shr ebx, 2
+ shr ah, 4
+ shl dl, 2
+ shr ebp, 7
+ add eax, edx
+ add ebx, ebp
+ mov [edi], al
+ mov [edi + 1], bl
+ mov [edi + 2], ah
+ add edi, 4
+ loop @b
+ pop ebp edx ebx
+ jmp .palette_parsed
+
+ .24bpp_palette:
+ @@:
+ lodsd
+ dec esi
+ and eax, 0xffffff
+ stosd
+ loop @b
+ .palette_parsed:
+ mov edi, [ebx + Image.Data]
+ mov ebx, [width]
+ imul ebx, [height]
+ mov edx, [bytes_per_pixel]
+ mov eax, [_data]
+ test byte[eax + tga_header.image_type], 0x08
+ jz .uncompressed
+ .next_rle_packet:
+ xor eax, eax
+ lodsb
+ btr ax, 7 ; Run-length packet?
+ jnc .raw_packet
+ add eax, 1
+ sub ebx, eax
+ @@:
+ mov ecx, edx
+ rep movsb
+ sub esi, edx
+ sub eax, 1
+ jnz @b
+ add esi, edx
+ test ebx, ebx
+ jnz .next_rle_packet
+ jmp .done
+ .raw_packet:
+ mov ecx, eax
+ add ecx, 1
+ sub ebx, ecx
+ imul ecx, edx
+ rep movsb
+ test ebx, ebx
+ jnz .next_rle_packet
+ .uncompressed:
+ imul edx, ebx
+ mov ecx, edx
+ rep movsb
+ .done:
+ xor ebx, ebx
+ mov esi, [_data]
+ test byte[esi + tga_header.image_spec.descriptor], TGA_START_TOP
+ jnz @f
+ or ebx, FLIP_VERTICAL
+ @@:
+ test byte[esi + tga_header.image_spec.descriptor], TGA_START_RIGHT
+ jz @f
+ or ebx, FLIP_HORIZONTAL
+ @@:
+ test ebx, ebx
+ jz @f
+ stdcall img.flip, [retvalue], ebx
+ @@:
+ pop edi esi ebx
+ mov eax, [retvalue]
+ ret
+endp
+
+;;================================================================================================;;
+proc img.encode.tga _img, _p_length, _options ;///////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? Encode image into raw data in Targa format ;;
+;;------------------------------------------------------------------------------------------------;;
+;> _img = pointer to image ;;
+;;------------------------------------------------------------------------------------------------;;
+;< eax = 0 (error) or pointer to encoded data ;;
+;< _p_length = encoded data length ;;
+;;================================================================================================;;
+ xor eax, eax
+ ret
+endp
+
+;;================================================================================================;;
+;;////////////////////////////////////////////////////////////////////////////////////////////////;;
+;;================================================================================================;;
+;! Below are private procs you should never call directly from your code ;;
+;;================================================================================================;;
+;;////////////////////////////////////////////////////////////////////////////////////////////////;;
+;;================================================================================================;;
+
+;;================================================================================================;;
+;;////////////////////////////////////////////////////////////////////////////////////////////////;;
+;;================================================================================================;;
+;! Below is private data you should never use directly from your code ;;
+;;================================================================================================;;
+;;////////////////////////////////////////////////////////////////////////////////////////////////;;
+;;================================================================================================;;
diff --git a/programs/develop/libraries/libs-dev/libimg/tga/tga.inc b/programs/develop/libraries/libs-dev/libimg/tga/tga.inc
index a7615831d..5b1e9b19d 100644
--- a/programs/develop/libraries/libs-dev/libimg/tga/tga.inc
+++ b/programs/develop/libraries/libs-dev/libimg/tga/tga.inc
@@ -1,44 +1,44 @@
-;;================================================================================================;;
-;;//// tga.inc //// (c) Nable, 2007-2008, (c) dunkaist, 2012 /////////////////////////////////////;;
-;;================================================================================================;;
-;; ;;
-;; This file is part of Common development libraries (Libs-Dev). ;;
-;; ;;
-;; Libs-Dev is free software: you can redistribute it and/or modify it under the terms of the GNU ;;
-;; Lesser General Public License as published by the Free Software Foundation, either version 2.1 ;;
-;; of the License, or (at your option) any later version. ;;
-;; ;;
-;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without ;;
-;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;
-;; Lesser General Public License for more details. ;;
-;; ;;
-;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;;
-;; If not, see . ;;
-;; ;;
-;;================================================================================================;;
-
-struct tga_colormap_spec
- first_entry_index dw ?
- colormap_length dw ?
- entry_size db ?
-ends
-
-struct tga_image_spec
- x_origin dw ?
- y_origin dw ?
- width dw ?
- height dw ?
- depth db ?
- descriptor db ?
-ends
-
-struct tga_header
- id_length db ?
- colormap_type db ?
- image_type db ?
- colormap_spec tga_colormap_spec
- image_spec tga_image_spec
-ends
-
-TGA_START_TOP = 0x20
-TGA_START_RIGHT = 0x10
+;;================================================================================================;;
+;;//// tga.inc //// (c) Nable, 2007-2008, (c) dunkaist, 2012 /////////////////////////////////////;;
+;;================================================================================================;;
+;; ;;
+;; This file is part of Common development libraries (Libs-Dev). ;;
+;; ;;
+;; Libs-Dev is free software: you can redistribute it and/or modify it under the terms of the GNU ;;
+;; Lesser General Public License as published by the Free Software Foundation, either version 2.1 ;;
+;; of the License, or (at your option) any later version. ;;
+;; ;;
+;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without ;;
+;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;
+;; Lesser General Public License for more details. ;;
+;; ;;
+;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;;
+;; If not, see . ;;
+;; ;;
+;;================================================================================================;;
+
+struct tga_colormap_spec
+ first_entry_index dw ?
+ colormap_length dw ?
+ entry_size db ?
+ends
+
+struct tga_image_spec
+ x_origin dw ?
+ y_origin dw ?
+ width dw ?
+ height dw ?
+ depth db ?
+ descriptor db ?
+ends
+
+struct tga_header
+ id_length db ?
+ colormap_type db ?
+ image_type db ?
+ colormap_spec tga_colormap_spec
+ image_spec tga_image_spec
+ends
+
+TGA_START_TOP = 0x20
+TGA_START_RIGHT = 0x10
diff --git a/programs/develop/libraries/libs-dev/libimg/xcf/xcf.asm b/programs/develop/libraries/libs-dev/libimg/xcf/xcf.asm
index aa1ff8215..473fc2990 100644
--- a/programs/develop/libraries/libs-dev/libimg/xcf/xcf.asm
+++ b/programs/develop/libraries/libs-dev/libimg/xcf/xcf.asm
@@ -29,10 +29,6 @@
include 'xcf.inc'
;include '../../../../../system/board/trunk/debug.inc'
-COMPOSITE_MODE equ MMX
-; MMX | pretty fast and compatible
-; SSE | a bit faster, but may be unsupported by some CPUs
-
MAX_LAYERS = 255
;;================================================================================================;;
@@ -1616,10 +1612,6 @@ endl
ret
endp
-
-match =MMX, COMPOSITE_MODE{include 'composite_mmx.asm'}
-match =SSE, COMPOSITE_MODE{include 'composite_sse.asm'}
-
;;================================================================================================;;
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
;;================================================================================================;;
@@ -1636,28 +1628,3 @@ xcf._.prop_table_begin:
dd 11, xcf._.parse_properties.11
dd 15, xcf._.parse_properties.15
xcf._.prop_table_end:
-
-xcf._.composite_table.begin:
- .p00 dd 00, xcf._.composite_rgb_00, xcf._.composite_gray_00, xcf._.composite_indexed_00 ; Normal
- .p01 dd 01, xcf._.composite_rgb_01, xcf._.composite_gray_01, xcf._.composite_gray_01 ; Dissolve : random dithering to discrete alpha
-; .p02 dd 02, xcf._.composite_rgb_02, 0, xcf._.composite_indexed_02 ; Behind : not selectable in the GIMP UI. not implemented
- .p03 dd 03, xcf._.composite_rgb_03, xcf._.composite_rgb_03, xcf._.composite_indexed_00 ; Multiply
- .p04 dd 04, xcf._.composite_rgb_04, xcf._.composite_rgb_04, xcf._.composite_indexed_00 ; Screen
- .p05 dd 05, xcf._.composite_rgb_05, xcf._.composite_rgb_05, xcf._.composite_indexed_00 ; Overlay
- .p06 dd 06, xcf._.composite_rgb_06, xcf._.composite_rgb_06, xcf._.composite_indexed_00 ; Difference
- .p07 dd 07, xcf._.composite_rgb_07, xcf._.composite_rgb_07, xcf._.composite_indexed_00 ; Addition
- .p08 dd 08, xcf._.composite_rgb_08, xcf._.composite_rgb_08, xcf._.composite_indexed_00 ; Subtract
- .p09 dd 09, xcf._.composite_rgb_09, xcf._.composite_rgb_09, xcf._.composite_indexed_00 ; Darken Only
- .p10 dd 10, xcf._.composite_rgb_10, xcf._.composite_rgb_10, xcf._.composite_indexed_00 ; Lighten Only
- .p11 dd 11, xcf._.composite_rgb_11, xcf._.composite_gray_00, xcf._.composite_indexed_00 ; Hue (H of HSV)
- .p12 dd 12, xcf._.composite_rgb_12, xcf._.composite_gray_00, xcf._.composite_indexed_00 ; Saturation (S of HSV)
- .p13 dd 13, xcf._.composite_rgb_13, xcf._.composite_gray_00, xcf._.composite_indexed_00 ; Color (H and S of HSL)
- .p14 dd 14, xcf._.composite_rgb_14, xcf._.composite_gray_00, xcf._.composite_indexed_00 ; Value (V of HSV)
- .p15 dd 15, xcf._.composite_rgb_15, xcf._.composite_rgb_15, xcf._.composite_indexed_00 ; Divide
- .p16 dd 16, xcf._.composite_rgb_16, xcf._.composite_rgb_16, xcf._.composite_indexed_00 ; Dodge
- .p17 dd 17, xcf._.composite_rgb_17, xcf._.composite_rgb_17, xcf._.composite_indexed_00 ; Burn
- .p18 dd 18, xcf._.composite_rgb_18, xcf._.composite_rgb_18, xcf._.composite_indexed_00 ; Hard Light
- .p19 dd 19, xcf._.composite_rgb_05, xcf._.composite_rgb_05, xcf._.composite_indexed_00 ; Soft Light : XCF >= 2 only ('soft light' == 'overlay')
- .p20 dd 20, xcf._.composite_rgb_20, xcf._.composite_rgb_20, xcf._.composite_indexed_00 ; Grain Extract : XCF >= 2 only
- .p21 dd 21, xcf._.composite_rgb_21, xcf._.composite_rgb_21, xcf._.composite_indexed_00 ; Grain Merge : XCF >= 2 only
-xcf._.composite_table.end:
diff --git a/programs/develop/libraries/libs-dev/libimg/z80/z80.asm b/programs/develop/libraries/libs-dev/libimg/z80/z80.asm
index a1b6adc21..9efb1920f 100644
--- a/programs/develop/libraries/libs-dev/libimg/z80/z80.asm
+++ b/programs/develop/libraries/libs-dev/libimg/z80/z80.asm
@@ -1,257 +1,257 @@
-;;================================================================================================;;
-;;//// z80.asm //// (c) Nable, 2007-2008 /////////////////////////////////////////////////////////;;
-;;================================================================================================;;
-;; ;;
-;; This file is part of Common development libraries (Libs-Dev). ;;
-;; ;;
-;; Libs-Dev is free software: you can redistribute it and/or modify it under the terms of the GNU ;;
-;; Lesser General Public License as published by the Free Software Foundation, either version 2.1 ;;
-;; of the License, or (at your option) any later version. ;;
-;; ;;
-;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without ;;
-;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;
-;; Lesser General Public License for more details. ;;
-;; ;;
-;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;;
-;; If not, see . ;;
-;; ;;
-;;================================================================================================;;
-;; ;;
-;; References: ;;
-;; 1. ;;
-;; ;;
-;;================================================================================================;;
-
-include 'z80.inc'
-
-;;================================================================================================;;
-proc img.is.z80 _data, _length ;//////////////////////////////////////////////////////////////////;;
-;;------------------------------------------------------------------------------------------------;;
-;? Determine if raw data could be decoded (is in z80 screen format) ;;
-;;------------------------------------------------------------------------------------------------;;
-;> _data = raw data as read from file/stream ;;
-;> _length = data length ;;
-;;------------------------------------------------------------------------------------------------;;
-;< eax = false / true ;;
-;;================================================================================================;;
- xor eax,eax
- cmp [_length],6929
- setz al
- je @f
- cmp [_length],6912
- setz al
-@@:
- ret
-endp
-
-;;================================================================================================;;
-proc img.decode.z80 _data, _length, _options ;////////////////////////////////////////////////////;;
-;;------------------------------------------------------------------------------------------------;;
-;? Decode data into image if it contains correctly formed raw data in z80 screen format ;;
-;;------------------------------------------------------------------------------------------------;;
-;> _data = raw data as read from file/stream ;;
-;> _length = data length ;;
-;;------------------------------------------------------------------------------------------------;;
-;< eax = 0 (error) or pointer to image ;;
-;;================================================================================================;;
-;---------------------------------------------------------------------------------------------------
-;During the decoding:
-;bl - PixelLeft (this means how much pixels left to put in current string)
-;bh - CurrentString
-;High half of ebx - use DualStos (two frames per one pixel_write)
-;cl - PixelColorIndexInPalette
-;ch - BackgroundColorIndexInPalette
-;High half of ecx - blinking flag
-;edx - address of current attribute byte
-;---------------------------------------------------------------------------------------------------
-locals
- frame1 dd ?
- OffsetIn2ndFrame dd ?
-endl
- xor eax,eax
- pushad
- cld ;paranoia
- stdcall img.create,256,192,Image.bpp8i
- test eax,eax
- jz img.decode.z80.locret ;test if allocation failed
- mov [frame1],eax
- mov esi,z80._._16color_palette
- mov ecx,16
- mov edi,[eax+Image.Palette]
- rep movsd ;write palette for the first frame
- mov esi,[_data]
- cmp [_length],6929
- jne @f
- add esi,17 ;in case of 6929 byte files we just skip the info in the begininning.
-@@:
-;---------------------------------------------------------------------------------------------------
-;At first we'll determine if there are any blinking pixels
-;if no - we'll produce statical single image
- mov ecx,768
- lea edx,[esi+6912-768];edx points to attribute area
- xor ebx,ebx ;begin from <0,0> (for further decoding)
-@@:
- test byte[edx+ecx-1],z80.BlinkFlag ;such addressing is a good optimisation
- ;(as I hope), edx is unchanged
- jnz .decode_z80_with_blinking
- loop @b
-.decode_z80_without_blinking:
- jmp .decode_z80_main_stage
-
-.decode_z80_with_blinking:
- or ebx,0xFFFF0000 ;use DualStos
- mov ecx,eax ;eax still points to the first frame
- stdcall img.create,256,192,Image.bpp8i
- test eax,eax
- jz img.decode.z80.failed
- mov [eax+Image.Previous],ecx
- mov [ecx+Image.Next],eax
- mov esi,z80._._16color_palette
- mov ecx,16
- mov edi,[eax+Image.Palette]
- rep movsd ;write palette for the second frame
- mov eax,[eax+Image.Data]
- mov [OffsetIn2ndFrame],eax
-;-------------------------------------------------------------------------------
-.decode_z80_main_stage:
-;2nd stage - convert z80 screen to 8bpp image with palette
-.decode_z80_main_stage_main_loop:
- test bl,7
- jnz .decode_z80_main_stage_put_now
-
-._z80_update_attributes:
- movsx ecx,byte[edx] ;note that BlinkFlag is the highest bit in attribute
- ;byte, so ecx's highest bit is set automatically
- shl ecx,5
- shr cl,5
- and ch,0xF
- test ch,1000b
- jz @f
- or ecx,1000b ;it has the same size with 'or cl,1000b' but could be faster
-@@:
- inc edx
-
- lodsb
- mov ah,al
-
-.decode_z80_main_stage_put_now:
- shl ah,1
-;-------------------------------------------------------------------------------
-._z80_put_pixel:
-;In: CF - put pixel with color CL, !CF - pixel with color CH
-;High parts of ebx and ecx - as described above
- mov al,cl ;'mov' doesn't affect flags
- jc @f
- mov al,ch
-@@:
- stosb ;'stosb' doesn't affect flags
-
- test ebx,ebx
- jns @f
- test ecx,ecx
- jns .1
- mov al,ch
-.1:
- xchg [OffsetIn2ndFrame],edi
- stosb
- xchg [OffsetIn2ndFrame],edi
-@@:
- inc bl ;next pixel
- jz .decode_z80_main_stage_row_finished
- jmp .decode_z80_main_stage_main_loop
-;-------------------------------------------------------------------------------
-.decode_z80_main_stage_row_finished:
- cmp bh,191 ;is image finished?
- jb .decode_z80_main_stage_image_not_finished ;no.
-.decode_z80_finish:
- jmp .locret ;now really finished
-;-------------------------------------------------------------------------------
-;or not finished yet. Branch according to a row number (see documentation)
-.decode_z80_main_stage_next_third:
- sub bh,7
- sub edi,256*(8-1)
- jmp .decode_z80_main_stage_main_loop
-
-.decode_z80_main_stage_image_not_finished:
-;next row
- add bh,8 ;refer to documentation
- add edi,256*(8-1)
-
-;if finished row is 63 or 127 then we process next third of the image
- cmp bh,63+8
- je .decode_z80_main_stage_next_third
- cmp bh,127+8
- je .decode_z80_main_stage_next_third
-
- cmp bh,56+8 ;if finished row in [56;63) or [120;127) or [184;191)
- jb .decode_z80_main_stage_main_loop
- cmp bh,63+8
- jb .4
- cmp bh,120+8
- jb .decode_z80_main_stage_main_loop
- cmp bh,127+8
- jb .4
- cmp bh,184+8
- jb .decode_z80_main_stage_main_loop
-;note that if we are here then bh is < 191 (see label .2) but >= 184+8
-.4:
-;and if we here then bh is in [56;63) or [120;127) or [184;191)
- sub bh,(8+56-1)
- sub edi,256*(8+56-1)
- sub edx,z80.AttrString*8
- jmp .decode_z80_main_stage_main_loop
-img.decode.z80.locret:
- popad
- ret
-img.decode.z80.failed:
- stdcall img.destroy,[frame1]
- jmp img.decode.z80.locret
-endp
-
-;;================================================================================================;;
-proc img.encode.z80 _img, _p_length, _options ;///////////////////////////////////////////////////;;
-;;------------------------------------------------------------------------------------------------;;
-;? Encode image into raw data in z80 screen format ;;
-;;------------------------------------------------------------------------------------------------;;
-;> _img = pointer to image ;;
-;;------------------------------------------------------------------------------------------------;;
-;< eax = 0 (error) or pointer to encoded data ;;
-;< _p_length = encoded data length ;;
-;;================================================================================================;;
- xor eax, eax
- ret
-endp
-
-
-;;================================================================================================;;
-;;////////////////////////////////////////////////////////////////////////////////////////////////;;
-;;================================================================================================;;
-;! Below are private procs you should never call directly from your code ;;
-;;================================================================================================;;
-;;////////////////////////////////////////////////////////////////////////////////////////////////;;
-;;================================================================================================;;
-
-;;================================================================================================;;
-;;////////////////////////////////////////////////////////////////////////////////////////////////;;
-;;================================================================================================;;
-;! Below is private data you should never use directly from your code ;;
-;;================================================================================================;;
-;;////////////////////////////////////////////////////////////////////////////////////////////////;;
-;;================================================================================================;;
-z80._._16color_palette:
-dd 0 ; black
-dd 0x000000b0 ; blue
-dd 0x00b00000 ; red
-dd 0x00b000b0 ; magenta
-dd 0x0000b000 ; green
-dd 0x0000b0b0 ; cyan
-dd 0x00b0b000 ; yellow
-dd 0x00b0b0b0 ; gray
-dd 0 ; black
-dd 0x000000ff ; light blue
-dd 0x00ff0000 ; light red
-dd 0x00ff00ff ; light magenta
-dd 0x0000ff00 ; light green
-dd 0x0000ffff ; light cyan
-dd 0x00ffff00 ; light yellow
-dd 0x00ffffff ; white
+;;================================================================================================;;
+;;//// z80.asm //// (c) Nable, 2007-2008 /////////////////////////////////////////////////////////;;
+;;================================================================================================;;
+;; ;;
+;; This file is part of Common development libraries (Libs-Dev). ;;
+;; ;;
+;; Libs-Dev is free software: you can redistribute it and/or modify it under the terms of the GNU ;;
+;; Lesser General Public License as published by the Free Software Foundation, either version 2.1 ;;
+;; of the License, or (at your option) any later version. ;;
+;; ;;
+;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without ;;
+;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;
+;; Lesser General Public License for more details. ;;
+;; ;;
+;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;;
+;; If not, see . ;;
+;; ;;
+;;================================================================================================;;
+;; ;;
+;; References: ;;
+;; 1. ;;
+;; ;;
+;;================================================================================================;;
+
+include 'z80.inc'
+
+;;================================================================================================;;
+proc img.is.z80 _data, _length ;//////////////////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? Determine if raw data could be decoded (is in z80 screen format) ;;
+;;------------------------------------------------------------------------------------------------;;
+;> _data = raw data as read from file/stream ;;
+;> _length = data length ;;
+;;------------------------------------------------------------------------------------------------;;
+;< eax = false / true ;;
+;;================================================================================================;;
+ xor eax,eax
+ cmp [_length],6929
+ setz al
+ je @f
+ cmp [_length],6912
+ setz al
+@@:
+ ret
+endp
+
+;;================================================================================================;;
+proc img.decode.z80 _data, _length, _options ;////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? Decode data into image if it contains correctly formed raw data in z80 screen format ;;
+;;------------------------------------------------------------------------------------------------;;
+;> _data = raw data as read from file/stream ;;
+;> _length = data length ;;
+;;------------------------------------------------------------------------------------------------;;
+;< eax = 0 (error) or pointer to image ;;
+;;================================================================================================;;
+;---------------------------------------------------------------------------------------------------
+;During the decoding:
+;bl - PixelLeft (this means how much pixels left to put in current string)
+;bh - CurrentString
+;High half of ebx - use DualStos (two frames per one pixel_write)
+;cl - PixelColorIndexInPalette
+;ch - BackgroundColorIndexInPalette
+;High half of ecx - blinking flag
+;edx - address of current attribute byte
+;---------------------------------------------------------------------------------------------------
+locals
+ frame1 dd ?
+ OffsetIn2ndFrame dd ?
+endl
+ xor eax,eax
+ pushad
+ cld ;paranoia
+ stdcall img.create,256,192,Image.bpp8i
+ test eax,eax
+ jz img.decode.z80.locret ;test if allocation failed
+ mov [frame1],eax
+ mov esi,z80._._16color_palette
+ mov ecx,16
+ mov edi,[eax+Image.Palette]
+ rep movsd ;write palette for the first frame
+ mov esi,[_data]
+ cmp [_length],6929
+ jne @f
+ add esi,17 ;in case of 6929 byte files we just skip the info in the begininning.
+@@:
+;---------------------------------------------------------------------------------------------------
+;At first we'll determine if there are any blinking pixels
+;if no - we'll produce statical single image
+ mov ecx,768
+ lea edx,[esi+6912-768];edx points to attribute area
+ xor ebx,ebx ;begin from <0,0> (for further decoding)
+@@:
+ test byte[edx+ecx-1],z80.BlinkFlag ;such addressing is a good optimisation
+ ;(as I hope), edx is unchanged
+ jnz .decode_z80_with_blinking
+ loop @b
+.decode_z80_without_blinking:
+ jmp .decode_z80_main_stage
+
+.decode_z80_with_blinking:
+ or ebx,0xFFFF0000 ;use DualStos
+ mov ecx,eax ;eax still points to the first frame
+ stdcall img.create,256,192,Image.bpp8i
+ test eax,eax
+ jz img.decode.z80.failed
+ mov [eax+Image.Previous],ecx
+ mov [ecx+Image.Next],eax
+ mov esi,z80._._16color_palette
+ mov ecx,16
+ mov edi,[eax+Image.Palette]
+ rep movsd ;write palette for the second frame
+ mov eax,[eax+Image.Data]
+ mov [OffsetIn2ndFrame],eax
+;-------------------------------------------------------------------------------
+.decode_z80_main_stage:
+;2nd stage - convert z80 screen to 8bpp image with palette
+.decode_z80_main_stage_main_loop:
+ test bl,7
+ jnz .decode_z80_main_stage_put_now
+
+._z80_update_attributes:
+ movsx ecx,byte[edx] ;note that BlinkFlag is the highest bit in attribute
+ ;byte, so ecx's highest bit is set automatically
+ shl ecx,5
+ shr cl,5
+ and ch,0xF
+ test ch,1000b
+ jz @f
+ or ecx,1000b ;it has the same size with 'or cl,1000b' but could be faster
+@@:
+ inc edx
+
+ lodsb
+ mov ah,al
+
+.decode_z80_main_stage_put_now:
+ shl ah,1
+;-------------------------------------------------------------------------------
+._z80_put_pixel:
+;In: CF - put pixel with color CL, !CF - pixel with color CH
+;High parts of ebx and ecx - as described above
+ mov al,cl ;'mov' doesn't affect flags
+ jc @f
+ mov al,ch
+@@:
+ stosb ;'stosb' doesn't affect flags
+
+ test ebx,ebx
+ jns @f
+ test ecx,ecx
+ jns .1
+ mov al,ch
+.1:
+ xchg [OffsetIn2ndFrame],edi
+ stosb
+ xchg [OffsetIn2ndFrame],edi
+@@:
+ inc bl ;next pixel
+ jz .decode_z80_main_stage_row_finished
+ jmp .decode_z80_main_stage_main_loop
+;-------------------------------------------------------------------------------
+.decode_z80_main_stage_row_finished:
+ cmp bh,191 ;is image finished?
+ jb .decode_z80_main_stage_image_not_finished ;no.
+.decode_z80_finish:
+ jmp .locret ;now really finished
+;-------------------------------------------------------------------------------
+;or not finished yet. Branch according to a row number (see documentation)
+.decode_z80_main_stage_next_third:
+ sub bh,7
+ sub edi,256*(8-1)
+ jmp .decode_z80_main_stage_main_loop
+
+.decode_z80_main_stage_image_not_finished:
+;next row
+ add bh,8 ;refer to documentation
+ add edi,256*(8-1)
+
+;if finished row is 63 or 127 then we process next third of the image
+ cmp bh,63+8
+ je .decode_z80_main_stage_next_third
+ cmp bh,127+8
+ je .decode_z80_main_stage_next_third
+
+ cmp bh,56+8 ;if finished row in [56;63) or [120;127) or [184;191)
+ jb .decode_z80_main_stage_main_loop
+ cmp bh,63+8
+ jb .4
+ cmp bh,120+8
+ jb .decode_z80_main_stage_main_loop
+ cmp bh,127+8
+ jb .4
+ cmp bh,184+8
+ jb .decode_z80_main_stage_main_loop
+;note that if we are here then bh is < 191 (see label .2) but >= 184+8
+.4:
+;and if we here then bh is in [56;63) or [120;127) or [184;191)
+ sub bh,(8+56-1)
+ sub edi,256*(8+56-1)
+ sub edx,z80.AttrString*8
+ jmp .decode_z80_main_stage_main_loop
+img.decode.z80.locret:
+ popad
+ ret
+img.decode.z80.failed:
+ stdcall img.destroy,[frame1]
+ jmp img.decode.z80.locret
+endp
+
+;;================================================================================================;;
+proc img.encode.z80 _img, _p_length, _options ;///////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? Encode image into raw data in z80 screen format ;;
+;;------------------------------------------------------------------------------------------------;;
+;> _img = pointer to image ;;
+;;------------------------------------------------------------------------------------------------;;
+;< eax = 0 (error) or pointer to encoded data ;;
+;< _p_length = encoded data length ;;
+;;================================================================================================;;
+ xor eax, eax
+ ret
+endp
+
+
+;;================================================================================================;;
+;;////////////////////////////////////////////////////////////////////////////////////////////////;;
+;;================================================================================================;;
+;! Below are private procs you should never call directly from your code ;;
+;;================================================================================================;;
+;;////////////////////////////////////////////////////////////////////////////////////////////////;;
+;;================================================================================================;;
+
+;;================================================================================================;;
+;;////////////////////////////////////////////////////////////////////////////////////////////////;;
+;;================================================================================================;;
+;! Below is private data you should never use directly from your code ;;
+;;================================================================================================;;
+;;////////////////////////////////////////////////////////////////////////////////////////////////;;
+;;================================================================================================;;
+z80._._16color_palette:
+dd 0 ; black
+dd 0x000000b0 ; blue
+dd 0x00b00000 ; red
+dd 0x00b000b0 ; magenta
+dd 0x0000b000 ; green
+dd 0x0000b0b0 ; cyan
+dd 0x00b0b000 ; yellow
+dd 0x00b0b0b0 ; gray
+dd 0 ; black
+dd 0x000000ff ; light blue
+dd 0x00ff0000 ; light red
+dd 0x00ff00ff ; light magenta
+dd 0x0000ff00 ; light green
+dd 0x0000ffff ; light cyan
+dd 0x00ffff00 ; light yellow
+dd 0x00ffffff ; white
diff --git a/programs/develop/libraries/libs-dev/libimg/z80/z80.inc b/programs/develop/libraries/libs-dev/libimg/z80/z80.inc
index 4be190035..f0702a3ba 100644
--- a/programs/develop/libraries/libs-dev/libimg/z80/z80.inc
+++ b/programs/develop/libraries/libs-dev/libimg/z80/z80.inc
@@ -1,23 +1,23 @@
-;;================================================================================================;;
-;;//// z80.inc //// (c) Nable, 2007-2008 /////////////////////////////////////////////////////////;;
-;;================================================================================================;;
-;; ;;
-;; This file is part of Common development libraries (Libs-Dev). ;;
-;; ;;
-;; Libs-Dev is free software: you can redistribute it and/or modify it under the terms of the GNU ;;
-;; Lesser General Public License as published by the Free Software Foundation, either version 2.1 ;;
-;; of the License, or (at your option) any later version. ;;
-;; ;;
-;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without ;;
-;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;
-;; Lesser General Public License for more details. ;;
-;; ;;
-;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;;
-;; If not, see . ;;
-;; ;;
-;;================================================================================================;;
-z80.PixColor equ 000111b
-z80.BgrColor equ 111000b
-z80.BrightFlag equ (1 shl 6)
-z80.BlinkFlag equ (1 shl 7)
+;;================================================================================================;;
+;;//// z80.inc //// (c) Nable, 2007-2008 /////////////////////////////////////////////////////////;;
+;;================================================================================================;;
+;; ;;
+;; This file is part of Common development libraries (Libs-Dev). ;;
+;; ;;
+;; Libs-Dev is free software: you can redistribute it and/or modify it under the terms of the GNU ;;
+;; Lesser General Public License as published by the Free Software Foundation, either version 2.1 ;;
+;; of the License, or (at your option) any later version. ;;
+;; ;;
+;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without ;;
+;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;
+;; Lesser General Public License for more details. ;;
+;; ;;
+;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;;
+;; If not, see . ;;
+;; ;;
+;;================================================================================================;;
+z80.PixColor equ 000111b
+z80.BgrColor equ 111000b
+z80.BrightFlag equ (1 shl 6)
+z80.BlinkFlag equ (1 shl 7)
z80.AttrString equ 32
\ No newline at end of file