	Tramage monochrome: filtre de Bayer
	***********************************#


	Certains d'entre vous m'ont demand par courrier une mthode pour
afficher une image couleur sur un cran monochrome. Je vous prsente ici
l'une d'entre elles qui a l'avantage d'tre extrmement simple 
comprendre et  programmer: le filtre de Bayer.
	Les rsultats qu'elle donne sont de qualit moyenne, par contre
elle offre des avantages de compacit et de rapidit qui la rendent bien
utile.

LA LUMINOSIT D'UN POINT
------------------------

	Le premier travail consiste  transformer une couleur en
'luminosit', ou plus simplement en niveau de gris. On applique pour ceci
la formule (arrondie aux diximes): L = 0.6V + 0.3R + 0.1B dans laquelle
R,V,B sont les composantes rouge/vert/bleu de la couleur.
	En supposant que RVB sont des octets (0-255), voici les lignes
utiles au calcul de L:
	a1=pointe sur le triplet RVB

	moveq #0,d0
	move.b (a1)+,d0  ; rouge
	moveq #0,d1
	move.b (a1)+,d1  ; vert
	add d1,d1
	add d0,d1
	move d1,d0
	add d0,d0
	add d0,d1
	moveq #0,d0
	move.b (a1)+,d0  ; bleu
	add d0,d1
	divs #40,d1

	On obtient ainsi dans D1.B une valeur de luminosit allant de 0
(=noir)  63 (=blanc). Si les triplets RVB sont des valeurs allant de 0 
63 (comme dans la palette d'une animation FLI par exemple), on remplacera
le 40 de la division par 10: divs #10,d1.
        Pour finir, si RVB sont des MOTS de 0  1000, c'est  dire au
format standard du VDI, on utilisera:

	move (a1)+,d0   ; rouge
	moveq #0,d1
	move (a1)+,d1   ; vert
	add d1,d1
	add d0,d1
	move d1,d0
	add d0,d0
	add d0,d1
	add (a1)+,d1	; +bleu
	divs #157,d1

	Ce qui donne encore dans D1.b une valeur allant de 0  63. Vous
remarquerez que des additions ont t prfres aux multiplications pour
des questions de vitesse.

LE FILTRE DE BAYER
------------------

	Une fois votre image convertie en niveaux de gris, de 0  63 pour
chaque pixel, on peut passer  l'tape suivante: l'application du filtre.
Pour cela, on utilise une matrice de dimensions 8x8 qu'on applique sur
l'image en la rptant en largeur et en hauteur tous les huits points. Si
la luminosit d'un pixel est suprieure  la valeur de la matrice, il
apparait blanc, si sa luminosit est infrieure, il apparait noir. Voici
la matrice:

matrice:
 dc.b 0,32,8,40,2,34,10,42
 dc.b 48,16,56,24,50,18,58,26
 dc.b 12,44,4,36,14,46,6,38
 dc.b 60,28,52,20,62,30,54,22
 dc.b 3,35,11,43,1,33,9,41
 dc.b 51,19,59,27,49,17,57,25
 dc.b 15,47,7,39,13,45,5,37
 dc.b 63,31,55,23,61,29,53,21

 	On remarque que si notre image est blanche (luminosit uniforme
63), tous les points apparaissent blancs (car suprieurs  la matrice).
Inversement, avec une image noire, ils apparaissent noirs (car infrieurs
 la matrice). Pour les niveaux intermdiaires, prenons une image grise de
luminosit 15, seuls 15 points sur 64 seront blancs (d'ou l'effet de gris
fonc qu'on obtiendra avec cette trame).

LE PROGRAMME LUI-MEME
---------------------

	Ce programme tourne sur 680x0 et affiche une image sur un cran
monochrome. On suppose que:
	- l'image est dj en niveaux de gris (valeurs d'octets de 0  63)
	- son adresse est range dans 'image'
	- l'adresse de l'cran est dans 'physbase'


	Voici l'initialisation, on calcule dans D3.W le nombre de pixels 
sauter  l'cran entre la fin d'une ligne et le dbut de la suivante,
'lsr' divise ce nombre de pixels par 8 puisque sur l'cran monochrome, 8
pixels tiennent dans un octet. Le saut immdiat vers 'boucle' permet de
traiter le cas (improbable) ou la hauteur D5 serait nulle (donc rien 
faire!).

	move larg_ecran,d3
	move larg_image,d4
	sub d4,d3
	lsr #3,d3
	move haut_image,d5
	lea matrice,a3
	move.l physbase,a1
	move.l image,a0
	bra boucle

	Ensuite, la premire partie permet de traiter les paquets entiers
de 8 pixels: ceci impose le saut direct vers 'fin8' qui par dcrmentation
verifie si on a au moins 8 pixels de large. La valeur A3 conserve
l'adresse du dbut de la ligne courante de la matrice qu'on rutilise pour
chaque groupe de 8 pixels. La comparaison de la matrice avec l'image (A2
et A0) donne lieu  la mise  0 d'un bit dans D0 si le point doit tre
blanc.

ligne:
	move d4,d2
	bra.s fin8
pixels_8:
	moveq #7,d1
	move.l a3,a2
	moveq #-1,d0
.loop:
	cmp.b (a2)+,(a0)+
	bmi.s .noir
	bclr d1,d0
.blanc:
	dbf d1,.loop
	move.b (a1)+
fin8:
	subq #8,d2
	bpl.s pixels_8

	Ds que les groupes entiers de 8 pixels sur une mme ligne sont
puiss, on s'occupe du reste: saut vers 'fin_ligne' si il ne reste rien,
ou deuxime partie si il reste de 1  7 pixels. L'octet D0 est mis  $FF
(points noirs), la boucle n'en modifie qu'une partie (de 1  7) et la
rotation 'rol.b d1,d0' permet d'amener les points modifis  gauche et
donc de complter par des noirs  droite.

	addq #7,d2
	bmi.s fin_ligne
	moveq #-1,d0
	moveq #7,d1
	sub d2,d1
	move.l a3,a2
.loop2:
	cmp.b (a2)+,(a0)+
	bmi.s .noir2
	bclr d2,d0
.noir2:
	dbf d2,.loop2
	rol.b d1,d0
	move.b d0,(a1)+

	Enfin,  chaque fin de ligne d'cran, le pointeur de matrice A3
est augment de 8 (passage  la ligne suivante). Si on a atteint la fin de
la matrice, au bout de 8 lignes d'image, ce pointeur revient au dbut. Le
pointeur d'cran A1 est lui aussi corrig pour passer  la ligne physique
suivante.

fin_ligne:
	addq.l #8,a3
	cmp.l #matrice+64,a3
	bne.s .pas_8
	sub #64,a3
.pas_8:
	add d3,a1
boucle:
	dbf d5,ligne

POUR FINIR
----------

	Ce filtre, vous le verrez  l'utilisation, laisse apparatre une
trame assez marque sous forme de lignes verticales ou horizontales qui
peuvent nuire  la clart de l'image. On peut dj dcaler la matrice
d'une ligne vers le bas une fois sur deux en largeur: ainsi on rompt la
rgularit de la trame et l'oeil est moins drang par ces lignes
parasites (c'est ce qui est utilis dans MP_STE pour l'affichage
d'animations en ST Haute).
	Cette mthode sert de base  d'autres algorithmes de dithering.
Pour rduire une image  8 couleurs par exemple: on applique Bayer aux
trois plans R, V, B sparment et on obtient ainsi pour chaque point 3
valeurs: Rouge=1 ou 0, Vert=1 ou 0, Bleu=1 ou 0. Ces diffrentes
possibilits recombines forment 8 couleurs diffrentes.

	Tout  fait  ct du sujet, j'ai reu un mulateur PC 286
entirement SOFT! Il tourne en 640x480x16 (mais n'mule que le CGA) et a,
avec la CaTTamaran et de la TT_Ram, un facteur Norton de 2.4 sur TT. Par
comparaison, l'mulateur hard Supercharger (NEC V30  8MHz) obtient un
facteur Norton de 4.2.

	Vos ractions sont les bienvenues sur internet,

	Guillaume Tello
	gtello@wanadoo.fr