Génération d'images avec PHP |
|
La librairie
graphique |
Sous Windows, la librairie graphique
se nomme "php_gd.dll". Elle permet de
manipuler des images au format PNG, JPEG, WBMP et SWF.
- Le format Gif a été abandonné pour des
raisons de copyright. Par contre, le PNG le
remplace avantageusement, prenant en charge les couleurs 8 bits et, ce qui est plus important, 24 bits. Une image PNG 24
bits préservera la netteté du
dessin et la transparence du fond
(Gif), ainsi que la subtilité des couleurs
(Jpeg), sans perte de données.
- Le format JPEG est le plus utilisé sur
le Web, pour son taux de compression élévé (avec
perte de données).
- Le format WBMP est particulier au
WAP.
- Le format SWF nécessite le plug-in Flash.
|
Installation et
configuration |
La librairie php_gd.dll se trouve
dans le package complet de PHP 4. Vous
pouvez télécharger la dernière version de GD ici. Pour charger automatiquement la dll, enlevez simplement le ";" en début de ligne dans le fichier php.ini (le fichier de configuration de PHP, situé
dans WINNT ou Windows), section "Dynamic
Extensions". Assurez-vous également que le chemin du répertoire
contenant la dll est correct, dans la section "Paths and Directories", ex : "extension_dir =
C:\php\extensions"
|
Rééchantillonnage d'une image |
Une des utilisations les plus interessantes de GD est le rééchantillonnage d'images. Dans cet exemple, nous
allons retailler une image JPEG à 50% de sa taille
originale. Le principe est le suivant :
- créer une image noire en vraies couleurs de la taille de l'image de
destination
- copier et rééchantillonner les pixels de l'image originale
- générer l'image dans le flux de sortie standard (navigateur)
<?
Header("Content-type: image/jpeg");
$src_im = ImageCreateFromJpeg("palmier.jpg");
$src_w = imageSX($src_im);
$src_h = imageSY($src_im);
$dst_w = floor($src_w * 0.5);
$dst_h = floor($src_h * 0.5);
/* ImageCreateTrueColor crée une image noire en vraie couleurs */
$dst_im = ImageCreateTrueColor($dst_w,$dst_h);
/* ImageCopyResampled copie et rééchantillonne l'image originale*/
ImageCopyResampled($dst_im,$src_im,0,0,0,0,$dst_w,$dst_h,$src_w,$src_h);
/* ImageJpeg génère l'image dans la sortie standard (c.à.d le navigateur).
Le second paramètre est optionnel ; dans ce cas, l'image est générée dans un fichier*/
ImageJpeg($dst_im);
ImageDestroy($dst_im);
imageDestroy($src_im);
?>
Si vous souhaitez contraindre le rééchantillonnage à une valeur fixe en
hauteur ou en largeur, vous pouvez procéder ainsi :
<?
$size = GetImageSize("palmier.jpg"); $src_w = $size[0]; $src_h = $size[1]; $dst_w = 150; // Contraint le rééchantillonage à une largeur fixe $dst_h = round(($dst_w / $src_w) * $src_h); // Maintient le ratio de l'image
?>
|
Mode Batch |
Pour utiliser cet exemple en mode
batch (traitement par lots), il
suffit de modifier le script pour en faire une fonction. On parcourt
ensuite le répertoire contenant les images originales, et, à chaque image
Jpeg rencontrée, on appelle la fonction redim() en lui passant en second argument le
répertoire de destination.
<?
function redim($im_src,$im_dest) {
$size = GetImageSize($im_src);
$src_w = $size[0];
$src_h = $size[1];
$dst_w = floor($src_w * 0.5);
$dst_h = floor($src_h * 0.5);
$dst_im = ImageCreateTrueColor($dst_w,$dst_h);
$src_im = ImageCreateFromJpeg($im_src);
ImageCopyResampled($dst_im,$src_im,0,0,0,0,$dst_w,$dst_h,$src_w,$src_h);
ImageJpeg($dst_im,$im_dest);
ImageDestroy($dst_im);
imageDestroy($src_im);
}
$dst_dir = "thumbnails"; // le répertoire qui stockera les images redimensionnées
if(!file_exists($dst_dir))
mkdir($dst_dir,0700); // crée le répertoire s'il n'existe pas
$src_dir = ".";
$dir = opendir($src_dir);
while($im = readdir($dir))
{
// ne prend que les images Jpeg
if(strtolower(substr($im)),-3) == "jpg" || strtolower(substr($im,-4)) == "jpeg") {
redim($im,$dst_dir."/50_".$im); // préfixe le nom des images avec "50_"
$i++;
}
}
closedir($dir);
?>
|
Dessin d'une
chaîne de caractères |
GD ne sert pas seulement à redimensionner des images, mais permet
de manipuler du texte. GD écrit le texte soit avec une police par défaut
(bitmap), soit une police TrueType ou PostScript. La fonction ImageString est utilisée pour écrire du texte
bitmap sur une image. L'exemple suivant crée
une image qui s'adapte en fonction de la dimension du texte.
<?
$texte = "Ecriture de texte bitmap avec GD...";
$font_size = 3;
/* Calcule la longueur du texte en pixels */
$font_width = strlen($texte) * ImageFontWidth($font_size);
/* Calcule la hauteur du texte en pixels */
$font_height = ImageFontHeight($font_size);
/* Crée une image de la dimension du texte */
$image = ImageCreate($font_width,$font_height);
/* ImageColorAllocate alloue un fond blanc à l'image */
$white = ImageColorAllocate($image,255,255,255);
/* Définit la couleur du texte */
$black = ImageColorAllocate($image,0,0,0);
/* ImageString écrit le texte dans l'image */
ImageString($image,$font_size,0,0,$texte,$black);
Imagepng($image,"texte_bmp.png");
ImageDestroy($image);
?>
Comme vous pouvez le constater, le texte n'est pas anti-aliasé (lissé) ; de plus, vous n'avez pas
vraiment le choix de la police. Le second exemple vous montre comment
utiliser une police TrueType de votre choix,
ici arial bold italique (que vous pouvez télécharger
pour tester l'exemple). La fonction ImageTtfBBox retourne un tableau de 8 éléments
contenant les coordonnées du rectangle qui entoure le texte, ce qui permet
d'en calculer les dimensions en pixels. Le texte est tracé avec la
fonction ImageTtfText, qui, contrairement à
ImageString vue plus haut, prend pour
origine le coin inférieur gauche du premier caractère (la ligne de
base).
Note
: pour cette raison, certaines polices de
caractère possédant un jambage
important peuvent être coupées à l'affichage. Si
le cas se produit, vous devrez faire des essais en augmentant la hauteur
de l'image. GD ne possède malheureusement pas de méthode permettant de
calculer les valeurs entre la ligne de base et les parties supérieures ou
inférieures de lettres comme "p" ou "b", comme en Java par
exemple.
<?
$corps = 30;
/* Le chemin du fichier de police True Type */
$font = "/WINNT/fonts/arialbi.ttf";
$texte = "Texte TrueType";
/* ImageTtfBBox retourne les dimensions du texte */
$size =ImageTtfBBox($corps,0,$font,$texte);
$dx = abs($size[2]-$size[0]);
$dy = abs($size[5]-$size[3]);
$xpad=10; $ypad=10;
$im = ImageCreate($dx+$xpad,$dy+$ypad);
$fond = ImageColorAllocate($im,255,255,255);
$couleur = ImageColorAllocate($im,255,210,100);
/* ImageTtfText dessine le texte en partant de la ligne de base du premier caractère */
ImageTtfText($im,$corps,0,(int)($xpad/2),$dy-(int)($ypad/2),$couleur,$font,$texte);
ImagePng($im,"texte_truetype.png");
ImageDestroy($im);
?>
|
Tracés |
Avec GD, vous pouvez également tracer des lignes et tout type de
figure géométrique. Ces fonctions sont très utiles pour la génération
dynamique de graphiques. Voici un exemple simple d'utilisation de la
fonction ImageArc, qui sert habituellement à
dessiner des graphiques de type camembert. Le code suivant crée un
masque circulaire dans une image Jpeg. La fonction ImageArc trace des arcs d'ellipse. Puisque nous
souhaitons dessiner un cercle, la hauteur et la largeur de l'ellipse
devront être identiques, tandis que les valeurs de début et de fin de
l'arc seront respectivement 0° et 360 °. Nous utilisons ensuite la
fonction ImageFillToBorder pour remplir la
région de l'image limitée par la couleur de contour du cercle (noir).
<?
$image = imagecreatefromjpeg("palmier.jpg");
$largeur = imageSX($image); $hauteur = imageSY($image);
$centre_w = $largeur / 2; $centre_h = $hauteur / 2;
$diametre = round(min($largeur,$hauteur) / 2);
$noir = imagecolorallocate($image, 0, 0, 0);
imagearc($image, $centre_w, $centre_h, $diametre, $diametre, 0, 360, $noir);
imagefilltoborder($image, 0, 0, $noir, $noir);
$dst_im = imagecreatetruecolor($diametre,$diametre);
imagecopy($dst_im,$image,0,0,$centre_w - (int)($diametre / 2),
$centre_h - (int)($diametre / 2),$diametre,$diametre);
imagejpeg($dst_im,"masque.jpg");
ImageDestroy($image);
ImageDestroy($dst_im);
?>
|
Transparence |
Comme le format GIF, le PNG prend en charge la transparence. Dans cette section, nous ne
traiterons de la transparence que pour les images en mode couleurs indexées (8 bits). Dans ce mode,
chaque pixel peut contenir jusqu'à 256
couleurs (les 2 couleurs, noir et blanc, du mode bitmap élevées à
la puissance 8). Une table des couleurs,
située dans l'en-tête du fichier, comprend les références RVB des 256 couleurs qui composent
l'image. A chaque pixel de l'image est attribué un de ces
numéros.
Reprenons la chaine de texte que nous avons dessinée plus
haut (avec une police true type). Nous allons changer la couleur de fond
de l'image sans toucher au texte. Ensuite, nous rendrons la couleur du
texte transparente afin de créer un masque avec la photo du palmier. En
mode couleurs indexées, il faut procéder en 2 étapes :
- retrouver la référence de la couleur
que nous souhaitons modifier ou rendre transparente
- attribuer de nouvelles valeurs RVB à
cette couleur
La fonction ImageColorAt permet de retrouver
l'index de la couleur d'un pixel. ImageColorSet attribue une couleur à l'index
identifié par ImageColorAt, tandis qu'ImageColorTransparent rend transparente la couleur
indexée.
Note : le texte a été
dessiné sans anti-aliasing pour permettre un détourage plus net. Pour
désactiver l'anti-aliasing, donnez un identifiant de couleur négatif à la
fonction ImageTtfText.
<?
$image = ImageCreateFromPng("texte_truetype.png");
/* ImageColorAt retourne l'index de la couleur du pixel situé aux coordonnées (x, y) 0, 0 */
$color = ImageColorAt($image,0,0);
/* ImageColorSet fixe une couleur à l'index identifié par ImageColorAt */
ImageColorSet ($image, $color, 0, 130, 255);
Imagepng($image,"fond_couleur.png");
ImageDestroy($image);
?>
<?
$texte = ImageCreateFromPng("texte_truetype.png");
$image = ImageCreateFromPng("palmier.png");
$largeur_texte = imageSX($texte);
$hauteur_texte = imageSY($texte);
$largeur_image = imageSX($image);
$hauteur_image = imageSY($image);
$coord_x = floor(($largeur_image - $largeur_texte) / 2);
$coord_y = floor(($hauteur_image - $hauteur_texte) / 2);
$index = imagecolorexact($texte,255,210,100);
ImageColorTransparent($texte,$index);
imagecopy($image, $texte, $coord_x, $coord_y, 0, 0, $largeur_image, $hauteur_image);
imagecopy($texte, $image, 0, 0,$coord_x,$coord_y,$largeur_image, $hauteur_image);
imagepng($texte,"texte_transparent.png");
ImageDestroy($texte);
ImageDestroy($image);
?>
|
Effets |
En allant plus loin avec les fonctions
d'images à palette, vous pouvez créer des effets intéressants. La
fonction ImageCopyMerge fusionne deux
images, ce qui donne un effet de transparence au fond blanc :
<?
...
/* ImageCopyMerge fonctionne exactement comme ImageCopy, mais ajoute un paramètre*/
imagecopymerge($image, $texte, $coord_x, $coord_y, 0, 0, $largeur_image, $hauteur_image, 60);
...
?>
L'exemple suivant simule une image en niveaux de gris en modifiant les valeurs RVB des index de la table des couleurs :
<?
$im = imageCreateFromPNG("palmier.png");
for($i=0;$i<imagecolorstotal ($im);$i++)
{
$color = ImageColorsForIndex($im,$i);
$rvb=.299 * ($color['red'])+ .587 * ($color['green'])+ .114 * ($color['blue']);
ImageColorSet($im, $i, $rvb, $rvb, $rvb);
} imagePNG($im,"noir_et_blanc.png");
ImageDestroy($im);
?>
Toujours avec la même méthode, il est possible de coloriser l'image :
<?
...
$rouge=.299 * ($color['red'])+ .587 * ($color['green'])+ .114 * ($color['blue']); $vert=.299 * ($color['red'])+ .587 * ($color['green'])+ .114 * ($color['blue']); $bleu=.100 * ($color['red'])+ .100 * ($color['green'])+ .100 * ($color['blue']); ImageColorSet($im, $i, $rouge, $vert, $bleu);
...
?>
|
|