From 722650c58d55da22bfdad4a176cd221677945da2 Mon Sep 17 00:00:00 2001 From: IgorA Date: Mon, 21 Nov 2016 16:00:11 +0000 Subject: [PATCH] libimg can save 24-bit *.png images git-svn-id: svn://kolibrios.org@6733 a494cfbc-eb01-0410-851d-a64ba20cac60 --- .../libraries/libs-dev/.test/006/test006.asm | 277 + .../libraries/libs-dev/libimg/libimg.asm | 16 +- .../libs-dev/libimg/png/libpng/png.asm | 4733 +++++++++++++++++ .../libs-dev/libimg/png/libpng/png.inc | 2222 ++++++++ .../libs-dev/libimg/png/libpng/pngerror.asm | 897 ++++ .../libs-dev/libimg/png/libpng/pngget.asm | 1282 +++++ .../libs-dev/libimg/png/libpng/pnginfo.inc | 254 + .../libs-dev/libimg/png/libpng/pnglibconf.inc | 209 + .../libs-dev/libimg/png/libpng/pngmem.asm | 303 ++ .../libs-dev/libimg/png/libpng/pngpriv.inc | 306 ++ .../libs-dev/libimg/png/libpng/pngset.asm | 1862 +++++++ .../libs-dev/libimg/png/libpng/pngstruct.inc | 443 ++ .../libs-dev/libimg/png/libpng/pngtokos.inc | 299 ++ .../libs-dev/libimg/png/libpng/pngtrans.asm | 886 +++ .../libs-dev/libimg/png/libpng/pngwio.asm | 165 + .../libs-dev/libimg/png/libpng/pngwrite.asm | 3318 ++++++++++++ .../libs-dev/libimg/png/libpng/pngwtran.asm | 610 +++ .../libs-dev/libimg/png/libpng/pngwutil.asm | 3319 ++++++++++++ .../libraries/libs-dev/libimg/png/png.asm | 66 +- 19 files changed, 21461 insertions(+), 6 deletions(-) create mode 100644 programs/develop/libraries/libs-dev/.test/006/test006.asm create mode 100644 programs/develop/libraries/libs-dev/libimg/png/libpng/png.asm create mode 100644 programs/develop/libraries/libs-dev/libimg/png/libpng/png.inc create mode 100644 programs/develop/libraries/libs-dev/libimg/png/libpng/pngerror.asm create mode 100644 programs/develop/libraries/libs-dev/libimg/png/libpng/pngget.asm create mode 100644 programs/develop/libraries/libs-dev/libimg/png/libpng/pnginfo.inc create mode 100644 programs/develop/libraries/libs-dev/libimg/png/libpng/pnglibconf.inc create mode 100644 programs/develop/libraries/libs-dev/libimg/png/libpng/pngmem.asm create mode 100644 programs/develop/libraries/libs-dev/libimg/png/libpng/pngpriv.inc create mode 100644 programs/develop/libraries/libs-dev/libimg/png/libpng/pngset.asm create mode 100644 programs/develop/libraries/libs-dev/libimg/png/libpng/pngstruct.inc create mode 100644 programs/develop/libraries/libs-dev/libimg/png/libpng/pngtokos.inc create mode 100644 programs/develop/libraries/libs-dev/libimg/png/libpng/pngtrans.asm create mode 100644 programs/develop/libraries/libs-dev/libimg/png/libpng/pngwio.asm create mode 100644 programs/develop/libraries/libs-dev/libimg/png/libpng/pngwrite.asm create mode 100644 programs/develop/libraries/libs-dev/libimg/png/libpng/pngwtran.asm create mode 100644 programs/develop/libraries/libs-dev/libimg/png/libpng/pngwutil.asm diff --git a/programs/develop/libraries/libs-dev/.test/006/test006.asm b/programs/develop/libraries/libs-dev/.test/006/test006.asm new file mode 100644 index 0000000000..c639d607c7 --- /dev/null +++ b/programs/develop/libraries/libs-dev/.test/006/test006.asm @@ -0,0 +1,277 @@ +use32 + org 0x0 + +db 'MENUET01' +dd 1,START,I_END,MEM,STACKTOP,0,cur_dir_path + + +include '../../../../../proc32.inc' +include '../../../../../macros.inc' +include '../../../../../KOSfuncs.inc' +include '../../../box_lib/load_lib.mac' +include '../../../../../dll.inc' +include '../../libimg/libimg.inc' + +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 +} + +@use_library_mem mem.Alloc,mem.Free,mem.ReAlloc, dll.Load + +align 4 +m1size dd 16*1024 +m1 rb 16*1024 + +align 4 +START: +load_libraries l_libs_start,load_lib_end +mov ebp,lib0 +.test_lib_open: + cmp dword [ebp+ll_struc_size-4],0 + jz @f + mcall SF_TERMINATE_PROCESS ;exit not correct +@@: + add ebp,ll_struc_size + cmp ebp,load_lib_end + jl .test_lib_open + + ;create image data + stdcall [buf2d_create], buf_0 + stdcall [buf2d_line], buf_0, 110, 20, 125, 90, 0xffff00 + stdcall [buf2d_line], buf_0, 60, 120, 110, 20, 0xd000 + stdcall [buf2d_curve_bezier], buf_0, (10 shl 16)+20,(110 shl 16)+10,(50 shl 16)+90, dword 0xff + stdcall [buf2d_circle], buf_0, 125, 90, 30, 0xffffff + stdcall [buf2d_circle], buf_0, 25, 70, 15, 0xff0000 + + ;create image struct + stdcall [img.create], [buf_0.w], [buf_0.h], Image.bpp24 + test eax,eax + jz @f + ;copy image + mov edi,[eax+Image.Data] + mov esi,[buf_0] + mov ecx,[buf_0.w] + imul ecx,[buf_0.h] + imul ecx,3 + rep movsb + + ;encode image + stdcall [img.encode], eax, LIBIMG_FORMAT_PNG, 0 + test eax,eax + jz @f + + ;copy output image + mov edi,m1 + mov esi,eax + mov [m1size],ecx + rep movsb + @@: + +align 4 +red: + call draw_window + +align 4 +still: + mcall SF_WAIT_EVENT ; функция 10 - ждать события + + cmp eax,1 ; перерисовать окно ? + je red ; если да - на метку red + cmp eax,2 ; нажата клавиша ? + je key ; если да - на key + cmp eax,3 ; нажата кнопка ? + je button ; если да - на button + + jmp still ; если другое событие - в начало цикла + +align 4 +key: ; нажата клавиша на клавиатуре + mcall SF_GET_KEY ; функция 2 - считать код символа (в ah) + + cmp ah,178 ;Up + jne @f + call but_save_file + @@: + jmp still ; вернуться к началу цикла + +;--------------------------------------------------------------------- +align 4 +button: + mcall SF_GET_BUTTON + cmp ah, 1 + jne still +.exit: + stdcall [buf2d_delete],buf_0 + mcall SF_TERMINATE_PROCESS + +align 4 +draw_window: + mcall SF_REDRAW, SSF_BEGIN_DRAW + mcall SF_STYLE_SETTINGS, SSF_GET_COLORS, sc,sizeof.system_colors + mov edx, [sc.work] ; цвет фона + or edx, 0x33000000 ; и тип окна 3 + mcall SF_CREATE_WINDOW, <50,400>, <50,230>, , ,title + + stdcall [buf2d_draw], buf_0 + + cStr edx,'Img. size:' + mcall SF_DRAW_TEXT, <10,130>,0x40f0,,10 + mcall SF_DRAW_NUMBER, (5 shl 16)+1, m1size, <80,130>, 0 + + mcall SF_REDRAW, SSF_END_DRAW + ret + +align 4 +title db 'Press button [Up] and see ' +openfile_path db '/rd/1/t1.png',0 + +struct FileInfoBlock + Function dd ? + Position dd ? + Flags dd ? + Count dd ? + Buffer dd ? + db ? + FileName dd ? +ends + +align 4 +run_file_70 FileInfoBlock + +align 4 +but_save_file: + pushad + mov eax,SF_FILE + mov [run_file_70.Function], SSF_CREATE_FILE + mov [run_file_70.Position], 0 + mov [run_file_70.Flags], 0 + mov [run_file_70.Buffer], m1 + mov ebx,[m1size] + mov dword[run_file_70.Count], ebx + mov byte[run_file_70+20], 0 + mov dword[run_file_70.FileName], openfile_path + mov ebx,run_file_70 + int 0x40 + ;cmp ebx,0xffffffff + ;je .end_save_file + ;... if error ... + ;.end_save_file: + popad + ret + +align 4 +buf_0: + dd 0 + dw 10 ;+4 left + dw 4 ;+6 top +.w: dd 360 ;+8 w +.h: dd 120 ;+12 h + dd 0x80 ;+16 color + db 24 ;+20 bit in pixel + +align 4 +sc system_colors + +align 4 +import_buf2d_lib: + dd sz_lib_init + buf2d_create dd sz_buf2d_create + buf2d_create_f_img dd sz_buf2d_create_f_img + buf2d_clear dd sz_buf2d_clear + buf2d_draw dd sz_buf2d_draw + buf2d_delete dd sz_buf2d_delete + buf2d_line dd sz_buf2d_line + buf2d_circle dd sz_buf2d_circle + buf2d_img_hdiv2 dd sz_buf2d_img_hdiv2 + buf2d_img_wdiv2 dd sz_buf2d_img_wdiv2 + buf2d_conv_24_to_8 dd sz_buf2d_conv_24_to_8 + buf2d_conv_24_to_32 dd sz_buf2d_conv_24_to_32 + buf2d_bit_blt dd sz_buf2d_bit_blt + buf2d_bit_blt_transp dd sz_buf2d_bit_blt_transp + buf2d_bit_blt_alpha dd sz_buf2d_bit_blt_alpha + buf2d_curve_bezier dd sz_buf2d_curve_bezier + buf2d_convert_text_matrix dd sz_buf2d_convert_text_matrix + buf2d_draw_text dd sz_buf2d_draw_text + dd 0,0 + sz_lib_init db 'lib_init',0 + sz_buf2d_create db 'buf2d_create',0 + sz_buf2d_create_f_img db 'buf2d_create_f_img',0 + sz_buf2d_clear db 'buf2d_clear',0 + sz_buf2d_draw db 'buf2d_draw',0 + sz_buf2d_delete db 'buf2d_delete',0 + sz_buf2d_line db 'buf2d_line',0 + sz_buf2d_circle db 'buf2d_circle',0 + sz_buf2d_img_hdiv2 db 'buf2d_img_hdiv2',0 + sz_buf2d_img_wdiv2 db 'buf2d_img_wdiv2',0 + sz_buf2d_conv_24_to_8 db 'buf2d_conv_24_to_8',0 + sz_buf2d_conv_24_to_32 db 'buf2d_conv_24_to_32',0 + sz_buf2d_bit_blt db 'buf2d_bit_blt',0 + sz_buf2d_bit_blt_transp db 'buf2d_bit_blt_transp',0 + sz_buf2d_bit_blt_alpha db 'buf2d_bit_blt_alpha',0 + sz_buf2d_curve_bezier db 'buf2d_curve_bezier',0 + sz_buf2d_convert_text_matrix db 'buf2d_convert_text_matrix',0 + sz_buf2d_draw_text db 'buf2d_draw_text',0 + +align 4 +import_libimg: + libimg.init dd sz_lib_init1 + img.draw dd sz_img_draw + img.decode dd sz_img_decode + img.encode dd sz_img_encode + img.create dd sz_img_create + img.destroy dd sz_img_destroy + img.to_rgb2 dd sz_img_to_rgb2 + img.formats_table dd sz_img_formats_table +dd 0,0 + sz_lib_init1 db 'lib_init',0 + sz_img_draw db 'img_draw',0 + sz_img_decode db 'img_decode',0 + sz_img_encode db 'img_encode',0 + sz_img_create db 'img_create',0 + sz_img_destroy db 'img_destroy',0 + sz_img_to_rgb2 db 'img_to_rgb2',0 + sz_img_formats_table db 'img_formats_table',0 + +;-------------------------------------------------- +system_dir_0 db '/sys/lib/' +lib_name_0 db 'buf2d.obj',0 + +system_dir_1 db '/sys/lib/' +lib_name_1 db 'libimg.obj',0 + +err_message_found_lib0 db 'Sorry I cannot load library buf2d.obj',0 +err_message_found_lib1 db 'Sorry I cannot load library libimg.obj',0 +head_f_i: +head_f_l db 'System error',0 +err_message_import0 db 'Error on load import library buf2d.obj',0 +err_message_import1 db 'Error on load import library libimg.obj',0 + +l_libs_start: + lib0 l_libs lib_name_0, cur_dir_path, library_path, system_dir_0,\ + err_message_found_lib0, head_f_l, import_buf2d_lib,err_message_import0, head_f_i + lib1 l_libs lib_name_1, cur_dir_path, library_path, system_dir_1,\ + err_message_found_lib1, head_f_l, import_libimg, err_message_import1, head_f_i +load_lib_end: +;--------------------------------------------------------------------- + +align 16 +I_END: + rd 4096 +STACKTOP: +cur_dir_path: + rb 4096 +library_path: + rb 4096 +MEM: diff --git a/programs/develop/libraries/libs-dev/libimg/libimg.asm b/programs/develop/libraries/libs-dev/libimg/libimg.asm index 37dccf924d..d2228b720d 100644 --- a/programs/develop/libraries/libs-dev/libimg/libimg.asm +++ b/programs/develop/libraries/libs-dev/libimg/libimg.asm @@ -68,6 +68,11 @@ proc lib_init ;///////////////////////////////////////////////////////////////// mov [mem.realloc], ecx mov [dll.load], edx + or edx,edx + jz @f + invoke dll.load, @IMPORT + @@: + call img.initialize.jpeg xor eax, eax @@ -2417,7 +2422,7 @@ img.formats_table: .ico dd LIBIMG_FORMAT_ICO, img.is.ico, img.decode.ico_cur, img.encode.ico, 0 .cur dd LIBIMG_FORMAT_CUR, img.is.cur, img.decode.ico_cur, img.encode.cur, 0 .gif dd LIBIMG_FORMAT_GIF, img.is.gif, img.decode.gif, img.encode.gif, 0 - .png dd LIBIMG_FORMAT_PNG, img.is.png, img.decode.png, img.encode.png, 0 + .png dd LIBIMG_FORMAT_PNG, img.is.png, img.decode.png, img.encode.png, 1 + (1 SHL Image.bpp24) .jpg dd LIBIMG_FORMAT_JPEG, img.is.jpg, img.decode.jpg, img.encode.jpg, 0 .tga dd LIBIMG_FORMAT_TGA, img.is.tga, img.decode.tga, img.encode.tga, 0 .pcx dd LIBIMG_FORMAT_PCX, img.is.pcx, img.decode.pcx, img.encode.pcx, 0 @@ -2771,12 +2776,17 @@ export \ ; import from deflate unpacker ; is initialized only when PNG loading is requested -align 4 +align 16 @IMPORT: library archiver, 'archiver.obj' import archiver, \ - deflate_unpack2, 'deflate_unpack2' + deflate_unpack2, 'deflate_unpack2',\ + deflateInit2, 'deflateInit2',\ + deflateReset, 'deflateReset',\ + deflate, 'deflate',\ + deflateEnd, 'deflateEnd',\ + calc_crc32, 'calc_crc32' align 4 ; mutex for unpacker loading diff --git a/programs/develop/libraries/libs-dev/libimg/png/libpng/png.asm b/programs/develop/libraries/libs-dev/libimg/png/libpng/png.asm new file mode 100644 index 0000000000..2254797939 --- /dev/null +++ b/programs/develop/libraries/libs-dev/libimg/png/libpng/png.asm @@ -0,0 +1,4733 @@ + +; 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 + +crc_table rd 256 + +include '../../../../../../KOSfuncs.inc' +include '../../../../../../fs/kfar/trunk/kfar_arc/crc.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 + cmp eax,0 + je .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] + cmp eax,0 + je @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] + cmp eax,0 + je @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] + cmp eax,0 + je @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] + cmp eax,0 + je @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] + cmp eax,0 + je @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] + mov esi,[esi+png_struct.colorspace] + mov edi,[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 new file mode 100644 index 0000000000..cb2fcef954 --- /dev/null +++ b/programs/develop/libraries/libs-dev/libimg/png/libpng/png.inc @@ -0,0 +1,2222 @@ + +; 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 + 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. + +; The PNG_EXPORT() and PNG_EXPORTA() macros used below are defined in +; pngconf.h and in the *.dfn files in the scripts directory. + +; PNG_EXPORT(ordinal, type, name, (args)); + +; ordinal: ordinal that is used while building +; *.def files. The ordinal value is only +; relevant when preprocessing png.h with +; the *.dfn files for building symbol table +; entries, and are removed by pngconf.h. +; type: return type of the function +; name: function name +; args: function arguments, with types + +; When we wish to append attributes to a function prototype we use +; the PNG_EXPORTA() macro instead. + +; PNG_EXPORTA(ordinal, type, name, (args), attributes); + +; ordinal, type, name, and args: same as in PNG_EXPORT(). +; attributes: function attributes + +macro PNG_EXPORT ordinal, typ, nam, arg +{ +align 4 +nam: +local .end_t +local .m_txt +jmp .end_t + .m_txt db `nam,13,10,0 +.end_t: + stdcall dbg_print,txt_zv,.m_txt +ret +} + +; 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 +} + +; Allocate and initialize png_ptr struct for reading, and any other memory. +;PNG_EXPORTA(4, png_structp, png_create_read_struct, +; (charp user_png_ver, voidp error_ptr, +; png_error_ptr error_fn, png_error_ptr warn_fn), +; PNG_ALLOCATED); + +; Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp +; match up. + +; Read the information before the actual image data. +PNG_EXPORT 22, void, png_read_info, '(png_structrp png_ptr, png_inforp info_ptr)' + +; Convert to a US string format: there is no localization support in this +; routine. The original implementation used a 29 character buffer in +; png_struct, this will be removed in future versions. + +;#if PNG_LIBPNG_VER < 10700 +; To do: remove this from libpng17 (and from libpng17/png.c and pngstruct.h) +;PNG_EXPORTA(23, charp, png_convert_to_rfc1123, (png_structrp png_ptr, +; png_const_timep ptime),PNG_DEPRECATED); +;end if + +; Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. +PNG_EXPORT 26, void, png_set_expand, '(png_structrp png_ptr)' +PNG_EXPORT 27, void, png_set_expand_gray_1_2_4_to_8, '(png_structrp png_ptr)' +PNG_EXPORT 28, void, png_set_palette_to_rgb, '(png_structrp png_ptr)' +PNG_EXPORT 29, void, png_set_tRNS_to_alpha, '(png_structrp png_ptr)' + +; Expand to 16-bit channels, forces conversion of palette to RGB and expansion +; of a tRNS chunk if present. +PNG_EXPORT 221, void, png_set_expand_16, '(png_structrp png_ptr)' + +; Expand the grayscale to 24-bit RGB if necessary. +PNG_EXPORT 31, void, png_set_gray_to_rgb, '(png_structrp png_ptr)' + +; 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 + +PNG_EXPORT 32, void, png_set_rgb_to_gray, '(png_structrp png_ptr, int error_action, double red, double green)' +PNG_EXPORT 33, void, png_set_rgb_to_gray_fixed, '(png_structrp png_ptr, int error_action, png_fixed_point red, png_fixed_point green)' + +PNG_EXPORT 34, byte, png_get_rgb_to_gray_status, '(png_const_structrp png_ptr)' + +PNG_EXPORT 35, void, png_build_grayscale_palette, '(int bit_depth, png_colorp palette)' + +; 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 + +PNG_EXPORT 227, void, png_set_alpha_mode, '(png_structrp png_ptr, int mode, double output_gamma)' +PNG_EXPORT 228, void, png_set_alpha_mode_fixed, '(png_structrp png_ptr, int mode, png_fixed_point output_gamma)' + +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 following are examples of calls to png_set_alpha_mode to achieve the +; required overall gamma correction and, where necessary, alpha +; premultiplication. + +; png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); +; This is the default libpng handling of the alpha channel - it is not +; pre-multiplied into the color components. In addition the call states +; that the output is for a sRGB system and causes all PNG files without gAMA +; chunks to be assumed to be encoded using sRGB. + +; png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); +; In this case the output is assumed to be something like an sRGB conformant +; display preceeded by a power-law lookup table of power 1.45. This is how +; early Mac systems behaved. + +; png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_GAMMA_LINEAR); +; This is the classic Jim Blinn approach and will work in academic +; environments where everything is done by the book. It has the shortcoming +; of assuming that input PNG data with no gamma information is linear - this +; is unlikely to be correct unless the PNG files where generated locally. +; Most of the time the output precision will be so low as to show +; significant banding in dark areas of the image. + +; png_set_expand_16(pp); +; png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_DEFAULT_sRGB); +; This is a somewhat more realistic Jim Blinn inspired approach. PNG files +; are assumed to have the sRGB encoding if not marked with a gamma value and +; the output is always 16 bits per component. This permits accurate scaling +; and processing of the data. If you know that your input PNG files were +; generated locally you might need to replace PNG_DEFAULT_sRGB with the +; correct value for your system. + +; png_set_alpha_mode(pp, PNG_ALPHA_OPTIMIZED, PNG_DEFAULT_sRGB); +; If you just need to composite the PNG image onto an existing background +; and if you control the code that does this you can use the optimization +; setting. In this case you just copy completely opaque pixels to the +; output. For pixels that are not completely transparent (you just skip +; those) you do the composition math using png_composite or png_composite_16 +; below then encode the resultant 8-bit or 16-bit values to match the output +; encoding. + +; Other cases +; If neither the PNG nor the standard linear encoding work for you because +; of the software or hardware you use then you have a big problem. The PNG +; case will probably result in halos around the image. The linear encoding +; will probably result in a washed out, too bright, image (it's actually too +; contrasty.) Try the ALPHA_OPTIMIZED mode above - this will probably +; substantially reduce the halos. Alternatively try: + +; png_set_alpha_mode(pp, PNG_ALPHA_BROKEN, PNG_DEFAULT_sRGB); +; This option will also reduce the halos, but there will be slight dark +; halos round the opaque parts of the image where the background is light. +; In the OPTIMIZED mode the halos will be light halos where the background +; is dark. Take your pick - the halos are unavoidable unless you can get +; your hardware/software fixed! (The OPTIMIZED approach is slightly +; faster.) + +; When the default gamma of PNG files doesn't match the output gamma. +; If you have PNG files with no gamma information png_set_alpha_mode allows +; you to provide a default gamma, but it also sets the ouput gamma to the +; matching value. If you know your PNG files have a gamma that doesn't +; match the output you can take advantage of the fact that +; png_set_alpha_mode always sets the output gamma but only sets the PNG +; default if it is not already set: + +; png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); +; png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); +; The first call sets both the default and the output gamma values, the +; second call overrides the output gamma without changing the default. This +; is easier than achieving the same effect with png_set_gamma. You must use +; PNG_ALPHA_PNG for the first call - internal checking in png_set_alpha will +; fire if more than one call to png_set_alpha_mode and png_set_background is +; made in the same read operation, however multiple calls with PNG_ALPHA_PNG +; are ignored. + +PNG_EXPORT 36, void, png_set_strip_alpha, '(png_structrp png_ptr)' + +; 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. + +PNG_EXPORT 47, void, png_set_background, '(png_structrp png_ptr, png_const_color_16p background_color, int background_gamma_code, int need_expand, double background_gamma)' +PNG_EXPORT 215, void, png_set_background_fixed, '(png_structrp png_ptr, png_const_color_16p background_color, int background_gamma_code, int need_expand, png_fixed_point background_gamma)' + +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 + +; Scale a 16-bit depth file down to 8-bit, accurately. +PNG_EXPORT 229, void, png_set_scale_16, '(png_structrp png_ptr)' + +;#define PNG_READ_16_TO_8_SUPPORTED /* Name prior to 1.5.4 */ +; Strip the second byte of information from a 16-bit depth file. +PNG_EXPORT 48, void, png_set_strip_16, '(png_structrp png_ptr)' + +; Turn on quantizing, and reduce the palette to the number of colors +; available. + +PNG_EXPORT 49, void, png_set_quantize, '(png_structrp png_ptr, png_colorp palette, int num_palette, int maximum_colors, png_const_uint_16p histogram, int full_quantize)' + +; The threshold on gamma processing is configurable but hard-wired into the +; library. The following is the floating point variant. + +;#define PNG_GAMMA_THRESHOLD (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! + +; These routines accept the same gamma values as png_set_alpha_mode (described +; above). The PNG_GAMMA_ defines and PNG_DEFAULT_sRGB can be passed to either +; API (floating point or fixed.) Notice, however, that the 'file_gamma' value +; is the inverse of a 'screen gamma' value. + +PNG_EXPORT 50, void, png_set_gamma, '(png_structrp png_ptr, double screen_gamma, double override_file_gamma)' +PNG_EXPORT 208, void, png_set_gamma_fixed, '(png_structrp png_ptr, png_fixed_point screen_gamma, png_fixed_point override_file_gamma)' + +; Optional update palette with requested transformations +PNG_EXPORT 53, void, png_start_read_image, '(png_structrp png_ptr)' + +; Optional call to update the users info structure +PNG_EXPORT 54, void, png_read_update_info, '(png_structrp png_ptr, png_inforp info_ptr)' + +; Read one or more rows of image data. +PNG_EXPORT 55, void, png_read_rows, '(png_structrp png_ptr, bytepp row, bytepp display_row, uint_32 num_rows)' + +; Read a row of data. +PNG_EXPORT 56, void, png_read_row, '(png_structrp png_ptr, bytep row, bytep display_row)' + +; Read the whole image into memory at once. +PNG_EXPORT 57, void, png_read_image, '(png_structrp png_ptr, bytepp image)' + +; Read the end of the PNG file. +PNG_EXPORT 62, void, png_read_end, '(png_structrp png_ptr, png_inforp info_ptr)' + +; Free any memory associated with the png_struct and the png_info_structs +PNG_EXPORT 64, void, png_destroy_read_struct, '(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)' + +; Set the libpng method of handling chunk CRC errors +PNG_EXPORT 66, void, png_set_crc_action, '(png_structrp png_ptr, int crit_action, int ancil_action)' + +; 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 + +; These next functions are called for input/output, memory, and error +; handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, +; and call standard C I/O routines such as fread(), fwrite(), and +; fprintf(). These functions can be made to use other I/O routines +; at run time for those applications that need to handle I/O in a +; different manner by calling png_set_???_fn(). See libpng-manual.txt for +; more information. + + +; Replace the default data input function with a user supplied one. +PNG_EXPORT 78, void, png_set_read_fn, '(png_structrp png_ptr, voidp io_ptr, png_rw_ptr read_data_fn)' + +PNG_EXPORT 80, void, png_set_read_status_fn, '(png_structrp png_ptr, png_read_status_ptr read_row_fn)' + +PNG_EXPORT 84, void, png_set_read_user_transform_fn, '(png_structrp png_ptr, png_user_transform_ptr read_user_transform_fn)' + +if PNG_PROGRESSIVE_READ_SUPPORTED eq 1 +; Sets the function callbacks for the push reader, and a pointer to a +; user-defined structure available to the callback functions. + +PNG_EXPORT 90, void, png_set_progressive_read_fn, '(png_structrp png_ptr, voidp progressive_ptr, png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, png_progressive_end_ptr end_fn)' + +; Returns the user pointer associated with the push read functions +PNG_EXPORT 91, voidp, png_get_progressive_ptr, '(png_const_structrp png_ptr)' + +; Function to be called when data becomes available +PNG_EXPORT 92, void, png_process_data, '(png_structrp png_ptr, png_inforp info_ptr, bytep buffer, png_size_t buffer_size)' + +; A function which may be called *only* within png_process_data to stop the +; processing of any more data. The function returns the number of bytes +; remaining, excluding any that libpng has cached internally. A subsequent +; call to png_process_data must supply these bytes again. If the argument +; 'save' is set to true the routine will first save all the pending data and +; will always return 0. + +PNG_EXPORT 219, png_size_t, png_process_data_pause, '(png_structrp, int save)' + +; A function which may be called *only* outside (after) a call to +; png_process_data. It returns the number of bytes of data to skip in the +; input. Normally it will return 0, but if it returns a non-zero value the +; application must skip than number of bytes of input data and pass the +; following data to the next call to png_process_data. + +PNG_EXPORT 220, uint_32, png_process_data_skip, '(png_structrp)' + +; Function that combines rows. 'new_row' is a flag that should come from +; the callback and be non-NULL if anything needs to be done; the library +; stores its own version of the new data internally and ignores the passed +; in value. + +PNG_EXPORT 93, void, png_progressive_combine_row, '(png_const_structrp png_ptr, bytep old_row, bytep new_row)' +end if ;PROGRESSIVE_READ + +; Reassign responsibility for freeing existing data, whether allocated +; by libpng or by the application; this works on the png_info structure passed +; in, it does not change the state for other png_info structures. + +; 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 +; The same, but the chunk name is prepended to the error string. +;PNG_EXPORTA(103, void, png_chunk_error, (png_const_structrp png_ptr, +; charp error_message), PNG_NORETURN); + +;#else +; Fatal error in PNG image of libpng - can't continue +;PNG_EXPORTA(104, void, png_err, (png_const_structrp png_ptr), PNG_NORETURN); +;# define png_chunk_error(s1,s2) png_err(s1) +;end if + +; Non-fatal error in libpng, chunk name is prepended to message. +PNG_EXPORT 106, void, png_chunk_warning, '(png_const_structrp png_ptr, charp warning_message)' +;#else +;# define png_warning(s1,s2) ((void)(s1)) +;# define png_chunk_warning(s1,s2) ((void)(s1)) + +; Benign error in libpng. Can continue, but may have a problem. +; User can choose whether to handle as a fatal error or as a warning. +PNG_EXPORT 107, void, png_benign_error, '(png_const_structrp png_ptr, charp warning_message)' + +;if PNG_READ_SUPPORTED +; Same, chunk name is prepended to message (only during read) +PNG_EXPORT 108, void, png_chunk_benign_error, '(png_const_structrp png_ptr, charp warning_message)' + +;#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 + +; Returns number of color channels in image. +PNG_EXPORT 114, byte, png_get_channels, '(png_const_structrp png_ptr, png_const_inforp info_ptr)' + +; Returns pixel aspect ratio, computed from pHYs chunk data. +PNG_EXPORT 125, float, png_get_pixel_aspect_ratio, '(png_const_structrp png_ptr, png_const_inforp info_ptr)' +PNG_EXPORT 210, png_fixed_point, png_get_pixel_aspect_ratio_fixed, '(png_const_structrp png_ptr, png_const_inforp info_ptr)' + +; Returns image x, y offset in pixels or microns, from oFFs chunk data. +PNG_EXPORT 126, int_32, png_get_x_offset_pixels, '(png_const_structrp png_ptr, png_const_inforp info_ptr)' +PNG_EXPORT 127, int_32, png_get_y_offset_pixels, '(png_const_structrp png_ptr, png_const_inforp info_ptr)' +PNG_EXPORT 128, int_32, png_get_x_offset_microns, '(png_const_structrp png_ptr, png_const_inforp info_ptr)' +PNG_EXPORT 129, int_32, png_get_y_offset_microns, '(png_const_structrp png_ptr, png_const_inforp info_ptr)' + +; Returns pointer to signature string read from PNG header +PNG_EXPORT 130, bytep, png_get_signature, '(png_const_structrp png_ptr, png_const_inforp info_ptr)' + +PNG_EXPORT 131, uint_32, png_get_bKGD, '(png_const_structrp png_ptr, png_inforp info_ptr, png_color_16p *background)' + +PNG_EXPORT 133, uint_32, png_get_cHRM, '(png_const_structrp png_ptr, png_const_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)' +PNG_EXPORT 230, uint_32, png_get_cHRM_XYZ, '(png_const_structrp png_ptr, png_const_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)' +PNG_EXPORT 134, uint_32, png_get_cHRM_fixed, '(png_const_structrp png_ptr, png_const_inforp info_ptr, png_fixed_point *int_white_x, png_fixed_point *int_white_y, png_fixed_point *int_red_x, png_fixed_point *int_red_y, png_fixed_point *int_green_x, png_fixed_point *int_green_y, png_fixed_point *int_blue_x, png_fixed_point *int_blue_y)' + +PNG_EXPORT 137, uint_32, png_get_gAMA, '(png_const_structrp png_ptr, png_const_inforp info_ptr, double *file_gamma)' +PNG_EXPORT 138, uint_32, png_get_gAMA_fixed, '(png_const_structrp png_ptr, png_const_inforp info_ptr, png_fixed_point *int_file_gamma)' + +PNG_EXPORT 145, uint_32, png_get_oFFs, '(png_const_structrp png_ptr, png_const_inforp info_ptr, int_32 *offset_x, int_32 *offset_y, int *unit_type)' + +PNG_EXPORT 147, uint_32, png_get_pCAL, '(png_const_structrp png_ptr, png_inforp info_ptr, charp *purpose, int_32 *X0, int_32 *X1, int *type, int *nparams, charp *units, charpp *params)' + +PNG_EXPORT 149, uint_32, png_get_pHYs, '(png_const_structrp png_ptr, png_const_inforp info_ptr, uint_32 *res_x, uint_32 *res_y, int *unit_type)' + +PNG_EXPORT 151, uint_32, png_get_PLTE, '(png_const_structrp png_ptr, png_inforp info_ptr, png_colorp *palette, int *num_palette)' + +PNG_EXPORT 153, uint_32, png_get_sBIT, '(png_const_structrp png_ptr, png_inforp info_ptr, png_color_8p *sig_bit)' + +PNG_EXPORT 155, uint_32, png_get_sRGB, '(png_const_structrp png_ptr, png_const_inforp info_ptr, int *file_srgb_intent)' + +; png_get_text also returns the number of text chunks in *num_text +PNG_EXPORT 162, int, png_get_text, '(png_const_structrp png_ptr, png_inforp info_ptr, png_textp *text_ptr, int *num_text)' + +PNG_EXPORT 164, uint_32, png_get_tIME, '(png_const_structrp png_ptr, png_inforp info_ptr, png_timep *mod_time)' + +PNG_EXPORT 166, uint_32, png_get_tRNS, '(png_const_structrp png_ptr, png_inforp info_ptr, bytep *trans_alpha, int *num_trans, png_color_16p *trans_color)' + +PNG_EXPORT 168, uint_32, png_get_sCAL, '(png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit, double *width, double *height)' + +; NOTE: this API is currently implemented using floating point arithmetic, +; consequently it can only be used on systems with floating point support. +; In any case the range of values supported by png_fixed_point is small and it +; is highly recommended that png_get_sCAL_s be used instead. + +PNG_EXPORT 214, uint_32, png_get_sCAL_fixed, '(png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit, png_fixed_point *width, png_fixed_point *height)' + +PNG_EXPORT 170, void, png_set_sCAL, '(png_const_structrp png_ptr, png_inforp info_ptr, int unit, double width, double height)' +PNG_EXPORT 171, void, png_set_sCAL_s, '(png_const_structrp png_ptr, png_inforp info_ptr, int unit, charp swidth, charp sheight)' + +; 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. + + +; The "params" pointer is currently not used and is for future expansion. +PNG_EXPORT 178, void, png_read_png, '(png_structrp png_ptr, png_inforp info_ptr, int transforms, voidp params)' + +; 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. + +;#define PNG_INTERLACE_ADAM7_PASSES 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 + not eax + mov ebx,pass + 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,pass + 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 */ + +PNG_EXPORT 201, uint_32, png_get_uint_32, '(bytep buf)' +PNG_EXPORT 202, uint_16, png_get_uint_16, '(bytep buf)' +PNG_EXPORT 203, int_32, png_get_int_32, '(bytep buf)' + +PNG_EXPORT 204, uint_32, png_get_uint_31, '(png_const_structrp png_ptr, bytep buf)' +; No png_get_int_16 -- may be added if there's a real need for it. + +;if PNG_USE_READ_MACROS +; 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))) + +; If PNG_PREFIX is defined the same thing as below happens in pnglibconf.h, +; but defining a macro name prefixed with PNG_PREFIX. + +;# ifndef PNG_PREFIX +;# define png_get_uint_32(buf) PNG_get_uint_32(buf) +;# define png_get_uint_16(buf) PNG_get_uint_16(buf) +;# define png_get_int_32(buf) PNG_get_int_32(buf) +;# endif +;#else +;# ifdef PNG_PREFIX + ; No macros; revert to the (redefined) function +;# define PNG_get_uint_32 (png_get_uint_32) +;# define PNG_get_uint_16 (png_get_uint_16) +;# define PNG_get_int_32 (png_get_int_32) +;# endif +;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 + +;if PNG_FORMAT_BGR_SUPPORTED +PNG_FORMAT_FLAG_BGR equ 0x10 ;BGR colors, else order is RGB +;end if + +;if PNG_FORMAT_AFIRST_SUPPORTED +PNG_FORMAT_FLAG_AFIRST equ 0x20 ;alpha channel comes first +;end if + +; 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_READ_SUPPORTED +; READ APIs +; --------- + +; The png_image passed to the read APIs must have been initialized by setting +; the png_controlp field 'opaque' to NULL (or, safer, memset the whole thing.) + +if PNG_STDIO_SUPPORTED eq 1 +PNG_EXPORT 234, int, png_image_begin_read_from_file, '(png_imagep image, const char *file_name)' +; The named file is opened for read and the image header is filled in +; from the PNG header in the file. + +PNG_EXPORT 235, int, png_image_begin_read_from_stdio, '(png_imagep image, FILE* file)' +; The PNG header is read from the stdio FILE object. +end if ;STDIO + +PNG_EXPORT 236, int, png_image_begin_read_from_memory, '(png_imagep image, png_const_voidp memory, png_size_t size)' +; The PNG header is read from the given memory buffer. + +PNG_EXPORT 237, int, png_image_finish_read, '(png_imagep image, png_const_colorp background, void *buffer, int_32 row_stride, void *colormap)' +; Finish reading the image into the supplied buffer and clean up the +; png_image structure. + +; row_stride is the step, in byte or 2-byte units as appropriate, +; between adjacent rows. A positive stride indicates that the top-most row +; is first in the buffer - the normal top-down arrangement. A negative +; stride indicates that the bottom-most row is first in the buffer. + +; background need only be supplied if an alpha channel must be removed from +; a byte format and the removal is to be done by compositing on a solid +; color; otherwise it may be NULL and any composition will be done directly +; onto the buffer. The value is an sRGB color to use for the background, +; for grayscale output the green channel is used. + +; background must be supplied when an alpha channel must be removed from a +; single byte color-mapped output format, in other words if: + +; 1) The original format from png_image_begin_read_from_* had +; PNG_FORMAT_FLAG_ALPHA set. +; 2) The format set by the application does not. +; 3) The format set by the application has PNG_FORMAT_FLAG_COLORMAP set and +; PNG_FORMAT_FLAG_LINEAR *not* set. + +; For linear output removing the alpha channel is always done by compositing +; on black and background is ignored. + +; colormap must be supplied when PNG_FORMAT_FLAG_COLORMAP is set. It must +; be at least the size (in bytes) returned by PNG_IMAGE_COLORMAP_SIZE. +; image->colormap_entries will be updated to the actual number of entries +; written to the colormap; this may be less than the original value. + + +;end if /* SIMPLIFIED_READ */ + +;if PNG_SIMPLIFIED_WRITE_SUPPORTED +;/* 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 new file mode 100644 index 0000000000..001d216302 --- /dev/null +++ b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngerror.asm @@ -0,0 +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 + diff --git a/programs/develop/libraries/libs-dev/libimg/png/libpng/pngget.asm b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngget.asm new file mode 100644 index 0000000000..75de1c6fce --- /dev/null +++ b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngget.asm @@ -0,0 +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 +; return png_ptr->IDAT_read_size; +else + mov eax,PNG_IDAT_READ_SIZE + jmp .end_f +end if +; } + +if PNG_WRITE_SUPPORTED eq 1 +; else +; return png_ptr->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 new file mode 100644 index 0000000000..cc8f6b498d --- /dev/null +++ b/programs/develop/libraries/libs-dev/libimg/png/libpng/pnginfo.inc @@ -0,0 +1,254 @@ + +; 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 defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_EXPAND_SUPPORTED) || \ +;defined(PNG_READ_BACKGROUND_SUPPORTED) + ; 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 new file mode 100644 index 0000000000..a45e43eb88 --- /dev/null +++ b/programs/develop/libraries/libs-dev/libimg/png/libpng/pnglibconf.inc @@ -0,0 +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 1 +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 1 +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 1 +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 1 +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 1 +PNG_WRITE_TRANSFORMS_SUPPORTED equ 1 +PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED equ 1 +PNG_WRITE_USER_TRANSFORM_SUPPORTED equ 1 +PNG_WRITE_WEIGHTED_FILTER_SUPPORTED equ 1 +PNG_WRITE_bKGD_SUPPORTED equ 1 +PNG_WRITE_cHRM_SUPPORTED equ 1 +PNG_WRITE_gAMA_SUPPORTED equ 1 +PNG_WRITE_hIST_SUPPORTED equ 1 +PNG_WRITE_iCCP_SUPPORTED equ 1 +PNG_WRITE_iTXt_SUPPORTED equ 1 +PNG_WRITE_oFFs_SUPPORTED equ 1 +PNG_WRITE_pCAL_SUPPORTED equ 1 +PNG_WRITE_pHYs_SUPPORTED equ 1 +PNG_WRITE_sBIT_SUPPORTED equ 1 +PNG_WRITE_sCAL_SUPPORTED equ 1 +PNG_WRITE_sPLT_SUPPORTED equ 1 +PNG_WRITE_sRGB_SUPPORTED equ 1 +PNG_WRITE_tEXt_SUPPORTED equ 1 +PNG_WRITE_tIME_SUPPORTED equ 1 +PNG_WRITE_tRNS_SUPPORTED equ 1 +PNG_WRITE_zTXt_SUPPORTED equ 1 +PNG_bKGD_SUPPORTED equ 1 +PNG_cHRM_SUPPORTED equ 1 +PNG_gAMA_SUPPORTED equ 1 +PNG_hIST_SUPPORTED equ 1 +PNG_iCCP_SUPPORTED equ 1 +PNG_iTXt_SUPPORTED equ 1 +PNG_oFFs_SUPPORTED equ 1 +PNG_pCAL_SUPPORTED equ 1 +PNG_pHYs_SUPPORTED equ 1 +PNG_sBIT_SUPPORTED equ 1 +PNG_sCAL_SUPPORTED equ 1 +PNG_sPLT_SUPPORTED equ 1 +PNG_sRGB_SUPPORTED equ 1 +PNG_tEXt_SUPPORTED equ 1 +PNG_tIME_SUPPORTED equ 1 +PNG_tRNS_SUPPORTED equ 1 +PNG_zTXt_SUPPORTED equ 1 +; 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 new file mode 100644 index 0000000000..e49f536084 --- /dev/null +++ b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngmem.asm @@ -0,0 +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 + diff --git a/programs/develop/libraries/libs-dev/libimg/png/libpng/pngpriv.inc b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngpriv.inc new file mode 100644 index 0000000000..0e76add99e --- /dev/null +++ b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngpriv.inc @@ -0,0 +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 diff --git a/programs/develop/libraries/libs-dev/libimg/png/libpng/pngset.asm b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngset.asm new file mode 100644 index 0000000000..b2cb803909 --- /dev/null +++ b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngset.asm @@ -0,0 +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_const_color_16p background) +align 4 +proc png_set_bKGD, png_ptr:dword, info_ptr:dword, background:dword + png_debug1 1, 'in %s storage function', 'bKGD' + +; if (png_ptr == NULL || info_ptr == NULL || background == NULL) +; return; + +; info_ptr->background = *background; +; info_ptr->valid |= PNG_INFO_bKGD; + ret +endp + +;if PNG_cHRM_SUPPORTED +;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 + +;end if /* cHRM */ + +;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_const_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 + jg @f ;if (..<0 || ..>3) + jmp .end0 + @@: + png_error edi, 'Invalid pCAL equation type' + .end0: + + cmp dword[type],0 + jl @f + cmp dword[type],255 + jg @f ;if (..<0 || ..>255) + jmp .end1 + @@: + 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_const_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_const_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_const_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_const_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_const_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_const_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_const_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_const_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 new file mode 100644 index 0000000000..f4454dd21f --- /dev/null +++ b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngstruct.inc @@ -0,0 +1,443 @@ + +; 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 dd ? ;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 +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 + +; 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 ? ;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 + background_gamma dd ? ;png_fixed_point + background png_color_16 ;background color in screen gamma space +if PNG_READ_GAMMA_SUPPORTED eq 1 + background_1 png_color_16 ;background normalized to gamma 1.0 +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 +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 +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 +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; +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 +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 + +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. + +; png_unknown_chunk unknown_chunk; +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 +; void (*read_filter[PNG_FILTER_VALUE_LAST-1])(png_row_infop row_info, +; bytep row, bytep prev_row); + +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 new file mode 100644 index 0000000000..46d01916b5 --- /dev/null +++ b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngtokos.inc @@ -0,0 +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 +} + diff --git a/programs/develop/libraries/libs-dev/libimg/png/libpng/pngtrans.asm b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngtrans.asm new file mode 100644 index 0000000000..cd37537cfc --- /dev/null +++ b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngtrans.asm @@ -0,0 +1,886 @@ + +; 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] + cmp edi,0 + je @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] + cmp edi,0 + je @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] + cmp edi,0 + je @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] + cmp edi,0 + je @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_const_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] + cmp edi,0 + je @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] + cmp edi,0 + je @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] + cmp edi,0 + je .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 + cmp eax,0 + je @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] + cmp edi,0 + je .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 + cmp eax,0 + je .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] + cmp edi,0 + je .end_f ;if (..==0) return + +; png_ptr->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] + cmp edi,0 + je .end_f ;if (..==0) return + +; png_ptr->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] + cmp edi,0 + je .end_f ;if (..==0) return + +; png_ptr->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, row_info:dword, row:dword + png_debug 1, 'in png_do_invert' + + ; This test removed from libpng version 1.0.13 and 1.2.0: + ; if (row_info->bit_depth == 1 && + +; if (row_info->color_type == PNG_COLOR_TYPE_GRAY) +; { +; bytep rp = row; +; png_size_t i; +; png_size_t istop = row_info->rowbytes; + +; for (i = 0; i < istop; i++) +; { +; *rp = (byte)(~(*rp)); +; rp++; +; } +; } + +; else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && +; row_info->bit_depth == 8) +; { +; bytep rp = row; +; png_size_t i; +; png_size_t istop = row_info->rowbytes; + +; for (i = 0; i < istop; i += 2) +; { +; *rp = (byte)(~(*rp)); +; rp += 2; +; } +; } + +if PNG_16BIT_SUPPORTED eq 1 +; else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && +; row_info->bit_depth == 16) +; { +; bytep rp = row; +; png_size_t i; +; png_size_t istop = row_info->rowbytes; + +; for (i = 0; i < istop; i += 4) +; { +; *rp = (byte)(~(*rp)); +; *(rp + 1) = (byte)(~(*(rp + 1))); +; rp += 4; +; } +; } +end if + 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' + +; if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0) +; { +; uint_32 row_width = row_info->width; +; if (row_info->bit_depth == 8) +; { +; if (row_info->color_type == PNG_COLOR_TYPE_RGB) +; { +; bytep rp; +; uint_32 i; + +; for (i = 0, rp = row; i < row_width; i++, rp += 3) +; { +; byte save = *rp; +; *rp = *(rp + 2); +; *(rp + 2) = save; +; } +; } + +; else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) +; { +; bytep rp; +; uint_32 i; + +; for (i = 0, rp = row; i < row_width; i++, rp += 4) +; { +; byte save = *rp; +; *rp = *(rp + 2); +; *(rp + 2) = save; +; } +; } +; } + +if PNG_16BIT_SUPPORTED eq 1 +; else if (row_info->bit_depth == 16) +; { +; if (row_info->color_type == PNG_COLOR_TYPE_RGB) +; { +; bytep rp; +; uint_32 i; + +; for (i = 0, rp = row; i < row_width; i++, rp += 6) +; { +; byte save = *rp; +; *rp = *(rp + 4); +; *(rp + 4) = save; +; save = *(rp + 1); +; *(rp + 1) = *(rp + 5); +; *(rp + 5) = save; +; } +; } + +; else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) +; { +; bytep rp; +; uint_32 i; + +; for (i = 0, rp = row; i < row_width; i++, rp += 8) +; { +; byte save = *rp; +; *rp = *(rp + 4); +; *(rp + 4) = save; +; save = *(rp + 1); +; *(rp + 1) = *(rp + 5); +; *(rp + 5) = save; +; } +; } +; } +end if +; } + 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] + cmp edi,0 + je .end_f + +if PNG_READ_USER_TRANSFORM_SUPPORTED eq 1 + mov eax,[edi+png_struct.mode] + and eax,PNG_IS_READ_STRUCT + cmp eax,0 + je @f + mov eax,[edi+png_struct.flags] + and eax,PNG_FLAG_ROW_INIT + cmp eax,0 + je @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_const_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_const_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_const_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 new file mode 100644 index 0000000000..956e74d69e --- /dev/null +++ b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngwio.asm @@ -0,0 +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 diff --git a/programs/develop/libraries/libs-dev/libimg/png/libpng/pngwrite.asm b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngwrite.asm new file mode 100644 index 0000000000..ff6abb1b4d --- /dev/null +++ b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngwrite.asm @@ -0,0 +1,3318 @@ + +; 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] + cmp eax,0 + je .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 + cmp eax,0 + jne .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 + cmp eax,0 + je @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 + cmp eax,0 + jne @f + movzx eax,word[esi+png_info_def.colorspace.flags] + and eax,PNG_COLORSPACE_FROM_gAMA + cmp eax,0 + je @f + mov eax,[esi+png_info_def.valid] + and eax,PNG_INFO_gAMA + cmp eax,0 + je @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 + cmp eax,0 + jne .end0 + mov eax,[esi+png_info_def.valid] + and eax,PNG_INFO_iCCP + cmp eax,0 + je .end0 ;if (..==0 && ..!=0) +if PNG_WRITE_sRGB_SUPPORTED eq 1 + mov eax,[esi+png_info_def.valid] + and eax,PNG_INFO_sRGB + cmp eax,0 + je @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 + cmp eax,0 + jne .end1 + mov eax,[esi+png_info_def.valid] + and eax,PNG_INFO_sRGB + cmp eax,0 + je .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 + cmp eax,0 + je @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 + cmp eax,0 + jne @f + movzx eax,word[esi+png_info_def.colorspace.flags] + and eax,PNG_COLORSPACE_FROM_cHRM + cmp eax,0 + je @f + mov eax,[esi+png_info_def.valid] + and eax,PNG_INFO_cHRM + cmp eax,0 + je @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 + cmp eax,0 + je @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 + cmp eax,0 + je .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 + cmp eax,0 + je @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 + cmp eax,0 + je @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 + cmp eax,0 + je @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 + cmp eax,0 + je @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 + cmp eax,0 + je @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 + cmp eax,0 + je @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 + cmp eax,0 + je @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 + cmp eax,0 + je @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 + cmp eax,0 + jne @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 + cmp eax,0 + je @f + mov eax,[edi+png_struct.mode] + and eax,PNG_WROTE_tIME + cmp eax,0 + jne @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 + cmp eax,0 + je .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 + cmp eax,0 + je .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 + cmp eax,0 + jne @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 + cmp eax,0 + je @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 + cmp eax,0 + je @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 + cmp eax,0 + je @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 + cmp eax,0 + je @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 + cmp eax,0 + je @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 + cmp eax,0 + je @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 + cmp eax,0 + je @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 + cmp eax,0 + je .end1 ;if(..!=0 && ..!=0) + cmp byte[edi+png_struct.pass],0 + jne @f + mov eax,[edi+png_struct.row_number] + and eax,0x07 + cmp eax,0 + je .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 + cmp eax,0 + jne .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 + cmp eax,0 + jne .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 + cmp eax,0 + jne .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 + cmp eax,0 + jne .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 + cmp eax,0 + je @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 + cmp eax,0 + je @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 + cmp eax,0 + je @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 + cmp eax,0 + je @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 + cmp eax,0 + je @f ;if (..) + inc ebx + @@: + mov eax,[filters] + and eax,PNG_FILTER_UP + cmp eax,0 + je @f ;if (..) + inc ebx + @@: + mov eax,[filters] + and eax,PNG_FILTER_AVG + cmp eax,0 + je @f ;if (..) + inc ebx + @@: + mov eax,[filters] + and eax,PNG_FILTER_PAETH + cmp eax,0 + je @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 + cmp eax,0 + je @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 + cmp eax,0 + je @f ;if(..!=0) +if PNG_WRITE_SHIFT_SUPPORTED eq 1 + mov eax,[esi+png_info_def.valid] + and eax,PNG_INFO_sBIT + cmp eax,0 + je @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 + cmp eax,0 + je @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 + cmp eax,0 + je @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 + cmp eax,0 + je .end_0 ;if(..!=0) +if PNG_WRITE_FILLER_SUPPORTED eq 1 + and eax,PNG_TRANSFORM_STRIP_FILLER_AFTER + cmp eax,0 + je .end_1 ;if(..!=0) + mov eax,[transforms] + and eax,PNG_TRANSFORM_STRIP_FILLER_BEFORE + cmp eax,0 + je @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 + cmp eax,0 + je @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 + cmp eax,0 + je @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 + cmp eax,0 + je @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 + cmp eax,0 + je @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 + + cmp eax,0 + je .end0 ;if (..!=0) + mov edi,eax + stdcall png_create_info_struct, edi + ;eax = info_ptr + + cmp eax,0 + je .end1 ;if (..!=0) + mov esi,eax + stdcall png_malloc_warn, edi, sizeof.png_control + ;control = eax + + cmp eax,0 + je .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 eax,[edx+png_image.format] + and eax,PNG_FORMAT_FLAG_COLOR + mov ecx,1 + cmp eax,0 + je @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 + cmp eax,0 + je .end0 ;if (..!=0) +if PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED eq 1 + mov eax,[edx+png_image.format] + and eax,PNG_FORMAT_FLAG_AFIRST + cmp eax,0 + je @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 eax,[edx+png_image.format] + and eax,PNG_FORMAT_FLAG_COLOR + mov ecx,1 + cmp eax,0 + je @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 + cmp eax,0 + je .end0 ;if (..!=0) +; bytep row_end; +; int aindex; + +if PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED eq 1 +; if ((image->format & PNG_FORMAT_FLAG_AFIRST) != 0) +; { +; aindex = -1; +; ++input_row; /* To point to the first component */ +; ++output_row; +; } + +; else +end if +; aindex = channels; + + ; Use row_end in place of a loop counter: +; row_end = output_row + image->width * (channels+1); + +; 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 + cmp eax,0 + je @f + mov eax,ecx + and eax,PNG_FORMAT_FLAG_ALPHA + cmp eax,0 + je @f + mov dword[afirst],-1 + @@: +end if + +if PNG_FORMAT_BGR_SUPPORTED eq 1 + mov eax,ecx + and eax,PNG_FORMAT_FLAG_BGR + cmp eax,0 + je @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 + cmp eax,0 + je .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 + cmp eax,0 + je @f + or ecx,PNG_COLOR_MASK_COLOR + @@: + mov eax,[format] + and eax,PNG_FORMAT_FLAG_ALPHA + cmp eax,0 + je @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 + cmp eax,0 + jne @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 + cmp eax,0 + jne @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 + cmp eax,0 + je .end12 ;if (..!=0) + cmp dword[colormap],0 + jne @f + mov eax,[format] + and eax,PNG_FORMAT_FLAG_COLOR + cmp eax,0 + je @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 + cmp eax,0 + je .end13 ;if (..!=0) + cmp dword[colormap],0 + jne @f + mov eax,[format] + and eax,PNG_FORMAT_FLAG_ALPHA + cmp eax,0 + je @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) + cmp eax,0 + je @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 + cmp eax,0 + je @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: + cmp eax,0 + je .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 + mov ecx,[edx+png_image_write_control.row_bytes] + inc ecx + imul ecx,[ebx+png_image.height] + cmp ecx,1 + jl .end8 + stdcall create_compress_IDAT, edi, [edx+png_image_write_control.first_row], ecx, [ebx+png_image.width], [ebx+png_image.height] +else ;;; not work, 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] + cmp eax,0 + je .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 + cmp eax,0 + je .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 + + 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 + @@: + + 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 edi esi + mov edx,[png_ptr] + ; Up filter + stdcall png_setup_up_row, edx, esi, [mins] + cmp eax,[mins] + jge .end2 ;if (..<..) +;png_debug 3, '(Up)' + mov eax,[edx+png_struct.try_row] + cmp eax,0 + je .end2 ;if (..!=0) + mov ecx,esi + inc ecx + mov esi,eax + rep movsb ;copy row + .end2: + pop esi edi 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 word[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 cx,[edi+png_struct.zstream.avail_out] + cmp word[edi+png_struct.zstream.avail_out],0 + je .cycle4 ;while (strm.avail_out == 0) +if 0 + mov word[edi+png_struct.zstream.avail_out],16*1024 + stdcall [deflate], esi, Z_FINISH + 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 + cmp eax,0 + jne @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 + @@: + stdcall png_free, edi, [m1] +.end0: + stdcall png_free, edi, [buf_f] +.end_f: +popad + 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 + cmp eax,0 + je .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 new file mode 100644 index 0000000000..d970f539cb --- /dev/null +++ b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngwtran.asm @@ -0,0 +1,610 @@ + +; 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 + cmp eax,0 + je @f ;if (..!=0) + mov eax,[edi+png_struct.write_user_transform_fn] + cmp eax,0 + je @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 + cmp eax,0 + je @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 + cmp eax,0 + je @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 + cmp eax,0 + je @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 + cmp eax,0 + je @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 + cmp eax,0 + je @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 + cmp eax,0 + je @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 + cmp eax,0 + je @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 + cmp eax,0 + je @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 + cmp eax,0 + je @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 new file mode 100644 index 0000000000..bf41944c02 --- /dev/null +++ b/programs/develop/libraries/libs-dev/libimg/png/libpng/pngwutil.asm @@ -0,0 +1,3319 @@ + +; 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 defined(PNG_DEBUG) && (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] + cmp edi,0 + je .end_f ;if (png_ptr == NULL) 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 + mov ebx,ebp + sub ebx,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 + + mov ebx,ebp + sub ebx,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 + mov ebx,ebp + sub ebx,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] + cmp edi,0 + je .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 + cmp eax,0 + je @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 + cmp eax,0 + je .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 word[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 + cmp eax,0 + je @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],ax + + 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 word[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 + + cmp eax,0 + jne .end1 ;if (..==0) + PNG_COMPRESSION_BUFFER_SIZE edi + stdcall png_malloc, edi, eax + mov [next],eax + + cmp eax,0 + jne @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],ax + 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. + + movzx eax,word[edi+png_struct.zstream.avail_out] + sub [output_len],eax + mov word[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 + cmp eax,0 + jne .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 + cmp eax,0 + jne @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],ax + .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] + jle @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 word[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 + cmp eax,0 + jne @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],cx + + ; 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] + sub cx,[edi+png_struct.zstream.avail_out] + ;edx = data + ;ecx = size + +if PNG_WRITE_OPTIMIZE_CMF_SUPPORTED eq 1 + mov eax,[edi+png_struct.mode] + and eax,PNG_HAVE_IDAT + cmp eax,0 + jne @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 word[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 + + cmp eax,0 + jne @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 + + cmp eax,0 + jne @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 + + cmp eax,0 + jne @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 + cmp eax,0 + jne @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] +;png_debug1 2, ' row_number = %d', eax +;png_debug1 2, ' num_rows = %d', [edi+png_struct.num_rows] + 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 + cmp eax,0 + je @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 + cmp eax,0 + jne .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 [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 + mov ah,byte[ebx] + shr ah,1 + sub al,ah + mov ah,byte[edx] + shr ah,1 + sub al,ah + stosb + png_setup_abs [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, png_ptr:dword, bpp:dword, row_bytes:dword, lmins:dword +; bytep rp, dp, pp, cp, lp; +; png_size_t i; +; png_size_t sum = 0; +; int v; + +; png_ptr->try_row[0] = PNG_FILTER_VALUE_PAETH; + +; for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1, +; pp = png_ptr->prev_row + 1; i < bpp; i++) +; { +; v = *dp++ = (byte)(((int)*rp++ - (int)*pp++) & 0xff); + +if PNG_USE_ABS eq 1 +; sum += 128 - abs(v - 128); +else +; sum += (v < 128) ? v : 256 - v; +end if +; } + +; for (lp = png_ptr->row_buf + 1, cp = png_ptr->prev_row + 1; i < row_bytes; +; i++) +; { +; int a, b, c, pa, pb, pc, p; + +; b = *pp++; +; c = *cp++; +; a = *lp++; + +; p = b - c; +; pc = a - c; + +if PNG_USE_ABS eq 1 +; pa = abs(p); +; pb = abs(pc); +; pc = abs(p + pc); +else +; pa = p < 0 ? -p : p; +; pb = pc < 0 ? -pc : pc; +; pc = (p + pc) < 0 ? -(p + pc) : p + pc; +end if + +; p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; + +; v = *dp++ = (byte)(((int)*rp++ - p) & 0xff); + +if PNG_USE_ABS eq 1 +; sum += 128 - abs(v - 128); +else +; sum += (v < 128) ? v : 256 - v; +end if + +; if (sum > lmins) /* We are already worse, don't continue. */ +; break; +; } + +; return (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 +; bytep rp, dp, pp, cp, lp; +; png_size_t i; + +; png_ptr->try_row[0] = PNG_FILTER_VALUE_PAETH; + +; for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1, +; pp = png_ptr->prev_row + 1; i < bpp; i++) +; { +; *dp++ = (byte)(((int)*rp++ - (int)*pp++) & 0xff); +; } + +; for (lp = png_ptr->row_buf + 1, cp = png_ptr->prev_row + 1; i < row_bytes; +; i++) +; { +; int a, b, c, pa, pb, pc, p; + +; b = *pp++; +; c = *cp++; +; a = *lp++; + +; p = b - c; +; pc = a - c; + +if PNG_USE_ABS eq 1 +; pa = abs(p); +; pb = abs(pc); +; pc = abs(p + pc); +else +; pa = p < 0 ? -p : p; +; pb = pc < 0 ? -pc : pc; +; pc = (p + pc) < 0 ? -(p + pc) : p + pc; +end if + +; p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; + +; *dp++ = (byte)(((int)*rp++ - p) & 0xff); +; } + 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 1 + 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] + mov eax,[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 PNG_SIZE_MAX/128, dword[row_bytes] + jg @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 + cmp eax,0 + je .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 + cmp eax,0 + je .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 + cmp eax,0 + je .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 + cmp eax,0 + je .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 + cmp eax,0 + je .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 + cmp eax,0 + je .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 + cmp eax,0 + je .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 + cmp eax,0 + je .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 + cmp eax,0 + je .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] + cmp eax,0 + je @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 a50ebe1493..c103c87399 100644 --- a/programs/develop/libraries/libs-dev/libimg/png/png.asm +++ b/programs/develop/libraries/libs-dev/libimg/png/png.asm @@ -17,6 +17,8 @@ ;; ;; ;;================================================================================================;; +include 'libpng/png.asm' + ;;================================================================================================;; ;;proc img.is.png _data, _length ;////////////////////////////////////////////////////////////////;; img.is.png: @@ -1076,6 +1078,64 @@ local .l1 ret ;endp -img.encode.png: - xor eax, eax - ret 12 + + +;;================================================================================================;; +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] + 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