Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
6807 dunkaist 1
;;================================================================================================;;
2
;;//// libimg.asm //// (c) mike.dld, 2007-2008, (c) diamond, 2009, (c) dunkaist, 2011-2013 ///////;;
3
;;================================================================================================;;
8463 IgorA 4
;;												  ;;
5
;; This file is part of Common development libraries (Libs-Dev).				  ;;
6
;;												  ;;
6807 dunkaist 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 ;;
8463 IgorA 9
;; of the License, or (at your option) any later version.					  ;;
10
;;												  ;;
6807 dunkaist 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  ;;
8463 IgorA 13
;; Lesser General Public License for more details.						  ;;
14
;;												  ;;
6807 dunkaist 15
;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev.  ;;
8463 IgorA 16
;; If not, see .							  ;;
17
;;												  ;;
6807 dunkaist 18
;;================================================================================================;;
19
 
20
 
21
format MS COFF
22
 
23
public @EXPORT as 'EXPORTS'
24
 
8341 dunkaist 25
include 'struct.inc'
26
include 'proc32.inc'
27
include 'macros.inc'
28
include 'config.inc'
29
include 'debug-fdo.inc'
7105 dunkaist 30
__DEBUG__ = 0
31
__DEBUG_LEVEL__ = 1
8341 dunkaist 32
include 'libio.inc'
6807 dunkaist 33
purge section,mov,add,sub
34
 
35
include 'libimg.inc'
36
 
37
section '.flat' code readable align 16
38
 
39
include 'bmp/bmp.asm'
40
include 'gif/gif.asm'
41
include 'jpeg/jpeg.asm'
42
include 'png/png.asm'
43
include 'tga/tga.asm'
44
include 'z80/z80.asm'
45
include 'ico_cur/ico_cur.asm'
46
include 'pcx/pcx.asm'
47
include 'xcf/xcf.asm'
48
include 'tiff/tiff.asm'
49
include 'pnm/pnm.asm'
50
include 'wbmp/wbmp.asm'
51
include 'xbm/xbm.asm'
52
 
53
include 'scale.asm'
54
include 'convert.asm'
55
 
8341 dunkaist 56
COMPOSITE_MODE equ MMX
57
; MMX | pretty fast and compatible
58
; SSE | a bit faster, but may be unsupported by some CPUs
59
include 'blend.asm'
60
 
6807 dunkaist 61
;;================================================================================================;;
62
proc lib_init ;///////////////////////////////////////////////////////////////////////////////////;;
63
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 64
;? Library entry point (called after library load)						  ;;
6807 dunkaist 65
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 66
;> eax = pointer to memory allocation routine							  ;;
67
;> ebx = pointer to memory freeing routine							  ;;
68
;> ecx = pointer to memory reallocation routine 						  ;;
69
;> edx = pointer to library loading routine							  ;;
6807 dunkaist 70
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 71
;< eax = 1 (fail) / 0 (ok) (library initialization result)					  ;;
6807 dunkaist 72
;;================================================================================================;;
73
    mov [mem.alloc], eax
74
    mov [mem.free], ebx
75
    mov [mem.realloc], ecx
76
    mov [dll.load], edx
77
 
78
    or edx,edx
79
    jz @f
80
      invoke dll.load, @IMPORT
81
    @@:
82
 
83
    call    img.initialize.jpeg
84
 
85
    xor eax, eax
86
    cpuid
87
    cmp ecx, 'ntel'
88
    jnz @f
89
    mov dword [img._.do_rgb.handlers + (Image.bpp15-1)*4], img._.do_rgb.bpp15.intel
90
    mov dword [img._.do_rgb.handlers + (Image.bpp16-1)*4], img._.do_rgb.bpp16.intel
91
  @@:
92
 
8463 IgorA 93
  .ok:	xor eax,eax
6807 dunkaist 94
    ret
95
endp
96
 
97
;;================================================================================================;;
98
proc img.is_img _data, _length ;//////////////////////////////////////////////////////////////////;;
99
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 100
;? --- TBD ---											  ;;
6807 dunkaist 101
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 102
;> --- TBD ---											  ;;
6807 dunkaist 103
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 104
;< --- TBD ---											  ;;
6807 dunkaist 105
;;================================================================================================;;
106
    push    ebx
107
    mov ebx, img.formats_table
108
    @@: stdcall [ebx + FormatsTableEntry.Is], [_data], [_length]
8463 IgorA 109
    or	eax, eax
6807 dunkaist 110
    jnz @f
111
    add ebx, sizeof.FormatsTableEntry
112
    cmp dword[ebx], 0
113
    jnz @b
114
    xor eax, eax
115
    @@: pop ebx
116
    ret
117
endp
118
 
119
;;================================================================================================;;
120
proc img.info _data, _length ;////////////////////////////////////////////////////////////////////;;
121
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 122
;? --- TBD ---											  ;;
6807 dunkaist 123
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 124
;> --- TBD ---											  ;;
6807 dunkaist 125
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 126
;< --- TBD ---											  ;;
6807 dunkaist 127
;;================================================================================================;;
128
    xor eax, eax
129
    ret
130
endp
131
 
132
;;================================================================================================;;
133
proc img.from_file _filename ;////////////////////////////////////////////////////////////////////;;
134
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 135
;? load file from disk and decode it								  ;;
6807 dunkaist 136
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 137
;> [_filename] = file name as passed to libio							  ;;
6807 dunkaist 138
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 139
;< eax = 0 / pointer to image									  ;;
6807 dunkaist 140
;;================================================================================================;;
7105 dunkaist 141
locals
8463 IgorA 142
	fd		dd ?
143
	img_data_len	dd ?
144
	img_data	dd ?	; raw bytes
145
	img		dd ?	; Image pointer
7105 dunkaist 146
endl
147
	push	ebx
8463 IgorA 148
	mov	[img], 0
149
	invoke	file.open, [_filename], O_READ
150
	mov	[fd], eax
151
	test	eax, eax
152
	jz	.exit
153
	invoke	file.size, [_filename]
154
	test	eax, eax
155
	jnz	.exit_close
156
	mov	[img_data_len], ebx
157
	invoke	mem.alloc, ebx
158
	test	eax, eax
159
	jz	.exit_close
160
	mov	[img_data], eax
161
	invoke	file.read, [fd], eax, [img_data_len]
162
	cmp	eax, -1
163
	jz	.exit_free_close
164
	cmp	eax, [img_data_len]
165
	jnz	.exit_free_close
166
	stdcall img.decode, [img_data], [img_data_len], 0
167
	test	eax, eax
168
	jz	.exit_free_close
169
	mov	[img], eax
7105 dunkaist 170
  .exit_free_close:
8463 IgorA 171
	invoke	mem.free, [img_data]
7105 dunkaist 172
  .exit_close:
8463 IgorA 173
	invoke	file.close, [fd]
174
	mov	eax, [img]
7105 dunkaist 175
  .exit:
176
	pop	ebx
8463 IgorA 177
	ret
6807 dunkaist 178
endp
179
 
180
;;================================================================================================;;
181
proc img.to_file _img, _filename ;////////////////////////////////////////////////////////////////;;
182
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 183
;? --- TBD ---											  ;;
6807 dunkaist 184
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 185
;> --- TBD ---											  ;;
6807 dunkaist 186
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 187
;< eax = false / true										  ;;
6807 dunkaist 188
;;================================================================================================;;
189
    xor eax, eax
190
    ret
191
endp
192
 
193
;;================================================================================================;;
194
proc img.from_rgb _rgb_data ;/////////////////////////////////////////////////////////////////////;;
195
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 196
;? --- TBD ---											  ;;
6807 dunkaist 197
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 198
;> --- TBD ---											  ;;
6807 dunkaist 199
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 200
;< eax = 0 / pointer to image									  ;;
6807 dunkaist 201
;;================================================================================================;;
202
    xor eax, eax
203
    ret
204
endp
205
 
206
;;================================================================================================;;
207
proc img.to_rgb2 _img, _out ;/////////////////////////////////////////////////////////////////////;;
208
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 209
;? decodes image data into RGB triplets and stores them where [_out] points to			  ;;
6807 dunkaist 210
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 211
;> [_img] = pointer to source image								  ;;
212
;> [_out] = where to store RGB triplets 							  ;;
6807 dunkaist 213
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 214
;< none 											  ;;
6807 dunkaist 215
;;================================================================================================;;
216
    push    esi edi
217
    mov esi, [_img]
218
    stdcall img._.validate, esi
8463 IgorA 219
    or	eax, eax
6807 dunkaist 220
    jnz .ret
221
    mov edi, [_out]
222
    call    img._.do_rgb
223
.ret:
224
    pop edi esi
225
    ret
226
endp
227
 
228
;;================================================================================================;;
229
proc img.to_rgb _img ;////////////////////////////////////////////////////////////////////////////;;
230
;;------------------------------------------------------------------------------------------------;;
231
;? decodes image data into RGB triplets and returns pointer to memory area of following structure:;;
8463 IgorA 232
;? width  dd ?											  ;;
233
;? height dd ?											  ;;
234
;? rgb triplets 										  ;;
6807 dunkaist 235
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 236
;> [_img] = pointer to source image								  ;;
6807 dunkaist 237
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 238
;< eax = 0 / pointer to rgb_data (array of [rgb] triplets)					  ;;
6807 dunkaist 239
;;================================================================================================;;
240
    push    esi edi
241
    mov esi, [_img]
242
    stdcall img._.validate, esi
8463 IgorA 243
    or	eax, eax
6807 dunkaist 244
    jnz .error
245
 
246
    mov esi, [_img]
247
    mov ecx, [esi + Image.Width]
248
    imul    ecx, [esi + Image.Height]
249
    lea eax, [ecx * 3 + 4 * 3]
250
    invoke  mem.alloc, eax
8463 IgorA 251
    or	eax, eax
252
    jz	.error
6807 dunkaist 253
 
254
    mov edi, eax
255
    push    eax
256
    mov eax, [esi + Image.Width]
257
    stosd
258
    mov eax, [esi + Image.Height]
259
    stosd
260
    call    img._.do_rgb
261
    pop eax
262
    pop edi esi
263
    ret
264
 
265
  .error:
266
    xor eax, eax
267
    pop edi esi
268
    ret
269
endp
270
 
271
;;================================================================================================;;
272
proc img._.do_rgb ;///////////////////////////////////////////////////////////////////////////////;;
273
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 274
;? decodes [esi + Image.Data] data into RGB triplets and stores them at [edi]			  ;;
6807 dunkaist 275
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 276
;> esi = pointer to source image								  ;;
277
;> edi = pointer to memory to store RGB triplets						  ;;
6807 dunkaist 278
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 279
;< none 											  ;;
6807 dunkaist 280
;;================================================================================================;;
281
    mov ecx, [esi + Image.Width]
282
    imul    ecx, [esi + Image.Height]
283
    mov eax, [esi + Image.Type]
284
    jmp dword [.handlers + (eax-1)*4]
285
 
286
align 16
287
.bpp8i:
288
; 8 BPP WITH PALETTE -> 24 BPP
289
    push    ebx
290
    mov ebx, [esi + Image.Palette]
291
    mov esi, [esi + Image.Data]
292
    sub ecx, 1
8463 IgorA 293
    jz	.bpp8i.last
6807 dunkaist 294
@@:
295
    movzx   eax, byte [esi]
296
    add esi, 1
297
    mov eax, [ebx + eax*4]
298
    mov [edi], eax
299
    add edi, 3
300
    sub ecx, 1
301
    jnz @b
302
.bpp8i.last:
303
    movzx   eax, byte [esi]
304
    mov eax, [ebx + eax*4]
305
    mov [edi], ax
306
    shr eax, 16
307
    mov [edi+2], al
308
    pop ebx
309
    ret
310
 
311
align 16
312
.bpp8g:
313
; 8 BPP GRAYSCALE -> 24 BPP
314
    mov esi, [esi + Image.Data]
315
@@:
316
    lodsb
317
    mov ah, al
318
    stosb
319
    stosw
320
    dec ecx
321
    jnz @b
322
    ret
323
;
324
;align 16
325
;.bpp8a: ; considered application layer, may be changed in the future
326
;; 8a BPP -> 24 BPP
327
;    mov esi, [esi + Image.Data]
328
;@@:
329
;    lodsw
330
;    mov ah, al
331
;    stosb
332
;    stosw
333
;    dec ecx
334
;    jnz @b
335
;    ret
336
 
337
; 15 BPP -> 24 BPP
338
.bpp15.intel:
339
    push    ebx ebp
340
    sub ecx, 4
8463 IgorA 341
    jb	.bpp15.tail
6807 dunkaist 342
align 16
343
.bpp15.intel.loop:
344
repeat 2
345
    mov ebx, [esi]
346
    mov al, [esi]
347
    mov ah, [esi+1]
348
    add esi, 4
349
    and al, 0x1F
350
    and ah, 0x1F shl 2
351
    mov ebp, ebx
352
    mov dl, al
353
    mov dh, ah
354
    shr al, 2
355
    shr ah, 4
356
    shl dl, 3
357
    shl dh, 1
358
    and ebp, 0x1F shl 5
359
    add al, dl
360
    add ah, dh
361
    shr ebp, 2
362
    mov [edi], al
363
    mov [edi+2], ah
364
    mov eax, ebx
365
    mov ebx, ebp
366
    shr eax, 16
367
    shr ebx, 5
368
    add ebx, ebp
369
    mov ebp, eax
370
    mov [edi+1], bl
371
    and eax, (0x1F) or (0x1F shl 10)
372
    and ebp, 0x1F shl 5
373
    lea edx, [eax+eax]
374
    shr al, 2
375
    mov ebx, ebp
376
    shr ah, 4
377
    shl dl, 2
378
    shr ebx, 2
379
    shr ebp, 7
380
    add al, dl
381
    add ah, dh
382
    mov [edi+3], al
383
    add ebx, ebp
384
    mov [edi+5], ah
385
    mov [edi+4], bl
386
    add edi, 6
387
end repeat
388
    sub ecx, 4
389
    jnb .bpp15.intel.loop
390
.bpp15.tail:
391
    add ecx, 4
8463 IgorA 392
    jz	.bpp15.done
6807 dunkaist 393
@@:
394
    movzx   eax, word [esi]
395
    mov ebx, eax
396
    add esi, 2
397
    and eax, (0x1F) or (0x1F shl 10)
398
    and ebx, 0x1F shl 5
399
    lea edx, [eax+eax]
400
    shr al, 2
401
    mov ebp, ebx
402
    shr ebx, 2
403
    shr ah, 4
404
    shl dl, 2
405
    shr ebp, 7
406
    add eax, edx
407
    add ebx, ebp
408
    mov [edi], al
409
    mov [edi+1], bl
410
    mov [edi+2], ah
411
    add edi, 3
412
    sub ecx, 1
413
    jnz @b
414
.bpp15.done:
415
    pop ebp ebx
416
    ret
417
 
418
.bpp15.amd:
419
    push    ebx ebp
420
    sub ecx, 4
8463 IgorA 421
    jb	.bpp15.tail
6807 dunkaist 422
align 16
423
.bpp15.amd.loop:
424
repeat 4
425
if (% mod 2) = 1
426
    mov eax, dword [esi]
427
    mov ebx, dword [esi]
428
else
429
    movzx   eax, word [esi]
430
    mov ebx, eax
431
end if
432
    add esi, 2
433
    and eax, (0x1F) or (0x1F shl 10)
434
    and ebx, 0x1F shl 5
435
    lea edx, [eax+eax]
436
    shr al, 2
437
    mov ebp, ebx
438
    shr ebx, 2
439
    shr ah, 4
440
    shl dl, 2
441
    shr ebp, 7
442
    add eax, edx
443
    add ebx, ebp
444
    mov [edi], al
445
    mov [edi+1], bl
446
    mov [edi+2], ah
447
    add edi, 3
448
end repeat
449
    sub ecx, 4
450
    jnb .bpp15.amd.loop
451
    jmp .bpp15.tail
452
 
453
; 16 BPP -> 24 BPP
454
.bpp16.intel:
455
    push    ebx ebp
456
    sub ecx, 4
8463 IgorA 457
    jb	.bpp16.tail
6807 dunkaist 458
align 16
459
.bpp16.intel.loop:
460
repeat 2
461
    mov ebx, [esi]
462
    mov al, [esi]
463
    mov ah, [esi+1]
464
    add esi, 4
465
    and al, 0x1F
466
    and ah, 0x1F shl 3
467
    mov ebp, ebx
468
    mov dl, al
469
    mov dh, ah
470
    shr al, 2
471
    shr ah, 5
472
    shl dl, 3
473
    and ebp, 0x3F shl 5
474
    add al, dl
475
    add ah, dh
476
    shr ebp, 3
477
    mov [edi], al
478
    mov [edi+2], ah
479
    mov eax, ebx
480
    mov ebx, ebp
481
    shr eax, 16
482
    shr ebx, 6
483
    add ebx, ebp
484
    mov ebp, eax
485
    mov [edi+1], bl
486
    and eax, (0x1F) or (0x1F shl 11)
487
    and ebp, 0x3F shl 5
488
    mov edx, eax
489
    shr al, 2
490
    mov ebx, ebp
491
    shr ah, 5
492
    shl dl, 3
493
    shr ebx, 3
494
    shr ebp, 9
495
    add al, dl
496
    add ah, dh
497
    mov [edi+3], al
498
    add ebx, ebp
499
    mov [edi+5], ah
500
    mov [edi+4], bl
501
    add edi, 6
502
end repeat
503
    sub ecx, 4
504
    jnb .bpp16.intel.loop
505
.bpp16.tail:
506
    add ecx, 4
8463 IgorA 507
    jz	.bpp16.done
6807 dunkaist 508
@@:
509
    movzx   eax, word [esi]
510
    mov ebx, eax
511
    add esi, 2
512
    and eax, (0x1F) or (0x1F shl 11)
513
    and ebx, 0x3F shl 5
514
    mov edx, eax
515
    shr al, 2
516
    mov ebp, ebx
517
    shr ebx, 3
518
    shr ah, 5
519
    shl dl, 3
520
    shr ebp, 9
521
    add eax, edx
522
    add ebx, ebp
523
    mov [edi], al
524
    mov [edi+1], bl
525
    mov [edi+2], ah
526
    add edi, 3
527
    sub ecx, 1
528
    jnz @b
529
.bpp16.done:
530
    pop ebp ebx
531
    ret
532
 
533
.bpp16.amd:
534
    push    ebx ebp
535
    sub ecx, 4
8463 IgorA 536
    jb	.bpp16.tail
6807 dunkaist 537
align 16
538
.bpp16.amd.loop:
539
repeat 4
540
if (% mod 2) = 1
541
    mov eax, dword [esi]
542
    mov ebx, dword [esi]
543
else
544
    movzx   eax, word [esi]
545
    mov ebx, eax
546
end if
547
    add esi, 2
548
    and eax, (0x1F) or (0x1F shl 11)
549
    and ebx, 0x3F shl 5
550
    mov edx, eax
551
    shr al, 2
552
    mov ebp, ebx
553
    shr ebx, 3
554
    shr ah, 5
555
    shl dl, 3
556
    shr ebp, 9
557
    add eax, edx
558
    add ebx, ebp
559
    mov [edi], al
560
    mov [edi+1], bl
561
    mov [edi+2], ah
562
    add edi, 3
563
end repeat
564
    sub ecx, 4
565
    jnb .bpp16.amd.loop
566
    jmp .bpp16.tail
567
 
568
align 16
569
.bpp24:
570
; 24 BPP -> 24 BPP
571
    lea ecx, [ecx*3 + 3]
572
    mov esi, [esi + Image.Data]
573
    shr ecx, 2
574
    rep movsd
575
    ret
576
 
577
align 16
578
.bpp32:
579
; 32 BPP -> 24 BPP
580
    mov esi, [esi + Image.Data]
581
 
582
    @@:
583
    mov eax, [esi]
584
    mov [edi], ax
585
    shr eax, 16
586
    mov [edi+2], al
587
    add esi, 4
588
    add edi, 3
589
    sub ecx, 1
590
    jnz @b
591
 
592
    @@:
593
    ret
594
 
595
align 16
596
.bpp1:
597
    push ebx ebp
598
    mov ebp, [esi + Image.Width]
599
    mov edx, [esi + Image.Height]
600
    shl edx, 16
601
    mov ebx, [esi + Image.Palette]
602
    mov esi, [esi + Image.Data]
603
  .bpp1.pre:
604
    mov dx, bp
605
    mov ecx, 7
606
  .bpp1.begin:
607
    xor eax, eax
8463 IgorA 608
    bt	[esi], ecx
6807 dunkaist 609
    adc eax, 0
610
    mov eax, [ebx + eax*4]
611
    mov [edi], ax
612
    shr eax, 16
613
    mov [edi + 2], al
614
    add edi, 3
615
    dec dx
616
    jz .bpp1.end_line
617
    dec ecx
618
    jns .bpp1.begin
619
    mov ecx, 7
620
    inc esi
621
    jmp .bpp1.begin
622
  .bpp1.end_line:
623
    sub edx, 0x10000
624
    jz .bpp1.quit
625
    inc esi
626
    jmp .bpp1.pre
627
  .bpp1.quit:
628
    pop ebp ebx
629
    ret
630
 
631
align 16
632
.bpp2i:
633
    push ebx ebp
634
    mov ebp, [esi + Image.Width]
635
    mov edx, [esi + Image.Height]
636
    shl edx, 16
637
    mov ebx, [esi + Image.Palette]
638
    mov esi, [esi + Image.Data]
639
  .bpp2i.pre:
640
    mov dx, bp
641
    mov ecx, 3
642
  .bpp2i.begin:
643
    mov eax, 3
644
    shl ecx, 1
645
    shl eax, cl
646
    and al, [esi]
647
    shr eax, cl
648
    shr ecx, 1
649
    mov eax, [ebx + eax*4]
650
    mov [edi], ax
651
    shr eax, 16
652
    mov [edi + 2], al
653
    add edi, 3
654
    dec dx
655
    jz .bpp2i.end_line
656
    dec ecx
657
    jns .bpp2i.begin
658
    mov ecx, 3
659
    inc esi
660
    jmp .bpp2i.begin
661
  .bpp2i.end_line:
662
    sub edx, 0x10000
663
    jz .bpp2i.quit
664
    inc esi
665
    jmp .bpp2i.pre
666
  .bpp2i.quit:
667
    pop ebp ebx
668
    ret
669
 
670
align 16
671
.bpp4i:
672
    push ebx ebp
673
    mov ebp, [esi + Image.Width]
674
    mov edx, [esi + Image.Height]
675
    shl edx, 16
676
    mov ebx, [esi + Image.Palette]
677
    mov esi, [esi + Image.Data]
678
  .bpp4i.pre:
679
    mov dx, bp
680
    mov ecx, 1
681
  .bpp4i.begin:
682
    mov eax, 15
683
    shl ecx, 2
684
    shl eax, cl
685
    and al, [esi]
686
    shr eax, cl
687
    shr ecx, 2
688
    mov eax, [ebx + eax*4]
689
    mov [edi], ax
690
    shr eax, 16
691
    mov [edi + 2], al
692
    add edi, 3
693
    dec dx
694
    jz .bpp4i.end_line
695
    dec ecx
696
    jns .bpp4i.begin
697
    mov ecx, 1
698
    inc esi
699
    jmp .bpp4i.begin
700
  .bpp4i.end_line:
701
    sub edx, 0x10000
702
    jz .bpp4i.quit
703
    inc esi
704
    jmp .bpp4i.pre
705
  .bpp4i.quit:
706
    pop ebp ebx
707
    ret
708
 
709
endp
710
 
711
;;================================================================================================;;
712
proc img.decode _data, _length, _options ;////////////////////////////////////////////////////////;;
713
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 714
;? decodes loaded into memory graphic file							  ;;
6807 dunkaist 715
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 716
;> [_data]    = pointer to file in memory							  ;;
717
;> [_length]  = size in bytes of memory area pointed to by [_data]				  ;;
718
;> [_options] = 0 / pointer to the structure of additional options				  ;;
6807 dunkaist 719
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 720
;< eax = 0 / pointer to image									  ;;
6807 dunkaist 721
;;================================================================================================;;
722
    push    ebx
8363 leency 723
    mov ebx, [_length]
724
    or  ebx,ebx
725
    jz  .fail
6807 dunkaist 726
    mov ebx, img.formats_table
727
    @@: stdcall [ebx + FormatsTableEntry.Is], [_data], [_length]
8463 IgorA 728
    or	eax, eax
6807 dunkaist 729
    jnz @f
730
    add ebx, sizeof.FormatsTableEntry
731
    cmp dword[ebx], eax ;0
732
    jnz @b
8363 leency 733
  .fail:
734
    xor eax, eax
6807 dunkaist 735
    pop ebx
736
    ret
737
    @@: mov eax, [ebx + FormatsTableEntry.Decode]
738
    pop ebx
739
    leave
740
    jmp eax
741
endp
742
 
743
;;================================================================================================;;
8463 IgorA 744
proc img.encode uses ebx, _img, _common, _specific ;////////////////////////////////////////////////////////;;
6807 dunkaist 745
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 746
;? encode image to some format									  ;;
6807 dunkaist 747
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 748
;> [_img]      = pointer to input image 							  ;;
749
;> [_common]   = some most important/common options						  ;;
750
;     0x00 :  byte : format id (defined in libimg.inc)						  ;;
751
;     0x01 :  byte : fast encoding (0) / best compression ratio (255)				  ;;
752
;		     0 : store uncompressed data (if supported both by the format and libimg)	  ;;
753
;		     1 - 255 : use compression, if supported					  ;;
754
;		     this option may be ignored if any format specific options are defined	  ;;
755
;		     i.e. 0 here will be ignored if particular compression algorithm is specified ;;
756
;     0x02 :  byte : flags (bitfield)								  ;;
757
;		    0x01 : return an error if format specific conditions cannot be met		  ;;
758
;		    0x02 : preserve current bit depth. means 8bpp/16bpp/24bpp and so on 	  ;;
759
;		    0x04 : delete alpha channel, if any 					  ;;
760
;		    0x08 : flush alpha channel with 0xff, if any; add it if none		  ;;
761
;     0x03 :  byte : reserved, must be 0							  ;;
762
;> [_specific] = 0 / pointer to the structure of format specific options			  ;;
763
;		    see .inc for description					  ;;
6807 dunkaist 764
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 765
;< eax = 0 / pointer to encoded data								  ;;
766
;< ecx = error code / the size of encoded data							  ;;
767
;     1 : out of memory 									  ;;
768
;     2 : format is not supported								  ;;
769
;     3 : specific conditions cannot be satisfied						  ;;
770
;     4 : bit depth cannot be preserved 							  ;;
6807 dunkaist 771
;;================================================================================================;;
8463 IgorA 772
	mov	ebx, [_img]
6807 dunkaist 773
 
8463 IgorA 774
	movzx	eax, byte[_common]
775
	dec	eax
776
	imul	eax, sizeof.FormatsTableEntry
777
	add	eax, FormatsTableEntry.Capabilities
778
	add	eax, img.formats_table
779
	mov	eax, [eax]
780
	test	eax, 1				; is encoding to this format supported at all?
781
	jnz	@f
782
	mov	ecx, LIBIMG_ERROR_FORMAT
783
	jmp	.error
6807 dunkaist 784
    @@:
8463 IgorA 785
	mov	ecx, [ebx + Image.Type]
786
	mov	edx, 1
787
	shl	edx, cl
788
	test	eax, edx
789
	jnz	.bit_depth_ok
790
	test	byte[_common+2], LIBIMG_ENCODE_STRICT_BIT_DEPTH
791
	jz	@f
792
	mov	ecx, LIBIMG_ERROR_BIT_DEPTH
793
	jmp	.error
6807 dunkaist 794
    @@:
8463 IgorA 795
	mov	edx, 1 SHL Image.bpp24
796
	test	eax, edx
797
	jnz	@f
798
	mov	ecx, LIBIMG_ERROR_BIT_DEPTH
799
	jmp	.error
6807 dunkaist 800
    @@:
8463 IgorA 801
	stdcall img.create, [ebx + Image.Width], [ebx + Image.Height], Image.bpp24
802
	test	eax, eax
803
	jnz	@f
804
	mov	ecx, LIBIMG_ERROR_OUT_OF_MEMORY
805
	jmp	.error
6807 dunkaist 806
    @@:
8463 IgorA 807
	push	eax
808
	stdcall img.to_rgb2, ebx, [eax + Image.Data]
809
	pop	ebx
6807 dunkaist 810
 
811
  .bit_depth_ok:
8463 IgorA 812
	movzx	eax, byte[_common]
813
	dec	eax
814
	imul	eax, sizeof.FormatsTableEntry
815
	add	eax, FormatsTableEntry.Encode
816
	add	eax, img.formats_table
817
	mov	eax, [eax]
818
	stdcall eax, [_img], [_common], [_specific]
819
	push	eax ecx
820
	cmp	ebx, [_img]
821
	je	@f
822
	stdcall img.destroy, ebx
6807 dunkaist 823
    @@:
8463 IgorA 824
	pop	ecx eax
825
	jmp	.quit
6807 dunkaist 826
 
827
  .error:
8463 IgorA 828
	xor	eax, eax
6807 dunkaist 829
  .quit:
8463 IgorA 830
	ret
6807 dunkaist 831
endp
832
 
833
;;================================================================================================;;
834
proc img.create _width, _height, _type ;//////////////////////////////////////////////////////////;;
835
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 836
;? creates an Image structure and initializes some its fields					  ;;
6807 dunkaist 837
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 838
;> [_width]  = width of an image in pixels							  ;;
839
;> [_height] = height of an image in pixels							  ;;
840
;> [_type]   = one of the Image.bppN constants from libimg.inc					  ;;
6807 dunkaist 841
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 842
;< eax = 0 / pointer to image									  ;;
6807 dunkaist 843
;;================================================================================================;;
844
    push    ecx
845
 
846
    stdcall img._.new
8463 IgorA 847
    or	eax, eax
848
    jz	.error
6807 dunkaist 849
 
850
    mov ecx, [_type]
851
    mov [eax + Image.Type], ecx
852
 
853
    push    eax
854
 
8395 dunkaist 855
    stdcall img.resize_data, eax, [_width], [_height]
8463 IgorA 856
    or	eax, eax
857
    jz	.error.2
6807 dunkaist 858
 
859
    pop eax
860
    jmp .ret
861
 
862
  .error.2:
8463 IgorA 863
;	pop	eax
6807 dunkaist 864
    stdcall img._.delete; eax
865
    xor eax, eax
866
 
867
  .error:
868
  .ret:
869
    pop ecx
870
    ret
871
endp
872
 
873
;;================================================================================================;;
874
proc img.destroy.layer _img ;/////////////////////////////////////////////////////////////////////;;
875
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 876
;? frees memory occupied by an image and all the memory regions its fields point to		  ;;
877
;? for image sequences deletes only one frame and fixes Previous/Next pointers			  ;;
6807 dunkaist 878
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 879
;> [_img] = pointer to image									  ;;
6807 dunkaist 880
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 881
;< eax = 0 (fail) / 1 (success) 								  ;;
6807 dunkaist 882
;;================================================================================================;;
883
    mov eax, [_img]
884
    mov edx, [eax + Image.Previous]
885
    test    edx, edx
8463 IgorA 886
    jz	@f
6807 dunkaist 887
    push    [eax + Image.Next]
888
    pop [edx + Image.Next]
889
@@:
890
    mov edx, [eax + Image.Next]
891
    test    edx, edx
8463 IgorA 892
    jz	@f
6807 dunkaist 893
    push    [eax + Image.Previous]
894
    pop [edx + Image.Previous]
895
@@:
896
    stdcall img._.delete, eax
897
    ret
898
endp
899
 
900
;;================================================================================================;;
901
proc img.destroy _img ;///////////////////////////////////////////////////////////////////////////;;
902
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 903
;? frees memory occupied by an image and all the memory regions its fields point to		  ;;
904
;? follows Previous/Next pointers and deletes all the images in sequence			  ;;
6807 dunkaist 905
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 906
;> [_img] = pointer to image									  ;;
6807 dunkaist 907
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 908
;< eax = 0 (fail) / 1 (success) 								  ;;
6807 dunkaist 909
;;================================================================================================;;
910
    push    1
911
    mov eax, [_img]
912
    mov eax, [eax + Image.Previous]
913
.destroy_prev_loop:
914
    test    eax, eax
8463 IgorA 915
    jz	.destroy_prev_done
6807 dunkaist 916
    pushd   [eax + Image.Previous]
917
    stdcall img._.delete, eax
918
    test    eax, eax
919
    jnz @f
920
    mov byte [esp+4], 0
921
@@:
922
    pop eax
923
    jmp .destroy_prev_loop
924
.destroy_prev_done:
925
    mov eax, [_img]
926
.destroy_next_loop:
927
    pushd   [eax + Image.Next]
928
    stdcall img._.delete, eax
929
    test    eax, eax
930
    jnz @f
931
    mov byte [esp+4], 0
932
@@:
933
    pop eax
934
    test    eax, eax
935
    jnz .destroy_next_loop
936
    pop eax
937
    ret
938
endp
939
 
940
;;================================================================================================;;
941
proc img.count _img ;/////////////////////////////////////////////////////////////////////////////;;
942
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 943
;? Get number of images in the list (e.g. in animated GIF file) 				  ;;
6807 dunkaist 944
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 945
;> _img = pointer to image									  ;;
6807 dunkaist 946
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 947
;< eax = -1 (fail) / >0 (ok)									  ;;
6807 dunkaist 948
;;================================================================================================;;
949
    push    ecx edx
950
    mov edx, [_img]
951
    stdcall img._.validate, edx
8463 IgorA 952
    or	eax, eax
6807 dunkaist 953
    jnz .error
954
 
955
    @@: mov eax, [edx + Image.Previous]
8463 IgorA 956
    or	eax, eax
957
    jz	@f
6807 dunkaist 958
    mov edx, eax
959
    jmp @b
960
 
961
    @@: xor ecx, ecx
962
    @@: inc ecx
963
    mov eax, [edx + Image.Next]
8463 IgorA 964
    or	eax, eax
965
    jz	.exit
6807 dunkaist 966
    mov edx, eax
967
    jmp @b
968
 
969
  .exit:
970
    mov eax, ecx
971
    pop edx ecx
972
    ret
973
 
974
  .error:
8463 IgorA 975
    or	eax, -1
6807 dunkaist 976
    pop edx ecx
977
    ret
978
endp
979
 
980
;;//// image processing //////////////////////////////////////////////////////////////////////////;;
981
 
982
;;================================================================================================;;
983
proc img.lock_bits _img, _start_line, _end_line ;/////////////////////////////////////////////////;;
984
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 985
;? --- TBD ---											  ;;
6807 dunkaist 986
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 987
;> --- TBD ---											  ;;
6807 dunkaist 988
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 989
;< eax = 0 / pointer to bits									  ;;
6807 dunkaist 990
;;================================================================================================;;
991
    xor eax, eax
992
    ret
993
endp
994
 
995
;;================================================================================================;;
996
proc img.unlock_bits _img, _lock ;////////////////////////////////////////////////////////////////;;
997
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 998
;? --- TBD ---											  ;;
6807 dunkaist 999
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 1000
;> --- TBD ---											  ;;
6807 dunkaist 1001
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 1002
;< eax = false / true										  ;;
6807 dunkaist 1003
;;================================================================================================;;
1004
    xor eax, eax
1005
    ret
1006
endp
1007
 
1008
;;================================================================================================;;
1009
proc img.flip.layer _img, _flip_kind ;////////////////////////////////////////////////////////////;;
1010
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 1011
;? Flip image layer										  ;;
6807 dunkaist 1012
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 1013
;> _img = pointer to image									  ;;
1014
;> _flip_kind = one of FLIP_* constants 							  ;;
6807 dunkaist 1015
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 1016
;< eax = false / true										  ;;
6807 dunkaist 1017
;;================================================================================================;;
1018
locals
1019
  scanline_len dd ?
1020
endl
1021
 
1022
    push    ebx esi edi
1023
    mov ebx, [_img]
1024
    stdcall img._.validate, ebx
8463 IgorA 1025
    or	eax, eax
6807 dunkaist 1026
    jnz .error
1027
 
1028
    mov ecx, [ebx + Image.Height]
1029
    mov eax, [ebx + Image.Width]
1030
    call    img._.get_scanline_len
1031
    mov [scanline_len], eax
1032
 
1033
    test    [_flip_kind], FLIP_VERTICAL
8463 IgorA 1034
    jz	.dont_flip_vert
6807 dunkaist 1035
 
1036
    imul    eax, ecx
1037
    sub eax, [scanline_len]
1038
    shr ecx, 1
1039
    mov esi, [ebx + Image.Data]
1040
    lea edi, [esi + eax]
1041
 
1042
  .next_line_vert:
1043
    push    ecx
1044
 
1045
    mov ecx, [scanline_len]
1046
    push    ecx
1047
    shr ecx, 2
1048
    @@:
1049
    dec ecx
8463 IgorA 1050
    js	@f
6807 dunkaist 1051
    mov eax, [esi]
1052
    xchg    eax, [edi]
1053
    mov [esi], eax
1054
    add esi, 4
1055
    add edi, 4
1056
    jmp @b
1057
    @@:
1058
 
1059
    pop ecx
1060
    and ecx, 3
8463 IgorA 1061
    jz	.cont_line_vert
6807 dunkaist 1062
    @@:
1063
    mov al, [esi]
1064
    xchg    al, [edi]
1065
    mov [esi], al
1066
    add esi, 1
1067
    add edi, 1
1068
    dec ecx
1069
    jnz @b
1070
    .cont_line_vert:
1071
 
1072
    pop ecx
1073
    mov eax, [scanline_len]
1074
    shl eax, 1
1075
    sub edi, eax
1076
    dec ecx
1077
    jnz .next_line_vert
1078
 
1079
  .dont_flip_vert:
1080
 
1081
    test    [_flip_kind], FLIP_HORIZONTAL
8463 IgorA 1082
    jz	.exit
6807 dunkaist 1083
 
1084
    mov ecx, [ebx + Image.Height]
1085
    mov eax, [ebx + Image.Type]
1086
    mov esi, [ebx + Image.Data]
1087
    mov edi, [scanline_len]
1088
    add edi, esi
1089
    jmp dword [.handlers_horz + (eax-1)*4]
1090
 
1091
.bpp32_horz:
1092
    sub edi, 4
1093
 
1094
  .next_line_horz:
1095
    push    ecx esi edi
1096
 
1097
    mov ecx, [scanline_len]
1098
    shr ecx, 3
1099
    @@: mov eax, [esi]
1100
    xchg    eax, [edi]
1101
    mov [esi], eax
1102
    add esi, 4
1103
    add edi, -4
1104
    sub ecx, 1
1105
    jnz @b
1106
 
1107
    pop edi esi ecx
1108
    add esi, [scanline_len]
1109
    add edi, [scanline_len]
1110
    dec ecx
1111
    jnz .next_line_horz
1112
    jmp .exit
1113
 
1114
.bpp1x_horz:
1115
    sub edi, 2
1116
  .next_line_horz1x:
1117
    push    ecx esi edi
1118
 
1119
    mov ecx, [ebx + Image.Width]
1120
    @@: mov ax, [esi]
1121
    mov dx, [edi]
1122
    mov [edi], ax
1123
    mov [esi], dx
1124
    add esi, 2
1125
    sub edi, 2
1126
    sub ecx, 2
8463 IgorA 1127
    ja	@b
6807 dunkaist 1128
 
1129
    pop edi esi ecx
1130
    add esi, [scanline_len]
1131
    add edi, [scanline_len]
1132
    dec ecx
1133
    jnz .next_line_horz1x
1134
    jmp .exit
1135
 
1136
.bpp8ig_horz:
1137
    dec edi
1138
  .next_line_horz8ig:
1139
    push    ecx esi edi
1140
 
1141
    mov ecx, [scanline_len]
1142
    shr ecx, 1
1143
    @@: mov al, [esi]
1144
    mov dl, [edi]
1145
    mov [edi], al
1146
    mov [esi], dl
1147
    add esi, 1
1148
    sub edi, 1
1149
    sub ecx, 1
1150
    jnz @b
1151
 
1152
    pop edi esi ecx
1153
    add esi, [scanline_len]
1154
    add edi, [scanline_len]
1155
    dec ecx
1156
    jnz .next_line_horz8ig
1157
    jmp .exit
1158
 
1159
.bpp24_horz:
1160
    sub edi, 3
1161
  .next_line_horz24:
1162
    push    ecx esi edi
1163
 
1164
    mov ecx, [ebx + Image.Width]
1165
    @@:
1166
    mov al, [esi]
1167
    mov dl, [edi]
1168
    mov [edi], al
1169
    mov [esi], dl
1170
    mov al, [esi+1]
1171
    mov dl, [edi+1]
1172
    mov [edi+1], al
1173
    mov [esi+1], dl
1174
    mov al, [esi+2]
1175
    mov dl, [edi+2]
1176
    mov [edi+2], al
1177
    mov [esi+2], dl
1178
    add esi, 3
1179
    sub edi, 3
1180
    sub ecx, 2
8463 IgorA 1181
    ja	@b
6807 dunkaist 1182
 
1183
    pop edi esi ecx
1184
    add esi, [scanline_len]
1185
    add edi, [scanline_len]
1186
    dec ecx
1187
    jnz .next_line_horz24
1188
    jmp .exit
1189
 
1190
.bpp1_horz:
1191
    mov edi, [scanline_len]
1192
    mov edx, [ebx + Image.Width]
1193
    and edx, 7
1194
    neg edx
1195
    add edx, 8
1196
    and edx, 7
1197
.bpp1_horz.begin:
1198
    push ebx edx esi
1199
    mov eax, 7
1200
    add edi, esi
1201
    sub edi, 1
1202
    mov ebx, [ebx + Image.Width]
1203
    shr ebx, 1
1204
.bpp1_horz.bit:
8463 IgorA 1205
    bt	[edi], edx
1206
    jc	@f
6807 dunkaist 1207
    btr [esi], eax
1208
    jmp .bpp1_horz.right
1209
  @@:
1210
    bts [esi], eax
1211
  .bpp1_horz.right:
1212
    jnc @f
1213
    bts [edi], edx
1214
    jmp .bpp1_horz.bit_done
1215
  @@:
1216
    btr [edi], edx
1217
  .bpp1_horz.bit_done:
1218
    inc edx
1219
    and edx, 7
1220
    jnz @f
1221
    dec edi
1222
  @@:
1223
    dec eax
1224
    jns @f
1225
    mov eax, 7
1226
    inc esi
1227
  @@:
1228
    dec ebx
1229
    jnz .bpp1_horz.bit
1230
 
1231
    pop esi edx ebx
1232
    add esi, [scanline_len]
1233
    mov edi, [scanline_len]
1234
    dec ecx
1235
    jnz .bpp1_horz.begin
1236
    jmp .exit
1237
 
1238
 
1239
.bpp2i_horz:
1240
    mov edi, [scanline_len]
1241
    mov edx, [ebx + Image.Width]
1242
    and edx, 3
1243
    neg edx
1244
    add edx, 4
1245
    and edx, 3
1246
.bpp2i_horz.begin:
1247
    push ebx edx esi
1248
    mov eax, 3
1249
    add edi, esi
1250
    sub edi, 1
1251
    mov ebx, [ebx + Image.Width]
1252
    shr ebx, 1
1253
.bpp2i_horz.pixel:
1254
    push ebx ecx
1255
    mov ebx, 3
1256
    mov ecx, edx
1257
    shl ebx, cl
1258
    shl ebx, cl
1259
    and bl, [edi]
1260
    shr ebx, cl
1261
    shr ebx, cl
1262
    mov bh,  3
1263
    mov ecx, eax
1264
    shl ebx, cl
1265
    shl ebx, cl
1266
    not bh
1267
    and bh, [esi]
8463 IgorA 1268
    or	bl, bh
6807 dunkaist 1269
    mov bh, [esi]
1270
    mov [esi], bl
1271
    shr ebx, 8
1272
    shr ebx, cl
1273
    shr ebx, cl
1274
    and ebx, 3
1275
    mov bh,  3
1276
    mov ecx, edx
1277
    shl ebx, cl
1278
    shl ebx, cl
1279
    not bh
1280
    and bh, [edi]
8463 IgorA 1281
    or	bl, bh
6807 dunkaist 1282
    mov [edi], bl
1283
    pop ecx ebx
1284
  .bpp2i_horz.pixel_done:
1285
    inc edx
1286
    and edx, 3
1287
    jnz @f
1288
    dec edi
1289
  @@:
1290
    dec eax
1291
    jns @f
1292
    mov eax, 3
1293
    inc esi
1294
  @@:
1295
    dec ebx
1296
    jnz .bpp2i_horz.pixel
1297
 
1298
    pop esi edx ebx
1299
    add esi, [scanline_len]
1300
    mov edi, [scanline_len]
1301
    dec ecx
1302
    jnz .bpp2i_horz.begin
1303
    jmp .exit
1304
 
1305
 
1306
.bpp4i_horz:
1307
    mov edi, [scanline_len]
1308
    mov edx, [ebx + Image.Width]
1309
    and edx, 1
1310
    neg edx
1311
    add edx, 2
1312
    and edx, 1
1313
.bpp4i_horz.begin:
1314
    push ebx edx esi
1315
    mov eax, 1
1316
    add edi, esi
1317
    sub edi, 1
1318
    mov ebx, [ebx + Image.Width]
1319
    shr ebx, 1
1320
.bpp4i_horz.pixel:
1321
    push ebx ecx
1322
    mov ebx, 15
1323
    mov ecx, edx
1324
    shl ecx, 2
1325
    shl ebx, cl
1326
    and bl, [edi]
1327
    shr ebx, cl
1328
    mov bh,  15
1329
    mov ecx, eax
1330
    shl ecx, 2
1331
    shl ebx, cl
1332
    not bh
1333
    and bh, [esi]
8463 IgorA 1334
    or	bl, bh
6807 dunkaist 1335
    mov bh, [esi]
1336
    mov [esi], bl
1337
    shr ebx, 8
1338
    shr ebx, cl
1339
    and ebx, 15
1340
    mov bh,  15
1341
    mov ecx, edx
1342
    shl ecx, 2
1343
    shl ebx, cl
1344
    not bh
1345
    and bh, [edi]
8463 IgorA 1346
    or	bl, bh
6807 dunkaist 1347
    mov [edi], bl
1348
    pop ecx ebx
1349
  .bpp4i_horz.pixel_done:
1350
    inc edx
1351
    and edx, 1
1352
    jnz @f
1353
    dec edi
1354
  @@:
1355
    dec eax
1356
    jns @f
1357
    mov eax, 1
1358
    inc esi
1359
  @@:
1360
    dec ebx
1361
    jnz .bpp4i_horz.pixel
1362
 
1363
    pop esi edx ebx
1364
    add esi, [scanline_len]
1365
    mov edi, [scanline_len]
1366
    dec ecx
1367
    jnz .bpp4i_horz.begin
1368
    jmp .exit
1369
 
1370
 
1371
  .exit:
1372
    xor eax, eax
1373
    inc eax
1374
    pop edi esi ebx
1375
    ret
1376
 
1377
  .error:
1378
    xor eax, eax
1379
    pop edi esi ebx
1380
    ret
1381
endp
1382
 
1383
;;================================================================================================;;
1384
proc img.flip _img, _flip_kind ;//////////////////////////////////////////////////////////////////;;
1385
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 1386
;? Flip all layers of image									  ;;
6807 dunkaist 1387
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 1388
;> _img = pointer to image									  ;;
1389
;> _flip_kind = one of FLIP_* constants 							  ;;
6807 dunkaist 1390
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 1391
;< eax = false / true										  ;;
6807 dunkaist 1392
;;================================================================================================;;
1393
    push    1
1394
    mov ebx, [_img]
1395
@@:
1396
    mov eax, [ebx + Image.Previous]
1397
    test    eax, eax
8463 IgorA 1398
    jz	.loop
6807 dunkaist 1399
    mov ebx, eax
1400
    jmp @b
1401
.loop:
1402
    stdcall img.flip.layer, ebx, [_flip_kind]
1403
    test    eax, eax
1404
    jnz @f
1405
    mov byte [esp], 0
1406
@@:
1407
    mov ebx, [ebx + Image.Next]
1408
    test    ebx, ebx
1409
    jnz .loop
1410
    pop eax
1411
    ret
1412
endp
1413
 
1414
;;================================================================================================;;
1415
proc img.rotate.layer _img, _rotate_kind ;////////////////////////////////////////////////////////;;
1416
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 1417
;? Rotate image layer										  ;;
6807 dunkaist 1418
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 1419
;> _img = pointer to image									  ;;
1420
;> _rotate_kind = one of ROTATE_* constants							  ;;
6807 dunkaist 1421
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 1422
;< eax = false / true										  ;;
6807 dunkaist 1423
;;================================================================================================;;
1424
locals
1425
  scanline_len_old    dd ?
1426
  scanline_len_new    dd ?
1427
  scanline_pixels_new dd ?
8463 IgorA 1428
  line_buffer	      dd ?
1429
  pixels_ptr	      dd ?
6807 dunkaist 1430
endl
1431
 
1432
    mov [line_buffer], 0
1433
 
1434
    push    ebx esi edi
1435
    mov ebx, [_img]
1436
    stdcall img._.validate, ebx
8463 IgorA 1437
    or	eax, eax
6807 dunkaist 1438
    jnz .error
1439
 
1440
    cmp [_rotate_kind], ROTATE_90_CCW
8463 IgorA 1441
    je	.rotate_ccw_low
6807 dunkaist 1442
    cmp [_rotate_kind], ROTATE_90_CW
8463 IgorA 1443
    je	.rotate_cw_low
6807 dunkaist 1444
    cmp [_rotate_kind], ROTATE_180
8463 IgorA 1445
    je	.flip
6807 dunkaist 1446
    jmp .exit
1447
 
1448
  .rotate_ccw_low:
1449
    mov eax, [ebx + Image.Height]
1450
    mov [scanline_pixels_new], eax
1451
    call    img._.get_scanline_len
1452
    mov [scanline_len_new], eax
1453
 
1454
    invoke  mem.alloc, eax
8463 IgorA 1455
    or	eax, eax
1456
    jz	.error
6807 dunkaist 1457
    mov [line_buffer], eax
1458
 
1459
    mov eax, [ebx + Image.Width]
1460
    mov ecx, eax
1461
    call    img._.get_scanline_len
1462
    mov [scanline_len_old], eax
1463
 
1464
    mov eax, [scanline_len_new]
1465
    imul    eax, ecx
1466
    add eax, [ebx + Image.Data]
1467
    mov [pixels_ptr], eax
1468
 
1469
    cmp [ebx + Image.Type], Image.bpp1
8463 IgorA 1470
    jz	.rotate_ccw1
6807 dunkaist 1471
    cmp [ebx + Image.Type], Image.bpp2i
8463 IgorA 1472
    jz	.rotate_ccw2i
6807 dunkaist 1473
    cmp [ebx + Image.Type], Image.bpp4i
8463 IgorA 1474
    jz	.rotate_ccw4i
6807 dunkaist 1475
    cmp [ebx + Image.Type], Image.bpp8i
8463 IgorA 1476
    jz	.rotate_ccw8ig
6807 dunkaist 1477
    cmp [ebx + Image.Type], Image.bpp8g
8463 IgorA 1478
    jz	.rotate_ccw8ig
6807 dunkaist 1479
    cmp [ebx + Image.Type], Image.bpp24
8463 IgorA 1480
    jz	.rotate_ccw24
6807 dunkaist 1481
    cmp [ebx + Image.Type], Image.bpp32
8463 IgorA 1482
    jz	.rotate_ccw32
6807 dunkaist 1483
 
1484
  .next_column_ccw_low1x:
1485
    dec ecx
8463 IgorA 1486
    js	.exchange_dims
6807 dunkaist 1487
    push    ecx
1488
 
1489
    mov edx, [scanline_len_old]
1490
    add [scanline_len_old], -2
1491
 
1492
    mov ecx, [scanline_pixels_new]
1493
    mov esi, [ebx + Image.Data]
1494
    mov edi, [line_buffer]
1495
    @@: mov ax, [esi]
1496
    mov [edi], ax
1497
    add esi, edx
1498
    add edi, 2
1499
    sub ecx, 1
1500
    jnz @b
1501
 
1502
    mov eax, [scanline_pixels_new]
1503
    mov edi, [ebx + Image.Data]
1504
    lea esi, [edi + 2]
1505
    mov edx, [scanline_len_old]
1506
    @@: mov ecx, edx
1507
    shr ecx, 2
1508
    rep movsd
1509
    mov ecx, edx
1510
    and ecx, 3
1511
    rep movsb
1512
    add esi, 1
1513
    sub eax, 1
1514
    jnz @b
1515
 
1516
    mov eax, [scanline_len_new]
1517
    sub [pixels_ptr], eax
1518
    mov ecx, [scanline_pixels_new]
1519
    mov esi, [line_buffer]
1520
    mov edi, [pixels_ptr]
1521
    mov edx, ecx
1522
    shr ecx, 2
1523
    rep movsd
1524
    mov ecx, edx
1525
    and ecx, 3
1526
    rep movsb
1527
 
1528
    pop ecx
1529
    jmp .next_column_ccw_low1x
1530
 
1531
.rotate_ccw32:
1532
  .next_column_ccw_low:
1533
    dec ecx
8463 IgorA 1534
    js	.exchange_dims
6807 dunkaist 1535
    push    ecx
1536
 
1537
    mov edx, [scanline_len_old]
1538
    add [scanline_len_old], -4
1539
 
1540
    mov ecx, [scanline_pixels_new]
1541
    mov esi, [ebx + Image.Data]
1542
    mov edi, [line_buffer]
1543
    @@: mov eax, [esi]
1544
    stosd
1545
    add esi, edx
1546
    dec ecx
1547
    jnz @b
1548
 
1549
    mov eax, [scanline_pixels_new]
1550
    mov edi, [ebx + Image.Data]
1551
    lea esi, [edi + 4]
1552
    mov edx, [scanline_len_old]
1553
    shr edx, 2
1554
    @@: mov ecx, edx
1555
    rep movsd
1556
    add esi, 4
1557
    dec eax
1558
    jnz @b
1559
 
1560
    mov eax, [scanline_len_new]
1561
    sub [pixels_ptr], eax
1562
    mov ecx, [scanline_pixels_new]
1563
    mov esi, [line_buffer]
1564
    mov edi, [pixels_ptr]
1565
    rep movsd
1566
 
1567
    pop ecx
1568
    jmp .next_column_ccw_low
1569
 
1570
.rotate_ccw8ig:
1571
  .next_column_ccw_low8ig:
1572
    dec ecx
8463 IgorA 1573
    js	.exchange_dims
6807 dunkaist 1574
    push    ecx
1575
 
1576
    mov edx, [scanline_len_old]
1577
    add [scanline_len_old], -1
1578
 
1579
    mov ecx, [scanline_pixels_new]
1580
    mov esi, [ebx + Image.Data]
1581
    mov edi, [line_buffer]
1582
    @@: mov al, [esi]
1583
    mov [edi], al
1584
    add esi, edx
1585
    add edi, 1
1586
    sub ecx, 1
1587
    jnz @b
1588
 
1589
    mov eax, [scanline_pixels_new]
1590
    mov edi, [ebx + Image.Data]
1591
    lea esi, [edi + 1]
1592
    mov edx, [scanline_len_old]
1593
    @@: mov ecx, edx
1594
    shr ecx, 2
1595
    rep movsd
1596
    mov ecx, edx
1597
    and ecx, 3
1598
    rep movsb
1599
    add esi, 1
1600
    sub eax, 1
1601
    jnz @b
1602
 
1603
    mov eax, [scanline_len_new]
1604
    sub [pixels_ptr], eax
1605
    mov ecx, [scanline_pixels_new]
1606
    mov esi, [line_buffer]
1607
    mov edi, [pixels_ptr]
1608
    mov edx, ecx
1609
    shr ecx, 2
1610
    rep movsd
1611
    mov ecx, edx
1612
    and ecx, 3
1613
    rep movsb
1614
 
1615
    pop ecx
1616
    jmp .next_column_ccw_low8ig
1617
 
1618
.rotate_ccw24:
1619
  .next_column_ccw_low24:
1620
    dec ecx
8463 IgorA 1621
    js	.exchange_dims
6807 dunkaist 1622
    push    ecx
1623
 
1624
    mov edx, [scanline_len_old]
1625
    add [scanline_len_old], -3
1626
 
1627
    mov ecx, [scanline_pixels_new]
1628
    mov esi, [ebx + Image.Data]
1629
    mov edi, [line_buffer]
1630
    @@: mov al, [esi]
1631
    mov [edi], al
1632
    mov al, [esi+1]
1633
    mov [edi+1], al
1634
    mov al, [esi+2]
1635
    mov [edi+2], al
1636
    add esi, edx
1637
    add edi, 3
1638
    sub ecx, 1
1639
    jnz @b
1640
 
1641
    mov eax, [scanline_pixels_new]
1642
    mov edi, [ebx + Image.Data]
1643
    lea esi, [edi + 3]
1644
    mov edx, [scanline_len_old]
1645
    @@: mov ecx, edx
1646
    shr ecx, 2
1647
    rep movsd
1648
    mov ecx, edx
1649
    and ecx, 3
1650
    rep movsb
1651
    add esi, 3
1652
    sub eax, 1
1653
    jnz @b
1654
 
1655
    mov eax, [scanline_len_new]
1656
    sub [pixels_ptr], eax
1657
    mov ecx, eax
1658
    mov esi, [line_buffer]
1659
    mov edi, [pixels_ptr]
1660
    shr ecx, 2
1661
    rep movsd
1662
    mov ecx, eax
1663
    and ecx, 3
1664
    rep movsb
1665
 
1666
    pop ecx
1667
    jmp .next_column_ccw_low24
1668
 
1669
.rotate_ccw1:
1670
    push ecx edx
1671
 
1672
    mov eax, [ebx + Image.Height]
1673
    add eax, 7
1674
    shr eax, 3
1675
    imul eax, [ebx + Image.Width]
8463 IgorA 1676
    push eax						; save new data size
6807 dunkaist 1677
 
1678
    invoke  mem.alloc, eax
8463 IgorA 1679
    or	eax, eax
1680
    jz	.error
1681
    push eax						; save pointer to new data
6807 dunkaist 1682
 
1683
    mov ecx, [ebx + Image.Width]
1684
    and ecx, 7
1685
    neg ecx
1686
    add ecx, 8
1687
    and ecx, 7
1688
 
1689
    mov edi, eax
1690
    mov esi, [ebx + Image.Data]
1691
    mov eax, 7
1692
    mov edx, [scanline_len_old]
1693
    dec edx
1694
    add esi, edx
1695
 
1696
  .rotate_ccw1.begin:
8463 IgorA 1697
    bt	[esi], ecx
6807 dunkaist 1698
    jc .rotate_ccw1.one
1699
  .rotate_ccw1.zero:
1700
    btr [edi], eax
1701
    jmp @f
1702
  .rotate_ccw1.one:
1703
    bts [edi], eax
1704
  @@:
1705
    add esi, [scanline_len_old]
1706
    dec [scanline_pixels_new]
1707
    jz .rotate_ccw1.end_of_line
1708
    sub eax, 1
1709
    adc edi, 0
1710
    and eax, 7
1711
    jmp .rotate_ccw1.begin
1712
  .rotate_ccw1.end_of_line:
1713
    inc edi
1714
    mov eax, [ebx + Image.Height]
1715
    mov [scanline_pixels_new], eax
1716
    mov eax, 7
1717
    inc ecx
1718
    and ecx, 7
1719
    jz @f
1720
    mov esi, [ebx + Image.Data]
1721
    add esi, edx
1722
    jmp .rotate_ccw1.begin
1723
  @@:
1724
    dec edx
1725
    js .rotate_ccw1.quit
1726
    mov esi, [ebx + Image.Data]
1727
    add esi, edx
1728
    jmp .rotate_ccw1.begin
1729
  .rotate_ccw1.quit:
8463 IgorA 1730
    pop esi						; get pointer to new data
6807 dunkaist 1731
    mov edi, [ebx + Image.Data]
8463 IgorA 1732
    pop ecx						; get new data size
6807 dunkaist 1733
    rep movsb
1734
    invoke  mem.free, esi
1735
    pop edx ecx
1736
     jmp .exchange_dims
1737
 
1738
 
1739
.rotate_ccw2i:
1740
    push ecx edx
1741
 
1742
    mov eax, [ebx + Image.Height]
1743
    add eax, 3
1744
    shr eax, 2
1745
    imul eax, [ebx + Image.Width]
8463 IgorA 1746
    push eax						; save new data size
6807 dunkaist 1747
 
1748
    invoke  mem.alloc, eax
8463 IgorA 1749
    or	eax, eax
1750
    jz	.error
1751
    push eax						; save pointer to new data
6807 dunkaist 1752
 
1753
    mov ecx, [ebx + Image.Width]
1754
    and ecx, 3
1755
    neg ecx
1756
    add ecx, 4
1757
    and ecx, 3
1758
 
1759
    mov edi, eax
1760
    mov esi, [ebx + Image.Data]
1761
    mov eax, 3
1762
    mov edx, [scanline_len_old]
1763
    dec edx
1764
    add esi, edx
1765
 
1766
  .rotate_ccw2i.begin:
1767
    push ebx ecx
1768
    mov ebx, 3
1769
    shl ebx, cl
1770
    shl ebx, cl
1771
    and bl, [esi]
1772
    shr ebx, cl
1773
    shr ebx, cl
1774
    mov bh, 3
1775
    mov ecx, eax
1776
    shl ebx, cl
1777
    shl ebx, cl
1778
    not bh
1779
    and bh, [edi]
8463 IgorA 1780
    or	bl, bh
6807 dunkaist 1781
    mov [edi], bl
1782
    pop ecx ebx
1783
 
1784
    add esi, [scanline_len_old]
1785
    dec [scanline_pixels_new]
1786
    jz .rotate_ccw2i.end_of_line
1787
    sub eax, 1
1788
    adc edi, 0
1789
    and eax, 3
1790
    jmp .rotate_ccw2i.begin
1791
  .rotate_ccw2i.end_of_line:
1792
    inc edi
1793
    mov eax, 3
1794
    mov esi, [ebx + Image.Height]
1795
    mov [scanline_pixels_new], esi
1796
    inc ecx
1797
    and ecx, 3
1798
    jz @f
1799
    mov esi, [ebx + Image.Data]
1800
    add esi, edx
1801
    jmp .rotate_ccw2i.begin
1802
  @@:
1803
    dec edx
1804
    js .rotate_ccw2i.quit
1805
    mov esi, [ebx + Image.Data]
1806
    add esi, edx
1807
    jmp .rotate_ccw2i.begin
1808
  .rotate_ccw2i.quit:
8463 IgorA 1809
    pop esi						; get pointer to new data
6807 dunkaist 1810
    mov edi, [ebx + Image.Data]
8463 IgorA 1811
    pop ecx						; get new data size
6807 dunkaist 1812
    rep movsb
1813
    invoke  mem.free, esi
1814
    pop edx ecx
1815
     jmp .exchange_dims
1816
 
1817
 
1818
.rotate_ccw4i:
1819
    push ecx edx
1820
 
1821
    mov eax, [ebx + Image.Height]
1822
    add eax, 1
1823
    shr eax, 1
1824
    imul eax, [ebx + Image.Width]
8463 IgorA 1825
    push eax						; save new data size
6807 dunkaist 1826
 
1827
    invoke  mem.alloc, eax
8463 IgorA 1828
    or	eax, eax
1829
    jz	.error
1830
    push eax						; save pointer to new data
6807 dunkaist 1831
 
1832
    mov ecx, [ebx + Image.Width]
1833
    and ecx, 1
1834
    neg ecx
1835
    add ecx, 2
1836
    and ecx, 1
1837
 
1838
    mov edi, eax
1839
    mov esi, [ebx + Image.Data]
1840
    mov eax, 1
1841
    mov edx, [scanline_len_old]
1842
    dec edx
1843
    add esi, edx
1844
 
1845
  .rotate_ccw4i.begin:
1846
    push ebx ecx
1847
    mov ebx, 15
1848
    shl ecx, 2
1849
    shl ebx, cl
1850
    and bl, [esi]
1851
    shr ebx, cl
1852
    mov bh, 15
1853
    mov ecx, eax
1854
    shl ecx, 2
1855
    shl ebx, cl
1856
    not bh
1857
    and bh, [edi]
8463 IgorA 1858
    or	bl, bh
6807 dunkaist 1859
    mov [edi], bl
1860
    pop ecx ebx
1861
 
1862
    add esi, [scanline_len_old]
1863
    dec [scanline_pixels_new]
1864
    jz .rotate_ccw4i.end_of_line
1865
    sub eax, 1
1866
    adc edi, 0
1867
    and eax, 1
1868
    jmp .rotate_ccw4i.begin
1869
  .rotate_ccw4i.end_of_line:
1870
    inc edi
1871
    mov eax, 1
1872
    mov esi, [ebx + Image.Height]
1873
    mov [scanline_pixels_new], esi
1874
    inc ecx
1875
    and ecx, 1
1876
    jz @f
1877
    mov esi, [ebx + Image.Data]
1878
    add esi, edx
1879
    jmp .rotate_ccw4i.begin
1880
  @@:
1881
    dec edx
1882
    js .rotate_ccw4i.quit
1883
    mov esi, [ebx + Image.Data]
1884
    add esi, edx
1885
    jmp .rotate_ccw4i.begin
1886
  .rotate_ccw4i.quit:
8463 IgorA 1887
    pop esi						; get pointer to new data
6807 dunkaist 1888
    mov edi, [ebx + Image.Data]
8463 IgorA 1889
    pop ecx						; get new data size
6807 dunkaist 1890
    rep movsb
1891
    invoke  mem.free, esi
1892
    pop edx ecx
1893
     jmp .exchange_dims
1894
 
1895
 
1896
 
1897
  .rotate_cw_low:
1898
    mov eax, [ebx + Image.Height]
1899
    mov [scanline_pixels_new], eax
1900
    call    img._.get_scanline_len
1901
    mov [scanline_len_new], eax
1902
 
1903
    invoke  mem.alloc, eax
8463 IgorA 1904
    or	eax, eax
1905
    jz	.error
6807 dunkaist 1906
    mov [line_buffer], eax
1907
 
1908
    mov eax, [ebx + Image.Width]
1909
    mov ecx, eax
1910
    call    img._.get_scanline_len
1911
    mov [scanline_len_old], eax
1912
 
1913
    mov eax, [scanline_len_new]
1914
    imul    eax, ecx
1915
    add eax, [ebx + Image.Data]
1916
    mov [pixels_ptr], eax
1917
 
1918
    cmp [ebx + Image.Type], Image.bpp1
8463 IgorA 1919
    jz	.rotate_cw1
6807 dunkaist 1920
    cmp [ebx + Image.Type], Image.bpp2i
8463 IgorA 1921
    jz	.rotate_cw2i
6807 dunkaist 1922
    cmp [ebx + Image.Type], Image.bpp4i
8463 IgorA 1923
    jz	.rotate_cw4i
6807 dunkaist 1924
    cmp [ebx + Image.Type], Image.bpp8i
8463 IgorA 1925
    jz	.rotate_cw8ig
6807 dunkaist 1926
    cmp [ebx + Image.Type], Image.bpp8g
8463 IgorA 1927
    jz	.rotate_cw8ig
6807 dunkaist 1928
    cmp [ebx + Image.Type], Image.bpp24
8463 IgorA 1929
    jz	.rotate_cw24
6807 dunkaist 1930
    cmp [ebx + Image.Type], Image.bpp32
8463 IgorA 1931
    jz	.rotate_cw32
6807 dunkaist 1932
 
1933
  .next_column_cw_low1x:
1934
    dec ecx
8463 IgorA 1935
    js	.exchange_dims
6807 dunkaist 1936
    push    ecx
1937
 
1938
    mov edx, [scanline_len_old]
1939
    add [scanline_len_old], -2
1940
 
1941
    mov ecx, [scanline_pixels_new]
1942
    mov esi, [pixels_ptr]
1943
    add esi, -2
1944
    mov edi, [line_buffer]
1945
    @@: mov ax, [esi]
1946
    mov [edi], ax
1947
    sub esi, edx
1948
    add edi, 2
1949
    sub ecx, 1
1950
    jnz @b
1951
 
1952
    mov eax, [scanline_pixels_new]
1953
    dec eax
1954
    mov edi, [ebx + Image.Data]
1955
    add edi, [scanline_len_old]
1956
    lea esi, [edi + 2]
1957
    mov edx, [scanline_len_old]
1958
    @@: mov ecx, edx
1959
    shr ecx, 2
1960
    rep movsd
1961
    mov ecx, edx
1962
    and ecx, 3
1963
    rep movsb
1964
    add esi, 3
1965
    sub eax, 1
1966
    jnz @b
1967
 
1968
    mov eax, [scanline_len_new]
1969
    sub [pixels_ptr], eax
1970
    mov ecx, eax
1971
    mov esi, [line_buffer]
1972
    mov edi, [pixels_ptr]
1973
    shr ecx, 2
1974
    rep movsd
1975
    mov ecx, eax
1976
    and ecx, 3
1977
    rep movsb
1978
 
1979
    pop ecx
1980
    jmp .next_column_cw_low1x
1981
 
1982
.rotate_cw32:
1983
  .next_column_cw_low:
1984
    dec ecx
8463 IgorA 1985
    js	.exchange_dims
6807 dunkaist 1986
    push    ecx
1987
 
1988
    mov edx, [scanline_len_old]
1989
    add [scanline_len_old], -4
1990
 
1991
    mov ecx, [scanline_pixels_new]
1992
    mov esi, [pixels_ptr]
1993
    add esi, -4
1994
    mov edi, [line_buffer]
1995
    @@: mov eax, [esi]
1996
    stosd
1997
    sub esi, edx
1998
    dec ecx
1999
    jnz @b
2000
 
2001
    mov eax, [scanline_pixels_new]
2002
    dec eax
2003
    mov edi, [ebx + Image.Data]
2004
    add edi, [scanline_len_old]
2005
    lea esi, [edi + 4]
2006
    mov edx, [scanline_len_old]
2007
    shr edx, 2
2008
    @@: mov ecx, edx
2009
    rep movsd
2010
    add esi, 4
2011
    dec eax
2012
    jnz @b
2013
 
2014
    mov eax, [scanline_len_new]
2015
    sub [pixels_ptr], eax
2016
    mov ecx, [scanline_pixels_new]
2017
    mov esi, [line_buffer]
2018
    mov edi, [pixels_ptr]
2019
    rep movsd
2020
 
2021
    pop ecx
2022
    jmp .next_column_cw_low
2023
 
2024
.rotate_cw8ig:
2025
  .next_column_cw_low8ig:
2026
    dec ecx
8463 IgorA 2027
    js	.exchange_dims
6807 dunkaist 2028
    push    ecx
2029
 
2030
    mov edx, [scanline_len_old]
2031
    add [scanline_len_old], -1
2032
 
2033
    mov ecx, [scanline_pixels_new]
2034
    mov esi, [pixels_ptr]
2035
    add esi, -1
2036
    mov edi, [line_buffer]
2037
    @@: mov al, [esi]
2038
    mov [edi], al
2039
    sub esi, edx
2040
    add edi, 1
2041
    sub ecx, 1
2042
    jnz @b
2043
 
2044
    mov eax, [scanline_pixels_new]
2045
    dec eax
2046
    mov edi, [ebx + Image.Data]
2047
    add edi, [scanline_len_old]
2048
    lea esi, [edi + 1]
2049
    mov edx, [scanline_len_old]
2050
    @@: mov ecx, edx
2051
    shr ecx, 2
2052
    rep movsd
2053
    mov ecx, edx
2054
    and ecx, 3
2055
    rep movsb
2056
    add esi, 1
2057
    sub eax, 1
2058
    jnz @b
2059
 
2060
    mov eax, [scanline_len_new]
2061
    sub [pixels_ptr], eax
2062
    mov ecx, eax
2063
    mov esi, [line_buffer]
2064
    mov edi, [pixels_ptr]
2065
    shr ecx, 2
2066
    rep movsd
2067
    mov ecx, eax
2068
    and ecx, 3
2069
    rep movsb
2070
 
2071
    pop ecx
2072
    jmp .next_column_cw_low8ig
2073
 
2074
.rotate_cw24:
2075
  .next_column_cw_low24:
2076
    dec ecx
8463 IgorA 2077
    js	.exchange_dims
6807 dunkaist 2078
    push    ecx
2079
 
2080
    mov edx, [scanline_len_old]
2081
    add [scanline_len_old], -3
2082
 
2083
    mov ecx, [scanline_pixels_new]
2084
    mov esi, [pixels_ptr]
2085
    add esi, -3
2086
    mov edi, [line_buffer]
2087
    @@: mov al, [esi]
2088
    mov [edi], al
2089
    mov al, [esi+1]
2090
    mov [edi+1], al
2091
    mov al, [esi+2]
2092
    mov [edi+2], al
2093
    sub esi, edx
2094
    add edi, 3
2095
    sub ecx, 1
2096
    jnz @b
2097
 
2098
    mov eax, [scanline_pixels_new]
2099
    dec eax
2100
    mov edi, [ebx + Image.Data]
2101
    add edi, [scanline_len_old]
2102
    lea esi, [edi + 3]
2103
    mov edx, [scanline_len_old]
2104
    @@: mov ecx, edx
2105
    shr ecx, 2
2106
    rep movsd
2107
    mov ecx, edx
2108
    and ecx, 3
2109
    rep movsb
2110
    add esi, 3
2111
    sub eax, 1
2112
    jnz @b
2113
 
2114
    mov eax, [scanline_len_new]
2115
    sub [pixels_ptr], eax
2116
    mov ecx, eax
2117
    mov esi, [line_buffer]
2118
    mov edi, [pixels_ptr]
2119
    shr ecx, 2
2120
    rep movsd
2121
    mov ecx, eax
2122
    and ecx, 3
2123
    rep movsb
2124
 
2125
    pop ecx
2126
    jmp .next_column_cw_low24
2127
 
2128
 
2129
.rotate_cw1:
2130
    push ecx edx
2131
 
2132
    mov eax, [ebx + Image.Height]
2133
    add eax, 7
2134
    shr eax, 3
2135
    imul [ebx + Image.Width]
8463 IgorA 2136
    push eax						; save new data size
6807 dunkaist 2137
 
2138
    invoke  mem.alloc, eax
8463 IgorA 2139
    or	eax, eax
2140
    jz	.error
2141
    push eax						; save pointer to new data
6807 dunkaist 2142
 
2143
    mov edi, eax
2144
    mov esi, [ebx + Image.Data]
2145
    mov eax, [ebx + Image.Height]
2146
    dec eax
2147
    imul eax, [scanline_len_old]
2148
    add esi, eax
2149
    mov eax, 7
2150
    mov ecx, 7
2151
    mov edx, 0
2152
 
2153
  .rotate_cw1.begin:
8463 IgorA 2154
    bt	[esi], ecx
6807 dunkaist 2155
    jc .rotate_cw1.one
2156
  .rotate_cw1.zero:
2157
    btr [edi], eax
2158
    jmp @f
2159
  .rotate_cw1.one:
2160
    bts [edi], eax
2161
  @@:
2162
    sub esi, [scanline_len_old]
2163
    dec [scanline_pixels_new]
8463 IgorA 2164
    jz	.rotate_cw1.end_of_line
6807 dunkaist 2165
    sub eax, 1
2166
    adc edi, 0
2167
    and eax, 7
2168
    jmp .rotate_cw1.begin
2169
  .rotate_cw1.end_of_line:
2170
    inc edi
2171
    mov eax, [ebx + Image.Height]
8463 IgorA 2172
    mov [scanline_pixels_new],	 eax
6807 dunkaist 2173
    mov eax, 7
2174
    dec ecx
2175
    jns @f
2176
    mov ecx, 7
2177
    inc edx
2178
    cmp edx, [scanline_len_old]
2179
    je .rotate_cw1.quit
2180
  @@:
2181
    mov esi, [ebx + Image.Height]
2182
    dec esi
2183
    imul esi, [scanline_len_old]
2184
    add esi, [ebx + Image.Data]
2185
    add esi, edx
2186
    jmp .rotate_cw1.begin
2187
  .rotate_cw1.quit:
8463 IgorA 2188
    pop eax						; get pointer to new data
6807 dunkaist 2189
    mov esi, eax
2190
    mov edi, [ebx + Image.Data]
8463 IgorA 2191
    pop ecx						; get new data size
6807 dunkaist 2192
    rep movsb
2193
    invoke  mem.free, eax
2194
    pop edx ecx
2195
    jmp .exchange_dims
2196
 
2197
 
2198
.rotate_cw2i:
2199
    push ecx edx
2200
 
2201
    mov eax, [ebx + Image.Height]
2202
    add eax, 3
2203
    shr eax, 2
2204
    imul [ebx + Image.Width]
8463 IgorA 2205
    push eax						; save new data size
6807 dunkaist 2206
 
2207
    invoke  mem.alloc, eax
8463 IgorA 2208
    or	eax, eax
2209
    jz	.error
2210
    push eax						; save pointer to new data
6807 dunkaist 2211
 
2212
    mov edi, eax
2213
    mov esi, [ebx + Image.Data]
2214
    mov eax, [ebx + Image.Height]
2215
    dec eax
2216
    imul eax, [scanline_len_old]
2217
    add esi, eax
2218
    mov eax, 3
2219
    mov ecx, 3
2220
    mov edx, 0
2221
 
2222
  .rotate_cw2i.begin:
2223
    push ebx ecx
2224
    mov ebx, 3
2225
    shl ebx, cl
2226
    shl ebx, cl
2227
    and bl, [esi]
2228
    shr ebx, cl
2229
    shr ebx, cl
2230
    mov bh, 3
2231
    mov ecx, eax
2232
    shl ebx, cl
2233
    shl ebx, cl
2234
    not bh
2235
    and bh, [edi]
8463 IgorA 2236
    or	bl, bh
6807 dunkaist 2237
    mov [edi], bl
2238
    pop ecx ebx
2239
 
2240
    sub esi, [scanline_len_old]
2241
    dec [scanline_pixels_new]
8463 IgorA 2242
    jz	.rotate_cw2i.end_of_line
6807 dunkaist 2243
    sub eax, 1
2244
    adc edi, 0
2245
    and eax, 3
2246
    jmp .rotate_cw2i.begin
2247
  .rotate_cw2i.end_of_line:
2248
    inc edi
2249
    mov eax, [ebx + Image.Height]
8463 IgorA 2250
    mov [scanline_pixels_new],	 eax
6807 dunkaist 2251
    mov eax, 3
2252
    dec ecx
2253
    jns @f
2254
    mov ecx, 3
2255
    inc edx
2256
    cmp edx, [scanline_len_old]
2257
    je .rotate_cw2i.quit
2258
  @@:
2259
    mov esi, [ebx + Image.Height]
2260
    dec esi
2261
    imul esi, [scanline_len_old]
2262
    add esi, [ebx + Image.Data]
2263
    add esi, edx
2264
    jmp .rotate_cw2i.begin
2265
  .rotate_cw2i.quit:
8463 IgorA 2266
    pop eax						; get pointer to new data
6807 dunkaist 2267
    mov esi, eax
2268
    mov edi, [ebx + Image.Data]
8463 IgorA 2269
    pop ecx						; get new data size
6807 dunkaist 2270
    rep movsb
2271
    invoke  mem.free, eax
2272
    pop edx ecx
2273
    jmp .exchange_dims
2274
 
2275
 
2276
.rotate_cw4i:
2277
    push ecx edx
2278
 
2279
    mov eax, [ebx + Image.Height]
2280
    add eax, 1
2281
    shr eax, 1
2282
    imul [ebx + Image.Width]
8463 IgorA 2283
    push eax						; save new data size
6807 dunkaist 2284
 
2285
    invoke  mem.alloc, eax
8463 IgorA 2286
    or	eax, eax
2287
    jz	.error
2288
    push eax						; save pointer to new data
6807 dunkaist 2289
 
2290
    mov edi, eax
2291
    mov esi, [ebx + Image.Data]
2292
    mov eax, [ebx + Image.Height]
2293
    dec eax
2294
    imul eax, [scanline_len_old]
2295
    add esi, eax
2296
    mov eax, 1
2297
    mov ecx, 1
2298
    mov edx, 0
2299
 
2300
  .rotate_cw4i.begin:
2301
    push ebx ecx
2302
    mov ebx, 15
2303
    shl ecx, 2
2304
    shl ebx, cl
2305
    and bl, [esi]
2306
    shr ebx, cl
2307
    mov bh, 15
2308
    mov ecx, eax
2309
    shl ecx, 2
2310
    shl ebx, cl
2311
    not bh
2312
    and bh, [edi]
8463 IgorA 2313
    or	bl, bh
6807 dunkaist 2314
    mov [edi], bl
2315
    pop ecx ebx
2316
 
2317
    sub esi, [scanline_len_old]
2318
    dec [scanline_pixels_new]
8463 IgorA 2319
    jz	.rotate_cw4i.end_of_line
6807 dunkaist 2320
    sub eax, 1
2321
    adc edi, 0
2322
    and eax, 1
2323
    jmp .rotate_cw4i.begin
2324
  .rotate_cw4i.end_of_line:
2325
    inc edi
2326
    mov eax, [ebx + Image.Height]
8463 IgorA 2327
    mov [scanline_pixels_new],	 eax
6807 dunkaist 2328
    mov eax, 1
2329
    dec ecx
2330
    jns @f
2331
    mov ecx, 1
2332
    inc edx
2333
    cmp edx, [scanline_len_old]
2334
    je .rotate_cw4i.quit
2335
  @@:
2336
    mov esi, [ebx + Image.Height]
2337
    dec esi
2338
    imul esi, [scanline_len_old]
2339
    add esi, [ebx + Image.Data]
2340
    add esi, edx
2341
    jmp .rotate_cw4i.begin
2342
  .rotate_cw4i.quit:
8463 IgorA 2343
    pop eax						; get pointer to new data
6807 dunkaist 2344
    mov esi, eax
2345
    mov edi, [ebx + Image.Data]
8463 IgorA 2346
    pop ecx						; get new data size
6807 dunkaist 2347
    rep movsb
2348
    invoke  mem.free, eax
2349
    pop edx ecx
2350
    jmp .exchange_dims
2351
 
2352
 
2353
  .flip:
2354
    stdcall img.flip.layer, [_img], FLIP_VERTICAL
2355
    test eax, eax
8463 IgorA 2356
    jz	.error
6807 dunkaist 2357
    jmp .exit
2358
 
2359
  .exchange_dims:
2360
    push    [ebx + Image.Width] [ebx + Image.Height]
2361
    pop [ebx + Image.Width] [ebx + Image.Height]
2362
 
2363
  .exit:
2364
    invoke  mem.free, [line_buffer]
2365
    xor eax, eax
2366
    inc eax
2367
    pop edi esi ebx
2368
    ret
2369
 
2370
  .error:
2371
    invoke  mem.free, [line_buffer]
2372
    xor eax, eax
2373
    pop edi esi ebx
2374
    ret
2375
endp
2376
 
2377
;;================================================================================================;;
2378
proc img.rotate _img, _rotate_kind ;//////////////////////////////////////////////////////////////;;
2379
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 2380
;? Rotate all layers of image									  ;;
6807 dunkaist 2381
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 2382
;> _img = pointer to image									  ;;
2383
;> _rotate_kind = one of ROTATE_* constants							  ;;
6807 dunkaist 2384
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 2385
;< eax = false / true										  ;;
6807 dunkaist 2386
;;================================================================================================;;
2387
    push    1
2388
    mov ebx, [_img]
2389
@@:
2390
    mov eax, [ebx + Image.Previous]
2391
    test    eax, eax
8463 IgorA 2392
    jz	.loop
6807 dunkaist 2393
    mov ebx, eax
2394
    jmp @b
2395
.loop:
2396
    stdcall img.rotate.layer, ebx, [_rotate_kind]
2397
    test    eax, eax
2398
    jnz @f
2399
    mov byte [esp], 0
2400
@@:
2401
    mov ebx, [ebx + Image.Next]
2402
    test    ebx, ebx
2403
    jnz .loop
2404
    pop eax
2405
    ret
2406
endp
2407
 
2408
;;================================================================================================;;
2409
proc img.draw _img, _x, _y, _width, _height, _xpos, _ypos ;///////////////////////////////////////;;
2410
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 2411
;? Draw image in the window									  ;;
6807 dunkaist 2412
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 2413
;> _img = pointer to image									  ;;
2414
;>_x = x-coordinate in the window								  ;;
2415
;>_y = y-coordinate in the window								  ;;
2416
;>_width = maximum width to draw								  ;;
2417
;>_height = maximum height to draw								  ;;
2418
;>_xpos = offset in image by x-axis								  ;;
2419
;>_ypos = offset in image by y-axis								  ;;
6807 dunkaist 2420
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 2421
;< no return value										  ;;
6807 dunkaist 2422
;;================================================================================================;;
2423
    push    ebx esi edi
2424
    mov ebx, [_img]
2425
    stdcall img._.validate, ebx
2426
    test    eax, eax
2427
    jnz .done
2428
    mov ecx, [ebx + Image.Width]
2429
    sub ecx, [_xpos]
2430
    jbe .done
2431
    cmp ecx, [_width]
8463 IgorA 2432
    jb	@f
6807 dunkaist 2433
    mov ecx, [_width]
2434
@@:
2435
    mov edx, [ebx + Image.Height]
2436
    sub edx, [_ypos]
2437
    jbe .done
2438
    cmp edx, [_height]
8463 IgorA 2439
    jb	@f
6807 dunkaist 2440
    mov edx, [_height]
2441
@@:
2442
    mov eax, [ebx + Image.Width]
2443
    sub eax, ecx
2444
    call    img._.get_scanline_len
2445
    shl ecx, 16
2446
    add ecx, edx
2447
    push    eax
2448
    mov eax, [ebx + Image.Width]
2449
    imul    eax, [_ypos]
2450
    add eax, [_xpos]
2451
    call    img._.get_scanline_len
2452
    add eax, [ebx + Image.Data]
2453
    mov edx, [_x - 2]
2454
    mov dx, word [_y]
2455
    mov esi, [ebx + Image.Type]
2456
    mov esi, [type2bpp + (esi-1)*4]
2457
    mov edi, [ebx + Image.Palette]
2458
    xchg    eax, ebx
2459
    pop eax
2460
    push    ebp
2461
    push    65
2462
    pop ebp
2463
    xchg    eax, ebp
2464
    int 40h
2465
    pop ebp
2466
.done:
2467
    pop edi esi ebx
2468
    ret
2469
endp
2470
 
2471
 
2472
align 4
2473
img.formats_table:
8463 IgorA 2474
  .bmp	dd LIBIMG_FORMAT_BMP,  img.is.bmp,  img.decode.bmp,	img.encode.bmp, 1 + (1 SHL Image.bpp24) + (1 SHL Image.bpp32)
2475
  .ico	dd LIBIMG_FORMAT_ICO,  img.is.ico,  img.decode.ico_cur, img.encode.ico, 0
2476
  .cur	dd LIBIMG_FORMAT_CUR,  img.is.cur,  img.decode.ico_cur, img.encode.cur, 0
2477
  .gif	dd LIBIMG_FORMAT_GIF,  img.is.gif,  img.decode.gif,	img.encode.gif, 0
2478
  .png	dd LIBIMG_FORMAT_PNG,  img.is.png,  img.decode.png,	img.encode.png, 1 + (1 SHL Image.bpp24)
2479
  .jpg	dd LIBIMG_FORMAT_JPEG, img.is.jpg,  img.decode.jpg,	img.encode.jpg, 0
2480
  .tga	dd LIBIMG_FORMAT_TGA,  img.is.tga,  img.decode.tga,	img.encode.tga, 0
2481
  .pcx	dd LIBIMG_FORMAT_PCX,  img.is.pcx,  img.decode.pcx,	img.encode.pcx, 0
2482
  .xcf	dd LIBIMG_FORMAT_XCF,  img.is.xcf,  img.decode.xcf,	img.encode.xcf, 0
2483
  .tiff dd LIBIMG_FORMAT_TIFF, img.is.tiff, img.decode.tiff,	img.encode.tiff,0
2484
  .pnm	dd LIBIMG_FORMAT_PNM,  img.is.pnm,  img.decode.pnm,	img.encode.pnm, 1 + (1 SHL Image.bpp1) + (1 SHL Image.bpp8g) + (1 SHL Image.bpp24)
2485
  .wbmp dd LIBIMG_FORMAT_WBMP, img.is.wbmp, img.decode.wbmp,	img.encode.wbmp,0
2486
  .xbm	dd LIBIMG_FORMAT_XBM,  img.is.xbm,  img.decode.xbm,	img.encode.xbm, 0
2487
  .z80	dd LIBIMG_FORMAT_Z80,  img.is.z80,  img.decode.z80,	img.encode.z80, 0 ;this must be the last entry as there are no signatures in z80 screens at all
2488
	dd 0
6807 dunkaist 2489
 
2490
;;================================================================================================;;
2491
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
2492
;;================================================================================================;;
8463 IgorA 2493
;! Below are private procs you should never call directly from your code			  ;;
6807 dunkaist 2494
;;================================================================================================;;
2495
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
2496
;;================================================================================================;;
2497
 
2498
 
2499
;;================================================================================================;;
2500
proc img._.validate, _img ;///////////////////////////////////////////////////////////////////////;;
2501
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 2502
;? --- TBD ---											  ;;
6807 dunkaist 2503
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 2504
;> --- TBD ---											  ;;
6807 dunkaist 2505
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 2506
;< --- TBD ---											  ;;
6807 dunkaist 2507
;;================================================================================================;;
2508
    xor eax, eax
2509
    ret
2510
endp
2511
 
2512
;;================================================================================================;;
2513
proc img._.new ;//////////////////////////////////////////////////////////////////////////////////;;
2514
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 2515
;? --- TBD ---											  ;;
6807 dunkaist 2516
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 2517
;> --- TBD ---											  ;;
6807 dunkaist 2518
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 2519
;< eax = 0 / pointer to image									  ;;
6807 dunkaist 2520
;;================================================================================================;;
2521
    invoke  mem.alloc, sizeof.Image
2522
    test    eax, eax
8463 IgorA 2523
    jz	@f
6807 dunkaist 2524
    push    ecx
2525
    xor ecx, ecx
2526
    mov [eax + Image.Data], ecx
2527
    mov [eax + Image.Type], ecx
2528
    mov [eax + Image.Flags], ecx
2529
    mov [eax + Image.Extended], ecx
2530
    mov [eax + Image.Previous], ecx
2531
    mov [eax + Image.Next], ecx
2532
    pop ecx
2533
@@:
2534
    ret
2535
endp
2536
 
2537
;;================================================================================================;;
2538
proc img._.delete _img ;//////////////////////////////////////////////////////////////////////////;;
2539
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 2540
;? --- TBD ---											  ;;
6807 dunkaist 2541
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 2542
;> --- TBD ---											  ;;
6807 dunkaist 2543
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 2544
;< eax = false / true										  ;;
6807 dunkaist 2545
;;================================================================================================;;
2546
    push    edx
2547
    mov edx, [_img]
2548
    cmp [edx + Image.Data], 0
8463 IgorA 2549
    je	@f
6807 dunkaist 2550
    invoke  mem.free, [edx + Image.Data]
2551
    @@: cmp [edx + Image.Extended], 0
8463 IgorA 2552
    je	@f
6807 dunkaist 2553
    invoke  mem.free, [edx + Image.Extended]
8463 IgorA 2554
    @@: invoke	mem.free, edx
6807 dunkaist 2555
    pop edx
2556
    ret
2557
endp
2558
 
2559
;;================================================================================================;;
8395 dunkaist 2560
proc img.resize_data _img, _width, _height ;//////////////////////////////////////////////////////;;
6807 dunkaist 2561
;;------------------------------------------------------------------------------------------------;;
8395 dunkaist 2562
;? Resize data block of image. New size is calculated from _width and _height params and internal ;;
2563
;? Image.Type value. All the internal fields are updated iff succeeded.                           ;;
2564
;? This function does not scale images, use img.scale if you need to.                             ;;
6807 dunkaist 2565
;;------------------------------------------------------------------------------------------------;;
8395 dunkaist 2566
;> _img = pointer to image                                                                        ;;
2567
;> _width = new width                                                                             ;;
2568
;> _height = new height                                                                           ;;
6807 dunkaist 2569
;;------------------------------------------------------------------------------------------------;;
8395 dunkaist 2570
;< eax = 0 (fail) / pointer to the new pixels data                                                ;;
6807 dunkaist 2571
;;================================================================================================;;
2572
    push    ebx esi
2573
    mov ebx, [_img]
2574
    mov eax, [_height]
2575
; our memory is limited, [_width]*[_height] must not overflow
2576
; image with width or height greater than 65535 is most likely bogus
2577
    cmp word [_width+2], 0
2578
    jnz .error
2579
    cmp word [_height+2], 0
2580
    jnz .error
2581
    imul    eax, [_width]
2582
    test    eax, eax
8463 IgorA 2583
    jz	.error
6807 dunkaist 2584
    cmp [ebx + Image.Type], Image.bpp1
8463 IgorA 2585
    jz	.bpp1
6807 dunkaist 2586
    cmp [ebx + Image.Type], Image.bpp2i
8463 IgorA 2587
    jz	.bpp2i
6807 dunkaist 2588
    cmp [ebx + Image.Type], Image.bpp4i
8463 IgorA 2589
    jz	.bpp4i
6807 dunkaist 2590
    cmp [ebx + Image.Type], Image.bpp8i
8463 IgorA 2591
    jz	.bpp8i
6807 dunkaist 2592
    cmp [ebx + Image.Type], Image.bpp8g
8463 IgorA 2593
    jz	.bpp8g
6807 dunkaist 2594
    cmp [ebx + Image.Type], Image.bpp8a
8463 IgorA 2595
    jz	.bpp8a
6807 dunkaist 2596
    cmp [ebx + Image.Type], Image.bpp24
8463 IgorA 2597
    jz	.bpp24
6807 dunkaist 2598
.bpp32:
2599
    shl eax, 2
2600
    jmp @f
2601
.bpp24:
2602
    lea eax, [eax*3]
2603
    jmp @f
2604
.bpp8i:
2605
    add eax, 256*4  ; for palette
2606
.bpp8g:
2607
    jmp @f
2608
.bpp8a:
2609
    shl eax, 1
2610
    jmp @f
2611
.bpp4i:
2612
    mov eax, [_width]
2613
    add eax, 1
2614
    shr eax, 1
2615
    imul eax, [_height]
2616
    mov ecx, eax
2617
    mov eax, [_height]
2618
    add eax, 1
2619
    shr eax, 1
2620
    imul eax, [_width]
2621
    cmp eax, ecx
2622
    jge .bpp4i.skip
2623
    mov eax, ecx
2624
 .bpp4i.skip:
2625
    add eax, 16*4    ; for palette
2626
    jmp @f
2627
.bpp2i:
2628
    mov eax, [_width]
2629
    add eax, 3
2630
    shr eax, 2
2631
    imul eax, [_height]
2632
    mov ecx, eax
2633
    mov eax, [_height]
2634
    add eax, 3
2635
    shr eax, 2
2636
    imul eax, [_width]
2637
    cmp eax, ecx
2638
    jge .bpp2i.skip
2639
    mov eax, ecx
2640
 .bpp2i.skip:
2641
    add eax, 4*4    ; for palette
2642
    jmp @f
2643
.bpp1:
2644
    mov eax, [_width]
2645
    add eax, 7
2646
    shr eax, 3
2647
    imul eax, [_height]
2648
    mov ecx, eax
2649
    mov eax, [_height]
2650
    add eax, 7
2651
    shr eax, 3
2652
    imul eax, [_width]
2653
    cmp eax, ecx
2654
    jge .bpp1.skip
2655
    mov eax, ecx
2656
 .bpp1.skip:
2657
 
2658
    add eax, 2*4    ; for palette
2659
@@:
2660
    mov esi, eax
2661
    invoke  mem.realloc, [ebx + Image.Data], eax
8463 IgorA 2662
    or	eax, eax
2663
    jz	.error
6807 dunkaist 2664
 
2665
    mov [ebx + Image.Data], eax
2666
    push    [_width]
2667
    pop [ebx + Image.Width]
2668
    push    [_height]
2669
    pop [ebx + Image.Height]
2670
    cmp [ebx + Image.Type], Image.bpp8i
2671
    jnz @f
2672
    lea esi, [eax + esi - 256*4]
2673
    mov [ebx + Image.Palette], esi
2674
    jmp .ret
2675
@@:
2676
    cmp [ebx + Image.Type], Image.bpp1
2677
    jnz @f
2678
    lea esi, [eax + esi - 2*4]
2679
    mov [ebx + Image.Palette], esi
2680
    jmp .ret
2681
@@:
2682
    cmp [ebx + Image.Type], Image.bpp2i
2683
    jnz @f
2684
    lea esi, [eax + esi - 4*4]
2685
    mov [ebx + Image.Palette], esi
2686
    jmp .ret
2687
@@:
2688
    cmp [ebx + Image.Type], Image.bpp4i
2689
    jnz .ret
2690
    lea esi, [eax + esi - 16*4]
2691
    mov [ebx + Image.Palette], esi
2692
    jmp .ret
2693
 
2694
  .error:
2695
    xor eax, eax
2696
  .ret:
2697
    pop esi ebx
2698
    ret
2699
endp
2700
 
2701
;;================================================================================================;;
2702
img._.get_scanline_len: ;/////////////////////////////////////////////////////////////////////////;;
2703
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 2704
;? Get scanline length of image in bytes							  ;;
6807 dunkaist 2705
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 2706
;> eax = width of image in pixels								  ;;
2707
;> ebx = image											  ;;
6807 dunkaist 2708
;;------------------------------------------------------------------------------------------------;;
8463 IgorA 2709
;< eax = scanline length in bytes								  ;;
6807 dunkaist 2710
;;================================================================================================;;
2711
    cmp [ebx + Image.Type], Image.bpp1
8463 IgorA 2712
    jz	.bpp1.1
6807 dunkaist 2713
    cmp [ebx + Image.Type], Image.bpp2i
8463 IgorA 2714
    jz	.bpp2i.1
6807 dunkaist 2715
    cmp [ebx + Image.Type], Image.bpp4i
8463 IgorA 2716
    jz	.bpp4i.1
6807 dunkaist 2717
    cmp [ebx + Image.Type], Image.bpp8i
8463 IgorA 2718
    jz	.bpp8.1
6807 dunkaist 2719
    cmp [ebx + Image.Type], Image.bpp8g
8463 IgorA 2720
    jz	.bpp8.1
6807 dunkaist 2721
    cmp [ebx + Image.Type], Image.bpp8a
8463 IgorA 2722
    jz	.bpp8a.1
6807 dunkaist 2723
    cmp [ebx + Image.Type], Image.bpp24
8463 IgorA 2724
    jz	.bpp24.1
6807 dunkaist 2725
    add eax, eax
2726
    cmp [ebx + Image.Type], Image.bpp32
2727
    jnz .quit
2728
    add eax, eax
2729
    jmp .quit
2730
.bpp24.1:
2731
    lea eax, [eax*3]
2732
    jmp .quit
2733
.bpp1.1:
2734
    add eax, 7
2735
    shr eax, 3
2736
    jmp .quit
2737
.bpp2i.1:
2738
    add eax, 3
2739
    shr eax, 2
2740
    jmp .quit
2741
.bpp4i.1:
2742
    add eax, 1
2743
    shr eax, 1
2744
    jmp .quit
2745
.bpp8a.1:
2746
    shl eax, 1
2747
.bpp8.1:
2748
.quit:
2749
    ret
2750
 
2751
 
2752
;;================================================================================================;;
2753
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
2754
;;================================================================================================;;
8463 IgorA 2755
;! Below is private data you should never use directly from your code				  ;;
6807 dunkaist 2756
;;================================================================================================;;
2757
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
2758
;;================================================================================================;;
2759
 
8341 dunkaist 2760
section '.data' data readable writable align 16
7735 dunkaist 2761
;include_debug_strings
7105 dunkaist 2762
 
6807 dunkaist 2763
align 4
8463 IgorA 2764
type2bpp    dd	8, 24, 32, 15, 16, 1, 9, 2, 4
6807 dunkaist 2765
img._.do_rgb.handlers:
8463 IgorA 2766
    dd	img._.do_rgb.bpp8i
2767
    dd	img._.do_rgb.bpp24
2768
    dd	img._.do_rgb.bpp32
2769
    dd	img._.do_rgb.bpp15.amd	; can be overwritten in lib_init
2770
    dd	img._.do_rgb.bpp16.amd	; can be overwritten in lib_init
2771
    dd	img._.do_rgb.bpp1
2772
    dd	img._.do_rgb.bpp8g
2773
    dd	img._.do_rgb.bpp2i
2774
    dd	img._.do_rgb.bpp4i
6807 dunkaist 2775
 
2776
img.flip.layer.handlers_horz:
8463 IgorA 2777
    dd	img.flip.layer.bpp8ig_horz
2778
    dd	img.flip.layer.bpp24_horz
2779
    dd	img.flip.layer.bpp32_horz
2780
    dd	img.flip.layer.bpp1x_horz
2781
    dd	img.flip.layer.bpp1x_horz
2782
    dd	img.flip.layer.bpp1_horz
2783
    dd	img.flip.layer.bpp8ig_horz
2784
    dd	img.flip.layer.bpp2i_horz
2785
    dd	img.flip.layer.bpp4i_horz
6807 dunkaist 2786
 
2787
;;================================================================================================;;
2788
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
2789
;;================================================================================================;;
8463 IgorA 2790
;! Exported functions section									  ;;
6807 dunkaist 2791
;;================================================================================================;;
2792
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
2793
;;================================================================================================;;
2794
 
2795
 
2796
align 4
2797
@EXPORT:
2798
 
8463 IgorA 2799
export					    \
2800
    lib_init	       , 'lib_init'	      , \
2801
    0x00050007	       , 'version'	      , \
2802
    img.is_img	       , 'img_is_img'	      , \
2803
    img.info	       , 'img_info'	      , \
6807 dunkaist 2804
    img.from_file      , 'img_from_file'      , \
8463 IgorA 2805
    img.to_file        , 'img_to_file'	      , \
6807 dunkaist 2806
    img.from_rgb       , 'img_from_rgb'       , \
8463 IgorA 2807
    img.to_rgb	       , 'img_to_rgb'	      , \
2808
    img.to_rgb2        , 'img_to_rgb2'	      , \
2809
    img.decode	       , 'img_decode'	      , \
2810
    img.encode	       , 'img_encode'	      , \
2811
    img.create	       , 'img_create'	      , \
2812
    img.destroy        , 'img_destroy'	      , \
6807 dunkaist 2813
    img.destroy.layer  , 'img_destroy_layer'  , \
8463 IgorA 2814
    img.count	       , 'img_count'	      , \
6807 dunkaist 2815
    img.lock_bits      , 'img_lock_bits'      , \
2816
    img.unlock_bits    , 'img_unlock_bits'    , \
8463 IgorA 2817
    img.flip	       , 'img_flip'	      , \
6807 dunkaist 2818
    img.flip.layer     , 'img_flip_layer'     , \
8463 IgorA 2819
    img.rotate	       , 'img_rotate'	      , \
6807 dunkaist 2820
    img.rotate.layer   , 'img_rotate_layer'   , \
8463 IgorA 2821
    img.draw	       , 'img_draw'	      , \
2822
    img.scale	       , 'img_scale'	      , \
6807 dunkaist 2823
    img.get_scaled_size, 'img_get_scaled_size', \
8463 IgorA 2824
    img.convert        , 'img_convert'	      , \
2825
    img.blend	       , 'img_blend'	      , \
8395 dunkaist 2826
    img.resize_data    , 'img_resize_data'    , \
6807 dunkaist 2827
    img.formats_table  , 'img_formats_table'
2828
 
2829
; import from deflate unpacker
2830
; is initialized only when PNG loading is requested
2831
align 16
2832
@IMPORT:
2833
 
8463 IgorA 2834
library 			  \
2835
	archiver, 'archiver.obj', \
2836
	libio	, 'libio.obj'
7105 dunkaist 2837
 
8463 IgorA 2838
import	archiver, \
2839
	deflate_unpack2, 'deflate_unpack2',\
2840
	deflateInit2,	 'deflateInit2',\
2841
	deflateReset,	 'deflateReset',\
2842
	deflate,	 'deflate',\
2843
	deflateEnd,	 'deflateEnd',\
2844
	calc_crc32,	 'calc_crc32'
6807 dunkaist 2845
 
8463 IgorA 2846
import libio			, \
2847
	file.size , 'file_size' , \
2848
	file.open , 'file_open' , \
2849
	file.read , 'file_read' , \
2850
	file.close, 'file_close'
7105 dunkaist 2851
 
6807 dunkaist 2852
align 4
2853
; mutex for unpacker loading
8463 IgorA 2854
deflate_loader_mutex	dd  0
6807 dunkaist 2855
 
2856
; default palette for GIF - b&w
2857
gif_default_palette:
8463 IgorA 2858
    db	0, 0, 0
2859
    db	0xFF, 0xFF, 0xFF
6807 dunkaist 2860
 
2861
; uninitialized data - global constant tables
2862
mem.alloc   dd ?
2863
mem.free    dd ?
2864
mem.realloc dd ?
2865
dll.load    dd ?
2866
 
2867
; data for YCbCr -> RGB translation
8463 IgorA 2868
color_table_1	    rd	256
2869
color_table_2	    rd	256
2870
color_table_3	    rd	256
2871
color_table_4	    rd	256