Subversion Repositories Kolibri OS

Rev

Rev 1079 | Go to most recent revision | Details | 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
518
	sub	ecx, 4
519
	jnz	@b
520
	sub	edx, 1
521
	jnz	.rgb_alpha2.next
522
	jmp	.convert_done
523
.rgb_alpha2_16bit:
524
	mov	ecx, [.scanline_len]
525
	sub	ebx, 1
526
	jc	.convert_done
527
	add	esi, 1
528
	sub	ebx, ecx
529
	jc	.convert_done
530
.rgb_alpha2.loop:
531
 
532
; convert 16 bit sample to 8 bit sample
533
macro convert_16_to_8
534
{
535
local .l1,.l2
536
	xor	ah, 0x80
537
	js	.l1
538
	cmp	al, ah
539
	adc	al, 0
540
	jmp	.l2
541
.l1:
542
	cmp	ah, al
543
	sbb	al, 0
544
.l2:
545
}
546
 
547
	mov	ax, [esi+4]
548
	convert_16_to_8
549
	mov	[edi], al
550
	mov	ax, [esi+2]
551
	convert_16_to_8
552
	mov	[edi+1], al
553
	mov	ax, [esi]
554
	convert_16_to_8
555
	mov	[edi+2], al
556
	;mov	ax, [esi+6]
557
	;convert_16_to_8
558
	;mov	[edi+3], al
559
	add	esi, 8
560
	add	edi, 4
561
	sub	ecx, 8
562
	jnz	.rgb_alpha2.loop
563
	sub	edx, 1
564
	jnz	.rgb_alpha2_16bit
565
	jmp	.convert_done
566
.grayscale2:
567
	push	edi edx
568
	mov	edi, [eax + Image.Palette]
569
	mov	ecx, [.bit_depth]
570
	cmp	cl, 16
571
	jnz	@f
572
	mov	cl, 8
573
@@:
574
	push	1
575
	pop	eax
576
	shl	eax, cl
577
	xchg	eax, ecx
578
	mov	edx, 0x010101
579
	cmp	al, 8
580
	jz	.graypal_common
581
	mov	edx, 0x111111
582
	cmp	al, 4
583
	jz	.graypal_common
584
	mov	edx, 0x555555
585
	cmp	al, 2
586
	jz	.graypal_common
587
	mov	edx, 0xFFFFFF
588
.graypal_common:
589
	xor	eax, eax
590
@@:
591
	stosd
592
	add	eax, edx
593
	loop	@b
594
	pop	edx edi
595
	cmp	[.bit_depth], 16
596
	jz	.grayscale2_16bit
597
.palette2:
598
	cmp	[.bit_depth], 1
599
	jz	.palette2_1bit
600
	cmp	[.bit_depth], 2
601
	jz	.palette2_2bit
602
	cmp	[.bit_depth], 4
603
	jz	.palette2_4bit
604
.palette2_8bit:
605
	mov	ecx, [.scanline_len]
606
	sub	ebx, 1
607
	jc	.convert_done
608
	add	esi, 1
609
	sub	ebx, ecx
610
	jc	.convert_done
611
	push	ecx
612
	shr	ecx, 2
613
	rep	movsd
614
	pop	ecx
615
	and	ecx, 3
616
	rep	movsb
617
	sub	edx, 1
618
	jnz	.palette2_8bit
619
	jmp	.convert_done
620
.palette2_4bit:
621
	sub	ebx, 1
622
	jc	.convert_done
623
	add	esi, 1
624
	sub	ebx, [.scanline_len]
625
	jc	.convert_done
626
	push	edx
627
	mov	ecx, [.width]
628
@@:
629
	mov	al, [esi]
630
	add	esi, 1
631
	mov	dl, al
632
	shr	al, 4
633
	and	dl, 0xF
634
	mov	[edi], al
635
	sub	ecx, 1
636
	jz	@f
637
	mov	[edi+1], dl
638
	add	edi, 2
639
	sub	ecx, 1
640
	jnz	@b
641
	sub	edi, 1
642
@@:
643
	pop	edx
644
	add	edi, 1
645
	sub	edx, 1
646
	jnz	.palette2_4bit
647
	jmp	.convert_done
648
.palette2_2bit:
649
	sub	ebx, 1
650
	jc	.convert_done
651
	add	esi, 1
652
	sub	ebx, [.scanline_len]
653
	jc	.convert_done
654
	push	edx
655
	mov	ecx, [.width]
656
@@:
657
	mov	al, [esi]
658
	add	esi, 1
659
	mov	dl, al
660
	shr	al, 6
661
	and	dl, not 11000000b
662
	mov	[edi], al
663
	add	edi, 1
664
	sub	ecx, 1
665
	jz	@f
666
	mov	al, dl
667
	shr	dl, 4
668
	and	al, not 00110000b
669
	mov	[edi], dl
670
	add	edi, 1
671
	sub	ecx, 1
672
	jz	@f
673
	mov	dl, al
674
	shr	al, 2
675
	and	dl, not 00001100b
676
	mov	[edi], al
677
	add	edi, 1
678
	sub	ecx, 1
679
	jz	@f
680
	mov	[edi], dl
681
	add	edi, 1
682
	sub	ecx, 1
683
	jnz	@b
684
@@:
685
	pop	edx
686
	sub	edx, 1
687
	jnz	.palette2_2bit
688
	jmp	.convert_done
689
.palette2_1bit:
690
	sub	ebx, 1
691
	jc	.convert_done
692
	add	esi, 1
693
	sub	ebx, [.scanline_len]
694
	jc	.convert_done
695
	push	edx
696
	mov	ecx, [.width]
697
@@:
698
	mov	al, [esi]
699
	add	esi, 1
700
repeat 3
701
	mov	dl, al
702
	shr	al, 9-%*2
703
	and	dl, not (1 shl (9-%*2))
704
	mov	[edi], al
705
	add	edi, 1
706
	sub	ecx, 1
707
	jz	@f
708
	mov	al, dl
709
	shr	dl, 8-%*2
710
	and	al, not (1 shl (8-%*2))
711
	mov	[edi], dl
712
	add	edi, 1
713
	sub	ecx, 1
714
	jz	@f
715
end repeat
716
	mov	dl, al
717
	shr	al, 1
718
	and	dl, not (1 shl 1)
719
	mov	[edi], al
720
	add	edi, 1
721
	sub	ecx, 1
722
	jz	@f
723
	mov	[edi], dl
724
	add	edi, 1
725
	sub	ecx, 1
726
	jnz	@b
727
@@:
728
	pop	edx
729
	sub	edx, 1
730
	jnz	.palette2_1bit
731
	jmp	.convert_done
732
.grayscale2_16bit:
733
	mov	ecx, [.scanline_len]
734
	sub	ebx, 1
735
	jc	.convert_done
736
	add	esi, 1
737
	sub	ebx, ecx
738
	jc	.convert_done
739
@@:
740
	convert_16_to_8
741
	add	esi, 2
742
	add	edi, 1
743
	sub	ecx, 2
744
	jnz	@b
745
	sub	edx, 1
746
	jnz	.grayscale2_16bit
747
	jmp	.convert_done
748
.rgb2:
749
	cmp	[.bit_depth], 16
750
	jz	.rgb2_16bit
751
.rgb2.next:
752
	mov	ecx, [.scanline_len]
753
	sub	ebx, 1
754
	jc	.convert_done
755
	add	esi, 1
756
	sub	ebx, ecx
757
	jc	.convert_done
758
@@:
759
	mov	al, [esi+2]
760
	mov	[edi], al
761
	mov	al, [esi+1]
762
	mov	[edi+1], al
763
	mov	al, [esi]
764
	mov	[edi+2], al
765
	add	esi, 3
766
	add	edi, 3
767
	sub	ecx, 3
768
	jnz	@b
769
	sub	edx, 1
770
	jnz	.rgb2.next
771
	jmp	.convert_done
772
.rgb2_16bit:
773
	mov	ecx, [.scanline_len]
774
	sub	ebx, 1
775
	jc	.convert_done
776
	add	esi, 1
777
	sub	ebx, ecx
778
	jc	.convert_done
779
.rgb2.loop:
780
	mov	ax, [esi+4]
781
	convert_16_to_8
782
	mov	[edi], al
783
	mov	ax, [esi+2]
784
	convert_16_to_8
785
	mov	[edi+1], al
786
	mov	ax, [esi]
787
	convert_16_to_8
788
	mov	[edi+2], al
789
	add	esi, 6
790
	add	edi, 3
791
	sub	ecx, 6
792
	jnz	.rgb2.loop
793
	sub	edx, 1
794
	jnz	.rgb2_16bit
795
	jmp	.convert_done
796
.grayscale_alpha2:
797
	cmp	[.bit_depth], 16
798
	jz	.grayscale_alpha2_16bit
799
.grayscale_alpha2.next:
800
	mov	ecx, [.scanline_len]
801
	sub	ebx, 1
802
	jc	.convert_done
803
	add	esi, 1
804
	sub	ebx, ecx
805
	jc	.convert_done
806
@@:
807
	mov	al, [esi]
808
	mov	[edi], al
809
	add	esi, 2
810
	add	edi, 1
811
	sub	ecx, 2
812
	jnz	@b
813
	sub	edx, 1
814
	jnz	.grayscale_alpha2.next
815
	jmp	.convert_done
816
.grayscale_alpha2_16bit:
817
	mov	ecx, [.scanline_len]
818
	sub	ebx, 1
819
	jc	.convert_done
820
	add	esi, 1
821
	sub	ebx, ecx
822
	jc	.convert_done
823
@@:
824
	convert_16_to_8
825
	add	esi, 4
826
	add	edi, 1
827
	sub	ecx, 4
828
	jnz	@b
829
	sub	edx, 1
830
	jnz	.grayscale_alpha2_16bit
831
.convert_done:
832
	pop	ecx
833
	mcall	68, 13
834
	mov	esi, [.cur_chunk_ptr]
835
	add	esi, [.cur_chunk_size]
836
	push	[.length]
837
	jmp	.next_chunk
838
 
839
.deflate_callback:
840
	mov	ebp, [esp+4]
841
	mov	ebx, [esp+8]
842
	xor	eax, eax
843
	mov	esi, [.cur_chunk_size]
844
	mov	[ebx], esi
845
	test	esi, esi
846
	jz	.deflate_callback.ret
847
	mov	eax, [.cur_chunk_ptr]
848
	mov	ecx, [.length]
849
	add	esi, eax
850
	mov	[.cur_chunk_ptr], esi
851
	and	[.cur_chunk_size], 0
852
@@:
853
	sub	ecx, 12
854
	jb	.deflate_callback.ret
855
	cmp	dword [esi+4+4], 'IDAT'
856
	jnz	.deflate_callback.ret
857
	mov	edx, [esi+4]
858
	bswap	edx
859
	sub	ecx, edx
860
	jb	.deflate_callback.ret
861
	add	esi, 4+8
862
	test	edx, edx
863
	jz	@b
864
	mov	[.cur_chunk_size], edx
865
	mov	[.cur_chunk_ptr], esi
866
	mov	[.length], ecx
867
.deflate_callback.ret:
868
	ret	8
869
;endp
870
 
871
img.encode.png:
872
	xor	eax, eax
873
	ret	8