Subversion Repositories Kolibri OS

Rev

Rev 6870 | Rev 6881 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 6870 Rev 6873
1
; pngwrite.asm - general routines to write a PNG file
1
; pngwrite.asm - general routines to write a PNG file
2
 
2
 
3
; Last changed in libpng 1.6.24 [August 4, 2016]
3
; Last changed in libpng 1.6.24 [August 4, 2016]
4
; Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
4
; Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
5
; (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
5
; (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
6
; (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
6
; (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
7
 
7
 
8
; This code is released under the libpng license.
8
; This code is released under the libpng license.
9
; For conditions of distribution and use, see the disclaimer
9
; For conditions of distribution and use, see the disclaimer
10
; and license in png.inc
10
; and license in png.inc
11
 
11
 
12
; Write out all the unknown chunks for the current given location
12
; Write out all the unknown chunks for the current given location
13
;void (png_structrp png_ptr, png_const_inforp info_ptr, unsigned int where)
13
;void (png_structrp png_ptr, png_const_inforp info_ptr, unsigned int where)
14
align 4
14
align 4
15
proc write_unknown_chunks, png_ptr:dword, info_ptr:dword, where:dword
15
proc write_unknown_chunks, png_ptr:dword, info_ptr:dword, where:dword
16
pushad
16
pushad
17
	mov esi,[info_ptr]
17
	mov esi,[info_ptr]
18
	cmp dword[esi+png_info_def.unknown_chunks_num],0
18
	cmp dword[esi+png_info_def.unknown_chunks_num],0
19
	je .end_f ;if(..!=0)
19
	je .end_f ;if(..!=0)
20
		mov edi,[png_ptr]
20
		mov edi,[png_ptr]
21
		;ecx = up
21
		;ecx = up
22
 
22
 
23
		png_debug 5, 'writing extra chunks'
23
		png_debug 5, 'writing extra chunks'
24
 
24
 
25
		mov ecx,[esi+png_info_def.unknown_chunks]
25
		mov ecx,[esi+png_info_def.unknown_chunks]
26
		mov edx,[esi+png_info_def.unknown_chunks_num]
26
		mov edx,[esi+png_info_def.unknown_chunks_num]
27
		imul edx,sizeof.png_unknown_chunk
27
		imul edx,sizeof.png_unknown_chunk
28
		add edx,ecx
28
		add edx,ecx
29
		.cycle0: ;for (..;..<..;..)
29
		.cycle0: ;for (..;..<..;..)
30
			cmp ecx,edx
30
			cmp ecx,edx
31
			jge .end_f
31
			jge .end_f
32
			movzx eax,byte[ecx+png_unknown_chunk.location]
32
			movzx eax,byte[ecx+png_unknown_chunk.location]
33
			and eax,[where]
33
			and eax,[where]
34
			jz .end0 ;if (..!=0)
34
			jz .end0 ;if (..!=0)
35
			; If per-chunk unknown chunk handling is enabled use it, otherwise
35
			; If per-chunk unknown chunk handling is enabled use it, otherwise
36
			; just write the chunks the application has set.
36
			; just write the chunks the application has set.
37
 
37
 
38
if PNG_SET_UNKNOWN_CHUNKS_SUPPORTED eq 1
38
if PNG_SET_UNKNOWN_CHUNKS_SUPPORTED eq 1
39
			mov eax,ecx
39
			mov eax,ecx
40
			add eax,png_unknown_chunk.name
40
			add eax,png_unknown_chunk.name
41
			stdcall png_handle_as_unknown, edi, eax
41
			stdcall png_handle_as_unknown, edi, eax
42
 
42
 
43
			; NOTE: this code is radically different from the read side in the
43
			; NOTE: this code is radically different from the read side in the
44
			; matter of handling an ancillary unknown chunk.  In the read side
44
			; matter of handling an ancillary unknown chunk.  In the read side
45
			; the default behavior is to discard it, in the code below the default
45
			; the default behavior is to discard it, in the code below the default
46
			; behavior is to write it.  Critical chunks are, however, only
46
			; behavior is to write it.  Critical chunks are, however, only
47
			; written if explicitly listed or if the default is set to write all
47
			; written if explicitly listed or if the default is set to write all
48
			; unknown chunks.
48
			; unknown chunks.
49
 
49
 
50
			; The default handling is also slightly weird - it is not possible to
50
			; The default handling is also slightly weird - it is not possible to
51
			; stop the writing of all unsafe-to-copy chunks!
51
			; stop the writing of all unsafe-to-copy chunks!
52
 
52
 
53
			; TODO: REVIEW: this would seem to be a bug.
53
			; TODO: REVIEW: this would seem to be a bug.
54
 
54
 
55
			cmp eax,PNG_HANDLE_CHUNK_NEVER
55
			cmp eax,PNG_HANDLE_CHUNK_NEVER
56
			je .end0
56
			je .end0
57
			mov bl,byte[ecx+png_unknown_chunk.name+3]
57
			mov bl,byte[ecx+png_unknown_chunk.name+3]
58
			and bl,0x20
58
			and bl,0x20
59
			cmp bl,0
59
			cmp bl,0
60
			jne .beg0
60
			jne .beg0
61
			cmp eax,PNG_HANDLE_CHUNK_ALWAYS
61
			cmp eax,PNG_HANDLE_CHUNK_ALWAYS
62
			je .beg0
62
			je .beg0
63
			cmp eax,PNG_HANDLE_CHUNK_AS_DEFAULT
63
			cmp eax,PNG_HANDLE_CHUNK_AS_DEFAULT
64
			jne .end0
64
			jne .end0
65
			cmp dword[edi+png_struct.unknown_default],PNG_HANDLE_CHUNK_ALWAYS
65
			cmp dword[edi+png_struct.unknown_default],PNG_HANDLE_CHUNK_ALWAYS
66
			jne .end0
66
			jne .end0
67
end if
67
end if
68
			.beg0: ;if (..!=.. && (.. safe-to-copy overrides everything || ..==.. || (..==.. && ..==..)))
68
			.beg0: ;if (..!=.. && (.. safe-to-copy overrides everything || ..==.. || (..==.. && ..==..)))
69
				; TODO: review, what is wrong with a zero length unknown chunk?
69
				; TODO: review, what is wrong with a zero length unknown chunk?
70
				cmp dword[ecx+png_unknown_chunk.size],0
70
				cmp dword[ecx+png_unknown_chunk.size],0
71
				jne @f ;if (..==0)
71
				jne @f ;if (..==0)
72
					png_warning [png_ptr], 'Writing zero-length unknown chunk'
72
					png_warning [png_ptr], 'Writing zero-length unknown chunk'
73
				@@:
73
				@@:
74
				mov eax,dword[ecx+png_unknown_chunk.name]
74
				mov eax,dword[ecx+png_unknown_chunk.name]
75
				stdcall png_write_chunk, edi, eax, [ecx+png_unknown_chunk.podata], [ecx+png_unknown_chunk.size]
75
				stdcall png_write_chunk, edi, eax, [ecx+png_unknown_chunk.podata], [ecx+png_unknown_chunk.size]
76
			.end0:
76
			.end0:
77
			add ecx,sizeof.png_unknown_chunk
77
			add ecx,sizeof.png_unknown_chunk
78
			jmp .cycle0
78
			jmp .cycle0
79
		;.cycle0end:
79
		;.cycle0end:
80
.end_f:
80
.end_f:
81
popad
81
popad
82
	ret
82
	ret
83
endp
83
endp
84
 
84
 
85
; Writes all the PNG information.  This is the suggested way to use the
85
; Writes all the PNG information.  This is the suggested way to use the
86
; library.  If you have a new chunk to add, make a function to write it,
86
; library.  If you have a new chunk to add, make a function to write it,
87
; and put it in the correct location here.  If you want the chunk written
87
; and put it in the correct location here.  If you want the chunk written
88
; after the image data, put it in png_write_end().  I strongly encourage
88
; after the image data, put it in png_write_end().  I strongly encourage
89
; you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing
89
; you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing
90
; the chunk, as that will keep the code from breaking if you want to just
90
; the chunk, as that will keep the code from breaking if you want to just
91
; write a plain PNG file.  If you have long comments, I suggest writing
91
; write a plain PNG file.  If you have long comments, I suggest writing
92
; them in png_write_end(), and compressing them.
92
; them in png_write_end(), and compressing them.
93
 
93
 
94
;void (png_structrp png_ptr, png_const_inforp info_ptr)
94
;void (png_structrp png_ptr, png_const_inforp info_ptr)
95
align 4
95
align 4
96
proc png_write_info_before_PLTE, png_ptr:dword, info_ptr:dword
96
proc png_write_info_before_PLTE, png_ptr:dword, info_ptr:dword
97
	png_debug 1, 'in png_write_info_before_PLTE'
97
	png_debug 1, 'in png_write_info_before_PLTE'
98
 
98
 
99
pushad
99
pushad
100
	mov edi,[png_ptr]
100
	mov edi,[png_ptr]
101
	cmp edi,0
101
	cmp edi,0
102
	je .end_f
102
	je .end_f
103
	mov esi,[info_ptr]
103
	mov esi,[info_ptr]
104
	cmp esi,0
104
	cmp esi,0
105
	je .end_f ;if(..==0 || ..==0) return
105
	je .end_f ;if(..==0 || ..==0) return
106
 
106
 
107
	mov eax,[edi+png_struct.mode]
107
	mov eax,[edi+png_struct.mode]
108
	and eax,PNG_WROTE_INFO_BEFORE_PLTE
108
	and eax,PNG_WROTE_INFO_BEFORE_PLTE
109
	jnz .end_f ;if (..==0)
109
	jnz .end_f ;if (..==0)
110
 
110
 
111
		; Write PNG signature
111
		; Write PNG signature
112
		stdcall png_write_sig, edi
112
		stdcall png_write_sig, edi
113
 
113
 
114
if PNG_MNG_FEATURES_SUPPORTED eq 1
114
if PNG_MNG_FEATURES_SUPPORTED eq 1
115
		mov eax,[edi+png_struct.mode]
115
		mov eax,[edi+png_struct.mode]
116
		and eax,PNG_HAVE_PNG_SIGNATURE
116
		and eax,PNG_HAVE_PNG_SIGNATURE
117
		jz @f
117
		jz @f
118
		cmp dword[edi+png_struct.mng_features_permitted],0
118
		cmp dword[edi+png_struct.mng_features_permitted],0
119
		je @f ;if(..!=0 && ..!=0)
119
		je @f ;if(..!=0 && ..!=0)
120
			png_warning edi, 'MNG features are not allowed in a PNG datastream'
120
			png_warning edi, 'MNG features are not allowed in a PNG datastream'
121
			mov dword[edi+png_struct.mng_features_permitted],0
121
			mov dword[edi+png_struct.mng_features_permitted],0
122
		@@:
122
		@@:
123
end if
123
end if
124
 
124
 
125
	; Write IHDR information.
125
	; Write IHDR information.
126
if PNG_WRITE_INTERLACING_SUPPORTED eq 1
126
if PNG_WRITE_INTERLACING_SUPPORTED eq 1
127
	movzx eax,byte[esi+png_info_def.interlace_type]
127
	movzx eax,byte[esi+png_info_def.interlace_type]
128
	push eax
128
	push eax
129
else
129
else
130
	push dword 0
130
	push dword 0
131
end if
131
end if
132
	movzx eax,byte[esi+png_info_def.filter_type]
132
	movzx eax,byte[esi+png_info_def.filter_type]
133
	push eax
133
	push eax
134
	movzx eax,byte[esi+png_info_def.compression_type]
134
	movzx eax,byte[esi+png_info_def.compression_type]
135
	push eax
135
	push eax
136
	movzx eax,byte[esi+png_info_def.color_type]
136
	movzx eax,byte[esi+png_info_def.color_type]
137
	push eax
137
	push eax
138
	movzx eax,byte[esi+png_info_def.bit_depth]
138
	movzx eax,byte[esi+png_info_def.bit_depth]
139
	stdcall png_write_IHDR, edi,\
139
	stdcall png_write_IHDR, edi,\
140
		dword[esi+png_info_def.width], dword[esi+png_info_def.height], eax
140
		dword[esi+png_info_def.width], dword[esi+png_info_def.height], eax
141
 
141
 
142
; The rest of these check to see if the valid field has the appropriate
142
; The rest of these check to see if the valid field has the appropriate
143
; flag set, and if it does, writes the chunk.
143
; flag set, and if it does, writes the chunk.
144
 
144
 
145
; 1.6.0: COLORSPACE support controls the writing of these chunks too, and
145
; 1.6.0: COLORSPACE support controls the writing of these chunks too, and
146
; the chunks will be written if the WRITE routine is there and
146
; the chunks will be written if the WRITE routine is there and
147
; information * is available in the COLORSPACE. (See
147
; information * is available in the COLORSPACE. (See
148
; png_colorspace_sync_info in png.c for where the valid flags get set.)
148
; png_colorspace_sync_info in png.c for where the valid flags get set.)
149
 
149
 
150
; Under certain circumstances the colorspace can be invalidated without
150
; Under certain circumstances the colorspace can be invalidated without
151
; syncing the info_struct 'valid' flags; this happens if libpng detects
151
; syncing the info_struct 'valid' flags; this happens if libpng detects
152
; an error and calls png_error while the color space is being set, yet
152
; an error and calls png_error while the color space is being set, yet
153
; the application continues writing the PNG.  So check the 'invalid'
153
; the application continues writing the PNG.  So check the 'invalid'
154
; flag here too.
154
; flag here too.
155
 
155
 
156
if PNG_GAMMA_SUPPORTED eq 1
156
if PNG_GAMMA_SUPPORTED eq 1
157
if PNG_WRITE_gAMA_SUPPORTED eq 1
157
if PNG_WRITE_gAMA_SUPPORTED eq 1
158
	movzx eax,word[esi+png_info_def.colorspace.flags]
158
	movzx eax,word[esi+png_info_def.colorspace.flags]
159
	and eax,PNG_COLORSPACE_INVALID
159
	and eax,PNG_COLORSPACE_INVALID
160
	jnz @f
160
	jnz @f
161
	movzx eax,word[esi+png_info_def.colorspace.flags]
161
	movzx eax,word[esi+png_info_def.colorspace.flags]
162
	and eax,PNG_COLORSPACE_FROM_gAMA
162
	and eax,PNG_COLORSPACE_FROM_gAMA
163
	jz @f
163
	jz @f
164
	mov eax,[esi+png_info_def.valid]
164
	mov eax,[esi+png_info_def.valid]
165
	and eax,PNG_INFO_gAMA
165
	and eax,PNG_INFO_gAMA
166
	jz @f ;if (..==0 && ..!=0 && ..!=0)
166
	jz @f ;if (..==0 && ..!=0 && ..!=0)
167
		stdcall png_write_gAMA_fixed, edi, [esi+png_info_def.colorspace.gamma]
167
		stdcall png_write_gAMA_fixed, edi, [esi+png_info_def.colorspace.gamma]
168
	@@:
168
	@@:
169
end if
169
end if
170
end if
170
end if
171
 
171
 
172
if PNG_COLORSPACE_SUPPORTED eq 1
172
if PNG_COLORSPACE_SUPPORTED eq 1
173
	; Write only one of sRGB or an ICC profile.  If a profile was supplied
173
	; Write only one of sRGB or an ICC profile.  If a profile was supplied
174
	; and it matches one of the known sRGB ones issue a warning.
174
	; and it matches one of the known sRGB ones issue a warning.
175
 
175
 
176
if PNG_WRITE_iCCP_SUPPORTED eq 1
176
if PNG_WRITE_iCCP_SUPPORTED eq 1
177
	movzx eax,word[esi+png_info_def.colorspace.flags]
177
	movzx eax,word[esi+png_info_def.colorspace.flags]
178
	and eax,PNG_COLORSPACE_INVALID
178
	and eax,PNG_COLORSPACE_INVALID
179
	jnz .end0
179
	jnz .end0
180
	mov eax,[esi+png_info_def.valid]
180
	mov eax,[esi+png_info_def.valid]
181
	and eax,PNG_INFO_iCCP
181
	and eax,PNG_INFO_iCCP
182
	jz .end0 ;if (..==0 && ..!=0)
182
	jz .end0 ;if (..==0 && ..!=0)
183
if PNG_WRITE_sRGB_SUPPORTED eq 1
183
if PNG_WRITE_sRGB_SUPPORTED eq 1
184
		mov eax,[esi+png_info_def.valid]
184
		mov eax,[esi+png_info_def.valid]
185
		and eax,PNG_INFO_sRGB
185
		and eax,PNG_INFO_sRGB
186
		jz @f ;if (..!=0)
186
		jz @f ;if (..!=0)
187
			png_app_warning edi, 'profile matches sRGB but writing iCCP instead'
187
			png_app_warning edi, 'profile matches sRGB but writing iCCP instead'
188
		@@:
188
		@@:
189
end if
189
end if
190
		stdcall png_write_iCCP, edi, [esi+png_info_def.iccp_name],\
190
		stdcall png_write_iCCP, edi, [esi+png_info_def.iccp_name],\
191
			[esi+png_info_def.iccp_profile]
191
			[esi+png_info_def.iccp_profile]
192
if PNG_WRITE_sRGB_SUPPORTED eq 1
192
if PNG_WRITE_sRGB_SUPPORTED eq 1
193
		jmp .end1
193
		jmp .end1
194
end if
194
end if
195
	.end0: ;else
195
	.end0: ;else
196
end if
196
end if
197
 
197
 
198
if PNG_WRITE_sRGB_SUPPORTED eq 1
198
if PNG_WRITE_sRGB_SUPPORTED eq 1
199
	movzx eax,word[esi+png_info_def.colorspace.flags]
199
	movzx eax,word[esi+png_info_def.colorspace.flags]
200
	and eax,PNG_COLORSPACE_INVALID
200
	and eax,PNG_COLORSPACE_INVALID
201
	jnz .end1
201
	jnz .end1
202
	mov eax,[esi+png_info_def.valid]
202
	mov eax,[esi+png_info_def.valid]
203
	and eax,PNG_INFO_sRGB
203
	and eax,PNG_INFO_sRGB
204
	jz .end1 ;if (..==0 && ..!=0)
204
	jz .end1 ;if (..==0 && ..!=0)
205
		movzx eax,word[esi+png_info_def.colorspace.rendering_intent]
205
		movzx eax,word[esi+png_info_def.colorspace.rendering_intent]
206
		stdcall png_write_sRGB, edi, eax
206
		stdcall png_write_sRGB, edi, eax
207
	.end1:
207
	.end1:
208
end if ;sRGB
208
end if ;sRGB
209
end if ;COLORSPACE
209
end if ;COLORSPACE
210
 
210
 
211
if PNG_WRITE_sBIT_SUPPORTED eq 1
211
if PNG_WRITE_sBIT_SUPPORTED eq 1
212
	mov eax,[esi+png_info_def.valid]
212
	mov eax,[esi+png_info_def.valid]
213
	and eax,PNG_INFO_sBIT
213
	and eax,PNG_INFO_sBIT
214
	jz @f ;if (..!=0)
214
	jz @f ;if (..!=0)
215
		movzx eax,byte[esi+png_info_def.color_type]
215
		movzx eax,byte[esi+png_info_def.color_type]
216
		push eax
216
		push eax
217
		mov eax,esi
217
		mov eax,esi
218
		add eax,png_info_def.sig_bit
218
		add eax,png_info_def.sig_bit
219
		stdcall png_write_sBIT, edi, eax ;, ...color_type
219
		stdcall png_write_sBIT, edi, eax ;, ...color_type
220
	@@:
220
	@@:
221
end if
221
end if
222
 
222
 
223
if PNG_COLORSPACE_SUPPORTED eq 1
223
if PNG_COLORSPACE_SUPPORTED eq 1
224
if PNG_WRITE_cHRM_SUPPORTED eq 1
224
if PNG_WRITE_cHRM_SUPPORTED eq 1
225
	movzx eax,word[esi+png_info_def.colorspace.flags]
225
	movzx eax,word[esi+png_info_def.colorspace.flags]
226
	and eax,PNG_COLORSPACE_INVALID
226
	and eax,PNG_COLORSPACE_INVALID
227
	jnz @f
227
	jnz @f
228
	movzx eax,word[esi+png_info_def.colorspace.flags]
228
	movzx eax,word[esi+png_info_def.colorspace.flags]
229
	and eax,PNG_COLORSPACE_FROM_cHRM
229
	and eax,PNG_COLORSPACE_FROM_cHRM
230
	jz @f
230
	jz @f
231
	mov eax,[esi+png_info_def.valid]
231
	mov eax,[esi+png_info_def.valid]
232
	and eax,PNG_INFO_cHRM
232
	and eax,PNG_INFO_cHRM
233
	jz @f ;if (..==0 && ..!=0 && ..!=0)
233
	jz @f ;if (..==0 && ..!=0 && ..!=0)
234
		stdcall png_write_cHRM_fixed, edi, [esi+png_info_def.colorspace.end_points_xy]
234
		stdcall png_write_cHRM_fixed, edi, [esi+png_info_def.colorspace.end_points_xy]
235
	@@:
235
	@@:
236
end if
236
end if
237
end if
237
end if
238
 
238
 
239
if PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED eq 1
239
if PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED eq 1
240
		stdcall write_unknown_chunks, edi, esi, PNG_HAVE_IHDR
240
		stdcall write_unknown_chunks, edi, esi, PNG_HAVE_IHDR
241
end if
241
end if
242
		or dword[edi+png_struct.mode],PNG_WROTE_INFO_BEFORE_PLTE
242
		or dword[edi+png_struct.mode],PNG_WROTE_INFO_BEFORE_PLTE
243
	.end_f:
243
	.end_f:
244
popad
244
popad
245
	ret
245
	ret
246
endp
246
endp
247
 
247
 
248
;void (png_structrp png_ptr, png_const_inforp info_ptr)
248
;void (png_structrp png_ptr, png_const_inforp info_ptr)
249
align 4
249
align 4
250
proc png_write_info, png_ptr:dword, info_ptr:dword
250
proc png_write_info, png_ptr:dword, info_ptr:dword
251
if (PNG_WRITE_TEXT_SUPPORTED eq 1) | (PNG_WRITE_sPLT_SUPPORTED eq 1)
251
if (PNG_WRITE_TEXT_SUPPORTED eq 1) | (PNG_WRITE_sPLT_SUPPORTED eq 1)
252
;   int i;
252
;   int i;
253
end if
253
end if
254
pushad
254
pushad
255
	png_debug 1, 'in png_write_info'
255
	png_debug 1, 'in png_write_info'
256
 
256
 
257
	mov edi,[png_ptr]
257
	mov edi,[png_ptr]
258
	cmp edi,0
258
	cmp edi,0
259
	je .end_f
259
	je .end_f
260
	mov esi,[info_ptr]
260
	mov esi,[info_ptr]
261
	cmp esi,0
261
	cmp esi,0
262
	je .end_f ;if (..==0 || ..==0) return
262
	je .end_f ;if (..==0 || ..==0) return
263
 
263
 
264
	stdcall png_write_info_before_PLTE, edi, esi
264
	stdcall png_write_info_before_PLTE, edi, esi
265
 
265
 
266
	mov eax,[esi+png_info_def.valid]
266
	mov eax,[esi+png_info_def.valid]
267
	and eax,PNG_INFO_PLTE
267
	and eax,PNG_INFO_PLTE
268
	jz @f ;if (..!=0)
268
	jz @f ;if (..!=0)
269
		movzx eax,word[esi+png_info_def.num_palette]
269
		movzx eax,word[esi+png_info_def.num_palette]
270
		stdcall png_write_PLTE, edi, [esi+png_info_def.palette], eax
270
		stdcall png_write_PLTE, edi, [esi+png_info_def.palette], eax
271
		jmp .end_0
271
		jmp .end_0
272
	@@:
272
	@@:
273
	mov al,byte[esi+png_info_def.color_type]
273
	mov al,byte[esi+png_info_def.color_type]
274
	cmp al,PNG_COLOR_TYPE_PALETTE
274
	cmp al,PNG_COLOR_TYPE_PALETTE
275
	jne .end_0 ;else if (..==..)
275
	jne .end_0 ;else if (..==..)
276
		png_error edi, 'Valid palette required for paletted images'
276
		png_error edi, 'Valid palette required for paletted images'
277
	.end_0:
277
	.end_0:
278
 
278
 
279
if PNG_WRITE_tRNS_SUPPORTED eq 1
279
if PNG_WRITE_tRNS_SUPPORTED eq 1
280
	mov eax,[esi+png_info_def.valid]
280
	mov eax,[esi+png_info_def.valid]
281
	and eax,PNG_INFO_tRNS
281
	and eax,PNG_INFO_tRNS
282
	jz .end_1 ;if (..!=0)
282
	jz .end_1 ;if (..!=0)
283
if PNG_WRITE_INVERT_ALPHA_SUPPORTED eq 1
283
if PNG_WRITE_INVERT_ALPHA_SUPPORTED eq 1
284
	; Invert the alpha channel (in tRNS)
284
	; Invert the alpha channel (in tRNS)
285
;      if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0 &&
285
;      if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0 &&
286
;          info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
286
;          info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
287
;      {
287
;      {
288
;         int j, jend;
288
;         int j, jend;
289
 
289
 
290
;         jend = info_ptr->num_trans;
290
;         jend = info_ptr->num_trans;
291
;         if (jend > PNG_MAX_PALETTE_LENGTH)
291
;         if (jend > PNG_MAX_PALETTE_LENGTH)
292
;            jend = PNG_MAX_PALETTE_LENGTH;
292
;            jend = PNG_MAX_PALETTE_LENGTH;
293
 
293
 
294
;         for (j = 0; j
294
;         for (j = 0; j
295
;            info_ptr->trans_alpha[j] =
295
;            info_ptr->trans_alpha[j] =
296
;               (byte)(255 - info_ptr->trans_alpha[j]);
296
;               (byte)(255 - info_ptr->trans_alpha[j]);
297
;      }
297
;      }
298
end if
298
end if
299
		mov eax,esi
299
		mov eax,esi
300
		add eax,png_info_def.trans_color
300
		add eax,png_info_def.trans_color
301
		movzx ebx,word[esi+png_info_def.num_trans]
301
		movzx ebx,word[esi+png_info_def.num_trans]
302
		movzx ecx,byte[esi+png_info_def.color_type]
302
		movzx ecx,byte[esi+png_info_def.color_type]
303
		stdcall png_write_tRNS, edi, dword[esi+png_info_def.trans_alpha], eax, ebx, ecx
303
		stdcall png_write_tRNS, edi, dword[esi+png_info_def.trans_alpha], eax, ebx, ecx
304
	.end_1:
304
	.end_1:
305
end if
305
end if
306
if PNG_WRITE_bKGD_SUPPORTED eq 1
306
if PNG_WRITE_bKGD_SUPPORTED eq 1
307
	mov eax,[esi+png_info_def.valid]
307
	mov eax,[esi+png_info_def.valid]
308
	and eax,PNG_INFO_bKGD
308
	and eax,PNG_INFO_bKGD
309
	jz @f ;if (..!=0)
309
	jz @f ;if (..!=0)
310
		mov eax,esi
310
		mov eax,esi
311
		add eax,png_info_def.background
311
		add eax,png_info_def.background
312
		movzx ebx,byte[esi+png_info_def.color_type]
312
		movzx ebx,byte[esi+png_info_def.color_type]
313
		stdcall png_write_bKGD, edi, eax, ebx
313
		stdcall png_write_bKGD, edi, eax, ebx
314
	@@:
314
	@@:
315
end if
315
end if
316
 
316
 
317
if PNG_WRITE_hIST_SUPPORTED eq 1
317
if PNG_WRITE_hIST_SUPPORTED eq 1
318
	mov eax,[esi+png_info_def.valid]
318
	mov eax,[esi+png_info_def.valid]
319
	and eax,PNG_INFO_hIST
319
	and eax,PNG_INFO_hIST
320
	jz @f ;if (..!=0)
320
	jz @f ;if (..!=0)
321
		movzx ebx,word[esi+png_info_def.num_palette]
321
		movzx ebx,word[esi+png_info_def.num_palette]
322
		stdcall png_write_hIST, edi, [esi+png_info_def.hist], ebx
322
		stdcall png_write_hIST, edi, [esi+png_info_def.hist], ebx
323
	@@:
323
	@@:
324
end if
324
end if
325
 
325
 
326
if PNG_WRITE_oFFs_SUPPORTED eq 1
326
if PNG_WRITE_oFFs_SUPPORTED eq 1
327
	mov eax,[esi+png_info_def.valid]
327
	mov eax,[esi+png_info_def.valid]
328
	and eax,PNG_INFO_oFFs
328
	and eax,PNG_INFO_oFFs
329
	jz @f ;if (..!=0)
329
	jz @f ;if (..!=0)
330
		movzx ebx,byte[esi+png_info_def.offset_unit_type]
330
		movzx ebx,byte[esi+png_info_def.offset_unit_type]
331
		stdcall png_write_oFFs, edi, [esi+png_info_def.x_offset], [esi+png_info_def.y_offset], ebx
331
		stdcall png_write_oFFs, edi, [esi+png_info_def.x_offset], [esi+png_info_def.y_offset], ebx
332
	@@:
332
	@@:
333
end if
333
end if
334
 
334
 
335
if PNG_WRITE_pCAL_SUPPORTED eq 1
335
if PNG_WRITE_pCAL_SUPPORTED eq 1
336
	mov eax,[esi+png_info_def.valid]
336
	mov eax,[esi+png_info_def.valid]
337
	and eax,PNG_INFO_pCAL
337
	and eax,PNG_INFO_pCAL
338
	jz @f ;if (..!=0)
338
	jz @f ;if (..!=0)
339
		movzx ebx,byte[esi+png_info_def.pcal_type]
339
		movzx ebx,byte[esi+png_info_def.pcal_type]
340
		movzx ecx,byte[esi+png_info_def.pcal_nparams]
340
		movzx ecx,byte[esi+png_info_def.pcal_nparams]
341
		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]
341
		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]
342
	@@:
342
	@@:
343
end if
343
end if
344
 
344
 
345
if PNG_WRITE_sCAL_SUPPORTED eq 1
345
if PNG_WRITE_sCAL_SUPPORTED eq 1
346
	mov eax,[esi+png_info_def.valid]
346
	mov eax,[esi+png_info_def.valid]
347
	and eax,PNG_INFO_sCAL
347
	and eax,PNG_INFO_sCAL
348
	jz @f ;if (..!=0)
348
	jz @f ;if (..!=0)
349
		movzx ebx,byte[esi+png_info_def.scal_unit]
349
		movzx ebx,byte[esi+png_info_def.scal_unit]
350
		stdcall png_write_sCAL_s, edi, ebx, [esi+png_info_def.scal_s_width], [esi+png_info_def.scal_s_height]
350
		stdcall png_write_sCAL_s, edi, ebx, [esi+png_info_def.scal_s_width], [esi+png_info_def.scal_s_height]
351
	@@:
351
	@@:
352
end if ;sCAL
352
end if ;sCAL
353
 
353
 
354
if PNG_WRITE_pHYs_SUPPORTED eq 1
354
if PNG_WRITE_pHYs_SUPPORTED eq 1
355
	mov eax,[esi+png_info_def.valid]
355
	mov eax,[esi+png_info_def.valid]
356
	and eax,PNG_INFO_pHYs
356
	and eax,PNG_INFO_pHYs
357
	jz @f ;if (..!=0)
357
	jz @f ;if (..!=0)
358
		movzx ebx,byte[esi+png_info_def.phys_unit_type]
358
		movzx ebx,byte[esi+png_info_def.phys_unit_type]
359
		stdcall png_write_pHYs, edi, [esi+png_info_def.x_pixels_per_unit], [esi+png_info_def.y_pixels_per_unit], ebx
359
		stdcall png_write_pHYs, edi, [esi+png_info_def.x_pixels_per_unit], [esi+png_info_def.y_pixels_per_unit], ebx
360
	@@:
360
	@@:
361
end if ;pHYs
361
end if ;pHYs
362
 
362
 
363
if PNG_WRITE_tIME_SUPPORTED eq 1
363
if PNG_WRITE_tIME_SUPPORTED eq 1
364
	mov eax,[esi+png_info_def.valid]
364
	mov eax,[esi+png_info_def.valid]
365
	and eax,PNG_INFO_tIME
365
	and eax,PNG_INFO_tIME
366
	jz @f ;if (..!=0)
366
	jz @f ;if (..!=0)
367
		mov eax,esi
367
		mov eax,esi
368
		add eax,png_info_def.mod_time
368
		add eax,png_info_def.mod_time
369
		stdcall png_write_tIME, edi, eax
369
		stdcall png_write_tIME, edi, eax
370
		or [edi+png_struct.mode],PNG_WROTE_tIME
370
		or [edi+png_struct.mode],PNG_WROTE_tIME
371
	@@:
371
	@@:
372
end if ;tIME
372
end if ;tIME
373
 
373
 
374
if PNG_WRITE_sPLT_SUPPORTED eq 1
374
if PNG_WRITE_sPLT_SUPPORTED eq 1
375
	mov eax,[esi+png_info_def.valid]
375
	mov eax,[esi+png_info_def.valid]
376
	and eax,PNG_INFO_sPLT
376
	and eax,PNG_INFO_sPLT
377
	jz @f ;if (..!=0)
377
	jz @f ;if (..!=0)
378
		mov eax,[esi+png_info_def.splt_palettes]
378
		mov eax,[esi+png_info_def.splt_palettes]
379
		mov ecx,[esi+png_info_def.splt_palettes_num]
379
		mov ecx,[esi+png_info_def.splt_palettes_num]
380
		cmp ecx,1
380
		cmp ecx,1
381
		jl @f
381
		jl @f
382
		.cycle0:
382
		.cycle0:
383
			stdcall png_write_sPLT, edi, eax
383
			stdcall png_write_sPLT, edi, eax
384
			add eax,4
384
			add eax,4
385
			loop .cycle0
385
			loop .cycle0
386
	@@:
386
	@@:
387
end if ;sPLT
387
end if ;sPLT
388
 
388
 
389
if PNG_WRITE_TEXT_SUPPORTED eq 1
389
if PNG_WRITE_TEXT_SUPPORTED eq 1
390
	; Check to see if we need to write text chunks
390
	; Check to see if we need to write text chunks
391
;   for (i = 0; i < info_ptr->num_text; i++)
391
;   for (i = 0; i < info_ptr->num_text; i++)
392
;   {
392
;   {
393
;      png_debug2(2, "Writing header text chunk %d, type %d", i,
393
;      png_debug2(2, "Writing header text chunk %d, type %d", i,
394
;          info_ptr->text[i].compression);
394
;          info_ptr->text[i].compression);
395
	; An internationalized chunk?
395
	; An internationalized chunk?
396
;      if (info_ptr->text[i].compression > 0)
396
;      if (info_ptr->text[i].compression > 0)
397
;      {
397
;      {
398
if PNG_WRITE_iTXt_SUPPORTED eq 1
398
if PNG_WRITE_iTXt_SUPPORTED eq 1
399
	; Write international chunk
399
	; Write international chunk
400
;         png_write_iTXt(png_ptr,
400
;         png_write_iTXt(png_ptr,
401
;             info_ptr->text[i].compression,
401
;             info_ptr->text[i].compression,
402
;             info_ptr->text[i].key,
402
;             info_ptr->text[i].key,
403
;             info_ptr->text[i].lang,
403
;             info_ptr->text[i].lang,
404
;             info_ptr->text[i].lang_key,
404
;             info_ptr->text[i].lang_key,
405
;             info_ptr->text[i].text);
405
;             info_ptr->text[i].text);
406
	; Mark this chunk as written
406
	; Mark this chunk as written
407
;         if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
407
;         if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
408
;            info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
408
;            info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
409
;         else
409
;         else
410
;            info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
410
;            info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
411
else
411
else
412
	png_warning edi, 'Unable to write international text'
412
	png_warning edi, 'Unable to write international text'
413
end if
413
end if
414
;      }
414
;      }
415
 
415
 
416
	; If we want a compressed text chunk
416
	; If we want a compressed text chunk
417
;      else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt)
417
;      else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt)
418
;      {
418
;      {
419
if PNG_WRITE_zTXt_SUPPORTED eq 1
419
if PNG_WRITE_zTXt_SUPPORTED eq 1
420
	; Write compressed chunk
420
	; Write compressed chunk
421
;         png_write_zTXt(png_ptr, info_ptr->text[i].key,
421
;         png_write_zTXt(png_ptr, info_ptr->text[i].key,
422
;             info_ptr->text[i].text, info_ptr->text[i].compression);
422
;             info_ptr->text[i].text, info_ptr->text[i].compression);
423
	; Mark this chunk as written
423
	; Mark this chunk as written
424
;         info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
424
;         info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
425
else
425
else
426
	png_warning edi, 'Unable to write compressed text'
426
	png_warning edi, 'Unable to write compressed text'
427
end if
427
end if
428
;      }
428
;      }
429
 
429
 
430
;      else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
430
;      else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
431
;      {
431
;      {
432
if PNG_WRITE_tEXt_SUPPORTED eq 1
432
if PNG_WRITE_tEXt_SUPPORTED eq 1
433
	; Write uncompressed chunk
433
	; Write uncompressed chunk
434
;         png_write_tEXt(png_ptr, info_ptr->text[i].key,
434
;         png_write_tEXt(png_ptr, info_ptr->text[i].key,
435
;             info_ptr->text[i].text,
435
;             info_ptr->text[i].text,
436
;             0);
436
;             0);
437
	; Mark this chunk as written
437
	; Mark this chunk as written
438
;         info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
438
;         info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
439
else
439
else
440
	; Can't get here
440
	; Can't get here
441
	png_warning edi, 'Unable to write uncompressed text'
441
	png_warning edi, 'Unable to write uncompressed text'
442
end if
442
end if
443
;      }
443
;      }
444
;   }
444
;   }
445
end if ;tEXt
445
end if ;tEXt
446
 
446
 
447
if PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED eq 1
447
if PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED eq 1
448
	stdcall write_unknown_chunks, edi, esi, PNG_HAVE_PLTE
448
	stdcall write_unknown_chunks, edi, esi, PNG_HAVE_PLTE
449
end if
449
end if
450
	.end_f:
450
	.end_f:
451
popad
451
popad
452
	ret
452
	ret
453
endp
453
endp
454
 
454
 
455
; Writes the end of the PNG file.  If you don't want to write comments or
455
; Writes the end of the PNG file.  If you don't want to write comments or
456
; time information, you can pass NULL for info.  If you already wrote these
456
; time information, you can pass NULL for info.  If you already wrote these
457
; in png_write_info(), do not write them again here.  If you have long
457
; in png_write_info(), do not write them again here.  If you have long
458
; comments, I suggest writing them here, and compressing them.
458
; comments, I suggest writing them here, and compressing them.
459
 
459
 
460
;void (png_structrp png_ptr, png_inforp info_ptr)
460
;void (png_structrp png_ptr, png_inforp info_ptr)
461
align 4
461
align 4
462
proc png_write_end, png_ptr:dword, info_ptr:dword
462
proc png_write_end, png_ptr:dword, info_ptr:dword
463
pushad
463
pushad
464
	png_debug 1, 'in png_write_end'
464
	png_debug 1, 'in png_write_end'
465
 
465
 
466
	mov edi,[png_ptr]
466
	mov edi,[png_ptr]
467
	cmp edi,0
467
	cmp edi,0
468
	je .end_f ;if (..==0) return
468
	je .end_f ;if (..==0) return
469
 
469
 
470
	mov eax,[edi+png_struct.mode]
470
	mov eax,[edi+png_struct.mode]
471
	and eax,PNG_HAVE_IDAT
471
	and eax,PNG_HAVE_IDAT
472
	jnz @f ;if (..==0)
472
	jnz @f ;if (..==0)
473
		png_error edi, 'No IDATs written into file'
473
		png_error edi, 'No IDATs written into file'
474
	@@:
474
	@@:
475
 
475
 
476
if PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED eq 1
476
if PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED eq 1
477
	mov eax,[edi+png_struct.num_palette_max]
477
	mov eax,[edi+png_struct.num_palette_max]
478
	cmp ax,[edi+png_struct.num_palette]
478
	cmp ax,[edi+png_struct.num_palette]
479
	jle @f ;if (..>..)
479
	jle @f ;if (..>..)
480
		png_benign_error edi, 'Wrote palette index exceeding num_palette'
480
		png_benign_error edi, 'Wrote palette index exceeding num_palette'
481
	@@:
481
	@@:
482
end if
482
end if
483
 
483
 
484
	; See if user wants us to write information chunks
484
	; See if user wants us to write information chunks
485
	mov esi,[info_ptr]
485
	mov esi,[info_ptr]
486
	cmp esi,0 
486
	cmp esi,0 
487
	je .end0 ;if (..!=0)
487
	je .end0 ;if (..!=0)
488
if PNG_WRITE_TEXT_SUPPORTED eq 1
488
if PNG_WRITE_TEXT_SUPPORTED eq 1
489
;      int i; /* local index variable */
489
;      int i; /* local index variable */
490
end if
490
end if
491
if PNG_WRITE_tIME_SUPPORTED eq 1
491
if PNG_WRITE_tIME_SUPPORTED eq 1
492
		; Check to see if user has supplied a time chunk
492
		; Check to see if user has supplied a time chunk
493
		mov eax,[esi+png_info_def.valid]
493
		mov eax,[esi+png_info_def.valid]
494
		and eax,PNG_INFO_tIME
494
		and eax,PNG_INFO_tIME
495
		jz @f
495
		jz @f
496
		mov eax,[edi+png_struct.mode]
496
		mov eax,[edi+png_struct.mode]
497
		and eax,PNG_WROTE_tIME
497
		and eax,PNG_WROTE_tIME
498
		jnz @f ;if (..!=0 && ..==0)
498
		jnz @f ;if (..!=0 && ..==0)
499
			mov eax,esi
499
			mov eax,esi
500
			add eax,png_info_def.mod_time
500
			add eax,png_info_def.mod_time
501
			stdcall png_write_tIME, edi, eax
501
			stdcall png_write_tIME, edi, eax
502
		@@:
502
		@@:
503
 
503
 
504
end if
504
end if
505
if PNG_WRITE_TEXT_SUPPORTED eq 1
505
if PNG_WRITE_TEXT_SUPPORTED eq 1
506
		; Loop through comment chunks
506
		; Loop through comment chunks
507
		cmp dword[esi+png_info_def.num_text],0
507
		cmp dword[esi+png_info_def.num_text],0
508
		jle .cycle0end
508
		jle .cycle0end
509
		xor ecx,ecx
509
		xor ecx,ecx
510
align 4
510
align 4
511
		.cycle0: ;for (i = 0; i < info_ptr->num_text; i++)
511
		.cycle0: ;for (i = 0; i < info_ptr->num_text; i++)
512
 
512
 
513
;         png_debug2(2, "Writing trailer text chunk %d, type %d", i,
513
;         png_debug2(2, "Writing trailer text chunk %d, type %d", i,
514
;             info_ptr->text[i].compression);
514
;             info_ptr->text[i].compression);
515
			; An internationalized chunk?
515
			; An internationalized chunk?
516
			mov eax,ecx
516
			mov eax,ecx
517
			shl eax,2
517
			shl eax,2
518
			add eax,[esi+png_info_def.text] ;eax = info_ptr.text[i]
518
			add eax,[esi+png_info_def.text] ;eax = info_ptr.text[i]
519
			cmp dword[eax+png_text.compression],0
519
			cmp dword[eax+png_text.compression],0
520
			jle .end1 ;if (info_ptr.text[i].compression > 0)
520
			jle .end1 ;if (info_ptr.text[i].compression > 0)
521
if PNG_WRITE_iTXt_SUPPORTED eq 1
521
if PNG_WRITE_iTXt_SUPPORTED eq 1
522
				; Write international chunk
522
				; Write international chunk
523
				stdcall png_write_iTXt, edi,\
523
				stdcall png_write_iTXt, edi,\
524
					[eax+png_text.compression],\
524
					[eax+png_text.compression],\
525
					[eax+png_text.key],\
525
					[eax+png_text.key],\
526
					[eax+png_text.lang],\
526
					[eax+png_text.lang],\
527
					[eax+png_text.lang_key],\
527
					[eax+png_text.lang_key],\
528
					[eax+png_text.text]
528
					[eax+png_text.text]
529
				; Mark this chunk as written
529
				; Mark this chunk as written
530
				mov ebx,PNG_TEXT_COMPRESSION_zTXt_WR
530
				mov ebx,PNG_TEXT_COMPRESSION_zTXt_WR
531
				cmp dword[eax+png_text.compression],PNG_TEXT_COMPRESSION_NONE
531
				cmp dword[eax+png_text.compression],PNG_TEXT_COMPRESSION_NONE
532
				jne @f
532
				jne @f
533
					mov ebx,PNG_TEXT_COMPRESSION_NONE_WR
533
					mov ebx,PNG_TEXT_COMPRESSION_NONE_WR
534
				@@:
534
				@@:
535
				mov dword[eax+png_text.compression],ebx
535
				mov dword[eax+png_text.compression],ebx
536
else
536
else
537
				png_warning edi, 'Unable to write international text'
537
				png_warning edi, 'Unable to write international text'
538
end if
538
end if
539
				jmp .end3
539
				jmp .end3
540
			.end1:
540
			.end1:
541
			cmp dword[eax+png_text.compression],PNG_TEXT_COMPRESSION_zTXt
541
			cmp dword[eax+png_text.compression],PNG_TEXT_COMPRESSION_zTXt
542
			jl .end2 ;else if (info_ptr.text[i].compression >= ..)
542
			jl .end2 ;else if (info_ptr.text[i].compression >= ..)
543
if PNG_WRITE_zTXt_SUPPORTED eq 1
543
if PNG_WRITE_zTXt_SUPPORTED eq 1
544
				; Write compressed chunk
544
				; Write compressed chunk
545
				stdcall png_write_zTXt, edi, [eax+png_text.key],\
545
				stdcall png_write_zTXt, edi, [eax+png_text.key],\
546
					[eax+png_text.text], [eax+png_text.compression]
546
					[eax+png_text.text], [eax+png_text.compression]
547
				; Mark this chunk as written
547
				; Mark this chunk as written
548
				mov dword[eax+png_text.compression],PNG_TEXT_COMPRESSION_zTXt_WR
548
				mov dword[eax+png_text.compression],PNG_TEXT_COMPRESSION_zTXt_WR
549
else
549
else
550
				png_warning edi, 'Unable to write compressed text'
550
				png_warning edi, 'Unable to write compressed text'
551
end if
551
end if
552
				jmp .end3
552
				jmp .end3
553
			.end2:
553
			.end2:
554
			cmp dword[eax+png_text.compression],PNG_TEXT_COMPRESSION_NONE
554
			cmp dword[eax+png_text.compression],PNG_TEXT_COMPRESSION_NONE
555
			jl .end3 ;else if (info_ptr.text[i].compression == ..)
555
			jl .end3 ;else if (info_ptr.text[i].compression == ..)
556
if PNG_WRITE_tEXt_SUPPORTED eq 1
556
if PNG_WRITE_tEXt_SUPPORTED eq 1
557
				; Write uncompressed chunk
557
				; Write uncompressed chunk
558
				stdcall png_write_tEXt, edi, [eax+png_text.key],\
558
				stdcall png_write_tEXt, edi, [eax+png_text.key],\
559
					[eax+png_text.text], 0
559
					[eax+png_text.text], 0
560
				; Mark this chunk as written
560
				; Mark this chunk as written
561
				mov dword[eax+png_text.compression],PNG_TEXT_COMPRESSION_NONE_WR
561
				mov dword[eax+png_text.compression],PNG_TEXT_COMPRESSION_NONE_WR
562
else
562
else
563
				png_warning edi, 'Unable to write uncompressed text'
563
				png_warning edi, 'Unable to write uncompressed text'
564
end if
564
end if
565
			.end3:
565
			.end3:
566
 
566
 
567
			inc ecx
567
			inc ecx
568
			cmp ecx,[esi+png_info_def.num_text]
568
			cmp ecx,[esi+png_info_def.num_text]
569
			jl .cycle0
569
			jl .cycle0
570
		.cycle0end:
570
		.cycle0end:
571
end if
571
end if
572
if PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED eq 1
572
if PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED eq 1
573
		stdcall write_unknown_chunks, edi, esi, PNG_AFTER_IDAT
573
		stdcall write_unknown_chunks, edi, esi, PNG_AFTER_IDAT
574
end if
574
end if
575
	.end0:
575
	.end0:
576
 
576
 
577
	or dword[edi+png_struct.mode], PNG_AFTER_IDAT
577
	or dword[edi+png_struct.mode], PNG_AFTER_IDAT
578
 
578
 
579
	; Write end of PNG file
579
	; Write end of PNG file
580
	stdcall png_write_IEND, edi
580
	stdcall png_write_IEND, edi
581
 
581
 
582
; This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03,
582
; This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03,
583
; and restored again in libpng-1.2.30, may cause some applications that
583
; and restored again in libpng-1.2.30, may cause some applications that
584
; do not set png_ptr->output_flush_fn to crash.  If your application
584
; do not set png_ptr->output_flush_fn to crash.  If your application
585
; experiences a problem, please try building libpng with
585
; experiences a problem, please try building libpng with
586
; PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED defined, and report the event to
586
; PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED defined, and report the event to
587
; png-mng-implement at lists.sf.net .
587
; png-mng-implement at lists.sf.net .
588
 
588
 
589
if PNG_WRITE_FLUSH_SUPPORTED eq 1
589
if PNG_WRITE_FLUSH_SUPPORTED eq 1
590
if PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED eq 1
590
if PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED eq 1
591
	stdcall png_flush, edi
591
	stdcall png_flush, edi
592
end if
592
end if
593
end if
593
end if
594
.end_f:
594
.end_f:
595
popad
595
popad
596
	ret
596
	ret
597
endp
597
endp
598
 
598
 
599
;void (png_timep ptime, struct tm * ttime)
599
;void (png_timep ptime, struct tm * ttime)
600
align 4
600
align 4
601
proc png_convert_from_struct_tm, ptime:dword, ttime:dword
601
proc png_convert_from_struct_tm, ptime:dword, ttime:dword
602
	png_debug 1, 'in png_convert_from_struct_tm'
602
	png_debug 1, 'in png_convert_from_struct_tm'
603
 
603
 
604
;   ptime->year = (uint_16)(1900 + ttime->tm_year);
604
;   ptime->year = (uint_16)(1900 + ttime->tm_year);
605
;   ptime->month = (byte)(ttime->tm_mon + 1);
605
;   ptime->month = (byte)(ttime->tm_mon + 1);
606
;   ptime->day = (byte)ttime->tm_mday;
606
;   ptime->day = (byte)ttime->tm_mday;
607
;   ptime->hour = (byte)ttime->tm_hour;
607
;   ptime->hour = (byte)ttime->tm_hour;
608
;   ptime->minute = (byte)ttime->tm_min;
608
;   ptime->minute = (byte)ttime->tm_min;
609
;   ptime->second = (byte)ttime->tm_sec;
609
;   ptime->second = (byte)ttime->tm_sec;
610
	ret
610
	ret
611
endp
611
endp
612
 
612
 
613
;void (png_timep ptime, time_t ttime)
613
;void (png_timep ptime, time_t ttime)
614
align 4
614
align 4
615
proc png_convert_from_time_t, ptime:dword, ttime:dword
615
proc png_convert_from_time_t, ptime:dword, ttime:dword
616
;   struct tm *tbuf;
616
;   struct tm *tbuf;
617
 
617
 
618
	png_debug 1, 'in png_convert_from_time_t'
618
	png_debug 1, 'in png_convert_from_time_t'
619
 
619
 
620
;   tbuf = gmtime(&ttime);
620
;   tbuf = gmtime(&ttime);
621
;   png_convert_from_struct_tm(ptime, tbuf);
621
;   png_convert_from_struct_tm(ptime, tbuf);
622
	ret
622
	ret
623
endp
623
endp
624
 
624
 
625
; Initialize png_ptr structure, and allocate any memory needed
625
; Initialize png_ptr structure, and allocate any memory needed
626
;png_structp (charp user_png_ver, voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn)
626
;png_structp (charp user_png_ver, voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn)
627
align 4
627
align 4
628
proc png_create_write_struct, user_png_ver:dword, error_ptr:dword, error_fn:dword, warn_fn:dword
628
proc png_create_write_struct, user_png_ver:dword, error_ptr:dword, error_fn:dword, warn_fn:dword
629
if PNG_USER_MEM_SUPPORTED eq 1
629
if PNG_USER_MEM_SUPPORTED eq 1
630
	stdcall png_create_png_struct, [user_png_ver], [error_ptr], [error_fn], [warn_fn], 0, 0, 0
630
	stdcall png_create_png_struct, [user_png_ver], [error_ptr], [error_fn], [warn_fn], 0, 0, 0
631
	;eax = png_ptr
631
	;eax = png_ptr
632
end if ;USER_MEM
632
end if ;USER_MEM
633
	cmp eax,0
633
	cmp eax,0
634
	je .end0 ;if (..!=0)
634
	je .end0 ;if (..!=0)
635
		; Set the zlib control values to defaults; they can be overridden by the
635
		; Set the zlib control values to defaults; they can be overridden by the
636
		; application after the struct has been created.
636
		; application after the struct has been created.
637
 
637
 
638
		mov dword[eax+png_struct.zbuffer_size], PNG_ZBUF_SIZE
638
		mov dword[eax+png_struct.zbuffer_size], PNG_ZBUF_SIZE
639
 
639
 
640
		; The 'zlib_strategy' setting is irrelevant because png_default_claim in
640
		; The 'zlib_strategy' setting is irrelevant because png_default_claim in
641
		; pngwutil.asm defaults it according to whether or not filters will be
641
		; pngwutil.asm defaults it according to whether or not filters will be
642
		; used, and ignores this setting.
642
		; used, and ignores this setting.
643
 
643
 
644
		mov dword[eax+png_struct.zlib_strategy], PNG_Z_DEFAULT_STRATEGY
644
		mov dword[eax+png_struct.zlib_strategy], PNG_Z_DEFAULT_STRATEGY
645
		mov dword[eax+png_struct.zlib_level], PNG_Z_DEFAULT_COMPRESSION
645
		mov dword[eax+png_struct.zlib_level], PNG_Z_DEFAULT_COMPRESSION
646
		mov dword[eax+png_struct.zlib_mem_level], 8
646
		mov dword[eax+png_struct.zlib_mem_level], 8
647
		mov dword[eax+png_struct.zlib_window_bits], 15
647
		mov dword[eax+png_struct.zlib_window_bits], 15
648
		mov dword[eax+png_struct.zlib_method], 8
648
		mov dword[eax+png_struct.zlib_method], 8
649
 
649
 
650
if PNG_WRITE_COMPRESSED_TEXT_SUPPORTED eq 1
650
if PNG_WRITE_COMPRESSED_TEXT_SUPPORTED eq 1
651
		mov dword[eax+png_struct.zlib_text_strategy], PNG_TEXT_Z_DEFAULT_STRATEGY
651
		mov dword[eax+png_struct.zlib_text_strategy], PNG_TEXT_Z_DEFAULT_STRATEGY
652
		mov dword[eax+png_struct.zlib_text_level], PNG_TEXT_Z_DEFAULT_COMPRESSION
652
		mov dword[eax+png_struct.zlib_text_level], PNG_TEXT_Z_DEFAULT_COMPRESSION
653
		mov dword[eax+png_struct.zlib_text_mem_level], 8
653
		mov dword[eax+png_struct.zlib_text_mem_level], 8
654
		mov dword[eax+png_struct.zlib_text_window_bits], 15
654
		mov dword[eax+png_struct.zlib_text_window_bits], 15
655
		mov dword[eax+png_struct.zlib_text_method], 8
655
		mov dword[eax+png_struct.zlib_text_method], 8
656
end if
656
end if
657
		; This is a highly dubious configuration option; by default it is off,
657
		; This is a highly dubious configuration option; by default it is off,
658
		; but it may be appropriate for private builds that are testing
658
		; but it may be appropriate for private builds that are testing
659
		; extensions not conformant to the current specification, or of
659
		; extensions not conformant to the current specification, or of
660
		; applications that must not fail to write at all costs!
660
		; applications that must not fail to write at all costs!
661
 
661
 
662
if PNG_BENIGN_WRITE_ERRORS_SUPPORTED eq 1
662
if PNG_BENIGN_WRITE_ERRORS_SUPPORTED eq 1
663
		; In stable builds only warn if an application error can be completely
663
		; In stable builds only warn if an application error can be completely
664
		; handled.
664
		; handled.
665
 
665
 
666
		or dword[eax+png_struct.flags], PNG_FLAG_BENIGN_ERRORS_WARN
666
		or dword[eax+png_struct.flags], PNG_FLAG_BENIGN_ERRORS_WARN
667
end if
667
end if
668
		; App warnings are warnings in release (or release candidate) builds but
668
		; App warnings are warnings in release (or release candidate) builds but
669
		; are errors during development.
669
		; are errors during development.
670
 
670
 
671
if PNG_RELEASE_BUILD eq 1
671
if PNG_RELEASE_BUILD eq 1
672
		or dword[eax+png_struct.flags], PNG_FLAG_APP_WARNINGS_WARN
672
		or dword[eax+png_struct.flags], PNG_FLAG_APP_WARNINGS_WARN
673
end if
673
end if
674
		; TODO: delay this, it can be done in png_init_io() (if the app doesn't
674
		; TODO: delay this, it can be done in png_init_io() (if the app doesn't
675
		; do it itself) avoiding setting the default function if it is not
675
		; do it itself) avoiding setting the default function if it is not
676
		; required.
676
		; required.
677
 
677
 
678
		stdcall png_set_write_fn, eax, 0, 0, 0
678
		stdcall png_set_write_fn, eax, 0, 0, 0
679
	.end0:
679
	.end0:
680
	ret
680
	ret
681
endp
681
endp
682
 
682
 
683
 
683
 
684
; Write a few rows of image data.  If the image is interlaced,
684
; Write a few rows of image data.  If the image is interlaced,
685
; either you will have to write the 7 sub images, or, if you
685
; either you will have to write the 7 sub images, or, if you
686
; have called png_set_interlace_handling(), you will have to
686
; have called png_set_interlace_handling(), you will have to
687
; "write" the image seven times.
687
; "write" the image seven times.
688
 
688
 
689
;void (png_structrp png_ptr, bytepp row, uint_32 num_rows)
689
;void (png_structrp png_ptr, bytepp row, uint_32 num_rows)
690
align 4
690
align 4
691
proc png_write_rows uses ebx ecx edi, png_ptr:dword, row:dword, num_rows:dword
691
proc png_write_rows uses ebx ecx edi, png_ptr:dword, row:dword, num_rows:dword
692
;locals
692
;locals
693
	;i dd ? ;uint_32 ;row counter
693
	;i dd ? ;uint_32 ;row counter
694
	;rp dd ? ;bytepp ;row pointer
694
	;rp dd ? ;bytepp ;row pointer
695
;endl
695
;endl
696
	png_debug 1, 'in png_write_rows'
696
	png_debug 1, 'in png_write_rows'
697
 
697
 
698
	mov edi,[png_ptr]
698
	mov edi,[png_ptr]
699
	cmp edi,0
699
	cmp edi,0
700
	je .end_f ;if(..==0) return
700
	je .end_f ;if(..==0) return
701
 
701
 
702
	; Loop through the rows
702
	; Loop through the rows
703
	mov ecx,[num_rows]
703
	mov ecx,[num_rows]
704
	cmp ecx,1
704
	cmp ecx,1
705
	jl .end_f
705
	jl .end_f
706
	mov ebx,[row]
706
	mov ebx,[row]
707
	@@: ;for (i = 0, rp = row; i < num_rows; i++, rp++)
707
	@@: ;for (i = 0, rp = row; i < num_rows; i++, rp++)
708
		stdcall png_write_row, edi, [ebx]
708
		stdcall png_write_row, edi, [ebx]
709
		add ebx,4
709
		add ebx,4
710
		loop @b
710
		loop @b
711
.end_f:
711
.end_f:
712
	ret
712
	ret
713
endp
713
endp
714
 
714
 
715
; Write the image.  You only need to call this function once, even
715
; Write the image.  You only need to call this function once, even
716
; if you are writing an interlaced image.
716
; if you are writing an interlaced image.
717
 
717
 
718
;void (png_structrp png_ptr, bytepp image)
718
;void (png_structrp png_ptr, bytepp image)
719
align 4
719
align 4
720
proc png_write_image, png_ptr:dword, image:dword
720
proc png_write_image, png_ptr:dword, image:dword
721
pushad
721
pushad
722
;ebx ;bytepp ;points to current row
722
;ebx ;bytepp ;points to current row
723
;ecx ;uint_32 ;row index
723
;ecx ;uint_32 ;row index
724
;edx ;int ;pass
724
;edx ;int ;pass
725
;esi ;int ;num_pass
725
;esi ;int ;num_pass
726
	mov edi,[png_ptr]
726
	mov edi,[png_ptr]
727
	cmp edi,0
727
	cmp edi,0
728
	je .end_f ;if (..==0) return
728
	je .end_f ;if (..==0) return
729
 
729
 
730
	png_debug 1, 'in png_write_image'
730
	png_debug 1, 'in png_write_image'
731
 
731
 
732
if PNG_WRITE_INTERLACING_SUPPORTED eq 1
732
if PNG_WRITE_INTERLACING_SUPPORTED eq 1
733
	; Initialize interlace handling.  If image is not interlaced,
733
	; Initialize interlace handling.  If image is not interlaced,
734
	; this will set pass to 1
734
	; this will set pass to 1
735
 
735
 
736
	stdcall png_set_interlace_handling, edi
736
	stdcall png_set_interlace_handling, edi
737
	mov esi,eax
737
	mov esi,eax
738
else
738
else
739
	xor esi,esi
739
	xor esi,esi
740
	inc esi
740
	inc esi
741
end if
741
end if
742
	; Loop through passes
742
	; Loop through passes
743
	xor edx,edx
743
	xor edx,edx
744
	.cycle0: ;for (edx = 0; edx < esi; edx++)
744
	.cycle0: ;for (edx = 0; edx < esi; edx++)
745
		cmp edx,esi
745
		cmp edx,esi
746
		jge .cycle0end
746
		jge .cycle0end
747
		; Loop through image
747
		; Loop through image
748
		mov ebx,[image]
748
		mov ebx,[image]
749
		xor ecx,ecx
749
		xor ecx,ecx
750
		.cycle1: ;for (ecx = 0, ebx = image; ecx < png_ptr.height; ecx++, ebx++)
750
		.cycle1: ;for (ecx = 0, ebx = image; ecx < png_ptr.height; ecx++, ebx++)
751
			stdcall png_write_row, edi,[ebx]
751
			stdcall png_write_row, edi,[ebx]
752
			inc ecx
752
			inc ecx
753
			add ebx,4
753
			add ebx,4
754
			cmp ecx,[edi+png_struct.height]
754
			cmp ecx,[edi+png_struct.height]
755
			jl .cycle1
755
			jl .cycle1
756
		;.cycle1end:
756
		;.cycle1end:
757
		inc edx
757
		inc edx
758
		jmp .cycle0
758
		jmp .cycle0
759
	.cycle0end:
759
	.cycle0end:
760
.end_f:
760
.end_f:
761
popad
761
popad
762
	ret
762
	ret
763
endp
763
endp
764
 
764
 
765
; Performs intrapixel differencing
765
; Performs intrapixel differencing
766
;void (png_row_infop row_info, bytep row)
766
;void (png_row_infop row_info, bytep row)
767
align 4
767
align 4
768
proc png_do_write_intrapixel uses eax ebx ecx edx edi, row_info:dword, row:dword
768
proc png_do_write_intrapixel uses eax ebx ecx edx edi, row_info:dword, row:dword
769
	png_debug 1, 'in png_do_write_intrapixel'
769
	png_debug 1, 'in png_do_write_intrapixel'
770
 
770
 
771
	mov ebx,[row_info]
771
	mov ebx,[row_info]
772
	movzx eax,byte[ebx+png_row_info.color_type]
772
	movzx eax,byte[ebx+png_row_info.color_type]
773
	and eax,PNG_COLOR_MASK_COLOR
773
	and eax,PNG_COLOR_MASK_COLOR
774
	jz .end_f ;if (..!=0)
774
	jz .end_f ;if (..!=0)
775
		;edx = bytes_per_pixel
775
		;edx = bytes_per_pixel
776
		mov ecx,[ebx+png_row_info.width] ;ecx = row_width
776
		mov ecx,[ebx+png_row_info.width] ;ecx = row_width
777
		cmp byte[ebx+png_row_info.bit_depth],8 ;if (..==8)
777
		cmp byte[ebx+png_row_info.bit_depth],8 ;if (..==8)
778
		jne .end0
778
		jne .end0
779
;         bytep rp;
779
;         bytep rp;
780
;         uint_32 i;
780
;         uint_32 i;
781
 
781
 
782
			cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_RGB
782
			cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_RGB
783
			jne @f ;if (..==..)
783
			jne @f ;if (..==..)
784
				mov edx,3-1 ;(-1) for stosb
784
				mov edx,3-1 ;(-1) for stosb
785
				jmp .end2
785
				jmp .end2
786
			@@:
786
			@@:
787
			cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_RGB_ALPHA
787
			cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_RGB_ALPHA
788
			jne @f ;else if (..==..)
788
			jne @f ;else if (..==..)
789
				mov edx,4-1 ;(-1) for stosb
789
				mov edx,4-1 ;(-1) for stosb
790
				jmp .end2
790
				jmp .end2
791
			@@:
791
			@@:
792
				jmp .end_f ;else return
792
				jmp .end_f ;else return
793
			.end2:
793
			.end2:
794
 
794
 
795
			mov edi,[row]
795
			mov edi,[row]
796
align 4
796
align 4
797
			.cycle0: ;for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
797
			.cycle0: ;for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
798
				mov ax,word[edi]
798
				mov ax,word[edi]
799
				sub al,ah
799
				sub al,ah
800
				stosb ;*(rp) = (byte)(*rp - *(rp + 1))
800
				stosb ;*(rp) = (byte)(*rp - *(rp + 1))
801
				mov ax,word[edi]
801
				mov ax,word[edi]
802
				sub ah,al
802
				sub ah,al
803
				mov byte[edi+1],ah ;*(rp + 2) = (byte)(*(rp + 2) - *(rp + 1))
803
				mov byte[edi+1],ah ;*(rp + 2) = (byte)(*(rp + 2) - *(rp + 1))
804
				add edi,edx
804
				add edi,edx
805
				loop .cycle0
805
				loop .cycle0
806
			.cycle0end:
806
			.cycle0end:
807
			jmp .end_f
807
			jmp .end_f
808
		.end0:
808
		.end0:
809
 
809
 
810
if PNG_WRITE_16BIT_SUPPORTED eq 1
810
if PNG_WRITE_16BIT_SUPPORTED eq 1
811
		cmp byte[ebx+png_row_info.bit_depth],16 ;else if (..==16)
811
		cmp byte[ebx+png_row_info.bit_depth],16 ;else if (..==16)
812
		jne .end1
812
		jne .end1
813
;         bytep rp;
813
;         bytep rp;
814
;         uint_32 i;
814
;         uint_32 i;
815
 
815
 
816
			cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_RGB
816
			cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_RGB
817
			jne @f ;if (..==..)
817
			jne @f ;if (..==..)
818
				mov edx,6
818
				mov edx,6
819
				jmp .end3
819
				jmp .end3
820
			@@:
820
			@@:
821
			cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_RGB_ALPHA
821
			cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_RGB_ALPHA
822
			jne @f ;else if (..==..)
822
			jne @f ;else if (..==..)
823
				mov edx,8
823
				mov edx,8
824
				jmp .end3
824
				jmp .end3
825
			@@:
825
			@@:
826
				jmp .end_f ;else return
826
				jmp .end_f ;else return
827
			.end3:
827
			.end3:
828
 
828
 
829
			mov edi,[row]
829
			mov edi,[row]
830
align 4
830
align 4
831
			.cycle1: ;for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
831
			.cycle1: ;for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
832
;            uint_32 s0   = (*(rp    ) << 8) | *(rp + 1);
832
;            uint_32 s0   = (*(rp    ) << 8) | *(rp + 1);
833
;            uint_32 s1   = (*(rp + 2) << 8) | *(rp + 3);
833
;            uint_32 s1   = (*(rp + 2) << 8) | *(rp + 3);
834
;            uint_32 s2   = (*(rp + 4) << 8) | *(rp + 5);
834
;            uint_32 s2   = (*(rp + 4) << 8) | *(rp + 5);
835
;            uint_32 red  = (uint_32)((s0 - s1) & 0xffffL);
835
;            uint_32 red  = (uint_32)((s0 - s1) & 0xffffL);
836
;            uint_32 blue = (uint_32)((s2 - s1) & 0xffffL);
836
;            uint_32 blue = (uint_32)((s2 - s1) & 0xffffL);
837
;            *(rp    ) = (byte)(red >> 8);
837
;            *(rp    ) = (byte)(red >> 8);
838
;            *(rp + 1) = (byte)red;
838
;            *(rp + 1) = (byte)red;
839
;            *(rp + 4) = (byte)(blue >> 8);
839
;            *(rp + 4) = (byte)(blue >> 8);
840
;            *(rp + 5) = (byte)blue;
840
;            *(rp + 5) = (byte)blue;
841
				add edi,edx
841
				add edi,edx
842
				loop .cycle1
842
				loop .cycle1
843
			.cycle1end:
843
			.cycle1end:
844
		.end1:
844
		.end1:
845
end if ;WRITE_16BIT
845
end if ;WRITE_16BIT
846
.end_f:
846
.end_f:
847
	ret
847
	ret
848
endp
848
endp
849
 
849
 
850
; Called by user to write a row of image data
850
; Called by user to write a row of image data
851
;void (png_structrp png_ptr, bytep row)
851
;void (png_structrp png_ptr, bytep row)
852
align 4
852
align 4
853
proc png_write_row, png_ptr:dword, row:dword
853
proc png_write_row, png_ptr:dword, row:dword
854
locals
854
locals
855
	; 1.5.6: moved from png_struct to be a local structure:
855
	; 1.5.6: moved from png_struct to be a local structure:
856
	row_info png_row_info
856
	row_info png_row_info
857
endl
857
endl
858
pushad
858
pushad
859
	mov edi,[png_ptr]
859
	mov edi,[png_ptr]
860
	cmp edi,0
860
	cmp edi,0
861
	je .end_f ;if(..==0) return
861
	je .end_f ;if(..==0) return
862
 
862
 
863
;   png_debug2(1, "in png_write_row (row %u, pass %d)",
863
;   png_debug2(1, "in png_write_row (row %u, pass %d)",
864
;       png_ptr->row_number, png_ptr->pass);
864
;       png_ptr->row_number, png_ptr->pass);
865
png_debug1 1, 'in png_write_row (row %u)',[edi+png_struct.row_number]
865
png_debug1 1, 'in png_write_row (row %u)',[edi+png_struct.row_number]
866
 
866
 
867
	; Initialize transformations and other stuff if first time
867
	; Initialize transformations and other stuff if first time
868
	cmp dword[edi+png_struct.row_number],0
868
	cmp dword[edi+png_struct.row_number],0
869
	jne .end0
869
	jne .end0
870
	cmp byte[edi+png_struct.pass],0
870
	cmp byte[edi+png_struct.pass],0
871
	jne .end0 ;if(..==0 && ..==0)
871
	jne .end0 ;if(..==0 && ..==0)
872
 
872
 
873
	; Make sure we wrote the header info
873
	; Make sure we wrote the header info
874
	mov eax,[edi+png_struct.mode]
874
	mov eax,[edi+png_struct.mode]
875
	and eax,PNG_WROTE_INFO_BEFORE_PLTE
875
	and eax,PNG_WROTE_INFO_BEFORE_PLTE
876
	jnz @f ;if(..==0)
876
	jnz @f ;if(..==0)
877
		png_error edi, 'png_write_info was never called before png_write_row'
877
		png_error edi, 'png_write_info was never called before png_write_row'
878
	@@:
878
	@@:
879
 
879
 
880
	; Check for transforms that have been set but were defined out
880
	; Check for transforms that have been set but were defined out
881
if (PNG_WRITE_INVERT_SUPPORTED eq 0) & (PNG_READ_INVERT_SUPPORTED eq 1)
881
if (PNG_WRITE_INVERT_SUPPORTED eq 0) & (PNG_READ_INVERT_SUPPORTED eq 1)
882
	mov eax,[edi+png_struct.transformations]
882
	mov eax,[edi+png_struct.transformations]
883
	and eax,PNG_INVERT_MONO
883
	and eax,PNG_INVERT_MONO
884
	jz @f ;if(..!=0)
884
	jz @f ;if(..!=0)
885
		png_warning edi, 'PNG_WRITE_INVERT_SUPPORTED is not defined'
885
		png_warning edi, 'PNG_WRITE_INVERT_SUPPORTED is not defined'
886
	@@:
886
	@@:
887
end if
887
end if
888
 
888
 
889
if (PNG_WRITE_FILLER_SUPPORTED eq 0) & (PNG_READ_FILLER_SUPPORTED eq 1)
889
if (PNG_WRITE_FILLER_SUPPORTED eq 0) & (PNG_READ_FILLER_SUPPORTED eq 1)
890
	mov eax,[edi+png_struct.transformations]
890
	mov eax,[edi+png_struct.transformations]
891
	and eax,PNG_FILLER
891
	and eax,PNG_FILLER
892
	jz @f ;if(..!=0)
892
	jz @f ;if(..!=0)
893
		png_warning edi, 'PNG_WRITE_FILLER_SUPPORTED is not defined'
893
		png_warning edi, 'PNG_WRITE_FILLER_SUPPORTED is not defined'
894
	@@:
894
	@@:
895
end if
895
end if
896
 
896
 
897
if (PNG_WRITE_PACKSWAP_SUPPORTED eq 0) & (PNG_READ_PACKSWAP_SUPPORTED eq 1)
897
if (PNG_WRITE_PACKSWAP_SUPPORTED eq 0) & (PNG_READ_PACKSWAP_SUPPORTED eq 1)
898
	mov eax,[edi+png_struct.transformations]
898
	mov eax,[edi+png_struct.transformations]
899
	and eax,PNG_PACKSWAP
899
	and eax,PNG_PACKSWAP
900
	jz @f ;if(..!=0)
900
	jz @f ;if(..!=0)
901
		png_warning edi, 'PNG_WRITE_PACKSWAP_SUPPORTED is not defined'
901
		png_warning edi, 'PNG_WRITE_PACKSWAP_SUPPORTED is not defined'
902
	@@:
902
	@@:
903
end if
903
end if
904
 
904
 
905
if (PNG_WRITE_PACK_SUPPORTED eq 0) & (PNG_READ_PACK_SUPPORTED eq 1)
905
if (PNG_WRITE_PACK_SUPPORTED eq 0) & (PNG_READ_PACK_SUPPORTED eq 1)
906
	mov eax,[edi+png_struct.transformations]
906
	mov eax,[edi+png_struct.transformations]
907
	and eax,PNG_PACK
907
	and eax,PNG_PACK
908
	jz @f ;if(..!=0)
908
	jz @f ;if(..!=0)
909
		png_warning edi, 'PNG_WRITE_PACK_SUPPORTED is not defined'
909
		png_warning edi, 'PNG_WRITE_PACK_SUPPORTED is not defined'
910
	@@:
910
	@@:
911
end if
911
end if
912
 
912
 
913
if (PNG_WRITE_SHIFT_SUPPORTED eq 0) & (PNG_READ_SHIFT_SUPPORTED eq 1)
913
if (PNG_WRITE_SHIFT_SUPPORTED eq 0) & (PNG_READ_SHIFT_SUPPORTED eq 1)
914
	mov eax,[edi+png_struct.transformations]
914
	mov eax,[edi+png_struct.transformations]
915
	and eax,PNG_SHIFT
915
	and eax,PNG_SHIFT
916
	jz @f ;if(..!=0)
916
	jz @f ;if(..!=0)
917
		png_warning edi, 'PNG_WRITE_SHIFT_SUPPORTED is not defined'
917
		png_warning edi, 'PNG_WRITE_SHIFT_SUPPORTED is not defined'
918
	@@:
918
	@@:
919
end if
919
end if
920
 
920
 
921
if (PNG_WRITE_BGR_SUPPORTED eq 0) & (PNG_READ_BGR_SUPPORTED eq 1)
921
if (PNG_WRITE_BGR_SUPPORTED eq 0) & (PNG_READ_BGR_SUPPORTED eq 1)
922
	mov eax,[edi+png_struct.transformations]
922
	mov eax,[edi+png_struct.transformations]
923
	and eax,PNG_BGR
923
	and eax,PNG_BGR
924
	jz @f ;if(..!=0)
924
	jz @f ;if(..!=0)
925
		png_warning edi, 'PNG_WRITE_BGR_SUPPORTED is not defined'
925
		png_warning edi, 'PNG_WRITE_BGR_SUPPORTED is not defined'
926
	@@:
926
	@@:
927
end if
927
end if
928
 
928
 
929
if (PNG_WRITE_SWAP_SUPPORTED eq 0) & (PNG_READ_SWAP_SUPPORTED eq 1)
929
if (PNG_WRITE_SWAP_SUPPORTED eq 0) & (PNG_READ_SWAP_SUPPORTED eq 1)
930
	mov eax,[edi+png_struct.transformations]
930
	mov eax,[edi+png_struct.transformations]
931
	and eax,PNG_SWAP_BYTES
931
	and eax,PNG_SWAP_BYTES
932
	jz @f ;if(..!=0)
932
	jz @f ;if(..!=0)
933
		png_warning edi, 'PNG_WRITE_SWAP_SUPPORTED is not defined'
933
		png_warning edi, 'PNG_WRITE_SWAP_SUPPORTED is not defined'
934
	@@:
934
	@@:
935
end if
935
end if
936
 
936
 
937
	stdcall png_write_start_row, edi
937
	stdcall png_write_start_row, edi
938
	.end0:
938
	.end0:
939
 
939
 
940
if PNG_WRITE_INTERLACING_SUPPORTED eq 1
940
if PNG_WRITE_INTERLACING_SUPPORTED eq 1
941
	; If interlaced and not interested in row, return
941
	; If interlaced and not interested in row, return
942
	cmp byte[edi+png_struct.interlaced],0
942
	cmp byte[edi+png_struct.interlaced],0
943
	je .end1
943
	je .end1
944
	mov eax,[edi+png_struct.transformations]
944
	mov eax,[edi+png_struct.transformations]
945
	and eax,PNG_INTERLACE
945
	and eax,PNG_INTERLACE
946
	jz .end1 ;if(..!=0 && ..!=0)
946
	jz .end1 ;if(..!=0 && ..!=0)
947
		cmp byte[edi+png_struct.pass],0
947
		cmp byte[edi+png_struct.pass],0
948
		jne @f
948
		jne @f
949
			mov eax,[edi+png_struct.row_number]
949
			mov eax,[edi+png_struct.row_number]
950
			and eax,0x07
950
			and eax,0x07
951
			jz .end1 ;if (..!=0)
951
			jz .end1 ;if (..!=0)
952
				stdcall png_write_finish_row, edi
952
				stdcall png_write_finish_row, edi
953
				jmp .end_f
953
				jmp .end_f
954
		@@:
954
		@@:
955
		cmp byte[edi+png_struct.pass],1
955
		cmp byte[edi+png_struct.pass],1
956
		jne @f
956
		jne @f
957
			mov eax,[edi+png_struct.row_number]
957
			mov eax,[edi+png_struct.row_number]
958
			and eax,0x07
958
			and eax,0x07
959
			jnz .end2
959
			jnz .end2
960
			cmp dword[edi+png_struct.width],5
960
			cmp dword[edi+png_struct.width],5
961
			jge .end1 ;if (..!=0 || ..<..)
961
			jge .end1 ;if (..!=0 || ..<..)
962
			.end2:
962
			.end2:
963
				stdcall png_write_finish_row, edi
963
				stdcall png_write_finish_row, edi
964
				jmp .end_f
964
				jmp .end_f
965
		@@:
965
		@@:
966
		cmp byte[edi+png_struct.pass],2
966
		cmp byte[edi+png_struct.pass],2
967
		jne @f
967
		jne @f
968
			mov eax,[edi+png_struct.row_number]
968
			mov eax,[edi+png_struct.row_number]
969
			and eax,0x07
969
			and eax,0x07
970
			cmp eax,4
970
			cmp eax,4
971
			je .end1 ;if (..!=..)
971
			je .end1 ;if (..!=..)
972
				stdcall png_write_finish_row, edi
972
				stdcall png_write_finish_row, edi
973
				jmp .end_f
973
				jmp .end_f
974
		@@:
974
		@@:
975
		cmp byte[edi+png_struct.pass],3
975
		cmp byte[edi+png_struct.pass],3
976
		jne @f
976
		jne @f
977
			mov eax,[edi+png_struct.row_number]
977
			mov eax,[edi+png_struct.row_number]
978
			and eax,0x03
978
			and eax,0x03
979
			jnz .end3
979
			jnz .end3
980
			cmp dword[edi+png_struct.width],3
980
			cmp dword[edi+png_struct.width],3
981
			jge .end1 ;if (..!=0 || ..<..)
981
			jge .end1 ;if (..!=0 || ..<..)
982
			.end3:
982
			.end3:
983
				stdcall png_write_finish_row, edi
983
				stdcall png_write_finish_row, edi
984
				jmp .end_f
984
				jmp .end_f
985
		@@:
985
		@@:
986
		cmp byte[edi+png_struct.pass],4
986
		cmp byte[edi+png_struct.pass],4
987
		jne @f
987
		jne @f
988
			mov eax,[edi+png_struct.row_number]
988
			mov eax,[edi+png_struct.row_number]
989
			and eax,0x03
989
			and eax,0x03
990
			cmp eax,2
990
			cmp eax,2
991
			je .end1 ;if (..!=..)
991
			je .end1 ;if (..!=..)
992
				stdcall png_write_finish_row, edi
992
				stdcall png_write_finish_row, edi
993
				jmp .end_f
993
				jmp .end_f
994
		@@:
994
		@@:
995
		cmp byte[edi+png_struct.pass],5
995
		cmp byte[edi+png_struct.pass],5
996
		jne @f
996
		jne @f
997
			mov eax,[edi+png_struct.row_number]
997
			mov eax,[edi+png_struct.row_number]
998
			and eax,0x01
998
			and eax,0x01
999
			jnz .end4
999
			jnz .end4
1000
			cmp dword[edi+png_struct.width],2
1000
			cmp dword[edi+png_struct.width],2
1001
			jge .end1 ;if (..!=0 || ..<..)
1001
			jge .end1 ;if (..!=0 || ..<..)
1002
			.end4:
1002
			.end4:
1003
				stdcall png_write_finish_row, edi
1003
				stdcall png_write_finish_row, edi
1004
				jmp .end_f
1004
				jmp .end_f
1005
		@@:
1005
		@@:
1006
		cmp byte[edi+png_struct.pass],6
1006
		cmp byte[edi+png_struct.pass],6
1007
		jne .end1
1007
		jne .end1
1008
			mov eax,[edi+png_struct.row_number]
1008
			mov eax,[edi+png_struct.row_number]
1009
			and eax,0x01
1009
			and eax,0x01
1010
			jnz .end1 ;if (..==0)
1010
			jnz .end1 ;if (..==0)
1011
				stdcall png_write_finish_row, edi
1011
				stdcall png_write_finish_row, edi
1012
				jmp .end_f
1012
				jmp .end_f
1013
	.end1:
1013
	.end1:
1014
end if
1014
end if
1015
 
1015
 
1016
	; Set up row info for transformations
1016
	; Set up row info for transformations
1017
	mov ebx,ebp
1017
	mov ebx,ebp
1018
	sub ebx,sizeof.png_row_info
1018
	sub ebx,sizeof.png_row_info
1019
	mov al,byte[edi+png_struct.color_type]
1019
	mov al,byte[edi+png_struct.color_type]
1020
	mov byte[ebx+png_row_info.color_type],al
1020
	mov byte[ebx+png_row_info.color_type],al
1021
	mov eax,[edi+png_struct.usr_width]
1021
	mov eax,[edi+png_struct.usr_width]
1022
	mov [ebx+png_row_info.width],eax
1022
	mov [ebx+png_row_info.width],eax
1023
	movzx eax,byte[edi+png_struct.usr_channels]
1023
	movzx eax,byte[edi+png_struct.usr_channels]
1024
	mov byte[ebx+png_row_info.channels],al
1024
	mov byte[ebx+png_row_info.channels],al
1025
	movzx ecx,byte[edi+png_struct.usr_bit_depth]
1025
	movzx ecx,byte[edi+png_struct.usr_bit_depth]
1026
	mov byte[ebx+png_row_info.bit_depth],cl
1026
	mov byte[ebx+png_row_info.bit_depth],cl
1027
	imul eax,ecx ;.bit_depth * .channels
1027
	imul eax,ecx ;.bit_depth * .channels
1028
	mov byte[ebx+png_row_info.pixel_depth],al
1028
	mov byte[ebx+png_row_info.pixel_depth],al
1029
	PNG_ROWBYTES eax, [ebx+png_row_info.width]
1029
	PNG_ROWBYTES eax, [ebx+png_row_info.width]
1030
	mov [ebx+png_row_info.rowbytes], eax
1030
	mov [ebx+png_row_info.rowbytes], eax
1031
 
1031
 
1032
	push eax
1032
	push eax
1033
	movzx eax,byte[ebx+png_row_info.color_type]
1033
	movzx eax,byte[ebx+png_row_info.color_type]
1034
	png_debug1 3, 'row_info->color_type = %d', eax
1034
	png_debug1 3, 'row_info->color_type = %d', eax
1035
	png_debug1 3, 'row_info->width = %u', [ebx+png_row_info.width]
1035
	png_debug1 3, 'row_info->width = %u', [ebx+png_row_info.width]
1036
	movzx eax,byte[ebx+png_row_info.channels]
1036
	movzx eax,byte[ebx+png_row_info.channels]
1037
	png_debug1 3, 'row_info->channels = %d', eax
1037
	png_debug1 3, 'row_info->channels = %d', eax
1038
	movzx eax,byte[ebx+png_row_info.bit_depth]
1038
	movzx eax,byte[ebx+png_row_info.bit_depth]
1039
	png_debug1 3, 'row_info->bit_depth = %d', eax
1039
	png_debug1 3, 'row_info->bit_depth = %d', eax
1040
	movzx eax,byte[ebx+png_row_info.pixel_depth]
1040
	movzx eax,byte[ebx+png_row_info.pixel_depth]
1041
	png_debug1 3, 'row_info->pixel_depth = %d', eax
1041
	png_debug1 3, 'row_info->pixel_depth = %d', eax
1042
	png_debug1 3, 'row_info->rowbytes = %lu', [ebx+png_row_info.rowbytes]
1042
	png_debug1 3, 'row_info->rowbytes = %lu', [ebx+png_row_info.rowbytes]
1043
	pop eax
1043
	pop eax
1044
 
1044
 
1045
	; Copy user's row into buffer, leaving room for filter byte.
1045
	; Copy user's row into buffer, leaving room for filter byte.
1046
	push edi
1046
	push edi
1047
	mov edi,[edi+png_struct.row_buf]
1047
	mov edi,[edi+png_struct.row_buf]
1048
	inc edi
1048
	inc edi
1049
	mov esi,[row]
1049
	mov esi,[row]
1050
	mov ecx,eax
1050
	mov ecx,eax
1051
	rep movsb ;memcpy(...
1051
	rep movsb ;memcpy(...
1052
	pop edi
1052
	pop edi
1053
 
1053
 
1054
if PNG_WRITE_INTERLACING_SUPPORTED eq 1
1054
if PNG_WRITE_INTERLACING_SUPPORTED eq 1
1055
	; Handle interlacing
1055
	; Handle interlacing
1056
	cmp byte[edi+png_struct.interlaced],0
1056
	cmp byte[edi+png_struct.interlaced],0
1057
	je @f
1057
	je @f
1058
	cmp byte[edi+png_struct.pass],6
1058
	cmp byte[edi+png_struct.pass],6
1059
	jge @f
1059
	jge @f
1060
	mov eax,[edi+png_struct.transformations]
1060
	mov eax,[edi+png_struct.transformations]
1061
	and eax,PNG_INTERLACE
1061
	and eax,PNG_INTERLACE
1062
	jz @f ;if (.. && ..<.. && ..!=0)
1062
	jz @f ;if (.. && ..<.. && ..!=0)
1063
		movzx eax,byte[edi+png_struct.pass]
1063
		movzx eax,byte[edi+png_struct.pass]
1064
		push eax
1064
		push eax
1065
		mov eax,[edi+png_struct.row_buf]
1065
		mov eax,[edi+png_struct.row_buf]
1066
		inc eax
1066
		inc eax
1067
		stdcall png_do_write_interlace, ebx, eax ;, ...pass
1067
		stdcall png_do_write_interlace, ebx, eax ;, ...pass
1068
		; This should always get caught above, but still ...
1068
		; This should always get caught above, but still ...
1069
		cmp dword[ebx+png_row_info.width],0
1069
		cmp dword[ebx+png_row_info.width],0
1070
		jne @f ;if (..==0)
1070
		jne @f ;if (..==0)
1071
			stdcall png_write_finish_row, edi
1071
			stdcall png_write_finish_row, edi
1072
			jmp .end_f
1072
			jmp .end_f
1073
	@@:
1073
	@@:
1074
end if
1074
end if
1075
 
1075
 
1076
if PNG_WRITE_TRANSFORMS_SUPPORTED eq 1
1076
if PNG_WRITE_TRANSFORMS_SUPPORTED eq 1
1077
	; Handle other transformations
1077
	; Handle other transformations
1078
	cmp dword[edi+png_struct.transformations],0
1078
	cmp dword[edi+png_struct.transformations],0
1079
	je @f ;if (..!=0)
1079
	je @f ;if (..!=0)
1080
		stdcall png_do_write_transformations, edi, ebx
1080
		stdcall png_do_write_transformations, edi, ebx
1081
	@@:
1081
	@@:
1082
end if
1082
end if
1083
 
1083
 
1084
	; At this point the row_info pixel depth must match the 'transformed' depth,
1084
	; At this point the row_info pixel depth must match the 'transformed' depth,
1085
	; which is also the output depth.
1085
	; which is also the output depth.
1086
 
1086
 
1087
	mov al,[ebx+png_row_info.pixel_depth]
1087
	mov al,[ebx+png_row_info.pixel_depth]
1088
	cmp al,[edi+png_struct.pixel_depth]
1088
	cmp al,[edi+png_struct.pixel_depth]
1089
	jne @f
1089
	jne @f
1090
	cmp al,[edi+png_struct.transformed_pixel_depth]
1090
	cmp al,[edi+png_struct.transformed_pixel_depth]
1091
	je .end5
1091
	je .end5
1092
	@@: ;if (..!=.. || ..!=..)
1092
	@@: ;if (..!=.. || ..!=..)
1093
		png_error edi, 'internal write transform logic error'
1093
		png_error edi, 'internal write transform logic error'
1094
	.end5:
1094
	.end5:
1095
 
1095
 
1096
if PNG_MNG_FEATURES_SUPPORTED eq 1
1096
if PNG_MNG_FEATURES_SUPPORTED eq 1
1097
	; Write filter_method 64 (intrapixel differencing) only if
1097
	; Write filter_method 64 (intrapixel differencing) only if
1098
	; 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
1098
	; 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
1099
	; 2. Libpng did not write a PNG signature (this filter_method is only
1099
	; 2. Libpng did not write a PNG signature (this filter_method is only
1100
	;    used in PNG datastreams that are embedded in MNG datastreams) and
1100
	;    used in PNG datastreams that are embedded in MNG datastreams) and
1101
	; 3. The application called png_permit_mng_features with a mask that
1101
	; 3. The application called png_permit_mng_features with a mask that
1102
	;    included PNG_FLAG_MNG_FILTER_64 and
1102
	;    included PNG_FLAG_MNG_FILTER_64 and
1103
	; 4. The filter_method is 64 and
1103
	; 4. The filter_method is 64 and
1104
	; 5. The color_type is RGB or RGBA
1104
	; 5. The color_type is RGB or RGBA
1105
 
1105
 
1106
	mov eax,[edi+png_struct.mng_features_permitted]
1106
	mov eax,[edi+png_struct.mng_features_permitted]
1107
	and eax,PNG_FLAG_MNG_FILTER_64
1107
	and eax,PNG_FLAG_MNG_FILTER_64
1108
	jz @f
1108
	jz @f
1109
	cmp byte[edi+png_struct.filter_type],PNG_INTRAPIXEL_DIFFERENCING
1109
	cmp byte[edi+png_struct.filter_type],PNG_INTRAPIXEL_DIFFERENCING
1110
	jne @f ;if (..!=0 && ..==..)
1110
	jne @f ;if (..!=0 && ..==..)
1111
		; Intrapixel differencing
1111
		; Intrapixel differencing
1112
		mov eax,[edi+png_struct.row_buf]
1112
		mov eax,[edi+png_struct.row_buf]
1113
		inc eax
1113
		inc eax
1114
		stdcall png_do_write_intrapixel, ebx, eax
1114
		stdcall png_do_write_intrapixel, ebx, eax
1115
	@@:
1115
	@@:
1116
end if
1116
end if
1117
 
1117
 
1118
; Added at libpng-1.5.10
1118
; Added at libpng-1.5.10
1119
if PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED eq 1
1119
if PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED eq 1
1120
	; Check for out-of-range palette index
1120
	; Check for out-of-range palette index
1121
	cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_PALETTE
1121
	cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_PALETTE
1122
	jne @f
1122
	jne @f
1123
	cmp dword[edi+png_struct.num_palette_max],0
1123
	cmp dword[edi+png_struct.num_palette_max],0
1124
	jl @f ;if (..==.. && ..>=0)
1124
	jl @f ;if (..==.. && ..>=0)
1125
		stdcall png_do_check_palette_indexes, edi, ebx
1125
		stdcall png_do_check_palette_indexes, edi, ebx
1126
	@@:
1126
	@@:
1127
end if
1127
end if
1128
 
1128
 
1129
	; Find a filter if necessary, filter the row and write it out.
1129
	; Find a filter if necessary, filter the row and write it out.
1130
	mov ebx,ebp
1130
	mov ebx,ebp
1131
	sub ebx,sizeof.png_row_info
1131
	sub ebx,sizeof.png_row_info
1132
	stdcall png_write_find_filter, edi, ebx
1132
	stdcall png_write_find_filter, edi, ebx
1133
 
1133
 
1134
	cmp dword[edi+png_struct.write_row_fn],0
1134
	cmp dword[edi+png_struct.write_row_fn],0
1135
	je .end_f ;if (..!=0)
1135
	je .end_f ;if (..!=0)
1136
		movzx eax,byte[edi+png_struct.pass]
1136
		movzx eax,byte[edi+png_struct.pass]
1137
		stdcall dword[edi+png_struct.write_row_fn], edi, [edi+png_struct.row_number], eax
1137
		stdcall dword[edi+png_struct.write_row_fn], edi, [edi+png_struct.row_number], eax
1138
.end_f:
1138
.end_f:
1139
popad
1139
popad
1140
	ret
1140
	ret
1141
endp
1141
endp
1142
 
1142
 
1143
; Set the automatic flush interval or 0 to turn flushing off
1143
; Set the automatic flush interval or 0 to turn flushing off
1144
;void (png_structrp png_ptr, int nrows)
1144
;void (png_structrp png_ptr, int nrows)
1145
align 4
1145
align 4
1146
proc png_set_flush uses eax edi, png_ptr:dword, nrows:dword
1146
proc png_set_flush uses eax edi, png_ptr:dword, nrows:dword
1147
	png_debug 1, 'in png_set_flush'
1147
	png_debug 1, 'in png_set_flush'
1148
 
1148
 
1149
	mov edi,[png_ptr]
1149
	mov edi,[png_ptr]
1150
	cmp edi,0
1150
	cmp edi,0
1151
	je .end_f ;if (..==0) return
1151
	je .end_f ;if (..==0) return
1152
 
1152
 
1153
	mov eax,[nrows]
1153
	mov eax,[nrows]
1154
	cmp eax,0
1154
	cmp eax,0
1155
	jge @f ;(nrows < 0 ? 0 : nrows)
1155
	jge @f ;(nrows < 0 ? 0 : nrows)
1156
		xor eax,eax
1156
		xor eax,eax
1157
	@@: 
1157
	@@: 
1158
	mov [edi+png_struct.flush_dist],eax
1158
	mov [edi+png_struct.flush_dist],eax
1159
.end_f:
1159
.end_f:
1160
	ret
1160
	ret
1161
endp
1161
endp
1162
 
1162
 
1163
; Flush the current output buffers now
1163
; Flush the current output buffers now
1164
;void (png_structrp png_ptr)
1164
;void (png_structrp png_ptr)
1165
align 4
1165
align 4
1166
proc png_write_flush uses eax edi, png_ptr:dword
1166
proc png_write_flush uses eax edi, png_ptr:dword
1167
	png_debug 1, 'in png_write_flush'
1167
	png_debug 1, 'in png_write_flush'
1168
 
1168
 
1169
	mov edi,[png_ptr]
1169
	mov edi,[png_ptr]
1170
	cmp edi,0
1170
	cmp edi,0
1171
	je .end_f ;if (..==0) return
1171
	je .end_f ;if (..==0) return
1172
 
1172
 
1173
	; We have already written out all of the data
1173
	; We have already written out all of the data
1174
	mov eax,[edi+png_struct.num_rows]
1174
	mov eax,[edi+png_struct.num_rows]
1175
	cmp [edi+png_struct.row_number],eax
1175
	cmp [edi+png_struct.row_number],eax
1176
	jge .end_f ;if (..>=..) return
1176
	jge .end_f ;if (..>=..) return
1177
 
1177
 
1178
	stdcall png_compress_IDAT, 0, 0, Z_SYNC_FLUSH
1178
	stdcall png_compress_IDAT, 0, 0, Z_SYNC_FLUSH
1179
	mov dword[edi+png_struct.flush_rows],0
1179
	mov dword[edi+png_struct.flush_rows],0
1180
	stdcall png_flush, edi
1180
	stdcall png_flush, edi
1181
.end_f:
1181
.end_f:
1182
popad
1182
popad
1183
	ret
1183
	ret
1184
endp
1184
endp
1185
 
1185
 
1186
; Free any memory used in png_ptr struct without freeing the struct itself.
1186
; Free any memory used in png_ptr struct without freeing the struct itself.
1187
;void (png_structrp png_ptr)
1187
;void (png_structrp png_ptr)
1188
align 4
1188
align 4
1189
proc png_write_destroy uses eax edi, png_ptr:dword
1189
proc png_write_destroy uses eax edi, png_ptr:dword
1190
	png_debug 1, 'in png_write_destroy'
1190
	png_debug 1, 'in png_write_destroy'
1191
 
1191
 
1192
	; Free any memory zlib uses
1192
	; Free any memory zlib uses
1193
	mov edi,[png_ptr]
1193
	mov edi,[png_ptr]
1194
	mov eax,[edi+png_struct.flags]
1194
	mov eax,[edi+png_struct.flags]
1195
	and eax,PNG_FLAG_ZSTREAM_INITIALIZED
1195
	and eax,PNG_FLAG_ZSTREAM_INITIALIZED
1196
	jz @f ;if (..!=0)
1196
	jz @f ;if (..!=0)
1197
		mov eax,edi
1197
		mov eax,edi
1198
		add eax,png_struct.zstream
1198
		add eax,png_struct.zstream
1199
		stdcall [deflateEnd], eax
1199
		stdcall [deflateEnd], eax
1200
	@@:
1200
	@@:
1201
 
1201
 
1202
	; Free our memory.  png_free checks NULL for us.
1202
	; Free our memory.  png_free checks NULL for us.
1203
	mov eax,edi
1203
	mov eax,edi
1204
	add eax,png_struct.zbuffer_list
1204
	add eax,png_struct.zbuffer_list
1205
	stdcall png_free_buffer_list, edi, eax
1205
	stdcall png_free_buffer_list, edi, eax
1206
	stdcall png_free, edi, [edi+png_struct.row_buf]
1206
	stdcall png_free, edi, [edi+png_struct.row_buf]
1207
	mov dword[edi+png_struct.row_buf],0
1207
	mov dword[edi+png_struct.row_buf],0
1208
if PNG_WRITE_FILTER_SUPPORTED eq 1
1208
if PNG_WRITE_FILTER_SUPPORTED eq 1
1209
	stdcall png_free, edi, [edi+png_struct.prev_row]
1209
	stdcall png_free, edi, [edi+png_struct.prev_row]
1210
	stdcall png_free, edi, [edi+png_struct.try_row]
1210
	stdcall png_free, edi, [edi+png_struct.try_row]
1211
	stdcall png_free, edi, [edi+png_struct.tst_row]
1211
	stdcall png_free, edi, [edi+png_struct.tst_row]
1212
	mov dword[edi+png_struct.prev_row],0
1212
	mov dword[edi+png_struct.prev_row],0
1213
	mov dword[edi+png_struct.try_row],0
1213
	mov dword[edi+png_struct.try_row],0
1214
	mov dword[edi+png_struct.tst_row],0
1214
	mov dword[edi+png_struct.tst_row],0
1215
end if
1215
end if
1216
 
1216
 
1217
if PNG_SET_UNKNOWN_CHUNKS_SUPPORTED eq 1
1217
if PNG_SET_UNKNOWN_CHUNKS_SUPPORTED eq 1
1218
	stdcall png_free, edi, [edi+png_struct.chunk_list]
1218
	stdcall png_free, edi, [edi+png_struct.chunk_list]
1219
	mov dword[edi+png_struct.chunk_list],0
1219
	mov dword[edi+png_struct.chunk_list],0
1220
end if
1220
end if
1221
 
1221
 
1222
	; The error handling and memory handling information is left intact at this
1222
	; The error handling and memory handling information is left intact at this
1223
	; point: the jmp_buf may still have to be freed.  See png_destroy_png_struct
1223
	; point: the jmp_buf may still have to be freed.  See png_destroy_png_struct
1224
	; for how this happens.
1224
	; for how this happens.
1225
	ret
1225
	ret
1226
endp
1226
endp
1227
 
1227
 
1228
; Free all memory used by the write.
1228
; Free all memory used by the write.
1229
; In libpng 1.6.0 this API changed quietly to no longer accept a NULL value for
1229
; In libpng 1.6.0 this API changed quietly to no longer accept a NULL value for
1230
; *png_ptr_ptr.  Prior to 1.6.0 it would accept such a value and it would free
1230
; *png_ptr_ptr.  Prior to 1.6.0 it would accept such a value and it would free
1231
; the passed in info_structs but it would quietly fail to free any of the data
1231
; the passed in info_structs but it would quietly fail to free any of the data
1232
; inside them.  In 1.6.0 it quietly does nothing (it has to be quiet because it
1232
; inside them.  In 1.6.0 it quietly does nothing (it has to be quiet because it
1233
; has no png_ptr.)
1233
; has no png_ptr.)
1234
 
1234
 
1235
;void (png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
1235
;void (png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
1236
align 4
1236
align 4
1237
proc png_destroy_write_struct uses edi esi, png_ptr_ptr:dword, info_ptr_ptr:dword
1237
proc png_destroy_write_struct uses edi esi, png_ptr_ptr:dword, info_ptr_ptr:dword
1238
	png_debug 1, 'in png_destroy_write_struct'
1238
	png_debug 1, 'in png_destroy_write_struct'
1239
 
1239
 
1240
	mov esi,[png_ptr_ptr]
1240
	mov esi,[png_ptr_ptr]
1241
	cmp esi,0
1241
	cmp esi,0
1242
	je @f ;if (..!=0)
1242
	je @f ;if (..!=0)
1243
		mov edi,[esi]
1243
		mov edi,[esi]
1244
 
1244
 
1245
		cmp edi,0
1245
		cmp edi,0
1246
		je @f ;if (..!=0) ;added in libpng 1.6.0
1246
		je @f ;if (..!=0) ;added in libpng 1.6.0
1247
			stdcall png_destroy_info_struct, edi, [info_ptr_ptr]
1247
			stdcall png_destroy_info_struct, edi, [info_ptr_ptr]
1248
 
1248
 
1249
			mov dword[esi],0
1249
			mov dword[esi],0
1250
			stdcall png_write_destroy, edi
1250
			stdcall png_write_destroy, edi
1251
			stdcall png_destroy_png_struct, edi
1251
			stdcall png_destroy_png_struct, edi
1252
	@@:
1252
	@@:
1253
	ret
1253
	ret
1254
endp
1254
endp
1255
 
1255
 
1256
; Allow the application to select one or more row filters to use.
1256
; Allow the application to select one or more row filters to use.
1257
;void (png_structrp png_ptr, int method, int filters)
1257
;void (png_structrp png_ptr, int method, int filters)
1258
align 4
1258
align 4
1259
proc png_set_filter uses eax ebx ecx edi, png_ptr:dword, method:dword, filters:dword
1259
proc png_set_filter uses eax ebx ecx edi, png_ptr:dword, method:dword, filters:dword
1260
	png_debug 1, 'in png_set_filter'
1260
	png_debug 1, 'in png_set_filter'
1261
pushad
1261
pushad
1262
	mov edi,[png_ptr]
1262
	mov edi,[png_ptr]
1263
	cmp edi,0
1263
	cmp edi,0
1264
	je .end_f ;if (..==0) return
1264
	je .end_f ;if (..==0) return
1265
 
1265
 
1266
if PNG_MNG_FEATURES_SUPPORTED eq 1
1266
if PNG_MNG_FEATURES_SUPPORTED eq 1
1267
	mov eax,[edi+png_struct.mng_features_permitted]
1267
	mov eax,[edi+png_struct.mng_features_permitted]
1268
	and eax,PNG_FLAG_MNG_FILTER_64
1268
	and eax,PNG_FLAG_MNG_FILTER_64
1269
	je @f
1269
	je @f
1270
	cmp dword[method], PNG_INTRAPIXEL_DIFFERENCING
1270
	cmp dword[method], PNG_INTRAPIXEL_DIFFERENCING
1271
	jne @f ;if (..!=0 && ..==..)
1271
	jne @f ;if (..!=0 && ..==..)
1272
		mov dword[method], PNG_FILTER_TYPE_BASE
1272
		mov dword[method], PNG_FILTER_TYPE_BASE
1273
	@@:
1273
	@@:
1274
end if
1274
end if
1275
	cmp dword[method], PNG_FILTER_TYPE_BASE
1275
	cmp dword[method], PNG_FILTER_TYPE_BASE
1276
	jne .end0 ;if (..==..)
1276
	jne .end0 ;if (..==..)
1277
	mov ebx,[filters]
1277
	mov ebx,[filters]
1278
	and ebx,PNG_ALL_FILTERS or 0x07 ;switch (..)
1278
	and ebx,PNG_ALL_FILTERS or 0x07 ;switch (..)
1279
 
1279
 
1280
if PNG_WRITE_FILTER_SUPPORTED eq 1
1280
if PNG_WRITE_FILTER_SUPPORTED eq 1
1281
	cmp ebx,5
1281
	cmp ebx,5
1282
	je .end2
1282
	je .end2
1283
	cmp ebx,6
1283
	cmp ebx,6
1284
	je .end2
1284
	je .end2
1285
	cmp ebx,7
1285
	cmp ebx,7
1286
	je .end2
1286
	je .end2
1287
		jmp @f
1287
		jmp @f
1288
	.end2:
1288
	.end2:
1289
		cStr ,'Unknown row filter for method 0'
1289
		cStr ,'Unknown row filter for method 0'
1290
		stdcall png_app_error, edi, eax
1290
		stdcall png_app_error, edi, eax
1291
		; FALL THROUGH
1291
		; FALL THROUGH
1292
	@@:
1292
	@@:
1293
end if ;WRITE_FILTER
1293
end if ;WRITE_FILTER
1294
	cmp ebx,PNG_FILTER_VALUE_NONE
1294
	cmp ebx,PNG_FILTER_VALUE_NONE
1295
	jne @f
1295
	jne @f
1296
		mov byte[edi+png_struct.do_filter],PNG_FILTER_NONE
1296
		mov byte[edi+png_struct.do_filter],PNG_FILTER_NONE
1297
		jmp .end1
1297
		jmp .end1
1298
	@@:
1298
	@@:
1299
if PNG_WRITE_FILTER_SUPPORTED eq 1
1299
if PNG_WRITE_FILTER_SUPPORTED eq 1
1300
	cmp ebx,PNG_FILTER_VALUE_SUB
1300
	cmp ebx,PNG_FILTER_VALUE_SUB
1301
	jne @f
1301
	jne @f
1302
		mov byte[edi+png_struct.do_filter],PNG_FILTER_SUB
1302
		mov byte[edi+png_struct.do_filter],PNG_FILTER_SUB
1303
		jmp .end1
1303
		jmp .end1
1304
	@@:
1304
	@@:
1305
	cmp ebx,PNG_FILTER_VALUE_UP
1305
	cmp ebx,PNG_FILTER_VALUE_UP
1306
	jne @f
1306
	jne @f
1307
		mov byte[edi+png_struct.do_filter],PNG_FILTER_UP
1307
		mov byte[edi+png_struct.do_filter],PNG_FILTER_UP
1308
		jmp .end1
1308
		jmp .end1
1309
	@@:
1309
	@@:
1310
	cmp ebx,PNG_FILTER_VALUE_AVG
1310
	cmp ebx,PNG_FILTER_VALUE_AVG
1311
	jne @f
1311
	jne @f
1312
		mov byte[edi+png_struct.do_filter],PNG_FILTER_AVG
1312
		mov byte[edi+png_struct.do_filter],PNG_FILTER_AVG
1313
		jmp .end1
1313
		jmp .end1
1314
	@@:
1314
	@@:
1315
	cmp ebx,PNG_FILTER_VALUE_PAETH
1315
	cmp ebx,PNG_FILTER_VALUE_PAETH
1316
	jne @f
1316
	jne @f
1317
		mov byte[edi+png_struct.do_filter],PNG_FILTER_PAETH
1317
		mov byte[edi+png_struct.do_filter],PNG_FILTER_PAETH
1318
		jmp .end1
1318
		jmp .end1
1319
	@@: ;default:
1319
	@@: ;default:
1320
		mov eax,[filters]
1320
		mov eax,[filters]
1321
		mov byte[edi+png_struct.do_filter],al
1321
		mov byte[edi+png_struct.do_filter],al
1322
		jmp .end1
1322
		jmp .end1
1323
else
1323
else
1324
	@@: ;default:
1324
	@@: ;default:
1325
		cStr ,'Unknown row filter for method 0'
1325
		cStr ,'Unknown row filter for method 0'
1326
		stdcall png_app_error edi, eax
1326
		stdcall png_app_error edi, eax
1327
end if ;WRITE_FILTER
1327
end if ;WRITE_FILTER
1328
	.end1:
1328
	.end1:
1329
 
1329
 
1330
if PNG_WRITE_FILTER_SUPPORTED eq 1
1330
if PNG_WRITE_FILTER_SUPPORTED eq 1
1331
	; If we have allocated the row_buf, this means we have already started
1331
	; If we have allocated the row_buf, this means we have already started
1332
	; with the image and we should have allocated all of the filter buffers
1332
	; with the image and we should have allocated all of the filter buffers
1333
	; that have been selected.  If prev_row isn't already allocated, then
1333
	; that have been selected.  If prev_row isn't already allocated, then
1334
	; it is too late to start using the filters that need it, since we
1334
	; it is too late to start using the filters that need it, since we
1335
	; will be missing the data in the previous row.  If an application
1335
	; will be missing the data in the previous row.  If an application
1336
	; wants to start and stop using particular filters during compression,
1336
	; wants to start and stop using particular filters during compression,
1337
	; it should start out with all of the filters, and then remove them
1337
	; it should start out with all of the filters, and then remove them
1338
	; or add them back after the start of compression.
1338
	; or add them back after the start of compression.
1339
 
1339
 
1340
		; NOTE: this is a nasty constraint on the code, because it means that the
1340
		; NOTE: this is a nasty constraint on the code, because it means that the
1341
		; prev_row buffer must be maintained even if there are currently no
1341
		; prev_row buffer must be maintained even if there are currently no
1342
		; 'prev_row' requiring filters active.
1342
		; 'prev_row' requiring filters active.
1343
 
1343
 
1344
		cmp dword[edi+png_struct.row_buf],0
1344
		cmp dword[edi+png_struct.row_buf],0
1345
		je .end3 ;if (..!=0)
1345
		je .end3 ;if (..!=0)
1346
			;ebx = num_filters
1346
			;ebx = num_filters
1347
			;ecx = buf_size
1347
			;ecx = buf_size
1348
 
1348
 
1349
			; Repeat the checks in png_write_start_row; 1 pixel high or wide
1349
			; Repeat the checks in png_write_start_row; 1 pixel high or wide
1350
			; images cannot benefit from certain filters.  If this isn't done here
1350
			; images cannot benefit from certain filters.  If this isn't done here
1351
			; the check below will fire on 1 pixel high images.
1351
			; the check below will fire on 1 pixel high images.
1352
 
1352
 
1353
			cmp dword[edi+png_struct.height],1
1353
			cmp dword[edi+png_struct.height],1
1354
			jne @f ;if (..==..)
1354
			jne @f ;if (..==..)
1355
				and dword[filters],not (PNG_FILTER_UP or PNG_FILTER_AVG or PNG_FILTER_PAETH)
1355
				and dword[filters],not (PNG_FILTER_UP or PNG_FILTER_AVG or PNG_FILTER_PAETH)
1356
			@@:
1356
			@@:
1357
			cmp dword[edi+png_struct.width],1
1357
			cmp dword[edi+png_struct.width],1
1358
			jne @f ;if (..==..)
1358
			jne @f ;if (..==..)
1359
				and dword[filters],not (PNG_FILTER_SUB or PNG_FILTER_AVG or PNG_FILTER_PAETH)
1359
				and dword[filters],not (PNG_FILTER_SUB or PNG_FILTER_AVG or PNG_FILTER_PAETH)
1360
			@@:
1360
			@@:
1361
			mov eax,[filters]
1361
			mov eax,[filters]
1362
			and eax,PNG_FILTER_UP or PNG_FILTER_AVG or PNG_FILTER_PAETH
1362
			and eax,PNG_FILTER_UP or PNG_FILTER_AVG or PNG_FILTER_PAETH
1363
			jz @f
1363
			jz @f
1364
			cmp dword[edi+png_struct.prev_row],0
1364
			cmp dword[edi+png_struct.prev_row],0
1365
			je @f;if (..!=0 && ..==0)
1365
			je @f;if (..!=0 && ..==0)
1366
				; This is the error case, however it is benign - the previous row
1366
				; This is the error case, however it is benign - the previous row
1367
				; is not available so the filter can't be used.  Just warn here.
1367
				; is not available so the filter can't be used.  Just warn here.
1368
 
1368
 
1369
				png_app_warning edi, 'png_set_filter: UP/AVG/PAETH cannot be added after start'
1369
				png_app_warning edi, 'png_set_filter: UP/AVG/PAETH cannot be added after start'
1370
				and dword[filters],not (PNG_FILTER_UP or PNG_FILTER_AVG or PNG_FILTER_PAETH)
1370
				and dword[filters],not (PNG_FILTER_UP or PNG_FILTER_AVG or PNG_FILTER_PAETH)
1371
			@@:
1371
			@@:
1372
 
1372
 
1373
			xor ebx,ebx
1373
			xor ebx,ebx
1374
 
1374
 
1375
			mov eax,[filters]
1375
			mov eax,[filters]
1376
			and eax,PNG_FILTER_SUB
1376
			and eax,PNG_FILTER_SUB
1377
			jz @f ;if (..)
1377
			jz @f ;if (..)
1378
				inc ebx
1378
				inc ebx
1379
			@@:
1379
			@@:
1380
			mov eax,[filters]
1380
			mov eax,[filters]
1381
			and eax,PNG_FILTER_UP
1381
			and eax,PNG_FILTER_UP
1382
			jz @f ;if (..)
1382
			jz @f ;if (..)
1383
				inc ebx
1383
				inc ebx
1384
			@@:
1384
			@@:
1385
			mov eax,[filters]
1385
			mov eax,[filters]
1386
			and eax,PNG_FILTER_AVG
1386
			and eax,PNG_FILTER_AVG
1387
			jz @f ;if (..)
1387
			jz @f ;if (..)
1388
				inc ebx
1388
				inc ebx
1389
			@@:
1389
			@@:
1390
			mov eax,[filters]
1390
			mov eax,[filters]
1391
			and eax,PNG_FILTER_PAETH
1391
			and eax,PNG_FILTER_PAETH
1392
			jz @f ;if (..)
1392
			jz @f ;if (..)
1393
				inc ebx
1393
				inc ebx
1394
			@@:
1394
			@@:
1395
			; Allocate needed row buffers if they have not already been
1395
			; Allocate needed row buffers if they have not already been
1396
			; allocated.
1396
			; allocated.
1397
 
1397
 
1398
			movzx eax,byte[edi+png_struct.usr_channels]
1398
			movzx eax,byte[edi+png_struct.usr_channels]
1399
			movzx ecx,byte[edi+png_struct.usr_bit_depth]
1399
			movzx ecx,byte[edi+png_struct.usr_bit_depth]
1400
			imul eax,ecx ;.bit_depth * .channels
1400
			imul eax,ecx ;.bit_depth * .channels
1401
			mov ecx,[edi+png_struct.width]
1401
			mov ecx,[edi+png_struct.width]
1402
			inc ecx
1402
			inc ecx
1403
			PNG_ROWBYTES eax, ecx
1403
			PNG_ROWBYTES eax, ecx
1404
			mov ecx, eax
1404
			mov ecx, eax
1405
 
1405
 
1406
			cmp dword[edi+png_struct.try_row],0
1406
			cmp dword[edi+png_struct.try_row],0
1407
			jne @f ;if (..==0)
1407
			jne @f ;if (..==0)
1408
				stdcall png_malloc, edi, ecx
1408
				stdcall png_malloc, edi, ecx
1409
				mov [edi+png_struct.try_row],eax
1409
				mov [edi+png_struct.try_row],eax
1410
			@@:
1410
			@@:
1411
 
1411
 
1412
			cmp ebx,1
1412
			cmp ebx,1
1413
			jle .end3 ;if (..>..)
1413
			jle .end3 ;if (..>..)
1414
			cmp dword[edi+png_struct.tst_row],0
1414
			cmp dword[edi+png_struct.tst_row],0
1415
			jne .end3 ;if (..==0)
1415
			jne .end3 ;if (..==0)
1416
				stdcall png_malloc, edi, ecx
1416
				stdcall png_malloc, edi, ecx
1417
				mov [edi+png_struct.tst_row],eax
1417
				mov [edi+png_struct.tst_row],eax
1418
		.end3:
1418
		.end3:
1419
		mov eax,[filters]
1419
		mov eax,[filters]
1420
		mov byte[edi+png_struct.do_filter],al
1420
		mov byte[edi+png_struct.do_filter],al
1421
end if
1421
end if
1422
		jmp .end_f
1422
		jmp .end_f
1423
	.end0: ;else
1423
	.end0: ;else
1424
		png_error edi, 'Unknown custom filter method'
1424
		png_error edi, 'Unknown custom filter method'
1425
.end_f:
1425
.end_f:
1426
popad
1426
popad
1427
	ret
1427
	ret
1428
endp
1428
endp
1429
 
1429
 
1430
; Provide floating and fixed point APIs
1430
; Provide floating and fixed point APIs
1431
;void (png_structrp png_ptr, int heuristic_method,
1431
;void (png_structrp png_ptr, int heuristic_method,
1432
;    int num_weights, png_const_doublep filter_weights, png_const_doublep filter_costs)
1432
;    int num_weights, png_const_doublep filter_weights, png_const_doublep filter_costs)
1433
align 4
1433
align 4
1434
proc png_set_filter_heuristics, png_ptr:dword, heuristic_method:dword, num_weights:dword, filter_weights:dword, filter_costs:dword
1434
proc png_set_filter_heuristics, png_ptr:dword, heuristic_method:dword, num_weights:dword, filter_weights:dword, filter_costs:dword
1435
	ret
1435
	ret
1436
endp
1436
endp
1437
 
1437
 
1438
;void (png_structrp png_ptr, int heuristic_method,
1438
;void (png_structrp png_ptr, int heuristic_method,
1439
;    int num_weights, png_const_fixed_point_p filter_weights,
1439
;    int num_weights, png_const_fixed_point_p filter_weights,
1440
;    png_const_fixed_point_p filter_costs)
1440
;    png_const_fixed_point_p filter_costs)
1441
align 4
1441
align 4
1442
proc png_set_filter_heuristics_fixed, png_ptr:dword, heuristic_method:dword, num_weights:dword, filter_weights:dword, filter_costs:dword
1442
proc png_set_filter_heuristics_fixed, png_ptr:dword, heuristic_method:dword, num_weights:dword, filter_weights:dword, filter_costs:dword
1443
	ret
1443
	ret
1444
endp
1444
endp
1445
 
1445
 
1446
;void (png_structrp png_ptr, int level)
1446
;void (png_structrp png_ptr, int level)
1447
align 4
1447
align 4
1448
proc png_set_compression_level uses edi, png_ptr:dword, level:dword
1448
proc png_set_compression_level uses edi, png_ptr:dword, level:dword
1449
	png_debug 1, 'in png_set_compression_level'
1449
	png_debug 1, 'in png_set_compression_level'
1450
 
1450
 
1451
	mov edi,[png_ptr]
1451
	mov edi,[png_ptr]
1452
	cmp edi,0
1452
	cmp edi,0
1453
	je @f ;if (..==0) return
1453
	je @f ;if (..==0) return
1454
 
1454
 
1455
	m2m [edi+png_struct.zlib_level], [level]
1455
	m2m [edi+png_struct.zlib_level], [level]
1456
	@@:
1456
	@@:
1457
	ret
1457
	ret
1458
endp
1458
endp
1459
 
1459
 
1460
;void (png_structrp png_ptr, int mem_level)
1460
;void (png_structrp png_ptr, int mem_level)
1461
align 4
1461
align 4
1462
proc png_set_compression_mem_level uses edi, png_ptr:dword, mem_level:dword
1462
proc png_set_compression_mem_level uses edi, png_ptr:dword, mem_level:dword
1463
	png_debug 1, 'in png_set_compression_mem_level'
1463
	png_debug 1, 'in png_set_compression_mem_level'
1464
 
1464
 
1465
	mov edi,[png_ptr]
1465
	mov edi,[png_ptr]
1466
	cmp edi,0
1466
	cmp edi,0
1467
	je @f ;if (..==0) return
1467
	je @f ;if (..==0) return
1468
 
1468
 
1469
	m2m [edi+png_struct.zlib_mem_level], [mem_level]
1469
	m2m [edi+png_struct.zlib_mem_level], [mem_level]
1470
	@@:
1470
	@@:
1471
	ret
1471
	ret
1472
endp
1472
endp
1473
 
1473
 
1474
;void (png_structrp png_ptr, int strategy)
1474
;void (png_structrp png_ptr, int strategy)
1475
align 4
1475
align 4
1476
proc png_set_compression_strategy uses edi, png_ptr:dword, strategy:dword
1476
proc png_set_compression_strategy uses edi, png_ptr:dword, strategy:dword
1477
	png_debug 1, 'in png_set_compression_strategy'
1477
	png_debug 1, 'in png_set_compression_strategy'
1478
 
1478
 
1479
	mov edi,[png_ptr]
1479
	mov edi,[png_ptr]
1480
	cmp edi,0
1480
	cmp edi,0
1481
	je .end_f ;if (..==0) return
1481
	je .end_f ;if (..==0) return
1482
 
1482
 
1483
	; The flag setting here prevents the libpng dynamic selection of strategy.
1483
	; The flag setting here prevents the libpng dynamic selection of strategy.
1484
 
1484
 
1485
	or dword[edi+png_struct.flags], PNG_FLAG_ZLIB_CUSTOM_STRATEGY
1485
	or dword[edi+png_struct.flags], PNG_FLAG_ZLIB_CUSTOM_STRATEGY
1486
	m2m [edi+png_struct.zlib_strategy], [strategy]
1486
	m2m [edi+png_struct.zlib_strategy], [strategy]
1487
.end_f:
1487
.end_f:
1488
	ret
1488
	ret
1489
endp
1489
endp
1490
 
1490
 
1491
; If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a
1491
; If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a
1492
; smaller value of window_bits if it can do so safely.
1492
; smaller value of window_bits if it can do so safely.
1493
 
1493
 
1494
;void (png_structrp png_ptr, int window_bits)
1494
;void (png_structrp png_ptr, int window_bits)
1495
align 4
1495
align 4
1496
proc png_set_compression_window_bits uses eax edi, png_ptr:dword, window_bits:dword
1496
proc png_set_compression_window_bits uses eax edi, png_ptr:dword, window_bits:dword
1497
	mov edi,[png_ptr]
1497
	mov edi,[png_ptr]
1498
	cmp edi,0
1498
	cmp edi,0
1499
	je .end_f ;if (..==0) return
1499
	je .end_f ;if (..==0) return
1500
 
1500
 
1501
	; Prior to 1.6.0 this would warn but then set the window_bits value. This
1501
	; Prior to 1.6.0 this would warn but then set the window_bits value. This
1502
	; meant that negative window bits values could be selected that would cause
1502
	; meant that negative window bits values could be selected that would cause
1503
	; libpng to write a non-standard PNG file with raw deflate or gzip
1503
	; libpng to write a non-standard PNG file with raw deflate or gzip
1504
	; compressed IDAT or ancillary chunks.  Such files can be read and there is
1504
	; compressed IDAT or ancillary chunks.  Such files can be read and there is
1505
	; no warning on read, so this seems like a very bad idea.
1505
	; no warning on read, so this seems like a very bad idea.
1506
 
1506
 
1507
	mov eax,[window_bits]
1507
	mov eax,[window_bits]
1508
	cmp eax,15
1508
	cmp eax,15
1509
	jle @f ;if (..>..)
1509
	jle @f ;if (..>..)
1510
		png_warning edi, 'Only compression windows <= 32k supported by PNG'
1510
		png_warning edi, 'Only compression windows <= 32k supported by PNG'
1511
		mov eax,15
1511
		mov eax,15
1512
		jmp .end0
1512
		jmp .end0
1513
	@@: ;else if (..<..)
1513
	@@: ;else if (..<..)
1514
	cmp eax,8
1514
	cmp eax,8
1515
	jge @f
1515
	jge @f
1516
		png_warning edi, 'Only compression windows >= 256 supported by PNG'
1516
		png_warning edi, 'Only compression windows >= 256 supported by PNG'
1517
		mov eax,8
1517
		mov eax,8
1518
	.end0:
1518
	.end0:
1519
 
1519
 
1520
	mov [edi+png_struct.zlib_window_bits],eax
1520
	mov [edi+png_struct.zlib_window_bits],eax
1521
.end_f:
1521
.end_f:
1522
	ret
1522
	ret
1523
endp
1523
endp
1524
 
1524
 
1525
;void (png_structrp png_ptr, int method)
1525
;void (png_structrp png_ptr, int method)
1526
align 4
1526
align 4
1527
proc png_set_compression_method uses eax edi, png_ptr:dword, method:dword
1527
proc png_set_compression_method uses eax edi, png_ptr:dword, method:dword
1528
	png_debug 1, 'in png_set_compression_method'
1528
	png_debug 1, 'in png_set_compression_method'
1529
 
1529
 
1530
	mov edi,[png_ptr]
1530
	mov edi,[png_ptr]
1531
	cmp edi,0
1531
	cmp edi,0
1532
	je .end_f ;if (..==0) return
1532
	je .end_f ;if (..==0) return
1533
 
1533
 
1534
	; This would produce an invalid PNG file if it worked, but it doesn't and
1534
	; This would produce an invalid PNG file if it worked, but it doesn't and
1535
	; deflate will fault it, so it is harmless to just warn here.
1535
	; deflate will fault it, so it is harmless to just warn here.
1536
 
1536
 
1537
	mov eax,[method]
1537
	mov eax,[method]
1538
	cmp eax,8
1538
	cmp eax,8
1539
	je @f ;if (..!=..)
1539
	je @f ;if (..!=..)
1540
		png_warning edi, 'Only compression method 8 is supported by PNG'
1540
		png_warning edi, 'Only compression method 8 is supported by PNG'
1541
	@@:
1541
	@@:
1542
	mov [edi+png_struct.zlib_method],eax
1542
	mov [edi+png_struct.zlib_method],eax
1543
.end_f:
1543
.end_f:
1544
	ret
1544
	ret
1545
endp
1545
endp
1546
 
1546
 
1547
; The following were added to libpng-1.5.4
1547
; The following were added to libpng-1.5.4
1548
if PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED eq 1
1548
if PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED eq 1
1549
;void (png_structrp png_ptr, int level)
1549
;void (png_structrp png_ptr, int level)
1550
align 4
1550
align 4
1551
proc png_set_text_compression_level uses edi, png_ptr:dword, level:dword
1551
proc png_set_text_compression_level uses edi, png_ptr:dword, level:dword
1552
	png_debug 1, 'in png_set_text_compression_level'
1552
	png_debug 1, 'in png_set_text_compression_level'
1553
 
1553
 
1554
	mov edi,[png_ptr]
1554
	mov edi,[png_ptr]
1555
	cmp edi,0
1555
	cmp edi,0
1556
	je @f ;if (..==0) return
1556
	je @f ;if (..==0) return
1557
 
1557
 
1558
	m2m [edi+png_struct.zlib_text_level], [level]
1558
	m2m [edi+png_struct.zlib_text_level], [level]
1559
	@@:
1559
	@@:
1560
	ret
1560
	ret
1561
endp
1561
endp
1562
 
1562
 
1563
;void (png_structrp png_ptr, int mem_level)
1563
;void (png_structrp png_ptr, int mem_level)
1564
align 4
1564
align 4
1565
proc png_set_text_compression_mem_level uses edi, png_ptr:dword, mem_level:dword
1565
proc png_set_text_compression_mem_level uses edi, png_ptr:dword, mem_level:dword
1566
	png_debug 1, 'in png_set_text_compression_mem_level'
1566
	png_debug 1, 'in png_set_text_compression_mem_level'
1567
 
1567
 
1568
	mov edi,[png_ptr]
1568
	mov edi,[png_ptr]
1569
	cmp edi,0
1569
	cmp edi,0
1570
	je @f ;if (..==0) return
1570
	je @f ;if (..==0) return
1571
 
1571
 
1572
	m2m [edi+png_struct.zlib_text_mem_level], [mem_level]
1572
	m2m [edi+png_struct.zlib_text_mem_level], [mem_level]
1573
	@@:
1573
	@@:
1574
	ret
1574
	ret
1575
endp
1575
endp
1576
 
1576
 
1577
;void (png_structrp png_ptr, int strategy)
1577
;void (png_structrp png_ptr, int strategy)
1578
align 4
1578
align 4
1579
proc png_set_text_compression_strategy uses edi, png_ptr:dword, strategy:dword
1579
proc png_set_text_compression_strategy uses edi, png_ptr:dword, strategy:dword
1580
	png_debug 1, 'in png_set_text_compression_strategy'
1580
	png_debug 1, 'in png_set_text_compression_strategy'
1581
 
1581
 
1582
	mov edi,[png_ptr]
1582
	mov edi,[png_ptr]
1583
	cmp edi,0
1583
	cmp edi,0
1584
	je .end_f ;if (..==0) return
1584
	je .end_f ;if (..==0) return
1585
 
1585
 
1586
	m2m [edi+png_struct.zlib_text_strategy], [strategy]
1586
	m2m [edi+png_struct.zlib_text_strategy], [strategy]
1587
.end_f:
1587
.end_f:
1588
	ret
1588
	ret
1589
endp
1589
endp
1590
 
1590
 
1591
; If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a
1591
; If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a
1592
; smaller value of window_bits if it can do so safely.
1592
; smaller value of window_bits if it can do so safely.
1593
 
1593
 
1594
;void (png_structrp png_ptr, int window_bits)
1594
;void (png_structrp png_ptr, int window_bits)
1595
align 4
1595
align 4
1596
proc png_set_text_compression_window_bits uses eax edi, png_ptr:dword, window_bits:dword
1596
proc png_set_text_compression_window_bits uses eax edi, png_ptr:dword, window_bits:dword
1597
	mov edi,[png_ptr]
1597
	mov edi,[png_ptr]
1598
	cmp edi,0
1598
	cmp edi,0
1599
	je .end_f ;if (..==0) return
1599
	je .end_f ;if (..==0) return
1600
 
1600
 
1601
	mov eax,[window_bits]
1601
	mov eax,[window_bits]
1602
	cmp eax,15
1602
	cmp eax,15
1603
	jle @f ;if (..>..)
1603
	jle @f ;if (..>..)
1604
		png_warning edi, 'Only compression windows <= 32k supported by PNG'
1604
		png_warning edi, 'Only compression windows <= 32k supported by PNG'
1605
		mov eax,15
1605
		mov eax,15
1606
		jmp .end0
1606
		jmp .end0
1607
	@@: ;else if (..<..)
1607
	@@: ;else if (..<..)
1608
	cmp eax,8
1608
	cmp eax,8
1609
	jge @f
1609
	jge @f
1610
		png_warning edi, 'Only compression windows >= 256 supported by PNG'
1610
		png_warning edi, 'Only compression windows >= 256 supported by PNG'
1611
		mov eax,8
1611
		mov eax,8
1612
	.end0:
1612
	.end0:
1613
 
1613
 
1614
	mov [edi+png_struct.zlib_text_window_bits],eax
1614
	mov [edi+png_struct.zlib_text_window_bits],eax
1615
.end_f:
1615
.end_f:
1616
	ret
1616
	ret
1617
endp
1617
endp
1618
 
1618
 
1619
;void (png_structrp png_ptr, int method)
1619
;void (png_structrp png_ptr, int method)
1620
align 4
1620
align 4
1621
proc png_set_text_compression_method uses edi, png_ptr:dword, method:dword
1621
proc png_set_text_compression_method uses edi, png_ptr:dword, method:dword
1622
	png_debug 1, 'in png_set_text_compression_method'
1622
	png_debug 1, 'in png_set_text_compression_method'
1623
 
1623
 
1624
	mov edi,[png_ptr]
1624
	mov edi,[png_ptr]
1625
	cmp edi,0
1625
	cmp edi,0
1626
	je .end_f ;if (..==0) return
1626
	je .end_f ;if (..==0) return
1627
 
1627
 
1628
	cmp dword[method],8
1628
	cmp dword[method],8
1629
	je @f ;if (..!=..)
1629
	je @f ;if (..!=..)
1630
		png_warning edi, 'Only compression method 8 is supported by PNG'
1630
		png_warning edi, 'Only compression method 8 is supported by PNG'
1631
	@@:
1631
	@@:
1632
	m2m [edi+png_struct.zlib_text_method], [method]
1632
	m2m [edi+png_struct.zlib_text_method], [method]
1633
.end_f:
1633
.end_f:
1634
	ret
1634
	ret
1635
endp
1635
endp
1636
end if ;WRITE_CUSTOMIZE_ZTXT_COMPRESSION
1636
end if ;WRITE_CUSTOMIZE_ZTXT_COMPRESSION
1637
; end of API added to libpng-1.5.4
1637
; end of API added to libpng-1.5.4
1638
 
1638
 
1639
;void (png_structrp png_ptr, png_write_status_ptr write_row_fn)
1639
;void (png_structrp png_ptr, png_write_status_ptr write_row_fn)
1640
align 4
1640
align 4
1641
proc png_set_write_status_fn uses edi, png_ptr:dword, write_row_fn:dword
1641
proc png_set_write_status_fn uses edi, png_ptr:dword, write_row_fn:dword
1642
	mov edi,[png_ptr]
1642
	mov edi,[png_ptr]
1643
	cmp edi,0
1643
	cmp edi,0
1644
	je @f ;if (..==0) return
1644
	je @f ;if (..==0) return
1645
		m2m [edi+png_struct.write_row_fn], [write_row_fn]
1645
		m2m [edi+png_struct.write_row_fn], [write_row_fn]
1646
	@@:
1646
	@@:
1647
	ret
1647
	ret
1648
endp
1648
endp
1649
 
1649
 
1650
;void (png_structrp png_ptr, png_user_transform_ptr write_user_transform_fn)
1650
;void (png_structrp png_ptr, png_user_transform_ptr write_user_transform_fn)
1651
align 4
1651
align 4
1652
proc png_set_write_user_transform_fn uses edi, png_ptr:dword, write_user_transform_fn:dword
1652
proc png_set_write_user_transform_fn uses edi, png_ptr:dword, write_user_transform_fn:dword
1653
	png_debug 1, 'in png_set_write_user_transform_fn'
1653
	png_debug 1, 'in png_set_write_user_transform_fn'
1654
 
1654
 
1655
	mov edi,[png_ptr]
1655
	mov edi,[png_ptr]
1656
	cmp edi,0
1656
	cmp edi,0
1657
	je @f ;if (..==0) return
1657
	je @f ;if (..==0) return
1658
		or dword[edi+png_struct.transformations], PNG_USER_TRANSFORM
1658
		or dword[edi+png_struct.transformations], PNG_USER_TRANSFORM
1659
		m2m [edi+png_struct.write_user_transform_fn], [write_user_transform_fn]
1659
		m2m [edi+png_struct.write_user_transform_fn], [write_user_transform_fn]
1660
	@@:
1660
	@@:
1661
	ret
1661
	ret
1662
endp
1662
endp
1663
 
1663
 
1664
;void (png_structrp png_ptr, png_inforp info_ptr, int transforms, voidp params)
1664
;void (png_structrp png_ptr, png_inforp info_ptr, int transforms, voidp params)
1665
align 4
1665
align 4
1666
proc png_write_png, png_ptr:dword, info_ptr:dword, transforms:dword, params:dword
1666
proc png_write_png, png_ptr:dword, info_ptr:dword, transforms:dword, params:dword
1667
pushad
1667
pushad
1668
	mov edi,[png_ptr]
1668
	mov edi,[png_ptr]
1669
	cmp edi,0
1669
	cmp edi,0
1670
	je .end_f
1670
	je .end_f
1671
	mov esi,[info_ptr]
1671
	mov esi,[info_ptr]
1672
	cmp esi,0
1672
	cmp esi,0
1673
	je .end_f ;if(..==0 || ..==0) return
1673
	je .end_f ;if(..==0 || ..==0) return
1674
 
1674
 
1675
	and dword[esi+png_info_def.valid],PNG_INFO_IDAT
1675
	and dword[esi+png_info_def.valid],PNG_INFO_IDAT
1676
	cmp esi,0 ;if(..==0)
1676
	cmp esi,0 ;if(..==0)
1677
	jne @f
1677
	jne @f
1678
		cStr ,'no rows for png_write_image to write'
1678
		cStr ,'no rows for png_write_image to write'
1679
		stdcall png_app_error edi, eax
1679
		stdcall png_app_error edi, eax
1680
		jmp .end_f ;return
1680
		jmp .end_f ;return
1681
	@@:
1681
	@@:
1682
 
1682
 
1683
	; Write the file header information.
1683
	; Write the file header information.
1684
	stdcall png_write_info, edi, esi
1684
	stdcall png_write_info, edi, esi
1685
 
1685
 
1686
	; ------ these transformations don't touch the info structure -------
1686
	; ------ these transformations don't touch the info structure -------
1687
 
1687
 
1688
	; Invert monochrome pixels
1688
	; Invert monochrome pixels
1689
	mov eax,[transforms]
1689
	mov eax,[transforms]
1690
	and eax,PNG_TRANSFORM_INVERT_MONO
1690
	and eax,PNG_TRANSFORM_INVERT_MONO
1691
	jz @f ;if(..!=0)
1691
	jz @f ;if(..!=0)
1692
if PNG_WRITE_INVERT_SUPPORTED eq 1
1692
if PNG_WRITE_INVERT_SUPPORTED eq 1
1693
		stdcall png_set_invert_mono,edi
1693
		stdcall png_set_invert_mono,edi
1694
else
1694
else
1695
		cStr ,'PNG_TRANSFORM_INVERT_MONO not supported'
1695
		cStr ,'PNG_TRANSFORM_INVERT_MONO not supported'
1696
		stdcall png_app_error edi, eax
1696
		stdcall png_app_error edi, eax
1697
end if
1697
end if
1698
	@@:
1698
	@@:
1699
 
1699
 
1700
	; Shift the pixels up to a legal bit depth and fill in
1700
	; Shift the pixels up to a legal bit depth and fill in
1701
	; as appropriate to correctly scale the image.
1701
	; as appropriate to correctly scale the image.
1702
 
1702
 
1703
	mov eax,[transforms]
1703
	mov eax,[transforms]
1704
	and eax,PNG_TRANSFORM_SHIFT
1704
	and eax,PNG_TRANSFORM_SHIFT
1705
	jz @f ;if(..!=0)
1705
	jz @f ;if(..!=0)
1706
if PNG_WRITE_SHIFT_SUPPORTED eq 1
1706
if PNG_WRITE_SHIFT_SUPPORTED eq 1
1707
	mov eax,[esi+png_info_def.valid]
1707
	mov eax,[esi+png_info_def.valid]
1708
	and eax,PNG_INFO_sBIT
1708
	and eax,PNG_INFO_sBIT
1709
	jz @f ;if(..!=0)
1709
	jz @f ;if(..!=0)
1710
		mov eax,esi
1710
		mov eax,esi
1711
		add eax,png_info_def.sig_bit
1711
		add eax,png_info_def.sig_bit
1712
		stdcall png_set_shift, edi, eax
1712
		stdcall png_set_shift, edi, eax
1713
else
1713
else
1714
		cStr ,'PNG_TRANSFORM_SHIFT not supported'
1714
		cStr ,'PNG_TRANSFORM_SHIFT not supported'
1715
		stdcall png_app_error edi, eax
1715
		stdcall png_app_error edi, eax
1716
end if
1716
end if
1717
	@@:
1717
	@@:
1718
 
1718
 
1719
	; Pack pixels into bytes
1719
	; Pack pixels into bytes
1720
	mov eax,[transforms]
1720
	mov eax,[transforms]
1721
	and eax,PNG_TRANSFORM_PACKING
1721
	and eax,PNG_TRANSFORM_PACKING
1722
	jz @f ;if(..!=0)
1722
	jz @f ;if(..!=0)
1723
if PNG_WRITE_PACK_SUPPORTED eq 1
1723
if PNG_WRITE_PACK_SUPPORTED eq 1
1724
		stdcall png_set_packing, edi
1724
		stdcall png_set_packing, edi
1725
else
1725
else
1726
		cStr ,'PNG_TRANSFORM_PACKING not supported'
1726
		cStr ,'PNG_TRANSFORM_PACKING not supported'
1727
		stdcall png_app_error edi, eax
1727
		stdcall png_app_error edi, eax
1728
end if
1728
end if
1729
	@@:
1729
	@@:
1730
 
1730
 
1731
	; Swap location of alpha bytes from ARGB to RGBA
1731
	; Swap location of alpha bytes from ARGB to RGBA
1732
	mov eax,[transforms]
1732
	mov eax,[transforms]
1733
	and eax,PNG_TRANSFORM_SWAP_ALPHA
1733
	and eax,PNG_TRANSFORM_SWAP_ALPHA
1734
	jz @f ;if(..!=0)
1734
	jz @f ;if(..!=0)
1735
if PNG_WRITE_SWAP_ALPHA_SUPPORTED eq 1
1735
if PNG_WRITE_SWAP_ALPHA_SUPPORTED eq 1
1736
		stdcall png_set_swap_alpha, edi
1736
		stdcall png_set_swap_alpha, edi
1737
else
1737
else
1738
		cStr ,'PNG_TRANSFORM_SWAP_ALPHA not supported'
1738
		cStr ,'PNG_TRANSFORM_SWAP_ALPHA not supported'
1739
		stdcall png_app_error edi, eax
1739
		stdcall png_app_error edi, eax
1740
end if
1740
end if
1741
	@@:
1741
	@@:
1742
 
1742
 
1743
	; Remove a filler (X) from XRGB/RGBX/AG/GA into to convert it into
1743
	; Remove a filler (X) from XRGB/RGBX/AG/GA into to convert it into
1744
	; RGB, note that the code expects the input color type to be G or RGB; no
1744
	; RGB, note that the code expects the input color type to be G or RGB; no
1745
	; alpha channel.
1745
	; alpha channel.
1746
 
1746
 
1747
	mov eax,[transforms]
1747
	mov eax,[transforms]
1748
	and eax,PNG_TRANSFORM_STRIP_FILLER_AFTER or PNG_TRANSFORM_STRIP_FILLER_BEFORE
1748
	and eax,PNG_TRANSFORM_STRIP_FILLER_AFTER or PNG_TRANSFORM_STRIP_FILLER_BEFORE
1749
	jz .end_0 ;if(..!=0)
1749
	jz .end_0 ;if(..!=0)
1750
if PNG_WRITE_FILLER_SUPPORTED eq 1
1750
if PNG_WRITE_FILLER_SUPPORTED eq 1
1751
	and eax,PNG_TRANSFORM_STRIP_FILLER_AFTER
1751
	and eax,PNG_TRANSFORM_STRIP_FILLER_AFTER
1752
	jz .end_1 ;if(..!=0)
1752
	jz .end_1 ;if(..!=0)
1753
		mov eax,[transforms]
1753
		mov eax,[transforms]
1754
		and eax,PNG_TRANSFORM_STRIP_FILLER_BEFORE
1754
		and eax,PNG_TRANSFORM_STRIP_FILLER_BEFORE
1755
		jz @f ;if(..!=0)
1755
		jz @f ;if(..!=0)
1756
            cStr ,'PNG_TRANSFORM_STRIP_FILLER: BEFORE+AFTER not supported'
1756
            cStr ,'PNG_TRANSFORM_STRIP_FILLER: BEFORE+AFTER not supported'
1757
			stdcall png_app_error edi, eax
1757
			stdcall png_app_error edi, eax
1758
		@@:
1758
		@@:
1759
 
1759
 
1760
		; Continue if ignored - this is the pre-1.6.10 behavior
1760
		; Continue if ignored - this is the pre-1.6.10 behavior
1761
		stdcall png_set_filler, edi, 0, PNG_FILLER_AFTER
1761
		stdcall png_set_filler, edi, 0, PNG_FILLER_AFTER
1762
		jmp .end_0
1762
		jmp .end_0
1763
	.end_1: ;else if ((transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) != 0)
1763
	.end_1: ;else if ((transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) != 0)
1764
		stdcall png_set_filler, edi, 0, PNG_FILLER_BEFORE
1764
		stdcall png_set_filler, edi, 0, PNG_FILLER_BEFORE
1765
else
1765
else
1766
		cStr ,'PNG_TRANSFORM_STRIP_FILLER not supported'
1766
		cStr ,'PNG_TRANSFORM_STRIP_FILLER not supported'
1767
		stdcall png_app_error edi, eax
1767
		stdcall png_app_error edi, eax
1768
end if
1768
end if
1769
	.end_0:
1769
	.end_0:
1770
 
1770
 
1771
	; Flip BGR pixels to RGB
1771
	; Flip BGR pixels to RGB
1772
	mov eax,[transforms]
1772
	mov eax,[transforms]
1773
	and eax,PNG_TRANSFORM_BGR
1773
	and eax,PNG_TRANSFORM_BGR
1774
	jz @f ;if(..!=0)
1774
	jz @f ;if(..!=0)
1775
if PNG_WRITE_BGR_SUPPORTED eq 1
1775
if PNG_WRITE_BGR_SUPPORTED eq 1
1776
		stdcall png_set_bgr, edi
1776
		stdcall png_set_bgr, edi
1777
else
1777
else
1778
		cStr ,'PNG_TRANSFORM_BGR not supported'
1778
		cStr ,'PNG_TRANSFORM_BGR not supported'
1779
		stdcall png_app_error edi, eax
1779
		stdcall png_app_error edi, eax
1780
end if
1780
end if
1781
	@@:
1781
	@@:
1782
 
1782
 
1783
	; Swap bytes of 16-bit files to most significant byte first
1783
	; Swap bytes of 16-bit files to most significant byte first
1784
	mov eax,[transforms]
1784
	mov eax,[transforms]
1785
	and eax,PNG_TRANSFORM_SWAP_ENDIAN
1785
	and eax,PNG_TRANSFORM_SWAP_ENDIAN
1786
	jz @f ;if(..!=0)
1786
	jz @f ;if(..!=0)
1787
if PNG_WRITE_SWAP_SUPPORTED eq 1
1787
if PNG_WRITE_SWAP_SUPPORTED eq 1
1788
		stdcall png_set_swap, edi
1788
		stdcall png_set_swap, edi
1789
else
1789
else
1790
		cStr ,'PNG_TRANSFORM_SWAP_ENDIAN not supported'
1790
		cStr ,'PNG_TRANSFORM_SWAP_ENDIAN not supported'
1791
		stdcall png_app_error edi, eax
1791
		stdcall png_app_error edi, eax
1792
end if
1792
end if
1793
	@@:
1793
	@@:
1794
 
1794
 
1795
	; Swap bits of 1-bit, 2-bit, 4-bit packed pixel formats
1795
	; Swap bits of 1-bit, 2-bit, 4-bit packed pixel formats
1796
	mov eax,[transforms]
1796
	mov eax,[transforms]
1797
	and eax,PNG_TRANSFORM_PACKSWAP
1797
	and eax,PNG_TRANSFORM_PACKSWAP
1798
	jz @f ;if(..!=0)
1798
	jz @f ;if(..!=0)
1799
if PNG_WRITE_PACKSWAP_SUPPORTED eq 1
1799
if PNG_WRITE_PACKSWAP_SUPPORTED eq 1
1800
		stdcall png_set_packswap, edi
1800
		stdcall png_set_packswap, edi
1801
else
1801
else
1802
		cStr ,'PNG_TRANSFORM_PACKSWAP not supported'
1802
		cStr ,'PNG_TRANSFORM_PACKSWAP not supported'
1803
		stdcall png_app_error edi, eax
1803
		stdcall png_app_error edi, eax
1804
end if
1804
end if
1805
	@@:
1805
	@@:
1806
 
1806
 
1807
	; Invert the alpha channel from opacity to transparency
1807
	; Invert the alpha channel from opacity to transparency
1808
	mov eax,[transforms]
1808
	mov eax,[transforms]
1809
	and eax,PNG_TRANSFORM_INVERT_ALPHA
1809
	and eax,PNG_TRANSFORM_INVERT_ALPHA
1810
	jz @f ;if(..!=0)
1810
	jz @f ;if(..!=0)
1811
if PNG_WRITE_INVERT_ALPHA_SUPPORTED eq 1
1811
if PNG_WRITE_INVERT_ALPHA_SUPPORTED eq 1
1812
		stdcall png_set_invert_alpha, edi
1812
		stdcall png_set_invert_alpha, edi
1813
else
1813
else
1814
		cStr ,'PNG_TRANSFORM_INVERT_ALPHA not supported'
1814
		cStr ,'PNG_TRANSFORM_INVERT_ALPHA not supported'
1815
		stdcall png_app_error edi, eax
1815
		stdcall png_app_error edi, eax
1816
end if
1816
end if
1817
	@@:
1817
	@@:
1818
 
1818
 
1819
	; ----------------------- end of transformations -------------------
1819
	; ----------------------- end of transformations -------------------
1820
 
1820
 
1821
	; Write the bits
1821
	; Write the bits
1822
	stdcall png_write_image, edi, dword[esi+png_info_def.row_pointers]
1822
	stdcall png_write_image, edi, dword[esi+png_info_def.row_pointers]
1823
 
1823
 
1824
	; It is REQUIRED to call this to finish writing the rest of the file
1824
	; It is REQUIRED to call this to finish writing the rest of the file
1825
	stdcall png_write_end, edi, esi
1825
	stdcall png_write_end, edi, esi
1826
 
1826
 
1827
.end_f:
1827
.end_f:
1828
popad
1828
popad
1829
	ret
1829
	ret
1830
endp
1830
endp
1831
 
1831
 
1832
if PNG_SIMPLIFIED_WRITE_SUPPORTED eq 1
1832
if PNG_SIMPLIFIED_WRITE_SUPPORTED eq 1
1833
; Initialize the write structure - general purpose utility.
1833
; Initialize the write structure - general purpose utility.
1834
;int (png_imagep image)
1834
;int (png_imagep image)
1835
align 4
1835
align 4
1836
proc png_image_write_init uses ebx ecx edx edi esi, image:dword
1836
proc png_image_write_init uses ebx ecx edx edi esi, image:dword
1837
	mov ebx,[image]
1837
	mov ebx,[image]
1838
	stdcall png_create_write_struct, PNG_LIBPNG_VER_STRING, ebx, png_safe_error, png_safe_warning
1838
	stdcall png_create_write_struct, PNG_LIBPNG_VER_STRING, ebx, png_safe_error, png_safe_warning
1839
	;eax = png_ptr
1839
	;eax = png_ptr
1840
 
1840
 
1841
	cmp eax,0
1841
	cmp eax,0
1842
	je .end0 ;if (..!=0)
1842
	je .end0 ;if (..!=0)
1843
		mov edi,eax
1843
		mov edi,eax
1844
		stdcall png_create_info_struct, edi
1844
		stdcall png_create_info_struct, edi
1845
		;eax = info_ptr
1845
		;eax = info_ptr
1846
 
1846
 
1847
		cmp eax,0
1847
		cmp eax,0
1848
		je .end1 ;if (..!=0)
1848
		je .end1 ;if (..!=0)
1849
			mov esi,eax
1849
			mov esi,eax
1850
			stdcall png_malloc_warn, edi, sizeof.png_control
1850
			stdcall png_malloc_warn, edi, sizeof.png_control
1851
			;control = eax
1851
			;control = eax
1852
 
1852
 
1853
			cmp eax,0
1853
			cmp eax,0
1854
			je .end2 ;if (..!=0)
1854
			je .end2 ;if (..!=0)
1855
				push eax
1855
				push eax
1856
				mov edx,edi ; edx = png_ptr
1856
				mov edx,edi ; edx = png_ptr
1857
				mov ecx,sizeof.png_control
1857
				mov ecx,sizeof.png_control
1858
				mov edi,eax
1858
				mov edi,eax
1859
				xor eax,eax
1859
				xor eax,eax
1860
				rep stosb ;memset(control, 0, (sizeof.control))
1860
				rep stosb ;memset(control, 0, (sizeof.control))
1861
				pop eax
1861
				pop eax
1862
 
1862
 
1863
				mov [eax+png_control.png_ptr], edx
1863
				mov [eax+png_control.png_ptr], edx
1864
				mov [eax+png_control.info_ptr], esi
1864
				mov [eax+png_control.info_ptr], esi
1865
				mov [eax+png_control.for_write], 1
1865
				mov [eax+png_control.for_write], 1
1866
 
1866
 
1867
				mov [ebx+png_image.opaque], eax
1867
				mov [ebx+png_image.opaque], eax
1868
				xor eax,eax
1868
				xor eax,eax
1869
				inc eax
1869
				inc eax
1870
				jmp .end_f
1870
				jmp .end_f
1871
			.end2:
1871
			.end2:
1872
 
1872
 
1873
			; Error clean up
1873
			; Error clean up
1874
			push esi
1874
			push esi
1875
			mov esi,esp
1875
			mov esi,esp
1876
			stdcall png_destroy_info_struct, edi, esi
1876
			stdcall png_destroy_info_struct, edi, esi
1877
			add esp,4
1877
			add esp,4
1878
		.end1:
1878
		.end1:
1879
 
1879
 
1880
		push edi
1880
		push edi
1881
		mov edi,esp
1881
		mov edi,esp
1882
		stdcall png_destroy_write_struct, edi, 0
1882
		stdcall png_destroy_write_struct, edi, 0
1883
		add esp,4
1883
		add esp,4
1884
	.end0:
1884
	.end0:
1885
 
1885
 
1886
	std_png_image_error ebx, 'png_image_write_: out of memory'
1886
	std_png_image_error ebx, 'png_image_write_: out of memory'
1887
.end_f:
1887
.end_f:
1888
	ret
1888
	ret
1889
endp
1889
endp
1890
 
1890
 
1891
; Arguments to png_image_write_main:
1891
; Arguments to png_image_write_main:
1892
struct png_image_write_control
1892
struct png_image_write_control
1893
	; Arguments:
1893
	; Arguments:
1894
	image  dd ? ;png_imagep
1894
	image  dd ? ;png_imagep
1895
	buffer dd ? ;png_const_voidp
1895
	buffer dd ? ;png_const_voidp
1896
	row_stride dd ? ;int_32
1896
	row_stride dd ? ;int_32
1897
	colormap   dd ? ;png_const_voidp
1897
	colormap   dd ? ;png_const_voidp
1898
	convert_to_8bit dd ? ;int
1898
	convert_to_8bit dd ? ;int
1899
	; Local variables:
1899
	; Local variables:
1900
	first_row dd ? ;png_const_voidp
1900
	first_row dd ? ;png_const_voidp
1901
	row_bytes dd ? ;ptrdiff_t
1901
	row_bytes dd ? ;ptrdiff_t
1902
	local_row dd ? ;voidp
1902
	local_row dd ? ;voidp
1903
	; Byte count for memory writing
1903
	; Byte count for memory writing
1904
	memory    dd ? ;bytep
1904
	memory    dd ? ;bytep
1905
	memory_bytes dd ? ;png_alloc_size_t ;not used for STDIO
1905
	memory_bytes dd ? ;png_alloc_size_t ;not used for STDIO
1906
	output_bytes dd ? ;png_alloc_size_t ;running total
1906
	output_bytes dd ? ;png_alloc_size_t ;running total
1907
ends
1907
ends
1908
 
1908
 
1909
; Write uint_16 input to a 16-bit PNG; the png_ptr has already been set to
1909
; Write uint_16 input to a 16-bit PNG; the png_ptr has already been set to
1910
; do any necessary byte swapping.  The component order is defined by the
1910
; do any necessary byte swapping.  The component order is defined by the
1911
; png_image format value.
1911
; png_image format value.
1912
 
1912
 
1913
;int (voidp argument)
1913
;int (voidp argument)
1914
align 4
1914
align 4
1915
proc png_write_image_16bit uses ebx ecx edx, argument:dword
1915
proc png_write_image_16bit uses ebx ecx edx, argument:dword
1916
locals
1916
locals
1917
	display dd ? ;png_image_write_control* ;= argument
1917
	display dd ? ;png_image_write_control* ;= argument
1918
	image   dd ? ;png_imagep ;= display->image
1918
	image   dd ? ;png_imagep ;= display->image
1919
	png_ptr dd ? ;png_structrp ;= image->opaque->png_ptr
1919
	png_ptr dd ? ;png_structrp ;= image->opaque->png_ptr
1920
	input_row  dd ? ;const_uint_16p ;= display->first_row
1920
	input_row  dd ? ;const_uint_16p ;= display->first_row
1921
	output_row dd ? ;uint_16p ;= display->local_row
1921
	output_row dd ? ;uint_16p ;= display->local_row
1922
	row_end  dd ? ;uint_16p
1922
	row_end  dd ? ;uint_16p
1923
	channels dd ? ;const int ;= (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1;
1923
	channels dd ? ;const int ;= (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1;
1924
	aindex   dd 0 ;int  ;= 0
1924
	aindex   dd 0 ;int  ;= 0
1925
	y dd ? ;uint_32 ;= image->height
1925
	y dd ? ;uint_32 ;= image->height
1926
endl
1926
endl
1927
	mov ebx,[argument]
1927
	mov ebx,[argument]
1928
	mov [display],ebx
1928
	mov [display],ebx
1929
	mov edx,[ebx+png_image_write_control.image]
1929
	mov edx,[ebx+png_image_write_control.image]
1930
	mov [image],edx
1930
	mov [image],edx
1931
	mov ecx,[edx+png_image.opaque]
1931
	mov ecx,[edx+png_image.opaque]
1932
	mov ecx,[ecx+png_control.png_ptr]
1932
	mov ecx,[ecx+png_control.png_ptr]
1933
	mov [png_ptr],ecx
1933
	mov [png_ptr],ecx
1934
	mov ecx,[ebx+png_image_write_control.first_row]
1934
	mov ecx,[ebx+png_image_write_control.first_row]
1935
	mov [input_row],ecx
1935
	mov [input_row],ecx
1936
	mov ecx,[ebx+png_image_write_control.local_row]
1936
	mov ecx,[ebx+png_image_write_control.local_row]
1937
	mov [output_row],ecx
1937
	mov [output_row],ecx
1938
 
1938
 
1939
	mov ecx,1
1939
	mov ecx,1
1940
	mov eax,[edx+png_image.format]
1940
	mov eax,[edx+png_image.format]
1941
	and eax,PNG_FORMAT_FLAG_COLOR
1941
	and eax,PNG_FORMAT_FLAG_COLOR
1942
	jz @f
1942
	jz @f
1943
		mov ecx,3
1943
		mov ecx,3
1944
	@@:
1944
	@@:
1945
	mov [channels],ecx
1945
	mov [channels],ecx
1946
	mov eax,[edx+png_image.height]
1946
	mov eax,[edx+png_image.height]
1947
	mov [y],eax
1947
	mov [y],eax
1948
 
1948
 
1949
	mov eax,[edx+png_image.format]
1949
	mov eax,[edx+png_image.format]
1950
	and eax,PNG_FORMAT_FLAG_ALPHA
1950
	and eax,PNG_FORMAT_FLAG_ALPHA
1951
	jz .end0 ;if (..!=0)
1951
	jz .end0 ;if (..!=0)
1952
if PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED eq 1
1952
if PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED eq 1
1953
	mov eax,[edx+png_image.format]
1953
	mov eax,[edx+png_image.format]
1954
	and eax,PNG_FORMAT_FLAG_AFIRST
1954
	and eax,PNG_FORMAT_FLAG_AFIRST
1955
	jz @f ;if (..!=0)
1955
	jz @f ;if (..!=0)
1956
		mov dword[aindex],-1
1956
		mov dword[aindex],-1
1957
		inc dword[input_row] ;To point to the first component
1957
		inc dword[input_row] ;To point to the first component
1958
		inc dword[output_row]
1958
		inc dword[output_row]
1959
		jmp .end1
1959
		jmp .end1
1960
	@@: ;else
1960
	@@: ;else
1961
end if
1961
end if
1962
		mov eax,[channels]
1962
		mov eax,[channels]
1963
		mov [aindex],eax
1963
		mov [aindex],eax
1964
		jmp .end1
1964
		jmp .end1
1965
	.end0: ;else
1965
	.end0: ;else
1966
		png_error [png_ptr], 'png_write_image: internal call error'
1966
		png_error [png_ptr], 'png_write_image: internal call error'
1967
	.end1:
1967
	.end1:
1968
 
1968
 
1969
	; Work out the output row end and count over this, note that the increment
1969
	; Work out the output row end and count over this, note that the increment
1970
	; above to 'row' means that row_end can actually be beyond the end of the
1970
	; above to 'row' means that row_end can actually be beyond the end of the
1971
	; row; this is correct.
1971
	; row; this is correct.
1972
 
1972
 
1973
	mov eax,[channels]
1973
	mov eax,[channels]
1974
	inc eax
1974
	inc eax
1975
	imul eax,[edx+png_image.width]
1975
	imul eax,[edx+png_image.width]
1976
	add eax,[output_row]
1976
	add eax,[output_row]
1977
	mov [row_end],eax
1977
	mov [row_end],eax
1978
 
1978
 
1979
;   while (y-- > 0)
1979
;   while (y-- > 0)
1980
;   {
1980
;   {
1981
;      const_uint_16p in_ptr = input_row;
1981
;      const_uint_16p in_ptr = input_row;
1982
;      uint_16p out_ptr = output_row;
1982
;      uint_16p out_ptr = output_row;
1983
 
1983
 
1984
;      while (out_ptr < row_end)
1984
;      while (out_ptr < row_end)
1985
;      {
1985
;      {
1986
;         const uint_16 alpha = in_ptr[aindex];
1986
;         const uint_16 alpha = in_ptr[aindex];
1987
;         uint_32 reciprocal = 0;
1987
;         uint_32 reciprocal = 0;
1988
;         int c;
1988
;         int c;
1989
 
1989
 
1990
;         out_ptr[aindex] = alpha;
1990
;         out_ptr[aindex] = alpha;
1991
 
1991
 
1992
	; Calculate a reciprocal.  The correct calculation is simply
1992
	; Calculate a reciprocal.  The correct calculation is simply
1993
	; component/alpha*65535 << 15. (I.e. 15 bits of precision); this
1993
	; component/alpha*65535 << 15. (I.e. 15 bits of precision); this
1994
	; allows correct rounding by adding .5 before the shift.  'reciprocal'
1994
	; allows correct rounding by adding .5 before the shift.  'reciprocal'
1995
	; is only initialized when required.
1995
	; is only initialized when required.
1996
 
1996
 
1997
;         if (alpha > 0 && alpha < 65535)
1997
;         if (alpha > 0 && alpha < 65535)
1998
;            reciprocal = ((0xffff<<15)+(alpha>>1))/alpha;
1998
;            reciprocal = ((0xffff<<15)+(alpha>>1))/alpha;
1999
 
1999
 
2000
;         c = channels;
2000
;         c = channels;
2001
;         do /* always at least one channel */
2001
;         do /* always at least one channel */
2002
;         {
2002
;         {
2003
;            uint_16 component = *in_ptr++;
2003
;            uint_16 component = *in_ptr++;
2004
 
2004
 
2005
	; The following gives 65535 for an alpha of 0, which is fine,
2005
	; The following gives 65535 for an alpha of 0, which is fine,
2006
	; otherwise if 0/0 is represented as some other value there is more
2006
	; otherwise if 0/0 is represented as some other value there is more
2007
	; likely to be a discontinuity which will probably damage
2007
	; likely to be a discontinuity which will probably damage
2008
	; compression when moving from a fully transparent area to a
2008
	; compression when moving from a fully transparent area to a
2009
	; nearly transparent one.  (The assumption here is that opaque
2009
	; nearly transparent one.  (The assumption here is that opaque
2010
	; areas tend not to be 0 intensity.)
2010
	; areas tend not to be 0 intensity.)
2011
 
2011
 
2012
;            if (component >= alpha)
2012
;            if (component >= alpha)
2013
;               component = 65535;
2013
;               component = 65535;
2014
 
2014
 
2015
	; component
2015
	; component
2016
	; component*reciprocal is less than 2^31.
2016
	; component*reciprocal is less than 2^31.
2017
 
2017
 
2018
;            else if (component > 0 && alpha < 65535)
2018
;            else if (component > 0 && alpha < 65535)
2019
;            {
2019
;            {
2020
;               uint_32 calc = component * reciprocal;
2020
;               uint_32 calc = component * reciprocal;
2021
;               calc += 16384; /* round to nearest */
2021
;               calc += 16384; /* round to nearest */
2022
;               component = (uint_16)(calc >> 15);
2022
;               component = (uint_16)(calc >> 15);
2023
;            }
2023
;            }
2024
 
2024
 
2025
;            *out_ptr++ = component;
2025
;            *out_ptr++ = component;
2026
;         }
2026
;         }
2027
;         while (--c > 0);
2027
;         while (--c > 0);
2028
 
2028
 
2029
	; Skip to next component (skip the intervening alpha channel)
2029
	; Skip to next component (skip the intervening alpha channel)
2030
;         ++in_ptr;
2030
;         ++in_ptr;
2031
;         ++out_ptr;
2031
;         ++out_ptr;
2032
;      }
2032
;      }
2033
 
2033
 
2034
;      png_write_row(png_ptr, display->local_row);
2034
;      png_write_row(png_ptr, display->local_row);
2035
;      input_row += display->row_bytes/(sizeof (uint_16));
2035
;      input_row += display->row_bytes/(sizeof (uint_16));
2036
;   }
2036
;   }
2037
 
2037
 
2038
	xor eax,eax
2038
	xor eax,eax
2039
	inc eax ;return 1
2039
	inc eax ;return 1
2040
	ret
2040
	ret
2041
endp
2041
endp
2042
 
2042
 
2043
; Given 16-bit input (1 to 4 channels) write 8-bit output.  If an alpha channel
2043
; Given 16-bit input (1 to 4 channels) write 8-bit output.  If an alpha channel
2044
; is present it must be removed from the components, the components are then
2044
; is present it must be removed from the components, the components are then
2045
; written in sRGB encoding.  No components are added or removed.
2045
; written in sRGB encoding.  No components are added or removed.
2046
 
2046
 
2047
; Calculate an alpha reciprocal to reverse pre-multiplication.  As above the
2047
; Calculate an alpha reciprocal to reverse pre-multiplication.  As above the
2048
; calculation can be done to 15 bits of accuracy; however, the output needs to
2048
; calculation can be done to 15 bits of accuracy; however, the output needs to
2049
; be scaled in the range 0..255*65535, so include that scaling here.
2049
; be scaled in the range 0..255*65535, so include that scaling here.
2050
 
2050
 
2051
;#   define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+(alpha>>1))/alpha)
2051
;#   define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+(alpha>>1))/alpha)
2052
 
2052
 
2053
;byte (uint_32 component, uint_32 alpha, uint_32 reciprocal/*from the above macro*/)
2053
;byte (uint_32 component, uint_32 alpha, uint_32 reciprocal/*from the above macro*/)
2054
align 4
2054
align 4
2055
proc png_unpremultiply, component:dword, alpha:dword, reciprocal:dword
2055
proc png_unpremultiply, component:dword, alpha:dword, reciprocal:dword
2056
	; The following gives 1.0 for an alpha of 0, which is fine, otherwise if 0/0
2056
	; The following gives 1.0 for an alpha of 0, which is fine, otherwise if 0/0
2057
	; is represented as some other value there is more likely to be a
2057
	; is represented as some other value there is more likely to be a
2058
	; discontinuity which will probably damage compression when moving from a
2058
	; discontinuity which will probably damage compression when moving from a
2059
	; fully transparent area to a nearly transparent one.  (The assumption here
2059
	; fully transparent area to a nearly transparent one.  (The assumption here
2060
	; is that opaque areas tend not to be 0 intensity.)
2060
	; is that opaque areas tend not to be 0 intensity.)
2061
 
2061
 
2062
	; There is a rounding problem here; if alpha is less than 128 it will end up
2062
	; There is a rounding problem here; if alpha is less than 128 it will end up
2063
	; as 0 when scaled to 8 bits.  To avoid introducing spurious colors into the
2063
	; as 0 when scaled to 8 bits.  To avoid introducing spurious colors into the
2064
	; output change for this too.
2064
	; output change for this too.
2065
 
2065
 
2066
	mov eax,[alpha]
2066
	mov eax,[alpha]
2067
	cmp [component],eax
2067
	cmp [component],eax
2068
	jge @f
2068
	jge @f
2069
	cmp eax,128
2069
	cmp eax,128
2070
	jge .end0
2070
	jge .end0
2071
	@@: ;if (..>=.. || ..<..)
2071
	@@: ;if (..>=.. || ..<..)
2072
		mov eax,255
2072
		mov eax,255
2073
		jmp .end_f
2073
		jmp .end_f
2074
		; component
2074
		; component
2075
		; component*reciprocal is less than 2^31.
2075
		; component*reciprocal is less than 2^31.
2076
 
2076
 
2077
	.end0: ;else if (component > 0)
2077
	.end0: ;else if (component > 0)
2078
	cmp dword[component],0
2078
	cmp dword[component],0
2079
	jle .end1
2079
	jle .end1
2080
		; The test is that alpha/257 (rounded) is less than 255, the first value
2080
		; The test is that alpha/257 (rounded) is less than 255, the first value
2081
		; that becomes 255 is 65407.
2081
		; that becomes 255 is 65407.
2082
		; NOTE: this must agree with the PNG_DIV257 macro (which must, therefore,
2082
		; NOTE: this must agree with the PNG_DIV257 macro (which must, therefore,
2083
		; be exact!)  [Could also test reciprocal != 0]
2083
		; be exact!)  [Could also test reciprocal != 0]
2084
 
2084
 
2085
;      if (alpha < 65407)
2085
;      if (alpha < 65407)
2086
;      {
2086
;      {
2087
;         component *= reciprocal;
2087
;         component *= reciprocal;
2088
;         component += 64; /* round to nearest */
2088
;         component += 64; /* round to nearest */
2089
;         component >>= 7;
2089
;         component >>= 7;
2090
;      }
2090
;      }
2091
 
2091
 
2092
;      else
2092
;      else
2093
;         component *= 255;
2093
;         component *= 255;
2094
 
2094
 
2095
		; Convert the component to sRGB.
2095
		; Convert the component to sRGB.
2096
		PNG_sRGB_FROM_LINEAR [component]
2096
		PNG_sRGB_FROM_LINEAR [component]
2097
		and eax,0xff
2097
		and eax,0xff
2098
		jmp .end_f
2098
		jmp .end_f
2099
	.end1: ;else
2099
	.end1: ;else
2100
		xor eax,eax
2100
		xor eax,eax
2101
.end_f:
2101
.end_f:
2102
	ret
2102
	ret
2103
endp
2103
endp
2104
 
2104
 
2105
;int (voidp argument)
2105
;int (voidp argument)
2106
align 4
2106
align 4
2107
proc png_write_image_8bit uses ebx ecx edx edi esi, argument:dword
2107
proc png_write_image_8bit uses ebx ecx edx edi esi, argument:dword
2108
locals
2108
locals
2109
	display dd ? ;png_image_write_control* ;= argument
2109
	display dd ? ;png_image_write_control* ;= argument
2110
	image   dd ? ;png_imagep ;= display->image
2110
	image   dd ? ;png_imagep ;= display->image
2111
	png_ptr dd ? ;png_structrp ;= image->opaque->png_ptr
2111
	png_ptr dd ? ;png_structrp ;= image->opaque->png_ptr
2112
	input_row  dd ? ;const_uint_16p ;= display->first_row
2112
	input_row  dd ? ;const_uint_16p ;= display->first_row
2113
	output_row dd ? ;uint_16p ;= display->local_row
2113
	output_row dd ? ;uint_16p ;= display->local_row
2114
	row_end  dd ? ;uint_16p
2114
	row_end  dd ? ;uint_16p
2115
	channels dd ? ;const int ;= (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1;
2115
	channels dd ? ;const int ;= (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1;
2116
	aindex   dd 0 ;int  ;= 0
2116
	aindex   dd 0 ;int  ;= 0
2117
	y dd ? ;uint_32 ;= image->height
2117
	y dd ? ;uint_32 ;= image->height
2118
	component dd ? ;uint_32
2118
	component dd ? ;uint_32
2119
endl
2119
endl
2120
	mov ebx,[argument]
2120
	mov ebx,[argument]
2121
	mov [display],ebx
2121
	mov [display],ebx
2122
	mov edx,[ebx+png_image_write_control.image]
2122
	mov edx,[ebx+png_image_write_control.image]
2123
	mov [image],edx
2123
	mov [image],edx
2124
	mov ecx,[edx+png_image.opaque]
2124
	mov ecx,[edx+png_image.opaque]
2125
	mov ecx,[ecx+png_control.png_ptr]
2125
	mov ecx,[ecx+png_control.png_ptr]
2126
	mov [png_ptr],ecx
2126
	mov [png_ptr],ecx
2127
	mov ecx,[ebx+png_image_write_control.first_row]
2127
	mov ecx,[ebx+png_image_write_control.first_row]
2128
	mov [input_row],ecx
2128
	mov [input_row],ecx
2129
	mov ecx,[ebx+png_image_write_control.local_row]
2129
	mov ecx,[ebx+png_image_write_control.local_row]
2130
	mov [output_row],ecx
2130
	mov [output_row],ecx
2131
 
2131
 
2132
	mov ecx,1
2132
	mov ecx,1
2133
	mov eax,[edx+png_image.format]
2133
	mov eax,[edx+png_image.format]
2134
	and eax,PNG_FORMAT_FLAG_COLOR
2134
	and eax,PNG_FORMAT_FLAG_COLOR
2135
	jz @f
2135
	jz @f
2136
		mov ecx,3
2136
		mov ecx,3
2137
	@@:
2137
	@@:
2138
	mov [channels],ecx
2138
	mov [channels],ecx
2139
	mov eax,[edx+png_image.height]
2139
	mov eax,[edx+png_image.height]
2140
	mov [y],eax
2140
	mov [y],eax
2141
 
2141
 
2142
	mov eax,[edx+png_image.format]
2142
	mov eax,[edx+png_image.format]
2143
	and eax,PNG_FORMAT_FLAG_ALPHA
2143
	and eax,PNG_FORMAT_FLAG_ALPHA
2144
	jz .end0 ;if (..!=0)
2144
	jz .end0 ;if (..!=0)
2145
;      bytep row_end;
2145
;      bytep row_end;
2146
;      int aindex;
2146
;      int aindex;
2147
 
2147
 
2148
if PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED eq 1
2148
if PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED eq 1
2149
;      if ((image->format & PNG_FORMAT_FLAG_AFIRST) != 0)
2149
;      if ((image->format & PNG_FORMAT_FLAG_AFIRST) != 0)
2150
;      {
2150
;      {
2151
;         aindex = -1;
2151
;         aindex = -1;
2152
;         ++input_row; /* To point to the first component */
2152
;         ++input_row; /* To point to the first component */
2153
;         ++output_row;
2153
;         ++output_row;
2154
;      }
2154
;      }
2155
 
2155
 
2156
;      else
2156
;      else
2157
end if
2157
end if
2158
;      aindex = channels;
2158
;      aindex = channels;
2159
 
2159
 
2160
	; Use row_end in place of a loop counter:
2160
	; Use row_end in place of a loop counter:
2161
;      row_end = output_row + image->width * (channels+1);
2161
;      row_end = output_row + image->width * (channels+1);
2162
 
2162
 
2163
;      while (y-- > 0)
2163
;      while (y-- > 0)
2164
;      {
2164
;      {
2165
;         const_uint_16p in_ptr = input_row;
2165
;         const_uint_16p in_ptr = input_row;
2166
;         bytep out_ptr = output_row;
2166
;         bytep out_ptr = output_row;
2167
 
2167
 
2168
;         while (out_ptr < row_end)
2168
;         while (out_ptr < row_end)
2169
;         {
2169
;         {
2170
;            uint_16 alpha = in_ptr[aindex];
2170
;            uint_16 alpha = in_ptr[aindex];
2171
;            byte alphabyte = (byte)PNG_DIV257(alpha);
2171
;            byte alphabyte = (byte)PNG_DIV257(alpha);
2172
;            uint_32 reciprocal = 0;
2172
;            uint_32 reciprocal = 0;
2173
;            int c;
2173
;            int c;
2174
 
2174
 
2175
	; Scale and write the alpha channel.
2175
	; Scale and write the alpha channel.
2176
;            out_ptr[aindex] = alphabyte;
2176
;            out_ptr[aindex] = alphabyte;
2177
 
2177
 
2178
;            if (alphabyte > 0 && alphabyte < 255)
2178
;            if (alphabyte > 0 && alphabyte < 255)
2179
;               reciprocal = UNP_RECIPROCAL(alpha);
2179
;               reciprocal = UNP_RECIPROCAL(alpha);
2180
 
2180
 
2181
;            c = channels;
2181
;            c = channels;
2182
;            do /* always at least one channel */
2182
;            do /* always at least one channel */
2183
;               *out_ptr++ = png_unpremultiply(*in_ptr++, alpha, reciprocal);
2183
;               *out_ptr++ = png_unpremultiply(*in_ptr++, alpha, reciprocal);
2184
;            while (--c > 0);
2184
;            while (--c > 0);
2185
 
2185
 
2186
	; Skip to next component (skip the intervening alpha channel)
2186
	; Skip to next component (skip the intervening alpha channel)
2187
;            ++in_ptr;
2187
;            ++in_ptr;
2188
;            ++out_ptr;
2188
;            ++out_ptr;
2189
;         } /* while out_ptr < row_end */
2189
;         } /* while out_ptr < row_end */
2190
 
2190
 
2191
;         png_write_row(png_ptr, display->local_row);
2191
;         png_write_row(png_ptr, display->local_row);
2192
;         input_row += display->row_bytes/(sizeof (uint_16));
2192
;         input_row += display->row_bytes/(sizeof (uint_16));
2193
;      } /* while y */
2193
;      } /* while y */
2194
		jmp .end1
2194
		jmp .end1
2195
	.end0: ;else
2195
	.end0: ;else
2196
		; No alpha channel, so the row_end really is the end of the row and it
2196
		; No alpha channel, so the row_end really is the end of the row and it
2197
		; is sufficient to loop over the components one by one.
2197
		; is sufficient to loop over the components one by one.
2198
 
2198
 
2199
		mov ecx,[edx+png_image.width]
2199
		mov ecx,[edx+png_image.width]
2200
		imul ecx,[channels]
2200
		imul ecx,[channels]
2201
		add ecx,[output_row]
2201
		add ecx,[output_row]
2202
		;ecx = row_end
2202
		;ecx = row_end
2203
 
2203
 
2204
		.cycle2: ;while (y-- > 0)
2204
		.cycle2: ;while (y-- > 0)
2205
			cmp dword[y],0
2205
			cmp dword[y],0
2206
			jle .cycle2end
2206
			jle .cycle2end
2207
			mov esi,[input_row]
2207
			mov esi,[input_row]
2208
			mov edi,[output_row]
2208
			mov edi,[output_row]
2209
			;esi = in_ptr
2209
			;esi = in_ptr
2210
			;edi = out_ptr
2210
			;edi = out_ptr
2211
 
2211
 
2212
			.cycle3: ;while (..<..)
2212
			.cycle3: ;while (..<..)
2213
				cmp edi,ecx
2213
				cmp edi,ecx
2214
				jge .cycle3end
2214
				jge .cycle3end
2215
				xor eax,eax
2215
				xor eax,eax
2216
				lodsw
2216
				lodsw
2217
 
2217
 
2218
				imul eax,255
2218
				imul eax,255
2219
				mov [component],eax
2219
				mov [component],eax
2220
				PNG_sRGB_FROM_LINEAR [component]
2220
				PNG_sRGB_FROM_LINEAR [component]
2221
				stosb
2221
				stosb
2222
				jmp .cycle3
2222
				jmp .cycle3
2223
align 4
2223
align 4
2224
			.cycle3end:
2224
			.cycle3end:
2225
 
2225
 
2226
			stdcall png_write_row, [png_ptr], [output_row]
2226
			stdcall png_write_row, [png_ptr], [output_row]
2227
			mov eax,[ebx+png_image_write_control.row_bytes]
2227
			mov eax,[ebx+png_image_write_control.row_bytes]
2228
			shr eax,1 ;sizeof.uint_16
2228
			shr eax,1 ;sizeof.uint_16
2229
			add [input_row],eax
2229
			add [input_row],eax
2230
			dec dword[y]
2230
			dec dword[y]
2231
			jmp .cycle2
2231
			jmp .cycle2
2232
align 4
2232
align 4
2233
		.cycle2end:
2233
		.cycle2end:
2234
	.end1:
2234
	.end1:
2235
 
2235
 
2236
	xor eax,eax
2236
	xor eax,eax
2237
	inc eax
2237
	inc eax
2238
	ret
2238
	ret
2239
endp
2239
endp
2240
 
2240
 
2241
;void (png_image_write_control *display)
2241
;void (png_image_write_control *display)
2242
align 4
2242
align 4
2243
proc png_image_set_PLTE, display:dword
2243
proc png_image_set_PLTE, display:dword
2244
locals
2244
locals
2245
	image dd ? ;png_imagep ;= display->image
2245
	image dd ? ;png_imagep ;= display->image
2246
	cmap dd ? ;void * ;= display->colormap
2246
	cmap dd ? ;void * ;= display->colormap
2247
	entries dd ? ;int
2247
	entries dd ? ;int
2248
 
2248
 
2249
	; NOTE: the caller must check for cmap != NULL and entries != 0
2249
	; NOTE: the caller must check for cmap != NULL and entries != 0
2250
	format dd ? ;uint_32 ;= image->format
2250
	format dd ? ;uint_32 ;= image->format
2251
	channels dd ? ;int
2251
	channels dd ? ;int
2252
	afirst dd 0
2252
	afirst dd 0
2253
	bgr dd 0
2253
	bgr dd 0
2254
	num_trans dd 0
2254
	num_trans dd 0
2255
	palette rb 256*sizeof.png_color
2255
	palette rb 256*sizeof.png_color
2256
	tRNS rb 256 ;byte[]
2256
	tRNS rb 256 ;byte[]
2257
endl
2257
endl
2258
pushad
2258
pushad
2259
	mov edx,[display]
2259
	mov edx,[display]
2260
	mov ebx,[edx+png_image_write_control.image]
2260
	mov ebx,[edx+png_image_write_control.image]
2261
	mov [image],ebx
2261
	mov [image],ebx
2262
	mov eax,[edx+png_image_write_control.colormap]
2262
	mov eax,[edx+png_image_write_control.colormap]
2263
	mov [cmap],eax
2263
	mov [cmap],eax
2264
	mov eax,[ebx+png_image.colormap_entries]
2264
	mov eax,[ebx+png_image.colormap_entries]
2265
	cmp eax,256
2265
	cmp eax,256
2266
	jle @f
2266
	jle @f
2267
		mov eax,256
2267
		mov eax,256
2268
	@@:
2268
	@@:
2269
	mov [entries],eax
2269
	mov [entries],eax
2270
	mov ecx,[ebx+png_image.format]
2270
	mov ecx,[ebx+png_image.format]
2271
	mov [format],ecx
2271
	mov [format],ecx
2272
	PNG_IMAGE_SAMPLE_CHANNELS ecx
2272
	PNG_IMAGE_SAMPLE_CHANNELS ecx
2273
	mov [channels],eax
2273
	mov [channels],eax
2274
 
2274
 
2275
if (PNG_FORMAT_BGR_SUPPORTED eq 1) & (PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED eq 1)
2275
if (PNG_FORMAT_BGR_SUPPORTED eq 1) & (PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED eq 1)
2276
	mov eax,ecx
2276
	mov eax,ecx
2277
	and eax,PNG_FORMAT_FLAG_AFIRST
2277
	and eax,PNG_FORMAT_FLAG_AFIRST
2278
	jz @f
2278
	jz @f
2279
	mov eax,ecx
2279
	mov eax,ecx
2280
	and eax,PNG_FORMAT_FLAG_ALPHA
2280
	and eax,PNG_FORMAT_FLAG_ALPHA
2281
	jz @f
2281
	jz @f
2282
		mov dword[afirst],-1
2282
		mov dword[afirst],-1
2283
	@@:
2283
	@@:
2284
end if
2284
end if
2285
 
2285
 
2286
if PNG_FORMAT_BGR_SUPPORTED eq 1
2286
if PNG_FORMAT_BGR_SUPPORTED eq 1
2287
	mov eax,ecx
2287
	mov eax,ecx
2288
	and eax,PNG_FORMAT_FLAG_BGR
2288
	and eax,PNG_FORMAT_FLAG_BGR
2289
	jz @f
2289
	jz @f
2290
		mov dword[bgr],2
2290
		mov dword[bgr],2
2291
	@@:
2291
	@@:
2292
end if
2292
end if
2293
 
2293
 
2294
;   int i;
2294
;   int i;
2295
 
2295
 
2296
	xor eax,eax
2296
	xor eax,eax
2297
	mov ecx,(256*sizeof.png_color)/4
2297
	mov ecx,(256*sizeof.png_color)/4
2298
	mov edi,ebp
2298
	mov edi,ebp
2299
	sub edi,256+256*sizeof.png_color
2299
	sub edi,256+256*sizeof.png_color
2300
	rep stosd ;memset(palette, 0, ...
2300
	rep stosd ;memset(palette, 0, ...
2301
	not eax
2301
	not eax
2302
	mov ecx,256/4
2302
	mov ecx,256/4
2303
	;;mov edi,ebp ;if 'tRNS' after 'palette' this code can be comment
2303
	;;mov edi,ebp ;if 'tRNS' after 'palette' this code can be comment
2304
	;;sub edi,256
2304
	;;sub edi,256
2305
	rep stosd ;memset(tRNS, 255, ...
2305
	rep stosd ;memset(tRNS, 255, ...
2306
 
2306
 
2307
 
2307
 
2308
;   for (i=num_trans=0; i
2308
;   for (i=num_trans=0; i
2309
;   {
2309
;   {
2310
		; This gets automatically converted to sRGB with reversal of the
2310
		; This gets automatically converted to sRGB with reversal of the
2311
		; pre-multiplication if the color-map has an alpha channel.
2311
		; pre-multiplication if the color-map has an alpha channel.
2312
 
2312
 
2313
;      if ((format & PNG_FORMAT_FLAG_LINEAR) != 0)
2313
;      if ((format & PNG_FORMAT_FLAG_LINEAR) != 0)
2314
;      {
2314
;      {
2315
;         png_const_uint_16p entry = cmap;
2315
;         png_const_uint_16p entry = cmap;
2316
 
2316
 
2317
;         entry += i * channels;
2317
;         entry += i * channels;
2318
 
2318
 
2319
;         if ((channels & 1) != 0) /* no alpha */
2319
;         if ((channels & 1) != 0) /* no alpha */
2320
;         {
2320
;         {
2321
;            if (channels >= 3) /* RGB */
2321
;            if (channels >= 3) /* RGB */
2322
;            {
2322
;            {
2323
;               palette[i].blue = (byte)PNG_sRGB_FROM_LINEAR(255 *
2323
;               palette[i].blue = (byte)PNG_sRGB_FROM_LINEAR(255 *
2324
;                   entry[(2 ^ bgr)]);
2324
;                   entry[(2 ^ bgr)]);
2325
;               palette[i].green = (byte)PNG_sRGB_FROM_LINEAR(255 *
2325
;               palette[i].green = (byte)PNG_sRGB_FROM_LINEAR(255 *
2326
;                   entry[1]);
2326
;                   entry[1]);
2327
;               palette[i].red = (byte)PNG_sRGB_FROM_LINEAR(255 *
2327
;               palette[i].red = (byte)PNG_sRGB_FROM_LINEAR(255 *
2328
;                   entry[bgr]);
2328
;                   entry[bgr]);
2329
;            }
2329
;            }
2330
 
2330
 
2331
;            else /* Gray */
2331
;            else /* Gray */
2332
;               palette[i].blue = palette[i].red = palette[i].green =
2332
;               palette[i].blue = palette[i].red = palette[i].green =
2333
;                  (byte)PNG_sRGB_FROM_LINEAR(255 * *entry);
2333
;                  (byte)PNG_sRGB_FROM_LINEAR(255 * *entry);
2334
;         }
2334
;         }
2335
 
2335
 
2336
;         else /* alpha */
2336
;         else /* alpha */
2337
;         {
2337
;         {
2338
;            uint_16 alpha = entry[afirst ? 0 : channels-1];
2338
;            uint_16 alpha = entry[afirst ? 0 : channels-1];
2339
;            byte alphabyte = (byte)PNG_DIV257(alpha);
2339
;            byte alphabyte = (byte)PNG_DIV257(alpha);
2340
;            uint_32 reciprocal = 0;
2340
;            uint_32 reciprocal = 0;
2341
 
2341
 
2342
		; Calculate a reciprocal, as in the png_write_image_8bit code above
2342
		; Calculate a reciprocal, as in the png_write_image_8bit code above
2343
		; this is designed to produce a value scaled to 255*65535 when
2343
		; this is designed to produce a value scaled to 255*65535 when
2344
		; divided by 128 (i.e. asr 7).
2344
		; divided by 128 (i.e. asr 7).
2345
 
2345
 
2346
;            if (alphabyte > 0 && alphabyte < 255)
2346
;            if (alphabyte > 0 && alphabyte < 255)
2347
;               reciprocal = (((0xffff*0xff)<<7)+(alpha>>1))/alpha;
2347
;               reciprocal = (((0xffff*0xff)<<7)+(alpha>>1))/alpha;
2348
 
2348
 
2349
;            tRNS[i] = alphabyte;
2349
;            tRNS[i] = alphabyte;
2350
;            if (alphabyte < 255)
2350
;            if (alphabyte < 255)
2351
;               num_trans = i+1;
2351
;               num_trans = i+1;
2352
 
2352
 
2353
;            if (channels >= 3) /* RGB */
2353
;            if (channels >= 3) /* RGB */
2354
;            {
2354
;            {
2355
;               palette[i].blue = png_unpremultiply(entry[afirst + (2 ^ bgr)],
2355
;               palette[i].blue = png_unpremultiply(entry[afirst + (2 ^ bgr)],
2356
;                   alpha, reciprocal);
2356
;                   alpha, reciprocal);
2357
;               palette[i].green = png_unpremultiply(entry[afirst + 1], alpha,
2357
;               palette[i].green = png_unpremultiply(entry[afirst + 1], alpha,
2358
;                   reciprocal);
2358
;                   reciprocal);
2359
;               palette[i].red = png_unpremultiply(entry[afirst + bgr], alpha,
2359
;               palette[i].red = png_unpremultiply(entry[afirst + bgr], alpha,
2360
;                   reciprocal);
2360
;                   reciprocal);
2361
;            }
2361
;            }
2362
 
2362
 
2363
;            else /* gray */
2363
;            else /* gray */
2364
;               palette[i].blue = palette[i].red = palette[i].green =
2364
;               palette[i].blue = palette[i].red = palette[i].green =
2365
;                   png_unpremultiply(entry[afirst], alpha, reciprocal);
2365
;                   png_unpremultiply(entry[afirst], alpha, reciprocal);
2366
;         }
2366
;         }
2367
;      }
2367
;      }
2368
 
2368
 
2369
;      else /* Color-map has sRGB values */
2369
;      else /* Color-map has sRGB values */
2370
;      {
2370
;      {
2371
;         bytep entry = cmap;
2371
;         bytep entry = cmap;
2372
 
2372
 
2373
;         entry += i * channels;
2373
;         entry += i * channels;
2374
 
2374
 
2375
;         switch (channels)
2375
;         switch (channels)
2376
;         {
2376
;         {
2377
;            case 4:
2377
;            case 4:
2378
;               tRNS[i] = entry[afirst ? 0 : 3];
2378
;               tRNS[i] = entry[afirst ? 0 : 3];
2379
;               if (tRNS[i] < 255)
2379
;               if (tRNS[i] < 255)
2380
;                  num_trans = i+1;
2380
;                  num_trans = i+1;
2381
;               /* FALL THROUGH */
2381
;               /* FALL THROUGH */
2382
;            case 3:
2382
;            case 3:
2383
;               palette[i].blue = entry[afirst + (2 ^ bgr)];
2383
;               palette[i].blue = entry[afirst + (2 ^ bgr)];
2384
;               palette[i].green = entry[afirst + 1];
2384
;               palette[i].green = entry[afirst + 1];
2385
;               palette[i].red = entry[afirst + bgr];
2385
;               palette[i].red = entry[afirst + bgr];
2386
;               break;
2386
;               break;
2387
 
2387
 
2388
;            case 2:
2388
;            case 2:
2389
;               tRNS[i] = entry[1 ^ afirst];
2389
;               tRNS[i] = entry[1 ^ afirst];
2390
;               if (tRNS[i] < 255)
2390
;               if (tRNS[i] < 255)
2391
;                  num_trans = i+1;
2391
;                  num_trans = i+1;
2392
;               /* FALL THROUGH */
2392
;               /* FALL THROUGH */
2393
;            case 1:
2393
;            case 1:
2394
;               palette[i].blue = palette[i].red = palette[i].green =
2394
;               palette[i].blue = palette[i].red = palette[i].green =
2395
;                  entry[afirst];
2395
;                  entry[afirst];
2396
;               break;
2396
;               break;
2397
 
2397
 
2398
;            default:
2398
;            default:
2399
;               break;
2399
;               break;
2400
;         }
2400
;         }
2401
;      }
2401
;      }
2402
;   }
2402
;   }
2403
 
2403
 
2404
	mov ecx,[ebx+png_image.opaque]
2404
	mov ecx,[ebx+png_image.opaque]
2405
	mov eax,ebp
2405
	mov eax,ebp
2406
	sub eax,256+256*sizeof.png_color
2406
	sub eax,256+256*sizeof.png_color
2407
	stdcall png_set_PLTE, [ecx+png_control.png_ptr], [ecx+png_control.info_ptr], eax, [entries]
2407
	stdcall png_set_PLTE, [ecx+png_control.png_ptr], [ecx+png_control.info_ptr], eax, [entries]
2408
 
2408
 
2409
	cmp dword[num_trans],0
2409
	cmp dword[num_trans],0
2410
	jle @f ;if (..>0)
2410
	jle @f ;if (..>0)
2411
		mov eax,ebp
2411
		mov eax,ebp
2412
		sub eax,256
2412
		sub eax,256
2413
		stdcall png_set_tRNS, [ecx+png_control.png_ptr], [ecx+png_control.info_ptr], eax, [num_trans], 0
2413
		stdcall png_set_tRNS, [ecx+png_control.png_ptr], [ecx+png_control.info_ptr], eax, [num_trans], 0
2414
	@@:
2414
	@@:
2415
 
2415
 
2416
	mov eax,[entries]
2416
	mov eax,[entries]
2417
	mov [ebx+png_image.colormap_entries],eax
2417
	mov [ebx+png_image.colormap_entries],eax
2418
popad
2418
popad
2419
	ret
2419
	ret
2420
endp
2420
endp
2421
 
2421
 
2422
;int (voidp argument)
2422
;int (voidp argument)
2423
align 4
2423
align 4
2424
proc png_image_write_main uses ebx ecx edx esi edi, argument:dword
2424
proc png_image_write_main uses ebx ecx edx esi edi, argument:dword
2425
locals
2425
locals
2426
	display dd ? ;= png_image_write_control * = argument
2426
	display dd ? ;= png_image_write_control * = argument
2427
	image dd ? ;= display->image
2427
	image dd ? ;= display->image
2428
	png_ptr dd ? ;= image->opaque->png_ptr
2428
	png_ptr dd ? ;= image->opaque->png_ptr
2429
	info_ptr dd ? ;= image->opaque->info_ptr
2429
	info_ptr dd ? ;= image->opaque->info_ptr
2430
	format dd ? ;= image->format
2430
	format dd ? ;= image->format
2431
 
2431
 
2432
	colormap dd ?
2432
	colormap dd ?
2433
	linear dd ?
2433
	linear dd ?
2434
	alpha dd ?
2434
	alpha dd ?
2435
	write_16bit dd ? ;= linear && !colormap && (display->convert_to_8bit == 0)
2435
	write_16bit dd ? ;= linear && !colormap && (display->convert_to_8bit == 0)
2436
endl
2436
endl
2437
	mov edx,[argument]
2437
	mov edx,[argument]
2438
	mov [display],edx
2438
	mov [display],edx
2439
	mov ebx,[edx+png_image_write_control.image]
2439
	mov ebx,[edx+png_image_write_control.image]
2440
	mov [image],ebx
2440
	mov [image],ebx
2441
	mov ecx,[ebx+png_image.format]
2441
	mov ecx,[ebx+png_image.format]
2442
	mov [format],ecx
2442
	mov [format],ecx
2443
	mov eax,[ebx+png_image.opaque]
2443
	mov eax,[ebx+png_image.opaque]
2444
	mov edi,[eax+png_control.png_ptr]
2444
	mov edi,[eax+png_control.png_ptr]
2445
	mov [png_ptr],edi
2445
	mov [png_ptr],edi
2446
	mov esi,[eax+png_control.info_ptr]
2446
	mov esi,[eax+png_control.info_ptr]
2447
	mov [info_ptr],esi
2447
	mov [info_ptr],esi
2448
 
2448
 
2449
	; The following four ints are actually booleans
2449
	; The following four ints are actually booleans
2450
	and ecx,PNG_FORMAT_FLAG_COLORMAP
2450
	and ecx,PNG_FORMAT_FLAG_COLORMAP
2451
	mov [colormap],ecx
2451
	mov [colormap],ecx
2452
	not ecx
2452
	not ecx
2453
	mov eax,[format]
2453
	mov eax,[format]
2454
	and eax,PNG_FORMAT_FLAG_LINEAR
2454
	and eax,PNG_FORMAT_FLAG_LINEAR
2455
	mov [linear],eax
2455
	mov [linear],eax
2456
	mov eax,[format]
2456
	mov eax,[format]
2457
	and eax,ecx
2457
	and eax,ecx
2458
	and eax,PNG_FORMAT_FLAG_ALPHA
2458
	and eax,PNG_FORMAT_FLAG_ALPHA
2459
	and eax,ecx
2459
	and eax,ecx
2460
	mov [alpha],eax
2460
	mov [alpha],eax
2461
	xor eax,eax ;false
2461
	xor eax,eax ;false
2462
	cmp dword[edx+png_image_write_control.convert_to_8bit],0
2462
	cmp dword[edx+png_image_write_control.convert_to_8bit],0
2463
	jne @f
2463
	jne @f
2464
		not eax ;true
2464
		not eax ;true
2465
	@@:
2465
	@@:
2466
	and eax,[linear]
2466
	and eax,[linear]
2467
	and eax,ecx
2467
	and eax,ecx
2468
	mov [write_16bit],eax
2468
	mov [write_16bit],eax
2469
 
2469
 
2470
if PNG_BENIGN_ERRORS_SUPPORTED eq 1
2470
if PNG_BENIGN_ERRORS_SUPPORTED eq 1
2471
	; Make sure we error out on any bad situation
2471
	; Make sure we error out on any bad situation
2472
	stdcall png_set_benign_errors, edi, 0 ;error
2472
	stdcall png_set_benign_errors, edi, 0 ;error
2473
end if
2473
end if
2474
 
2474
 
2475
	; Default the 'row_stride' parameter if required, also check the row stride
2475
	; Default the 'row_stride' parameter if required, also check the row stride
2476
	; and total image size to ensure that they are within the system limits.
2476
	; and total image size to ensure that they are within the system limits.
2477
 
2477
 
2478
	PNG_IMAGE_PIXEL_CHANNELS [ebx+png_image.format]
2478
	PNG_IMAGE_PIXEL_CHANNELS [ebx+png_image.format]
2479
	;eax = channels 
2479
	;eax = channels 
2480
 
2480
 
2481
	push edx
2481
	push edx
2482
	mov ecx,eax
2482
	mov ecx,eax
2483
	mov eax,0x7FFFFFFF
2483
	mov eax,0x7FFFFFFF
2484
	xor edx,edx
2484
	xor edx,edx
2485
	div ecx
2485
	div ecx
2486
	pop edx
2486
	pop edx
2487
	cmp [ebx+png_image.width],eax
2487
	cmp [ebx+png_image.width],eax
2488
	jg .end0 ;if (..<=..) ;no overflow
2488
	jg .end0 ;if (..<=..) ;no overflow
2489
		imul ecx,[ebx+png_image.width]
2489
		imul ecx,[ebx+png_image.width]
2490
 
2490
 
2491
		cmp dword[edx+png_image_write_control.row_stride],0
2491
		cmp dword[edx+png_image_write_control.row_stride],0
2492
		jne @f ;if (..==0)
2492
		jne @f ;if (..==0)
2493
			mov [edx+png_image_write_control.row_stride],ecx
2493
			mov [edx+png_image_write_control.row_stride],ecx
2494
		@@:
2494
		@@:
2495
		mov eax,[edx+png_image_write_control.row_stride]
2495
		mov eax,[edx+png_image_write_control.row_stride]
2496
		cmp eax,0
2496
		cmp eax,0
2497
		jge .end2 ;if (..<0)
2497
		jge .end2 ;if (..<0)
2498
			neg eax
2498
			neg eax
2499
			inc eax
2499
			inc eax
2500
		.end2:
2500
		.end2:
2501
 
2501
 
2502
		cmp eax,ecx
2502
		cmp eax,ecx
2503
		jl .end3 ;if (..>=..)
2503
		jl .end3 ;if (..>=..)
2504
			; Now check for overflow of the image buffer calculation; this
2504
			; Now check for overflow of the image buffer calculation; this
2505
			; limits the whole image size to 32 bits for API compatibility with
2505
			; limits the whole image size to 32 bits for API compatibility with
2506
			; the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro.
2506
			; the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro.
2507
 
2507
 
2508
			push edx
2508
			push edx
2509
			mov eax,0xFFFFFFFF
2509
			mov eax,0xFFFFFFFF
2510
			xor edx,edx
2510
			xor edx,edx
2511
			div ecx
2511
			div ecx
2512
			pop edx
2512
			pop edx
2513
			cmp [ebx+png_image.height],eax
2513
			cmp [ebx+png_image.height],eax
2514
			jle @f ;if (..>..)
2514
			jle @f ;if (..>..)
2515
				mov eax,[ebx+png_image.opaque]
2515
				mov eax,[ebx+png_image.opaque]
2516
				mov eax,[eax+png_control.png_ptr]
2516
				mov eax,[eax+png_control.png_ptr]
2517
				png_error eax, 'memory image too large'
2517
				png_error eax, 'memory image too large'
2518
			@@:
2518
			@@:
2519
			jmp .end1
2519
			jmp .end1
2520
		.end3: ;else
2520
		.end3: ;else
2521
			mov eax,[ebx+png_image.opaque]
2521
			mov eax,[ebx+png_image.opaque]
2522
			mov eax,[eax+png_control.png_ptr]
2522
			mov eax,[eax+png_control.png_ptr]
2523
			png_error eax, 'supplied row stride too small'
2523
			png_error eax, 'supplied row stride too small'
2524
		jmp .end1
2524
		jmp .end1
2525
	.end0: ;else
2525
	.end0: ;else
2526
		mov eax,[ebx+png_image.opaque]
2526
		mov eax,[ebx+png_image.opaque]
2527
		mov eax,[eax+png_control.png_ptr]
2527
		mov eax,[eax+png_control.png_ptr]
2528
		png_error eax, 'image row stride too large'
2528
		png_error eax, 'image row stride too large'
2529
	.end1:
2529
	.end1:
2530
 
2530
 
2531
	; Set the required transforms then write the rows in the correct order.
2531
	; Set the required transforms then write the rows in the correct order.
2532
	mov eax,[format]
2532
	mov eax,[format]
2533
	and eax,PNG_FORMAT_FLAG_COLORMAP
2533
	and eax,PNG_FORMAT_FLAG_COLORMAP
2534
	jz .end4 ;if (..!=0)
2534
	jz .end4 ;if (..!=0)
2535
		cmp dword[edx+png_image_write_control.colormap],0
2535
		cmp dword[edx+png_image_write_control.colormap],0
2536
		je .end6
2536
		je .end6
2537
		mov eax,[ebx+png_image.colormap_entries]
2537
		mov eax,[ebx+png_image.colormap_entries]
2538
		cmp eax,0
2538
		cmp eax,0
2539
		jle .end6 ;if (..!=0 && ..>0)
2539
		jle .end6 ;if (..!=0 && ..>0)
2540
			;eax = entries
2540
			;eax = entries
2541
			xor ecx,ecx
2541
			xor ecx,ecx
2542
			inc ecx ;=1
2542
			inc ecx ;=1
2543
			cmp eax,2
2543
			cmp eax,2
2544
			jle @f
2544
			jle @f
2545
				shl ecx,1 ;=2
2545
				shl ecx,1 ;=2
2546
			cmp eax,4
2546
			cmp eax,4
2547
			jle @f
2547
			jle @f
2548
				shl ecx,1 ;=4
2548
				shl ecx,1 ;=4
2549
			cmp eax,16
2549
			cmp eax,16
2550
			jle @f
2550
			jle @f
2551
				shl ecx,1 ;=8
2551
				shl ecx,1 ;=8
2552
			@@:
2552
			@@:
2553
			stdcall png_set_IHDR, edi, esi, [ebx+png_image.width], [ebx+png_image.height],\
2553
			stdcall png_set_IHDR, edi, esi, [ebx+png_image.width], [ebx+png_image.height],\
2554
				ecx, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,\
2554
				ecx, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,\
2555
				PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE
2555
				PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE
2556
 
2556
 
2557
			stdcall png_image_set_PLTE, edx
2557
			stdcall png_image_set_PLTE, edx
2558
			jmp .end5
2558
			jmp .end5
2559
		.end6: ;else
2559
		.end6: ;else
2560
			mov eax,[ebx+png_image.opaque]
2560
			mov eax,[ebx+png_image.opaque]
2561
			mov eax,[eax+png_control.png_ptr]
2561
			mov eax,[eax+png_control.png_ptr]
2562
			png_error eax, 'no color-map for color-mapped image'
2562
			png_error eax, 'no color-map for color-mapped image'
2563
		jmp .end5
2563
		jmp .end5
2564
	.end4: ;else
2564
	.end4: ;else
2565
		xor ecx,ecx
2565
		xor ecx,ecx
2566
		mov eax,[format]
2566
		mov eax,[format]
2567
		and eax,PNG_FORMAT_FLAG_COLOR
2567
		and eax,PNG_FORMAT_FLAG_COLOR
2568
		jz @f
2568
		jz @f
2569
			or ecx,PNG_COLOR_MASK_COLOR
2569
			or ecx,PNG_COLOR_MASK_COLOR
2570
		@@:
2570
		@@:
2571
		mov eax,[format]
2571
		mov eax,[format]
2572
		and eax,PNG_FORMAT_FLAG_ALPHA
2572
		and eax,PNG_FORMAT_FLAG_ALPHA
2573
		jz @f
2573
		jz @f
2574
			or ecx,PNG_COLOR_MASK_ALPHA
2574
			or ecx,PNG_COLOR_MASK_ALPHA
2575
		@@:
2575
		@@:
2576
		mov eax,8
2576
		mov eax,8
2577
		cmp dword[write_16bit],0
2577
		cmp dword[write_16bit],0
2578
		je @f
2578
		je @f
2579
			mov eax,16
2579
			mov eax,16
2580
		@@:
2580
		@@:
2581
		stdcall png_set_IHDR, edi, esi, [ebx+png_image.width], [ebx+png_image.height],\
2581
		stdcall png_set_IHDR, edi, esi, [ebx+png_image.width], [ebx+png_image.height],\
2582
			eax, ecx, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE
2582
			eax, ecx, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE
2583
	.end5:
2583
	.end5:
2584
 
2584
 
2585
	; Counter-intuitively the data transformations must be called *after*
2585
	; Counter-intuitively the data transformations must be called *after*
2586
	; png_write_info, not before as in the read code, but the 'set' functions
2586
	; png_write_info, not before as in the read code, but the 'set' functions
2587
	; must still be called before.  Just set the color space information, never
2587
	; must still be called before.  Just set the color space information, never
2588
	; write an interlaced image.
2588
	; write an interlaced image.
2589
 
2589
 
2590
	cmp dword[write_16bit],0
2590
	cmp dword[write_16bit],0
2591
	je @f ;if (..!=0)
2591
	je @f ;if (..!=0)
2592
		; The gamma here is 1.0 (linear) and the cHRM chunk matches sRGB.
2592
		; The gamma here is 1.0 (linear) and the cHRM chunk matches sRGB.
2593
		stdcall png_set_gAMA_fixed, edi, esi, PNG_GAMMA_LINEAR
2593
		stdcall png_set_gAMA_fixed, edi, esi, PNG_GAMMA_LINEAR
2594
 
2594
 
2595
		mov eax,[ebx+png_image.flags]
2595
		mov eax,[ebx+png_image.flags]
2596
		and eax,PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB
2596
		and eax,PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB
2597
		jnz @f ;if (..==0)
2597
		jnz @f ;if (..==0)
2598
			stdcall png_set_cHRM_fixed, edi, esi,\
2598
			stdcall png_set_cHRM_fixed, edi, esi,\
2599
			31270, 32900,\ ;white
2599
			31270, 32900,\ ;white
2600
			64000, 33000,\ ;red
2600
			64000, 33000,\ ;red
2601
			30000, 60000,\ ;green
2601
			30000, 60000,\ ;green
2602
			15000,  6000   ;blue
2602
			15000,  6000   ;blue
2603
		jmp .end7
2603
		jmp .end7
2604
	@@:
2604
	@@:
2605
	mov eax,[ebx+png_image.flags]
2605
	mov eax,[ebx+png_image.flags]
2606
	and eax,PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB
2606
	and eax,PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB
2607
	jnz @f ;else if (..==0)
2607
	jnz @f ;else if (..==0)
2608
		stdcall png_set_sRGB, edi, esi, PNG_sRGB_INTENT_PERCEPTUAL
2608
		stdcall png_set_sRGB, edi, esi, PNG_sRGB_INTENT_PERCEPTUAL
2609
		jmp .end7
2609
		jmp .end7
2610
	@@: ;else
2610
	@@: ;else
2611
		; Else writing an 8-bit file and the *colors* aren't sRGB, but the 8-bit
2611
		; Else writing an 8-bit file and the *colors* aren't sRGB, but the 8-bit
2612
		; space must still be gamma encoded.
2612
		; space must still be gamma encoded.
2613
		stdcall png_set_gAMA_fixed, edi, esi, PNG_GAMMA_sRGB_INVERSE
2613
		stdcall png_set_gAMA_fixed, edi, esi, PNG_GAMMA_sRGB_INVERSE
2614
	.end7:
2614
	.end7:
2615
 
2615
 
2616
	; Write the file header.
2616
	; Write the file header.
2617
	stdcall png_write_info, edi, esi
2617
	stdcall png_write_info, edi, esi
2618
 
2618
 
2619
	; Now set up the data transformations (*after* the header is written),
2619
	; Now set up the data transformations (*after* the header is written),
2620
	; remove the handled transformations from the 'format' flags for checking.
2620
	; remove the handled transformations from the 'format' flags for checking.
2621
 
2621
 
2622
	; First check for a little endian system if writing 16-bit files.
2622
	; First check for a little endian system if writing 16-bit files.
2623
 
2623
 
2624
	cmp dword[write_16bit],0
2624
	cmp dword[write_16bit],0
2625
	je @f ;if (..!=0)
2625
	je @f ;if (..!=0)
2626
;      uint_16 le = 0x0001;
2626
;      uint_16 le = 0x0001;
2627
 
2627
 
2628
;      if ((*(bytep) & le) != 0)
2628
;      if ((*(bytep) & le) != 0)
2629
		stdcall png_set_swap, edi
2629
		stdcall png_set_swap, edi
2630
	@@:
2630
	@@:
2631
 
2631
 
2632
if PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED eq 1
2632
if PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED eq 1
2633
	mov eax,[format]
2633
	mov eax,[format]
2634
	and eax,PNG_FORMAT_FLAG_BGR
2634
	and eax,PNG_FORMAT_FLAG_BGR
2635
	jz .end12 ;if (..!=0)
2635
	jz .end12 ;if (..!=0)
2636
		cmp dword[colormap],0
2636
		cmp dword[colormap],0
2637
		jne @f
2637
		jne @f
2638
		mov eax,[format]
2638
		mov eax,[format]
2639
		and eax,PNG_FORMAT_FLAG_COLOR
2639
		and eax,PNG_FORMAT_FLAG_COLOR
2640
		jz @f ;if (..==0 && ..!=0)
2640
		jz @f ;if (..==0 && ..!=0)
2641
			stdcall png_set_bgr, edi
2641
			stdcall png_set_bgr, edi
2642
		@@:
2642
		@@:
2643
		and dword[format], not PNG_FORMAT_FLAG_BGR
2643
		and dword[format], not PNG_FORMAT_FLAG_BGR
2644
	.end12:
2644
	.end12:
2645
end if
2645
end if
2646
 
2646
 
2647
if PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED eq 1
2647
if PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED eq 1
2648
	mov eax,[format]
2648
	mov eax,[format]
2649
	and eax,PNG_FORMAT_FLAG_AFIRST
2649
	and eax,PNG_FORMAT_FLAG_AFIRST
2650
	jz .end13 ;if (..!=0)
2650
	jz .end13 ;if (..!=0)
2651
		cmp dword[colormap],0
2651
		cmp dword[colormap],0
2652
		jne @f
2652
		jne @f
2653
		mov eax,[format]
2653
		mov eax,[format]
2654
		and eax,PNG_FORMAT_FLAG_ALPHA
2654
		and eax,PNG_FORMAT_FLAG_ALPHA
2655
		jz @f ;if (..==0 && ..!=0)
2655
		jz @f ;if (..==0 && ..!=0)
2656
			stdcall png_set_swap_alpha, edi
2656
			stdcall png_set_swap_alpha, edi
2657
		@@:
2657
		@@:
2658
		and dword[format], not PNG_FORMAT_FLAG_AFIRST
2658
		and dword[format], not PNG_FORMAT_FLAG_AFIRST
2659
	.end13:
2659
	.end13:
2660
end if
2660
end if
2661
 
2661
 
2662
	; If there are 16 or fewer color-map entries we wrote a lower bit depth
2662
	; If there are 16 or fewer color-map entries we wrote a lower bit depth
2663
	; above, but the application data is still byte packed.
2663
	; above, but the application data is still byte packed.
2664
 
2664
 
2665
	cmp dword[colormap],0
2665
	cmp dword[colormap],0
2666
	je @f
2666
	je @f
2667
	cmp dword[ebx+png_image.colormap_entries],16
2667
	cmp dword[ebx+png_image.colormap_entries],16
2668
	jg @f ;if (..!=0 && ..<=16)
2668
	jg @f ;if (..!=0 && ..<=16)
2669
		stdcall png_set_packing, edi
2669
		stdcall png_set_packing, edi
2670
	@@:
2670
	@@:
2671
 
2671
 
2672
	; That should have handled all (both) the transforms.
2672
	; That should have handled all (both) the transforms.
2673
	mov eax,[format]
2673
	mov eax,[format]
2674
	and eax, not (PNG_FORMAT_FLAG_COLOR or PNG_FORMAT_FLAG_LINEAR or PNG_FORMAT_FLAG_ALPHA or PNG_FORMAT_FLAG_COLORMAP)
2674
	and eax, not (PNG_FORMAT_FLAG_COLOR or PNG_FORMAT_FLAG_LINEAR or PNG_FORMAT_FLAG_ALPHA or PNG_FORMAT_FLAG_COLORMAP)
2675
	jz @f ;if (..!=0)
2675
	jz @f ;if (..!=0)
2676
		png_error edi, 'png_write_image: unsupported transformation'
2676
		png_error edi, 'png_write_image: unsupported transformation'
2677
	@@:
2677
	@@:
2678
 
2678
 
2679
	push esi
2679
	push esi
2680
	;ecx - row ;bytep
2680
	;ecx - row ;bytep
2681
	;esi - row_bytes
2681
	;esi - row_bytes
2682
	mov ecx,[edx+png_image_write_control.buffer]
2682
	mov ecx,[edx+png_image_write_control.buffer]
2683
	mov esi,[edx+png_image_write_control.row_stride]
2683
	mov esi,[edx+png_image_write_control.row_stride]
2684
 
2684
 
2685
	cmp dword[linear],0
2685
	cmp dword[linear],0
2686
	je @f ;if (..!=0)
2686
	je @f ;if (..!=0)
2687
		shl esi,1 ;*= sizeof.uint_16
2687
		shl esi,1 ;*= sizeof.uint_16
2688
	@@:
2688
	@@:
2689
	cmp esi,0
2689
	cmp esi,0
2690
	jge @f ;if (..<0)
2690
	jge @f ;if (..<0)
2691
		mov eax,[ebx+png_image.height]
2691
		mov eax,[ebx+png_image.height]
2692
		dec eax
2692
		dec eax
2693
		imul eax,esi
2693
		imul eax,esi
2694
		sub ecx,eax
2694
		sub ecx,eax
2695
	@@:
2695
	@@:
2696
	mov [edx+png_image_write_control.first_row],ecx
2696
	mov [edx+png_image_write_control.first_row],ecx
2697
	mov [edx+png_image_write_control.row_bytes],esi
2697
	mov [edx+png_image_write_control.row_bytes],esi
2698
	pop esi
2698
	pop esi
2699
 
2699
 
2700
	; Apply 'fast' options if the flag is set.
2700
	; Apply 'fast' options if the flag is set.
2701
	mov eax,[ebx+png_image.flags]
2701
	mov eax,[ebx+png_image.flags]
2702
	and eax,PNG_IMAGE_FLAG_FAST
2702
	and eax,PNG_IMAGE_FLAG_FAST
2703
	jz @f ;if (..!=0)
2703
	jz @f ;if (..!=0)
2704
		stdcall png_set_filter, edi, PNG_FILTER_TYPE_BASE, PNG_NO_FILTERS
2704
		stdcall png_set_filter, edi, PNG_FILTER_TYPE_BASE, PNG_NO_FILTERS
2705
		; NOTE: determined by experiment using pngstest, this reflects some
2705
		; NOTE: determined by experiment using pngstest, this reflects some
2706
		; balance between the time to write the image once and the time to read
2706
		; balance between the time to write the image once and the time to read
2707
		; it about 50 times.  The speed-up in pngstest was about 10-20% of the
2707
		; it about 50 times.  The speed-up in pngstest was about 10-20% of the
2708
		; total (user) time on a heavily loaded system.
2708
		; total (user) time on a heavily loaded system.
2709
 
2709
 
2710
if PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED eq 1
2710
if PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED eq 1
2711
		stdcall png_set_compression_level, edi, 3
2711
		stdcall png_set_compression_level, edi, 3
2712
end if
2712
end if
2713
	@@:
2713
	@@:
2714
 
2714
 
2715
	; Check for the cases that currently require a pre-transform on the row
2715
	; Check for the cases that currently require a pre-transform on the row
2716
	; before it is written.  This only applies when the input is 16-bit and
2716
	; before it is written.  This only applies when the input is 16-bit and
2717
	; either there is an alpha channel or it is converted to 8-bit.
2717
	; either there is an alpha channel or it is converted to 8-bit.
2718
 
2718
 
2719
	cmp dword[linear],0
2719
	cmp dword[linear],0
2720
	je @f
2720
	je @f
2721
	cmp dword[alpha],0
2721
	cmp dword[alpha],0
2722
	je @f
2722
	je @f
2723
		jmp .end10
2723
		jmp .end10
2724
	@@:
2724
	@@:
2725
	cmp dword[colormap],0
2725
	cmp dword[colormap],0
2726
	jne .end9
2726
	jne .end9
2727
	cmp dword[edx+png_image_write_control.convert_to_8bit],0
2727
	cmp dword[edx+png_image_write_control.convert_to_8bit],0
2728
	je .end9
2728
	je .end9
2729
	.end10: ;if ((..!=0 && ..!=0 ) || (..==0 && ..!=0))
2729
	.end10: ;if ((..!=0 && ..!=0 ) || (..==0 && ..!=0))
2730
		stdcall png_get_rowbytes, edi, esi
2730
		stdcall png_get_rowbytes, edi, esi
2731
		stdcall png_malloc, edi, eax
2731
		stdcall png_malloc, edi, eax
2732
		mov ecx,eax ;ecx = row
2732
		mov ecx,eax ;ecx = row
2733
		
2733
		
2734
		mov [edx+png_image_write_control.local_row],ecx
2734
		mov [edx+png_image_write_control.local_row],ecx
2735
		cmp dword[write_16bit],0
2735
		cmp dword[write_16bit],0
2736
		je @f ;if (..!=0)
2736
		je @f ;if (..!=0)
2737
			stdcall png_safe_execute, ebx, png_write_image_16bit, edx
2737
			stdcall png_safe_execute, ebx, png_write_image_16bit, edx
2738
			jmp .end11
2738
			jmp .end11
2739
		@@: ;else
2739
		@@: ;else
2740
			stdcall png_safe_execute, ebx, png_write_image_8bit, edx
2740
			stdcall png_safe_execute, ebx, png_write_image_8bit, edx
2741
		.end11:
2741
		.end11:
2742
		mov dword[edx+png_image_write_control.local_row],0
2742
		mov dword[edx+png_image_write_control.local_row],0
2743
 
2743
 
2744
		stdcall png_free, edi, ecx
2744
		stdcall png_free, edi, ecx
2745
 
2745
 
2746
		; Skip the 'write_end' on error:
2746
		; Skip the 'write_end' on error:
2747
		cmp eax,0
2747
		cmp eax,0
2748
		je .end_f ;if (..==0) return 0
2748
		je .end_f ;if (..==0) return 0
2749
		jmp .end8
2749
		jmp .end8
2750
 
2750
 
2751
	; Otherwise this is the case where the input is in a format currently
2751
	; Otherwise this is the case where the input is in a format currently
2752
	; supported by the rest of the libpng write code; call it directly.
2752
	; supported by the rest of the libpng write code; call it directly.
2753
 
2753
 
2754
	.end9: ;else
2754
	.end9: ;else
2755
if 1 ;;; IDAT compress all
2755
if 1 ;;; IDAT compress all
2756
		mov ecx,[edx+png_image_write_control.row_bytes]
2756
		mov ecx,[edx+png_image_write_control.row_bytes]
2757
		inc ecx
2757
		inc ecx
2758
		imul ecx,[ebx+png_image.height]
2758
		imul ecx,[ebx+png_image.height]
2759
		cmp ecx,1
2759
		cmp ecx,1
2760
		jl .end8
2760
		jl .end8
2761
		stdcall create_compress_IDAT, edi, [edx+png_image_write_control.first_row], ecx, [ebx+png_image.width], [ebx+png_image.height]
2761
		stdcall create_compress_IDAT, edi, [edx+png_image_write_control.first_row], ecx, [ebx+png_image.width], [ebx+png_image.height]
2762
else ;;; not work, IDAT compress by lines
2762
else ;;; not work, IDAT compress by lines
2763
		mov ecx,[ebx+png_image.height]
2763
		mov ecx,[ebx+png_image.height]
2764
		cmp ecx,1
2764
		cmp ecx,1
2765
		jl .end8
2765
		jl .end8
2766
		mov eax,[edx+png_image_write_control.first_row]
2766
		mov eax,[edx+png_image_write_control.first_row]
2767
		mov ebx,[edx+png_image_write_control.row_bytes]
2767
		mov ebx,[edx+png_image_write_control.row_bytes]
2768
		@@:
2768
		@@:
2769
			stdcall png_write_row, edi, eax
2769
			stdcall png_write_row, edi, eax
2770
			add eax, ebx
2770
			add eax, ebx
2771
			loop @b
2771
			loop @b
2772
end if
2772
end if
2773
	.end8:
2773
	.end8:
2774
 
2774
 
2775
	stdcall png_write_end, edi, esi
2775
	stdcall png_write_end, edi, esi
2776
	xor eax,eax
2776
	xor eax,eax
2777
	inc eax
2777
	inc eax
2778
.end_f:
2778
.end_f:
2779
	ret
2779
	ret
2780
endp
2780
endp
2781
 
2781
 
2782
align 16
2782
align 16
2783
proc create_compress_IDAT, png_ptr:dword, buf:dword, len:dword, width:dword, height:dword
2783
proc create_compress_IDAT, png_ptr:dword, buf:dword, len:dword, width:dword, height:dword
2784
locals
2784
locals
2785
	m1 dd ? ;memory for compress IDAT
2785
	m1 dd ? ;memory for compress IDAT
2786
	buf_f dd ? ;memory for IDAT
2786
	buf_f dd ? ;memory for IDAT
2787
	mins dd ? ;minimum sum
2787
	mins dd ? ;minimum sum
2788
endl
2788
endl
2789
pushad
2789
pushad
2790
	mov edi,[png_ptr]
2790
	mov edi,[png_ptr]
2791
png_debug 1, 'IDAT compress all'
2791
png_debug 1, 'IDAT compress all'
2792
 
2792
 
2793
	;create buffer with filters
2793
	;create buffer with filters
2794
	stdcall png_zalloc, edi, 1, [len]
2794
	stdcall png_zalloc, edi, 1, [len]
2795
	cmp eax,0
2795
	cmp eax,0
2796
	je .end_f
2796
	je .end_f
2797
	mov [buf_f],eax
2797
	mov [buf_f],eax
2798
 
2798
 
2799
	mov eax,ZLIB_IO_MAX
2799
	mov eax,ZLIB_IO_MAX
2800
	cmp eax,[len]
2800
	cmp eax,[len]
2801
	jge @f
2801
	jge @f
2802
		mov eax,[len]
2802
		mov eax,[len]
2803
	@@:
2803
	@@:
2804
	stdcall png_zalloc, edi, 1, eax
2804
	stdcall png_zalloc, edi, 1, eax
2805
	cmp eax,0
2805
	cmp eax,0
2806
	je .end0
2806
	je .end0
2807
	mov [m1],eax
2807
	mov [m1],eax
2808
 
2808
 
2809
	;init buffer with filters
2809
	;init buffer with filters
2810
	mov ebx,[width]
2810
	mov ebx,[width]
2811
	mov edx,[height]
2811
	mov edx,[height]
2812
	mov edi,[buf_f]
2812
	mov edi,[buf_f]
2813
	mov esi,[buf]
2813
	mov esi,[buf]
2814
	.cycle0:
2814
	.cycle0:
2815
	cmp edx,1
2815
	cmp edx,1
2816
	jl .cycle0end
2816
	jl .cycle0end
2817
		mov ecx,ebx
2817
		mov ecx,ebx
2818
		xor al,al
2818
		xor al,al
2819
		stosb ;insert filter (0 - none)
2819
		stosb ;insert filter (0 - none)
2820
align 4
2820
align 4
2821
		.cycle1:
2821
		.cycle1:
2822
			lodsb   ;1
2822
			lodsb   ;1
2823
			inc edi ;
2823
			inc edi ;
2824
			movsb   ;2
2824
			movsb   ;2
2825
			stosb   ;3
2825
			stosb   ;3
2826
			lodsb   ;
2826
			lodsb   ;
2827
			mov [edi-3],al
2827
			mov [edi-3],al
2828
			loop .cycle1
2828
			loop .cycle1
2829
		dec edx
2829
		dec edx
2830
		jmp .cycle0
2830
		jmp .cycle0
2831
	.cycle0end:
2831
	.cycle0end:
2832
 
2832
 
2833
	;make filters
2833
	;make filters
2834
	mov edx,[height]
2834
	mov edx,[height]
2835
	mov esi,[width]
2835
	mov esi,[width]
2836
	imul esi,3 ;esi - rowbytes
2836
	imul esi,3 ;esi - rowbytes
2837
 
2837
 
2838
	inc esi
2838
	inc esi
2839
	mov edi,[png_ptr]
2839
	mov edi,[png_ptr]
2840
	cmp dword[edi+png_struct.try_row],0
2840
	cmp dword[edi+png_struct.try_row],0
2841
	jne @f ;if (..==0)
2841
	jne @f ;if (..==0)
2842
		stdcall png_malloc, edi, esi
2842
		stdcall png_malloc, edi, esi
2843
		mov [edi+png_struct.try_row],eax
2843
		mov [edi+png_struct.try_row],eax
2844
	@@:
2844
	@@:
2845
	cmp dword[edi+png_struct.tst_row],0
2845
	cmp dword[edi+png_struct.tst_row],0
2846
	jne @f ;if (..==0)
2846
	jne @f ;if (..==0)
2847
		stdcall png_malloc, edi, esi
2847
		stdcall png_malloc, edi, esi
2848
		mov [edi+png_struct.tst_row],eax
2848
		mov [edi+png_struct.tst_row],eax
2849
	@@:
2849
	@@:
2850
	dec esi
2850
	dec esi
2851
 
2851
 
2852
	mov edi,[buf_f]
2852
	mov edi,[buf_f]
2853
	add edi,[len]
2853
	add edi,[len]
2854
	.cycle3:
2854
	.cycle3:
2855
		dec edx
2855
		dec edx
2856
		cmp edx,1
2856
		cmp edx,1
2857
		jl .cycle3end
2857
		jl .cycle3end
2858
		sub edi,esi
2858
		sub edi,esi
2859
		dec edi ;move in perv row
2859
		dec edi ;move in perv row
2860
 
2860
 
2861
		;init pointers for function png_setup_up_row
2861
		;init pointers for function png_setup_up_row
2862
		mov ebx,[png_ptr]
2862
		mov ebx,[png_ptr]
2863
		mov [ebx+png_struct.row_buf],edi
2863
		mov [ebx+png_struct.row_buf],edi
2864
		mov [ebx+png_struct.prev_row],edi
2864
		mov [ebx+png_struct.prev_row],edi
2865
		sub [ebx+png_struct.prev_row],esi
2865
		sub [ebx+png_struct.prev_row],esi
2866
		dec dword[ebx+png_struct.prev_row]
2866
		dec dword[ebx+png_struct.prev_row]
2867
 
2867
 
2868
		;calculate start minimum sum
2868
		;calculate start minimum sum
2869
		push esi
2869
		push esi
2870
		xor eax,eax
2870
		xor eax,eax
2871
		xor ebx,ebx
2871
		xor ebx,ebx
2872
		mov ecx,esi
2872
		mov ecx,esi
2873
		mov esi,edi
2873
		mov esi,edi
2874
		inc esi
2874
		inc esi
2875
		.cycle2:
2875
		.cycle2:
2876
			lodsb
2876
			lodsb
2877
			png_setup_abs ebx
2877
			png_setup_abs ebx
2878
			loop .cycle2
2878
			loop .cycle2
2879
		pop esi
2879
		pop esi
2880
		mov [mins],ebx
2880
		mov [mins],ebx
2881
 
2881
 
2882
		push edx
2882
		push edx
2883
		mov edx,[png_ptr]
2883
		mov edx,[png_ptr]
2884
		mov eax,[edx+png_struct.tst_row]
2884
		mov eax,[edx+png_struct.tst_row]
2885
		mov byte[eax],0 ;not filter
2885
		mov byte[eax],0 ;not filter
2886
 
2886
 
2887
		; Up filter
2887
		; Up filter
2888
		stdcall png_setup_up_row, edx, esi, [mins]
2888
		stdcall png_setup_up_row, edx, esi, [mins]
2889
		cmp eax,[mins]
2889
		cmp eax,[mins]
2890
		jge @f ;if (..<..)
2890
		jge @f ;if (..<..)
2891
			mov [mins],eax
2891
			mov [mins],eax
2892
			stdcall copy_row_mins, [edx+png_struct.tst_row], [edx+png_struct.try_row]
2892
			stdcall copy_row_mins, [edx+png_struct.tst_row], [edx+png_struct.try_row]
2893
		@@:
2893
		@@:
2894
 
2894
 
2895
		; Find out how many bytes offset each pixel is
2895
		; Find out how many bytes offset each pixel is
2896
		movzx ebx,byte[edx+png_struct.pixel_depth]
2896
		movzx ebx,byte[edx+png_struct.pixel_depth]
2897
		add ebx,7
2897
		add ebx,7
2898
		shr ebx,3
2898
		shr ebx,3
2899
 
2899
 
2900
		; Sub filter
2900
		; Sub filter
2901
		stdcall png_setup_sub_row, edx, ebx, esi, [mins]
2901
		stdcall png_setup_sub_row, edx, ebx, esi, [mins]
2902
		cmp eax,[mins]
2902
		cmp eax,[mins]
2903
		jge @f ;if (..<..)
2903
		jge @f ;if (..<..)
2904
			mov [mins],eax
2904
			mov [mins],eax
2905
			stdcall copy_row_mins, [edx+png_struct.tst_row], [edx+png_struct.try_row]
2905
			stdcall copy_row_mins, [edx+png_struct.tst_row], [edx+png_struct.try_row]
2906
		@@:
2906
		@@:
2907
 
2907
 
2908
		; Avg filter
2908
		; Avg filter
2909
		stdcall png_setup_avg_row, edx, ebx, esi, [mins]
2909
		stdcall png_setup_avg_row, edx, ebx, esi, [mins]
2910
		cmp eax,[mins]
2910
		cmp eax,[mins]
2911
		jge @f ;if (..<..)
2911
		jge @f ;if (..<..)
2912
			mov [mins],eax
2912
			mov [mins],eax
2913
			stdcall copy_row_mins, [edx+png_struct.tst_row], [edx+png_struct.try_row]
2913
			stdcall copy_row_mins, [edx+png_struct.tst_row], [edx+png_struct.try_row]
2914
		@@:
2914
		@@:
2915
 
2915
 
2916
		; Copy best row
2916
		; Copy best row
2917
		mov eax,[edx+png_struct.tst_row]
2917
		mov eax,[edx+png_struct.tst_row]
2918
		cmp byte[eax],0
2918
		cmp byte[eax],0
2919
		je @f
2919
		je @f
2920
			stdcall copy_row_mins, edi, [edx+png_struct.tst_row]
2920
			stdcall copy_row_mins, edi, [edx+png_struct.tst_row]
2921
		@@:
2921
		@@:
2922
		pop edx
2922
		pop edx
2923
		jmp .cycle3
2923
		jmp .cycle3
2924
	.cycle3end:
2924
	.cycle3end:
2925
	
2925
	
2926
	mov edi,[png_ptr]
2926
	mov edi,[png_ptr]
2927
	mov esi,edi
2927
	mov esi,edi
2928
	add esi,png_struct.zstream
2928
	add esi,png_struct.zstream
2929
	stdcall [deflateInit2], esi,\
2929
	stdcall [deflateInit2], esi,\
2930
		-1, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY
2930
		-1, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY
2931
 
2931
 
2932
	mov eax,[buf_f]
2932
	mov eax,[buf_f]
2933
	mov [edi+png_struct.zstream.next_in],eax
2933
	mov [edi+png_struct.zstream.next_in],eax
2934
	mov eax,[len]
2934
	mov eax,[len]
2935
	mov [edi+png_struct.zstream.avail_in],eax
2935
	mov [edi+png_struct.zstream.avail_in],eax
2936
	mov eax,[m1]
2936
	mov eax,[m1]
2937
	mov [edi+png_struct.zstream.next_out],eax
2937
	mov [edi+png_struct.zstream.next_out],eax
2938
	xor ecx,ecx
2938
	xor ecx,ecx
2939
align 4
2939
align 4
2940
	.cycle4:
2940
	.cycle4:
2941
		mov dword[edi+png_struct.zstream.avail_out],16*1024
2941
		mov dword[edi+png_struct.zstream.avail_out],16*1024
2942
 
2942
 
2943
		stdcall [deflate], esi, Z_NO_FLUSH
2943
		stdcall [deflate], esi, Z_FINISH ;Z_NO_FLUSH
2944
		cmp eax,Z_STREAM_ERROR
2944
		cmp eax,Z_STREAM_ERROR
2945
		je .end1
2945
		je .end1
2946
 
2946
 
2947
		add ecx,16*1024
2947
		add ecx,16*1024
2948
		sub ecx,[edi+png_struct.zstream.avail_out]
2948
		sub ecx,[edi+png_struct.zstream.avail_out]
2949
		cmp dword[edi+png_struct.zstream.avail_out],0
2949
		cmp dword[edi+png_struct.zstream.avail_out],0
2950
	je .cycle4 ;while (strm.avail_out == 0)
2950
	je .cycle4 ;while (strm.avail_out == 0)
2951
	mov dword[edi+png_struct.zstream.avail_out],16*1024
2951
if 0
-
 
2952
	mov dword[edi+png_struct.zstream.avail_out],16*1024
2952
	stdcall [deflate], esi, Z_FINISH
2953
	stdcall [deflate], esi, Z_FINISH
2953
	add ecx,16*1024
2954
	add ecx,16*1024
2954
	sub ecx,[edi+png_struct.zstream.avail_out]
2955
	sub ecx,[edi+png_struct.zstream.avail_out]
2955
	cmp eax,Z_STREAM_ERROR
2956
	cmp eax,Z_STREAM_ERROR
2956
	je .end1
2957
	je .end1
2957
 
2958
end if
2958
	stdcall [deflateEnd], esi
2959
	stdcall [deflateEnd], esi
2959
 
2960
 
2960
if PNG_WRITE_OPTIMIZE_CMF_SUPPORTED eq 1
2961
if PNG_WRITE_OPTIMIZE_CMF_SUPPORTED eq 1
2961
	mov eax,[edi+png_struct.mode]
2962
	mov eax,[edi+png_struct.mode]
2962
	and eax,PNG_HAVE_IDAT
2963
	and eax,PNG_HAVE_IDAT
2963
	jnz @f
2964
	jnz @f
2964
	cmp byte[edi+png_struct.compression_type],PNG_COMPRESSION_TYPE_BASE
2965
	cmp byte[edi+png_struct.compression_type],PNG_COMPRESSION_TYPE_BASE
2965
	jne @f ;if (..==0 && ..==..)
2966
	jne @f ;if (..==0 && ..==..)
2966
		stdcall png_image_size, edi
2967
		stdcall png_image_size, edi
2967
		stdcall optimize_cmf, [m1], eax
2968
		stdcall optimize_cmf, [m1], eax
2968
	@@:
2969
	@@:
2969
end if
2970
end if
2970
	stdcall png_write_complete_chunk, edi, png_IDAT, [m1], ecx
2971
	stdcall png_write_complete_chunk, edi, png_IDAT, [m1], ecx
2971
	or dword[edi+png_struct.mode],PNG_HAVE_IDAT
2972
	or dword[edi+png_struct.mode],PNG_HAVE_IDAT
2972
 
2973
 
2973
	jmp @f
2974
	jmp @f
2974
	.end1:
2975
	.end1:
2975
		png_debug 1, 'Z_STREAM_ERROR'
2976
		png_debug 1, 'Z_STREAM_ERROR'
2976
	@@:
2977
	@@:
2977
 
2978
 
2978
	;free memory
2979
	;free memory
2979
	cmp dword[edi+png_struct.try_row],0
2980
	cmp dword[edi+png_struct.try_row],0
2980
	je @f ;if (..!=0)
2981
	je @f ;if (..!=0)
2981
		stdcall png_free, edi, [edi+png_struct.try_row]
2982
		stdcall png_free, edi, [edi+png_struct.try_row]
2982
		mov dword[edi+png_struct.try_row],0
2983
		mov dword[edi+png_struct.try_row],0
2983
	@@:
2984
	@@:
2984
	cmp dword[edi+png_struct.tst_row],0
2985
	cmp dword[edi+png_struct.tst_row],0
2985
	je @f ;if (..!=0)
2986
	je @f ;if (..!=0)
2986
		stdcall png_free, edi, [edi+png_struct.tst_row]
2987
		stdcall png_free, edi, [edi+png_struct.tst_row]
2987
		mov dword[edi+png_struct.tst_row],0
2988
		mov dword[edi+png_struct.tst_row],0
2988
	@@:
2989
	@@:
2989
	stdcall png_free, edi, [m1]
2990
	stdcall png_free, edi, [m1]
2990
.end0:
2991
.end0:
2991
	stdcall png_free, edi, [buf_f]
2992
	stdcall png_free, edi, [buf_f]
2992
.end_f:
2993
.end_f:
2993
popad
2994
popad
2994
	ret
2995
	ret
2995
endp
2996
endp
2996
 
2997
 
2997
;input:
2998
;input:
2998
; esi - rowbytes
2999
; esi - rowbytes
2999
align 4
3000
align 4
3000
proc copy_row_mins uses edi esi, dest:dword, sour:dword
3001
proc copy_row_mins uses edi esi, dest:dword, sour:dword
3001
	mov ecx,esi
3002
	mov ecx,esi
3002
	inc ecx
3003
	inc ecx
3003
	mov edi,[dest]
3004
	mov edi,[dest]
3004
	mov esi,[sour]
3005
	mov esi,[sour]
3005
	rep movsb
3006
	rep movsb
3006
	ret
3007
	ret
3007
endp
3008
endp
3008
 
3009
 
3009
;void (png_structp png_ptr, bytep/*const*/ data, png_size_t size)
3010
;void (png_structp png_ptr, bytep/*const*/ data, png_size_t size)
3010
align 4
3011
align 4
3011
proc image_memory_write uses eax ebx ecx edi esi, png_ptr:dword, p2data:dword, size:dword
3012
proc image_memory_write uses eax ebx ecx edi esi, png_ptr:dword, p2data:dword, size:dword
3012
	mov edi,[png_ptr]
3013
	mov edi,[png_ptr]
3013
	mov esi,[edi+png_struct.io_ptr] ;esi = png_image_write_control *display
3014
	mov esi,[edi+png_struct.io_ptr] ;esi = png_image_write_control *display
3014
	mov ebx,[esi+png_image_write_control.output_bytes] ;ebx = ob
3015
	mov ebx,[esi+png_image_write_control.output_bytes] ;ebx = ob
3015
 
3016
 
3016
	; Check for overflow; this should never happen:
3017
	; Check for overflow; this should never happen:
3017
	mov eax,PNG_SIZE_MAX
3018
	mov eax,PNG_SIZE_MAX
3018
	sub eax,ebx
3019
	sub eax,ebx
3019
	mov ecx,[size]
3020
	mov ecx,[size]
3020
	cmp ecx,eax
3021
	cmp ecx,eax
3021
	jg .end1 ;if (..<=..)
3022
	jg .end1 ;if (..<=..)
3022
		; I don't think libpng ever does this, but just in case:
3023
		; I don't think libpng ever does this, but just in case:
3023
		cmp ecx,0
3024
		cmp ecx,0
3024
		jle .end0 ;if (..>0)
3025
		jle .end0 ;if (..>0)
3025
			mov eax,ebx
3026
			mov eax,ebx
3026
			add eax,ecx
3027
			add eax,ecx
3027
			cmp [esi+png_image_write_control.memory_bytes],eax
3028
			cmp [esi+png_image_write_control.memory_bytes],eax
3028
			jl @f ;if (..>=..) ;writing
3029
			jl @f ;if (..>=..) ;writing
3029
				push esi
3030
				push esi
3030
				mov edi,[esi+png_image_write_control.memory]
3031
				mov edi,[esi+png_image_write_control.memory]
3031
				add edi,ebx
3032
				add edi,ebx
3032
				mov esi,[p2data]
3033
				mov esi,[p2data]
3033
				rep movsb ;memcpy(...
3034
				rep movsb ;memcpy(...
3034
				pop esi
3035
				pop esi
3035
			@@:
3036
			@@:
3036
 
3037
 
3037
			; Always update the size:
3038
			; Always update the size:
3038
			add ebx,[size]
3039
			add ebx,[size]
3039
			mov [esi+png_image_write_control.output_bytes],ebx
3040
			mov [esi+png_image_write_control.output_bytes],ebx
3040
		.end0:
3041
		.end0:
3041
		jmp .end2
3042
		jmp .end2
3042
	.end1: ;else
3043
	.end1: ;else
3043
		png_error edi, 'png_image_write_to_memory: PNG too big'
3044
		png_error edi, 'png_image_write_to_memory: PNG too big'
3044
	.end2:
3045
	.end2:
3045
	ret
3046
	ret
3046
endp
3047
endp
3047
 
3048
 
3048
;void (png_structp png_ptr)
3049
;void (png_structp png_ptr)
3049
align 4
3050
align 4
3050
proc image_memory_flush, png_ptr:dword
3051
proc image_memory_flush, png_ptr:dword
3051
	ret
3052
	ret
3052
endp
3053
endp
3053
 
3054
 
3054
;int (voidp argument)
3055
;int (voidp argument)
3055
align 4
3056
align 4
3056
proc png_image_write_memory uses ebx, argument:dword
3057
proc png_image_write_memory uses ebx, argument:dword
3057
	; The rest of the memory-specific init and write_main in an error protected
3058
	; The rest of the memory-specific init and write_main in an error protected
3058
	; environment.  This case needs to use callbacks for the write operations
3059
	; environment.  This case needs to use callbacks for the write operations
3059
	; since libpng has no built in support for writing to memory.
3060
	; since libpng has no built in support for writing to memory.
3060
 
3061
 
3061
	mov eax,[argument]
3062
	mov eax,[argument]
3062
	mov ebx,[eax+png_image_write_control.image]
3063
	mov ebx,[eax+png_image_write_control.image]
3063
	mov ebx,[ebx+png_image.opaque]
3064
	mov ebx,[ebx+png_image.opaque]
3064
	stdcall png_set_write_fn, [ebx+png_control.png_ptr], eax, image_memory_write, image_memory_flush
3065
	stdcall png_set_write_fn, [ebx+png_control.png_ptr], eax, image_memory_write, image_memory_flush
3065
 
3066
 
3066
	stdcall png_image_write_main, [argument]
3067
	stdcall png_image_write_main, [argument]
3067
	ret
3068
	ret
3068
endp
3069
endp
3069
 
3070
 
3070
;int (png_imagep image, void *memory,
3071
;int (png_imagep image, void *memory,
3071
;    png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8bit,
3072
;    png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8bit,
3072
;    const void *buffer, int_32 row_stride, const void *colormap)
3073
;    const void *buffer, int_32 row_stride, const void *colormap)
3073
align 4
3074
align 4
3074
proc png_image_write_to_memory uses ebx ecx edx edi esi, image:dword, memory:dword,\
3075
proc png_image_write_to_memory uses ebx ecx edx edi esi, image:dword, memory:dword,\
3075
	memory_bytes:dword, convert_to_8bit:dword, buffer:dword, row_stride:dword, colormap:dword
3076
	memory_bytes:dword, convert_to_8bit:dword, buffer:dword, row_stride:dword, colormap:dword
3076
locals
3077
locals
3077
	display png_image_write_control ;local struct
3078
	display png_image_write_control ;local struct
3078
endl
3079
endl
3079
;edi - display png_image_write_control
3080
;edi - display png_image_write_control
3080
 
3081
 
3081
	; Write the image to the given buffer, or count the bytes if it is NULL
3082
	; Write the image to the given buffer, or count the bytes if it is NULL
3082
	mov ebx,[image]
3083
	mov ebx,[image]
3083
	cmp ebx,0
3084
	cmp ebx,0
3084
	je .end0
3085
	je .end0
3085
	cmp dword[ebx+png_image.version],PNG_IMAGE_VERSION
3086
	cmp dword[ebx+png_image.version],PNG_IMAGE_VERSION
3086
	jne .end0 ;if (..!=0 && ..==..)
3087
	jne .end0 ;if (..!=0 && ..==..)
3087
		cmp dword[memory_bytes],0
3088
		cmp dword[memory_bytes],0
3088
		je .end2
3089
		je .end2
3089
		cmp dword[buffer],0
3090
		cmp dword[buffer],0
3090
		je .end2 ;if (..!=0 && ..!=0)
3091
		je .end2 ;if (..!=0 && ..!=0)
3091
			; This is to give the caller an easier error detection in the NULL
3092
			; This is to give the caller an easier error detection in the NULL
3092
			; case and guard against uninitialized variable problems:
3093
			; case and guard against uninitialized variable problems:
3093
 
3094
 
3094
			cmp dword[memory],0
3095
			cmp dword[memory],0
3095
			jne @f ;if(..==0)
3096
			jne @f ;if(..==0)
3096
				mov eax,[memory_bytes]
3097
				mov eax,[memory_bytes]
3097
				mov dword[eax],0
3098
				mov dword[eax],0
3098
			@@:
3099
			@@:
3099
 
3100
 
3100
			stdcall png_image_write_init, ebx
3101
			stdcall png_image_write_init, ebx
3101
			cmp eax,0
3102
			cmp eax,0
3102
			je .end3 ;if (..!=0)
3103
			je .end3 ;if (..!=0)
3103
				mov ecx,sizeof.png_image_write_control
3104
				mov ecx,sizeof.png_image_write_control
3104
				mov edi,ebp
3105
				mov edi,ebp
3105
				sub edi,ecx
3106
				sub edi,ecx
3106
				xor eax,eax
3107
				xor eax,eax
3107
				rep stosb ;memset(&display, 0, sizeof.display))
3108
				rep stosb ;memset(&display, 0, sizeof.display))
3108
				sub edi,sizeof.png_image_write_control
3109
				sub edi,sizeof.png_image_write_control
3109
				mov [edi+png_image_write_control.image],ebx
3110
				mov [edi+png_image_write_control.image],ebx
3110
				mov eax,[buffer]
3111
				mov eax,[buffer]
3111
				mov [edi+png_image_write_control.buffer],eax
3112
				mov [edi+png_image_write_control.buffer],eax
3112
				mov eax,[row_stride]
3113
				mov eax,[row_stride]
3113
				mov [edi+png_image_write_control.row_stride],eax
3114
				mov [edi+png_image_write_control.row_stride],eax
3114
				mov eax,[colormap]
3115
				mov eax,[colormap]
3115
				mov [edi+png_image_write_control.colormap],eax
3116
				mov [edi+png_image_write_control.colormap],eax
3116
				mov eax,[convert_to_8bit]
3117
				mov eax,[convert_to_8bit]
3117
				mov [edi+png_image_write_control.convert_to_8bit],eax
3118
				mov [edi+png_image_write_control.convert_to_8bit],eax
3118
				mov eax,[memory]
3119
				mov eax,[memory]
3119
				mov [edi+png_image_write_control.memory],eax
3120
				mov [edi+png_image_write_control.memory],eax
3120
				mov eax,[memory_bytes]
3121
				mov eax,[memory_bytes]
3121
				mov eax,[eax]
3122
				mov eax,[eax]
3122
				mov [edi+png_image_write_control.memory_bytes],eax
3123
				mov [edi+png_image_write_control.memory_bytes],eax
3123
				mov dword[edi+png_image_write_control.output_bytes], 0
3124
				mov dword[edi+png_image_write_control.output_bytes], 0
3124
 
3125
 
3125
				stdcall png_safe_execute, ebx, png_image_write_memory, edi
3126
				stdcall png_safe_execute, ebx, png_image_write_memory, edi
3126
				mov ecx,eax ;ecx = result
3127
				mov ecx,eax ;ecx = result
3127
				stdcall png_image_free, ebx
3128
				stdcall png_image_free, ebx
3128
 
3129
 
3129
				; write_memory returns true even if we ran out of buffer.
3130
				; write_memory returns true even if we ran out of buffer.
3130
				cmp ecx,0 ;if (..)
3131
				cmp ecx,0 ;if (..)
3131
				je .end4
3132
				je .end4
3132
					; On out-of-buffer this function returns '0' but still updates
3133
					; On out-of-buffer this function returns '0' but still updates
3133
					; memory_bytes:
3134
					; memory_bytes:
3134
 
3135
 
3135
					mov edx,[edi+png_image_write_control.output_bytes]
3136
					mov edx,[edi+png_image_write_control.output_bytes]
3136
					mov eax,[memory_bytes]
3137
					mov eax,[memory_bytes]
3137
					cmp dword[memory],0
3138
					cmp dword[memory],0
3138
					je @f ;if (..!=0 && ..>..)
3139
					je @f ;if (..!=0 && ..>..)
3139
					cmp edx,[eax]
3140
					cmp edx,[eax]
3140
					jle @f
3141
					jle @f
3141
						xor ecx,ecx
3142
						xor ecx,ecx
3142
					@@:
3143
					@@:
3143
					mov [eax],edx
3144
					mov [eax],edx
3144
				.end4:
3145
				.end4:
3145
 
3146
 
3146
				mov eax,ecx
3147
				mov eax,ecx
3147
				jmp .end_f
3148
				jmp .end_f
3148
			.end3: ;else
3149
			.end3: ;else
3149
			xor eax,eax
3150
			xor eax,eax
3150
			jmp .end_f
3151
			jmp .end_f
3151
		.end2: ;else
3152
		.end2: ;else
3152
			std_png_image_error ebx, 'png_image_write_to_memory: invalid argument'
3153
			std_png_image_error ebx, 'png_image_write_to_memory: invalid argument'
3153
			jmp .end_f
3154
			jmp .end_f
3154
	.end0:
3155
	.end0:
3155
	cmp ebx,0
3156
	cmp ebx,0
3156
	je .end1 ;else if (..!=0)
3157
	je .end1 ;else if (..!=0)
3157
		std_png_image_error ebx, 'png_image_write_to_memory: incorrect PNG_IMAGE_VERSION'
3158
		std_png_image_error ebx, 'png_image_write_to_memory: incorrect PNG_IMAGE_VERSION'
3158
		jmp .end_f
3159
		jmp .end_f
3159
	.end1: ;else
3160
	.end1: ;else
3160
		xor eax,eax
3161
		xor eax,eax
3161
.end_f:
3162
.end_f:
3162
	ret
3163
	ret
3163
endp
3164
endp
3164
 
3165
 
3165
;int (png_imagep image, FILE *file, int convert_to_8bit,
3166
;int (png_imagep image, FILE *file, int convert_to_8bit,
3166
;    const void *buffer, int_32 row_stride, const void *colormap)
3167
;    const void *buffer, int_32 row_stride, const void *colormap)
3167
align 4
3168
align 4
3168
proc png_image_write_to_stdio, image:dword, file:dword, convert_to_8bit:dword, buffer:dword, row_stride:dword, colormap:dword
3169
proc png_image_write_to_stdio, image:dword, file:dword, convert_to_8bit:dword, buffer:dword, row_stride:dword, colormap:dword
3169
	; Write the image to the given (FILE*).
3170
	; Write the image to the given (FILE*).
3170
;   if (image != NULL && image->version == PNG_IMAGE_VERSION)
3171
;   if (image != NULL && image->version == PNG_IMAGE_VERSION)
3171
;   {
3172
;   {
3172
;      if (file != NULL && buffer != NULL)
3173
;      if (file != NULL && buffer != NULL)
3173
;      {
3174
;      {
3174
;         if (png_image_write_init(image) != 0)
3175
;         if (png_image_write_init(image) != 0)
3175
;         {
3176
;         {
3176
;            png_image_write_control display;
3177
;            png_image_write_control display;
3177
;            int result;
3178
;            int result;
3178
 
3179
 
3179
	; This is slightly evil, but png_init_io doesn't do anything other
3180
	; This is slightly evil, but png_init_io doesn't do anything other
3180
	; than this and we haven't changed the standard IO functions so
3181
	; than this and we haven't changed the standard IO functions so
3181
	; this saves a 'safe' function.
3182
	; this saves a 'safe' function.
3182
 
3183
 
3183
;            image->opaque->png_ptr->io_ptr = file;
3184
;            image->opaque->png_ptr->io_ptr = file;
3184
 
3185
 
3185
;            memset(&display, 0, (sizeof display));
3186
;            memset(&display, 0, (sizeof display));
3186
;            display.image = image;
3187
;            display.image = image;
3187
;            display.buffer = buffer;
3188
;            display.buffer = buffer;
3188
;            display.row_stride = row_stride;
3189
;            display.row_stride = row_stride;
3189
;            display.colormap = colormap;
3190
;            display.colormap = colormap;
3190
;            display.convert_to_8bit = convert_to_8bit;
3191
;            display.convert_to_8bit = convert_to_8bit;
3191
 
3192
 
3192
;            result = png_safe_execute(image, png_image_write_main, &display);
3193
;            result = png_safe_execute(image, png_image_write_main, &display);
3193
;            png_image_free(image);
3194
;            png_image_free(image);
3194
;            return result;
3195
;            return result;
3195
;         }
3196
;         }
3196
 
3197
 
3197
;         else
3198
;         else
3198
;            return 0;
3199
;            return 0;
3199
;      }
3200
;      }
3200
 
3201
 
3201
;      else
3202
;      else
3202
;         return png_image_error(image,
3203
;         return png_image_error(image,
3203
;             "png_image_write_to_stdio: invalid argument");
3204
;             "png_image_write_to_stdio: invalid argument");
3204
;   }
3205
;   }
3205
 
3206
 
3206
;   else if (image != NULL)
3207
;   else if (image != NULL)
3207
;      return png_image_error(image,
3208
;      return png_image_error(image,
3208
;          "png_image_write_to_stdio: incorrect PNG_IMAGE_VERSION");
3209
;          "png_image_write_to_stdio: incorrect PNG_IMAGE_VERSION");
3209
 
3210
 
3210
;   else
3211
;   else
3211
;      return 0;
3212
;      return 0;
3212
	ret
3213
	ret
3213
endp
3214
endp
3214
 
3215
 
3215
;int (png_imagep image, const char *file_name,
3216
;int (png_imagep image, const char *file_name,
3216
;    int convert_to_8bit, const void *buffer, int_32 row_stride,
3217
;    int convert_to_8bit, const void *buffer, int_32 row_stride,
3217
;    const void *colormap)
3218
;    const void *colormap)
3218
align 4
3219
align 4
3219
proc png_image_write_to_file, image:dword, file_name:dword, convert_to_8bit:dword, buffer:dword, row_stride:dword, colormap:dword
3220
proc png_image_write_to_file, image:dword, file_name:dword, convert_to_8bit:dword, buffer:dword, row_stride:dword, colormap:dword
3220
	; Write the image to the named file.
3221
	; Write the image to the named file.
3221
;   if (image != NULL && image->version == PNG_IMAGE_VERSION)
3222
;   if (image != NULL && image->version == PNG_IMAGE_VERSION)
3222
;   {
3223
;   {
3223
;      if (file_name != NULL && buffer != NULL)
3224
;      if (file_name != NULL && buffer != NULL)
3224
;      {
3225
;      {
3225
;         FILE *fp = fopen(file_name, "wb");
3226
;         FILE *fp = fopen(file_name, "wb");
3226
 
3227
 
3227
;         if (fp != NULL)
3228
;         if (fp != NULL)
3228
;         {
3229
;         {
3229
;            if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer,
3230
;            if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer,
3230
;                row_stride, colormap) != 0)
3231
;                row_stride, colormap) != 0)
3231
;            {
3232
;            {
3232
;               int error; /* from fflush/fclose */
3233
;               int error; /* from fflush/fclose */
3233
 
3234
 
3234
	; Make sure the file is flushed correctly.
3235
	; Make sure the file is flushed correctly.
3235
;               if (fflush(fp) == 0 && ferror(fp) == 0)
3236
;               if (fflush(fp) == 0 && ferror(fp) == 0)
3236
;               {
3237
;               {
3237
;                  if (fclose(fp) == 0)
3238
;                  if (fclose(fp) == 0)
3238
;                     return 1;
3239
;                     return 1;
3239
 
3240
 
3240
;                  error = errno; /* from fclose */
3241
;                  error = errno; /* from fclose */
3241
;               }
3242
;               }
3242
 
3243
 
3243
;               else
3244
;               else
3244
;               {
3245
;               {
3245
;                  error = errno; /* from fflush or ferror */
3246
;                  error = errno; /* from fflush or ferror */
3246
;                  (void)fclose(fp);
3247
;                  (void)fclose(fp);
3247
;               }
3248
;               }
3248
 
3249
 
3249
;               (void)remove(file_name);
3250
;               (void)remove(file_name);
3250
	; The image has already been cleaned up; this is just used to
3251
	; The image has already been cleaned up; this is just used to
3251
	; set the error (because the original write succeeded).
3252
	; set the error (because the original write succeeded).
3252
 
3253
 
3253
;               return png_image_error(image, strerror(error));
3254
;               return png_image_error(image, strerror(error));
3254
;            }
3255
;            }
3255
 
3256
 
3256
;            else
3257
;            else
3257
;            {
3258
;            {
3258
	; Clean up: just the opened file.
3259
	; Clean up: just the opened file.
3259
;               (void)fclose(fp);
3260
;               (void)fclose(fp);
3260
;               (void)remove(file_name);
3261
;               (void)remove(file_name);
3261
;               return 0;
3262
;               return 0;
3262
;            }
3263
;            }
3263
;         }
3264
;         }
3264
 
3265
 
3265
;         else
3266
;         else
3266
;            return png_image_error(image, strerror(errno));
3267
;            return png_image_error(image, strerror(errno));
3267
;      }
3268
;      }
3268
 
3269
 
3269
;      else
3270
;      else
3270
;         return png_image_error(image,
3271
;         return png_image_error(image,
3271
;             "png_image_write_to_file: invalid argument");
3272
;             "png_image_write_to_file: invalid argument");
3272
;   }
3273
;   }
3273
 
3274
 
3274
;   else if (image != NULL)
3275
;   else if (image != NULL)
3275
;      return png_image_error(image,
3276
;      return png_image_error(image,
3276
;          "png_image_write_to_file: incorrect PNG_IMAGE_VERSION");
3277
;          "png_image_write_to_file: incorrect PNG_IMAGE_VERSION");
3277
 
3278
 
3278
;   else
3279
;   else
3279
;      return 0;
3280
;      return 0;
3280
	ret
3281
	ret
3281
endp
3282
endp
3282
end if ;SIMPLIFIED_WRITE
3283
end if ;SIMPLIFIED_WRITE
3283
>
3284
>
3284
>
3285
>
3285
>
3286
>
3286
>
3287
>
3287
>
3288
>
3288
>
3289
>
3289
>
3290
>
3290
>
3291
>
3291
>
3292
>
3292
>
3293
>
3293
>
3294
>
3294
>
3295
>
3295
>
3296
>
3296
>
3297
>
3297
>
3298
>