Chapitre 3

Écrit le 02/07/2003 par Bob le Pointu
Dernière mise à jour : 06/02/2006

Les couleurs avec TinyPTC

Bonsoir à tous. Vous savez comment créer une fenêtre vide, il est temps de la colorer un peu ;>

TinyPTC utilise des couleurs codées sur 24 bits (True color), 8 bits pour chaque composante, rouge, verte et bleue.

11111111 }-> 8 bits pour la composante rouge
10101111 }-> 8 bits pour la composante verte
01100101 }-> 8 bits pour la composante bleue

La couleur d'un pixel peut donc prendre 224 soit 16 777 216 (de tête ;>) valeurs différentes. Vous devrez donner à chaque élément de votre buffer une valeur de cet ordre afin de lui faire correspondre la couleur désirée.

Exemple, vous désirez afficher un pixel de couleur rouge pur. Vous allez donc donner au premier octet la valeur maximale qu'il peut prendre, c'est à dire 255, ou 0xFF en hexadécimal, et laisser les autres à 0. Le nombre que vous devez obtenir est le suivant :

0xFF0000 en hexadécimal.
111111110000000000000000 en binaire.
16 711 680 en décimal.

C'est pourquoi je recommande d'utiliser la notation hexadécimale, qui est la plus adaptée à ce genre de programmation. Il est très simple de comprendre que 0xFF0000 représente la couleur rouge absolue alors qu'il est quasiment impossible de le comprendre avec 16 711 680.

Exemple, vous désirez afficher un pixel rouge, suivi d'un vert et enfin d'un bleu, alors codez :

buffer[0] = 0xFF0000;
buffer[1] = 0x0000FF;
buffer[2] = 0x00FF00;

Les trois premiers éléments de votre buffer sont donc associés à ces couleurs, il ne vous reste plus qu'à rafraîchir la fenêtre en utilisant ptc_update(buffer).

Les opérateurs binaires

Pour pouvoir séparer les couleurs, il est très pratique d'utiliser les opérateurs binaires. C'est pourquoi je vais rapidement vous expliquer leur fonctionnement par l'exemple.
& : [et] binaire :

Binaire Héxadécimal Décimal
00101100 0x2C 44
&
11000110 0xC6 198
=
00000100 4 4

Les deux bits comparés doivent être à 1 pour donner 1.
| : [ou] binaire :

Binaire Héxadécimal Décimal
00101100 0x2C 44
|
11000110 0xC6 198
=
11101110 0xEE 238

Au moins un des deux bits comparés doit être à 1 pour donner 1.
^ : [ou exclusif (xor)] binaire :

Binaire Héxadécimal Décimal
00101100 0x2C 44
^
11000110 0xC6 198
=
11001010 0xCA 202

Seulement un des deux bits comparés doit être à 1 pour donner 1.

A présent, passons aux opérateurs de décalage, qui servent, comme leur nom l'indique, à décaler des bits.

>> : décalage vers la droite. Ainsi, 00000000 11011101 >> 3 deviendra 00000000 00011011 . Les bits sont en effet décalés de 3 positions vers la droite.

<< : décalage vers la gauche. Ainsi, 00000000 11011101 << 4 deviendra 00001101 11010000 . Les bits sont en effet décalés de 4 positions vers la gauche.

Séparer les composantes

Imaginons la situation suivante, je possède un pixel de couleur 0xFCA32D, et je voudrais pouvoir modifier la composante verte, ou tout simplement savoir quelles en sont les proportions. Il faut se représenter le nombre en binaire. 0xFCA32D donne :

11111100 10100011 00101101

Puisqu'on souhaite récupérer la composante verte, il nous faut récupérer seulement le deuxième octet, il nous faut obtenir ce nombre :

10100011

Grâce aux opérateurs binaires, ce travail est très aisé. Il suffit de faire l'opération 0xFCA32D & 0x00FF00. Le & donne un 1 si les deux bits sont à 1. En mettant tous les bits du premier et troisième octet, on est sûr de ne retrouver que des 0 au final. Quant au deuxième octet, le & permet d'en faire une 'copie' puisqu'on aura des 1 au final, seulement pour les bits étant déjà à 1. Ainsi 0xFCA32D & 0x00FF00 = 0x00A300 = 0xA300.
Maintenant il faut décaler les bits vers la gauche, car pour l'instant, nous n'avons réussi qu'à isoler le nombre 0xA300, alors que nous cherchons à obtenir juste 0xA3.

10100011 00000000 >> 8 = 00000000 10100011
0xA300 >> 8 = 0x00A3 = 0xA3 .

Voilà qui est fait, pour résumer voici les formules pour extraire les couleurs :

rouge = (couleur & 0xFF0000) >> 16;
vert = (couleur & 0x00FF00) >> 8;
bleu = (couleur & 0x0000FF); 

Et voici celles qui permettent de créer une couleur à partir des composantes :

couleur = (rouge<<16) | (vert<<8) | bleu)

Mise en application

Pour illustrer ce dernier paragraphe, je vous propose d'écrire un programme affichant une fenêtre 320x200 avec une couleur de fond que l'utilisateur pour choisir lors du lancement de l'application.

#include <stdio.h>
#include <stdlib.h>
#include "tinyptc.h"

#define LARGEUR 320
#define HAUTEUR 200
#define ( TAILLE LARGEUR * HAUTEUR )

int buffer[TAILLE];

int main( int argc, char *argv[] )
{
    int i;
    int r, g, b;
    int couleur;

    r = atoi(argv[1]);
    g = atoi(argv[2]);
    b = atoi(argv[3]);

    couleur = (r << 16) | (g <<8) | b;

    ptc_open("Couleur au choix", LARGEUR, HAUTEUR);

    for (i=0;i<TAILLE;i++)
    {
        buffer[i] = couleur;
    }

    while(1)
    {
        ptc_update(buffer);
    }

    ptc_close();
    return 1;
}

Ici on récupère les composantes entrées en paramètres par l'utilisateur, et on créer la couleur à partir de celles-là. Ensuite, pour chaque élément du buffer, on lui attribue la couleur.

Conclusion

Vous savez maintenant manipuler les couleurs, cependant je vous recommande de vous entraînez encore, c'est un domaine difficile à maîtriser lorsqu'on n'est pas habitué à travailler sur les bits.