Subversion Repositories Kolibri OS

Rev

Rev 1102 | Rev 2733 | 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
;;================================================================================================;;
1102 diamond 52
;;proc img.decode.png _data, _length, _options ;//////////////////////////////////////////////////;;
1014 diamond 53
img.decode.png:
54
	xor	eax, eax	; .image = 0
55
	pushad
56
	mov	ebp, esp
1308 diamond 57
.localsize = 29*4
1014 diamond 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	?
1308 diamond 65
.bits_per_pixel dd	?
66
.size_rest	dd	?
1014 diamond 67
.cur_chunk_ptr	dd	?
68
.cur_chunk_size	dd	?
1308 diamond 69
.allocated	dd	?
1014 diamond 70
.paeth_a	dd	?
71
.paeth_b	dd	?
72
.paeth_c	dd	?
73
.paeth_pa	dd	?
74
.paeth_pb	dd	?
75
.paeth_pc	dd	?
1308 diamond 76
.i		dd	?
77
.j		dd	?
78
; variables to handle interlace
79
.row_distance	dd	?	; diff between two consecutives rows in destination
80
.col_distance	dd	?	; summand for moving to next row in source
81
.row_increment	dd	?
82
.col_increment	dd	?
83
.block_height	dd	?
84
.block_width	dd	?
85
.interlace	db	?	; 0 if not interlaced, 1 if interlaced
86
.row_increment_shift db	?
87
.col_increment_shift db	?
88
.shift		db	?	; shift for current src byte
89
.starting_row	dd	?
90
.starting_col	dd	?
1014 diamond 91
.idat_read	dd	?
92
	rb	1Ch
93
.image		dd	?
94
	rd	1
95
.data		dd	?
96
.length		dd	?
1102 diamond 97
.options	dd	?
1014 diamond 98
end virtual
1308 diamond 99
	push	eax	; .idat_read = 0
100
	push	eax	; .starting_col = 0
101
	push	eax	; .starting_row = 0
102
	push	eax	; .col_increment_shift, .row_increment_shift
103
	inc	eax
104
	push	eax	; .block_width
105
	push	eax	; .block_height
106
	push	eax	; .col_increment
107
	push	eax	; .row_increment
108
	sub	esp, .localsize-32
1014 diamond 109
; load deflate unpacker, if not yet
110
; acquire mutex
111
@@:
112
	push	1
113
	pop	eax
114
	xchg	[deflate_loader_mutex], eax	; 'xchg' has an implicit 'lock' prefix
115
	test	eax, eax
116
	jz	@f
117
	mcall	5, 1
118
	jmp	@b
119
@@:
120
	cmp	[deflate_unpack2], __deflate_unpack2_import_name__
121
	jnz	.deflate_loaded
122
; do loading
123
	invoke	dll.load, @IMPORT
124
	test	eax, eax
125
	jz	.deflate_loaded
126
	add	esp, .localsize
127
	popad
128
	mov	[deflate_loader_mutex], eax
1102 diamond 129
	ret	12
1014 diamond 130
.deflate_loaded:
131
; release mutex
132
	mov	[deflate_loader_mutex], 0
133
; ok, continue
134
	mov	esi, [.data]		; esi -> data
135
	mov	ecx, [.length]		; ecx = length
136
; the signature has been already checked in img.is.png
137
	lodsd
138
	lodsd
139
	sub	ecx, 8
140
	xor	ebx, ebx	; no image allocated
141
.chunks_loop:
142
	sub	ecx, 12
143
	jc	.eof
144
	lodsd	; chunk length
145
	bswap	eax
146
	sub	ecx, eax
147
	jc	.eof
148
	push	ecx	; save length of data rest
149
	xchg	eax, ecx	; ecx = size of data in the chunk
150
	lodsd	; chunk type
151
	cmp	eax, 'IHDR'
152
	jz	.ihdr
153
	cmp	eax, 'IDAT'
154
	jz	.idat
155
	cmp	eax, 'IEND'
156
	jz	.iend
157
	cmp	eax, 'PLTE'
158
	jz	.palette
159
; unrecognized chunk, ignore
160
	lea	esi, [esi+ecx+4]
161
	pop	ecx
162
	jmp	.chunks_loop
163
; IHDR chunk
164
.ihdr:
165
	cmp	ecx, 13
166
	jnz	.invalid_chunk
167
	cmp	[.image], 0
168
	jnz	.invalid_chunk
169
; read image characteristics
170
	lodsd
171
	bswap	eax
172
	mov	[.width], eax
173
	lodsd
174
	bswap	eax
175
	mov	[.height], eax
176
	xor	eax, eax
177
	lea	ebx, [eax+1]
178
	lodsb
179
	cmp	al, 16
180
	ja	.invalid_chunk
181
	test	al, al
182
	jz	.invalid_chunk
183
	lea	edx, [eax-1]
184
	test	al, dl
185
	jnz	.invalid_chunk
186
	mov	[.bit_depth], eax
187
	lodsb
188
	test	al, not 7
189
	jnz	.invalid_chunk
190
	mov	[.color_type], eax
191
	lodsb
192
	test	al, al
193
	jnz	.invalid_chunk	; only compression method 0 is defined
194
	lodsb
195
	test	al, al
196
	jnz	.invalid_chunk	; only filtering method 0 is defined
197
	lodsb
1308 diamond 198
	cmp	al, 1
199
	ja	.invalid_chunk	; only interlacing methods 0 and 1 are defined
200
	mov	[.interlace], al
1014 diamond 201
; check for correctness and calculate bytes_per_pixel and scanline_len
202
	mov	eax, [.bit_depth]
203
	mov	edx, [.color_type]
204
	dec	edx
205
	js	.grayscale1
206
	dec	edx
207
	jz	.rgb1
208
	dec	edx
209
	jz	.palette1
210
	dec	edx
211
	jz	.grayscale_alpha1
212
	dec	edx
213
	dec	edx
214
	jnz	.invalid_chunk
215
.rgb_alpha1:
216
	inc	ebx
217
.rgb1:
218
	inc	ebx
219
.grayscale_alpha1:
220
	inc	ebx
221
	cmp	al, 8
222
	jb	.invalid_chunk
223
	jmp	@f
224
.palette1:
225
	cmp	al, 8
226
	ja	.invalid_chunk
227
.grayscale1:
228
@@:
229
	mul	ebx
1308 diamond 230
	mov	[.bits_per_pixel], eax
1014 diamond 231
	add	eax, 7
232
	shr	eax, 3
233
	mov	[.bytes_per_pixel], eax
234
; allocate image
235
	push	Image.bpp24
236
	pop	eax
237
	cmp	[.color_type], 2
238
	jz	@f
239
	mov	al, Image.bpp32
240
	cmp	[.color_type], 6
241
	jz	@f
242
	mov	al, Image.bpp8
243
@@:
244
	stdcall	img.create, [.width], [.height], eax
245
	test	eax, eax
246
	jz	.invalid_chunk
247
	mov	[.image], eax
248
	jmp	.next_chunk
249
.invalid_chunk:
250
.iend:
251
	pop	ecx
252
.eof:
253
	add	esp, .localsize
254
	popad
1102 diamond 255
	ret	12
1014 diamond 256
; PLTE chunk
257
.palette:
258
	mov	eax, [.image]
259
	test	eax, eax
260
	jz	.invalid_chunk
261
	cmp	[.color_type], 3
262
	jz	.copy_palette
263
.ignore_chunk:
264
	add	esi, ecx
265
.next_chunk:
266
	lodsd
267
	pop	ecx
268
	jmp	.chunks_loop
269
.copy_palette:
270
	mov	edi, [eax + Image.Palette]
271
	xor	eax, eax
272
	cmp	ecx, 256*3
273
	ja	.next_chunk
274
@@:
275
	sub	ecx, 3
276
	jz	@f
277
	js	.invalid_chunk
278
	lodsd
279
	dec	esi
280
	bswap	eax
281
	shr	eax, 8
282
	stosd
283
	jmp	@b
284
@@:
285
	lodsd
286
	dec	esi
287
	bswap	eax
288
	shr	eax, 8
289
	stosd
290
	jmp	.next_chunk
291
.idat:
292
	jecxz	.next_chunk
293
	cmp	[.idat_read], 0
294
	jnz	@f
295
	lodsb
296
	inc	[.idat_read]
297
	and	al, 0xF
298
	cmp	al, 8
299
	jnz	.invalid_chunk
300
	dec	ecx
301
	jz	.next_chunk
302
@@:
303
	cmp	[.idat_read], 1
304
	jnz	@f
305
	lodsb
306
	inc	[.idat_read]
307
	test	al, 20h
308
	jnz	.invalid_chunk
309
	dec	ecx
310
	jz	.next_chunk
311
@@:
312
	mov	[.cur_chunk_ptr], esi
313
	mov	[.cur_chunk_size], ecx
314
	pop	[.length]
315
	push	eax
316
	push	esp
317
	push	ebp
318
	push	.deflate_callback
319
	call	[deflate_unpack2]
320
	pop	ecx
321
	test	eax, eax
322
	jz	.invalid_chunk
323
; convert PNG unpacked data to RAW data
324
	mov	esi, eax
1308 diamond 325
	mov	[.allocated], eax
326
	mov	[.size_rest], ecx
327
; unfilter and deinterlace
328
; .interlace_pass, .starting_row and .starting_col have been already set to 0
329
; .block_width, .block_height, .col_increment, .row_increment were set
330
; to values for non-interlaced images; correct if necessary
331
	cmp	[.interlace], 0
332
	jz	.deinterlace_loop
333
	push	8
334
	pop	eax
335
	mov	[.row_increment], eax
336
	mov	[.col_increment], eax
337
	mov	[.block_height], eax
338
	mov	[.block_width], eax
339
	mov	[.row_increment_shift], 3
340
	mov	[.col_increment_shift], 3
341
.deinterlace_loop:
1014 diamond 342
	mov	edx, [.height]
1308 diamond 343
	cmp	edx, [.starting_row]
344
	jbe	.deinterlace_next
345
	mov	ebx, [.width]
346
	sub	ebx, [.starting_col]
347
	jbe	.deinterlace_next
348
	mov	cl, [.col_increment_shift]
349
	add	ebx, [.col_increment]
350
	dec	ebx
351
	shr	ebx, cl
352
	mov	eax, [.bits_per_pixel]
353
	imul	eax, ebx
354
	add	eax, 7
355
	shr	eax, 3
356
	mov	[.scanline_len], eax
357
	shl	ebx, cl
358
	mov	[.col_distance], ebx
359
; Unfilter
360
	mov	ecx, [.size_rest]
361
	push	esi
1014 diamond 362
.unfilter_loop_e:
363
	mov	ebx, [.scanline_len]
364
	sub	ecx, 1
1308 diamond 365
	jc	.unfilter_abort
1014 diamond 366
	sub	ecx, ebx
1308 diamond 367
	jc	.unfilter_abort
1014 diamond 368
	movzx	eax, byte [esi]
369
	add	esi, 1
370
	cmp	eax, 4
371
	ja	.next_scanline
372
	jmp	dword [@f + eax*4]
373
align 4
374
@@:
375
	dd	.unfilter_none
376
	dd	.unfilter_sub
377
	dd	.unfilter_up
378
	dd	.unfilter_average
379
	dd	.unfilter_paeth
380
.unfilter_sub:
381
	mov	edi, [.bytes_per_pixel]
382
	add	esi, edi
383
	sub	ebx, edi
384
	jbe	.next_scanline
385
	neg	edi
386
@@:
387
	mov	al, [esi+edi]
388
	add	[esi], al
389
	add	esi, 1
390
	sub	ebx, 1
391
	jnz	@b
392
	jmp	.next_scanline
393
.unfilter_up:
394
	cmp	edx, [.height]
395
	jz	.unfilter_none
396
	lea	edi, [ebx+1]
397
	neg	edi
398
@@:
399
	mov	al, [esi+edi]
400
	add	[esi], al
401
	add	esi, 1
402
	sub	ebx, 1
403
	jnz	@b
404
	jmp	.next_scanline
405
.unfilter_average:
406
	mov	edi, [.bytes_per_pixel]
407
	cmp	edx, [.height]
408
	jz	.unfilter_average_firstline
409
	push	edx
410
	lea	edx, [ebx+1]
411
	neg	edx
412
	sub	ebx, edi
413
@@:
414
	mov	al, [esi+edx]
415
	shr	al, 1
416
	add	[esi], al
417
	add	esi, 1
418
	sub	edi, 1
419
	jnz	@b
420
	mov	edi, [.bytes_per_pixel]
421
	neg	edi
422
	test	ebx, ebx
423
	jz	.unfilter_average_done
424
@@:
425
	mov	al, [esi+edx]
426
	add	al, [esi+edi]
427
	rcr	al, 1
428
	add	[esi], al
429
	add	esi, 1
430
	sub	ebx, 1
431
	jnz	@b
432
.unfilter_average_done:
433
	pop	edx
434
	jmp	.next_scanline
435
.unfilter_average_firstline:
436
	mov	edi, [.bytes_per_pixel]
437
	add	esi, edi
438
	sub	ebx, edi
439
	jbe	.next_scanline
440
	neg	edi
441
@@:
442
	mov	al, [esi+edi]
443
	shr	al, 1
444
	add	[esi], al
445
	add	esi, 1
446
	sub	ebx, 1
447
	jnz	@b
448
	jmp	.unfilter_none
449
.unfilter_paeth:
450
	cmp	edx, [.height]
451
	jz	.unfilter_sub
452
	push	edx
453
	lea	edx, [ebx+1]
454
	mov	edi, [.bytes_per_pixel]
455
	neg	edx
456
	sub	ebx, edi
457
@@:
458
	mov	al, [esi+edx]
459
	add	[esi], al
460
	add	esi, 1
461
	sub	edi, 1
462
	jnz	@b
463
	mov	edi, [.bytes_per_pixel]
464
	neg	edi
465
	test	ebx, ebx
466
	jz	.unfilter_paeth_done
467
	push	ecx
468
@@:
469
	push	ebx
470
; PaethPredictor(Raw(x-bpp) = a, Prior(x) = b, Prior(x-bpp) = c)
471
	movzx	eax, byte [esi+edi]
472
	mov	[.paeth_a], eax
473
	movzx	ecx, byte [esi+edx]
474
	add	edi, edx
475
	mov	[.paeth_b], ecx
476
	add	ecx, eax
477
	movzx	eax, byte [esi+edi]
478
	mov	[.paeth_c], eax
479
	sub	ecx, eax	; ecx = a + b - c = p
480
; calculate pa = abs(p-a), pb = abs(p-b), pc = abs(p-c)
481
	mov	ebx, ecx
482
	sub	ebx, eax	; ebx = p - c
483
	cmp	ebx, 80000000h
484
	sbb	eax, eax	; eax = (p < c) ? 0 : 0xFFFFFFF
485
	not	eax		; eax = (p < c) ? 0xFFFFFFFF : 0
486
	and	eax, ebx	; eax = (p < c) ? p - c : 0
487
	sub	ebx, eax
488
	sub	ebx, eax	; ebx = abs(p-c)
489
	mov	[.paeth_pc], ebx
490
	mov	ebx, ecx
491
	sub	ebx, [.paeth_a]
492
	cmp	ebx, 80000000h
493
	sbb	eax, eax
494
	not	eax
495
	and	eax, ebx
496
	sub	ebx, eax
497
	sub	ebx, eax
498
	mov	[.paeth_pa], ebx
499
	mov	ebx, ecx
500
	sub	ebx, [.paeth_b]
501
	cmp	ebx, 80000000h
502
	sbb	eax, eax
503
	not	eax
504
	and	eax, ebx
505
	sub	ebx, eax
506
	sub	ebx, eax
507
	;mov	[.paeth_pb], ebx
508
; select closest value
509
	push	edx
510
	mov	edx, [.paeth_b]
511
	sub	edx, [.paeth_a]
512
	sub	ebx, [.paeth_pa]
513
	sbb	ecx, ecx	; ecx = (pa > pb) ? 0xFFFFFFFF : 0
514
	sbb	eax, eax	; eax = (pa > pb) ? 0xFFFFFFFF : 0
515
	and	ecx, ebx	; ecx = (pa > pb) ? pb - pa : 0
516
	and	eax, edx	; eax = (pa > pb) ? b - a : 0
517
	add	ecx, [.paeth_pa]	; ecx = (pa > pb) ? pb : pa = min(pa,pb)
518
	add	eax, [.paeth_a]		; eax = (pa > pb) ? b : a
519
	mov	edx, [.paeth_c]
520
	sub	edx, eax
521
	sub	[.paeth_pc], ecx
522
	sbb	ebx, ebx	; ebx = (min(pa,pb) <= pc) ? 0 : 0xFFFFFFFF
523
	and	ebx, edx	; ebx = (min(pa,pb) <= pc) ? 0 : c - eax
524
	add	eax, ebx
525
	pop	edx
526
	add	[esi], al
527
	pop	ebx
528
	sub	edi, edx
529
	add	esi, 1
530
	sub	ebx, 1
531
	jnz	@b
532
	pop	ecx
533
.unfilter_paeth_done:
534
	pop	edx
535
	jmp	.next_scanline
536
.unfilter_none:
537
	add	esi, ebx
538
.next_scanline:
1308 diamond 539
	sub	edx, [.row_increment]
540
	jc	.unfilter_done
541
	cmp	edx, [.starting_row]
542
	jbe	.unfilter_done
543
	jmp	.unfilter_loop_e
544
.unfilter_abort:
545
	xor	ecx, ecx
1014 diamond 546
.unfilter_done:
547
; unfiltering done, now convert to raw data
1308 diamond 548
; with deinterlacing if needed
549
	pop	esi
550
	mov	ebx, [.image]
551
	mov	eax, [.width]
552
	call	img._.get_scanline_len
553
	mov	[.row_distance], eax
554
	mov	eax, [.row_increment]
555
	mul	[.width]
556
	sub	eax, [.col_distance]
557
	call	img._.get_scanline_len
558
	mov	[.col_distance], eax
559
	mov	edi, [ebx + Image.Data]
560
	mov	eax, [.starting_row]
561
	mul	[.width]
562
	add	eax, [.starting_col]
563
	call	img._.get_scanline_len
564
	add	edi, eax
565
	mov	eax, ebx
566
	mov	ebx, [.size_rest]
567
	mov	[.size_rest], ecx
1014 diamond 568
	mov	edx, [.height]
1308 diamond 569
	sub	edx, [.starting_row]
570
	mov	[.j], edx
1014 diamond 571
	cmp	[.color_type], 0
572
	jz	.grayscale2
573
	cmp	[.color_type], 2
574
	jz	.rgb2
575
	cmp	[.color_type], 3
576
	jz	.palette2
577
	cmp	[.color_type], 4
578
	jz	.grayscale_alpha2
579
.rgb_alpha2:
580
	cmp	[.bit_depth], 16
581
	jz	.rgb_alpha2_16bit
582
.rgb_alpha2.next:
583
	sub	ebx, 1
584
	jc	.convert_done
585
	add	esi, 1
1308 diamond 586
	sub	ebx, [.scanline_len]
1014 diamond 587
	jc	.convert_done
1308 diamond 588
	mov	ecx, [.width]
589
	sub	ecx, [.starting_col]
590
	mov	[.i], ecx
591
.rgb_alpha2.extloop:
592
 
593
macro init_block
594
{
595
	push	ebx
596
	mov	eax, [.col_increment]
597
	mov	edx, [.j]
598
	cmp	edx, [.block_height]
599
	jb	@f
600
	mov	edx, [.block_height]
1014 diamond 601
@@:
1308 diamond 602
	mov	ebx, [.i]
603
	cmp	ebx, [.block_width]
604
	jb	@f
605
	mov	ebx, [.block_width]
606
@@:
607
}
608
 
609
	init_block
610
	lea	eax, [edi+eax*4]
611
	push	eax
612
.rgb_alpha2.innloop1:
613
	push	edi
614
	mov	ecx, ebx
615
.rgb_alpha2.innloop2:
1014 diamond 616
	mov	al, [esi+2]
617
	mov	[edi], al
618
	mov	al, [esi+1]
619
	mov	[edi+1], al
620
	mov	al, [esi]
621
	mov	[edi+2], al
622
	mov	al, [esi+3]
623
	mov	[edi+3], al
1308 diamond 624
	add	edi, 4
625
	dec	ecx
626
	jnz	.rgb_alpha2.innloop2
627
	pop	edi
628
	add	edi, [.row_distance]
629
	dec	edx
630
	jnz	.rgb_alpha2.innloop1
631
	pop	edi ebx
1079 diamond 632
	add	esi, 4
1308 diamond 633
	mov	eax, [.col_increment]
634
	sub	[.i], eax
635
	ja	.rgb_alpha2.extloop
636
	add	edi, [.col_distance]
637
	mov	eax, [.row_increment]
638
	sub	[.j], eax
639
	ja	.rgb_alpha2.next
1014 diamond 640
	jmp	.convert_done
641
.rgb_alpha2_16bit:
642
	sub	ebx, 1
643
	jc	.convert_done
644
	add	esi, 1
1308 diamond 645
	sub	ebx, [.scanline_len]
1014 diamond 646
	jc	.convert_done
1308 diamond 647
	mov	ecx, [.width]
648
	sub	ecx, [.starting_col]
649
	mov	[.i], ecx
650
.rgb_alpha2_16bit.loop:
651
	init_block
652
	lea	eax, [edi+eax*4]
653
	push	eax
1014 diamond 654
 
655
; convert 16 bit sample to 8 bit sample
656
macro convert_16_to_8
657
{
658
local .l1,.l2
659
	xor	ah, 0x80
660
	js	.l1
661
	cmp	al, ah
662
	adc	al, 0
663
	jmp	.l2
664
.l1:
665
	cmp	ah, al
666
	sbb	al, 0
667
.l2:
668
}
669
 
1308 diamond 670
.rgb_alpha2_16bit.innloop1:
671
	push	edi
672
	mov	ecx, ebx
673
.rgb_alpha2_16bit.innloop2:
1014 diamond 674
	mov	ax, [esi+4]
675
	convert_16_to_8
676
	mov	[edi], al
677
	mov	ax, [esi+2]
678
	convert_16_to_8
679
	mov	[edi+1], al
680
	mov	ax, [esi]
681
	convert_16_to_8
682
	mov	[edi+2], al
683
	;mov	ax, [esi+6]
684
	;convert_16_to_8
685
	;mov	[edi+3], al
1308 diamond 686
	add	edi, 4
687
	dec	ecx
688
	jnz	.rgb_alpha2_16bit.innloop2
689
	pop	edi
690
	add	edi, [.row_distance]
691
	dec	edx
692
	jnz	.rgb_alpha2_16bit.innloop1
693
	pop	edi ebx
1014 diamond 694
	add	esi, 8
1308 diamond 695
	mov	eax, [.col_increment]
696
	sub	[.i], eax
697
	ja	.rgb_alpha2_16bit.loop
698
	add	edi, [.col_distance]
699
	mov	eax, [.row_increment]
700
	sub	[.j], eax
701
	ja	.rgb_alpha2_16bit
1014 diamond 702
	jmp	.convert_done
703
.grayscale2:
1308 diamond 704
	call	.create_grayscale_palette
1014 diamond 705
	cmp	[.bit_depth], 16
706
	jz	.grayscale2_16bit
707
.palette2:
708
	cmp	[.bit_depth], 1
709
	jz	.palette2_1bit
710
	cmp	[.bit_depth], 2
711
	jz	.palette2_2bit
712
	cmp	[.bit_depth], 4
713
	jz	.palette2_4bit
714
.palette2_8bit:
715
	sub	ebx, 1
716
	jc	.convert_done
717
	add	esi, 1
1308 diamond 718
	sub	ebx, [.scanline_len]
1014 diamond 719
	jc	.convert_done
1308 diamond 720
	mov	ecx, [.width]
721
	sub	ecx, [.starting_col]
722
	mov	[.i], ecx
723
.palette2_8bit.extloop:
724
	init_block
725
	add	eax, edi
726
	push	eax
727
	mov	al, [esi]
728
	inc	esi
729
macro block_byte_innerloop extloop
730
{
731
local .l1
732
.l1:
733
	mov	ecx, ebx
734
	rep	stosb
735
	sub	edi, ebx
736
	add	edi, [.row_distance]
737
	dec	edx
738
	jnz	.l1
739
	pop	edi ebx
740
	mov	eax, [.col_increment]
741
	sub	[.i], eax
742
	ja	extloop
743
	add	edi, [.col_distance]
744
	mov	eax, [.row_increment]
745
	sub	[.j], eax
746
}
747
	block_byte_innerloop .palette2_8bit.extloop
748
	ja	.palette2_8bit
1014 diamond 749
	jmp	.convert_done
750
.palette2_4bit:
751
	sub	ebx, 1
752
	jc	.convert_done
753
	add	esi, 1
754
	sub	ebx, [.scanline_len]
755
	jc	.convert_done
756
	mov	ecx, [.width]
1308 diamond 757
	sub	ecx, [.starting_col]
758
	mov	[.i], ecx
759
	mov	[.shift], 0
760
.palette2_4bit.extloop:
761
	init_block
762
	add	eax, edi
763
	push	eax
764
	xor	[.shift], 1
765
	jz	.palette2_4bit.shifted
1014 diamond 766
	mov	al, [esi]
1308 diamond 767
	inc	esi
1014 diamond 768
	shr	al, 4
1308 diamond 769
	jmp	@f
770
.palette2_4bit.shifted:
771
	mov	al, [esi-1]
772
	and	al, 0xF
1014 diamond 773
@@:
1308 diamond 774
	block_byte_innerloop .palette2_4bit.extloop
775
	ja	.palette2_4bit
1014 diamond 776
	jmp	.convert_done
777
.palette2_2bit:
778
	sub	ebx, 1
779
	jc	.convert_done
780
	add	esi, 1
781
	sub	ebx, [.scanline_len]
782
	jc	.convert_done
783
	mov	ecx, [.width]
1308 diamond 784
	sub	ecx, [.starting_col]
785
	mov	[.i], ecx
786
	mov	[.shift], 0
787
.palette2_2bit.extloop:
788
	init_block
789
	add	eax, edi
790
	push	eax
791
	mov	cl, [.shift]
792
	sub	cl, 2
793
	jns	.palette2_2bit.shifted
794
	mov	cl, 6
1014 diamond 795
	mov	al, [esi]
1308 diamond 796
	inc	esi
797
	shr	al, cl
798
	jmp	@f
799
.palette2_2bit.shifted:
800
	mov	al, [esi-1]
801
	shr	al, cl
802
	and	al, 3
1014 diamond 803
@@:
1308 diamond 804
	mov	[.shift], cl
805
	block_byte_innerloop .palette2_2bit.extloop
806
	ja	.palette2_2bit
1014 diamond 807
	jmp	.convert_done
808
.palette2_1bit:
809
	sub	ebx, 1
810
	jc	.convert_done
811
	add	esi, 1
812
	sub	ebx, [.scanline_len]
813
	jc	.convert_done
814
	mov	ecx, [.width]
1308 diamond 815
	sub	ecx, [.starting_col]
816
	mov	[.i], ecx
817
	mov	[.shift], 0
818
.palette2_1bit.extloop:
819
	init_block
820
	add	eax, edi
821
	push	eax
822
	mov	cl, [.shift]
823
	dec	cl
824
	jns	.palette2_1bit.shifted
825
	mov	cl, 7
1014 diamond 826
	mov	al, [esi]
1308 diamond 827
	inc	esi
828
	shr	al, cl
829
	jmp	@f
830
.palette2_1bit.shifted:
831
	mov	al, [esi-1]
832
	shr	al, cl
833
	and	al, 1
1014 diamond 834
@@:
1308 diamond 835
	mov	[.shift], cl
836
	block_byte_innerloop .palette2_1bit.extloop
837
	ja	.palette2_1bit
1014 diamond 838
	jmp	.convert_done
839
.grayscale2_16bit:
840
	sub	ebx, 1
841
	jc	.convert_done
842
	add	esi, 1
1308 diamond 843
	sub	ebx, [.scanline_len]
1014 diamond 844
	jc	.convert_done
1308 diamond 845
	mov	ecx, [.width]
846
	sub	ecx, [.starting_col]
847
	mov	[.i], ecx
848
.grayscale2_16bit.extloop:
849
	init_block
850
	add	eax, edi
851
	push	eax
1079 diamond 852
	mov	ax, [esi]
853
	add	esi, 2
1014 diamond 854
	convert_16_to_8
1308 diamond 855
	block_byte_innerloop .grayscale2_16bit.extloop
856
	ja	.grayscale2_16bit
1014 diamond 857
	jmp	.convert_done
858
.rgb2:
859
	cmp	[.bit_depth], 16
860
	jz	.rgb2_16bit
861
.rgb2.next:
862
	sub	ebx, 1
863
	jc	.convert_done
864
	add	esi, 1
1308 diamond 865
	sub	ebx, [.scanline_len]
1014 diamond 866
	jc	.convert_done
1308 diamond 867
	mov	ecx, [.width]
868
	sub	ecx, [.starting_col]
869
	mov	[.i], ecx
870
.rgb2.extloop:
871
	init_block
872
	lea	eax, [eax*3]
873
	add	eax, edi
874
	push	eax
875
.rgb2.innloop1:
876
	push	edi
877
	mov	ecx, ebx
878
.rgb2.innloop2:
1014 diamond 879
	mov	al, [esi+2]
880
	mov	[edi], al
881
	mov	al, [esi+1]
882
	mov	[edi+1], al
883
	mov	al, [esi]
884
	mov	[edi+2], al
1308 diamond 885
	add	edi, 3
886
	dec	ecx
887
	jnz	.rgb2.innloop2
888
	pop	edi
889
	add	edi, [.row_distance]
890
	dec	edx
891
	jnz	.rgb2.innloop1
892
	pop	edi ebx
1014 diamond 893
	add	esi, 3
1308 diamond 894
	mov	eax, [.col_increment]
895
	sub	[.i], eax
896
	ja	.rgb2.extloop
897
	add	edi, [.col_distance]
898
	mov	eax, [.row_increment]
899
	sub	[.j], eax
900
	ja	.rgb2.next
1014 diamond 901
	jmp	.convert_done
902
.rgb2_16bit:
903
	sub	ebx, 1
904
	jc	.convert_done
905
	add	esi, 1
1308 diamond 906
	sub	ebx, [.scanline_len]
1014 diamond 907
	jc	.convert_done
1308 diamond 908
	mov	ecx, [.width]
909
	sub	ecx, [.starting_col]
910
	mov	[.i], ecx
911
.rgb2_16bit.extloop:
912
	init_block
913
	lea	eax, [eax*3]
914
	add	eax, edi
915
	push	eax
916
.rgb2_16bit.innloop1:
917
	push	edi
918
	mov	ecx, ebx
919
.rgb2_16bit.innloop2:
1014 diamond 920
	mov	ax, [esi+4]
921
	convert_16_to_8
922
	mov	[edi], al
923
	mov	ax, [esi+2]
924
	convert_16_to_8
925
	mov	[edi+1], al
926
	mov	ax, [esi]
927
	convert_16_to_8
928
	mov	[edi+2], al
1308 diamond 929
	add	edi, 3
930
	dec	ecx
931
	jnz	.rgb2_16bit.innloop2
932
	pop	edi
933
	add	edi, [.row_distance]
934
	dec	edx
935
	jnz	.rgb2_16bit.innloop1
936
	pop	edi ebx
1014 diamond 937
	add	esi, 6
1308 diamond 938
	mov	eax, [.col_increment]
939
	sub	[.i], eax
940
	ja	.rgb2_16bit.extloop
941
	add	edi, [.col_distance]
942
	mov	eax, [.row_increment]
943
	sub	[.j], eax
944
	ja	.rgb2_16bit
1014 diamond 945
	jmp	.convert_done
946
.grayscale_alpha2:
1308 diamond 947
	call	.create_grayscale_palette
1014 diamond 948
	cmp	[.bit_depth], 16
949
	jz	.grayscale_alpha2_16bit
950
.grayscale_alpha2.next:
951
	sub	ebx, 1
952
	jc	.convert_done
953
	add	esi, 1
1308 diamond 954
	sub	ebx, [.scanline_len]
1014 diamond 955
	jc	.convert_done
1308 diamond 956
	mov	ecx, [.width]
957
	sub	ecx, [.starting_col]
958
	mov	[.i], ecx
959
.grayscale_alpha2.extloop:
960
	init_block
961
	add	eax, edi
962
	push	eax
1014 diamond 963
	mov	al, [esi]
964
	add	esi, 2
1308 diamond 965
	block_byte_innerloop .grayscale_alpha2.extloop
966
	ja	.grayscale_alpha2.next
1014 diamond 967
	jmp	.convert_done
968
.grayscale_alpha2_16bit:
969
	sub	ebx, 1
970
	jc	.convert_done
971
	add	esi, 1
1308 diamond 972
	sub	ebx, [.scanline_len]
1014 diamond 973
	jc	.convert_done
1308 diamond 974
	mov	ecx, [.width]
975
	sub	ecx, [.starting_col]
976
	mov	[.i], ecx
977
.grayscale_alpha2_16bit.extloop:
978
	init_block
979
	add	eax, edi
980
	push	eax
1079 diamond 981
	mov	ax, [esi]
982
	add	esi, 4
1014 diamond 983
	convert_16_to_8
1308 diamond 984
	block_byte_innerloop .grayscale_alpha2_16bit.extloop
985
	ja	.grayscale_alpha2_16bit
1014 diamond 986
.convert_done:
1308 diamond 987
; next interlace pass
988
.deinterlace_next:
989
	mov	eax, [.block_width]
990
	cmp	eax, [.block_height]
991
	jz	.deinterlace_dec_width
992
	mov	[.block_height], eax
993
	mov	[.col_increment], eax
994
	dec	[.col_increment_shift]
995
	mov	[.starting_row], eax
996
	and	[.starting_col], 0
997
	jmp	.deinterlace_loop
998
.deinterlace_dec_width:
999
	shr	eax, 1
1000
	jz	.deinterlace_done
1001
	mov	[.block_width], eax
1002
	mov	[.starting_col], eax
1003
	add	eax, eax
1004
	and	[.starting_row], 0
1005
	mov	[.row_increment], eax
1006
	bsf	eax, eax
1007
	mov	[.row_increment_shift], al
1008
	jmp	.deinterlace_loop
1009
.deinterlace_done:
1010
	mcall	68, 13, [.allocated]
1014 diamond 1011
	mov	esi, [.cur_chunk_ptr]
1012
	add	esi, [.cur_chunk_size]
1013
	push	[.length]
1014
	jmp	.next_chunk
1015
 
1016
.deflate_callback:
1017
	mov	ebp, [esp+4]
1018
	mov	ebx, [esp+8]
1019
	xor	eax, eax
1020
	mov	esi, [.cur_chunk_size]
1021
	mov	[ebx], esi
1022
	test	esi, esi
1023
	jz	.deflate_callback.ret
1024
	mov	eax, [.cur_chunk_ptr]
1025
	mov	ecx, [.length]
1026
	add	esi, eax
1027
	mov	[.cur_chunk_ptr], esi
1028
	and	[.cur_chunk_size], 0
1029
@@:
1030
	sub	ecx, 12
1031
	jb	.deflate_callback.ret
1032
	cmp	dword [esi+4+4], 'IDAT'
1033
	jnz	.deflate_callback.ret
1034
	mov	edx, [esi+4]
1035
	bswap	edx
1036
	sub	ecx, edx
1037
	jb	.deflate_callback.ret
1038
	add	esi, 4+8
1039
	test	edx, edx
1040
	jz	@b
1041
	mov	[.cur_chunk_size], edx
1042
	mov	[.cur_chunk_ptr], esi
1043
	mov	[.length], ecx
1044
.deflate_callback.ret:
1045
	ret	8
1308 diamond 1046
 
1047
.create_grayscale_palette:
1048
	push	edi edx
1049
	mov	edi, [eax + Image.Palette]
1050
	mov	ecx, [.bit_depth]
1051
	cmp	cl, 16
1052
	jnz	@f
1053
	mov	cl, 8
1054
@@:
1055
	push	1
1056
	pop	eax
1057
	shl	eax, cl
1058
	xchg	eax, ecx
1059
	mov	edx, 0x010101
1060
	cmp	al, 8
1061
	jz	.graypal_common
1062
	mov	edx, 0x111111
1063
	cmp	al, 4
1064
	jz	.graypal_common
1065
	mov	edx, 0x555555
1066
	cmp	al, 2
1067
	jz	.graypal_common
1068
	mov	edx, 0xFFFFFF
1069
.graypal_common:
1070
	xor	eax, eax
1071
@@:
1072
	stosd
1073
	add	eax, edx
1074
	loop	@b
1075
	pop	edx edi
1076
	ret
1014 diamond 1077
;endp
1078
 
1079
img.encode.png:
1080
	xor	eax, eax
1102 diamond 1081
	ret	12