Subversion Repositories Kolibri OS

Rev

Rev 8449 | Details | Compare with Previous | Last modification | View Log | RSS feed

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