Nous venons d'apprendre à charger la SDL, à ouvrir une fenêtre et gérer des surfaces. C'est vraiment la base de ce qu'il faut connaître sur cette bibliothèque. Cependant, pour le moment nous ne pouvons créer que des surfaces unies, c'est-à-dire ayant la même couleur, ce qui est un peu monotone.
Dans ce chapitre, nous allons apprendre à charger des images dans des surfaces, que ce soit des BMP, des PNG, des GIF ou des JPG. La manipulation d'images est souvent très motivante car c'est en assemblant ces images (aussi appelées « sprites ») que l'on fabrique les premières briques d'un jeu vidéo.
Charger une image BMP
La SDL est une bibliothèque très simple. Elle ne propose à la base que le chargement d'images de type « bitmap » (extension.bmp
). Ne paniquez pas pour autant, car grâce à une extension de la SDL (la bibliothèqueSDL_Image
), nous verrons qu'il est possible de charger de nombreux autres types.
Pour commencer, nous allons nous contenter de ce que la SDL offre à la base. Nous allons donc étudier le chargement de BMP.
Le format BMP
Un BMP (abréviation de « Bitmap ») est un format d'image.
Les images que vous voyez sur votre ordinateur sont stockées dans des fichiers. Il existe plusieurs formats d'images, c'est-à-dire plusieurs façons de coder l'image dans un fichier. Selon le format, l'image prend plus ou moins d'espace disque et se trouve être de plus ou moins bonne qualité.
Le Bitmap est un format non compressé (contrairement aux JPG, PNG, GIF, etc.).
Concrètement, cela signifie les choses suivantes :
le fichier est très rapide à lire, contrairement aux formats compressés qui doivent être décompressés, ce qui prend un peu plus de temps ;
la qualité de l'image est parfaite. Certains formats compressés (je pense au JPG plus particulièrement, car les PNG et GIF n'altèrent pas l'image) détériorent la qualité de l'image, ce n'est pas le cas du BMP ;
mais le fichier est aussi bien plus gros puisqu'il n'est pas compressé !
Il a donc des qualités et des défauts.
Pour la SDL, l'avantage c'est que ce type de fichier est simple et rapide à lire. Si vous avez souvent besoin de charger des images au cours de l'exécution de votre programme, il vaut mieux utiliser des BMP : certes le fichier est plus gros, mais il se chargera plus vite qu'un GIF par exemple. Cela peut se révéler utile si votre programme doit charger de très nombreuses images en peu de temps.
Charger un Bitmap
Téléchargement du pack d'images
Nous allons travailler avec plusieurs images dans ce chapitre. Si vous voulez faire les tests en même temps que vous lisez (et vous devriez !), je vous recommande de télécharger un pack qui contient toutes les images dont on va avoir besoin.
Télécharger le pack d'images (1 Mo)
Bien entendu, vous pouvez utiliser vos propres images. Il faudra en revanche adapter la taille de votre fenêtre à celles-ci.
Placez toutes les images dans le dossier de votre projet. Nous allons commencer par travailler avec le fichierlac_en_montagne.bmp
. C'est une scène 3D d'exemple tirée de l'excellent logiciel de modélisation de paysages Vue d'Esprit 4, qui n'est aujourd'hui plus commercialisé. Depuis, le logiciel a été renommé en « Vue » et a beaucoup évolué. Si vous voulez en savoir plus, rendez-vous sure-onsoftware.com
.
Charger l'image dans une surface
Nous allons utiliser une fonction qui va charger l'image BMP et la mettre dans une surface.
Cette fonction a pour nomSDL_LoadBMP
. Vous allez voir à quel point c'est simple :
maSurface = SDL_LoadBMP("image.bmp");
La fonctionSDL_LoadBMP
remplace deux fonctions que vous connaissez :
SDL_CreateRGBSurface
: elle se chargeait d'allouer de la mémoire pour stocker une surface de la taille demandée (équivalent aumalloc
) ;SDL_FillRect
: elle remplissait la structure d'une couleur unie.
Pourquoi est-ce que ça remplace ces deux fonctions ? C'est très simple :
la taille à allouer en mémoire pour la surface dépend de la taille de l'image : si l'image a une taille de 250 x 300, alors votre surface aura une taille de 250 x 300 ;
d'autre part, votre surface sera remplie pixel par pixel par le contenu de votre image BMP.
Codons sans plus tarder :
int main(int argc, char *argv[])
{
SDL_Surface *ecran = NULL, *imageDeFond = NULL;
SDL_Rect positionFond;
positionFond.x = 0;
positionFond.y = 0;
SDL_Init(SDL_INIT_VIDEO);
ecran = SDL_SetVideoMode(800, 600, 32, SDL_HWSURFACE);
SDL_WM_SetCaption("Chargement d'images en SDL", NULL);
/* Chargement d'une image Bitmap dans une surface */
imageDeFond = SDL_LoadBMP("lac_en_montagne.bmp");
/* On blitte par-dessus l'écran */
SDL_BlitSurface(imageDeFond, NULL, ecran, &positionFond);
SDL_Flip(ecran);
pause();
SDL_FreeSurface(imageDeFond); /* On libère la surface */
SDL_Quit();
return EXIT_SUCCESS;
}
J'ai donc créé un pointeur vers une surface (imageDeFond
) ainsi que les coordonnées correspondantes (positionFond
).
La surface est créée en mémoire et remplie par la fonctionSDL_LoadBMP
.
On la blitte ensuite sur la surfaceecran
et c'est tout ! Admirez le résultat sur la fig. suivante.

Comme vous voyez ce n'était pas bien difficile !
Associer une icône à son application
Maintenant que nous savons charger des images, nous pouvons découvrir comment associer une icône à notre programme. L'icône sera affichée en haut à gauche de la fenêtre (ainsi que dans la barre des tâches). Pour le moment nous avons une icône par défaut.
Mais, les icônes des programmes ne sont-elles pas des.ico
, normalement ?
Non, pas forcément ! D'ailleurs les.ico
n'existent que sous Windows. La SDL réconcilie tout le monde en utilisant un système bien à elle : une surface !
Eh oui, l'icône d'un programme SDL n'est rien d'autre qu'une simple surface.
Pour ajouter l'icône à la fenêtre, on utilise la fonctionSDL_WM_SetIcon
.
Cette fonction prend deux paramètres : la surface qui contient l'image à afficher ainsi que des informations sur la transparence (NULL
si on ne veut pas de transparence). La gestion de la transparence d'une icône est un peu compliquée (il faut préciser un à un quels sont les pixels transparents), nous ne l'étudierons donc pas.
On va combiner deux fonctions en une :
SDL_WM_SetIcon(SDL_LoadBMP("sdl_icone.bmp"), NULL);
L'image est chargée en mémoire parSDL_LoadBMP
et l'adresse de la surface est directement envoyée àSDL_WM_SetIcon
.
Voici le code source complet. Vous noterez que j'ai simplement ajouté leSDL_WM_SetIcon
par rapport au code précédent :
int main(int argc, char *argv[])
{
SDL_Surface *ecran = NULL, *imageDeFond = NULL;
SDL_Rect positionFond;
positionFond.x = 0;
positionFond.y = 0;
SDL_Init(SDL_INIT_VIDEO);
/* Chargement de l'icône AVANT SDL_SetVideoMode */
SDL_WM_SetIcon(SDL_LoadBMP("sdl_icone.bmp"), NULL);
ecran = SDL_SetVideoMode(800, 600, 32, SDL_HWSURFACE);
SDL_WM_SetCaption("Chargement d'images en SDL", NULL);
imageDeFond = SDL_LoadBMP("lac_en_montagne.bmp");
SDL_BlitSurface(imageDeFond, NULL, ecran, &positionFond);
SDL_Flip(ecran);
pause();
SDL_FreeSurface(imageDeFond);
SDL_Quit();
return EXIT_SUCCESS;
}
Résultat, l'icône est chargée et affichée sur la fenêtre (fig. suivante).

Gestion de la transparence
Le problème de la transparence
Nous avons tout à l'heure chargé une image bitmap dans notre fenêtre.
Supposons que l'on veuille blitter une image par-dessus. Ça vous arrivera très fréquemment car dans un jeu, en général, le personnage que l'on déplace est un Bitmap et il se déplace sur une image de fond.
On va blitter l'image de Zozor (il s'agit de la bonne vieille mascotte du Site du Zéro pour ceux qui ne le connaîtraient pas) sur la scène :
int main(int argc, char *argv[])
{
SDL_Surface *ecran = NULL, *imageDeFond = NULL, *zozor = NULL;
SDL_Rect positionFond, positionZozor;
positionFond.x = 0;
positionFond.y = 0;
positionZozor.x = 500;
positionZozor.y = 260;
SDL_Init(SDL_INIT_VIDEO);
SDL_WM_SetIcon(SDL_LoadBMP("sdl_icone.bmp"), NULL);
ecran = SDL_SetVideoMode(800, 600, 32, SDL_HWSURFACE);
SDL_WM_SetCaption("Chargement d'images en SDL", NULL);
imageDeFond = SDL_LoadBMP("lac_en_montagne.bmp");
SDL_BlitSurface(imageDeFond, NULL, ecran, &positionFond);
/* Chargement et blittage de Zozor sur la scène */
zozor = SDL_LoadBMP("zozor.bmp");
SDL_BlitSurface(zozor, NULL, ecran, &positionZozor);
SDL_Flip(ecran);
pause();
SDL_FreeSurface(imageDeFond);
SDL_FreeSurface(zozor);
SDL_Quit();
return EXIT_SUCCESS;
}
On a juste rajouté une surface pour y stocker Zozor, que l'on blitte ensuite à un endroit sur la scène (fig. suivante).

C'est plutôt laid, non ?
Je sais pourquoi, c'est parce que tu as mis un fond bleu tout moche sur l'image de Zozor !
Parce que vous croyez qu'avec un fond noir ou un fond marron derrière Zozor, ça aurait été plus joli ? Eh bien non, le problème ici c'est que notre image est forcément rectangulaire, donc si on la colle sur la scène on voit son fond, ce qui ne rend pas très bien.
Heureusement, la SDL gère la transparence !
Rendre une image transparente
Étape 1 : préparer l'image
Pour commencer, il faut préparer l'image que vous voulez blitter sur la scène.
Le format BMP ne gère pas la transparence, contrairement aux GIF et PNG. Il va donc falloir utiliser une astuce.
Il faut mettre la même couleur de fond sur toute l'image. Celle-ci sera rendue transparente par la SDL au moment du blit. Observez à quoi ressemble monzozor.bmp
de plus près (fig. suivante).

Le fond bleu derrière est donc volontaire. Notez que j'ai choisi le bleu au hasard, j'aurais très bien pu mettre un fond vert ou rouge par exemple. Ce qui compte, c'est que cette couleur soit unique et unie. J'ai choisi le bleu parce qu'il n'y en avait pas dans l'image de Zozor. Si j'avais choisi le vert, j'aurais pris le risque que l'herbe que machouille Zozor (en bas à gauche de l'image) soit rendue transparente.
À vous donc de vous débrouiller avec votre logiciel de dessin (Paint, Photoshop, The Gimp, chacun ses goûts) pour donner un fond uni à votre image.
Étape 2 : indiquer la couleur transparente
Pour indiquer à la SDL la couleur qui doit être rendue transparente, vous devez utiliser la fonctionSDL_SetColorKey
. Cette fonction doit être appelée avant de blitter l'image.
Voici comment je m'en sers pour rendre le bleu derrière Zozor transparent :
SDL_SetColorKey(zozor, SDL_SRCCOLORKEY, SDL_MapRGB(zozor->format, 0, 0, 255));
Il y a trois paramètres :
la surface qui doit être rendue transparente (ici, c'est
zozor
) ;une liste de flags : utilisez
SDL_SRCCOLORKEY
pour activer la transparence, 0 pour la désactiver ;indiquez ensuite la couleur qui doit être rendue transparente. J'ai utilisé
SDL_MapRGB
pour créer la couleur au format nombre (Uint32
) comme on l'a déjà fait par le passé. Comme vous le voyez, c'est le bleu pur (0, 0, 255) que je rends transparent.
En résumé, on charge d'abord l'image avecSDL_LoadBMP
, on indique la couleur transparente avecSDL_SetColorKey
, puis on peut blitter avecSDL_BlitSurface
:
/* On charge l'image : */
zozor = SDL_LoadBMP("zozor.bmp");
/* On rend le bleu derrière Zozor transparent : */
SDL_SetColorKey(zozor, SDL_SRCCOLORKEY, SDL_MapRGB(zozor->format, 0, 0, 255));
/* On blitte l'image maintenant transparente sur le fond : */
SDL_BlitSurface(zozor, NULL, ecran, &positionZozor);
Résultat : Zozor est parfaitement intégré à la scène (fig. suivante) !

Voilà LA technique de base que vous réutiliserez tout le temps dans vos futurs programmes. Apprenez à bien manier la transparence car c'est fondamental pour réaliser un jeu un minimum réaliste.
La transparence Alpha
C'est un autre type de transparence.
Jusqu'ici, on se contentait de définir UNE couleur de transparence (par exemple le bleu). Cette couleur n'apparaissait pas une fois l'image blittée.
La transparence Alpha correspond à tout autre chose. Elle permet de réaliser un « mélange » entre une image et le fond. C'est une sorte de fondu.
La transparence Alpha d'une surface peut être activée par la fonctionSDL_SetAlpha
:
SDL_SetAlpha(zozor, SDL_SRCALPHA, 128);
Il y a là encore trois paramètres :
la surface en question (
zozor
) ;une liste de flags : mettez
SDL_SRCALPHA
pour activer la transparence, 0 pour la désactiver ;très important : la valeur Alpha de la transparence. C'est un nombre compris entre 0 (image totalement transparente, donc invisible) et 255 (image totalement opaque, comme s'il n'y avait pas de transparence Alpha).
Plus le nombre Alpha est petit, plus l'image est transparente et fondue.
Voici par exemple un code qui applique une transparence Alpha de 128 à notre Zozor :
zozor = SDL_LoadBMP("zozor.bmp");
SDL_SetColorKey(zozor, SDL_SRCCOLORKEY, SDL_MapRGB(zozor->format, 0, 0, 255));
/* Transparence Alpha moyenne (128) : */
SDL_SetAlpha(zozor, SDL_SRCALPHA, 128);
SDL_BlitSurface(zozor, NULL, ecran, &positionZozor);
Vous noterez que j'ai conservé la transparence deSDL_SetColorKey
. Les deux types de transparence sont en effet combinables.
La fig. suivante vous montre à quoi ressemble Zozor selon la valeur Alpha.
Alpha | Aperçu |
---|---|
255 | ![]() ![]() ![]() ![]() |
190 | ![]() ![]() ![]() ![]() |
128 | ![]() ![]() ![]() ![]() |
75 | ![]() ![]() ![]() ![]() |
0 | ![]() ![]() ![]() ![]() |
Charger plus de formats d'image avec SDL_Image
La SDL ne gère que les Bitmap (BMP) comme on l'a vu.
A priori, ce n'est pas un très gros problème parce que la lecture des BMP est rapide pour la SDL, mais il faut reconnaître qu'aujourd'hui on a plutôt l'habitude d'utiliser d'autres formats. En particulier, nous sommes habitués aux formats d'images « compressés » comme le PNG, le GIF et le JPEG. Ça tombe bien, il existe justement une bibliothèqueSDL_Image
qui gère tous les formats suivants :
TGA ;
BMP ;
PNM ;
XPM ;
XCF ;
PCX ;
GIF ;
JPG ;
TIF ;
LBM ;
PNG.
Il est en fait possible de rajouter des extensions à la SDL. Ce sont des bibliothèques qui ont besoin de la SDL pour fonctionner. On peut voir ça comme des add-ons (on emploie aussi parfois le mot « greffon », plus français).SDL_Image
est l'une d'entre elles.
InstallerSDL_image
sous Windows
Téléchargement
Une page spéciale du site de la SDL référence les bibliothèques utilisant la SDL. Cette page s'intituleLibraries
, vous trouverez un lien dans le menu de gauche.
Vous pourrez voir qu'il y a beaucoup de bibliothèques disponibles. Celles-ci ne proviennent généralement pas des auteurs de la SDL, ce sont plutôt des utilisateurs de la SDL qui proposent leurs bibliothèques pour améliorer la SDL.
Certaines sont très bonnes et méritent le détour, d'autres sont moins bonnes et encore boguées. Il faut arriver à faire le tri.
CherchezSDL_Image
dans la liste… vous arriverez sur la page dédiée àSDL_Image
.
Téléchargez la version deSDL_Image
qui vous correspond dans la sectionBinary
(ne prenez PAS la source, on n'en a pas besoin !). Si vous êtes sous Windows, téléchargezSDL_image-devel-1.2.10-VC.zip
, et ce même si vous n'utilisez pas Visual C++ !
Installation
Dans ce .zip, vous trouverez :
SDL_image.h
: le seul header dont a besoin la bibliothèqueSDL_Image
. Placez-le dansC:\Program Files\CodeBlocks\SDL-1.2.13\include
, c'est-à-dire à côté des autres headers de la SDL ;SDL_image.lib
: copiez dansC:\Program Files\CodeBlocks\SDL-1.2.13\lib
. Oui, je sais, je vous ai dit que normalement les.lib
étaient des fichiers réservés à Visual, mais ici exceptionnellement le.lib
fonctionnera même avec le compilateurmingw
;plusieurs DLL : placez-les toutes dans le dossier de votre projet (à côté de
SDL.dll
, donc).
Ensuite, vous devez modifier les options de votre projet pour « linker » avec le fichierSDL_image.lib
.
Si vous êtes sous Code::Blocks par exemple, allez dans le menuProjects / Build options
. Dans l'ongletLinker
, cliquez sur le boutonAdd
et indiquez où se trouve le fichierSDL_image.lib
(fig. suivante).

Si on vous demande Keep as a relative path?, répondez ce que vous voulez, ça ne changera rien dans l'immédiat. Je recommande de répondre par la négative, personnellement.
Ensuite, vous n'avez plus qu'à inclure le headerSDL_image.h
dans votre code source. Selon l'endroit où vous avez placé le fichierSDL_image.h
, vous devrez soit utiliser ce code :
#include <SDL/SDL_image.h>
… soit celui-ci :
#include <SDL_image.h>
Essayez les deux, l'un des deux devrait fonctionner.
InstallerSDL_image
sous Mac OS X
Si vous utilisez Mac OS X, téléchargez le fichier.dmg
sur le site de la SDL et mettez-le dans le dossier/Library/Frameworks
(/Bibliothèque/Frameworks
en français).
Ensuite, tapez « search paths » dans le champ de recherche de Xcode. Repérez la ligneHeader search paths
; double-cliquez sur la ligne à droite, et ajoutez « /Library/Frameworks/SDL_image.framework/Headers ».
Il ne vous reste plus qu'à ajouter le framework à votre projet. La figure suivante vous montre à quoi ressemble leHeader search paths
du projet après avoir installéSDL_image
.

Il faudra en revanche inclure le fichier.h
dans votre code comme ceci :
#include "SDL_image.h"
… au lieu d'utiliser des chevrons< >
. Remplacez donc la ligne d'include
deSDL_image
dans le code qui va suivre par celle que je viens de vous donner.
Charger les images
En fait, installerSDL_image
est 100 fois plus compliqué que de l'utiliser, c'est vous dire la complexité de la bibliothèque !
Il y a UNE seule fonction à connaître :IMG_Load
.
Elle prend un paramètre : le nom du fichier à ouvrir.
Ce qui est pratique, c'est que cette fonction est capable d'ouvrir tous les types de fichiers que gèreSDL_image
(GIF, PNG, JPG, mais aussi BMP, TIF…). Elle détectera toute seule le type du fichier en fonction de son extension.
Autre bon point : si l'image que vous chargez gère la transparence (comme c'est le cas des PNG et des GIF), alorsSDL_image
activera automatiquement la transparence pour cette image ! Cela vous évite donc d'avoir à appelerSDL_SetColorKey
.
Je vais vous présenter le code source qui chargesapin.png
et l'affiche.
Notez bien que j'inclueSDL/SDL_image.h
et que je ne fais pas appel àSDL_SetColorKey
car mon PNG est naturellement transparent.
Vous allez voir que j'utiliseIMG_Load
partout dans ce code en remplacement deSDL_LoadBMP
.
#include <stdlib.h>
#include <stdio.h>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h> /* Inclusion du header de SDL_image (adapter le dossier au besoin) */
void pause();
int main(int argc, char *argv[])
{
SDL_Surface *ecran = NULL, *imageDeFond = NULL, *sapin = NULL;
SDL_Rect positionFond, positionSapin;
positionFond.x = 0;
positionFond.y = 0;
positionSapin.x = 500;
positionSapin.y = 260;
SDL_Init(SDL_INIT_VIDEO);
SDL_WM_SetIcon(IMG_Load("sdl_icone.bmp"), NULL);
ecran = SDL_SetVideoMode(800, 600, 32, SDL_HWSURFACE);
SDL_WM_SetCaption("Chargement d'images en SDL", NULL);
imageDeFond = IMG_Load("lac_en_montagne.bmp");
SDL_BlitSurface(imageDeFond, NULL, ecran, &positionFond);
/* Chargement d'un PNG avec IMG_Load
Celui-ci est automatiquement rendu transparent car les informations de
transparence sont codées à l'intérieur du fichier PNG */
sapin = IMG_Load("sapin.png");
SDL_BlitSurface(sapin, NULL, ecran, &positionSapin);
SDL_Flip(ecran);
pause();
SDL_FreeSurface(imageDeFond);
SDL_FreeSurface(sapin);
SDL_Quit();
return EXIT_SUCCESS;
}
void pause()
{
int continuer = 1;
SDL_Event event;
while (continuer)
{
SDL_WaitEvent(&event);
switch(event.type)
{
case SDL_QUIT:
continuer = 0;
}
}
}
Comme on peut le voir sur la fig. suivante, l'image PNG a été insérée avec la transparence sur l'image de fond !

En résumé
La SDL permet de charger des images dans des surfaces. Par défaut, elle ne gère que les BMP avec
SDL_LoadBMP
.On peut définir une couleur transparente avec
SDL_SetColorKey
.On peut rendre l'ensemble de l'image plus ou moins transparent avec la fonction
SDL_SetAlpha
.La bibliothèque
SDL_image
permet d'insérer n'importe quel type d'image (PNG, JPEG…) avecIMG_Load
. Il faut cependant l'installer en plus de la SDL.