V. Images▲
V-A. Introduction▲
Toutes les images sont des bitmaps dans un programme Allegro. Nous commençons ainsi par présenter la bitmap en mémoire qui dans un programme permet de créer, de composer ou de modifier une image. Ensuite nous présentons les « images ». À la différence des bitmaps en mémoire, ce sont au départ des fichiers externes au programme que l'on peut charger dans le programme. Nous abordons comment afficher ces images, comment les modifier, éventuellement pixel par pixel et comment les sauvegarder ensuite.
V-B. Bitmap en mémoire▲
Une bitmap, littéralement plan ou surface de bits, sert au codage d'une image en mémoire. Le principe est celui d'un tableau d'octets à deux dimensions, un tableau d'unsigned char. Chaque position du tableau correspond à un pixel de l'image et sa valeur code sa couleur.
En 8 bits, dont l'utilisation est de plus en plus rare, la valeur correspond à un indice dans un tableau de 256 couleurs RGB appelé une palette (comme la palette du peintre). En 15, 16, 24 et 32 bits, la valeur du pixel est décomposée en trois sous-valeurs, une pour le rouge, une pour le vert, une pour le bleu. En 32 bits, il y a en plus une valeur de transparence. Chacune de ses sous-valeurs correspond à un nombre de bits. Par exemple, pour la couleur 16 bits dans l'ancienne version 4 d'Allegro, chaque couleur est codée sur un unsigned short (2 octets) décomposé en 6 bits pour le rouge, 5 bits pour le vert et 6 bits pour le bleu. Actuellement la couleur est pratiquement toujours codée en 32 bits avec un octet par composante de couleur et un octet pour la transparence.
Il y a deux grands types de bitmap en mémoire : les bitmaps qui utilisent la RAM désignées sous le terme de « bitmaps mémoire » et les bitmaps de mémoire vidéo qui utilisent la mémoire de la carte vidéo. En général, les opérations de dessin et tous les traitements directement en mémoire RAM sont plus rapides. Pour cette raison, il est souvent préférable de faire ses opérations graphiques avec des bitmaps mémoire et d'afficher ensuite ou au fur et à mesure les résultats à l'écran. L'écran utilise de la mémoire vidéo. Les traitements sur l'image y sont beaucoup plus lents, en revanche les opérations d'affichage bénéficient au contraire d'une accélération graphique.
Le module bitmap fait partie du tronc commun d'Allegro, ce n'est pas un greffon (ce n'est pas un addon) et l'utilisation des fonctions de bitmaps nécessite uniquement l'inclusion du module de base de la bibliothèque Allegro :
#include <allegro5/allegro.h>
V-B-1. Créer une bitmap▲
Sous Allegro, une bitmap est une structure du type ALLEGRO_BITMAP . Elles seront toujours manipulées via des pointeurs. Pour créer une bitmap, il faut déclarer un pointeur :
ALLEGRO_BITMAP*
mabmp ;
Ensuite plusieurs options sont possibles : bitmap mémoire, bitmap vidéo… Chaque option est désignée par une valeur drapeau (flag en anglais). L'option choisie doit être activée avec un appel à la fonction :
void
al_set_new_bitmap_flags
(
int
flags)
La documentation présente dix options mais les trois options les plus courantes sont :
ALLEGRO_MEMORY_BITMAP
Spécifie la création d'une bitmap en mémoire RAM. Pas d'accélération graphique mais l'accès direct aux pixels est plus rapide qu'avec la mémoire vidéo.
ALLEGRO_VIDEO_BITMAP
Bitmap en mémoire sur la carte vidéo. Profite de l'accélération graphique. Toutes les bitmaps vidéo dépendent de l'affichage (display) courant. La création peut échouer s'il n'y a pas de display ou si les dimensions ne sont pas supportées.
ALLEGRO_CONVERT_BITMAP
C'est le réglage par défaut et il ne nécessite pas d'appel à la fonction al_set_new_bitmap_flags() . Le principe sous-jacent pour la création d'une bitmap est alors premièrement d'essayer d'avoir une bitmap vidéo optimisée pour la fenêtre d'affichage du display courant et en cas d'échec de créer une bitmap mémoire.
Une fois l'option sélectionnée, la bitmap finale est obtenue avec un appel à la fonction :
ALLEGRO_BITMAP *
al_create_bitmap
(
int
w, int
h)
La fonction retourne un pointeur alloué selon les dimensions demandées en w pour la largeur et h pour la hauteur de la bitmap.
Typiquement pour avoir une bitmap mémoire, nous aurons la séquence :
ALLEGRO_BITMAP*
bmp ;
(
...)
al_set_new_bitmap_flags
(
ALLEGRO_MEMORY_BITMAP);
bmp=
al_create_bitmap
(
tx,ty);
if
(!
bmp)
erreur
(
"
al_create_bitmap()
"
);
Par ailleurs une fonction offre la possibilité de cloner une bitmap.
La fonction al_clone_bitmap :
ALLEGRO_BITMAP *
al_clone_bitmap
(
ALLEGRO_BITMAP *
source)
Clone une bitmap existante. Elle retourne une copie de la bitmap passée au paramètre source.
V-B-2. Dessiner dans une bitmap▲
Une fois la bitmap créée, pour que les opérations de dessin s'exécutent dedans elle doit au préalable être sélectionnée avec un appel à la fonction :
void
al_set_target_bitmap
(
ALLEGRO_BITMAP *
bitmap)
qui prend en paramètre la bitmap pour dessiner (target signifie cible en anglais). Tant que cette bitmap est sélectionnée, il n'est pas possible de dessiner ailleurs et toutes les opérations d'affichage et de dessin se feront dedans. Pour retourner à l'écran, il faut resélectionner l'écran. C'est le rôle de la fonction :
void
al_set_target_backbuffer
(
ALLEGRO_DISPLAY *
display)
qui prend en paramètre la fenêtre d'affichage display courant. Cela revient à sélectionner le double buffer de l'écran pour les opérations d'affichage. Nous pourrions aussi utiliser la fonction al_set_target_bitmap() de la façon suivante :
al_set_target_bitmap
(
al_get_backbuffer
(
display));
Sachant que l'appel de la fonction al_get_backbuffer(display) retourne le double buffer de la fenêtre display passée en paramètre.
Typiquement nous aurons une séquence :
// sélection de la bitmap
al_set_target_bitmap
(
bmp);
// dessins dedans, par exemple
al_clear_to_color
(
al_map_rgb
(
10
,0
,100
));
al_draw_filled_rectangle
(
10
,20
,30
,40
,color) ;
// revenir à l'affichage display
al_set_target_backbuffer
(
display);
Pour afficher à l'écran l'image ainsi créée, il y a de nombreuses fonctions que nous étudierons plus loin mais voici la plus usitée :
void
al_draw_bitmap
(
ALLEGRO_BITMAP *
bmp, float
x, float
y, int
flags)
Cette fonction affiche la bitmap bmp dans la bitmap actuellement sélectionnée pour l'affichage (écran ou une autre bitmap) à la position x, y , selon le paramétrage donné par flags . Il y a trois possibilités :
0 : l'image est affichée sans changement.
ALLEGRO_FLIP_HORIZONTAL : renversement horizontal selon l'axe des y.
ALLEGRO_FLIP_VERTICAL : renversement vertical selon l'axe des x.
La bitmap à afficher et la bitmap de destination ne peuvent pas être la même bitmap. Pour une opération sur la même bitmap il faut passer par des copies sur des bitmaps intermédiaires.
Dernière chose, la libération de la mémoire allouée pour une bitmap se fait avec la fonction :
void
al_destroy_bitmap
(
ALLEGRO_BITMAP *
bitmap)
Elle prend en paramètre la bitmap à libérer de la mémoire.
V-B-2-a. Expérimentation▲
Voici un exemple complet, création d'une bitmap, dessin, mouvement et affichage à l'écran :
#include <allegro5/allegro.h>
#include <allegro5/allegro_native_dialog.h>
#include <allegro5/allegro_primitives.h>
#include <time.h>
#define COLORALEA al_map_rgb(rand()%256,rand()%256,rand()%256);
void
erreur
(
const
char
*
txt)
{
ALLEGRO_DISPLAY*
d;
d =
al_is_system_installed
(
) ? al_get_current_display
(
) : NULL
;
al_show_native_message_box
(
d, "
Erreur
"
, txt, NULL
, NULL
, 0
);
exit
(
EXIT_FAILURE);
}
/**
***************************************************************
****************************************************************
*/
int
is_key_pressed
(
ALLEGRO_KEYBOARD_STATE*
key, int
touche, int
repeat)
{
//le tableau conserve ses valeurs d'un appel à l'autre (static)
static
int
press[ALLEGRO_KEY_MAX] =
{
0
}
;
int
res =
0
;
if
(
al_key_down
(
key, touche) &&
press[touche] <
repeat){
press[touche]++
;
res =
1
;
}
else
if
(!
al_key_down
(
key, touche))
press[touche] =
0
;
return
res;
}
/**
***************************************************************
****************************************************************
*/
int
main
(
)
{
ALLEGRO_DISPLAY*
display;
ALLEGRO_KEYBOARD_STATE key;
ALLEGRO_BITMAP*
bmp;
ALLEGRO_COLOR color;
int
x, y, tx, ty, dx, dy, i;
int
screenx, screeny;
srand
(
time
(
NULL
));
if
(!
al_init
(
))
erreur
(
"
al_init()
"
);
if
(!
al_install_keyboard
(
))
erreur
(
"
al_install_keyboard()
"
);
if
(!
al_init_primitives_addon
(
))
erreur
(
"
al_init_primitives_addon()
"
);
display =
al_create_display
(
800
, 600
);
if
(!
display)
erreur
(
"
al_create_display()
"
);
screenx =
al_get_display_width
(
display);
screeny =
al_get_display_height
(
display);
// dimension pour la bitmap
tx =
10
+
rand
(
) %
(
screenx /
2
);
ty =
10
+
rand
(
) %
(
screeny /
2
);
// création d'une bitmap mémoire
al_set_new_bitmap_flags
(
ALLEGRO_MEMORY_BITMAP);
bmp =
al_create_bitmap
(
tx, ty);
if
(!
bmp)
erreur
(
"
al_create_bitmap()
"
);
// dessiner dans la bitmap en mémoire
al_set_target_bitmap
(
bmp);
// bombardement de pixel de couleurs aléatoires
al_clear_to_color
(
al_map_rgb
(
10
, 0
, 100
));
for
(
i =
0
; i<
10000
; i++
){
color =
COLORALEA;
al_put_pixel
(
rand
(
) %
tx, rand
(
) %
ty, color);
}
// revenir à l'affichage display
al_set_target_backbuffer
(
display);
// position de départ
x =
rand
(
) %
(
screenx -
tx);
y =
rand
(
) %
(
screeny -
ty);
// déplacement
dx =
rand
(
) %
20
-
10
;
dy =
rand
(
) %
20
-
10
;
do
{
al_get_keyboard_state
(&
key);
// bouger
x +=
dx;
if
(
x<
0
||
x +
tx>
screenx)
dx *=
-
1
;
y +=
dy;
if
(
y<
0
||
y +
ty>
screeny)
dy *=
-
1
;
// effacement Double Buffer
al_clear_to_color
(
al_map_rgb
(
0
, 0
, 0
));
// affichage DB de l'imae aux coordonnées x,y
al_draw_bitmap
(
bmp, x, y, 0
);
// DB copié à l'écran
al_flip_display
(
);
al_rest
(
1
.0
/
30
.0
);
}
while
(!
al_key_down
(&
key, ALLEGRO_KEY_ESCAPE));
al_destroy_display
(
display);
al_destroy_bitmap
(
bmp);
return
0
;
}
/**
***************************************************************
****************************************************************
*/
V-C. Image▲
L'image est toujours une bitmap dans le programme mais elle provient au départ d'un fichier sur le disque dur. Les formats reconnus avec certitude sont BMP, PCX, TGA, JPEG et PNG.
V-C-1. Charger une image (load)▲
Le chargement d'images ainsi que la sauvegarde des images nécessitent l'utilisation du module image, soit l'inclusion de allegro_image.h :
#include <allegro5/allegro_image.h>
et l'initialisation du module image avec un appel à :
bool al_init_image_addon
(
void
)
La fonction retourne true si succès et false sinon. Typiquement nous écrirons :
if
(!
al_init_image_addon
(
))
erreur
(
"
al_init_image_addon()
"
);
Ensuite pour charger une image dans le programme c'est un appel à la fonction :
ALLEGRO_BITMAP *
al_load_bitmap
(
const
char
*
filename)
Cette fonction prend en paramètre le chemin d'accès au fichier image extension comprise et retourne un pointeur sur la bitmap qui est une copie de l'image ou NULL en cas d'échec.
Tous les formats d'image ne sont pas reconnus, mais les principaux formats BMP, PCX, TGA, JPEG et PNG le sont. Exemple d'utilisation, le programme charge une image de type bitmap (.bmp) nommée « image.bmp » qui se trouve dans le dossier « images » lui-même dans le répertoire du programme :
#include <allegro5/allegro.h>
#include <allegro5/allegro_native_dialog.h>
#include <allegro5/allegro_image.h>
void
erreur
(
const
char
*
txt)
{
ALLEGRO_DISPLAY*
d;
d =
al_is_system_installed
(
) ? al_get_current_display
(
) : NULL
;
al_show_native_message_box
(
d, "
Erreur
"
, txt, NULL
, NULL
, 0
);
exit
(
EXIT_FAILURE);
}
/**
***************************************************************
****************************************************************
*/
int
main
(
)
{
ALLEGRO_DISPLAY*
display;
ALLEGRO_BITMAP*
image; // l'image
if
(!
al_init
(
))
erreur
(
"
al_init()
"
);
display =
al_create_display
(
800
, 600
);
if
(!
display)
erreur
(
"
al_create_display()
"
);
//nécessaire pour laod et save bitmap
if
(!
al_init_image_addon
(
))
erreur
(
"
al_init_image_addon()
"
);
// charger une image dans le programme
image =
al_load_bitmap
(
"
./images/image.bmp
"
);
if
(!
image)
erreur
(
"
al_load_bitmap()
"
);
// l'afficher
al_draw_bitmap
(
image, 0
, 0
, 0
);
al_flip_display
(
);
al_rest
(
3
.0
);
al_destroy_display
(
display);
al_destroy_bitmap
(
image);
return
0
;
}
/**
***************************************************************
****************************************************************
*/
V-C-2. Afficher une image▲
Allegro fournit de nombreuses fonctions pour l'affichage des images.
La fonction al_draw_bitmap :
void
al_draw_bitmap
(
ALLEGRO_BITMAP *
source, float
x, float
y, int
flags)
Affiche la bitmap source dans la bitmap cible actuellement sélectionnée à la position x , y et selon la valeur flags qui peut être :
0 : l'image est affichée sans changement.
ALLEGRO_FLIP_HORIZONTAL : renversement horizontal selon l'axe des y.
ALLEGRO_FLIP_VERTICAL : renversement vertical selon l'axe des x.
La bitmap à afficher et la bitmap cible ne peuvent pas être la même bitmap. Pour une opération sur la même bitmap, il faut passer par des copies sur des bitmaps intermédiaires.
La fonction al_draw_bitmap_region :
void
al_draw_bitmap_region
(
ALLEGRO_BITMAP *
source, float
sx, float
sy, float
sw, float
sh, float
dx, float
dy, int
flags)
Copie une région de la bitmap source définie par sx, sy, sw, sh à la position dx, dy dans la bitmap cible actuellement sélectionnée. Le paramètre flags peut être : 0 , ALLEGRO_FLIP_HORIZONTAL,
ALLEGRO_FLIP_VERTICAL.
La fonction al_draw_scaled_bitmap :
void
al_draw_scaled_bitmap
(
ALLEGRO_BITMAP *
source ,float
sx, float
sy, float
sw, float
sh, float
dx, float
dy, float
dw, float
dh, int
flags)
Copie en étirée ou en réduction (scale, stretch) de la région définie par sx , sy , sw , sh dans la bitmap source vers la région définie par dx , dy , dw , dh dans la bitmap cible (target) actuellement sélectionnée. Le paramètre flags peut être : 0 , ALLEGRO_FLIP_HORIZONTAL , ALLEGRO_FLIP_VERTICAL .
La fonction al_draw_rotated_bitmap :
void
al_draw_rotated_bitmap
(
ALLEGRO_BITMAP *
source, float
cx, float
cy, float
dx, float
dy, float
angle, int
flags)
Copie la bitmap source dans la bitmap cible sélectionnée en effectuant une rotation. Les paramètres cx et cy fournissent un point dans l'image source autour duquel s'effectue la rotation. Les paramètres dx et dy fournissent la correspondance dans l'image de destination. L'angle est donné en radians avec angle . Le paramètre flags indique si une permutation horizontale ou verticale doit être effectuée.
La fonction al_draw_scaled_rotated_bitmap :
void
al_draw_scaled_rotated_bitmap
(
ALLEGRO_BITMAP *
source, float
cx, float
cy, float
dx, float
dy, float
xscale, float
yscale, float
angle, int
flags)
Copie la bitmap source dans la bitmap cible (target) sélectionnée en effectuant un étirement ou une réduction (scale, stretch) et une rotation (se reporter aux deux fonctions précédentes pour le détail des paramètres).
La fonction al_draw_tinted_bitmap :
void
al_draw_tinted_bitmap
(
ALLEGRO_BITMAP *
bmp, ALLEGRO_COLOR tint, float
dx, float
dy, int
flags)
Identique à al_draw_bitmap() mais en plus le paramètre tint permet un filtrage des couleurs de l'image. Le filtre est une couleur. Chaque composante rouge, vert, bleu, alpha de la couleur du filtre multiplie les composantes correspondantes de la couleur de chaque pixel de l'image. Par exemple :
ALLEGRO_COLOR tint=
al_map_rgba_f
(
0
.5
, 0
.5
, 0
.5
, 0
.5
);
al_draw_tinted_bitmap
(
bitmap, tint, x, y, 0
);
Cet appel divise par deux l'affichage de la valeur de couleur de chaque composante des couleurs de l'image source ce qui l'assombrit.
ALLEGRO_COLOR tint=
al_map_rgba_f
(
1
, 0
, 0
, 2
);
al_draw_tinted_bitmap
(
bitmap, tint, x, y, 0
);
Cet appel laisse le rouge inchangé, met à 0 le vert et le bleu puis multiplie par deux la transparence.
La fonction al_draw_tinted_bitmap_region :
void
al_draw_tinted_bitmap_region
(
ALLEGRO_BITMAP *
bmp, ALLEGRO_COLOR tint, float
sx, float
sy, float
sw, float
sh, float
dx, float
dy, int
flags)
Fonction identique à al_draw_bitmap_region() mais ajoute le paramètre tint pour le filtrage des couleurs (voir al_draw_tinted_bitmap() pour le fonctionnement de ce paramètre).
La fonction al_draw_tinted_scaled_bitmap :
void
al_draw_tinted_scaled_bitmap
(
ALLEGRO_BITMAP *
bmp, ALLEGRO_COLOR tint, float
sx, float
sy, float
sw, float
sh, float
dx, float
dy, float
dw, float
dh, int
flags)
Fonction identique à al_draw_scaled_bitmap() mais ajoute le paramètre tint pour le filtrage des couleurs (voir al_draw_tinted_bitmap() pour le fonctionnement de ce paramètre).
La fonction al_draw_tinted_rotated_bitmap :
void
al_draw_tinted_rotated_bitmap
(
ALLEGRO_BITMAP *
bmp, ALLEGRO_COLOR tint, float
cx, float
cy, float
dx, float
dy, float
angle, int
flags)
Fonction identique à al_draw_rotated_bitmap() mais ajoute le paramètre tint pour le filtrage des couleurs (voir al_draw_tinted_bitmap() pour le fonctionnement de ce paramètre).
La fonction al_draw_tinted_scaled_rotated_bitmap :
void
al_draw_tinted_scaled_rotated_bitmap
(
ALLEGRO_BITMAP *
bmp, ALLEGRO_COLOR tint, float
cx, float
cy, float
dx, float
dy, float
xscale, float
yscale, float
angle, int
flags)
Fonction identique à al_draw_scaled_rotated_bitmap_region() mais ajoute le paramètre tint pour le filtrage des couleurs (voir al_draw_tinted_bitmap() pour le fonctionnement de ce paramètre).
La fonction al_draw_tinted_scaled_rotated_bitmap_region :
void
al_draw_tinted_scaled_rotated_bitmap_region
(
ALLEGRO_BITMAP *
bmp, float
sx, float
sy, float
sw, float
sh, ALLEGRO_COLOR tint, float
cx, float
cy, float
dx, float
dy, float
xscale, float
yscale, float
angle, int
flags)
Fonction identique à al_draw_scaled_rotated_bitmap_region() mais ajoute le paramètre tint pour le filtrage des couleurs (voir al_draw_tinted_bitmap() pour le fonctionnement de ce paramètre).
V-C-3. Expérimenter les fonctions d'affichage▲
Très honnêtement les affichages valent la peine d'être tous expérimentés. Ils sont vraiment très réussis. Une chose est de comprendre ce que fait la fonction, une autre de voir le résultat. Le programme ci-dessous suppose une image bitmap (.bmp) positionnée dans le répertoire du programme et nommée « image.bmp ». Toutes les fonctions d'affichage sont testées à partir des touches [F1] à [F11]. La touche [Entrée] efface l'écran.
Nous profitons volontairement dans ce programme de la répétition de touche due à la méthode de capture du clavier dans une structure ALLEGRO_KEYBOARD_STATE par la fonction al_get_keyboard_state() .
#include <allegro5/allegro.h>
#include <allegro5/allegro_native_dialog.h>
#include <allegro5/allegro_image.h>
void
erreur
(
const
char
*
txt)
{
ALLEGRO_DISPLAY*
d;
d =
al_is_system_installed
(
) ? al_get_current_display
(
) : NULL
;
al_show_native_message_box
(
d, "
Erreur
"
, txt, NULL
, NULL
, 0
);
exit
(
EXIT_FAILURE);
}
/**
***************************************************************
****************************************************************
*/
int
main
(
)
{
ALLEGRO_DISPLAY*
display;
ALLEGRO_KEYBOARD_STATE key;
ALLEGRO_BITMAP*
image;
int
tx, ty, screenx, screeny;
if
(!
al_init
(
))
erreur
(
"
al_init()
"
);
if
(!
al_install_keyboard
(
))
erreur
(
"
al_install_keyboard()
"
);
if
(!
al_init_image_addon
(
))
erreur
(
"
al_init_image_addon()
"
);
display =
al_create_display
(
800
, 600
);
if
(!
display)
erreur
(
"
al_create_display()
"
);
screenx =
al_get_display_width
(
display);
screeny =
al_get_display_height
(
display);
image =
al_load_bitmap
(
"
image.bmp
"
);
if
(!
image)
erreur
(
"
al_load_bitmap()
"
);
tx =
al_get_bitmap_width
(
image);
ty =
al_get_bitmap_height
(
image);
do
{
al_get_keyboard_state
(&
key);
int
flags =
0
; // pas de permutation
// autres possibilités :
// flags=ALLEGRO_FLIP_HORIZONTAL
// flags=ALLEGRO_FLIP_VERTICAL
// flags=ALLEGRO_FLIP_HORIZONTAL|ALLEGRO_FLIP_VERTICAL
if
(
al_key_down
(&
key, ALLEGRO_KEY_F1))
al_draw_bitmap
(
image, // l'image source
0
, 0
, // position
flags); // permutation
// pour les régions
int
sx =
rand
(
) %
tx;
int
sy =
rand
(
) %
ty;
int
sw =
rand
(
) %
(
tx -
sx);
int
sh =
rand
(
) %
(
ty -
sy);
int
dx =
rand
(
) %
(
screenx -
sw);
int
dy =
rand
(
) %
(
screeny -
sh);
if
(
al_key_down
(&
key, ALLEGRO_KEY_F2)){
al_draw_bitmap_region
(
image,
sx, sy, // hg source
sw, sh, // taille dans source
dx, dy, // hg destination
flags); //permutation
}
// taille destination pour déformation
float
dw =
((
float
)rand
(
) /
RAND_MAX)*
screenx;
float
dh =
((
float
)rand
(
) /
RAND_MAX)*
screeny;
if
(
al_key_down
(&
key, ALLEGRO_KEY_F3))
al_draw_scaled_bitmap
(
image, // image source
0
, 0
, // coin haut gauche
tx, ty, // taille source
0
, 0
, // coin haut gauche destination
dw, // taille destination
dh,
flags); // permutation
if
(
al_key_down
(&
key, ALLEGRO_KEY_F4))
al_draw_rotated_bitmap
(
image, // image source
tx /
2
, ty /
2
, //pivot source
screenx /
2
, //pivot destination
screeny /
2
,
rand
(
) %
360
, // angle en radian
flags); // permutation
// proportion pour déformation
float
xscale =
((
float
)rand
(
) /
RAND_MAX) *
2
;
float
yscale =
((
float
)rand
(
) /
RAND_MAX) *
2
;
float
angle =
((
float
)rand
(
) /
RAND_MAX)*
(
2
*
3
.14
);
if
(
al_key_down
(&
key, ALLEGRO_KEY_F5)){
al_draw_scaled_rotated_bitmap
(
image,
tx /
2
, ty /
2
, //pivot source
screenx /
2
, //pivot destination
screeny /
2
,
xscale, yscale, // le rapport,
angle, // angle en radian
flags); // permutation
}
// pour les affichages teintés
// la couleur originale de chaque pixel est modifiée
// par multiplication. Par exemple un filtre de
// al_map_rgba_f(0.5, 0.5,0.5,0.5)
// signifie que rouge,vert, bleu et transparence de
// l'image seront divisés par deux
// un filtre de al_map_rgba_f(1, 0,0,2) signifie
// que le rouge reste identique, vert et bleu sont
// supprimés et transparence multipliée par deux.
float
r =
((
float
)rand
(
) /
RAND_MAX) *
2
;
float
g =
((
float
)rand
(
) /
RAND_MAX) *
2
;
float
b =
((
float
)rand
(
) /
RAND_MAX) *
2
;
float
a =
((
float
)rand
(
) /
RAND_MAX) *
2
;
ALLEGRO_COLOR filtre =
al_map_rgba_f
(
r, g, b, a);
if
(
al_key_down
(&
key, ALLEGRO_KEY_F6))
al_draw_tinted_bitmap
(
image,
filtre, // transformation couleur
0
, 0
, // position destination
flags); // permutation
if
(
al_key_down
(&
key, ALLEGRO_KEY_F7))
al_draw_tinted_bitmap_region
(
image,
filtre,
sx, sy, //coin hg source
sw, sh, // taille source
dx, dy, // position destination
flags);// permutations
if
(
al_key_down
(&
key, ALLEGRO_KEY_F8))
al_draw_tinted_scaled_bitmap
(
image,
filtre,
sx, sy,// coin h-g source
sw, sh,// taille source
dx, dy,// coin h-g destination
dw, dh,// taille destination
flags); // permutation
if
(
al_key_down
(&
key, ALLEGRO_KEY_F9))
al_draw_tinted_rotated_bitmap
(
image,
filtre,
tx /
2
, ty /
2
, // pivot source
dx, dy, // pivot destination
angle,
flags);
if
(
al_key_down
(&
key, ALLEGRO_KEY_F10))
al_draw_tinted_scaled_rotated_bitmap
(
image,
filtre,
tx /
2
, ty /
2
,//pivot source
dx, dy, // pivot destination
xscale, yscale,// rapport taille
angle,
flags);
if
(
al_key_down
(&
key, ALLEGRO_KEY_F11))
al_draw_tinted_scaled_rotated_bitmap_region
(
image,
sx, sy,// source h-g
sw, sh,// source taille
filtre,
tx /
2
, ty /
2
,// pivot source
dx, dy,// pivot destination
xscale, yscale, // rapport taille
angle,
flags);
if
(
al_key_down
(&
key, ALLEGRO_KEY_ENTER))
al_clear_to_color
(
al_map_rgb
(
0
, 0
, 0
));
al_flip_display
(
);
}
while
(!
al_key_down
(&
key, ALLEGRO_KEY_ESCAPE));
al_destroy_display
(
display);
al_destroy_bitmap
(
image);
return
0
;
}
/**
***************************************************************
****************************************************************
*/
V-C-4. Sélectionner une image pour la modifier▲
Dans un programme Allegro, une image est une copie en bitmap d'un fichier sur le disque dur. Nous avons vu que pour pouvoir dessiner ou afficher dans une bitmap, la bitmap cible doit au préalable être sélectionnée. Voici un rappel des principales fonctions pour cette opération et aussi le moyen de connaître celle réservée pour l'affichage à un moment dans le programme.
La fonction al_set_target_bitmap :
void
al_set_target_bitmap
(
ALLEGRO_BITMAP *
bitmap)
Cette fonction permet de sélectionner la bitmap dans laquelle dessiner ou afficher.
La fonction al_get_target_bitmap :
ALLEGRO_BITMAP *
al_get_target_bitmap
(
void
)
Cette fonction retourne l'adresse de la bitmap actuellement sélectionnée pour les opérations de dessin et d'affichage.
La fonction al_set_target_backbuffer :
void
al_set_target_backbuffer
(
ALLEGRO_DISPLAY *
display)
Cette fonction sélectionne le double buffer de la fenêtre display passée en paramètre pour les opérations de dessin et d'affichage.
La fonction al_get_current_display :
ALLEGRO_DISPLAY *
al_get_current_display
(
void
)
Cette fonction récupère la fenêtre display actuellement sélectionnée pour les opérations d'affichage.
La fonction al_get_backbuffer :
ALLEGRO_BITMAP *
al_get_backbuffer
(
ALLEGRO_DISPLAY *
display)
Cette fonction retourne l'adresse de la bitmap double buffer de la fenêtre display passée en paramètre.
V-C-5. Obtenir les propriétés de l'image▲
Allegro fournit également des fonctions pour connaître la longueur, la hauteur et la profondeur, c'est-à-dire le format de couleur des pixels (8, 15, 16, 24, 32 bits), d'une bitmap.
Les fonctions al_get_bitmap_width et al_get_bitmap_height :
int
al_get_bitmap_width
(
ALLEGRO_BITMAP *
bmp)
int
al_get_bitmap_height
(
ALLEGRO_BITMAP *
bmp)
Ces deux fonctions permettent de récupérer respectivement la longueur et la hauteur de la bitmap bmp.
La fonction al_get_bitmap_format :
int
al_get_bitmap_format
(
ALLEGRO_BITMAP *
bmp)
Donne le format de pixel de la bitmap bmp, c'est-à-dire la taille en mémoire du pixel avec la configuration des bits pour la couleur. Tous les formats sont définis au sein d'Allegro 5 par un enum :
typedef
enum
ALLEGRO_PIXEL_FORMAT
Ce sont donc des valeurs entières. C'est pourquoi la fonction retourne un int. Chaque valeur code un type de format, en voici quelques-uns à titre indicatif :
ALLEGRO_PIXEL_FORMAT_ARGB_8888 - 32 bit
ALLEGRO_PIXEL_FORMAT_RGBA_8888 - 32 bit
ALLEGRO_PIXEL_FORMAT_ARGB_4444 - 16 bit
ALLEGRO_PIXEL_FORMAT_RGB_888 - 24 bit
ALLEGRO_PIXEL_FORMAT_RGB_565 - 16 bit
ALLEGRO_PIXEL_FORMAT_RGB_555 - 15 bit
Ceci permet éventuellement d'accéder directement à chaque composante de couleur en utilisant les opérateurs bit à bit plutôt que les fonctions prévues. Par exemple soit le format 32 bits ALLEGRO_PIXEL_FORMAT_ARGB_8888 , l'expression :
(
pixel &
0x00FF0000
) >>
16
donne la valeur de la composante de rouge (chaque colonne correspond à 4 bits). Le masque 0x00FF0000 isole les 8 bits qui correspondent à la valeur du rouge et le décalage à droite ramène cette valeur pour donner le résultat.
Toutefois il est peut-être plus simple d'utiliser les fonctions dédiées à la couleur. Notamment pour récupérer ses composantes il y a la série de fonctions al_unmap_(...) présentées dans le chapitre Texte, polices, couleur, dessin, section Couleurs, transparenceCouleurs, transparence.
V-C-6. Sauvegarder une image▲
Pour sauvegarder une image, le greffon (addon) « image » est nécessaire et il doit être inclus :
#include <allegro5/allegro_image.h>
Il faut également veiller à son initialisation ensuite avec la fonction al_init_image_addon() qui retourne true sur succès et false sur erreur :
if
(!
al_init_image_addon
(
))
erreur
(
"
al_init_image_addon()
"
);
Ensuite dans le programme la sauvegarde d'une bitmap s'effectue avec :
bool al_save_bitmap
(
const
char
*
filename, ALLEGRO_BITMAP *
source)
Cette fonction crée un fichier en copie de la bitmap source. Le nom du fichier est passé en filename, il se termine obligatoirement par une extension : .bmp, .png, .jpg, .pcx, .tga, qui détermine quel est le type de l'image.
V-C-6-a. Expérimentation▲
Nous reprenons une partie du programme précédent de chargement d'une image et de son affichage avec la fonction al_draw_tinted_scaled_rotated_bitmap_region() qui donne de très beaux résultats. Au départ appuyer sur [F1] pour obtenir un affichage. Ensuite chaque appui sur la touche S déclenche une sauvegarde de l'image affichée dans la fenêtre courante display de l'application ou une capture d'écran si le programme est en plein écran.
Pour éviter des sauvegardes multiples avec un seul appui sur la touche S, la fonction is_key_pressed() , présentée dans le chapitre Premiers pas avec Allegro 5, section Compter les répétitions clavierCompter les répétitions clavier, est utilisée.
// ceci sous Visual Studio uniquement afin de
// lever l'interdiction d'utiliser des fonctions
// jugées unsafe par microsoft.
#define _CRT_SECURE_NO_WARNINGS
#include <allegro5/allegro.h>
#include <allegro5/allegro_native_dialog.h>
#include <allegro5/allegro_image.h>
#include <stdio.h>
void
erreur
(
const
char
*
txt)
{
ALLEGRO_DISPLAY*
d;
d =
al_is_system_installed
(
) ? al_get_current_display
(
) : NULL
;
al_show_native_message_box
(
d, "
Erreur
"
, txt, NULL
, NULL
, 0
);
exit
(
EXIT_FAILURE);
}
/**
***************************************************************
****************************************************************
*/
int
is_key_pressed
(
ALLEGRO_KEYBOARD_STATE*
key, int
touche,
int
repeat)
{
//le tableau conserve ses valeurs d'un appel à l'autre (static)
static
int
press[ALLEGRO_KEY_MAX] =
{
0
}
;
int
res =
0
;
if
(
al_key_down
(
key, touche) &&
press[touche] <
repeat){
press[touche]++
;
res =
1
;
}
else
if
(!
al_key_down
(
key, touche))
press[touche] =
0
;
return
res;
}
/**
***************************************************************
****************************************************************
*/
int
main
(
)
{
ALLEGRO_DISPLAY*
display;
ALLEGRO_KEYBOARD_STATE key;
ALLEGRO_BITMAP*
image;
int
tx, ty, screenx, screeny;
if
(!
al_init
(
))
erreur
(
"
al_init()
"
);
if
(!
al_install_keyboard
(
))
erreur
(
"
al_install_keyboard()
"
);
if
(!
al_init_image_addon
(
))
erreur
(
"
al_init_image_addon()
"
);
display =
al_create_display
(
800
, 600
);
if
(!
display)
erreur
(
"
al_create_display()
"
);
screenx =
al_get_display_width
(
display);
screeny =
al_get_display_height
(
display);
image =
al_load_bitmap
(
"
image.bmp
"
);
if
(!
image)
erreur
(
"
al_load_bitmap()
"
);
tx =
al_get_bitmap_width
(
image);
ty =
al_get_bitmap_height
(
image);
do
{
al_get_keyboard_state
(&
key);
// pour les régions
int
sx =
rand
(
) %
tx;
int
sy =
rand
(
) %
ty;
int
sw =
rand
(
) %
(
tx -
sx);
int
sh =
rand
(
) %
(
ty -
sy);
// pivot destination (pivot source centré)
int
dx =
rand
(
) %
(
screenx -
sw);
int
dy =
rand
(
) %
(
screeny -
sh);
// filtre
float
r =
((
float
)rand
(
) /
RAND_MAX) *
2
;
float
g =
((
float
)rand
(
) /
RAND_MAX) *
2
;
float
b =
((
float
)rand
(
) /
RAND_MAX) *
2
;
float
a =
((
float
)rand
(
) /
RAND_MAX) *
2
;
ALLEGRO_COLOR filtre =
al_map_rgba_f
(
r, g, b, a);
// proportion pour déformation
float
xscale =
((
float
)rand
(
) /
RAND_MAX) *
2
;
float
yscale =
((
float
)rand
(
) /
RAND_MAX) *
2
;
float
angle =
((
float
)rand
(
) /
RAND_MAX)*
(
2
*
3
.14
);
if
(
is_key_pressed
(&
key, ALLEGRO_KEY_F1, 100
))
al_draw_tinted_scaled_rotated_bitmap_region
(
image,
sx, sy,// source h-g
sw, sh,// source taille
filtre,
tx /
2
, ty /
2
,// pivot source
dx, dy,// pivot destination
xscale, yscale, // rapport taille
angle,
0
);// pas de permutation
// faire une photo d'écran
if
(
is_key_pressed
(&
key, ALLEGRO_KEY_S, 1
)){
static
int
cmpt =
1
;
char
nom[80
];
ALLEGRO_BITMAP*
save;
// nom du fichier (save+numéro+extension)
sprintf
(
nom, "
save%d.png
"
, cmpt);
cmpt++
;
// l'image bitmap, deux solutions pour obtenir écran :
save =
al_get_backbuffer
(
display); // écran
//save=al_get_target_bitmap();// image cible actuelle
// sauvegarde
al_save_bitmap
(
nom, save);
}
if
(
al_key_down
(&
key, ALLEGRO_KEY_ENTER))
al_clear_to_color
(
al_map_rgb
(
0
, 0
, 0
));
al_flip_display
(
);
}
while
(!
al_key_down
(&
key, ALLEGRO_KEY_ESCAPE));
al_destroy_display
(
display);
al_destroy_bitmap
(
image);
return
0
;
}
/**
***************************************************************
****************************************************************
*/
V-D. L'image pixel par pixel▲
Il est possible d'accéder à chaque pixel d'une image soit pour connaître sa couleur avec la fonction al_get_pixel() , soit pour la modifier avec la fonction al_put_pixel() . Ces accès sont lents surtout en mémoire vidéo, mais ils peuvent être accélérés avec l'utilisation de fonctions de verrouillage quels que soient les types de bitmap.
V-D-1. Accès aux pixels▲
La partie graphique du module de base de la bibliothèque Allegro (inclusion de allegro.h) met à disposition les fonctions suivantes pour l'accès pixel par pixel.
La fonction al_get_pixel :
ALLEGRO_COLOR al_get_pixel
(
ALLEGRO_BITMAP *
source, int
x, int
y)
Cette fonction retourne la couleur du pixel à la position x , y dans la bitmap source.
La couleur retournée peut ensuite être décomposée avec les fonctions spécifiques al_unmap_rgb() , al_unmap_rgb_f() etc. présentées au chapitre Texte, polices, couleur, dessin, section Couleurs, transparenceCouleurs, transparence.
Si la fonction doit être appelée souvent lors d'un traitement sur une même bitmap, il est conseillé de « verrouiller » cette bitmap afin de faciliter les opérations de lecture-écriture. Le verrouillage s'effectue avec la fonction al_lock_bitmap() expliquée plus loin. Une fois les opérations d'accès aux pixels effectuées, le déverrouillage s'effectue avec la fonction al_unlock_bitmap() . Verrouillage et déverrouillage ne concernent que des opérations pixel par pixel.
Cette opération est absolument nécessaire dans le cas d'une bitmap de mémoire vidéo. La mémoire vidéo est en effet destinée à l'affichage et se révèle extrêmement lente pour des traitements internes spécifiques pixel par pixel. Rappelons que la création d'une bitmap avec la fonction al_create_bitmap() ou le chargement d'une bitmap avec al_load_bitmap() retournent par défaut une bitmap vidéo optimisée pour l'affichage dans la fenêtre display courante.
La fonction al_put_pixel
void
al_put_pixel
(
int
x, int
y, ALLEGRO_COLOR color)
Cette fonction colore un pixel à la position x , y avec la couleur color . C'est relativement lent avec une bitmap mémoire et très lent avec une bitmap vidéo. Si les appels sont répétés et fréquents, il est nécessaire de verrouiller la bitmap au début des opérations et de la déverrouiller à la fin (voir al_lock_bitmap() ).
La fonction al_get_bitmap_format
int
al_get_bitmap_format
(
ALLEGRO_BITMAP *
bmp)
Retourne le format de la bitmap bmp. Chaque format est identifié par une valeur entière (cf. chapitre Images - Obtenir les propriétés de l'imageObtenir les propriétés de l'image où la fonction a déjà été présentée avec le détail des formats).
La fonction al_get_pixel_format_bits :
int
al_get_pixel_format_bits
(
int
format)
Retourne le nombre de bits d'un pixel selon le format format .
La fonction al_lock_bitmap :
ALLEGRO_LOCKED_REGION *
al_lock_bitmap
(
ALLEGRO_BITMAP *
bitmap, int
format, int
flags)
La fonction verrouille toute la bitmap pour accélérer l'accès en écriture et en lecture et retourne une structure ALLEGRO_LOCKED_REGION qui correspond ici à toute la bitmap. L'appel fonctionne avec n'importe quel type de bitmap, vidéo aussi bien que mémoire. Cette structure est la suivante :
typedef
struct
ALLEGRO_LOCKED_REGION {
void
*
data;
int
format;
int
pitch;
int
pixel_size;
}
ALLEGRO_LOCKED_REGION;
Le champ data permet d'accéder à chaque pixel de la partie de l'image verrouillée, le format donne le format de la bitmap. Le champ pixel_size donne la taille en octet d'un pixel et le champ pitch donne la taille en octets d'une ligne (largeur de la région * pixel_size).
Le format de la bitmap passé au paramètre format peut être obtenu avec la fonction al_get_bitmap_format() . Pour le drapeau flags il y a trois valeurs possibles :
ALLEGRO_LOCK_READONLY : lecture uniquement.
ALLEGRO_LOCK_WRITEONLY : écriture uniquement. Attention il est impératif d'écrire sur absolument tous les pixels avant de déverrouiller.
ALLEGRO_LOCK_READWRITE : lecture et écriture sont possibles. Cette valeur est à utiliser pour des besoins en écriture seule lorsque tous les pixels ne sont pas à prendre en compte.
La fonction al_lock_bitmap_region :
Éventuellement il peut être utile de ne verrouiller qu'une partie de l'image avec la fonction :
ALLEGRO_LOCKED_REGION *
al_lock_bitmap_region
(
ALLEGRO_BITMAP *
bitmap, int
x, int
y, int
width, int
height, int
format, int
flags)
La région est alors verrouillée à partir de x sur la longueur width et à partir de y sur la hauteur height pour le format obtenu avec la fonction al_get_bitmap_format() et selon la valeur passée en flags pour lecture, écriture ou lecture-écriture.
La fonction al_unlock_bitmap :
void
al_unlock_bitmap
(
ALLEGRO_BITMAP *
bitmap)
Déverrouille la bitmap ou région de bitmap préalablement verrouillée.
La fonction al_is_bitmap_locked :
bool al_is_bitmap_locked
(
ALLEGRO_BITMAP *
bitmap)
Retourne true si la bitmap est verrouillée et false sinon.
Attention : le verrouillage-déverrouillage ne concerne que les opérations pixel par pixel. Les autres opérations de dessin et d'affichage ne sont pas possibles pendant que la bitmap est verrouillée.
V-D-2. Expérimentations verrouillage, al_get_pixel(), al_put_pixel()▲
Au départ, on charge une image. C'est une bitmap nommée « image.bmp » qui se trouve dans le répertoire du programme. Ensuite si la touche [F1] est appuyée, la bitmap image est sélectionnée pour affichage, elle est verrouillée, puis chaque pixel est récupéré et modifié, la bitmap est déverrouillée, la sélection est redonnée au double buffer du display , l'image modifiée y est copiée, le double buffer est affiché. Ce qui donne :
#include <allegro5/allegro.h>
#include <allegro5/allegro_native_dialog.h>
#include <allegro5/allegro_image.h>
void
erreur
(
const
char
*
txt)
{
ALLEGRO_DISPLAY*
d;
d =
al_is_system_installed
(
) ? al_get_current_display
(
) : NULL
;
al_show_native_message_box
(
d, "
Erreur
"
, txt, NULL
, NULL
, 0
);
exit
(
EXIT_FAILURE);
}
/**
***************************************************************
****************************************************************
*/
int
is_key_pressed
(
ALLEGRO_KEYBOARD_STATE*
key, int
touche, int
repeat)
{
//le tableau conserve ses valeurs d'un appel à l'autre (static)
static
int
press[ALLEGRO_KEY_MAX] =
{
0
}
;
int
res =
0
;
if
(
al_key_down
(
key, touche) &&
press[touche] <
repeat){
press[touche]++
;
res =
1
;
}
else
if
(!
al_key_down
(
key, touche))
press[touche] =
0
;
return
res;
}
/**
***************************************************************
****************************************************************
*/
int
main
(
)
{
ALLEGRO_DISPLAY*
display;
ALLEGRO_KEYBOARD_STATE key;
ALLEGRO_BITMAP*
image;
int
tx, ty;
if
(!
al_init
(
))
erreur
(
"
al_init()
"
);
if
(!
al_install_keyboard
(
))
erreur
(
"
al_install_keyboard()
"
);
if
(!
al_init_image_addon
(
))
erreur
(
"
al_init_primitives_addon()
"
);
display =
al_create_display
(
800
, 600
);
if
(!
display)
erreur
(
"
al_create_display()
"
);
image =
al_load_bitmap
(
"
image.bmp
"
);
if
(!
image)
erreur
(
"
al_load_bitmap()
"
);
tx =
al_get_bitmap_width
(
image);
ty =
al_get_bitmap_height
(
image);
do
{
al_get_keyboard_state
(&
key);
if
(
is_key_pressed
(&
key, ALLEGRO_KEY_F1, 10
)){
al_set_target_bitmap
(
image);
if
(
al_lock_bitmap
(
image,
al_get_bitmap_format
(
image),
ALLEGRO_LOCK_READWRITE) !=
NULL
){
int
x, y;
for
(
y =
0
; y<
ty; y++
){
for
(
x =
0
; x<
tx; x++
){
unsigned
char
r, g, b;
ALLEGRO_COLOR color;
color =
al_get_pixel
(
image, x, y);
al_unmap_rgb
(
color, &
r, &
g, &
b);
r =
(
r<
246
) ? r +
rand
(
) %
10
: 0
;
g =
(
g>
10
) ? g -
rand
(
) %
10
: 255
;
b =
(
b<
251
) ? b +
rand
(
) %
5
: 0
;
al_put_pixel
(
x, y, al_map_rgb
(
r, g, b));
}
}
al_unlock_bitmap
(
image);
al_set_target_backbuffer
(
display);
}
}
al_draw_bitmap
(
image, 0
, 0
, 0
);
al_flip_display
(
);
}
while
(!
al_key_down
(&
key, ALLEGRO_KEY_ESCAPE));
al_destroy_display
(
display);
return
0
;
}
/**
***************************************************************
****************************************************************
*/
Lors d'un appui sur [F1], dix tours se produisent. Si vous mettez en commentaire le verrouillage, vous constaterez que la lenteur est phénoménale au point de penser que ça ne marche pas. En revanche c'est instantané avec le verrouillage.
V-D-3. Mélanges de couleurs (blending)▲
Une autre fonction pixel par pixel nous amène à considérer des opérations de mélange entre couleurs.
La fonction al_put_blended_pixel :
void
al_put_blended_pixel
(
int
x, int
y, ALLEGRO_COLOR color)
Elle fonctionne comme al_put_pixel() mais au lieu qu'une couleur source remplace la couleur d'un pixel dans la bitmap cible, les deux couleurs sont mélangées. La couleur color est mélangée avec la couleur du pixel en x , y de l'image concernée (l'image cible actuellement sélectionnée avec la fonction al_set_target_bitmap() ).
Différentes options de mélange sont prévues. L'option choisie doit au préalable être sélectionnée par un appel à la fonction al_set_blender .
La fonction al_set_blender :
void
al_set_blender
(
int
mel, int
src, int
dst)
Le paramètre mel indique un type prédéfini de mélange. En fonction de ce type, la valeur de src est retenue dans une opération pour la couleur source et la valeur dest est retenue dans une opération pour la couleur de destination. Ces valeurs ne sont pas libres et les valeurs valides sont prédéfinies.
Les formules proposées qui définissent les types de mélange sont les suivantes : soit sr , sg , sb , sa pour des valeurs de rouge, vert, bleu, alpha de la couleur source et dr , dg , db , da pour des valeurs de rouge, vert, bleu, alpha de la couleur de destination. Nous avons donc :
ALLEGRO_ADD
r =
dr *
dst +
sr *
src
g =
dg *
dst +
sg *
src
b =
db *
dst +
sb *
src
a =
da *
dst +
sa *
src
ALLEGRO_DEST_MINUS_SRC
r =
dr *
dst -
sr *
src
g =
dg *
dst -
sg *
src
b =
db *
dst -
sb *
src
a =
da *
dst -
sa *
src
ALLEGRO_SRC_MINUS_DEST
r =
sr *
src -
dr *
dst
g =
sg *
src -
dg *
dst
b =
sb *
src -
db *
dst
a =
sa *
src -
da *
dst
Les valeurs valides pour src et dest sont les suivantes :
ALLEGRO_ZERO
src =
0
dst =
0
ALLEGRO_ONE
src =
1
dst =
1
ALLEGRO_ALPHA
src =
sa
dst =
sa
ALLEGRO_INVERSE_ALPHA
src =
1
-
sa
dst =
1
-
sa
ALLEGRO_SRC_COLOR
f =
s.r, s.g, s.b, s.a
ALLEGRO_DEST_COLOR
f =
d.r, d.g, d.b, d.a
ALLEGRO_INVERSE_SRC_COLOR
f =
1
-
s.r, 1
-
s.g, 1
-
s.b, 1
-
s.a
ALLEGRO_INVERSE_DEST_COLOR
f =
1
-
d.r, 1
-
d.g, 1
-
d.b, 1
-
d.a
Voici quelques exemples d'appel :
Mode par défaut :
al_set_blender
(
ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA)
Action transparence :
al_set_blender
(
ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA)
Addition :
al_set_blender
(
ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ONE)
Copier la source dans la destination :
al_set_blender
(
ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO)
Multiplier la source et la destination :
al_set_blender
(
ALLEGRO_ADD, ALLEGRO_DEST_COLOR, ALLEGRO_ZERO)
V-D-3-a. Expérimentation : al_put_blended_pixel() ▲
Le test est un peu rudimentaire mais il permet de se faire rapidement une idée. Au départ, nous avons une couleur qui va être mélangée à chaque pixel de l'image (une bitmap nommée image.bmp et qui se trouve dans le répertoire du programme). Cette couleur peut être changée en tapant la touche C. Le blender par défaut (éclaircissant) est en [F2], il peut être changé pour un blender assombrissant en [F1]. Taper [Entrée] réinitialise l'image.
Après sélection d'une opération [F1][F2] pour exécuter la transformation, il faut taper la touche [Espace].
#include <allegro5/allegro.h>
#include <allegro5/allegro_native_dialog.h>
#include <allegro5/allegro_image.h>
// remarque signe \ pour aller à la ligne dans une macro :
#define COLORALEA al_map_rgba(rand()%256,rand()%256,\
rand() % 256, rand() % 256);
void
erreur
(
const
char
*
txt)
{
ALLEGRO_DISPLAY*
d;
d =
al_is_system_installed
(
) ? al_get_current_display
(
) : NULL
;
al_show_native_message_box
(
d, "
Erreur
"
, txt, NULL
, NULL
, 0
);
exit
(
EXIT_FAILURE);
}
/**
***************************************************************
****************************************************************
*/
int
is_key_pressed
(
ALLEGRO_KEYBOARD_STATE*
key, int
touche,
int
repeat)
{
//le tableau conserve ses valeurs d'un appel à l'autre (static)
static
int
press[ALLEGRO_KEY_MAX] =
{
0
}
;
int
res =
0
;
if
(
al_key_down
(
key, touche) &&
press[touche] <
repeat){
press[touche]++
;
res =
1
;
}
else
if
(!
al_key_down
(
key, touche))
press[touche] =
0
;
return
res;
}
/**
***************************************************************
****************************************************************
*/
int
main
(
)
{
ALLEGRO_DISPLAY*
display;
ALLEGRO_KEYBOARD_STATE key;
ALLEGRO_BITMAP*
image, *
save;
int
tx, ty, scrx, scry;
ALLEGRO_COLOR color;
if
(!
al_init
(
))
erreur
(
"
al_init()
"
);
if
(!
al_install_keyboard
(
))
erreur
(
"
al_install_keyboard()
"
);
if
(!
al_init_image_addon
(
))
erreur
(
"
al_init_primitives_addon()
"
);
display =
al_create_display
(
800
, 600
);
if
(!
display)
erreur
(
"
al_create_display()
"
);
scrx =
al_get_display_width
(
display);
scry =
al_get_display_height
(
display);
image =
al_load_bitmap
(
"
image.bmp
"
);
if
(!
image)
erreur
(
"
al_load_bitmap()
"
);
save =
al_clone_bitmap
(
image);
tx =
al_get_bitmap_width
(
image);
ty =
al_get_bitmap_height
(
image);
color =
al_map_rgba
(
128
, 8
, 32
, 2
);
do
{
al_get_keyboard_state
(&
key);
// modification de l'image
if
(
is_key_pressed
(&
key, ALLEGRO_KEY_SPACE, 5
)){
al_set_target_bitmap
(
image);
if
(
al_lock_bitmap
(
image,
al_get_bitmap_format
(
image),
ALLEGRO_LOCK_READWRITE) !=
NULL
){
int
x, y;
for
(
y =
0
; y<
ty; y++
){
for
(
x =
0
; x<
tx; x++
)
al_put_blended_pixel
(
x, y, color);
}
al_unlock_bitmap
(
image);
al_set_target_backbuffer
(
display);
}
}
// changer la couleur à ajouter
if
(
is_key_pressed
(&
key, ALLEGRO_KEY_C, 1
))
color =
COLORALEA;
// SELECTION TYPE MELANGE (BLENDER)
// assombrissant
if
(
is_key_pressed
(&
key, ALLEGRO_KEY_F1, 1
))
al_set_blender
(
ALLEGRO_ADD,
ALLEGRO_ALPHA,
ALLEGRO_INVERSE_ALPHA);
// éclaircissant, mode par défaut
if
(
is_key_pressed
(&
key, ALLEGRO_KEY_F2, 1
))
al_set_blender
(
ALLEGRO_ADD,
ALLEGRO_ONE,
ALLEGRO_INVERSE_ALPHA);
// efface l'écran, recopie l'image de départ
if
(
is_key_pressed
(&
key, ALLEGRO_KEY_ENTER, 1
)){
al_clear_to_color
(
al_map_rgba
(
0
, 0
, 0
, 0
));
al_destroy_bitmap
(
image);
image =
al_clone_bitmap
(
save);
}
// affichage écran à chaque tour
al_draw_bitmap
(
image, (
scrx -
tx) /
2
, (
scry -
ty) /
2
, 0
);
al_flip_display
(
);
}
while
(!
al_key_down
(&
key, ALLEGRO_KEY_ESCAPE));
al_destroy_bitmap
(
image);
al_destroy_bitmap
(
save);
al_destroy_display
(
display);
return
0
;
}
/**
***************************************************************
****************************************************************
*/
C'est une technique qui peut être utilisée pour opérer des transitions d'une image à une autre. Par exemple prendre chaque pixel d'une image source et le mélanger à chaque pixel correspondant dans l'image de destination, les deux images étant de même dimension. On peut aussi agir juste sur une partie d'une image source ou d'une image cible.
V-E. Paramétrage des options▲
Dans les deux programmes précédents, la couleur est toujours traitée dans un mode 32 bits choisi par Allegro. Allegro est multiplateforme et il y a en effet plusieurs modes 32 bits (ils se différencient par la position des composantes et l'existence ou non du canal alpha de transparence). Après expérimentation sur notre machine, c'est le mode identifié par la constante ALLEGRO_PIXEL_FORMAT_XRGB_8888 , qui correspond au mode par défaut. Mais, le cas échéant, il peut être utile de choisir un autre format de couleur 15, 16 ou 24 bits. Pour ce faire, il faut utiliser la fonction al_set_new_display_option .
La fonction al_set_new_display_option :
void
al_set_new_display_option
(
int
option,int
value,int
importance)
Cette fonction permet de paramétrer un certain nombre d'options qui concernent l'affichage et le son pour une fenêtre display . Parmi ces options, nous nous intéressons ici uniquement à la possibilité de modifier le format de couleur. Le type d'option à modifier est indiqué en paramètre p1. Chaque option est définie par une constante. La valeur à donner à l'option est donnée en paramètre p2. En paramètre p3 est spécifié le degré de priorité voulu pour la requête. Pour modifier plusieurs options, il faut donc plusieurs appels, un par option. L'option qui nous intéresse pour la couleur est :
ALLEGRO_COLOR_SIZE
Il y a trois degrés, chacun défini par une macro constante :
ALLEGRO_REQUIRE : en principe la fenêtre display ne sera pas créée si le paramétrage n'est pas possible. Toutefois, dans notre test ci-dessous, le programme prend la valeur par défaut.
ALLEGRO_SUGGEST : si le paramétrage n'est pas possible, la fenêtre display sera créée de toute façon avec une valeur acceptable la plus proche de ce qui est demandé.
ALLEGRO_DONTCARE : avec ce degré, Allegro ne tient pas compte des éventuels paramétrages réalisés préalablement avec les deux degrés précédents. En cas d'échec, il écrase les valeurs obtenues précédemment et prend des valeurs par défaut.
V-E-1. Expérimentation ▲
Le programme ci-dessous permet de voir ce qui se passe si l'on demande un double buffer en 16 bits. Il affiche le choix fait par la machine entre les différentes possibilités de 16 bits.
En modifiant le paramètre deux pour le nombre de bits et trois pour la priorité, on constate qu'il y a peu de différence entre ALLEGRO_REQUIRE et ALLEGRO_SUGGEST , en général si la demande ne passe pas c'est la valeur par défaut ALLEGRO_PIXEL_FORMAT_XRGB_8888 qui est sélectionnée de sorte que AUTRE du case default ne sort jamais.
#include <allegro5/allegro.h>
#include <allegro5/allegro_native_dialog.h>
#include <allegro5/allegro_primitives.h>
#include <stdio.h>
void
erreur
(
const
char
*
txt)
{
ALLEGRO_DISPLAY*
d;
d =
al_is_system_installed
(
) ? al_get_current_display
(
) : NULL
;
al_show_native_message_box
(
d, "
ERREUR
"
, txt, NULL
, NULL
, 0
);
exit
(
EXIT_FAILURE);
}
/**
***************************************************************
****************************************************************
*/
int
main
(
)
{
ALLEGRO_DISPLAY*
display;
ALLEGRO_KEYBOARD_STATE key;
ALLEGRO_BITMAP*
db;
int
screenx =
800
;
int
screeny =
600
;
if
(!
al_init
(
))
erreur
(
"
al_init()
"
);
if
(!
al_install_keyboard
(
))
erreur
(
"
al_install_keyboard()
"
);
// peu de différence ici entre ALLEGRO_REQUIRE et ALLEGRO_SUGGEST
al_set_new_display_option
(
ALLEGRO_COLOR_SIZE, 16
, ALLEGRO_SUGGEST);
display =
al_create_display
(
screenx, screeny);
if
(!
display)
erreur
(
"
al_create_display()
"
);
db =
al_get_backbuffer
(
display);
int
format =
al_get_bitmap_format
(
db);
switch
(
format){
case
ALLEGRO_PIXEL_FORMAT_ANY_16_NO_ALPHA:
printf
(
"
ALLEGRO_PIXEL_FORMAT_ANY_16_NO_ALPHA
\n
"
);
break
;
case
ALLEGRO_PIXEL_FORMAT_ANY_16_WITH_ALPHA:
printf
(
"
ALLEGRO_PIXEL_FORMAT_ANY_16_WITH_ALPHA
\n
"
);
break
;
case
ALLEGRO_PIXEL_FORMAT_ARGB_4444:
printf
(
"
ALLEGRO_PIXEL_FORMAT_ARGB_4444
\n
"
);
break
;
case
ALLEGRO_PIXEL_FORMAT_RGB_565:
printf
(
"
ALLEGRO_PIXEL_FORMAT_RGB_565
\n
"
);
break
;
case
ALLEGRO_PIXEL_FORMAT_RGBA_5551:
printf
(
"
ALLEGRO_PIXEL_FORMAT_RGBA_5551
\n
"
);
break
;
case
ALLEGRO_PIXEL_FORMAT_ARGB_1555:
printf
(
"
ALLEGRO_PIXEL_FORMAT_ARGB_1555
\n
"
);
break
;
case
ALLEGRO_PIXEL_FORMAT_BGR_565:
printf
(
"
ALLEGRO_PIXEL_FORMAT_BGR_565
\n
"
);
break
;
//Mode par défaut sur notre machine
case
ALLEGRO_PIXEL_FORMAT_XRGB_8888 :
printf
(
"
ALLEGRO_PIXEL_FORMAT_XRGB_8888
\n
"
);
break
;
default
:
printf
(
"
AUTRE
\n
"
);
break
;
}
printf
(
"
valeur : %d
\n
"
, format);
do
{
al_get_keyboard_state
(&
key);
}
while
(!
al_key_down
(&
key, ALLEGRO_KEY_ESCAPE));
al_destroy_display
(
display);
return
0
;
}
Obtenir ce livre▲
Ce document est une retranscription autorisée du livre Allegro 5 - Programmation de jeux en C et C++ écrit par Frédéric DROUILLON. Initialement publié aux éditions ENI, vous pouvez commander le livre sur le site de l'éditeur. |