Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 6723 → Rev 6733

/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:
/programs/develop/libraries/libs-dev/libimg/libimg.asm
68,6 → 68,11
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
.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
 
; 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
/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(&gtest, 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<<bitshift;
; }
 
; else
; if (s32 == d32 && s00 >= d00)
; s32 = 0, s00 -= d00, result += 1<<bitshift;
; }
 
; /* Handle the rounding. */
; if (s00 >= (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:
 
; <all high 8-bit values><n << gamma_shift>..<(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 */
/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,
; <http://www.w3.org/TR/2003/REC-PNG-20031110/
 
 
 
; Y2K compliance in libpng:
; =========================
 
; September 1, 2016
 
; Since the PNG Development group is an ad-hoc body, we can't make
; an official declaration.
 
; This is your unofficial assurance that libpng from version 0.71 and
; upward through 1.6.25 are Y2K compliant. It is my belief that
; earlier versions were also Y2K compliant.
 
; Libpng only has two year fields. One is a 2-byte unsigned integer
; that will hold years up to 65535. The other, which is deprecated,
; holds the date in text format, and will hold years up to 9999.
 
; The integer is
; "uint_16 year" in png_time_struct.
 
; The string is
; "char time_buffer[29]" in png_struct. This is no longer used
; in libpng-1.6.x and will be removed from libpng-1.7.0.
 
; There are seven time-related functions:
; png.asm: png_convert_to_rfc_1123_buffer() in png.asm
; (formerly png_convert_to_rfc_1123() prior to libpng-1.5.x and
; png_convert_to_rfc_1152() in error prior to libpng-0.98)
; png_convert_from_struct_tm() in pngwrite.asm, called in pngwrite.asm
; png_convert_from_time_t() in pngwrite.asm
; png_get_tIME() in pngget.asm
; png_handle_tIME() in pngrutil.asm, called in pngread.asm
; png_set_tIME() in pngset.asm
; png_write_tIME() in pngwutil.asm, called in pngwrite.asm
 
; All handle dates properly in a Y2K environment. The
; png_convert_from_time_t() function calls gmtime() to convert from system
; clock time, which returns (year - 1900), which we properly convert to
; the full 4-digit year. There is a possibility that libpng applications
; are not passing 4-digit years into the png_convert_to_rfc_1123_buffer()
; function, or that they are incorrectly passing only a 2-digit year
; instead of "year - 1900" into the png_convert_from_struct_tm() function,
; but this is not under our control. The libpng documentation has always
; stated that it works with 4-digit years, and the APIs have been
; documented as such.
 
; The tIME chunk itself is also Y2K compliant. It uses a 2-byte unsigned
; integer to hold the year, and can hold years as large as 65535.
 
; zlib, upon which libpng depends, is also Y2K compliant. It contains
; no date-related code.
 
; Glenn Randers-Pehrson
; libpng maintainer
; PNG Development Group
 
 
; This is not the place to learn how to use libpng. The file libpng-manual.txt
; describes how to use libpng, and the file example.c summarizes it
; with some code on which to build. This file is useful for looking
; at the actual function definitions and structure components. If that
; file has been stripped from your copy of libpng, you can find it at
; <http://www.libpng.org/pub/png/libpng-manual.txt>
 
; 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_<chunk> 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 <setjmp.h>, 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)<<PNG_PASS_ROW_SHIFT(pass))+PNG_PASS_START_ROW(pass))
;#define PNG_COL_FROM_PASS_COL(x_in, pass) \
; (((x_in)<<PNG_PASS_COL_SHIFT(pass))+PNG_PASS_START_COL(pass))
 
; Two macros which return a boolean (0 or 1) saying whether the given row
; or column is in a particular pass. These use a common utility macro that
; returns a mask for a given pass - the offset 'off' selects the row or
; column version. The mask has the appropriate bit set for each column in
; the tile.
 
;#define PNG_PASS_MASK(pass,off) ( \
; ((0x110145AF>>(((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
/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 @<number>, 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
 
/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
 
/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
/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
/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
 
/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
/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; i<nparams; ++i)
; {
; if (params[i] == NULL ||
; !png_check_fp_string(params[i], strlen(params[i])))
; png_error(png_ptr, "Invalid format for pCAL parameter");
; }
 
; info_ptr->pcal_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<count; ++i, list += 5)
; {
; if (memcmp(list, p3add, 4) == 0)
; {
; list[4] = (byte)keep;
 
; return count;
; }
; }
 
; if (keep != PNG_HANDLE_CHUNK_AS_DEFAULT)
; {
; ++count;
; memcpy(list, p3add, 4);
; list[4] = (byte)keep;
; }
 
; return count;
ret
endp
 
;void (png_structrp png_ptr, int keep, bytep chunk_list, int num_chunks_in)
align 4
proc png_set_keep_unknown_chunks uses edi, png_ptr:dword, keep:dword, chunk_list:dword, num_chunks_in:dword
; bytep new_list;
; uint num_chunks, old_num_chunks;
 
mov edi,[png_ptr]
cmp edi,0
je .end_f ;if (..== 0) return
 
; if (keep < 0 || keep >= 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; i<num_chunks; ++i)
; {
; old_num_chunks = add_one_chunk(new_list, old_num_chunks,
; chunk_list+5*i, keep);
; }
 
; Now remove any spurious 'default' entries.
; num_chunks = 0;
; for (i=0, inlist=outlist=new_list; i<old_num_chunks; ++i, inlist += 5)
; {
; if (inlist[4])
; {
; if (outlist != inlist)
; memcpy(outlist, inlist, 5);
; outlist += 5;
; ++num_chunks;
; }
; }
 
; This means the application has removed all the specialized handling.
; if (num_chunks == 0)
; {
; if (png_ptr->chunk_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
 
/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
/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,<txt>
}
 
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
}
 
/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
/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
/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; j<jend; ++j)
; info_ptr->trans_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<alpha, so component/alpha is less than one and
; component*reciprocal is less than 2^31.
 
; else if (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<alpha, so component/alpha is less than one and
; component*reciprocal is less than 2^31.
 
.end0: ;else if (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<entries; ++i)
; {
; This gets automatically converted to sRGB with reversal of the
; pre-multiplication if the color-map has an alpha channel.
 
; if ((format & PNG_FORMAT_FLAG_LINEAR) != 0)
; {
; png_const_uint_16p entry = cmap;
 
; entry += i * channels;
 
; if ((channels & 1) != 0) /* no alpha */
; {
; if (channels >= 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
/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
/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 "<chunk> 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; ep<spalette->entries + 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
/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
ret
;endp
 
img.encode.png:
 
 
;;================================================================================================;;
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
ret 12
.quit:
ret
endp