require("../global.php"); entete(); ?>
Bonjour,
nous allons parler de conversions. Il faut savoir que l'on peut représenter
une couleur de différentes facons. Cela a commencé par un codage simple sur 1
bit, ce qui a donné deux couleurs possibles selon l'état du bit en question.
Puis cela a évolué rapidement vers 16 couleurs et, avec l'apparition des
cartes graphiques VGA, vers les 256 couleurs. Maintenant, nous en sommes à
coder l'information sur 32 bits, et même 48 bits pour les cartes graphiques
et scanners professionnels.
Note : nous parlerons de bpp pour parler du nombre de bits utilisés pour
contenir l'information d'un pixel. Par exemple 8 bpp pour les modes 256
couleurs.
La conversion de 8 bpp vers des mode high-color ou true-color sera donc aisée. L'opération inverse est beaucoup plus difficile. Elle s'appelle "dithering" et n'entre pas dans le cadre de cet article.
 
Ainsi, le pixel ne donne pas un index dans la palette mais les proportions de rouge, de vert et de bleu directement. Voici l'organisation des bits :
76543210 76543210 RRRRRVVV VVVBBBBB
Nous avons donc 2 octets pour chaque pixel. Comment extraire les informations de couleurs ? Réponse : les décalages de bit, les OU et les ET sont vos amis : pour avoir le bleu, il suffit de mettre à 0 tous les bits qui ne nous interessent pas, c'est à dire les bits correspondant aux composantes rouge et vert.
Voici les formules (le >>1 représente un décalage de bits vers la droite) :
rouge = (couleur >> 11) & 31 (31 = 011111b) vert = (couleur >> 5 ) & 63 (63 = 0111111b) bleu = couleur & 31
De la meme maniere, pour recomposer une couleur 16 bpp, vous ferez :
couleur = (rouge << 11) | (vert << 5) | bleu
76543210 76543210 76543210 pour le 24 bpp RRRRRRRR VVVVVVVV BBBBBBBB
voici les formules pour le 24 bpp :
rouge = (couleur >> 16) & 255 vert = (couleur >> 8 ) & 255 bleu = couleur & 255
De la meme maniere, pour recomposer une couleur 16 bpp, vous ferez :
couleur = (rouge << 11) | (vert << 5) | bleu
Mais, lecteur alerte, tu vas me dire, que fait-on des 8 bits supplémentaires du mode 32 bpp, on rajoute le pourpre ou le jaune ? Ben non, sot. On va rajouter une information indiquant le niveau de transparence du pixel (appelé composante alpha). 255 signifie que le pixel est totalement opaque, 0 signifie que le pixel est totalement transparent. Je vous laisse faire les formules de conversion, sachant que les 8 bits de la composante alpha sont les 8 bits de poids le plus fort (situés à gauche selon la convention des schémas précédents).
Comment utiliser cette information de transparence ?
supposons que le pixel ait la couleur cPixel et que le fond d'écran ait la couleur cFond. La valeur du pixel à afficher est :
cFinale = alpha*cPixel/255 + (255-alpha)*cFond/255
Pour optimiser le calcul de la transparence, il suffit de factoriser un peu la formule. Nous obtenons au final :
cFinale = alpha*( cPixel - cFond )/255 + cFond (une multiplication au lieu de deux).
(WORD *)(source) // Pointeur sur la source de pixels en 16 bpp (uchar *)(destination) // Pointeur sur la destination en 24 bpp for (int y=0; y<hauteur; y++) { for (int x=0; x<largeur; x++) { // Pour le bleu puis on passe a la composante suivante : *(destination++) = ( ( (*source) & 0x001F ) << 3 ); // Pour le vert puis idem : *(destination++) = ( ( (*source) & 0x07E0 ) >> 3 ); // Pour le rouge puis on change de pixel car on a parcouru les 3 // composantes du pixel situe en (x,y)): *(destination++) = ( ( (*source) & 0xF800 ) >> 8 ); // On change de pixel (on passe au "word" suivant) : source++; } }
Personellement, j'ai defini des macros qui recomposent une couleur en fonction des composantes RVB voulues :
#define MakeColor32(a, r, g, b) ( ((uchar)(a) << 24) | ((uchar)(r) << 16) | ((uchar)(g) << 8) | ((uchar)(b)) ) #define MakeColor16(r, g, b) ( (((uchar)(b) >> 3)<< 11) | (((uchar)(g) >> 2) << 5) | ((uchar)(r) >> 3) )
Pour passer de 24 bpp a 16 bpp il suffira de faire :
(uchar *)(source) // Pointeur sur la source de pixels en 24 bpp (WORD *)(destination) // Pointeur sur la destination en 16 bpp for (int y=0; y<hauteur; y++) { for (int x=0; x<largeur; x++) { *(destination) = (WORD)(MakeColor16( (uchar)(*(source+0) << 3), (uchar)(*(source+1) >> 2), (uchar)(*(source+2) >> 7) )); // On passe aux pixels suivants destination++; source+=3; } }
76543210 76543210 RRRRRVV VVVBBBBB
Le 16e bit peut servir comme information pour savoir si le pixel est visible ou non par exemple.
A la prochaine.
########################################## # Auteur : Vincent PRAT aka Gore # # e-mail : vprat@ifrance.com # # Home page : http://vprat.ifrance.com # # ICQ : 101306450 # ########################################## -= Greets/coucous =- .. Jerome, Guillaume, Gersandre .. .. Les gens patients de #Codefr ..PiedDePage(); ?>