	Images TGA compresses (2)
	**************************

	La dernire fois, nous vimes comment lire une image TGA, qu'elle
soit compresse ou non. Cette fois-ci, nous allons la crer, en-tete et
pixels compresss, la totale.

Hardi!
------
	La compression, dans des cas limites, peut conduire  un
fichier plus gros que l'original. Les utilitaires comme ZIP ou LZH vous
signalent la chose en indiquant que le fichier est "stored", c'est a dire
simplement rang dans l'archive dans son tat original puisque la
compression n'amne rien de plus.
	Ici aussi nous allons traiter ce cas: si la compression est
efficace on sort un TGA 10 compress, si elle est inefficace, on sort un
TGA 2 non compress.

La routine
----------

	Comme la dernire fois, elle s'adapte aux modes 16 et 24 bits.

En entre:
A0: pointe sur les pixels BVR ou vvvbbbbb xrrrrrvv
A1: pointe sur le buffer o construire le TGA
D0: largeur
D1: hauteur
D2: nombre de bits par pixel (16 ou 24)

En interne:
D4: compte les octets restants dans la destination
D5: compte les pixels restant dans la source
A3: conserve A0 original
A4: conserve A1 original
D6: conserve le nombre de pixels

En sortie:
A1: adresse du debut du fichier TGA
D1: taille du fichier TGA
D0: type (0=non compresse en TGA2; -1=compress en TGA 10)


sauve_tga:
	move.l a0,a3
	move.l a1,a4
	move.l #$00000a00,(a1)+	; prepare un header de TGA 10
	clr.l (a1)+
	clr.l (a1)+
	ror #8,d0
	move d0,(a1)+
	ror #8,d1
	move d1,(a1)+
	move.b d2,(a1)+
	move.b #32,(a1)+
	ror #8,d1
	ror #8,d0
	muls d0,d1	; nombre de pixels de l'image
	move.l d1,d4	; dans d4
	move.l d1,d6
	cmp.b #24,d2
	beq _tga10_24			; 24 bits!

	; ici on compresse du 16 bits

_tga10_16:
	move.l d4,d5	; compte les pixels lus dans source
	add.l d4,d4	; compte les octets utilisables dans dest
	subq.l #1,d4
	move (a0)+,d0	; permier pixel
	subq.l #1,d5	; lu!
.fin_egal:
	move.l a1,a2
	sf (a1)+	; nouveau code N=0
	subq.l #1,d4
	bmi.s .comp_inefficace
.autre:
	move d0,(a1)+	; qu'on range
	subq.l #2,d4
	bmi.s .comp_inefficace
	subq.l #1,d5
	bmi.s .fin
	move (a0)+,d1	; pixel supplmentaire
	cmp d1,d0
	beq.s .egal
	move d1,d0
	addq.b #1,(a2)
	bpl.s .autre	; si >0, moins de 128
	subq.b #1,(a2)	; retour a $00 + 127
	bra.s .fin_egal
.egal:
	tst.b (a2)
	beq.s .good
	subq.l #2,a1
	subq.b #1,(a2)
	move.l a1,a2
	sf (a1)+
	move d1,(a1)+
	subq.l #1,d4	; #1 car A1-2 puis +1 +2
	bmi.s .comp_inefficace
.good:
	move.b #$81,(a2)
.encore:
	subq.l #1,d5
	bmi.s .fin
	move (a0)+,d0
	cmp d1,d0
	bne.s .fin_egal
	addq.b #1,(a2)
	bmi.s .encore	; si toujours<0, moins de 128
	st (a2)		; retour a $80 + 127
	bra.s .fin_egal	; le 129eme ne commence pas forcement un bloc repeat
.comp_inefficace:
	move.l a4,a1	; debut fichier TGA
	move.b #2,2(a4)	; change TGA 10 en TGA 2
	lea 18(a4),a4	; saute le header
.copy:
	move (a3)+,(a4)+; un pixel
	subq.l #1,d6
	bne.s .copy
	sub.l a1,a4	; taille fichier TGA 2
	move.l a4,d1
	moveq #0,d0	; pas compress
	rts
.fin:
	move.l a1,d1
	sub.l a4,d1	; taille fichier TGA 10
	move.l a4,a1	; debut fichier
	moveq #-1,d0	; compress
	rts

	; ici on compresse du TGA 24 bits

_tga10_24:
	move.l d4,d5
	add.l d4,d4
	add.l d5,d4
	subq.l #1,d4
	move.l #$FFFFFF00,d2
	move.l (a0),d0
	and.l d2,d0
	addq.l #3,a0
	subq.l #1,d5
.fin_egal:
	move.l a1,a2
	sf (a1)+
	subq.l #1,d4
	bmi.s .comp_inefficace
.autre:
	move.l d0,(a1)
	addq.l #3,a1
	subq.l #3,d4
	bmi.s .comp_inefficace
	subq.l #1,d5
	bmi.s .fin
	move.l (a0),d1
	addq.l #3,a0
	and.l d2,d1
	cmp.l d1,d0
	beq.s .egal
	move.l d1,d0
	addq.b #1,(a2)
	bpl.s .autre
	subq.b #1,(a2)
	bra.s .fin_egal
.egal:
	tst.b (a2)
	beq.s .good
	subq.l #3,a1
	subq.b #1,(a2)
	move.l a1,a2
	sf (a1)+
	move.l d1,(a1)
	addq.l #3,a1
	subq.l #1,d4
	bmi.s .comp_inefficace
.good:
	move.b #$81,(a2)
.encore:
	subq.l #1,d5
	bmi.s .fin
	move.l (a0),d0
	addq.l #3,a0
	and.l d2,d0
	cmp.l d1,d0
	bne.s .fin_egal
	addq.b #1,(a2)
	bmi.s .encore
	st (a2)
	bra.s .fin_egal
.comp_inefficace:
	move.l a4,a1		; debut fichier TGA
	move.b #2,2(a4)		; change TGA 10 en TGA 2
	lea 18(a4),a4		; saute le header
.copy:
	move.b (a3)+,(a4)+
	move.b (a3)+,(a4)+
	move.b (a3)+,(a4)+	; un pixel
	subq.l #1,d6
	bne.s .copy
	sub.l a1,a4		; taille fichier TGA 2
	move.l a4,d1
	moveq #0,d0		; pas compress
	rts
.fin:
	move.l a1,d1
	sub.l a4,d1		; taille fichier TGA 10
	move.l a4,a1		; debut fichier
	moveq #-1,d0		; compress
	rts

Ben oui, mais c'est pas top
---------------------------
	En effet, cette fois ci, un 68030 est plus indiqu car je n'ai pas
tenu compte de la parit des pointeurs. A vous de changer les MOVE.W et
les MOVE.L en plusieurs MOVE.B si vous devez utiliser un 68000.
	C'est  vous d'allouer le bloc contenant le TGA de sortie, il doit
faire un minimum de:
	18 + (largeur * hauteur * bits par pixel ) / 8 pour contenir un
TGA 2 non compress. Par exemple pour du 320x240 en 16 bits, il faut:
	18 + (320 * 240 * 16) / 8 = 153618 octets.
	Ma routine suppose galement que le format des pixels dans le
bloc source correspond dj au codage TGA, c'est  dire BVR pour le 24
bits et vvvbbbbb xrrrrrvv pour le 16 bits.

Quelques commentaires
---------------------
	La compression TGA 10 ne tient aucun compte du passage d'une ligne
 l'autre. De ce fait, un bloc peut trs bien dpasser la fin de ligne et
s'tendre  la ligne suivante. Si ceci est trs pratique pour le
compresseur, il en va autrement pour le programme qui affiche. Oui car,
par souci de rapidit, il est intressant de dcompresser tout en
affichant. Mais l, il faut redoubler de tests car la fin d'une ligne
d'cran peut survenir au milieu d'un bloc.

	Il existe aussi d'autres compressions plus pousses supportes par
le TGA: les types 32 et 33 vont jusqu'au Huffman. Tout ceci tant bien
loin de mes comptences, je m'arrete au RLE.

	Guillaume Tello
	gtello@wanadoo.fr