Subversion Repositories Kolibri OS

Rev

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