Subversion Repositories Kolibri OS

Rev

Rev 6888 | Rev 7279 | 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
		or dword[eax+png_struct.transformations],PNG_BGR ;transformation rgb for KoliriOS
6891 IgorA 1845
		stdcall png_create_info_struct, edi
6733 IgorA 1846
		;eax = info_ptr
1847
1848
 
6881 IgorA 1849
		jz .end1 ;if (..!=0)
1850
			mov esi,eax
6733 IgorA 1851
			stdcall png_malloc_warn, edi, sizeof.png_control
1852
			;control = eax
1853
1854
 
6881 IgorA 1855
			jz .end2 ;if (..!=0)
1856
				push eax
6733 IgorA 1857
				mov edx,edi ; edx = png_ptr
1858
				mov ecx,sizeof.png_control
1859
				mov edi,eax
1860
				xor eax,eax
1861
				rep stosb ;memset(control, 0, (sizeof.control))
1862
				pop eax
1863
1864
 
1865
				mov [eax+png_control.info_ptr], esi
1866
				mov [eax+png_control.for_write], 1
1867
1868
 
1869
				xor eax,eax
1870
				inc eax
1871
				jmp .end_f
1872
			.end2:
1873
1874
 
1875
			push esi
1876
			mov esi,esp
1877
			stdcall png_destroy_info_struct, edi, esi
1878
			add esp,4
1879
		.end1:
1880
1881
 
1882
		mov edi,esp
1883
		stdcall png_destroy_write_struct, edi, 0
1884
		add esp,4
1885
	.end0:
1886
1887
 
1888
.end_f:
1889
	ret
1890
endp
1891
1892
 
1893
struct png_image_write_control
1894
	; Arguments:
1895
	image  dd ? ;png_imagep
1896
	buffer dd ? ;png_const_voidp
1897
	row_stride dd ? ;int_32
1898
	colormap   dd ? ;png_const_voidp
1899
	convert_to_8bit dd ? ;int
1900
	; Local variables:
1901
	first_row dd ? ;png_const_voidp
1902
	row_bytes dd ? ;ptrdiff_t
1903
	local_row dd ? ;voidp
1904
	; Byte count for memory writing
1905
	memory    dd ? ;bytep
1906
	memory_bytes dd ? ;png_alloc_size_t ;not used for STDIO
1907
	output_bytes dd ? ;png_alloc_size_t ;running total
1908
ends
1909
1910
 
1911
; do any necessary byte swapping.  The component order is defined by the
1912
; png_image format value.
1913
1914
 
1915
align 4
1916
proc png_write_image_16bit uses ebx ecx edx, argument:dword
1917
locals
1918
	display dd ? ;png_image_write_control* ;= argument
1919
	image   dd ? ;png_imagep ;= display->image
1920
	png_ptr dd ? ;png_structrp ;= image->opaque->png_ptr
1921
	input_row  dd ? ;const_uint_16p ;= display->first_row
1922
	output_row dd ? ;uint_16p ;= display->local_row
1923
	row_end  dd ? ;uint_16p
1924
	channels dd ? ;const int ;= (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1;
1925
	aindex   dd 0 ;int  ;= 0
1926
	y dd ? ;uint_32 ;= image->height
1927
endl
1928
	mov ebx,[argument]
1929
	mov [display],ebx
1930
	mov edx,[ebx+png_image_write_control.image]
1931
	mov [image],edx
1932
	mov ecx,[edx+png_image.opaque]
1933
	mov ecx,[ecx+png_control.png_ptr]
1934
	mov [png_ptr],ecx
1935
	mov ecx,[ebx+png_image_write_control.first_row]
1936
	mov [input_row],ecx
1937
	mov ecx,[ebx+png_image_write_control.local_row]
1938
	mov [output_row],ecx
1939
1940
 
6779 IgorA 1941
	mov eax,[edx+png_image.format]
6733 IgorA 1942
	and eax,PNG_FORMAT_FLAG_COLOR
1943
	jz @f
6779 IgorA 1944
		mov ecx,3
6733 IgorA 1945
	@@:
1946
	mov [channels],ecx
1947
	mov eax,[edx+png_image.height]
1948
	mov [y],eax
1949
1950
 
1951
	and eax,PNG_FORMAT_FLAG_ALPHA
1952
	jz .end0 ;if (..!=0)
6779 IgorA 1953
if PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED eq 1
6733 IgorA 1954
	mov eax,[edx+png_image.format]
1955
	and eax,PNG_FORMAT_FLAG_AFIRST
1956
	jz @f ;if (..!=0)
6779 IgorA 1957
		mov dword[aindex],-1
6733 IgorA 1958
		inc dword[input_row] ;To point to the first component
1959
		inc dword[output_row]
1960
		jmp .end1
1961
	@@: ;else
1962
end if
1963
		mov eax,[channels]
1964
		mov [aindex],eax
1965
		jmp .end1
1966
	.end0: ;else
1967
		png_error [png_ptr], 'png_write_image: internal call error'
1968
	.end1:
1969
1970
 
1971
	; above to 'row' means that row_end can actually be beyond the end of the
1972
	; row; this is correct.
1973
1974
 
1975
	inc eax
1976
	imul eax,[edx+png_image.width]
1977
	add eax,[output_row]
1978
	mov [row_end],eax
1979
1980
 
1981
;   {
1982
;      const_uint_16p in_ptr = input_row;
1983
;      uint_16p out_ptr = output_row;
1984
1985
 
1986
;      {
1987
;         const uint_16 alpha = in_ptr[aindex];
1988
;         uint_32 reciprocal = 0;
1989
;         int c;
1990
1991
 
1992
1993
 
1994
	; component/alpha*65535 << 15. (I.e. 15 bits of precision); this
1995
	; allows correct rounding by adding .5 before the shift.  'reciprocal'
1996
	; is only initialized when required.
1997
1998
 
1999
;            reciprocal = ((0xffff<<15)+(alpha>>1))/alpha;
2000
2001
 
2002
;         do /* always at least one channel */
2003
;         {
2004
;            uint_16 component = *in_ptr++;
2005
2006
 
2007
	; otherwise if 0/0 is represented as some other value there is more
2008
	; likely to be a discontinuity which will probably damage
2009
	; compression when moving from a fully transparent area to a
2010
	; nearly transparent one.  (The assumption here is that opaque
2011
	; areas tend not to be 0 intensity.)
2012
2013
 
2014
;               component = 65535;
2015
2016
 
2017
	; component*reciprocal is less than 2^31.
2018
2019
 
2020
;            {
2021
;               uint_32 calc = component * reciprocal;
2022
;               calc += 16384; /* round to nearest */
2023
;               component = (uint_16)(calc >> 15);
2024
;            }
2025
2026
 
2027
;         }
2028
;         while (--c > 0);
2029
2030
 
2031
;         ++in_ptr;
2032
;         ++out_ptr;
2033
;      }
2034
2035
 
2036
;      input_row += display->row_bytes/(sizeof (uint_16));
2037
;   }
2038
2039
 
2040
	inc eax ;return 1
2041
	ret
2042
endp
2043
2044
 
2045
; is present it must be removed from the components, the components are then
2046
; written in sRGB encoding.  No components are added or removed.
2047
2048
 
2049
; calculation can be done to 15 bits of accuracy; however, the output needs to
2050
; be scaled in the range 0..255*65535, so include that scaling here.
2051
2052
 
2053
2054
 
2055
align 4
2056
proc png_unpremultiply, component:dword, alpha:dword, reciprocal:dword
2057
	; The following gives 1.0 for an alpha of 0, which is fine, otherwise if 0/0
2058
	; is represented as some other value there is more likely to be a
2059
	; discontinuity which will probably damage compression when moving from a
2060
	; fully transparent area to a nearly transparent one.  (The assumption here
2061
	; is that opaque areas tend not to be 0 intensity.)
2062
2063
 
2064
	; as 0 when scaled to 8 bits.  To avoid introducing spurious colors into the
2065
	; output change for this too.
2066
2067
 
2068
	cmp [component],eax
2069
	jge @f
2070
	cmp eax,128
2071
	jge .end0
2072
	@@: ;if (..>=.. || ..<..)
2073
		mov eax,255
2074
		jmp .end_f
2075
		; component
2076
		; component*reciprocal is less than 2^31.
2077
2078
 
2079
	cmp dword[component],0
2080
	jle .end1
2081
		; The test is that alpha/257 (rounded) is less than 255, the first value
2082
		; that becomes 255 is 65407.
2083
		; NOTE: this must agree with the PNG_DIV257 macro (which must, therefore,
2084
		; be exact!)  [Could also test reciprocal != 0]
2085
2086
 
2087
;      {
2088
;         component *= reciprocal;
2089
;         component += 64; /* round to nearest */
2090
;         component >>= 7;
2091
;      }
2092
2093
 
2094
;         component *= 255;
2095
2096
 
2097
		PNG_sRGB_FROM_LINEAR [component]
2098
		and eax,0xff
2099
		jmp .end_f
2100
	.end1: ;else
2101
		xor eax,eax
2102
.end_f:
2103
	ret
2104
endp
2105
2106
 
2107
align 4
2108
proc png_write_image_8bit uses ebx ecx edx edi esi, argument:dword
2109
locals
2110
	display dd ? ;png_image_write_control* ;= argument
2111
	image   dd ? ;png_imagep ;= display->image
2112
	png_ptr dd ? ;png_structrp ;= image->opaque->png_ptr
2113
	input_row  dd ? ;const_uint_16p ;= display->first_row
2114
	output_row dd ? ;uint_16p ;= display->local_row
2115
	row_end  dd ? ;uint_16p
2116
	channels dd ? ;const int ;= (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1;
2117
	aindex   dd 0 ;int  ;= 0
2118
	y dd ? ;uint_32 ;= image->height
2119
	component dd ? ;uint_32
2120
endl
2121
	mov ebx,[argument]
2122
	mov [display],ebx
2123
	mov edx,[ebx+png_image_write_control.image]
2124
	mov [image],edx
2125
	mov ecx,[edx+png_image.opaque]
2126
	mov ecx,[ecx+png_control.png_ptr]
2127
	mov [png_ptr],ecx
2128
	mov ecx,[ebx+png_image_write_control.first_row]
2129
	mov [input_row],ecx
2130
	mov ecx,[ebx+png_image_write_control.local_row]
2131
	mov [output_row],ecx
2132
2133
 
6779 IgorA 2134
	mov eax,[edx+png_image.format]
6733 IgorA 2135
	and eax,PNG_FORMAT_FLAG_COLOR
2136
	jz @f
6779 IgorA 2137
		mov ecx,3
6733 IgorA 2138
	@@:
2139
	mov [channels],ecx
2140
	mov eax,[edx+png_image.height]
2141
	mov [y],eax
2142
2143
 
2144
	and eax,PNG_FORMAT_FLAG_ALPHA
2145
	jz .end0 ;if (..!=0)
6779 IgorA 2146
;      bytep row_end;
6733 IgorA 2147
;      int aindex;
2148
2149
 
2150
;      if ((image->format & PNG_FORMAT_FLAG_AFIRST) != 0)
2151
;      {
2152
;         aindex = -1;
2153
;         ++input_row; /* To point to the first component */
2154
;         ++output_row;
2155
;      }
2156
2157
 
2158
end if
2159
;      aindex = channels;
2160
2161
 
2162
;      row_end = output_row + image->width * (channels+1);
2163
2164
 
2165
;      {
2166
;         const_uint_16p in_ptr = input_row;
2167
;         bytep out_ptr = output_row;
2168
2169
 
2170
;         {
2171
;            uint_16 alpha = in_ptr[aindex];
2172
;            byte alphabyte = (byte)PNG_DIV257(alpha);
2173
;            uint_32 reciprocal = 0;
2174
;            int c;
2175
2176
 
2177
;            out_ptr[aindex] = alphabyte;
2178
2179
 
2180
;               reciprocal = UNP_RECIPROCAL(alpha);
2181
2182
 
2183
;            do /* always at least one channel */
2184
;               *out_ptr++ = png_unpremultiply(*in_ptr++, alpha, reciprocal);
2185
;            while (--c > 0);
2186
2187
 
2188
;            ++in_ptr;
2189
;            ++out_ptr;
2190
;         } /* while out_ptr < row_end */
2191
2192
 
2193
;         input_row += display->row_bytes/(sizeof (uint_16));
2194
;      } /* while y */
2195
		jmp .end1
2196
	.end0: ;else
2197
		; No alpha channel, so the row_end really is the end of the row and it
2198
		; is sufficient to loop over the components one by one.
2199
2200
 
2201
		imul ecx,[channels]
2202
		add ecx,[output_row]
2203
		;ecx = row_end
2204
2205
 
2206
			cmp dword[y],0
2207
			jle .cycle2end
2208
			mov esi,[input_row]
2209
			mov edi,[output_row]
2210
			;esi = in_ptr
2211
			;edi = out_ptr
2212
2213
 
2214
				cmp edi,ecx
2215
				jge .cycle3end
2216
				xor eax,eax
2217
				lodsw
2218
2219
 
2220
				mov [component],eax
2221
				PNG_sRGB_FROM_LINEAR [component]
2222
				stosb
2223
				jmp .cycle3
2224
align 4
2225
			.cycle3end:
2226
2227
 
2228
			mov eax,[ebx+png_image_write_control.row_bytes]
2229
			shr eax,1 ;sizeof.uint_16
2230
			add [input_row],eax
2231
			dec dword[y]
2232
			jmp .cycle2
2233
align 4
2234
		.cycle2end:
2235
	.end1:
2236
2237
 
2238
	inc eax
2239
	ret
2240
endp
2241
2242
 
2243
align 4
2244
proc png_image_set_PLTE, display:dword
2245
locals
2246
	image dd ? ;png_imagep ;= display->image
2247
	cmap dd ? ;void * ;= display->colormap
2248
	entries dd ? ;int
2249
2250
 
2251
	format dd ? ;uint_32 ;= image->format
2252
	channels dd ? ;int
2253
	afirst dd 0
2254
	bgr dd 0
2255
	num_trans dd 0
2256
	palette rb 256*sizeof.png_color
2257
	tRNS rb 256 ;byte[]
2258
endl
2259
pushad
2260
	mov edx,[display]
2261
	mov ebx,[edx+png_image_write_control.image]
2262
	mov [image],ebx
2263
	mov eax,[edx+png_image_write_control.colormap]
2264
	mov [cmap],eax
2265
	mov eax,[ebx+png_image.colormap_entries]
2266
	cmp eax,256
2267
	jle @f
2268
		mov eax,256
2269
	@@:
2270
	mov [entries],eax
2271
	mov ecx,[ebx+png_image.format]
2272
	mov [format],ecx
2273
	PNG_IMAGE_SAMPLE_CHANNELS ecx
2274
	mov [channels],eax
2275
2276
 
2277
	mov eax,ecx
2278
	and eax,PNG_FORMAT_FLAG_AFIRST
2279
	jz @f
6779 IgorA 2280
	mov eax,ecx
6733 IgorA 2281
	and eax,PNG_FORMAT_FLAG_ALPHA
2282
	jz @f
6779 IgorA 2283
		mov dword[afirst],-1
6733 IgorA 2284
	@@:
2285
end if
2286
2287
 
2288
	mov eax,ecx
2289
	and eax,PNG_FORMAT_FLAG_BGR
2290
	jz @f
6779 IgorA 2291
		mov dword[bgr],2
6733 IgorA 2292
	@@:
2293
end if
2294
2295
 
2296
2297
 
2298
	mov ecx,(256*sizeof.png_color)/4
2299
	mov edi,ebp
2300
	sub edi,256+256*sizeof.png_color
2301
	rep stosd ;memset(palette, 0, ...
2302
	not eax
2303
	mov ecx,256/4
2304
	;;mov edi,ebp ;if 'tRNS' after 'palette' this code can be comment
2305
	;;sub edi,256
2306
	rep stosd ;memset(tRNS, 255, ...
2307
2308
 
2309
 
2310
;   {
2311
		; This gets automatically converted to sRGB with reversal of the
2312
		; pre-multiplication if the color-map has an alpha channel.
2313
2314
 
2315
;      {
2316
;         png_const_uint_16p entry = cmap;
2317
2318
 
2319
2320
 
2321
;         {
2322
;            if (channels >= 3) /* RGB */
2323
;            {
2324
;               palette[i].blue = (byte)PNG_sRGB_FROM_LINEAR(255 *
2325
;                   entry[(2 ^ bgr)]);
2326
;               palette[i].green = (byte)PNG_sRGB_FROM_LINEAR(255 *
2327
;                   entry[1]);
2328
;               palette[i].red = (byte)PNG_sRGB_FROM_LINEAR(255 *
2329
;                   entry[bgr]);
2330
;            }
2331
2332
 
2333
;               palette[i].blue = palette[i].red = palette[i].green =
2334
;                  (byte)PNG_sRGB_FROM_LINEAR(255 * *entry);
2335
;         }
2336
2337
 
2338
;         {
2339
;            uint_16 alpha = entry[afirst ? 0 : channels-1];
2340
;            byte alphabyte = (byte)PNG_DIV257(alpha);
2341
;            uint_32 reciprocal = 0;
2342
2343
 
2344
		; this is designed to produce a value scaled to 255*65535 when
2345
		; divided by 128 (i.e. asr 7).
2346
2347
 
2348
;               reciprocal = (((0xffff*0xff)<<7)+(alpha>>1))/alpha;
2349
2350
 
2351
;            if (alphabyte < 255)
2352
;               num_trans = i+1;
2353
2354
 
2355
;            {
2356
;               palette[i].blue = png_unpremultiply(entry[afirst + (2 ^ bgr)],
2357
;                   alpha, reciprocal);
2358
;               palette[i].green = png_unpremultiply(entry[afirst + 1], alpha,
2359
;                   reciprocal);
2360
;               palette[i].red = png_unpremultiply(entry[afirst + bgr], alpha,
2361
;                   reciprocal);
2362
;            }
2363
2364
 
2365
;               palette[i].blue = palette[i].red = palette[i].green =
2366
;                   png_unpremultiply(entry[afirst], alpha, reciprocal);
2367
;         }
2368
;      }
2369
2370
 
2371
;      {
2372
;         bytep entry = cmap;
2373
2374
 
2375
2376
 
2377
;         {
2378
;            case 4:
2379
;               tRNS[i] = entry[afirst ? 0 : 3];
2380
;               if (tRNS[i] < 255)
2381
;                  num_trans = i+1;
2382
;               /* FALL THROUGH */
2383
;            case 3:
2384
;               palette[i].blue = entry[afirst + (2 ^ bgr)];
2385
;               palette[i].green = entry[afirst + 1];
2386
;               palette[i].red = entry[afirst + bgr];
2387
;               break;
2388
2389
 
2390
;               tRNS[i] = entry[1 ^ afirst];
2391
;               if (tRNS[i] < 255)
2392
;                  num_trans = i+1;
2393
;               /* FALL THROUGH */
2394
;            case 1:
2395
;               palette[i].blue = palette[i].red = palette[i].green =
2396
;                  entry[afirst];
2397
;               break;
2398
2399
 
2400
;               break;
2401
;         }
2402
;      }
2403
;   }
2404
2405
 
2406
	mov eax,ebp
2407
	sub eax,256+256*sizeof.png_color
2408
	stdcall png_set_PLTE, [ecx+png_control.png_ptr], [ecx+png_control.info_ptr], eax, [entries]
2409
2410
 
2411
	jle @f ;if (..>0)
2412
		mov eax,ebp
2413
		sub eax,256
2414
		stdcall png_set_tRNS, [ecx+png_control.png_ptr], [ecx+png_control.info_ptr], eax, [num_trans], 0
2415
	@@:
2416
2417
 
2418
	mov [ebx+png_image.colormap_entries],eax
2419
popad
2420
	ret
2421
endp
2422
2423
 
2424
align 4
2425
proc png_image_write_main uses ebx ecx edx esi edi, argument:dword
2426
locals
2427
	display dd ? ;= png_image_write_control * = argument
2428
	image dd ? ;= display->image
2429
	png_ptr dd ? ;= image->opaque->png_ptr
2430
	info_ptr dd ? ;= image->opaque->info_ptr
2431
	format dd ? ;= image->format
2432
2433
 
2434
	linear dd ?
2435
	alpha dd ?
2436
	write_16bit dd ? ;= linear && !colormap && (display->convert_to_8bit == 0)
2437
endl
2438
	mov edx,[argument]
2439
	mov [display],edx
2440
	mov ebx,[edx+png_image_write_control.image]
2441
	mov [image],ebx
2442
	mov ecx,[ebx+png_image.format]
2443
	mov [format],ecx
2444
	mov eax,[ebx+png_image.opaque]
2445
	mov edi,[eax+png_control.png_ptr]
2446
	mov [png_ptr],edi
2447
	mov esi,[eax+png_control.info_ptr]
2448
	mov [info_ptr],esi
2449
2450
 
2451
	and ecx,PNG_FORMAT_FLAG_COLORMAP
2452
	mov [colormap],ecx
2453
	not ecx
2454
	mov eax,[format]
2455
	and eax,PNG_FORMAT_FLAG_LINEAR
2456
	mov [linear],eax
2457
	mov eax,[format]
2458
	and eax,ecx
2459
	and eax,PNG_FORMAT_FLAG_ALPHA
2460
	and eax,ecx
2461
	mov [alpha],eax
2462
	xor eax,eax ;false
2463
	cmp dword[edx+png_image_write_control.convert_to_8bit],0
2464
	jne @f
2465
		not eax ;true
2466
	@@:
2467
	and eax,[linear]
2468
	and eax,ecx
2469
	mov [write_16bit],eax
2470
2471
 
2472
	; Make sure we error out on any bad situation
2473
	stdcall png_set_benign_errors, edi, 0 ;error
2474
end if
2475
2476
 
2477
	; and total image size to ensure that they are within the system limits.
2478
2479
 
2480
	;eax = channels
2481
2482
 
2483
	mov ecx,eax
2484
	mov eax,0x7FFFFFFF
2485
	xor edx,edx
2486
	div ecx
2487
	pop edx
2488
	cmp [ebx+png_image.width],eax
2489
	jg .end0 ;if (..<=..) ;no overflow
2490
		imul ecx,[ebx+png_image.width]
2491
2492
 
2493
		jne @f ;if (..==0)
2494
			mov [edx+png_image_write_control.row_stride],ecx
2495
		@@:
2496
		mov eax,[edx+png_image_write_control.row_stride]
2497
		cmp eax,0
2498
		jge .end2 ;if (..<0)
2499
			neg eax
2500
			inc eax
2501
		.end2:
2502
2503
 
2504
		jl .end3 ;if (..>=..)
2505
			; Now check for overflow of the image buffer calculation; this
2506
			; limits the whole image size to 32 bits for API compatibility with
2507
			; the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro.
2508
2509
 
2510
			mov eax,0xFFFFFFFF
2511
			xor edx,edx
2512
			div ecx
2513
			pop edx
2514
			cmp [ebx+png_image.height],eax
2515
			jle @f ;if (..>..)
2516
				mov eax,[ebx+png_image.opaque]
2517
				mov eax,[eax+png_control.png_ptr]
2518
				png_error eax, 'memory image too large'
2519
			@@:
2520
			jmp .end1
2521
		.end3: ;else
2522
			mov eax,[ebx+png_image.opaque]
2523
			mov eax,[eax+png_control.png_ptr]
2524
			png_error eax, 'supplied row stride too small'
2525
		jmp .end1
2526
	.end0: ;else
2527
		mov eax,[ebx+png_image.opaque]
2528
		mov eax,[eax+png_control.png_ptr]
2529
		png_error eax, 'image row stride too large'
2530
	.end1:
2531
2532
 
2533
	mov eax,[format]
2534
	and eax,PNG_FORMAT_FLAG_COLORMAP
2535
	jz .end4 ;if (..!=0)
6779 IgorA 2536
		cmp dword[edx+png_image_write_control.colormap],0
6733 IgorA 2537
		je .end6
2538
		mov eax,[ebx+png_image.colormap_entries]
2539
		cmp eax,0
2540
		jle .end6 ;if (..!=0 && ..>0)
2541
			;eax = entries
2542
			xor ecx,ecx
2543
			inc ecx ;=1
2544
			cmp eax,2
2545
			jle @f
2546
				shl ecx,1 ;=2
2547
			cmp eax,4
2548
			jle @f
2549
				shl ecx,1 ;=4
2550
			cmp eax,16
2551
			jle @f
2552
				shl ecx,1 ;=8
2553
			@@:
2554
			stdcall png_set_IHDR, edi, esi, [ebx+png_image.width], [ebx+png_image.height],\
2555
				ecx, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,\
2556
				PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE
2557
2558
 
2559
			jmp .end5
2560
		.end6: ;else
2561
			mov eax,[ebx+png_image.opaque]
2562
			mov eax,[eax+png_control.png_ptr]
2563
			png_error eax, 'no color-map for color-mapped image'
2564
		jmp .end5
2565
	.end4: ;else
2566
		xor ecx,ecx
2567
		mov eax,[format]
2568
		and eax,PNG_FORMAT_FLAG_COLOR
2569
		jz @f
6779 IgorA 2570
			or ecx,PNG_COLOR_MASK_COLOR
6733 IgorA 2571
		@@:
2572
		mov eax,[format]
2573
		and eax,PNG_FORMAT_FLAG_ALPHA
2574
		jz @f
6779 IgorA 2575
			or ecx,PNG_COLOR_MASK_ALPHA
6733 IgorA 2576
		@@:
2577
		mov eax,8
2578
		cmp dword[write_16bit],0
2579
		je @f
2580
			mov eax,16
2581
		@@:
2582
		stdcall png_set_IHDR, edi, esi, [ebx+png_image.width], [ebx+png_image.height],\
2583
			eax, ecx, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE
2584
	.end5:
2585
2586
 
2587
	; png_write_info, not before as in the read code, but the 'set' functions
2588
	; must still be called before.  Just set the color space information, never
2589
	; write an interlaced image.
2590
2591
 
2592
	je @f ;if (..!=0)
2593
		; The gamma here is 1.0 (linear) and the cHRM chunk matches sRGB.
2594
		stdcall png_set_gAMA_fixed, edi, esi, PNG_GAMMA_LINEAR
2595
2596
 
2597
		and eax,PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB
2598
		jnz @f ;if (..==0)
6779 IgorA 2599
			stdcall png_set_cHRM_fixed, edi, esi,\
6733 IgorA 2600
			31270, 32900,\ ;white
2601
			64000, 33000,\ ;red
2602
			30000, 60000,\ ;green
2603
			15000,  6000   ;blue
2604
		jmp .end7
2605
	@@:
2606
	mov eax,[ebx+png_image.flags]
2607
	and eax,PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB
2608
	jnz @f ;else if (..==0)
6779 IgorA 2609
		stdcall png_set_sRGB, edi, esi, PNG_sRGB_INTENT_PERCEPTUAL
6733 IgorA 2610
		jmp .end7
2611
	@@: ;else
2612
		; Else writing an 8-bit file and the *colors* aren't sRGB, but the 8-bit
2613
		; space must still be gamma encoded.
2614
		stdcall png_set_gAMA_fixed, edi, esi, PNG_GAMMA_sRGB_INVERSE
2615
	.end7:
2616
2617
 
2618
	stdcall png_write_info, edi, esi
2619
2620
 
2621
	; remove the handled transformations from the 'format' flags for checking.
2622
2623
 
2624
2625
 
2626
	je @f ;if (..!=0)
2627
;      uint_16 le = 0x0001;
2628
2629
 
2630
		stdcall png_set_swap, edi
2631
	@@:
2632
2633
 
2634
	mov eax,[format]
2635
	and eax,PNG_FORMAT_FLAG_BGR
2636
	jz .end12 ;if (..!=0)
6779 IgorA 2637
		cmp dword[colormap],0
6733 IgorA 2638
		jne @f
2639
		mov eax,[format]
2640
		and eax,PNG_FORMAT_FLAG_COLOR
2641
		jz @f ;if (..==0 && ..!=0)
6779 IgorA 2642
			stdcall png_set_bgr, edi
6733 IgorA 2643
		@@:
2644
		and dword[format], not PNG_FORMAT_FLAG_BGR
2645
	.end12:
2646
end if
2647
2648
 
2649
	mov eax,[format]
2650
	and eax,PNG_FORMAT_FLAG_AFIRST
2651
	jz .end13 ;if (..!=0)
6779 IgorA 2652
		cmp dword[colormap],0
6733 IgorA 2653
		jne @f
2654
		mov eax,[format]
2655
		and eax,PNG_FORMAT_FLAG_ALPHA
2656
		jz @f ;if (..==0 && ..!=0)
6779 IgorA 2657
			stdcall png_set_swap_alpha, edi
6733 IgorA 2658
		@@:
2659
		and dword[format], not PNG_FORMAT_FLAG_AFIRST
2660
	.end13:
2661
end if
2662
2663
 
2664
	; above, but the application data is still byte packed.
2665
2666
 
2667
	je @f
2668
	cmp dword[ebx+png_image.colormap_entries],16
2669
	jg @f ;if (..!=0 && ..<=16)
2670
		stdcall png_set_packing, edi
2671
	@@:
2672
2673
 
2674
	mov eax,[format]
2675
	and eax, not (PNG_FORMAT_FLAG_COLOR or PNG_FORMAT_FLAG_LINEAR or PNG_FORMAT_FLAG_ALPHA or PNG_FORMAT_FLAG_COLORMAP)
2676
	jz @f ;if (..!=0)
6779 IgorA 2677
		png_error edi, 'png_write_image: unsupported transformation'
6733 IgorA 2678
	@@:
2679
2680
 
2681
	;ecx - row ;bytep
2682
	;esi - row_bytes
2683
	mov ecx,[edx+png_image_write_control.buffer]
2684
	mov esi,[edx+png_image_write_control.row_stride]
2685
2686
 
2687
	je @f ;if (..!=0)
2688
		shl esi,1 ;*= sizeof.uint_16
2689
	@@:
2690
	cmp esi,0
2691
	jge @f ;if (..<0)
2692
		mov eax,[ebx+png_image.height]
2693
		dec eax
2694
		imul eax,esi
2695
		sub ecx,eax
2696
	@@:
2697
	mov [edx+png_image_write_control.first_row],ecx
2698
	mov [edx+png_image_write_control.row_bytes],esi
2699
	pop esi
2700
2701
 
2702
	mov eax,[ebx+png_image.flags]
2703
	and eax,PNG_IMAGE_FLAG_FAST
2704
	jz @f ;if (..!=0)
6779 IgorA 2705
		stdcall png_set_filter, edi, PNG_FILTER_TYPE_BASE, PNG_NO_FILTERS
6733 IgorA 2706
		; NOTE: determined by experiment using pngstest, this reflects some
2707
		; balance between the time to write the image once and the time to read
2708
		; it about 50 times.  The speed-up in pngstest was about 10-20% of the
2709
		; total (user) time on a heavily loaded system.
2710
2711
 
2712
		stdcall png_set_compression_level, edi, 3
2713
end if
2714
	@@:
2715
2716
 
2717
	; before it is written.  This only applies when the input is 16-bit and
2718
	; either there is an alpha channel or it is converted to 8-bit.
2719
2720
 
2721
	je @f
2722
	cmp dword[alpha],0
2723
	je @f
2724
		jmp .end10
2725
	@@:
2726
	cmp dword[colormap],0
2727
	jne .end9
2728
	cmp dword[edx+png_image_write_control.convert_to_8bit],0
2729
	je .end9
2730
	.end10: ;if ((..!=0 && ..!=0 ) || (..==0 && ..!=0))
2731
		stdcall png_get_rowbytes, edi, esi
2732
		stdcall png_malloc, edi, eax
2733
		mov ecx,eax ;ecx = row
2734
2735
 
2736
		cmp dword[write_16bit],0
2737
		je @f ;if (..!=0)
2738
			stdcall png_safe_execute, ebx, png_write_image_16bit, edx
2739
			jmp .end11
2740
		@@: ;else
2741
			stdcall png_safe_execute, ebx, png_write_image_8bit, edx
2742
		.end11:
2743
		mov dword[edx+png_image_write_control.local_row],0
2744
2745
 
2746
2747
 
2748
		test eax,eax
6881 IgorA 2749
		jz .end_f ;if (..==0) return 0
2750
		jmp .end8
6733 IgorA 2751
2752
 
2753
	; supported by the rest of the libpng write code; call it directly.
2754
2755
 
2756
if 1 ;;; IDAT compress all (only 24 bit)
6891 IgorA 2757
		mov ecx,[edx+png_image_write_control.row_bytes]
6733 IgorA 2758
		inc ecx
2759
		imul ecx,[ebx+png_image.height]
2760
		cmp ecx,1
2761
		jl .end8
2762
		stdcall create_compress_IDAT, edi, [edx+png_image_write_control.first_row], ecx, [ebx+png_image.width], [ebx+png_image.height]
2763
else ;;; IDAT compress by lines
6888 IgorA 2764
		mov ecx,[ebx+png_image.height]
6733 IgorA 2765
		cmp ecx,1
2766
		jl .end8
2767
		mov eax,[edx+png_image_write_control.first_row]
2768
		mov ebx,[edx+png_image_write_control.row_bytes]
2769
		@@:
2770
			stdcall png_write_row, edi, eax
2771
			add eax, ebx
2772
			loop @b
2773
end if
2774
	.end8:
2775
2776
 
2777
	xor eax,eax
2778
	inc eax
2779
.end_f:
2780
	ret
2781
endp
2782
2783
 
2784
proc create_compress_IDAT, png_ptr:dword, buf:dword, len:dword, width:dword, height:dword
2785
locals
2786
	m1 dd ? ;memory for compress IDAT
2787
	buf_f dd ? ;memory for IDAT
2788
	mins dd ? ;minimum sum
2789
endl
2790
pushad
2791
	mov edi,[png_ptr]
2792
png_debug 1, 'IDAT compress all'
2793
2794
 
2795
	stdcall png_zalloc, edi, 1, [len]
2796
	test eax,eax
6881 IgorA 2797
	jz .end_f
2798
	mov [buf_f],eax
6733 IgorA 2799
2800
 
2801
	cmp eax,[len]
2802
	jge @f
2803
		mov eax,[len]
2804
	@@:
2805
	stdcall png_zalloc, edi, 1, eax
2806
	test eax,eax
6881 IgorA 2807
	jz .end0
2808
	mov [m1],eax
6733 IgorA 2809
2810
 
2811
	mov ebx,[width]
2812
	mov edx,[height]
2813
	mov edi,[buf_f]
2814
	mov esi,[buf]
2815
	.cycle0:
2816
	cmp edx,1
2817
	jl .cycle0end
2818
		mov ecx,ebx
2819
		xor al,al
2820
		stosb ;insert filter (0 - none)
2821
align 4
2822
		.cycle1:
2823
			lodsb   ;1
2824
			inc edi ;
2825
			movsb   ;2
2826
			stosb   ;3
2827
			lodsb   ;
2828
			mov [edi-3],al
2829
			loop .cycle1
2830
		dec edx
2831
		jmp .cycle0
2832
	.cycle0end:
2833
2834
 
2835
	mov edx,[height]
2836
	mov esi,[width]
2837
	imul esi,3 ;esi - rowbytes
2838
2839
 
6779 IgorA 2840
	mov edi,[png_ptr]
6733 IgorA 2841
	cmp dword[edi+png_struct.try_row],0
2842
	jne @f ;if (..==0)
2843
		stdcall png_malloc, edi, esi
2844
		mov [edi+png_struct.try_row],eax
2845
	@@:
2846
	cmp dword[edi+png_struct.tst_row],0
6779 IgorA 2847
	jne @f ;if (..==0)
2848
		stdcall png_malloc, edi, esi
2849
		mov [edi+png_struct.tst_row],eax
2850
	@@:
2851
	dec esi
2852
6733 IgorA 2853
 
2854
	add edi,[len]
2855
	.cycle3:
2856
		dec edx
2857
		cmp edx,1
2858
		jl .cycle3end
2859
		sub edi,esi
2860
		dec edi ;move in perv row
2861
2862
 
2863
		mov ebx,[png_ptr]
2864
		mov [ebx+png_struct.row_buf],edi
2865
		mov [ebx+png_struct.prev_row],edi
2866
		sub [ebx+png_struct.prev_row],esi
2867
		dec dword[ebx+png_struct.prev_row]
2868
2869
 
2870
		push esi
2871
		xor eax,eax
2872
		xor ebx,ebx
2873
		mov ecx,esi
2874
		mov esi,edi
2875
		inc esi
2876
		.cycle2:
2877
			lodsb
2878
			png_setup_abs ebx
2879
			loop .cycle2
2880
		pop esi
2881
		mov [mins],ebx
2882
2883
 
6779 IgorA 2884
		mov edx,[png_ptr]
6733 IgorA 2885
		mov eax,[edx+png_struct.tst_row]
6779 IgorA 2886
		mov byte[eax],0 ;not filter
2887
2888
 
6733 IgorA 2889
		stdcall png_setup_up_row, edx, esi, [mins]
2890
		cmp eax,[mins]
2891
		jge @f ;if (..<..)
6779 IgorA 2892
			mov [mins],eax
2893
			stdcall copy_row_mins, [edx+png_struct.tst_row], [edx+png_struct.try_row]
2894
		@@:
2895
2896
 
2897
		movzx ebx,byte[edx+png_struct.pixel_depth]
2898
		add ebx,7
2899
		shr ebx,3
2900
2901
 
2902
		stdcall png_setup_sub_row, edx, ebx, esi, [mins]
2903
		cmp eax,[mins]
2904
		jge @f ;if (..<..)
2905
			mov [mins],eax
2906
			stdcall copy_row_mins, [edx+png_struct.tst_row], [edx+png_struct.try_row]
2907
		@@:
2908
2909
 
2910
		stdcall png_setup_avg_row, edx, ebx, esi, [mins]
2911
		cmp eax,[mins]
2912
		jge @f ;if (..<..)
2913
			mov [mins],eax
2914
			stdcall copy_row_mins, [edx+png_struct.tst_row], [edx+png_struct.try_row]
2915
		@@:
2916
2917
 
6888 IgorA 2918
		stdcall png_setup_paeth_row, edx, ebx, esi, [mins]
2919
		cmp eax,[mins]
2920
		jge @f ;if (..<..)
2921
			mov [mins],eax
2922
			stdcall copy_row_mins, [edx+png_struct.tst_row], [edx+png_struct.try_row]
2923
		@@:
2924
2925
 
6779 IgorA 2926
		mov eax,[edx+png_struct.tst_row]
2927
		cmp byte[eax],0
2928
		je @f
2929
			stdcall copy_row_mins, edi, [edx+png_struct.tst_row]
2930
		@@:
2931
		pop edx
2932
		jmp .cycle3
6733 IgorA 2933
	.cycle3end:
2934
2935
 
2936
	mov esi,edi
2937
	add esi,png_struct.zstream
2938
	stdcall [deflateInit2], esi,\
2939
		-1, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY
2940
2941
 
2942
	mov [edi+png_struct.zstream.next_in],eax
2943
	mov eax,[len]
2944
	mov [edi+png_struct.zstream.avail_in],eax
2945
	mov eax,[m1]
2946
	mov [edi+png_struct.zstream.next_out],eax
2947
	xor ecx,ecx
2948
align 4
2949
	.cycle4:
2950
		mov dword[edi+png_struct.zstream.avail_out],16*1024
6797 IgorA 2951
6733 IgorA 2952
 
6873 IgorA 2953
		cmp eax,Z_STREAM_ERROR
6733 IgorA 2954
		je .end1
2955
2956
 
2957
		sub ecx,[edi+png_struct.zstream.avail_out]
6797 IgorA 2958
		cmp dword[edi+png_struct.zstream.avail_out],0
2959
	je .cycle4 ;while (strm.avail_out == 0)
6733 IgorA 2960
if 0
6873 IgorA 2961
	mov dword[edi+png_struct.zstream.avail_out],16*1024
6797 IgorA 2962
	stdcall [deflate], esi, Z_FINISH
6733 IgorA 2963
	add ecx,16*1024
6870 IgorA 2964
	sub ecx,[edi+png_struct.zstream.avail_out]
2965
	cmp eax,Z_STREAM_ERROR
6733 IgorA 2966
	je .end1
2967
end if
6873 IgorA 2968
	stdcall [deflateEnd], esi
6733 IgorA 2969
2970
 
2971
	mov eax,[edi+png_struct.mode]
2972
	and eax,PNG_HAVE_IDAT
2973
	jnz @f
6779 IgorA 2974
	cmp byte[edi+png_struct.compression_type],PNG_COMPRESSION_TYPE_BASE
6733 IgorA 2975
	jne @f ;if (..==0 && ..==..)
2976
		stdcall png_image_size, edi
2977
		stdcall optimize_cmf, [m1], eax
2978
	@@:
2979
end if
2980
	stdcall png_write_complete_chunk, edi, png_IDAT, [m1], ecx
2981
	or dword[edi+png_struct.mode],PNG_HAVE_IDAT
2982
2983
 
2984
	.end1:
2985
		png_debug 1, 'Z_STREAM_ERROR'
2986
	@@:
2987
2988
 
2989
	cmp dword[edi+png_struct.try_row],0
2990
	je @f ;if (..!=0)
2991
		stdcall png_free, edi, [edi+png_struct.try_row]
2992
		mov dword[edi+png_struct.try_row],0
2993
	@@:
2994
	cmp dword[edi+png_struct.tst_row],0
6779 IgorA 2995
	je @f ;if (..!=0)
2996
		stdcall png_free, edi, [edi+png_struct.tst_row]
2997
		mov dword[edi+png_struct.tst_row],0
2998
	@@:
2999
	stdcall png_free, edi, [m1]
6733 IgorA 3000
.end0:
3001
	stdcall png_free, edi, [buf_f]
3002
.end_f:
3003
popad
3004
	ret
3005
endp
3006
3007
 
6779 IgorA 3008
; esi - rowbytes
3009
align 4
3010
proc copy_row_mins uses edi esi, dest:dword, sour:dword
3011
	mov ecx,esi
3012
	inc ecx
3013
	mov edi,[dest]
3014
	mov esi,[sour]
3015
	rep movsb
3016
	ret
3017
endp
3018
3019
 
6733 IgorA 3020
align 4
3021
proc image_memory_write uses eax ebx ecx edi esi, png_ptr:dword, p2data:dword, size:dword
3022
	mov edi,[png_ptr]
3023
	mov esi,[edi+png_struct.io_ptr] ;esi = png_image_write_control *display
3024
	mov ebx,[esi+png_image_write_control.output_bytes] ;ebx = ob
3025
3026
 
3027
	mov eax,PNG_SIZE_MAX
3028
	sub eax,ebx
3029
	mov ecx,[size]
3030
	cmp ecx,eax
3031
	jg .end1 ;if (..<=..)
3032
		; I don't think libpng ever does this, but just in case:
3033
		cmp ecx,0
3034
		jle .end0 ;if (..>0)
3035
			mov eax,ebx
3036
			add eax,ecx
3037
			cmp [esi+png_image_write_control.memory_bytes],eax
3038
			jl @f ;if (..>=..) ;writing
3039
				push esi
3040
				mov edi,[esi+png_image_write_control.memory]
3041
				add edi,ebx
3042
				mov esi,[p2data]
3043
				rep movsb ;memcpy(...
3044
				pop esi
3045
			@@:
3046
3047
 
3048
			add ebx,[size]
3049
			mov [esi+png_image_write_control.output_bytes],ebx
3050
		.end0:
3051
		jmp .end2
3052
	.end1: ;else
3053
		png_error edi, 'png_image_write_to_memory: PNG too big'
3054
	.end2:
3055
	ret
3056
endp
3057
3058
 
3059
align 4
3060
proc image_memory_flush, png_ptr:dword
3061
	ret
3062
endp
3063
3064
 
3065
align 4
3066
proc png_image_write_memory uses ebx, argument:dword
3067
	; The rest of the memory-specific init and write_main in an error protected
3068
	; environment.  This case needs to use callbacks for the write operations
3069
	; since libpng has no built in support for writing to memory.
3070
3071
 
3072
	mov ebx,[eax+png_image_write_control.image]
3073
	mov ebx,[ebx+png_image.opaque]
3074
	stdcall png_set_write_fn, [ebx+png_control.png_ptr], eax, image_memory_write, image_memory_flush
3075
3076
 
3077
	ret
3078
endp
3079
3080
 
3081
;    png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8bit,
3082
;    const void *buffer, int_32 row_stride, const void *colormap)
3083
align 4
3084
proc png_image_write_to_memory uses ebx ecx edx edi esi, image:dword, memory:dword,\
3085
	memory_bytes:dword, convert_to_8bit:dword, buffer:dword, row_stride:dword, colormap:dword
3086
locals
3087
	display png_image_write_control ;local struct
3088
endl
3089
;edi - display png_image_write_control
3090
3091
 
3092
	mov ebx,[image]
3093
	cmp ebx,0
3094
	je .end0
3095
	cmp dword[ebx+png_image.version],PNG_IMAGE_VERSION
3096
	jne .end0 ;if (..!=0 && ..==..)
3097
		cmp dword[memory_bytes],0
3098
		je .end2
3099
		cmp dword[buffer],0
3100
		je .end2 ;if (..!=0 && ..!=0)
3101
			; This is to give the caller an easier error detection in the NULL
3102
			; case and guard against uninitialized variable problems:
3103
3104
 
3105
			jne @f ;if(..==0)
3106
				mov eax,[memory_bytes]
3107
				mov dword[eax],0
3108
			@@:
3109
3110
 
3111
			test eax,eax
6881 IgorA 3112
			jz .end3 ;if (..!=0)
3113
				mov ecx,sizeof.png_image_write_control
6733 IgorA 3114
				mov edi,ebp
3115
				sub edi,ecx
3116
				xor eax,eax
3117
				rep stosb ;memset(&display, 0, sizeof.display))
3118
				sub edi,sizeof.png_image_write_control
3119
				mov [edi+png_image_write_control.image],ebx
3120
				mov eax,[buffer]
3121
				mov [edi+png_image_write_control.buffer],eax
3122
				mov eax,[row_stride]
3123
				mov [edi+png_image_write_control.row_stride],eax
3124
				mov eax,[colormap]
3125
				mov [edi+png_image_write_control.colormap],eax
3126
				mov eax,[convert_to_8bit]
3127
				mov [edi+png_image_write_control.convert_to_8bit],eax
3128
				mov eax,[memory]
3129
				mov [edi+png_image_write_control.memory],eax
3130
				mov eax,[memory_bytes]
3131
				mov eax,[eax]
3132
				mov [edi+png_image_write_control.memory_bytes],eax
3133
				mov dword[edi+png_image_write_control.output_bytes], 0
3134
3135
 
3136
				mov ecx,eax ;ecx = result
3137
				stdcall png_image_free, ebx
3138
3139
 
3140
				cmp ecx,0 ;if (..)
3141
				je .end4
3142
					; On out-of-buffer this function returns '0' but still updates
3143
					; memory_bytes:
3144
3145
 
3146
					mov eax,[memory_bytes]
3147
					cmp dword[memory],0
3148
					je @f ;if (..!=0 && ..>..)
3149
					cmp edx,[eax]
3150
					jle @f
3151
						xor ecx,ecx
3152
					@@:
3153
					mov [eax],edx
3154
				.end4:
3155
3156
 
3157
				jmp .end_f
3158
			.end3: ;else
3159
			xor eax,eax
3160
			jmp .end_f
3161
		.end2: ;else
3162
			std_png_image_error ebx, 'png_image_write_to_memory: invalid argument'
3163
			jmp .end_f
3164
	.end0:
3165
	cmp ebx,0
3166
	je .end1 ;else if (..!=0)
3167
		std_png_image_error ebx, 'png_image_write_to_memory: incorrect PNG_IMAGE_VERSION'
3168
		jmp .end_f
3169
	.end1: ;else
3170
		xor eax,eax
3171
.end_f:
3172
	ret
3173
endp
3174
3175
 
3176
;    const void *buffer, int_32 row_stride, const void *colormap)
3177
align 4
3178
proc png_image_write_to_stdio, image:dword, file:dword, convert_to_8bit:dword, buffer:dword, row_stride:dword, colormap:dword
3179
	; Write the image to the given (FILE*).
3180
;   if (image != NULL && image->version == PNG_IMAGE_VERSION)
3181
;   {
3182
;      if (file != NULL && buffer != NULL)
3183
;      {
3184
;         if (png_image_write_init(image) != 0)
3185
;         {
3186
;            png_image_write_control display;
3187
;            int result;
3188
3189
 
3190
	; than this and we haven't changed the standard IO functions so
3191
	; this saves a 'safe' function.
3192
3193
 
3194
3195
 
3196
;            display.image = image;
3197
;            display.buffer = buffer;
3198
;            display.row_stride = row_stride;
3199
;            display.colormap = colormap;
3200
;            display.convert_to_8bit = convert_to_8bit;
3201
3202
 
3203
;            png_image_free(image);
3204
;            return result;
3205
;         }
3206
3207
 
3208
;            return 0;
3209
;      }
3210
3211
 
3212
;         return png_image_error(image,
3213
;             "png_image_write_to_stdio: invalid argument");
3214
;   }
3215
3216
 
3217
;      return png_image_error(image,
3218
;          "png_image_write_to_stdio: incorrect PNG_IMAGE_VERSION");
3219
3220
 
3221
;      return 0;
3222
	ret
3223
endp
3224
3225
 
3226
;    int convert_to_8bit, const void *buffer, int_32 row_stride,
3227
;    const void *colormap)
3228
align 4
3229
proc png_image_write_to_file, image:dword, file_name:dword, convert_to_8bit:dword, buffer:dword, row_stride:dword, colormap:dword
3230
	; Write the image to the named file.
3231
;   if (image != NULL && image->version == PNG_IMAGE_VERSION)
3232
;   {
3233
;      if (file_name != NULL && buffer != NULL)
3234
;      {
3235
;         FILE *fp = fopen(file_name, "wb");
3236
3237
 
3238
;         {
3239
;            if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer,
3240
;                row_stride, colormap) != 0)
3241
;            {
3242
;               int error; /* from fflush/fclose */
3243
3244
 
3245
;               if (fflush(fp) == 0 && ferror(fp) == 0)
3246
;               {
3247
;                  if (fclose(fp) == 0)
3248
;                     return 1;
3249
3250
 
3251
;               }
3252
3253
 
3254
;               {
3255
;                  error = errno; /* from fflush or ferror */
3256
;                  (void)fclose(fp);
3257
;               }
3258
3259
 
3260
	; The image has already been cleaned up; this is just used to
3261
	; set the error (because the original write succeeded).
3262
3263
 
3264
;            }
3265
3266
 
3267
;            {
3268
	; Clean up: just the opened file.
3269
;               (void)fclose(fp);
3270
;               (void)remove(file_name);
3271
;               return 0;
3272
;            }
3273
;         }
3274
3275
 
3276
;            return png_image_error(image, strerror(errno));
3277
;      }
3278
3279
 
3280
;         return png_image_error(image,
3281
;             "png_image_write_to_file: invalid argument");
3282
;   }
3283
3284
 
3285
;      return png_image_error(image,
3286
;          "png_image_write_to_file: incorrect PNG_IMAGE_VERSION");
3287
3288
 
3289
;      return 0;
3290
	ret
3291
endp
3292
end if ;SIMPLIFIED_WRITE
3293
>