Accueil > Développer sur Mac OS X > Les Bases du Blitting Transparent - Partie 1

Les Bases du Blitting Transparent - Partie 1

Par Michael J. Norton le 17/08/2004

Traduit par Olivier, le 02/09/2004

Nous voici dans une nouvelle session pour discuter des fondements de la programmation d’animations graphiques comme sur la Game Boy Advance SP.
Précédemment, nous avons discuté du buffer vidéo.
Dans cet article, nous allons étudier la copie de sprites vers le buffer vidéo.
Nous allons voir comment utiliser la transparence des pixels, les techniques utilisées pour le blitting.

Leçon 1 : Progresser à Travers le Marécage Hexadécimal

Même durant la plus paisible des traversées à la voile, il est possible de rencontrer un peu de turbulences…
Et bien aujourd’hui, il n’en est pas autrement.
Nous avons navigué tranquillement à travers les sujets concernant des éléments du graphisme sans avoir à examiner les mathématiques utilisées.
Aujourd’hui, on fait une exception.
J’ai besoin de présenter quelques bases mathématiques afin de discuter de pixels et de couleurs.

Les ordinateurs utilisent un système numérique spécial qui peut nous sembler un peu étranger au premier abord.
Avec un peu de temps et d’expérience, vous vous y habituerez.
Quand on apprend à compter, nous sommes habitués à commencer à 1 en allant à 10.
C’est ce qu’on appelle le système décimal, à base 10.
Quand un ordinateur compte, il va jusqu’à 16.
Il s’agit d’un système hexadécimal, à base 16.
Pour rendre les choses un peu plus intéressantes, un ordinateur utilise des lettres après 9.

Comparons le système en base 10 et le système en base 16.


0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 -- décompte en base 10
0 1 2 3 4 5 6 7 8 9 A  B  C  D  E  F  -- décompte en base 16

Mais pourquoi les ordinateurs utilisent-ils un système à base 16 ?
Tout est lié aux composants de l’ordinateur.
Un nombre en base 16 peut être représenté sur 4 bits.
Qu’est-ce-qu’un bit ?
Vous voulez vraiment en avoir pour votre argent, c’est ça ?

Un bit est la base du vrai langage utilisé par l’ordinateur.
Un bit peut avoir deux valeurs, 0 et 1.
Un bit est simplement un conteneur pour un 0 ou un 1.
Quatre bits peuvent contenir quatre zéros et uns.
Par exemple, 0000 est la représentation sur quatre bits du nombre 0.
Le nombre 1 en représentation sur quatre bits est 0001.
Un ordinateur ne contenant qu’un seul bit est complètement inutile.
Les premiers ordinateurs étaient basés sur 8 bits.
Cela signifie que 4 bits étaient utilisées pour représenter des nombres de 8 bits.

Pour représenter le nombre zéro sur une notation 8 bits, nous écririons 0000 0000.
Pour écrire le nombre 1 en utilisant la notation 8 bits, nous écririons 0000 0001.
Le plus petit nombre que l’on puisse représenter sur 4 bits est 0 et le plus grand nombre est 15.
Quatre bits, aux tous premiers jours de l’informatique, s’appelait un demi-octet (nibble).
Un ensemble de deux nibbles, 4 bits + 4bits = 8 bits, est appelé un octet.
Voyons comment les bits sont utilisés pour représenter les nombres.


4-bits	Décimal	Hexadécimal
0000	0	0
0001	1	1
0010	2	2
0011	3	3
0100	4	4
0101	5	5
0110	6	6
0111	7	7
1000	8	8
1001	9	9
1010	10	A
1011	11	B
1100	12	C
1101	13	D
1110	14	E
1111	15	F

La table montre l’une à côté de l’autre la valeur binaire avec ses équivalents en décimal et hexadécimal.
Avant que vous ne deveniez fou et que vous vous jetiez par la fenêtre, laissez-moi faire un point.
Vous n’avez pas besoin de comprendre clairement l’hexadécimal pour le moment.
Sachez juste qu’il existe et POURQUOI il existe.
C’est POUR CELA que les programmeurs utilisent des nombres hexadécimaux.
Regardez le tableau ci-dessus.
Un nombre hexadécimal peut représenter 4 bits.
Prenez par exemple la valeur 4 bits 1111.
Je sais par ce tableau que sa valeur hexadécimal est F.
C’est également plus simple à lire pour nous.
Avec un peu d’exercice, vous vous y habituerez.

Ceci conclut notre petite leçon de mathématique.
Amusons-nous un peu avec un peu de graphiques de jeu vidéo.

Leçon 2 : La Transparence des Pixels

Nous allons reprendre là où nous en étions restés dans l’article précédent : Concepts de Base de l’Utilisation du Buffer Vidéo.
La Figure 1 montre notre dernier exemple de programme.


Figure 1. Sprite copié sans transparence.

Nous avons directement copié notre sprite vers le buffer vidéo.
Le sprite a un arrière-plan fuchsia un peu funky qui recouvre l’image de fond de notre jeu.
C’est pas mal, hein ?
Mais nous pouvons arranger cela.
Ce que nous devons faire, c’est dessiner tous les pixels du monstre sauteur, mais pas les pixels fuchsia.
Ces pixels sont nos pixels de transparence, ce qui signifie que nous ne les afficherons pas.

Identifier les Pixels de Transparence

La première tâche est de déterminer les valeurs des pixels de la couleur fuchsia.
En partant du code de la leçon précédente, nous connaissons la position du sprite dans le buffer.
Le monstre sauteur est situé dans le buffer à la position (rectangle) 265 737 328 800.
La bibliothèque d’image de Tk nous permettra de déterminer la valeur du pixel en utilisant des outils de photo.
Le code ressemble à ceci :

# retrieve the transparency pixel value
set transparency_pixel [$sprites get 265 737]
puts $transparency_pixel
% 198 0 107

La procédure retourne une liste de trois nombres comme montré en Figure 2.
Ce sont des valeurs RGB (RVB), pour Red (Rouge), Green (Vert) et Blue (Bleu), les couleurs primaires.
Ces valeurs indiquent l’intensité que doit avoir le rouge, le vert et le bleu pour créer une couleur de pixel spécifique.
C’est un peu comme quand on mélange les peintures à l’eau dans les cours de peinture.
La différence est que nous utilisons un ordinateur qui les mélange pour nous.
Nous avons besoin d’un rouge d’intensité 198, un vert d’intensité 0, et un bleu d’intensité 107.
Ces trois valeurs RVB définissent notre fuchsia.
Nous avons atteint notre but. Nous avons les valeurs de notre couleur de transparence.


Figure 2. Valeurs des pixels des transparence fuchsia.

Conversion en Hexadécimal

Je vous avais prévenus que cela allait venir.
Quand on se met à manipuler la mémoire de l’ordinateur, il faut parler l’hexadécimal.
Le contenu de notre buffer vidéo est stocké sous forme de valeurs hexadécimales.
Si nous devons rechercher des valeurs RVB dans un buffer, alors nous devons utiliser les valeurs RVB au format hexadécimal.
Nous pouvons convertir nos valeurs RVB actuelles au format hexadécimal en utilisant les lignes de code suivantes :

# convert to hexadecimal
set R_value [format "%02x" [lindex $transparency_pixel 0]]
set G_value [format "%02x" [lindex $transparency_pixel 1]]
set B_value [format "%02x" [lindex $transparency_pixel 2]]

J’utilise les outils fournis avec le langage de script Tcl pour convertir les valeurs en hexadécimal.
Il n’y a donc pas de calculs à faire.

set transparency_pixel {198 0 107}
198 0 107
() 2 % # convert to hexadecimal
() 3 % set R_value \
[format "%02x" [lindex $transparency_pixel 0]]
c6
() 4 % set G_value \
[format "%02x" [lindex $transparency_pixel 1]]
00
() 5 % set B_value \
[format "%02x" [lindex $transparency_pixel 2]]
6b

Ces valeurs correspondent aux valeurs de la Figure 2.
Maintenant nous pouvons définir la valeur du pixel de transparence que nous allons rechercher dans le buffer du sprite.

# create the transparency value string
set RGB_value "#$R_value$G_value$B_value"

L’exécution du code ci-dessus dans Wish shell donne :

() 6 % # create the transparency value string
() 7 % set RGB_value "#$R_value$G_value$B_value"
#c6006b

La valeur #c6006b est ce que nous devons rechercher dans le buffer du sprite.

Création d’une Procédure Hexadécimal pour notre Outil Graphique

Ne serait-il pas pratique si nous avions une procédure de bibliothèque que nous pourrions appeler comme par magie pour qu’elle effectue pour nous la conversion RVB décimale en hexadécimale ?
Hé bien le langage Tcl nous permet d’ajouter les outils dont nous avons besoin à notre code.
Nous utiliserons la commande proc pour écrire notre procédure.

proc RGB_convert_decimal_hexadeimal { transparency_pixel } {
    # convert to hexadecimal
    set R_value \
        [format "%02x" [lindex $transparency_pixel 0]]
        set G_value \
        [format "%02x" [lindex $transparency_pixel 1]]
        set B_value \
        [format "%02x" [lindex $transparency_pixel 2]]
        # create the transparency value string

    set RGB_value "#$R_value$G_value$B_value"return $RGB_value
}

Encore une fois, essayons notre exemple précédent pour convertir les valeurs RVB de notre pixel de transparence de système décimal au système hexadécimal.

() 5 % RGB_convert_decimal_hexadeimal $transparency_pixel
#c6006b
() 6 %

La commande Tcl proc nous permet d’ajouter nos propres procédure de bibliothèque.

Je n’ai rien ajouté à l’intérieur du corps de la procédure.
Mais regardez ce que nous pouvons faire maintenant.

proc RGB_convert_decimal_hexadeimal { transparency_pixel } {
    # convert to hexadecimal
        :
        return $RGB_value
}

Nous commençons par la commande Tcl proc pour écrire une procédure.
La commande proc est suivie du nom de la procédure.
Le nom de la procédure est ce qui nous permet d’appeler l’opération depuis un script.
Ensuite, entre parenthèses, nous avons ce que l’on appelle un argument.
Un argument est une variable du script que nous voulons utiliser à l’intérieur de la procédure.
Cela s’appelle passer un argument.
Dans ce cas, nous passons ˆ la valeur RVB transparency_pixel.
Quand nous convertissons transparency_pixel d’une valeur décimale à hexadécimale nous voulons retourner la nouvelle valeur vers le script appelant.
Nous utilisons la commande Tcl return.
Ceci renvoie, la nouvelle valeur hexadécimale que nous voulions.

Leçon 3 : Rechercher les Pixels de Sprite Brut

Maintenant, une partie du travail est faite pour nous.
Nous avons également besoin d’implémenter une procédure un peu plus compliquée que celle-ci.
La bibliothèque d’image Tk ne fournit pas de procédure pour effectuer des copies de pixel de transparence.
Ne vous inquiétez pas, remontez les manches et commençons le travail.
Nous allons faire la nôtre.

La première tâche est d’avoir accès aux données brutes des pixels de notre sprite.
La bibliothèque d’image Tk, heureusement, nous apporte cette procédure.
Sinon, nous n’aurions plus qu’à fermer boutique et rentrer à la maison.
La bibliothèque d’image Tk qui nous fait cela est data.

# get image data
set raw_monster_data [$sprites data -from 265 737 328 800]

Tapez ce script dans la console Wish Shell.
Vous verrez certains concepts intéressants que nous avons vus jusque-là.
Souvenez-vous, vous aurez besoin d’avoir le répertoire /game_dev dans votre répertoire.
Et vous avez besoin du fichier graphique dans ce répertoire.

Le script :

# load the art file
set filename "/game_dev/game_art.gif"
set sprites [image create photo -file $filename]

# load the raw pixel data into raw_monster_data
set raw_monster_data [$sprites data -from 265 737 328 800] 

# raw_monster 63 lines long
llength $raw_monster_data

A l’exécution du script, vous verrez des valeurs hexadécimal familières, comme celles que nous avons vues auparavant.
J’ai ajouté dans la commande Tcl llength pour vous montrer que les données du monstre représentent 63 lignes de valeurs hexadécimales.
Vous vous demandez pourquoi ?
Faisons un peu de calcul.

Le pixel du haut du monstre est à la position y1=737.
Le pixel du bas est à la position y2=800.
Soustrayons,

800 - 737 = 63 (hauteur)

() 9 % llength $raw_monster_data
63

Coincidence ?
Pas vraiment.
Le sprite de notre monstre fait 63 pixels de hauteur.
Maintenant, considérons ces 63 lignes d’information de pixel.
Chaque ligne d’information de pixel contient les données pour 63 pixels.

Les lignes de pixels traversant le monstre sont à la position x1=265.
Le pixel le plus à droite est à la position x2=328.
Soustrayons,

328 - 265 = 63 (large)

Pour chaque ligne nous allons effectuer un scan.
Il y a 63 lignes d’information de pixels.
Chaque ligne de scan contient les données pour 63 pixels.


Figure 3. 63 pixels par lignes.

Définir les Contours du Rectangle

Vous vous souvenez que les opérations de copie de sprites utilisent des contours rectangulaires pour s’effectuer.
Nous aurons besoin de définir deux zones rectangulaires.
Le premier rectangle est la source.
Le rectangle source est la zone correspondant à notre monstre.
Nous savons déjà que cette zone a pour valeurs 265 737 328 800.
Le coin haut gauche est x1=265, y1=737 et le coin bas droite est x2=238, y2=800.
Nous savons que le sprite du monstre fait 63 par 63 pixels.
Alors, nous pouvons définir le rectangle avec son coin haut gauche à x1=265, y1=737 et le sprite fait 63 par 63.

De même, lorsque nous copions le sprite, nous avons besoin de connaître le rectangle de destination.
C’est là où nous allons copier notre sprite.
Ce que nous avons besoin de savoir, c’est que le rectangle de destination est de la même taille que le rectangle source du sprite.
Le rectangle de destination fait 63 pixels de haut par 63 pixels de large.
Vous me suivez ?
Le rectangle source du sprite et le rectangle de destination font tous les deux 63 pixels de haut et 63 pixels de large.

Notre blitter aura besoin de connaître la position du coin haut gauche du sprite de source, src_x et src_y.
Nous aurons besoin de connaître les hauteur et largeur du sprite.
Et nous aurons besoin de connaître la position du coin haut gauche du rectangle de destination.
La Figure 4 montre comment nous allons définir les contours rectangulaires des opérations de notre blitter.
Le rectangle source, src, est la position du sprite de notre monstre dans le buffer.
Le rectangle destination, dst, est là où nous allons copier le sprite de notre monstre.


Figure 4. Définition des contours rectangulaires.

Amusons-nous avec un exemple pour avoir une idée de ce que nous faisons.
Souvenez-vous que le rectangle de notre sprite est défini comme 265 737 328 800.

set src_x 265
set src_y 737
set width 63
set height 63

# calculate source bounding rectangle
set src_x2 [expr $src_x + $width]
set src_y2 [expr $src_y + $height]

Et en copiant/collant le code précédent dans la console Wish Shell, nous obtenons :

() 22 % # calculate source bounding rectangle
() 23 % set src_x2 [expr $src_x + $width]
328
() 24 % set src_y2 [expr $src_y + $height]
800

D’après l’exemple de notre Figure 4, nous avons src_x=265, src_y=737, src_x2=328, et src_y2=800.
Ce sont les contours rectangulaire du sprite de notre joyeux monstre sauteur.

Pour le rectangle de destination, nous allons copier l’opération de blit de l’article précédent.
L’exemple de cet article n’utilisait pas de pixel de transparence parce que la bibliothèque d’image Tk ne propose pas cette méthode de copie.
Nous allons copier vers le centre du buffer vidéo.
Le coin haut gauche du rectangle de destination est dst_x=320 et dst_y=303.

set dst_x 320
set dst_y 303
set width 63
set height 63

# calculate destination bounding rectangle
set dst_x2 [expr $dst_x + $width]
set dst_y2 [expr $dst_y + $height]

En exécutant ce code dans la console Wish Shell nous obtenons :

() 29 % # calculate destination bounding rectangle
() 30 % set dst_x2 [expr $dst_x + $width]
383
() 31 % set dst_y2 [expr $dst_y + $height]
366

Maître, ma Tête est Pleine !!

Une petite pause ?
Une overdose d’informations ?
Nous avons vu beaucoup de choses depuis le système hexadécimal jusqu’au système de coordonnées rectangulaires du sprite.
Vous pouvez vous féliciter.
Il y avait beaucoup de choses.
La prochaine fois, nous utiliserons tout cela et nous manipulerons les valeurs des pixels bruts.
Enfin, nous pourrons voir notre petit copain le monstre apparaître comme par magie avec un joli fond et sans ces horribles pixels fuchsia.

Textes originaux en anglais sur O’Reilly : Basics of Transparent Blitting, Part 1 par Michael J. Norton

opoppon Développer sur Mac OS X , ,

  1. Pas encore de commentaire
  1. Pas encore de trackbacks
S'abonner aux commentaires de cet article