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