/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(>est, colorspace->gamma, PNG_FP_1, gAMA) == 0 || |
; png_gamma_significant(gtest) != 0)) |
; { |
; Either this is an sRGB image, in which case the calculated gamma |
; approximation should match, or this is an image with a profile and the |
; value libpng calculates for the gamma of the profile does not match the |
; value recorded in the file. The former, sRGB, case is an error, the |
; latter is just a warning. |
; if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0 || from == 2) |
; { |
; png_chunk_report(png_ptr, "gamma value does not match sRGB", |
; PNG_CHUNK_ERROR); |
; /* Do not overwrite an sRGB value */ |
; return from == 2; |
; } |
; else /* sRGB tag not involved */ |
; { |
; png_chunk_report(png_ptr, "gamma value does not match libpng estimate", |
; PNG_CHUNK_WARNING); |
; return from == 1; |
; } |
; } |
; return 1; |
ret |
endp |
;void (png_structrp png_ptr, png_colorspacerp colorspace, png_fixed_point gAMA) |
align 4 |
proc png_colorspace_set_gamma, png_ptr:dword, colorspace:dword, gAMA:dword |
; Changed in libpng-1.5.4 to limit the values to ensure overflow can't |
; occur. Since the fixed point representation is asymetrical it is |
; possible for 1/gamma to overflow the limit of 21474 and this means the |
; gamma value must be at least 5/100000 and hence at most 20000.0. For |
; safety the limits here are a little narrower. The values are 0.00016 to |
; 6250.0, which are truly ridiculous gamma values (and will produce |
; displays that are all black or all white.) |
; In 1.6.0 this test replaces the ones in pngrutil.c, in the gAMA chunk |
; handling code, which only required the value to be >0. |
; charp errmsg; |
; if (gAMA < 16 || gAMA > 625000000) |
; errmsg = "gamma value out of range"; |
;# ifdef PNG_READ_gAMA_SUPPORTED |
; Allow the application to set the gamma value more than once |
; else if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 && |
; (colorspace->flags & PNG_COLORSPACE_FROM_gAMA) != 0) |
; errmsg = "duplicate"; |
;# endif |
; Do nothing if the colorspace is already invalid |
; else if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0) |
; return; |
; else |
; { |
; if (png_colorspace_check_gamma(png_ptr, colorspace, gAMA, |
; 1/*from gAMA*/) != 0) |
; { |
; /* Store this gamma value. */ |
; colorspace->gamma = gAMA; |
; colorspace->flags |= |
; (PNG_COLORSPACE_HAVE_GAMMA | PNG_COLORSPACE_FROM_gAMA); |
; } |
; At present if the check_gamma test fails the gamma of the colorspace is |
; not updated however the colorspace is not invalidated. This |
; corresponds to the case where the existing gamma comes from an sRGB |
; chunk or profile. An error message has already been output. |
; return; |
; } |
; Error exit - errmsg has been set. |
; colorspace->flags |= PNG_COLORSPACE_INVALID; |
; png_chunk_report(png_ptr, errmsg, PNG_CHUNK_WRITE_ERROR); |
.end_f: |
ret |
endp |
;void (png_structrp png_ptr, png_inforp info_ptr) |
align 4 |
proc png_colorspace_sync_info uses eax esi, png_ptr:dword, info_ptr:dword |
mov esi,[info_ptr] |
mov ax,[esi+png_info_def.colorspace.flags] |
and ax,PNG_COLORSPACE_INVALID |
cmp ax,0 |
je @f ;if (..!=0) |
; Everything is invalid |
and dword[esi+png_info_def.valid], not (PNG_INFO_gAMA or PNG_INFO_cHRM or PNG_INFO_sRGB or PNG_INFO_iCCP) |
if PNG_COLORSPACE_SUPPORTED eq 1 |
; Clean up the iCCP profile now if it won't be used. |
stdcall png_free_data, [png_ptr], esi, PNG_FREE_ICCP, -1 ;not used |
end if |
jmp .end0 |
@@: ;else |
if PNG_COLORSPACE_SUPPORTED eq 1 |
; Leave the INFO_iCCP flag set if the pngset.c code has already set |
; it; this allows a PNG to contain a profile which matches sRGB and |
; yet still have that profile retrievable by the application. |
mov ax,[esi+png_info_def.colorspace.flags] |
and ax,PNG_COLORSPACE_MATCHES_sRGB |
cmp ax,0 |
je @f ;if (..!=0) |
or dword[esi+png_info_def.valid], PNG_INFO_sRGB |
jmp .end1 |
@@: ;else |
and dword[esi+png_info_def.valid], not PNG_INFO_sRGB |
.end1: |
mov ax,[esi+png_info_def.colorspace.flags] |
and ax,PNG_COLORSPACE_HAVE_ENDPOINTS |
cmp ax,0 |
je @f ;if (..!=0) |
or dword[esi+png_info_def.valid], PNG_INFO_cHRM |
jmp .end2 |
@@: ;else |
and dword[esi+png_info_def.valid], not PNG_INFO_cHRM |
.end2: |
end if |
mov ax,[esi+png_info_def.colorspace.flags] |
and ax,PNG_COLORSPACE_HAVE_GAMMA |
cmp ax,0 |
je @f ;if (..!=0) |
or dword[esi+png_info_def.valid], PNG_INFO_gAMA |
jmp .end0 |
@@: ;else |
and dword[esi+png_info_def.valid], not PNG_INFO_gAMA |
.end0: |
ret |
endp |
;void (png_structrp png_ptr, png_inforp info_ptr) |
align 4 |
proc png_colorspace_sync uses ecx edi esi, png_ptr:dword, info_ptr:dword |
mov edi,[info_ptr] |
cmp edi,0 |
je @f ;if (..==0) ;reduce code size; check here not in the caller |
mov ecx,sizeof.png_colorspace |
mov esi,[png_ptr] |
mov esi,[esi+png_struct.colorspace] |
mov edi,[edi+png_info_def.colorspace] |
rep movsb |
stdcall png_colorspace_sync_info, [png_ptr], [info_ptr] |
@@: |
ret |
endp |
;end if /* GAMMA */ |
;if PNG_COLORSPACE_SUPPORTED |
; Added at libpng-1.5.5 to support read and write of true CIEXYZ values for |
; cHRM, as opposed to using chromaticities. These internal APIs return |
; non-zero on a parameter error. The X, Y and Z values are required to be |
; positive and less than 1.0. |
;int (png_xy *xy, const png_XYZ *XYZ) |
align 4 |
proc png_xy_from_XYZ, xy:dword, XYZ:dword |
; int_32 d, dwhite, whiteX, whiteY; |
; d = XYZ->red_X + XYZ->red_Y + XYZ->red_Z; |
; if (png_muldiv(&xy->redx, XYZ->red_X, PNG_FP_1, d) == 0) |
; return 1; |
; if (png_muldiv(&xy->redy, XYZ->red_Y, PNG_FP_1, d) == 0) |
; return 1; |
; dwhite = d; |
; whiteX = XYZ->red_X; |
; whiteY = XYZ->red_Y; |
; d = XYZ->green_X + XYZ->green_Y + XYZ->green_Z; |
; if (png_muldiv(&xy->greenx, XYZ->green_X, PNG_FP_1, d) == 0) |
; return 1; |
; if (png_muldiv(&xy->greeny, XYZ->green_Y, PNG_FP_1, d) == 0) |
; return 1; |
; dwhite += d; |
; whiteX += XYZ->green_X; |
; whiteY += XYZ->green_Y; |
; d = XYZ->blue_X + XYZ->blue_Y + XYZ->blue_Z; |
; if (png_muldiv(&xy->bluex, XYZ->blue_X, PNG_FP_1, d) == 0) |
; return 1; |
; if (png_muldiv(&xy->bluey, XYZ->blue_Y, PNG_FP_1, d) == 0) |
; return 1; |
; dwhite += d; |
; whiteX += XYZ->blue_X; |
; whiteY += XYZ->blue_Y; |
; The reference white is simply the sum of the end-point (X,Y,Z) vectors, |
; thus: |
; if (png_muldiv(&xy->whitex, whiteX, PNG_FP_1, dwhite) == 0) |
; return 1; |
; if (png_muldiv(&xy->whitey, whiteY, PNG_FP_1, dwhite) == 0) |
; return 1; |
; return 0; |
ret |
endp |
;int (png_XYZ *XYZ, const png_xy *xy) |
align 4 |
proc png_XYZ_from_xy, XYZ:dword, xy:dword |
; png_fixed_point red_inverse, green_inverse, blue_scale; |
; png_fixed_point left, right, denominator; |
; Check xy and, implicitly, z. Note that wide gamut color spaces typically |
; have end points with 0 tristimulus values (these are impossible end |
; points, but they are used to cover the possible colors). We check |
; xy->whitey against 5, not 0, to avoid a possible integer overflow. |
; if (xy->redx < 0 || xy->redx > PNG_FP_1) return 1; |
; if (xy->redy < 0 || xy->redy > PNG_FP_1-xy->redx) return 1; |
; if (xy->greenx < 0 || xy->greenx > PNG_FP_1) return 1; |
; if (xy->greeny < 0 || xy->greeny > PNG_FP_1-xy->greenx) return 1; |
; if (xy->bluex < 0 || xy->bluex > PNG_FP_1) return 1; |
; if (xy->bluey < 0 || xy->bluey > PNG_FP_1-xy->bluex) return 1; |
; if (xy->whitex < 0 || xy->whitex > PNG_FP_1) return 1; |
; if (xy->whitey < 5 || xy->whitey > PNG_FP_1-xy->whitex) return 1; |
; The reverse calculation is more difficult because the original tristimulus |
; value had 9 independent values (red,green,blue)x(X,Y,Z) however only 8 |
; derived values were recorded in the cHRM chunk; |
; (red,green,blue,white)x(x,y). This loses one degree of freedom and |
; therefore an arbitrary ninth value has to be introduced to undo the |
; original transformations. |
; Think of the original end-points as points in (X,Y,Z) space. The |
; chromaticity values (c) have the property: |
; C |
; c = --------- |
; X + Y + Z |
; For each c (x,y,z) from the corresponding original C (X,Y,Z). Thus the |
; three chromaticity values (x,y,z) for each end-point obey the |
; relationship: |
; x + y + z = 1 |
; This describes the plane in (X,Y,Z) space that intersects each axis at the |
; value 1.0; call this the chromaticity plane. Thus the chromaticity |
; calculation has scaled each end-point so that it is on the x+y+z=1 plane |
; and chromaticity is the intersection of the vector from the origin to the |
; (X,Y,Z) value with the chromaticity plane. |
; To fully invert the chromaticity calculation we would need the three |
; end-point scale factors, (red-scale, green-scale, blue-scale), but these |
; were not recorded. Instead we calculated the reference white (X,Y,Z) and |
; recorded the chromaticity of this. The reference white (X,Y,Z) would have |
; given all three of the scale factors since: |
; color-C = color-c * color-scale |
; white-C = red-C + green-C + blue-C |
; = red-c*red-scale + green-c*green-scale + blue-c*blue-scale |
; But cHRM records only white-x and white-y, so we have lost the white scale |
; factor: |
; white-C = white-c*white-scale |
; To handle this the inverse transformation makes an arbitrary assumption |
; about white-scale: |
; Assume: white-Y = 1.0 |
; Hence: white-scale = 1/white-y |
; Or: red-Y + green-Y + blue-Y = 1.0 |
; Notice the last statement of the assumption gives an equation in three of |
; the nine values we want to calculate. 8 more equations come from the |
; above routine as summarised at the top above (the chromaticity |
; calculation): |
; Given: color-x = color-X / (color-X + color-Y + color-Z) |
; Hence: (color-x - 1)*color-X + color.x*color-Y + color.x*color-Z = 0 |
; This is 9 simultaneous equations in the 9 variables "color-C" and can be |
; solved by Cramer's rule. Cramer's rule requires calculating 10 9x9 matrix |
; determinants, however this is not as bad as it seems because only 28 of |
; the total of 90 terms in the various matrices are non-zero. Nevertheless |
; Cramer's rule is notoriously numerically unstable because the determinant |
; calculation involves the difference of large, but similar, numbers. It is |
; difficult to be sure that the calculation is stable for real world values |
; and it is certain that it becomes unstable where the end points are close |
; together. |
; So this code uses the perhaps slightly less optimal but more |
; understandable and totally obvious approach of calculating color-scale. |
; This algorithm depends on the precision in white-scale and that is |
; (1/white-y), so we can immediately see that as white-y approaches 0 the |
; accuracy inherent in the cHRM chunk drops off substantially. |
; libpng arithmetic: a simple inversion of the above equations |
; ------------------------------------------------------------ |
; white_scale = 1/white-y |
; white-X = white-x * white-scale |
; white-Y = 1.0 |
; white-Z = (1 - white-x - white-y) * white_scale |
; white-C = red-C + green-C + blue-C |
; = red-c*red-scale + green-c*green-scale + blue-c*blue-scale |
; This gives us three equations in (red-scale,green-scale,blue-scale) where |
; all the coefficients are now known: |
; red-x*red-scale + green-x*green-scale + blue-x*blue-scale |
; = white-x/white-y |
; red-y*red-scale + green-y*green-scale + blue-y*blue-scale = 1 |
; red-z*red-scale + green-z*green-scale + blue-z*blue-scale |
; = (1 - white-x - white-y)/white-y |
; In the last equation color-z is (1 - color-x - color-y) so we can add all |
; three equations together to get an alternative third: |
; red-scale + green-scale + blue-scale = 1/white-y = white-scale |
; So now we have a Cramer's rule solution where the determinants are just |
; 3x3 - far more tractible. Unfortunately 3x3 determinants still involve |
; multiplication of three coefficients so we can't guarantee to avoid |
; overflow in the libpng fixed point representation. Using Cramer's rule in |
; floating point is probably a good choice here, but it's not an option for |
; fixed point. Instead proceed to simplify the first two equations by |
; eliminating what is likely to be the largest value, blue-scale: |
; blue-scale = white-scale - red-scale - green-scale |
; Hence: |
; (red-x - blue-x)*red-scale + (green-x - blue-x)*green-scale = |
; (white-x - blue-x)*white-scale |
; (red-y - blue-y)*red-scale + (green-y - blue-y)*green-scale = |
; 1 - blue-y*white-scale |
; And now we can trivially solve for (red-scale,green-scale): |
; green-scale = |
; (white-x - blue-x)*white-scale - (red-x - blue-x)*red-scale |
; ----------------------------------------------------------- |
; green-x - blue-x |
; red-scale = |
; 1 - blue-y*white-scale - (green-y - blue-y) * green-scale |
; --------------------------------------------------------- |
; red-y - blue-y |
; Hence: |
; red-scale = |
; ( (green-x - blue-x) * (white-y - blue-y) - |
; (green-y - blue-y) * (white-x - blue-x) ) / white-y |
; ------------------------------------------------------------------------- |
; (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x) |
; green-scale = |
; ( (red-y - blue-y) * (white-x - blue-x) - |
; (red-x - blue-x) * (white-y - blue-y) ) / white-y |
; ------------------------------------------------------------------------- |
; (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x) |
; Accuracy: |
; The input values have 5 decimal digits of accuracy. The values are all in |
; the range 0 < value < 1, so simple products are in the same range but may |
; need up to 10 decimal digits to preserve the original precision and avoid |
; underflow. Because we are using a 32-bit signed representation we cannot |
; match this; the best is a little over 9 decimal digits, less than 10. |
; The approach used here is to preserve the maximum precision within the |
; signed representation. Because the red-scale calculation above uses the |
; difference between two products of values that must be in the range -1..+1 |
; it is sufficient to divide the product by 7; ceil(100,000/32767*2). The |
; factor is irrelevant in the calculation because it is applied to both |
; numerator and denominator. |
; Note that the values of the differences of the products of the |
; chromaticities in the above equations tend to be small, for example for |
; the sRGB chromaticities they are: |
; red numerator: -0.04751 |
; green numerator: -0.08788 |
; denominator: -0.2241 (without white-y multiplication) |
; The resultant Y coefficients from the chromaticities of some widely used |
; color space definitions are (to 15 decimal places): |
; sRGB |
; 0.212639005871510 0.715168678767756 0.072192315360734 |
; Kodak ProPhoto |
; 0.288071128229293 0.711843217810102 0.000085653960605 |
; Adobe RGB |
; 0.297344975250536 0.627363566255466 0.075291458493998 |
; Adobe Wide Gamut RGB |
; 0.258728243040113 0.724682314948566 0.016589442011321 |
; By the argument, above overflow should be impossible here. The return |
; value of 2 indicates an internal error to the caller. |
; if (png_muldiv(&left, xy->greenx-xy->bluex, xy->redy - xy->bluey, 7) == 0) |
; return 2; |
; if (png_muldiv(&right, xy->greeny-xy->bluey, xy->redx - xy->bluex, 7) == 0) |
; return 2; |
; denominator = left - right; |
; Now find the red numerator. |
; if (png_muldiv(&left, xy->greenx-xy->bluex, xy->whitey-xy->bluey, 7) == 0) |
; return 2; |
; if (png_muldiv(&right, xy->greeny-xy->bluey, xy->whitex-xy->bluex, 7) == 0) |
; return 2; |
; Overflow is possible here and it indicates an extreme set of PNG cHRM |
; chunk values. This calculation actually returns the reciprocal of the |
; scale value because this allows us to delay the multiplication of white-y |
; into the denominator, which tends to produce a small number. |
; if (png_muldiv(&red_inverse, xy->whitey, denominator, left-right) == 0 || |
; red_inverse <= xy->whitey /* r+g+b scales = white scale */) |
; return 1; |
; Similarly for green_inverse: |
; if (png_muldiv(&left, xy->redy-xy->bluey, xy->whitex-xy->bluex, 7) == 0) |
; return 2; |
; if (png_muldiv(&right, xy->redx-xy->bluex, xy->whitey-xy->bluey, 7) == 0) |
; return 2; |
; if (png_muldiv(&green_inverse, xy->whitey, denominator, left-right) == 0 || |
; green_inverse <= xy->whitey) |
; return 1; |
; And the blue scale, the checks above guarantee this can't overflow but it |
; can still produce 0 for extreme cHRM values. |
; blue_scale = png_reciprocal(xy->whitey) - png_reciprocal(red_inverse) - |
; png_reciprocal(green_inverse); |
; if (blue_scale <= 0) |
; return 1; |
; And fill in the png_XYZ: |
; if (png_muldiv(&XYZ->red_X, xy->redx, PNG_FP_1, red_inverse) == 0) |
; return 1; |
; if (png_muldiv(&XYZ->red_Y, xy->redy, PNG_FP_1, red_inverse) == 0) |
; return 1; |
; if (png_muldiv(&XYZ->red_Z, PNG_FP_1 - xy->redx - xy->redy, PNG_FP_1, |
; red_inverse) == 0) |
; return 1; |
; if (png_muldiv(&XYZ->green_X, xy->greenx, PNG_FP_1, green_inverse) == 0) |
; return 1; |
; if (png_muldiv(&XYZ->green_Y, xy->greeny, PNG_FP_1, green_inverse) == 0) |
; return 1; |
; if (png_muldiv(&XYZ->green_Z, PNG_FP_1 - xy->greenx - xy->greeny, PNG_FP_1, |
; green_inverse) == 0) |
; return 1; |
; if (png_muldiv(&XYZ->blue_X, xy->bluex, blue_scale, PNG_FP_1) == 0) |
; return 1; |
; if (png_muldiv(&XYZ->blue_Y, xy->bluey, blue_scale, PNG_FP_1) == 0) |
; return 1; |
; if (png_muldiv(&XYZ->blue_Z, PNG_FP_1 - xy->bluex - xy->bluey, blue_scale, |
; PNG_FP_1) == 0) |
; return 1; |
; return 0; /*success*/ |
ret |
endp |
;int (png_XYZ *XYZ) |
align 4 |
proc png_XYZ_normalize, XYZ:dword |
; int_32 Y; |
; if (XYZ->red_Y < 0 || XYZ->green_Y < 0 || XYZ->blue_Y < 0 || |
; XYZ->red_X < 0 || XYZ->green_X < 0 || XYZ->blue_X < 0 || |
; XYZ->red_Z < 0 || XYZ->green_Z < 0 || XYZ->blue_Z < 0) |
; return 1; |
; Normalize by scaling so the sum of the end-point Y values is PNG_FP_1. |
; IMPLEMENTATION NOTE: ANSI requires signed overflow not to occur, therefore |
; relying on addition of two positive values producing a negative one is not |
; safe. |
; Y = XYZ->red_Y; |
; if (0x7fffffff - Y < XYZ->green_X) |
; return 1; |
; Y += XYZ->green_Y; |
; if (0x7fffffff - Y < XYZ->blue_X) |
; return 1; |
; Y += XYZ->blue_Y; |
; if (Y != PNG_FP_1) |
; { |
; if (png_muldiv(&XYZ->red_X, XYZ->red_X, PNG_FP_1, Y) == 0) |
; return 1; |
; if (png_muldiv(&XYZ->red_Y, XYZ->red_Y, PNG_FP_1, Y) == 0) |
; return 1; |
; if (png_muldiv(&XYZ->red_Z, XYZ->red_Z, PNG_FP_1, Y) == 0) |
; return 1; |
; if (png_muldiv(&XYZ->green_X, XYZ->green_X, PNG_FP_1, Y) == 0) |
; return 1; |
; if (png_muldiv(&XYZ->green_Y, XYZ->green_Y, PNG_FP_1, Y) == 0) |
; return 1; |
; if (png_muldiv(&XYZ->green_Z, XYZ->green_Z, PNG_FP_1, Y) == 0) |
; return 1; |
; if (png_muldiv(&XYZ->blue_X, XYZ->blue_X, PNG_FP_1, Y) == 0) |
; return 1; |
; if (png_muldiv(&XYZ->blue_Y, XYZ->blue_Y, PNG_FP_1, Y) == 0) |
; return 1; |
; if (png_muldiv(&XYZ->blue_Z, XYZ->blue_Z, PNG_FP_1, Y) == 0) |
; return 1; |
; } |
; return 0; |
ret |
endp |
;int (const png_xy *xy1, const png_xy *xy2, int delta) |
align 4 |
proc png_colorspace_endpoints_match, xy1:dword, xy2:dword, delta:dword |
; Allow an error of +/-0.01 (absolute value) on each chromaticity |
; if (PNG_OUT_OF_RANGE(xy1->whitex, xy2->whitex,delta) || |
; PNG_OUT_OF_RANGE(xy1->whitey, xy2->whitey,delta) || |
; PNG_OUT_OF_RANGE(xy1->redx, xy2->redx, delta) || |
; PNG_OUT_OF_RANGE(xy1->redy, xy2->redy, delta) || |
; PNG_OUT_OF_RANGE(xy1->greenx, xy2->greenx,delta) || |
; PNG_OUT_OF_RANGE(xy1->greeny, xy2->greeny,delta) || |
; PNG_OUT_OF_RANGE(xy1->bluex, xy2->bluex, delta) || |
; PNG_OUT_OF_RANGE(xy1->bluey, xy2->bluey, delta)) |
; return 0; |
; return 1; |
ret |
endp |
; Added in libpng-1.6.0, a different check for the validity of a set of cHRM |
; chunk chromaticities. Earlier checks used to simply look for the overflow |
; condition (where the determinant of the matrix to solve for XYZ ends up zero |
; because the chromaticity values are not all distinct.) Despite this it is |
; theoretically possible to produce chromaticities that are apparently valid |
; but that rapidly degrade to invalid, potentially crashing, sets because of |
; arithmetic inaccuracies when calculations are performed on them. The new |
; check is to round-trip xy -> XYZ -> xy and then check that the result is |
; within a small percentage of the original. |
;int (png_XYZ *XYZ, const png_xy *xy) |
align 4 |
proc png_colorspace_check_xy, XYZ:dword, xy:dword |
; int result; |
; png_xy xy_test; |
; As a side-effect this routine also returns the XYZ endpoints. |
; result = png_XYZ_from_xy(XYZ, xy); |
; if (result != 0) |
; return result; |
; result = png_xy_from_XYZ(&xy_test, XYZ); |
; if (result != 0) |
; return result; |
; if (png_colorspace_endpoints_match(xy, &xy_test, |
; 5/*actually, the math is pretty accurate*/) != 0) |
; return 0; |
; Too much slip |
; return 1; |
ret |
endp |
; This is the check going the other way. The XYZ is modified to normalize it |
; (another side-effect) and the xy chromaticities are returned. |
;int (png_xy *xy, png_XYZ *XYZ) |
align 4 |
proc png_colorspace_check_XYZ, xy:dword, XYZ:dword |
; int result; |
; png_XYZ XYZtemp; |
; result = png_XYZ_normalize(XYZ); |
; if (result != 0) |
; return result; |
; result = png_xy_from_XYZ(xy, XYZ); |
; if (result != 0) |
; return result; |
; XYZtemp = *XYZ; |
; return png_colorspace_check_xy(&XYZtemp, xy); |
ret |
endp |
; Used to check for an endpoint match against sRGB |
;const png_xy sRGB_xy = /* From ITU-R BT.709-3 */ |
; /* color x y */ |
; /* red */ 64000, 33000, |
; /* green */ 30000, 60000, |
; /* blue */ 15000, 6000, |
; /* white */ 31270, 32900 |
;int (png_structrp png_ptr, |
; png_colorspacerp colorspace, const png_xy *xy, const png_XYZ *XYZ, |
; int preferred) |
align 4 |
proc png_colorspace_set_xy_and_XYZ, png_ptr:dword, colorspace:dword, xy:dword, XYZ:dword, preferred:dword |
; if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0) |
; return 0; |
; The consistency check is performed on the chromaticities; this factors out |
; variations because of the normalization (or not) of the end point Y |
; values. |
; if (preferred < 2 && |
; (colorspace->flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0) |
; { |
; The end points must be reasonably close to any we already have. The |
; following allows an error of up to +/-.001 |
; if (png_colorspace_endpoints_match(xy, &colorspace->end_points_xy, |
; 100) == 0) |
; { |
; colorspace->flags |= PNG_COLORSPACE_INVALID; |
; png_benign_error(png_ptr, "inconsistent chromaticities"); |
; return 0; /* failed */ |
; } |
; Only overwrite with preferred values |
; if (preferred == 0) |
; return 1; /* ok, but no change */ |
; } |
; colorspace->end_points_xy = *xy; |
; colorspace->end_points_XYZ = *XYZ; |
; colorspace->flags |= PNG_COLORSPACE_HAVE_ENDPOINTS; |
; /* The end points are normally quoted to two decimal digits, so allow +/-0.01 |
; on this test. |
; if (png_colorspace_endpoints_match(xy, &sRGB_xy, 1000) != 0) |
; colorspace->flags |= PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB; |
; |
; else |
; colorspace->flags &= PNG_COLORSPACE_CANCEL( |
; PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB); |
; return 2; /* ok and changed */ |
ret |
endp |
;int (png_structrp png_ptr, |
; png_colorspacerp colorspace, const png_xy *xy, int preferred) |
align 4 |
proc png_colorspace_set_chromaticities, png_ptr:dword, colorspace:dword, xy:dword, preferred:dword |
; We must check the end points to ensure they are reasonable - in the past |
; color management systems have crashed as a result of getting bogus |
; colorant values, while this isn't the fault of libpng it is the |
; responsibility of libpng because PNG carries the bomb and libpng is in a |
; position to protect against it. |
; png_XYZ XYZ; |
; switch (png_colorspace_check_xy(&XYZ, xy)) |
; { |
; case 0: /* success */ |
; return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, xy, &XYZ, |
; preferred); |
; case 1: |
; We can't invert the chromaticities so we can't produce value XYZ |
; values. Likely as not a color management system will fail too. |
; colorspace->flags |= PNG_COLORSPACE_INVALID; |
; png_benign_error(png_ptr, "invalid chromaticities"); |
; break; |
; |
; default: |
; libpng is broken; this should be a warning but if it happens we |
; want error reports so for the moment it is an error. |
; colorspace->flags |= PNG_COLORSPACE_INVALID; |
; png_error(png_ptr, "internal error checking chromaticities"); |
; } |
xor eax,eax |
.end_f: |
ret |
endp |
;int (png_structrp png_ptr, |
; png_colorspacerp colorspace, const png_XYZ *XYZ_in, int preferred) |
align 4 |
proc png_colorspace_set_endpoints, png_ptr:dword, colorspace:dword, XYZ_in:dword, preferred:dword |
; png_XYZ XYZ = *XYZ_in; |
; png_xy xy; |
; switch (png_colorspace_check_XYZ(&xy, &XYZ)) |
; { |
; case 0: |
; return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, &xy, &XYZ, |
; preferred); |
; case 1: |
; End points are invalid. |
; colorspace->flags |= PNG_COLORSPACE_INVALID; |
; png_benign_error(png_ptr, "invalid end points"); |
; break; |
; default: |
; colorspace->flags |= PNG_COLORSPACE_INVALID; |
; png_error(png_ptr, "internal error checking chromaticities"); |
; } |
xor eax,eax |
.end_f: |
ret |
endp |
; Error message generation |
;char (uint_32 byte) |
align 4 |
proc png_icc_tag_char, p1byte:dword |
mov eax,[p1byte] |
cmp al,32 |
jl @f |
cmp al,126 |
jg @f ;if (..>=.. && ..<=..) return |
mov al,'?' |
@@: |
and eax,0xff |
ret |
endp |
;void (char *name, uint_32 tag) |
align 4 |
proc png_icc_tag_name uses eax edi, name:dword, tag:dword |
mov edi,[name] |
mov byte[edi],39 |
mov byte[edi+5],39 |
inc edi |
mov eax,[tag] |
shr eax,24 |
stdcall png_icc_tag_char,eax |
stosb |
mov eax,[tag] |
shr eax,16 |
stdcall png_icc_tag_char,eax |
stosb |
mov eax,[tag] |
shr eax,8 |
stdcall png_icc_tag_char,eax |
stosb |
stdcall png_icc_tag_char,[tag] |
stosb |
ret |
endp |
;int (png_alloc_size_t it) |
align 4 |
proc is_ICC_signature_char, it:dword |
; return it == 32 || (it >= 48 && it <= 57) || (it >= 65 && it <= 90) || |
; (it >= 97 && it <= 122); |
ret |
endp |
;int (png_alloc_size_t it) |
align 4 |
proc is_ICC_signature, it:dword |
; return is_ICC_signature_char(it >> 24) /* checks all the top bits */ && |
; is_ICC_signature_char((it >> 16) & 0xff) && |
; is_ICC_signature_char((it >> 8) & 0xff) && |
; is_ICC_signature_char(it & 0xff); |
ret |
endp |
;int (png_structrp png_ptr, png_colorspacerp colorspace, |
; charp name, png_alloc_size_t value, charp reason) |
align 4 |
proc png_icc_profile_error, png_ptr:dword, colorspace:dword, name:dword, value:dword, reason:dword |
locals |
pos dd ? ;size_t |
message rb 196 ;char[] ;see below for calculation |
endl |
mov eax,[colorspace] |
cmp eax,0 |
je @f ;if (..!=0) |
or word[eax+png_colorspace.flags], PNG_COLORSPACE_INVALID |
@@: |
; pos = png_safecat(message, (sizeof message), 0, "profile '"); /* 9 chars */ |
; pos = png_safecat(message, pos+79, pos, name); /* Truncate to 79 chars */ |
; pos = png_safecat(message, (sizeof message), pos, "': "); /* +2 = 90 */ |
; if (is_ICC_signature(value) != 0) |
; { |
; So 'value' is at most 4 bytes and the following cast is safe |
; png_icc_tag_name(message+pos, (uint_32)value); |
; pos += 6; /* total +8; less than the else clause */ |
; message[pos++] = ':'; |
; message[pos++] = ' '; |
; } |
if PNG_WARNINGS_SUPPORTED eq 1 |
; else |
; { |
; char number[PNG_NUMBER_BUFFER_SIZE]; /* +24 = 114*/ |
; pos = png_safecat(message, (sizeof message), pos, |
; png_format_number(number, number+(sizeof number), |
; PNG_NUMBER_FORMAT_x, value)); |
; pos = png_safecat(message, (sizeof message), pos, "h: "); /*+2 = 116*/ |
; } |
end if |
; The 'reason' is an arbitrary message, allow +79 maximum 195 |
; pos = png_safecat(message, (sizeof message), pos, reason); |
; This is recoverable, but make it unconditionally an app_error on write to |
; avoid writing invalid ICC profiles into PNG files (i.e., we handle them |
; on read, with a warning, but on write unless the app turns off |
; application errors the PNG won't be written.) |
; png_chunk_report(png_ptr, message, |
; (colorspace != NULL) ? PNG_CHUNK_ERROR : PNG_CHUNK_WRITE_ERROR); |
xor eax,eax |
ret |
endp |
if PNG_sRGB_SUPPORTED eq 1 |
;color X Y Z |
sRGB_XYZ dd 41239, 21264, 1933,\ ;red |
35758, 71517, 11919,\ ;green |
18048, 7219, 95053 ;blue |
end if |
;int (png_structrp png_ptr, png_colorspacerp colorspace, int intent) |
align 4 |
proc png_colorspace_set_sRGB uses ebx ecx edi esi, png_ptr:dword, colorspace:dword, intent:dword |
; sRGB sets known gamma, end points and (from the chunk) intent. |
; IMPORTANT: these are not necessarily the values found in an ICC profile |
; because ICC profiles store values adapted to a D50 environment; it is |
; expected that the ICC profile mediaWhitePointTag will be D50; see the |
; checks and code elsewhere to understand this better. |
; These XYZ values, which are accurate to 5dp, produce rgb to gray |
; coefficients of (6968,23435,2366), which are reduced (because they add up |
; to 32769 not 32768) to (6968,23434,2366). These are the values that |
; libpng has traditionally used (and are the best values given the 15bit |
; algorithm used by the rgb to gray code.) |
; Do nothing if the colorspace is already invalidated. |
mov ebx,[colorspace] |
mov ax,[ebx+png_colorspace.flags] |
and ax,PNG_COLORSPACE_INVALID |
cmp ax,0 |
je @f ;if (..!=0) |
xor eax,eax |
jmp .end_f |
@@: |
; Check the intent, then check for existing settings. It is valid for the |
; PNG file to have cHRM or gAMA chunks along with sRGB, but the values must |
; be consistent with the correct values. If, however, this function is |
; called below because an iCCP chunk matches sRGB then it is quite |
; conceivable that an older app recorded incorrect gAMA and cHRM because of |
; an incorrect calculation based on the values in the profile - this does |
; *not* invalidate the profile (though it still produces an error, which can |
; be ignored.) |
mov edi,[png_ptr] |
cmp dword[intent],0 |
jl @f |
cmp dword[intent],PNG_sRGB_INTENT_LAST |
jge @f |
jmp .end0 |
@@: ;if (..<0 || ..>=..) |
cStr ,'sRGB' |
cStr ecx,'invalid sRGB rendering intent' |
stdcall png_icc_profile_error, edi, ebx, eax, [intent], ecx |
jmp .end_f |
.end0: |
mov ax,[ebx+png_colorspace.flags] |
and ax,PNG_COLORSPACE_HAVE_INTENT |
cmp ax,0 |
je @f |
movzx eax,word[ebx+png_colorspace.rendering_intent] |
cmp eax,[intent] |
je @f ;if (..!=0 && ..!=..) |
cStr ,'sRGB' |
cStr ecx,'inconsistent rendering intents' |
stdcall png_icc_profile_error, edi, ebx, eax, [intent], ecx |
jmp .end_f |
@@: |
mov ax,[ebx+png_colorspace.flags] |
and ax,PNG_COLORSPACE_FROM_sRGB |
cmp ax,0 |
je @f ;if (..!=0) |
png_benign_error edi, 'duplicate sRGB information ignored' |
xor eax,eax |
jmp .end_f |
@@: |
; If the standard sRGB cHRM chunk does not match the one from the PNG file |
; warn but overwrite the value with the correct one. |
mov ax,[ebx+png_colorspace.flags] |
and ax,PNG_COLORSPACE_HAVE_ENDPOINTS |
cmp ax,0 |
je @f ;if (..!=0 && |
; !png_colorspace_endpoints_match(&sRGB_xy, &colorspace->end_points_xy, |
; 100)) |
cStr ,'cHRM chunk does not match sRGB' |
stdcall png_chunk_report, edi, eax, PNG_CHUNK_ERROR |
@@: |
; This check is just done for the error reporting - the routine always |
; returns true when the 'from' argument corresponds to sRGB (2). |
stdcall png_colorspace_check_gamma, edi, ebx, PNG_GAMMA_sRGB_INVERSE, 2 ;from sRGB |
; intent: bugs in GCC force 'int' to be used as the parameter type. |
mov eax,[intent] |
mov [ebx+png_colorspace.rendering_intent],ax |
or word[ebx+png_colorspace.flags], PNG_COLORSPACE_HAVE_INTENT |
; endpoints |
; colorspace->end_points_xy = sRGB_xy; |
; colorspace->end_points_XYZ = sRGB_XYZ; |
or word[ebx+png_colorspace.flags], (PNG_COLORSPACE_HAVE_ENDPOINTS or PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB) |
; gamma |
mov dword[ebx+png_colorspace.gamma], PNG_GAMMA_sRGB_INVERSE |
or word[ebx+png_colorspace.flags], PNG_COLORSPACE_HAVE_GAMMA |
; Finally record that we have an sRGB profile |
or word[ebx+png_colorspace.flags], (PNG_COLORSPACE_MATCHES_sRGB or PNG_COLORSPACE_FROM_sRGB) |
xor eax,eax |
inc eax ;set |
.end_f: |
ret |
endp |
;if PNG_iCCP_SUPPORTED |
; Encoded value of D50 as an ICC XYZNumber. From the ICC 2010 spec the value |
; is XYZ(0.9642,1.0,0.8249), which scales to: |
; (63189.8112, 65536, 54060.6464) |
D50_nCIEXYZ db \ ;byte[12] |
0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d |
;int /* bool */ |
;(png_structrp png_ptr, png_colorspacerp colorspace, charp name, uint_32 profile_length) |
align 4 |
proc icc_check_length, png_ptr:dword, colorspace:dword, name:dword, profile_length:dword |
cmp dword[profile_length],132 |
jge @f ;if (..<..) |
; return png_icc_profile_error(png_ptr, colorspace, name, profile_length, |
; "too short"); |
jmp .end_f |
@@: |
xor eax,eax |
inc eax |
.end_f: |
ret |
endp |
;int (png_structrp png_ptr, png_colorspacerp colorspace, |
; charp name, uint_32 profile_length) |
align 4 |
proc png_icc_check_length, png_ptr:dword, colorspace:dword, name:dword, profile_length:dword |
; if (!icc_check_length(png_ptr, colorspace, name, profile_length)) |
; return 0; |
; This needs to be here because the 'normal' check is in |
; png_decompress_chunk, yet this happens after the attempt to |
; png_malloc_base the required data. We only need this on read; on write |
; the caller supplies the profile buffer so libpng doesn't allocate it. See |
; the call to icc_check_length below (the write case). |
if PNG_SET_USER_LIMITS_SUPPORTED eq 1 |
; else if (png_ptr->user_chunk_malloc_max > 0 && |
; png_ptr->user_chunk_malloc_max < profile_length) |
; return png_icc_profile_error(png_ptr, colorspace, name, profile_length, |
; "exceeds application limits"); |
elseif PNG_USER_CHUNK_MALLOC_MAX > 0 |
; else if (PNG_USER_CHUNK_MALLOC_MAX < profile_length) |
; return png_icc_profile_error(png_ptr, colorspace, name, profile_length, |
; "exceeds libpng limits"); |
else ;!SET_USER_LIMITS |
; This will get compiled out on all 32-bit and better systems. |
; else if (PNG_SIZE_MAX < profile_length) |
; return png_icc_profile_error(png_ptr, colorspace, name, profile_length, |
; "exceeds system limits"); |
end if ;!SET_USER_LIMITS |
xor eax,eax |
inc eax |
.end_f: |
ret |
endp |
;int (png_structrp png_ptr, png_colorspacerp colorspace, |
; charp name, uint_32 profile_length, |
; bytep profile/* first 132 bytes only */, int color_type) |
align 4 |
proc png_icc_check_header, png_ptr:dword, colorspace:dword, name:dword, profile_length:dword, profile:dword, color_type:dword |
; uint_32 temp; |
; Length check; this cannot be ignored in this code because profile_length |
; is used later to check the tag table, so even if the profile seems over |
; long profile_length from the caller must be correct. The caller can fix |
; this up on read or write by just passing in the profile header length. |
; temp = png_get_uint_32(profile); |
; if (temp != profile_length) |
; return png_icc_profile_error(png_ptr, colorspace, name, temp, |
; "length does not match profile"); |
; temp = (uint_32) (*(profile+8)); |
; if (temp > 3 && (profile_length & 3)) |
; return png_icc_profile_error(png_ptr, colorspace, name, profile_length, |
; "invalid length"); |
; temp = png_get_uint_32(profile+128); /* tag count: 12 bytes/tag */ |
; if (temp > 357913930 || /* (2^32-4-132)/12: maximum possible tag count */ |
; profile_length < 132+12*temp) /* truncated tag table */ |
; return png_icc_profile_error(png_ptr, colorspace, name, temp, |
; "tag count too large"); |
; The 'intent' must be valid or we can't store it, ICC limits the intent to |
; 16 bits. |
; temp = png_get_uint_32(profile+64); |
; if (temp >= 0xffff) /* The ICC limit */ |
; return png_icc_profile_error(png_ptr, colorspace, name, temp, |
; "invalid rendering intent"); |
; This is just a warning because the profile may be valid in future |
; versions. |
; if (temp >= PNG_sRGB_INTENT_LAST) |
; (void)png_icc_profile_error(png_ptr, NULL, name, temp, |
; "intent outside defined range"); |
; At this point the tag table can't be checked because it hasn't necessarily |
; been loaded; however, various header fields can be checked. These checks |
; are for values permitted by the PNG spec in an ICC profile; the PNG spec |
; restricts the profiles that can be passed in an iCCP chunk (they must be |
; appropriate to processing PNG data!) |
; Data checks (could be skipped). These checks must be independent of the |
; version number; however, the version number doesn't accomodate changes in |
; the header fields (just the known tags and the interpretation of the |
; data.) |
; temp = png_get_uint_32(profile+36); /* signature 'ascp' */ |
; if (temp != 0x61637370) |
; return png_icc_profile_error(png_ptr, colorspace, name, temp, |
; "invalid signature"); |
; Currently the PCS illuminant/adopted white point (the computational |
; white point) are required to be D50, |
; however the profile contains a record of the illuminant so perhaps ICC |
; expects to be able to change this in the future (despite the rationale in |
; the introduction for using a fixed PCS adopted white.) Consequently the |
; following is just a warning. |
; if (memcmp(profile+68, D50_nCIEXYZ, 12) != 0) |
; (void)png_icc_profile_error(png_ptr, NULL, name, 0/*no tag value*/, |
; "PCS illuminant is not D50"); |
; The PNG spec requires this: |
; "If the iCCP chunk is present, the image samples conform to the colour |
; space represented by the embedded ICC profile as defined by the |
; International Color Consortium [ICC]. The colour space of the ICC profile |
; shall be an RGB colour space for colour images (PNG colour types 2, 3, and |
; 6), or a greyscale colour space for greyscale images (PNG colour types 0 |
; and 4)." |
; This checking code ensures the embedded profile (on either read or write) |
; conforms to the specification requirements. Notice that an ICC 'gray' |
; color-space profile contains the information to transform the monochrome |
; data to XYZ or L*a*b (according to which PCS the profile uses) and this |
; should be used in preference to the standard libpng K channel replication |
; into R, G and B channels. |
; Previously it was suggested that an RGB profile on grayscale data could be |
; handled. However it it is clear that using an RGB profile in this context |
; must be an error - there is no specification of what it means. Thus it is |
; almost certainly more correct to ignore the profile. |
; temp = png_get_uint_32(profile+16); /* data colour space field */ |
; switch (temp) |
; { |
; case 0x52474220: /* 'RGB ' */ |
; if ((color_type & PNG_COLOR_MASK_COLOR) == 0) |
; return png_icc_profile_error(png_ptr, colorspace, name, temp, |
; "RGB color space not permitted on grayscale PNG"); |
; break; |
; case 0x47524159: /* 'GRAY' */ |
; if ((color_type & PNG_COLOR_MASK_COLOR) != 0) |
; return png_icc_profile_error(png_ptr, colorspace, name, temp, |
; "Gray color space not permitted on RGB PNG"); |
; break; |
; default: |
; return png_icc_profile_error(png_ptr, colorspace, name, temp, |
; "invalid ICC profile color space"); |
; } |
; It is up to the application to check that the profile class matches the |
; application requirements; the spec provides no guidance, but it's pretty |
; weird if the profile is not scanner ('scnr'), monitor ('mntr'), printer |
; ('prtr') or 'spac' (for generic color spaces). Issue a warning in these |
; cases. Issue an error for device link or abstract profiles - these don't |
; contain the records necessary to transform the color-space to anything |
; other than the target device (and not even that for an abstract profile). |
; Profiles of these classes may not be embedded in images. |
; temp = png_get_uint_32(profile+12); /* profile/device class */ |
; switch (temp) |
; { |
; case 0x73636e72: /* 'scnr' */ |
; case 0x6d6e7472: /* 'mntr' */ |
; case 0x70727472: /* 'prtr' */ |
; case 0x73706163: /* 'spac' */ |
; /* All supported */ |
; break; |
; case 0x61627374: /* 'abst' */ |
; /* May not be embedded in an image */ |
; return png_icc_profile_error(png_ptr, colorspace, name, temp, |
; "invalid embedded Abstract ICC profile"); |
; case 0x6c696e6b: /* 'link' */ |
; /* DeviceLink profiles cannot be interpreted in a non-device specific |
; fashion, if an app uses the AToB0Tag in the profile the results are |
; undefined unless the result is sent to the intended device, |
; therefore a DeviceLink profile should not be found embedded in a |
; PNG. |
; return png_icc_profile_error(png_ptr, colorspace, name, temp, |
; "unexpected DeviceLink ICC profile class"); |
; case 0x6e6d636c: /* 'nmcl' */ |
; /* A NamedColor profile is also device specific, however it doesn't |
; contain an AToB0 tag that is open to misinterpretation. Almost |
; certainly it will fail the tests below. |
; (void)png_icc_profile_error(png_ptr, NULL, name, temp, |
; "unexpected NamedColor ICC profile class"); |
; break; |
; default: |
; /* To allow for future enhancements to the profile accept unrecognized |
; profile classes with a warning, these then hit the test below on the |
; tag content to ensure they are backward compatible with one of the |
; understood profiles. |
; (void)png_icc_profile_error(png_ptr, NULL, name, temp, |
; "unrecognized ICC profile class"); |
; break; |
; } |
; For any profile other than a device link one the PCS must be encoded |
; either in XYZ or Lab. |
; temp = png_get_uint_32(profile+20); |
; switch (temp) |
; { |
; case 0x58595a20: /* 'XYZ ' */ |
; case 0x4c616220: /* 'Lab ' */ |
; break; |
; default: |
; return png_icc_profile_error(png_ptr, colorspace, name, temp, |
; "unexpected ICC PCS encoding"); |
; } |
; return 1; |
ret |
endp |
;int (png_structrp png_ptr, png_colorspacerp colorspace, |
; charp name, uint_32 profile_length, |
; bytep profile /* header plus whole tag table */) |
align 4 |
proc png_icc_check_tag_table, png_ptr:dword, colorspace:dword, name:dword, profile_length:dword, profile:dword |
; uint_32 tag_count = png_get_uint_32(profile+128); |
; uint_32 itag; |
; bytep tag = profile+132; /* The first tag */ |
; First scan all the tags in the table and add bits to the icc_info value |
; (temporarily in 'tags'). |
; for (itag=0; itag < tag_count; ++itag, tag += 12) |
; { |
; uint_32 tag_id = png_get_uint_32(tag+0); |
; uint_32 tag_start = png_get_uint_32(tag+4); /* must be aligned */ |
; uint_32 tag_length = png_get_uint_32(tag+8);/* not padded */ |
; The ICC specification does not exclude zero length tags, therefore the |
; start might actually be anywhere if there is no data, but this would be |
; a clear abuse of the intent of the standard so the start is checked for |
; being in range. All defined tag types have an 8 byte header - a 4 byte |
; type signature then 0. |
; if ((tag_start & 3) != 0) |
; { |
; CNHP730S.icc shipped with Microsoft Windows 64 violates this, it is |
; only a warning here because libpng does not care about the |
; alignment. |
; (void)png_icc_profile_error(png_ptr, NULL, name, tag_id, |
; "ICC profile tag start not a multiple of 4"); |
; } |
; This is a hard error; potentially it can cause read outside the |
; profile. |
; if (tag_start > profile_length || tag_length > profile_length - tag_start) |
; return png_icc_profile_error(png_ptr, colorspace, name, tag_id, |
; "ICC profile tag outside profile"); |
; } |
xor eax,eax |
inc eax ;success, maybe with warnings |
.end_f: |
ret |
endp |
;if PNG_sRGB_SUPPORTED |
;#if PNG_sRGB_PROFILE_CHECKS >= 0 |
; Information about the known ICC sRGB profiles |
struct png_sRGB_checks |
adler dd ? ;uint_32 |
crc dd ? |
length dd ? |
md5 rd 4 ;uint_32[4] |
have_md5 db ? ;byte |
is_broken db ? ;byte |
intent dw ? ;uint_16 |
ends |
;# define PNG_MD5(a,b,c,d) { a, b, c, d }, (a!=0)||(b!=0)||(c!=0)||(d!=0) |
;# define PNG_ICC_CHECKSUM(adler, crc, md5, intent, broke, date, length, fname)\ |
; { adler, crc, length, md5, broke, intent }, |
;[] = |
; This data comes from contrib/tools/checksum-icc run on downloads of |
; all four ICC sRGB profiles from www.color.org. |
; adler32, crc32, MD5[4], intent, date, length, file-name |
; PNG_ICC_CHECKSUM(0x0a3fd9f6, 0x3b8772b9, |
; PNG_MD5(0x29f83dde, 0xaff255ae, 0x7842fae4, 0xca83390d), 0, 0, |
; "2009/03/27 21:36:31", 3048, "sRGB_IEC61966-2-1_black_scaled.icc") |
; ICC sRGB v2 perceptual no black-compensation: |
; PNG_ICC_CHECKSUM(0x4909e5e1, 0x427ebb21, |
; PNG_MD5(0xc95bd637, 0xe95d8a3b, 0x0df38f99, 0xc1320389), 1, 0, |
; "2009/03/27 21:37:45", 3052, "sRGB_IEC61966-2-1_no_black_scaling.icc") |
; PNG_ICC_CHECKSUM(0xfd2144a1, 0x306fd8ae, |
; PNG_MD5(0xfc663378, 0x37e2886b, 0xfd72e983, 0x8228f1b8), 0, 0, |
; "2009/08/10 17:28:01", 60988, "sRGB_v4_ICC_preference_displayclass.icc") |
; ICC sRGB v4 perceptual |
; PNG_ICC_CHECKSUM(0x209c35d2, 0xbbef7812, |
; PNG_MD5(0x34562abf, 0x994ccd06, 0x6d2c5721, 0xd0d68c5d), 0, 0, |
; "2007/07/25 00:05:37", 60960, "sRGB_v4_ICC_preference.icc") |
; The following profiles have no known MD5 checksum. If there is a match |
; on the (empty) MD5 the other fields are used to attempt a match and |
; a warning is produced. The first two of these profiles have a 'cprt' tag |
; which suggests that they were also made by Hewlett Packard. |
; PNG_ICC_CHECKSUM(0xa054d762, 0x5d5129ce, |
; PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 0, |
; "2004/07/21 18:57:42", 3024, "sRGB_IEC61966-2-1_noBPC.icc") |
; This is a 'mntr' (display) profile with a mediaWhitePointTag that does not |
; match the D50 PCS illuminant in the header (it is in fact the D65 values, |
; so the white point is recorded as the un-adapted value.) The profiles |
; below only differ in one byte - the intent - and are basically the same as |
; the previous profile except for the mediaWhitePointTag error and a missing |
; chromaticAdaptationTag. |
; PNG_ICC_CHECKSUM(0xf784f3fb, 0x182ea552, |
; PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 0, 1/*broken*/, |
; "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 perceptual") |
; PNG_ICC_CHECKSUM(0x0398f3fc, 0xf29e526d, |
; PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 1/*broken*/, |
; "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 media-relative") |
; |
;int (png_structrp png_ptr, bytep profile, uLong adler) |
align 4 |
proc png_compare_ICC_profile_with_sRGB, png_ptr:dword, profile:dword, adler:dword |
; The quick check is to verify just the MD5 signature and trust the |
; rest of the data. Because the profile has already been verified for |
; correctness this is safe. png_colorspace_set_sRGB will check the 'intent' |
; field too, so if the profile has been edited with an intent not defined |
; by sRGB (but maybe defined by a later ICC specification) the read of |
; the profile will fail at that point. |
; uint_32 length = 0; |
; uint_32 intent = 0x10000; /* invalid */ |
if PNG_sRGB_PROFILE_CHECKS > 1 |
; uLong crc = 0; /* the value for 0 length data */ |
end if |
; uint i; |
if PNG_SET_OPTION_SUPPORTED eq 1 |
; First see if PNG_SKIP_sRGB_CHECK_PROFILE has been set to "on" |
; if (((png_ptr->options >> PNG_SKIP_sRGB_CHECK_PROFILE) & 3) == |
; PNG_OPTION_ON) |
; return 0; |
end if |
; for (i=0; i < (sizeof png_sRGB_checks) / (sizeof png_sRGB_checks[0]); ++i) |
; { |
; if (png_get_uint_32(profile+84) == png_sRGB_checks[i].md5[0] && |
; png_get_uint_32(profile+88) == png_sRGB_checks[i].md5[1] && |
; png_get_uint_32(profile+92) == png_sRGB_checks[i].md5[2] && |
; png_get_uint_32(profile+96) == png_sRGB_checks[i].md5[3]) |
; { |
; This may be one of the old HP profiles without an MD5, in that |
; case we can only use the length and Adler32 (note that these |
; are not used by default if there is an MD5!) |
;# if PNG_sRGB_PROFILE_CHECKS == 0 |
; if (png_sRGB_checks[i].have_md5 != 0) |
; return 1+png_sRGB_checks[i].is_broken; |
;# endif |
; Profile is unsigned or more checks have been configured in. |
; if (length == 0) |
; { |
; length = png_get_uint_32(profile); |
; intent = png_get_uint_32(profile+64); |
; } |
; Length *and* intent must match |
; if (length == (uint_32) png_sRGB_checks[i].length && |
; intent == (uint_32) png_sRGB_checks[i].intent) |
; { |
; Now calculate the adler32 if not done already. |
; if (adler == 0) |
; { |
; adler = adler32(0, NULL, 0); |
; adler = adler32(adler, profile, length); |
; } |
; if (adler == png_sRGB_checks[i].adler) |
; { |
; These basic checks suggest that the data has not been |
; modified, but if the check level is more than 1 perform |
; our own crc32 checksum on the data. |
;# if PNG_sRGB_PROFILE_CHECKS > 1 |
; if (crc == 0) |
; { |
; crc = calc_crc32(0, NULL, 0); |
; crc = calc_crc32(crc, profile, length); |
; } |
; /* So this check must pass for the 'return' below to happen. |
; if (crc == png_sRGB_checks[i].crc) |
;# endif |
; { |
; if (png_sRGB_checks[i].is_broken != 0) |
; { |
; These profiles are known to have bad data that may cause |
; problems if they are used, therefore attempt to |
; discourage their use, skip the 'have_md5' warning below, |
; which is made irrelevant by this error. |
; png_chunk_report(png_ptr, "known incorrect sRGB profile", |
; PNG_CHUNK_ERROR); |
; } |
; Warn that this being done; this isn't even an error since |
; the profile is perfectly valid, but it would be nice if |
; people used the up-to-date ones. |
; else if (png_sRGB_checks[i].have_md5 == 0) |
; { |
; png_chunk_report(png_ptr, |
; "out-of-date sRGB profile with no signature", |
; PNG_CHUNK_WARNING); |
; } |
; return 1+png_sRGB_checks[i].is_broken; |
; } |
; } |
;# if PNG_sRGB_PROFILE_CHECKS > 0 |
; The signature matched, but the profile had been changed in some |
; way. This probably indicates a data error or uninformed hacking. |
; Fall through to "no match". |
; png_chunk_report(png_ptr, |
; "Not recognizing known sRGB profile that has been edited", |
; PNG_CHUNK_WARNING); |
; break; |
;# endif |
; } |
; } |
; } |
; return 0; /* no match */ |
ret |
endp |
;void (png_structrp png_ptr, |
; png_colorspacerp colorspace, bytep profile, uLong adler) |
align 4 |
proc png_icc_set_sRGB uses eax, png_ptr:dword, colorspace:dword, profile:dword, adler:dword |
; Is this profile one of the known ICC sRGB profiles? If it is, just set |
; the sRGB information. |
; if (png_compare_ICC_profile_with_sRGB(png_ptr, profile, adler) != 0) |
; (void)png_colorspace_set_sRGB(png_ptr, colorspace, |
; (int)/*already checked*/png_get_uint_32(profile+64)); |
ret |
endp |
;end if /* PNG_sRGB_PROFILE_CHECKS >= 0 */ |
;end if /* sRGB */ |
;int (png_structrp png_ptr, png_colorspacerp colorspace, |
; charp name, uint_32 profile_length, bytep profile, |
; int color_type) |
align 4 |
proc png_colorspace_set_ICC, png_ptr:dword, colorspace:dword, name:dword, profile_length:dword, profile:dword, color_type:dword |
; if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0) |
; return 0; |
; if (icc_check_length(png_ptr, colorspace, name, profile_length) != 0 && |
; png_icc_check_header(png_ptr, colorspace, name, profile_length, profile, |
; color_type) != 0 && |
; png_icc_check_tag_table(png_ptr, colorspace, name, profile_length, |
; profile) != 0) |
; { |
;# if defined(PNG_sRGB_SUPPORTED) && PNG_sRGB_PROFILE_CHECKS >= 0 |
; If no sRGB support, don't try storing sRGB information |
; png_icc_set_sRGB(png_ptr, colorspace, profile, 0); |
;# endif |
; return 1; |
; } |
; Failure case |
xor eax,eax |
.end_f: |
ret |
endp |
;end if /* iCCP */ |
;void (png_structrp png_ptr) |
align 4 |
proc png_colorspace_set_rgb_coefficients, png_ptr:dword |
; Set the rgb_to_gray coefficients from the colorspace. |
; if (png_ptr->rgb_to_gray_coefficients_set == 0 && |
; (png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0) |
; { |
; png_set_background has not been called, get the coefficients from the Y |
; values of the colorspace colorants. |
; png_fixed_point r = png_ptr->colorspace.end_points_XYZ.red_Y; |
; png_fixed_point g = png_ptr->colorspace.end_points_XYZ.green_Y; |
; png_fixed_point b = png_ptr->colorspace.end_points_XYZ.blue_Y; |
; png_fixed_point total = r+g+b; |
; if (total > 0 && |
; r >= 0 && png_muldiv(&r, r, 32768, total) && r >= 0 && r <= 32768 && |
; g >= 0 && png_muldiv(&g, g, 32768, total) && g >= 0 && g <= 32768 && |
; b >= 0 && png_muldiv(&b, b, 32768, total) && b >= 0 && b <= 32768 && |
; r+g+b <= 32769) |
; { |
; We allow 0 coefficients here. r+g+b may be 32769 if two or |
; all of the coefficients were rounded up. Handle this by |
; reducing the *largest* coefficient by 1; this matches the |
; approach used for the default coefficients in pngrtran.c |
; int add = 0; |
; |
; if (r+g+b > 32768) |
; add = -1; |
; else if (r+g+b < 32768) |
; add = 1; |
; if (add != 0) |
; { |
; if (g >= r && g >= b) |
; g += add; |
; else if (r >= g && r >= b) |
; r += add; |
; else |
; b += add; |
; } |
; /* Check for an internal error. */ |
; if (r+g+b != 32768) |
; png_error(png_ptr, |
; "internal error handling cHRM coefficients"); |
; else |
; { |
; png_ptr->rgb_to_gray_red_coeff = (uint_16)r; |
; png_ptr->rgb_to_gray_green_coeff = (uint_16)g; |
; } |
; } |
; This is a png_error at present even though it could be ignored - |
; it should never happen, but it is important that if it does, the |
; bug is fixed. |
; else |
; png_error(png_ptr, "internal error handling cHRM->XYZ"); |
; } |
ret |
endp |
;end if /* COLORSPACE */ |
;void (png_structrp png_ptr, |
; uint_32 width, uint_32 height, int bit_depth, |
; int color_type, int interlace_type, int compression_type, int filter_type) |
align 4 |
proc png_check_IHDR uses eax ebx edi, png_ptr:dword, width:dword, height:dword, bit_depth:dword, color_type:dword, interlace_type:dword, compression_type:dword, filter_type:dword |
mov edi,[png_ptr] |
xor ebx,ebx |
; Check for width and height valid values |
cmp dword[width],0 |
jne @f ;if (..==0) |
png_warning edi, 'Image width is zero in IHDR' |
inc ebx |
@@: |
cmp dword[width],PNG_UINT_31_MAX |
jle @f ;if (..>..) |
png_warning edi, 'Invalid image width in IHDR' |
inc ebx |
@@: |
; 48 - big_row_buf hack |
; 1 - filter byte |
; 8 - 8-byte RGBA pixels |
; 1 - extra max_pixel_depth pad |
mov eax,[width] |
add eax,7 |
and eax,not 7 |
cmp eax,((PNG_SIZE_MAX -48 -1) / 8) -1 |
jle @f ;if (..>..) |
; The size of the row must be within the limits of this architecture. |
; Because the read code can perform arbitrary transformations the |
; maximum size is checked here. Because the code in png_read_start_row |
; adds extra space "for safety's sake" in several places a conservative |
; limit is used here. |
; NOTE: it would be far better to check the size that is actually used, |
; but the effect in the real world is minor and the changes are more |
; extensive, therefore much more dangerous and much more difficult to |
; write in a way that avoids compiler warnings. |
png_warning edi, 'Image width is too large for this architecture' |
inc ebx |
@@: |
if PNG_SET_USER_LIMITS_SUPPORTED eq 1 |
mov eax,[edi+png_struct.user_width_max] |
cmp dword[width],eax |
else |
cmp dword[width],PNG_USER_WIDTH_MAX |
end if |
jle @f ;if (..>..) |
png_warning edi, 'Image width exceeds user limit in IHDR' |
inc ebx |
@@: |
cmp dword[height],0 |
jne @f ;if (..==0) |
png_warning edi, 'Image height is zero in IHDR' |
inc ebx |
@@: |
cmp dword[height],PNG_UINT_31_MAX |
jle @f ;if (..>..) |
png_warning edi, 'Invalid image height in IHDR' |
inc ebx |
@@: |
if PNG_SET_USER_LIMITS_SUPPORTED eq 1 |
mov eax,[edi+png_struct.user_height_max] |
cmp dword[height],eax |
else |
cmp dword[height],PNG_USER_HEIGHT_MAX |
end if |
jle @f ;if (..>..) |
png_warning edi, 'Image height exceeds user limit in IHDR' |
inc ebx |
@@: |
; Check other values |
cmp dword[bit_depth],1 |
je @f |
cmp dword[bit_depth],2 |
je @f |
cmp dword[bit_depth],4 |
je @f |
cmp dword[bit_depth],8 |
je @f |
cmp dword[bit_depth],16 |
je @f ;if (..!=.. && ...) |
png_warning edi, 'Invalid bit depth in IHDR' |
inc ebx |
@@: |
cmp dword[color_type],0 |
jl @f |
cmp dword[color_type],1 |
je @f |
cmp dword[color_type],5 |
je @f |
cmp dword[color_type],6 |
jg @f |
jmp .end0 |
@@: ;if (..<0 || ..==1 || ..==5 || ..>6) |
png_warning edi, 'Invalid color type in IHDR' |
inc ebx |
.end0: |
cmp dword[color_type],PNG_COLOR_TYPE_PALETTE |
jne @f |
cmp dword[bit_depth],8 |
jg .beg1 |
@@: |
cmp dword[color_type],PNG_COLOR_TYPE_RGB |
je @f |
cmp dword[color_type],PNG_COLOR_TYPE_GRAY_ALPHA |
je @f |
cmp dword[color_type],PNG_COLOR_TYPE_RGB_ALPHA |
jne .end1 |
@@: |
cmp dword[bit_depth],8 |
jge .end1 |
.beg1: ;if (((..==..) && ..>..) || ((..==.. || ..==.. || ..==..) && ..<..)) |
png_warning edi, 'Invalid color type/bit depth combination in IHDR' |
inc ebx |
.end1: |
cmp dword[interlace_type],PNG_INTERLACE_LAST |
jl @f ;if (..>=..) |
png_warning edi, 'Unknown interlace method in IHDR' |
inc ebx |
@@: |
cmp dword[compression_type],PNG_COMPRESSION_TYPE_BASE |
je @f ;if (..!=..) |
png_warning edi, 'Unknown compression method in IHDR' |
inc ebx |
@@: |
if PNG_MNG_FEATURES_SUPPORTED eq 1 |
; Accept filter_method 64 (intrapixel differencing) only if |
; 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and |
; 2. Libpng did not read a PNG signature (this filter_method is only |
; used in PNG datastreams that are embedded in MNG datastreams) and |
; 3. The application called png_permit_mng_features with a mask that |
; included PNG_FLAG_MNG_FILTER_64 and |
; 4. The filter_method is 64 and |
; 5. The color_type is RGB or RGBA |
; if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) != 0 && |
; png_ptr->mng_features_permitted != 0) |
png_warning edi, 'MNG features are not allowed in a PNG datastream' |
; if (filter_type != PNG_FILTER_TYPE_BASE) |
; { |
; if (!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 && |
; (filter_type == PNG_INTRAPIXEL_DIFFERENCING) && |
; ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) == 0) && |
; (color_type == PNG_COLOR_TYPE_RGB || |
; color_type == PNG_COLOR_TYPE_RGB_ALPHA))) |
; { |
png_warning edi, 'Unknown filter method in IHDR' |
inc ebx |
; } |
; if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) != 0) |
; { |
png_warning edi, 'Invalid filter method in IHDR' |
inc ebx |
; } |
; } |
else |
cmp dword[filter_type],PNG_FILTER_TYPE_BASE |
je @f ;if (..!=..) |
png_warning edi, 'Unknown filter method in IHDR' |
inc ebx |
@@: |
end if |
cmp ebx,0 |
je @f |
png_error edi, 'Invalid IHDR data' |
@@: |
ret |
endp |
;#if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) |
; ASCII to fp functions |
; Check an ASCII formated floating point value, see the more detailed |
; comments in pngpriv.inc |
; The following is used internally to preserve the sticky flags */ |
;#define png_fp_add(state, flags) ((state) |= (flags)) |
;#define png_fp_set(state, value) ((state) = (value) | ((state) & PNG_FP_STICKY)) |
;int (charp string, png_size_t size, int *statep, png_size_tp whereami) |
align 4 |
proc png_check_fp_number, string:dword, size:dword, statep:dword, whereami:dword |
; int state = *statep; |
; png_size_t i = *whereami; |
; while (i < size) |
; { |
; int type; |
; First find the type of the next character |
; switch (string[i]) |
; { |
; case 43: type = PNG_FP_SAW_SIGN; break; |
; case 45: type = PNG_FP_SAW_SIGN + PNG_FP_NEGATIVE; break; |
; case 46: type = PNG_FP_SAW_DOT; break; |
; case 48: type = PNG_FP_SAW_DIGIT; break; |
; case 49: case 50: case 51: case 52: |
; case 53: case 54: case 55: case 56: |
; case 57: type = PNG_FP_SAW_DIGIT + PNG_FP_NONZERO; break; |
; case 69: |
; case 101: type = PNG_FP_SAW_E; break; |
; default: goto PNG_FP_End; |
; } |
; Now deal with this type according to the current |
; state, the type is arranged to not overlap the |
; bits of the PNG_FP_STATE. |
; switch ((state & PNG_FP_STATE) + (type & PNG_FP_SAW_ANY)) |
; { |
; case PNG_FP_INTEGER + PNG_FP_SAW_SIGN: |
; if ((state & PNG_FP_SAW_ANY) != 0) |
; goto PNG_FP_End; /* not a part of the number */ |
; png_fp_add(state, type); |
; break; |
; case PNG_FP_INTEGER + PNG_FP_SAW_DOT: |
; Ok as trailer, ok as lead of fraction. |
; if ((state & PNG_FP_SAW_DOT) != 0) /* two dots */ |
; goto PNG_FP_End; |
; else if ((state & PNG_FP_SAW_DIGIT) != 0) /* trailing dot? */ |
; png_fp_add(state, type); |
; else |
; png_fp_set(state, PNG_FP_FRACTION | type); |
; break; |
; case PNG_FP_INTEGER + PNG_FP_SAW_DIGIT: |
; if ((state & PNG_FP_SAW_DOT) != 0) /* delayed fraction */ |
; png_fp_set(state, PNG_FP_FRACTION | PNG_FP_SAW_DOT); |
; png_fp_add(state, type | PNG_FP_WAS_VALID); |
; break; |
; case PNG_FP_INTEGER + PNG_FP_SAW_E: |
; if ((state & PNG_FP_SAW_DIGIT) == 0) |
; goto PNG_FP_End; |
; png_fp_set(state, PNG_FP_EXPONENT); |
; break; |
; /* case PNG_FP_FRACTION + PNG_FP_SAW_SIGN: goto PNG_FP_End; ** no sign in fraction */ |
; /* case PNG_FP_FRACTION + PNG_FP_SAW_DOT: goto PNG_FP_End; ** Because SAW_DOT is always set */ |
; case PNG_FP_FRACTION + PNG_FP_SAW_DIGIT: |
; png_fp_add(state, type | PNG_FP_WAS_VALID); |
; break; |
; case PNG_FP_FRACTION + PNG_FP_SAW_E: |
; This is correct because the trailing '.' on an |
; integer is handled above - so we can only get here |
; with the sequence ".E" (with no preceding digits). |
; if ((state & PNG_FP_SAW_DIGIT) == 0) |
; goto PNG_FP_End; |
; png_fp_set(state, PNG_FP_EXPONENT); |
; break; |
; case PNG_FP_EXPONENT + PNG_FP_SAW_SIGN: |
; if ((state & PNG_FP_SAW_ANY) != 0) |
; goto PNG_FP_End; /* not a part of the number */ |
; png_fp_add(state, PNG_FP_SAW_SIGN); |
; break; |
; /* case PNG_FP_EXPONENT + PNG_FP_SAW_DOT: goto PNG_FP_End; */ |
; case PNG_FP_EXPONENT + PNG_FP_SAW_DIGIT: |
; png_fp_add(state, PNG_FP_SAW_DIGIT | PNG_FP_WAS_VALID); |
; break; |
; /* case PNG_FP_EXPONEXT + PNG_FP_SAW_E: goto PNG_FP_End; */ |
; default: goto PNG_FP_End; /* I.e. break 2 */ |
; } |
; The character seems ok, continue. |
; ++i; |
; } |
; |
;PNG_FP_End: |
; Here at the end, update the state and return the correct |
; return code. |
; *statep = state; |
; *whereami = i; |
; return (state & PNG_FP_SAW_DIGIT) != 0; |
ret |
endp |
; The same but for a complete string. |
;int (charp string, png_size_t size) |
align 4 |
proc png_check_fp_string, string:dword, size:dword |
; int state=0; |
; png_size_t char_index=0; |
; |
; if (png_check_fp_number(string, size, &state, &char_index) != 0 && |
; (char_index == size || string[char_index] == 0)) |
; return state /* must be non-zero - see above */; |
; return 0; /* i.e. fail */ |
ret |
endp |
;end if /* pCAL || sCAL */ |
;if PNG_sCAL_SUPPORTED |
;# ifdef PNG_FLOATING_POINT_SUPPORTED |
; Utility used below - a simple accurate power of ten from an integral |
; exponent. |
;double (int power) |
align 4 |
proc png_pow10, power:dword |
; int recip = 0; |
; double d = 1; |
; Handle negative exponent with a reciprocal at the end because |
; 10 is exact whereas .1 is inexact in base 2 |
; if (power < 0) |
; { |
; if (power < DBL_MIN_10_EXP) return 0; |
; recip = 1, power = -power; |
; } |
; if (power > 0) |
; { |
; Decompose power bitwise. |
; double mult = 10; |
; do |
; { |
; if (power & 1) d *= mult; |
; mult *= mult; |
; power >>= 1; |
; } |
; while (power > 0); |
; if (recip != 0) d = 1/d; |
; } |
; else power is 0 and d is 1 |
; return d; |
ret |
endp |
; Function to format a floating point value in ASCII with a given |
; precision. |
;void (png_structrp png_ptr, charp ascii, png_size_t size, |
; double fp, uint precision) |
align 4 |
proc png_ascii_from_fp, png_ptr:dword, ascii:dword, size:dword, fp:dword, precision:dword |
; We use standard functions from math.h, but not printf because |
; that would require stdio. The caller must supply a buffer of |
; sufficient size or we will png_error. The tests on size and |
; the space in ascii[] consumed are indicated below. |
; if (precision < 1) |
; precision = DBL_DIG; |
; Enforce the limit of the implementation precision too. |
; if (precision > DBL_DIG+1) |
; precision = DBL_DIG+1; |
; Basic sanity checks |
; if (size >= precision+5) /* See the requirements below. */ |
; { |
; if (fp < 0) |
; { |
; fp = -fp; |
; *ascii++ = 45; /* '-' PLUS 1 TOTAL 1 */ |
; --size; |
; } |
; if (fp >= DBL_MIN && fp <= DBL_MAX) |
; { |
; int exp_b10; /* A base 10 exponent */ |
; double base; /* 10^exp_b10 */ |
; First extract a base 10 exponent of the number, |
; the calculation below rounds down when converting |
; from base 2 to base 10 (multiply by log10(2) - |
; 0.3010, but 77/256 is 0.3008, so exp_b10 needs to |
; be increased. Note that the arithmetic shift |
; performs a floor() unlike C arithmetic - using a |
; C multiply would break the following for negative |
; exponents. |
; (void)frexp(fp, &exp_b10); /* exponent to base 2 */ |
; exp_b10 = (exp_b10 * 77) >> 8; /* <= exponent to base 10 */ |
; /* Avoid underflow here. */ |
; base = png_pow10(exp_b10); /* May underflow */ |
; while (base < DBL_MIN || base < fp) |
; { |
; /* And this may overflow. */ |
; double test = png_pow10(exp_b10+1); |
; if (test <= DBL_MAX) |
; ++exp_b10, base = test; |
; else |
; break; |
; } |
; Normalize fp and correct exp_b10, after this fp is in the |
; range [.1,1) and exp_b10 is both the exponent and the digit |
; *before* which the decimal point should be inserted |
; (starting with 0 for the first digit). Note that this |
; works even if 10^exp_b10 is out of range because of the |
; test on DBL_MAX above. |
; fp /= base; |
; while (fp >= 1) fp /= 10, ++exp_b10; |
; Because of the code above fp may, at this point, be |
; less than .1, this is ok because the code below can |
; handle the leading zeros this generates, so no attempt |
; is made to correct that here. |
; { |
; uint czero, clead, cdigits; |
; char exponent[10]; |
; Allow up to two leading zeros - this will not lengthen |
; the number compared to using E-n. |
; if (exp_b10 < 0 && exp_b10 > -3) /* PLUS 3 TOTAL 4 */ |
; { |
; czero = -exp_b10; /* PLUS 2 digits: TOTAL 3 */ |
; exp_b10 = 0; /* Dot added below before first output. */ |
; } |
; else |
; czero = 0; /* No zeros to add */ |
; Generate the digit list, stripping trailing zeros and |
; inserting a '.' before a digit if the exponent is 0. |
; clead = czero; /* Count of leading zeros */ |
; cdigits = 0; /* Count of digits in list. */ |
; do |
; { |
; double d; |
; fp *= 10; |
; Use modf here, not floor and subtract, so that |
; the separation is done in one step. At the end |
; of the loop don't break the number into parts so |
; that the final digit is rounded. |
; if (cdigits+czero+1 < precision+clead) |
; fp = modf(fp, &d); |
; else |
; { |
; d = floor(fp + .5); |
; if (d > 9) |
; { |
; /* Rounding up to 10, handle that here. */ |
; if (czero > 0) |
; { |
; --czero, d = 1; |
; if (cdigits == 0) --clead; |
; } |
; else |
; { |
; while (cdigits > 0 && d > 9) |
; { |
; int ch = *--ascii; |
; if (exp_b10 != (-1)) |
; ++exp_b10; |
; else if (ch == 46) |
; { |
; ch = *--ascii, ++size; |
; /* Advance exp_b10 to '1', so that the |
; * decimal point happens after the |
; * previous digit. |
; exp_b10 = 1; |
; } |
; --cdigits; |
; d = ch - 47; /* I.e. 1+(ch-48) */ |
; } |
; /* Did we reach the beginning? If so adjust the |
; * exponent but take into account the leading |
; * decimal point. |
; if (d > 9) /* cdigits == 0 */ |
; { |
; if (exp_b10 == (-1)) |
; { |
; Leading decimal point (plus zeros?), if |
; we lose the decimal point here it must |
; be reentered below. |
; int ch = *--ascii; |
; if (ch == 46) |
; ++size, exp_b10 = 1; |
; /* Else lost a leading zero, so 'exp_b10' is |
; * still ok at (-1) |
; } |
; else |
; ++exp_b10; |
; /* In all cases we output a '1' */ |
; d = 1; |
; } |
; } |
; } |
; fp = 0; /* Guarantees termination below. */ |
; } |
; if (d == 0) |
; { |
; ++czero; |
; if (cdigits == 0) ++clead; |
; } |
; else |
; { |
; /* Included embedded zeros in the digit count. */ |
; cdigits += czero - clead; |
; clead = 0; |
; while (czero > 0) |
; { |
; exp_b10 == (-1) means we just output the decimal |
; place - after the DP don't adjust 'exp_b10' any |
; more! |
; if (exp_b10 != (-1)) |
; { |
; if (exp_b10 == 0) *ascii++ = 46, --size; |
; /* PLUS 1: TOTAL 4 */ |
; --exp_b10; |
; } |
; *ascii++ = 48, --czero; |
; } |
; if (exp_b10 != (-1)) |
; { |
; if (exp_b10 == 0) |
; *ascii++ = 46, --size; /* counted above */ |
; --exp_b10; |
; } |
; *ascii++ = (char)(48 + (int)d), ++cdigits; |
; } |
; } |
; while (cdigits+czero < precision+clead && fp > DBL_MIN); |
; /* The total output count (max) is now 4+precision */ |
; Check for an exponent, if we don't need one we are |
; done and just need to terminate the string. At |
; this point exp_b10==(-1) is effectively if flag - it got |
; to '-1' because of the decrement after outputting |
; the decimal point above (the exponent required is |
; *not* -1!) |
; if (exp_b10 >= (-1) && exp_b10 <= 2) |
; { |
; The following only happens if we didn't output the |
; leading zeros above for negative exponent, so this |
; doesn't add to the digit requirement. Note that the |
; two zeros here can only be output if the two leading |
; zeros were *not* output, so this doesn't increase |
; the output count. |
; while (--exp_b10 >= 0) *ascii++ = 48; |
; *ascii = 0; |
; /* Total buffer requirement (including the '\0') is |
; 5+precision - see check at the start. |
; return; |
; } |
; Here if an exponent is required, adjust size for |
; the digits we output but did not count. The total |
; digit output here so far is at most 1+precision - no |
; decimal point and no leading or trailing zeros have |
; been output. |
; size -= cdigits; |
; |
; *ascii++ = 69, --size; /* 'E': PLUS 1 TOTAL 2+precision */ |
; The following use of an unsigned temporary avoids ambiguities in |
; the signed arithmetic on exp_b10 and permits GCC at least to do |
; better optimization. |
; { |
; uint uexp_b10; |
; if (exp_b10 < 0) |
; { |
; *ascii++ = 45, --size; /* '-': PLUS 1 TOTAL 3+precision */ |
; uexp_b10 = -exp_b10; |
; } |
; else |
; uexp_b10 = exp_b10; |
; cdigits = 0; |
; while (uexp_b10 > 0) |
; { |
; exponent[cdigits++] = (char)(48 + uexp_b10 % 10); |
; uexp_b10 /= 10; |
; } |
; } |
; Need another size check here for the exponent digits, so |
; this need not be considered above. |
; if (size > cdigits) |
; { |
; while (cdigits > 0) *ascii++ = exponent[--cdigits]; |
; *ascii = 0; |
; return; |
; } |
; } |
; } |
; else if (!(fp >= DBL_MIN)) |
; { |
; *ascii++ = 48; /* '0' */ |
; *ascii = 0; |
; return; |
; } |
; else |
; { |
; *ascii++ = 105; /* 'i' */ |
; *ascii++ = 110; /* 'n' */ |
; *ascii++ = 102; /* 'f' */ |
; *ascii = 0; |
; return; |
; } |
; } |
; Here on buffer too small. |
; png_error(png_ptr, "ASCII conversion buffer too small"); |
ret |
endp |
;# endif /* FLOATING_POINT */ |
; Function to format a fixed point value in ASCII. |
;void (png_structrp png_ptr, charp ascii, png_size_t size, png_fixed_point fp) |
align 4 |
proc png_ascii_from_fixed, png_ptr:dword, ascii:dword, size:dword, fp:dword |
; Require space for 10 decimal digits, a decimal point, a minus sign and a |
; trailing \0, 13 characters: |
cmp dword[size],12 |
jle .end0 ;if (..>..) |
; uint_32 num; |
; Avoid overflow here on the minimum integer. |
; if (fp < 0) |
; *ascii++ = 45, num = -fp; |
; else |
; num = fp; |
; if (num <= 0x80000000) /* else overflowed */ |
; { |
; uint ndigits = 0, first = 16 /* flag value */; |
; char digits[10]; |
; while (num) |
; { |
; Split the low digit off num: |
; uint tmp = num/10; |
; num -= tmp*10; |
; digits[ndigits++] = (char)(48 + num); |
; Record the first non-zero digit, note that this is a number |
; starting at 1, it's not actually the array index. |
; if (first == 16 && num > 0) |
; first = ndigits; |
; num = tmp; |
; } |
; if (ndigits > 0) |
; { |
; while (ndigits > 5) *ascii++ = digits[--ndigits]; |
; The remaining digits are fractional digits, ndigits is '5' or |
; smaller at this point. It is certainly not zero. Check for a |
; non-zero fractional digit: |
; if (first <= 5) |
; { |
; uint i; |
; *ascii++ = 46; /* decimal point */ |
; ndigits may be <5 for small numbers, output leading zeros |
; then ndigits digits to first: |
; i = 5; |
; while (ndigits < i) *ascii++ = 48, --i; |
; while (ndigits >= first) *ascii++ = digits[--ndigits]; |
; Don't output the trailing zeros! |
; } |
; } |
; else |
; *ascii++ = 48; |
; And null terminate the string: |
; *ascii = 0; |
; return; |
; } |
.end0: |
; Here on buffer too small. |
png_error [png_ptr], 'ASCII conversion buffer too small' |
ret |
endp |
;end if /* SCAL */ |
;png_fixed_point (png_structrp png_ptr, double fp, charp text) |
align 4 |
proc png_fixed, png_ptr:dword, fp:dword, text:dword |
; double r = floor(100000 * fp + .5); |
; if (r > 2147483647. || r < -2147483648.) |
; png_fixed_error(png_ptr, text); |
; return (png_fixed_point)r; |
ret |
endp |
; muldiv functions |
; This API takes signed arguments and rounds the result to the nearest |
; integer (or, for a fixed point number - the standard argument - to |
; the nearest .00001). Overflow and divide by zero are signalled in |
; the result, a boolean - true on success, false on overflow. |
;int (png_fixed_point_p res, png_fixed_point a, int_32 times, int_32 divisor) |
align 4 |
proc png_muldiv, res:dword, a:dword, p3times:dword, divisor:dword |
; Return a * times / divisor, rounded. |
; if (divisor != 0) |
; { |
; if (a == 0 || p3times == 0) |
; { |
; *res = 0; |
; return 1; |
; } |
; else |
; { |
if PNG_FLOATING_ARITHMETIC_SUPPORTED eq 1 |
; double r = a; |
; r *= p3times; |
; r /= divisor; |
; r = floor(r+.5); |
; /* A png_fixed_point is a 32-bit integer. */ |
; if (r <= 2147483647. && r >= -2147483648.) |
; { |
; *res = (png_fixed_point)r; |
; return 1; |
; } |
else |
; int negative = 0; |
; uint_32 A, T, D; |
; uint_32 s16, s32, s00; |
; if (a < 0) |
; negative = 1, A = -a; |
; else |
; A = a; |
; if (p3times < 0) |
; negative = !negative, T = -p3times; |
; else |
; T = p3times; |
; if (divisor < 0) |
; negative = !negative, D = -divisor; |
; else |
; D = divisor; |
; Following can't overflow because the arguments only |
; have 31 bits each, however the result may be 32 bits. |
; s16 = (A >> 16) * (T & 0xffff) + |
; (A & 0xffff) * (T >> 16); |
; Can't overflow because the a*times bit is only 30 |
; bits at most. |
; s32 = (A >> 16) * (T >> 16) + (s16 >> 16); |
; s00 = (A & 0xffff) * (T & 0xffff); |
; s16 = (s16 & 0xffff) << 16; |
; s00 += s16; |
; if (s00 < s16) |
; ++s32; /* carry */ |
; if (s32 < D) /* else overflow */ |
; { |
; s32.s00 is now the 64-bit product, do a standard |
; division, we know that s32 < D, so the maximum |
; required shift is 31. |
; int bitshift = 32; |
; png_fixed_point result = 0; /* NOTE: signed */ |
; while (--bitshift >= 0) |
; { |
; uint_32 d32, d00; |
; if (bitshift > 0) |
; d32 = D >> (32-bitshift), d00 = D << bitshift; |
; else |
; d32 = 0, d00 = D; |
; if (s32 > d32) |
; { |
; if (s00 < d00) --s32; /* carry */ |
; s32 -= d32, s00 -= d00, result += 1<<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 |