From 263f2855f20900267219c33c2c4ae367ce6e42eb Mon Sep 17 00:00:00 2001 From: Ivan Baravy Date: Tue, 8 Dec 2020 17:40:34 +0000 Subject: [PATCH] libimg: Add and export img.blend function git-svn-id: svn://kolibrios.org@8341 a494cfbc-eb01-0410-851d-a64ba20cac60 --- .../libraries/libs-dev/libimg/Tupfile.lua | 6 +- .../libraries/libs-dev/libimg/blend.asm | 76 + .../{xcf/composite_mmx.asm => blend_mmx.asm} | 19 + .../{xcf/composite_sse.asm => blend_sse.asm} | 19 + .../libraries/libs-dev/libimg/bmp/bmp.asm | 2322 ++-- .../libraries/libs-dev/libimg/bmp/bmp.inc | 214 +- .../libraries/libs-dev/libimg/gif/gif.asm | 3166 +++--- .../libraries/libs-dev/libimg/gif/gif.inc | 284 +- .../libs-dev/libimg/ico_cur/ico_cur.asm | 744 +- .../libs-dev/libimg/ico_cur/ico_cur.inc | 92 +- .../libraries/libs-dev/libimg/jpeg/jpeg.asm | 4462 ++++---- .../libraries/libs-dev/libimg/jpeg/jpeg.inc | 192 +- .../libraries/libs-dev/libimg/libimg.asm | 20 +- .../libs-dev/libimg/png/libpng/png.asm | 9452 ++++++++--------- .../libs-dev/libimg/png/libpng/png.inc | 3628 +++---- .../libs-dev/libimg/png/libpng/pngerror.asm | 1794 ++-- .../libs-dev/libimg/png/libpng/pngget.asm | 2564 ++--- .../libs-dev/libimg/png/libpng/pnginfo.inc | 506 +- .../libs-dev/libimg/png/libpng/pnglibconf.inc | 418 +- .../libs-dev/libimg/png/libpng/pngmem.asm | 606 +- .../libs-dev/libimg/png/libpng/pngpriv.inc | 612 +- .../libs-dev/libimg/png/libpng/pngset.asm | 3724 +++---- .../libs-dev/libimg/png/libpng/pngstruct.inc | 906 +- .../libs-dev/libimg/png/libpng/pngtokos.inc | 598 +- .../libs-dev/libimg/png/libpng/pngtrans.asm | 1818 ++-- .../libs-dev/libimg/png/libpng/pngwio.asm | 330 +- .../libs-dev/libimg/png/libpng/pngwrite.asm | 6594 ++++++------ .../libs-dev/libimg/png/libpng/pngwtran.asm | 1200 +-- .../libs-dev/libimg/png/libpng/pngwutil.asm | 6958 ++++++------ .../libraries/libs-dev/libimg/png/png.asm | 2288 ++-- .../libraries/libs-dev/libimg/tga/tga.asm | 576 +- .../libraries/libs-dev/libimg/tga/tga.inc | 88 +- .../libraries/libs-dev/libimg/xcf/xcf.asm | 33 - .../libraries/libs-dev/libimg/z80/z80.asm | 514 +- .../libraries/libs-dev/libimg/z80/z80.inc | 44 +- 35 files changed, 28479 insertions(+), 28388 deletions(-) create mode 100644 programs/develop/libraries/libs-dev/libimg/blend.asm rename programs/develop/libraries/libs-dev/libimg/{xcf/composite_mmx.asm => blend_mmx.asm} (85%) rename programs/develop/libraries/libs-dev/libimg/{xcf/composite_sse.asm => blend_sse.asm} (90%) 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