Subversion Repositories Kolibri OS

Rev

Rev 6870 | Rev 6881 | 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
	cmp eax,0
634
	je .end0 ;if (..!=0)
635
		; Set the zlib control values to defaults; they can be overridden by the
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
 
1842
	je .end0 ;if (..!=0)
1843
		mov edi,eax
1844
		stdcall png_create_info_struct, edi
1845
		;eax = info_ptr
1846
1847
 
1848
		je .end1 ;if (..!=0)
1849
			mov esi,eax
1850
			stdcall png_malloc_warn, edi, sizeof.png_control
1851
			;control = eax
1852
1853
 
1854
			je .end2 ;if (..!=0)
1855
				push eax
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
		cmp eax,0
2748
		je .end_f ;if (..==0) return 0
2749
		jmp .end8
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 ;;; not work, IDAT compress by lines
2763
		mov ecx,[ebx+png_image.height]
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
	cmp eax,0
2796
	je .end_f
2797
	mov [buf_f],eax
2798
2799
 
2800
	cmp eax,[len]
2801
	jge @f
2802
		mov eax,[len]
2803
	@@:
2804
	stdcall png_zalloc, edi, 1, eax
2805
	cmp eax,0
2806
	je .end0
2807
	mov [m1],eax
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
 
2917
		mov eax,[edx+png_struct.tst_row]
2918
		cmp byte[eax],0
2919
		je @f
2920
			stdcall copy_row_mins, edi, [edx+png_struct.tst_row]
2921
		@@:
2922
		pop edx
2923
		jmp .cycle3
6733 IgorA 2924
	.cycle3end:
2925
2926
 
2927
	mov esi,edi
2928
	add esi,png_struct.zstream
2929
	stdcall [deflateInit2], esi,\
2930
		-1, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY
2931
2932
 
2933
	mov [edi+png_struct.zstream.next_in],eax
2934
	mov eax,[len]
2935
	mov [edi+png_struct.zstream.avail_in],eax
2936
	mov eax,[m1]
2937
	mov [edi+png_struct.zstream.next_out],eax
2938
	xor ecx,ecx
2939
align 4
2940
	.cycle4:
2941
		mov dword[edi+png_struct.zstream.avail_out],16*1024
6797 IgorA 2942
6733 IgorA 2943
 
6873 IgorA 2944
		cmp eax,Z_STREAM_ERROR
6733 IgorA 2945
		je .end1
2946
2947
 
2948
		sub ecx,[edi+png_struct.zstream.avail_out]
6797 IgorA 2949
		cmp dword[edi+png_struct.zstream.avail_out],0
2950
	je .cycle4 ;while (strm.avail_out == 0)
6733 IgorA 2951
if 0
6873 IgorA 2952
	mov dword[edi+png_struct.zstream.avail_out],16*1024
6797 IgorA 2953
	stdcall [deflate], esi, Z_FINISH
6733 IgorA 2954
	add ecx,16*1024
6870 IgorA 2955
	sub ecx,[edi+png_struct.zstream.avail_out]
2956
	cmp eax,Z_STREAM_ERROR
6733 IgorA 2957
	je .end1
2958
end if
6873 IgorA 2959
	stdcall [deflateEnd], esi
6733 IgorA 2960
2961
 
2962
	mov eax,[edi+png_struct.mode]
2963
	and eax,PNG_HAVE_IDAT
2964
	jnz @f
6779 IgorA 2965
	cmp byte[edi+png_struct.compression_type],PNG_COMPRESSION_TYPE_BASE
6733 IgorA 2966
	jne @f ;if (..==0 && ..==..)
2967
		stdcall png_image_size, edi
2968
		stdcall optimize_cmf, [m1], eax
2969
	@@:
2970
end if
2971
	stdcall png_write_complete_chunk, edi, png_IDAT, [m1], ecx
2972
	or dword[edi+png_struct.mode],PNG_HAVE_IDAT
2973
2974
 
2975
	.end1:
2976
		png_debug 1, 'Z_STREAM_ERROR'
2977
	@@:
2978
2979
 
2980
	cmp dword[edi+png_struct.try_row],0
2981
	je @f ;if (..!=0)
2982
		stdcall png_free, edi, [edi+png_struct.try_row]
2983
		mov dword[edi+png_struct.try_row],0
2984
	@@:
2985
	cmp dword[edi+png_struct.tst_row],0
6779 IgorA 2986
	je @f ;if (..!=0)
2987
		stdcall png_free, edi, [edi+png_struct.tst_row]
2988
		mov dword[edi+png_struct.tst_row],0
2989
	@@:
2990
	stdcall png_free, edi, [m1]
6733 IgorA 2991
.end0:
2992
	stdcall png_free, edi, [buf_f]
2993
.end_f:
2994
popad
2995
	ret
2996
endp
2997
2998
 
6779 IgorA 2999
; esi - rowbytes
3000
align 4
3001
proc copy_row_mins uses edi esi, dest:dword, sour:dword
3002
	mov ecx,esi
3003
	inc ecx
3004
	mov edi,[dest]
3005
	mov esi,[sour]
3006
	rep movsb
3007
	ret
3008
endp
3009
3010
 
6733 IgorA 3011
align 4
3012
proc image_memory_write uses eax ebx ecx edi esi, png_ptr:dword, p2data:dword, size:dword
3013
	mov edi,[png_ptr]
3014
	mov esi,[edi+png_struct.io_ptr] ;esi = png_image_write_control *display
3015
	mov ebx,[esi+png_image_write_control.output_bytes] ;ebx = ob
3016
3017
 
3018
	mov eax,PNG_SIZE_MAX
3019
	sub eax,ebx
3020
	mov ecx,[size]
3021
	cmp ecx,eax
3022
	jg .end1 ;if (..<=..)
3023
		; I don't think libpng ever does this, but just in case:
3024
		cmp ecx,0
3025
		jle .end0 ;if (..>0)
3026
			mov eax,ebx
3027
			add eax,ecx
3028
			cmp [esi+png_image_write_control.memory_bytes],eax
3029
			jl @f ;if (..>=..) ;writing
3030
				push esi
3031
				mov edi,[esi+png_image_write_control.memory]
3032
				add edi,ebx
3033
				mov esi,[p2data]
3034
				rep movsb ;memcpy(...
3035
				pop esi
3036
			@@:
3037
3038
 
3039
			add ebx,[size]
3040
			mov [esi+png_image_write_control.output_bytes],ebx
3041
		.end0:
3042
		jmp .end2
3043
	.end1: ;else
3044
		png_error edi, 'png_image_write_to_memory: PNG too big'
3045
	.end2:
3046
	ret
3047
endp
3048
3049
 
3050
align 4
3051
proc image_memory_flush, png_ptr:dword
3052
	ret
3053
endp
3054
3055
 
3056
align 4
3057
proc png_image_write_memory uses ebx, argument:dword
3058
	; The rest of the memory-specific init and write_main in an error protected
3059
	; environment.  This case needs to use callbacks for the write operations
3060
	; since libpng has no built in support for writing to memory.
3061
3062
 
3063
	mov ebx,[eax+png_image_write_control.image]
3064
	mov ebx,[ebx+png_image.opaque]
3065
	stdcall png_set_write_fn, [ebx+png_control.png_ptr], eax, image_memory_write, image_memory_flush
3066
3067
 
3068
	ret
3069
endp
3070
3071
 
3072
;    png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8bit,
3073
;    const void *buffer, int_32 row_stride, const void *colormap)
3074
align 4
3075
proc png_image_write_to_memory uses ebx ecx edx edi esi, image:dword, memory:dword,\
3076
	memory_bytes:dword, convert_to_8bit:dword, buffer:dword, row_stride:dword, colormap:dword
3077
locals
3078
	display png_image_write_control ;local struct
3079
endl
3080
;edi - display png_image_write_control
3081
3082
 
3083
	mov ebx,[image]
3084
	cmp ebx,0
3085
	je .end0
3086
	cmp dword[ebx+png_image.version],PNG_IMAGE_VERSION
3087
	jne .end0 ;if (..!=0 && ..==..)
3088
		cmp dword[memory_bytes],0
3089
		je .end2
3090
		cmp dword[buffer],0
3091
		je .end2 ;if (..!=0 && ..!=0)
3092
			; This is to give the caller an easier error detection in the NULL
3093
			; case and guard against uninitialized variable problems:
3094
3095
 
3096
			jne @f ;if(..==0)
3097
				mov eax,[memory_bytes]
3098
				mov dword[eax],0
3099
			@@:
3100
3101
 
3102
			cmp eax,0
3103
			je .end3 ;if (..!=0)
3104
				mov ecx,sizeof.png_image_write_control
3105
				mov edi,ebp
3106
				sub edi,ecx
3107
				xor eax,eax
3108
				rep stosb ;memset(&display, 0, sizeof.display))
3109
				sub edi,sizeof.png_image_write_control
3110
				mov [edi+png_image_write_control.image],ebx
3111
				mov eax,[buffer]
3112
				mov [edi+png_image_write_control.buffer],eax
3113
				mov eax,[row_stride]
3114
				mov [edi+png_image_write_control.row_stride],eax
3115
				mov eax,[colormap]
3116
				mov [edi+png_image_write_control.colormap],eax
3117
				mov eax,[convert_to_8bit]
3118
				mov [edi+png_image_write_control.convert_to_8bit],eax
3119
				mov eax,[memory]
3120
				mov [edi+png_image_write_control.memory],eax
3121
				mov eax,[memory_bytes]
3122
				mov eax,[eax]
3123
				mov [edi+png_image_write_control.memory_bytes],eax
3124
				mov dword[edi+png_image_write_control.output_bytes], 0
3125
3126
 
3127
				mov ecx,eax ;ecx = result
3128
				stdcall png_image_free, ebx
3129
3130
 
3131
				cmp ecx,0 ;if (..)
3132
				je .end4
3133
					; On out-of-buffer this function returns '0' but still updates
3134
					; memory_bytes:
3135
3136
 
3137
					mov eax,[memory_bytes]
3138
					cmp dword[memory],0
3139
					je @f ;if (..!=0 && ..>..)
3140
					cmp edx,[eax]
3141
					jle @f
3142
						xor ecx,ecx
3143
					@@:
3144
					mov [eax],edx
3145
				.end4:
3146
3147
 
3148
				jmp .end_f
3149
			.end3: ;else
3150
			xor eax,eax
3151
			jmp .end_f
3152
		.end2: ;else
3153
			std_png_image_error ebx, 'png_image_write_to_memory: invalid argument'
3154
			jmp .end_f
3155
	.end0:
3156
	cmp ebx,0
3157
	je .end1 ;else if (..!=0)
3158
		std_png_image_error ebx, 'png_image_write_to_memory: incorrect PNG_IMAGE_VERSION'
3159
		jmp .end_f
3160
	.end1: ;else
3161
		xor eax,eax
3162
.end_f:
3163
	ret
3164
endp
3165
3166
 
3167
;    const void *buffer, int_32 row_stride, const void *colormap)
3168
align 4
3169
proc png_image_write_to_stdio, image:dword, file:dword, convert_to_8bit:dword, buffer:dword, row_stride:dword, colormap:dword
3170
	; Write the image to the given (FILE*).
3171
;   if (image != NULL && image->version == PNG_IMAGE_VERSION)
3172
;   {
3173
;      if (file != NULL && buffer != NULL)
3174
;      {
3175
;         if (png_image_write_init(image) != 0)
3176
;         {
3177
;            png_image_write_control display;
3178
;            int result;
3179
3180
 
3181
	; than this and we haven't changed the standard IO functions so
3182
	; this saves a 'safe' function.
3183
3184
 
3185
3186
 
3187
;            display.image = image;
3188
;            display.buffer = buffer;
3189
;            display.row_stride = row_stride;
3190
;            display.colormap = colormap;
3191
;            display.convert_to_8bit = convert_to_8bit;
3192
3193
 
3194
;            png_image_free(image);
3195
;            return result;
3196
;         }
3197
3198
 
3199
;            return 0;
3200
;      }
3201
3202
 
3203
;         return png_image_error(image,
3204
;             "png_image_write_to_stdio: invalid argument");
3205
;   }
3206
3207
 
3208
;      return png_image_error(image,
3209
;          "png_image_write_to_stdio: incorrect PNG_IMAGE_VERSION");
3210
3211
 
3212
;      return 0;
3213
	ret
3214
endp
3215
3216
 
3217
;    int convert_to_8bit, const void *buffer, int_32 row_stride,
3218
;    const void *colormap)
3219
align 4
3220
proc png_image_write_to_file, image:dword, file_name:dword, convert_to_8bit:dword, buffer:dword, row_stride:dword, colormap:dword
3221
	; Write the image to the named file.
3222
;   if (image != NULL && image->version == PNG_IMAGE_VERSION)
3223
;   {
3224
;      if (file_name != NULL && buffer != NULL)
3225
;      {
3226
;         FILE *fp = fopen(file_name, "wb");
3227
3228
 
3229
;         {
3230
;            if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer,
3231
;                row_stride, colormap) != 0)
3232
;            {
3233
;               int error; /* from fflush/fclose */
3234
3235
 
3236
;               if (fflush(fp) == 0 && ferror(fp) == 0)
3237
;               {
3238
;                  if (fclose(fp) == 0)
3239
;                     return 1;
3240
3241
 
3242
;               }
3243
3244
 
3245
;               {
3246
;                  error = errno; /* from fflush or ferror */
3247
;                  (void)fclose(fp);
3248
;               }
3249
3250
 
3251
	; The image has already been cleaned up; this is just used to
3252
	; set the error (because the original write succeeded).
3253
3254
 
3255
;            }
3256
3257
 
3258
;            {
3259
	; Clean up: just the opened file.
3260
;               (void)fclose(fp);
3261
;               (void)remove(file_name);
3262
;               return 0;
3263
;            }
3264
;         }
3265
3266
 
3267
;            return png_image_error(image, strerror(errno));
3268
;      }
3269
3270
 
3271
;         return png_image_error(image,
3272
;             "png_image_write_to_file: invalid argument");
3273
;   }
3274
3275
 
3276
;      return png_image_error(image,
3277
;          "png_image_write_to_file: incorrect PNG_IMAGE_VERSION");
3278
3279
 
3280
;      return 0;
3281
	ret
3282
endp
3283
end if ;SIMPLIFIED_WRITE
3284
>