Subversion Repositories Kolibri OS

Rev

Rev 1014 | Rev 1102 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1014 diamond 1
;;================================================================================================;;
2
;;//// png.asm //// (c) diamond, 2009 ////////////////////////////////////////////////////////////;;
3
;;================================================================================================;;
4
;;                                                                                                ;;
5
;; This file is part of Common development libraries (Libs-Dev).                                  ;;
6
;;                                                                                                ;;
7
;; Libs-Dev is free software: you can redistribute it and/or modify it under the terms of the GNU ;;
8
;; Lesser General Public License as published by the Free Software Foundation, either version 2.1 ;;
9
;; of the License, or (at your option) any later version.                                         ;;
10
;;                                                                                                ;;
11
;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without  ;;
12
;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  ;;
13
;; Lesser General Public License for more details.                                                ;;
14
;;                                                                                                ;;
15
;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev.  ;;
16
;; If not, see .                                                    ;;
17
;;                                                                                                ;;
18
;;================================================================================================;;
19
 
20
;;================================================================================================;;
21
;;proc img.is.png _data, _length ;////////////////////////////////////////////////////////////////;;
22
img.is.png:
23
;;------------------------------------------------------------------------------------------------;;
24
;? Determine if raw data could be decoded (is in PNG format)                                      ;;
25
;;------------------------------------------------------------------------------------------------;;
26
;> _data = raw data as read from file/stream                                                      ;;
27
;> _length = data length                                                                          ;;
28
;;------------------------------------------------------------------------------------------------;;
29
;< eax = false / true                                                                             ;;
30
;;================================================================================================;;
31
; test 1 (length of data)
32
	cmp	dword [esp+8], 8
33
	jb	.nope
34
; test 2: signature
35
	mov	eax, [esp+4]
36
	cmp	dword [eax], 0x474E5089
37
	jne	.nope
38
	cmp	dword [eax+4], 0x0A1A0A0D
39
	je	.yep
40
 
41
  .nope:
42
	xor	eax, eax
43
	ret	8
44
 
45
  .yep:
46
	xor	eax, eax
47
	inc	eax
48
	ret	8
49
;endp
50
 
51
;;================================================================================================;;
52
;;proc img.decode.png _data, _length ;////////////////////////////////////////////////////////////;;
53
img.decode.png:
54
	xor	eax, eax	; .image = 0
55
	pushad
56
	mov	ebp, esp
57
.localsize = 15*4
58
virtual at ebp - .localsize
59
.width		dd	?
60
.height		dd	?
61
.bit_depth	dd	?
62
.color_type	dd	?
63
.bytes_per_pixel dd	?
64
.scanline_len	dd	?
65
.cur_chunk_ptr	dd	?
66
.cur_chunk_size	dd	?
67
.paeth_a	dd	?
68
.paeth_b	dd	?
69
.paeth_c	dd	?
70
.paeth_pa	dd	?
71
.paeth_pb	dd	?
72
.paeth_pc	dd	?
73
.idat_read	dd	?
74
	rb	1Ch
75
.image		dd	?
76
	rd	1
77
.data		dd	?
78
.length		dd	?
79
end virtual
80
	push	0	; .idat_read = 0
81
	sub	esp, .localsize-4
82
; load deflate unpacker, if not yet
83
; acquire mutex
84
@@:
85
	push	1
86
	pop	eax
87
	xchg	[deflate_loader_mutex], eax	; 'xchg' has an implicit 'lock' prefix
88
	test	eax, eax
89
	jz	@f
90
	mcall	5, 1
91
	jmp	@b
92
@@:
93
	cmp	[deflate_unpack2], __deflate_unpack2_import_name__
94
	jnz	.deflate_loaded
95
; do loading
96
	invoke	dll.load, @IMPORT
97
	test	eax, eax
98
	jz	.deflate_loaded
99
	add	esp, .localsize
100
	popad
101
	mov	[deflate_loader_mutex], eax
102
	ret
103
.deflate_loaded:
104
; release mutex
105
	mov	[deflate_loader_mutex], 0
106
; ok, continue
107
	mov	esi, [.data]		; esi -> data
108
	mov	ecx, [.length]		; ecx = length
109
; the signature has been already checked in img.is.png
110
	lodsd
111
	lodsd
112
	sub	ecx, 8
113
	xor	ebx, ebx	; no image allocated
114
.chunks_loop:
115
	sub	ecx, 12
116
	jc	.eof
117
	lodsd	; chunk length
118
	bswap	eax
119
	sub	ecx, eax
120
	jc	.eof
121
	push	ecx	; save length of data rest
122
	xchg	eax, ecx	; ecx = size of data in the chunk
123
	lodsd	; chunk type
124
	cmp	eax, 'IHDR'
125
	jz	.ihdr
126
	cmp	eax, 'IDAT'
127
	jz	.idat
128
	cmp	eax, 'IEND'
129
	jz	.iend
130
	cmp	eax, 'PLTE'
131
	jz	.palette
132
; unrecognized chunk, ignore
133
	lea	esi, [esi+ecx+4]
134
	pop	ecx
135
	jmp	.chunks_loop
136
; IHDR chunk
137
.ihdr:
138
	cmp	ecx, 13
139
	jnz	.invalid_chunk
140
	cmp	[.image], 0
141
	jnz	.invalid_chunk
142
; read image characteristics
143
	lodsd
144
	bswap	eax
145
	mov	[.width], eax
146
	lodsd
147
	bswap	eax
148
	mov	[.height], eax
149
	xor	eax, eax
150
	lea	ebx, [eax+1]
151
	lodsb
152
	cmp	al, 16
153
	ja	.invalid_chunk
154
	test	al, al
155
	jz	.invalid_chunk
156
	lea	edx, [eax-1]
157
	test	al, dl
158
	jnz	.invalid_chunk
159
	mov	[.bit_depth], eax
160
	lodsb
161
	test	al, not 7
162
	jnz	.invalid_chunk
163
	mov	[.color_type], eax
164
	lodsb
165
	test	al, al
166
	jnz	.invalid_chunk	; only compression method 0 is defined
167
	lodsb
168
	test	al, al
169
	jnz	.invalid_chunk	; only filtering method 0 is defined
170
	lodsb
171
	test	al, al
172
	jnz	.invalid_chunk	; progressive PNGs are not supported yet
173
; check for correctness and calculate bytes_per_pixel and scanline_len
174
	mov	eax, [.bit_depth]
175
	mov	edx, [.color_type]
176
	dec	edx
177
	js	.grayscale1
178
	dec	edx
179
	jz	.rgb1
180
	dec	edx
181
	jz	.palette1
182
	dec	edx
183
	jz	.grayscale_alpha1
184
	dec	edx
185
	dec	edx
186
	jnz	.invalid_chunk
187
.rgb_alpha1:
188
	inc	ebx
189
.rgb1:
190
	inc	ebx
191
.grayscale_alpha1:
192
	inc	ebx
193
	cmp	al, 8
194
	jb	.invalid_chunk
195
	jmp	@f
196
.palette1:
197
	cmp	al, 8
198
	ja	.invalid_chunk
199
.grayscale1:
200
@@:
201
	mul	ebx
202
	push	eax
203
	add	eax, 7
204
	shr	eax, 3
205
	mov	[.bytes_per_pixel], eax
206
	pop	eax
207
	mul	[.width]
208
	add	eax, 7
209
	shr	eax, 3
210
	mov	[.scanline_len], eax
211
; allocate image
212
	push	Image.bpp24
213
	pop	eax
214
	cmp	[.color_type], 2
215
	jz	@f
216
	mov	al, Image.bpp32
217
	cmp	[.color_type], 6
218
	jz	@f
219
	mov	al, Image.bpp8
220
@@:
221
	stdcall	img.create, [.width], [.height], eax
222
	test	eax, eax
223
	jz	.invalid_chunk
224
	mov	[.image], eax
225
	jmp	.next_chunk
226
.invalid_chunk:
227
.iend:
228
	pop	ecx
229
.eof:
230
	add	esp, .localsize
231
	popad
232
	ret
233
; PLTE chunk
234
.palette:
235
	mov	eax, [.image]
236
	test	eax, eax
237
	jz	.invalid_chunk
238
	cmp	[.color_type], 3
239
	jz	.copy_palette
240
.ignore_chunk:
241
	add	esi, ecx
242
.next_chunk:
243
	lodsd
244
	pop	ecx
245
	jmp	.chunks_loop
246
.copy_palette:
247
	mov	edi, [eax + Image.Palette]
248
	xor	eax, eax
249
	cmp	ecx, 256*3
250
	ja	.next_chunk
251
@@:
252
	sub	ecx, 3
253
	jz	@f
254
	js	.invalid_chunk
255
	lodsd
256
	dec	esi
257
	bswap	eax
258
	shr	eax, 8
259
	stosd
260
	jmp	@b
261
@@:
262
	lodsd
263
	dec	esi
264
	bswap	eax
265
	shr	eax, 8
266
	stosd
267
	jmp	.next_chunk
268
.idat:
269
	jecxz	.next_chunk
270
	cmp	[.idat_read], 0
271
	jnz	@f
272
	lodsb
273
	inc	[.idat_read]
274
	and	al, 0xF
275
	cmp	al, 8
276
	jnz	.invalid_chunk
277
	dec	ecx
278
	jz	.next_chunk
279
@@:
280
	cmp	[.idat_read], 1
281
	jnz	@f
282
	lodsb
283
	inc	[.idat_read]
284
	test	al, 20h
285
	jnz	.invalid_chunk
286
	dec	ecx
287
	jz	.next_chunk
288
@@:
289
	mov	[.cur_chunk_ptr], esi
290
	mov	[.cur_chunk_size], ecx
291
	pop	[.length]
292
	push	eax
293
	push	esp
294
	push	ebp
295
	push	.deflate_callback
296
	call	[deflate_unpack2]
297
	pop	ecx
298
	test	eax, eax
299
	jz	.invalid_chunk
300
; convert PNG unpacked data to RAW data
301
	mov	esi, eax
302
	push	eax ecx
303
; unfilter
304
	mov	edx, [.height]
305
.unfilter_loop_e:
306
	mov	ebx, [.scanline_len]
307
	sub	ecx, 1
308
	jc	.unfilter_done
309
	sub	ecx, ebx
310
	jc	.unfilter_done
311
	movzx	eax, byte [esi]
312
	add	esi, 1
313
	cmp	eax, 4
314
	ja	.next_scanline
315
	jmp	dword [@f + eax*4]
316
align 4
317
@@:
318
	dd	.unfilter_none
319
	dd	.unfilter_sub
320
	dd	.unfilter_up
321
	dd	.unfilter_average
322
	dd	.unfilter_paeth
323
.unfilter_sub:
324
	mov	edi, [.bytes_per_pixel]
325
	add	esi, edi
326
	sub	ebx, edi
327
	jbe	.next_scanline
328
	neg	edi
329
@@:
330
	mov	al, [esi+edi]
331
	add	[esi], al
332
	add	esi, 1
333
	sub	ebx, 1
334
	jnz	@b
335
	jmp	.next_scanline
336
.unfilter_up:
337
	cmp	edx, [.height]
338
	jz	.unfilter_none
339
	lea	edi, [ebx+1]
340
	neg	edi
341
@@:
342
	mov	al, [esi+edi]
343
	add	[esi], al
344
	add	esi, 1
345
	sub	ebx, 1
346
	jnz	@b
347
	jmp	.next_scanline
348
.unfilter_average:
349
	mov	edi, [.bytes_per_pixel]
350
	cmp	edx, [.height]
351
	jz	.unfilter_average_firstline
352
	push	edx
353
	lea	edx, [ebx+1]
354
	neg	edx
355
	sub	ebx, edi
356
@@:
357
	mov	al, [esi+edx]
358
	shr	al, 1
359
	add	[esi], al
360
	add	esi, 1
361
	sub	edi, 1
362
	jnz	@b
363
	mov	edi, [.bytes_per_pixel]
364
	neg	edi
365
	test	ebx, ebx
366
	jz	.unfilter_average_done
367
@@:
368
	mov	al, [esi+edx]
369
	add	al, [esi+edi]
370
	rcr	al, 1
371
	add	[esi], al
372
	add	esi, 1
373
	sub	ebx, 1
374
	jnz	@b
375
.unfilter_average_done:
376
	pop	edx
377
	jmp	.next_scanline
378
.unfilter_average_firstline:
379
	mov	edi, [.bytes_per_pixel]
380
	add	esi, edi
381
	sub	ebx, edi
382
	jbe	.next_scanline
383
	neg	edi
384
@@:
385
	mov	al, [esi+edi]
386
	shr	al, 1
387
	add	[esi], al
388
	add	esi, 1
389
	sub	ebx, 1
390
	jnz	@b
391
	jmp	.unfilter_none
392
.unfilter_paeth:
393
	cmp	edx, [.height]
394
	jz	.unfilter_sub
395
	push	edx
396
	lea	edx, [ebx+1]
397
	mov	edi, [.bytes_per_pixel]
398
	neg	edx
399
	sub	ebx, edi
400
@@:
401
	mov	al, [esi+edx]
402
	add	[esi], al
403
	add	esi, 1
404
	sub	edi, 1
405
	jnz	@b
406
	mov	edi, [.bytes_per_pixel]
407
	neg	edi
408
	test	ebx, ebx
409
	jz	.unfilter_paeth_done
410
	push	ecx
411
@@:
412
	push	ebx
413
; PaethPredictor(Raw(x-bpp) = a, Prior(x) = b, Prior(x-bpp) = c)
414
	movzx	eax, byte [esi+edi]
415
	mov	[.paeth_a], eax
416
	movzx	ecx, byte [esi+edx]
417
	add	edi, edx
418
	mov	[.paeth_b], ecx
419
	add	ecx, eax
420
	movzx	eax, byte [esi+edi]
421
	mov	[.paeth_c], eax
422
	sub	ecx, eax	; ecx = a + b - c = p
423
; calculate pa = abs(p-a), pb = abs(p-b), pc = abs(p-c)
424
	mov	ebx, ecx
425
	sub	ebx, eax	; ebx = p - c
426
	cmp	ebx, 80000000h
427
	sbb	eax, eax	; eax = (p < c) ? 0 : 0xFFFFFFF
428
	not	eax		; eax = (p < c) ? 0xFFFFFFFF : 0
429
	and	eax, ebx	; eax = (p < c) ? p - c : 0
430
	sub	ebx, eax
431
	sub	ebx, eax	; ebx = abs(p-c)
432
	mov	[.paeth_pc], ebx
433
	mov	ebx, ecx
434
	sub	ebx, [.paeth_a]
435
	cmp	ebx, 80000000h
436
	sbb	eax, eax
437
	not	eax
438
	and	eax, ebx
439
	sub	ebx, eax
440
	sub	ebx, eax
441
	mov	[.paeth_pa], ebx
442
	mov	ebx, ecx
443
	sub	ebx, [.paeth_b]
444
	cmp	ebx, 80000000h
445
	sbb	eax, eax
446
	not	eax
447
	and	eax, ebx
448
	sub	ebx, eax
449
	sub	ebx, eax
450
	;mov	[.paeth_pb], ebx
451
; select closest value
452
	push	edx
453
	mov	edx, [.paeth_b]
454
	sub	edx, [.paeth_a]
455
	sub	ebx, [.paeth_pa]
456
	sbb	ecx, ecx	; ecx = (pa > pb) ? 0xFFFFFFFF : 0
457
	sbb	eax, eax	; eax = (pa > pb) ? 0xFFFFFFFF : 0
458
	and	ecx, ebx	; ecx = (pa > pb) ? pb - pa : 0
459
	and	eax, edx	; eax = (pa > pb) ? b - a : 0
460
	add	ecx, [.paeth_pa]	; ecx = (pa > pb) ? pb : pa = min(pa,pb)
461
	add	eax, [.paeth_a]		; eax = (pa > pb) ? b : a
462
	mov	edx, [.paeth_c]
463
	sub	edx, eax
464
	sub	[.paeth_pc], ecx
465
	sbb	ebx, ebx	; ebx = (min(pa,pb) <= pc) ? 0 : 0xFFFFFFFF
466
	and	ebx, edx	; ebx = (min(pa,pb) <= pc) ? 0 : c - eax
467
	add	eax, ebx
468
	pop	edx
469
	add	[esi], al
470
	pop	ebx
471
	sub	edi, edx
472
	add	esi, 1
473
	sub	ebx, 1
474
	jnz	@b
475
	pop	ecx
476
.unfilter_paeth_done:
477
	pop	edx
478
	jmp	.next_scanline
479
.unfilter_none:
480
	add	esi, ebx
481
.next_scanline:
482
	sub	edx, 1
483
	jnz	.unfilter_loop_e
484
.unfilter_done:
485
; unfiltering done, now convert to raw data
486
	pop	ebx esi
487
	push	esi
488
	mov	edx, [.height]
489
	mov	eax, [.image]
490
	mov	edi, [eax + Image.Data]
491
	cmp	[.color_type], 0
492
	jz	.grayscale2
493
	cmp	[.color_type], 2
494
	jz	.rgb2
495
	cmp	[.color_type], 3
496
	jz	.palette2
497
	cmp	[.color_type], 4
498
	jz	.grayscale_alpha2
499
.rgb_alpha2:
500
	cmp	[.bit_depth], 16
501
	jz	.rgb_alpha2_16bit
502
.rgb_alpha2.next:
503
	mov	ecx, [.scanline_len]
504
	sub	ebx, 1
505
	jc	.convert_done
506
	add	esi, 1
507
	sub	ebx, ecx
508
	jc	.convert_done
509
@@:
510
	mov	al, [esi+2]
511
	mov	[edi], al
512
	mov	al, [esi+1]
513
	mov	[edi+1], al
514
	mov	al, [esi]
515
	mov	[edi+2], al
516
	mov	al, [esi+3]
517
	mov	[edi+3], al
1079 diamond 518
	add	esi, 4
519
	add	edi, 4
1014 diamond 520
	sub	ecx, 4
521
	jnz	@b
522
	sub	edx, 1
523
	jnz	.rgb_alpha2.next
524
	jmp	.convert_done
525
.rgb_alpha2_16bit:
526
	mov	ecx, [.scanline_len]
527
	sub	ebx, 1
528
	jc	.convert_done
529
	add	esi, 1
530
	sub	ebx, ecx
531
	jc	.convert_done
532
.rgb_alpha2.loop:
533
 
534
; convert 16 bit sample to 8 bit sample
535
macro convert_16_to_8
536
{
537
local .l1,.l2
538
	xor	ah, 0x80
539
	js	.l1
540
	cmp	al, ah
541
	adc	al, 0
542
	jmp	.l2
543
.l1:
544
	cmp	ah, al
545
	sbb	al, 0
546
.l2:
547
}
548
 
549
	mov	ax, [esi+4]
550
	convert_16_to_8
551
	mov	[edi], al
552
	mov	ax, [esi+2]
553
	convert_16_to_8
554
	mov	[edi+1], al
555
	mov	ax, [esi]
556
	convert_16_to_8
557
	mov	[edi+2], al
558
	;mov	ax, [esi+6]
559
	;convert_16_to_8
560
	;mov	[edi+3], al
561
	add	esi, 8
562
	add	edi, 4
563
	sub	ecx, 8
564
	jnz	.rgb_alpha2.loop
565
	sub	edx, 1
566
	jnz	.rgb_alpha2_16bit
567
	jmp	.convert_done
568
.grayscale2:
569
	push	edi edx
570
	mov	edi, [eax + Image.Palette]
571
	mov	ecx, [.bit_depth]
572
	cmp	cl, 16
573
	jnz	@f
574
	mov	cl, 8
575
@@:
576
	push	1
577
	pop	eax
578
	shl	eax, cl
579
	xchg	eax, ecx
580
	mov	edx, 0x010101
581
	cmp	al, 8
582
	jz	.graypal_common
583
	mov	edx, 0x111111
584
	cmp	al, 4
585
	jz	.graypal_common
586
	mov	edx, 0x555555
587
	cmp	al, 2
588
	jz	.graypal_common
589
	mov	edx, 0xFFFFFF
590
.graypal_common:
591
	xor	eax, eax
592
@@:
593
	stosd
594
	add	eax, edx
595
	loop	@b
596
	pop	edx edi
597
	cmp	[.bit_depth], 16
598
	jz	.grayscale2_16bit
599
.palette2:
600
	cmp	[.bit_depth], 1
601
	jz	.palette2_1bit
602
	cmp	[.bit_depth], 2
603
	jz	.palette2_2bit
604
	cmp	[.bit_depth], 4
605
	jz	.palette2_4bit
606
.palette2_8bit:
607
	mov	ecx, [.scanline_len]
608
	sub	ebx, 1
609
	jc	.convert_done
610
	add	esi, 1
611
	sub	ebx, ecx
612
	jc	.convert_done
613
	push	ecx
614
	shr	ecx, 2
615
	rep	movsd
616
	pop	ecx
617
	and	ecx, 3
618
	rep	movsb
619
	sub	edx, 1
620
	jnz	.palette2_8bit
621
	jmp	.convert_done
622
.palette2_4bit:
623
	sub	ebx, 1
624
	jc	.convert_done
625
	add	esi, 1
626
	sub	ebx, [.scanline_len]
627
	jc	.convert_done
628
	push	edx
629
	mov	ecx, [.width]
630
@@:
631
	mov	al, [esi]
632
	add	esi, 1
633
	mov	dl, al
634
	shr	al, 4
635
	and	dl, 0xF
636
	mov	[edi], al
637
	sub	ecx, 1
638
	jz	@f
639
	mov	[edi+1], dl
640
	add	edi, 2
641
	sub	ecx, 1
642
	jnz	@b
643
	sub	edi, 1
644
@@:
645
	pop	edx
646
	add	edi, 1
647
	sub	edx, 1
648
	jnz	.palette2_4bit
649
	jmp	.convert_done
650
.palette2_2bit:
651
	sub	ebx, 1
652
	jc	.convert_done
653
	add	esi, 1
654
	sub	ebx, [.scanline_len]
655
	jc	.convert_done
656
	push	edx
657
	mov	ecx, [.width]
658
@@:
659
	mov	al, [esi]
660
	add	esi, 1
661
	mov	dl, al
662
	shr	al, 6
663
	and	dl, not 11000000b
664
	mov	[edi], al
665
	add	edi, 1
666
	sub	ecx, 1
667
	jz	@f
668
	mov	al, dl
669
	shr	dl, 4
670
	and	al, not 00110000b
671
	mov	[edi], dl
672
	add	edi, 1
673
	sub	ecx, 1
674
	jz	@f
675
	mov	dl, al
676
	shr	al, 2
677
	and	dl, not 00001100b
678
	mov	[edi], al
679
	add	edi, 1
680
	sub	ecx, 1
681
	jz	@f
682
	mov	[edi], dl
683
	add	edi, 1
684
	sub	ecx, 1
685
	jnz	@b
686
@@:
687
	pop	edx
688
	sub	edx, 1
689
	jnz	.palette2_2bit
690
	jmp	.convert_done
691
.palette2_1bit:
692
	sub	ebx, 1
693
	jc	.convert_done
694
	add	esi, 1
695
	sub	ebx, [.scanline_len]
696
	jc	.convert_done
697
	push	edx
698
	mov	ecx, [.width]
699
@@:
700
	mov	al, [esi]
701
	add	esi, 1
702
repeat 3
703
	mov	dl, al
704
	shr	al, 9-%*2
705
	and	dl, not (1 shl (9-%*2))
706
	mov	[edi], al
707
	add	edi, 1
708
	sub	ecx, 1
709
	jz	@f
710
	mov	al, dl
711
	shr	dl, 8-%*2
712
	and	al, not (1 shl (8-%*2))
713
	mov	[edi], dl
714
	add	edi, 1
715
	sub	ecx, 1
716
	jz	@f
717
end repeat
718
	mov	dl, al
719
	shr	al, 1
720
	and	dl, not (1 shl 1)
721
	mov	[edi], al
722
	add	edi, 1
723
	sub	ecx, 1
724
	jz	@f
725
	mov	[edi], dl
726
	add	edi, 1
727
	sub	ecx, 1
728
	jnz	@b
729
@@:
730
	pop	edx
731
	sub	edx, 1
732
	jnz	.palette2_1bit
733
	jmp	.convert_done
734
.grayscale2_16bit:
735
	mov	ecx, [.scanline_len]
736
	sub	ebx, 1
737
	jc	.convert_done
738
	add	esi, 1
739
	sub	ebx, ecx
740
	jc	.convert_done
741
@@:
1079 diamond 742
	mov	ax, [esi]
743
	add	esi, 2
1014 diamond 744
	convert_16_to_8
1079 diamond 745
	mov	[edi], al
1014 diamond 746
	add	edi, 1
747
	sub	ecx, 2
748
	jnz	@b
749
	sub	edx, 1
750
	jnz	.grayscale2_16bit
751
	jmp	.convert_done
752
.rgb2:
753
	cmp	[.bit_depth], 16
754
	jz	.rgb2_16bit
755
.rgb2.next:
756
	mov	ecx, [.scanline_len]
757
	sub	ebx, 1
758
	jc	.convert_done
759
	add	esi, 1
760
	sub	ebx, ecx
761
	jc	.convert_done
762
@@:
763
	mov	al, [esi+2]
764
	mov	[edi], al
765
	mov	al, [esi+1]
766
	mov	[edi+1], al
767
	mov	al, [esi]
768
	mov	[edi+2], al
769
	add	esi, 3
770
	add	edi, 3
771
	sub	ecx, 3
772
	jnz	@b
773
	sub	edx, 1
774
	jnz	.rgb2.next
775
	jmp	.convert_done
776
.rgb2_16bit:
777
	mov	ecx, [.scanline_len]
778
	sub	ebx, 1
779
	jc	.convert_done
780
	add	esi, 1
781
	sub	ebx, ecx
782
	jc	.convert_done
783
.rgb2.loop:
784
	mov	ax, [esi+4]
785
	convert_16_to_8
786
	mov	[edi], al
787
	mov	ax, [esi+2]
788
	convert_16_to_8
789
	mov	[edi+1], al
790
	mov	ax, [esi]
791
	convert_16_to_8
792
	mov	[edi+2], al
793
	add	esi, 6
794
	add	edi, 3
795
	sub	ecx, 6
796
	jnz	.rgb2.loop
797
	sub	edx, 1
798
	jnz	.rgb2_16bit
799
	jmp	.convert_done
800
.grayscale_alpha2:
801
	cmp	[.bit_depth], 16
802
	jz	.grayscale_alpha2_16bit
803
.grayscale_alpha2.next:
804
	mov	ecx, [.scanline_len]
805
	sub	ebx, 1
806
	jc	.convert_done
807
	add	esi, 1
808
	sub	ebx, ecx
809
	jc	.convert_done
810
@@:
811
	mov	al, [esi]
812
	mov	[edi], al
813
	add	esi, 2
814
	add	edi, 1
815
	sub	ecx, 2
816
	jnz	@b
817
	sub	edx, 1
818
	jnz	.grayscale_alpha2.next
819
	jmp	.convert_done
820
.grayscale_alpha2_16bit:
821
	mov	ecx, [.scanline_len]
822
	sub	ebx, 1
823
	jc	.convert_done
824
	add	esi, 1
825
	sub	ebx, ecx
826
	jc	.convert_done
827
@@:
1079 diamond 828
	mov	ax, [esi]
829
	add	esi, 4
1014 diamond 830
	convert_16_to_8
1079 diamond 831
	mov	[edi], al
1014 diamond 832
	add	edi, 1
833
	sub	ecx, 4
834
	jnz	@b
835
	sub	edx, 1
836
	jnz	.grayscale_alpha2_16bit
837
.convert_done:
838
	pop	ecx
839
	mcall	68, 13
840
	mov	esi, [.cur_chunk_ptr]
841
	add	esi, [.cur_chunk_size]
842
	push	[.length]
843
	jmp	.next_chunk
844
 
845
.deflate_callback:
846
	mov	ebp, [esp+4]
847
	mov	ebx, [esp+8]
848
	xor	eax, eax
849
	mov	esi, [.cur_chunk_size]
850
	mov	[ebx], esi
851
	test	esi, esi
852
	jz	.deflate_callback.ret
853
	mov	eax, [.cur_chunk_ptr]
854
	mov	ecx, [.length]
855
	add	esi, eax
856
	mov	[.cur_chunk_ptr], esi
857
	and	[.cur_chunk_size], 0
858
@@:
859
	sub	ecx, 12
860
	jb	.deflate_callback.ret
861
	cmp	dword [esi+4+4], 'IDAT'
862
	jnz	.deflate_callback.ret
863
	mov	edx, [esi+4]
864
	bswap	edx
865
	sub	ecx, edx
866
	jb	.deflate_callback.ret
867
	add	esi, 4+8
868
	test	edx, edx
869
	jz	@b
870
	mov	[.cur_chunk_size], edx
871
	mov	[.cur_chunk_ptr], esi
872
	mov	[.length], ecx
873
.deflate_callback.ret:
874
	ret	8
875
;endp
876
 
877
img.encode.png:
878
	xor	eax, eax
879
	ret	8