PHP Et GD

Transcription

PHP Et GD
Conservatoire National des Arts et Métiers
FOD Ile de France
UE NFA054
PHP
Et
GD
22 février 2006
Version
Auteur
22 février 2006 Florent Brusciano
Commentaires
Version Initiale
Tous droits réservés.
Ce document est un support de cours à l'usage exclusif des auditeurs du Cnam dans le cadre de leur
formation. Tout autre usage est interdit sans l'autorisation écrite de l’auteur.
PHP et GD 1
SOMMAIRE
1 Introduction ______________________________________________________________ 3
1.1 Présentation ____________________________________________________________ 3
1.2 Vérification de la configuration_____________________________________________ 3
1.3 Installation de GD _______________________________________________________ 3
2 Les premiers pas __________________________________________________________ 4
2.1 La première image _______________________________________________________ 4
2.2 Sauvegarder l’image sur le disque dur _______________________________________ 6
3 Manipuler les images ______________________________________________________ 7
3.1 Obtenir des informations __________________________________________________ 7
3.2 L’ouverture d’une image __________________________________________________ 9
3.3 Redimensionner une image ________________________________________________ 9
3.4 Fusion de deux images___________________________________________________ 11
4 Le dessin _______________________________________________________________ 13
4.1 Manipuler les couleurs___________________________________________________ 13
4.2 Manipuler les formes ____________________________________________________ 14
4.3 Manipuler les textes _____________________________________________________ 18
5 Utilisation des fonctions dynamiques _________________________________________ 19
6 Pour aller plus loin _______________________________________________________ 20
PHP et GD 2
1 Introduction
1.1 Présentation
La librairie GD permet de créer dynamiquement des images aux formats GIF, JPEG et PNG
notamment. Elle est écrite en C (ANSI) et peut être utilisée en PHP. Le site de référence de
la librairie est : http://www.boutell.com/gd/.
Il y a de fortes chances que GD soit utilisable après une installation par défaut, sous Unix
comme sous Windows.
GD est particulièrement intéressante pour réaliser des graphes, en liaison avec une base de
données. Mais d’autres utilisations sont envisageables :
- Génération d’images aléatoire pour l’inscription d’un compte.
- Création de miniatures par exemple pour la création d’une galerie d’image.
- Création de graphique pour les statistiques.
- Génération de bannières.
- Génération de menus dynamiques.
- Compteur de visites.
1.2 Vérification de la configuration
GD est une librairie. C'est à dire que c'est un élément en plus que l'on va donner à PHP.
Depuis PHP 4.3, une version de GD est incluse dans la distribution. Pour savoir quelles
versions vous possédez, créez ce fichier à la racine de votre serveur et lancez le. Si vous
obtenez le message d'erreur, reportez vous à la section installation sinon, vous pouvez
commencer.
1.3 Installation de GD
Sous EasyPHP ou WAMP5, allez dans le dossier où est installé le logiciel et entrez dans le
dossier "apache". Editez le fichier php.ini avec bloc note. Recherchez l’instruction
« extension=php_gd2.dll » et décommentez là en supprimant le point virgule du début de
ligne.
Ligne à
décommenter
PHP et GD 3
Il faut redémarrer le serveur pour que les modifications soient prises en considération.
Pour vérifier que GD est bien disponible, lancez un phpinfo().
Vous devez obtenir les informations suivantes :
2 Les premiers pas
2.1 La première image
Il existe plusieurs fonctions pour créer une image. La première est imagecreate. Cette
fonction créé une image limitée à un maximum de 255 couleurs avec un canal alpha
(transparence). C'est donc une image plus légère mais limitée dans le nombre de couleurs
disponibles. Nous allons nous intéresser à imagecreatetruecolor qui créé une image en
vraies couleurs (24 bits).
Pour la création d’une image vide, nous allons utiliser trois fonctions :
- imagecreatetruecolor(…) qui créé une image 24 bits.
- imagepng(…) qui renvoie une image au navigateur au format PNG.
- imagedestroy(…) qui détruit l'image, libérant ainsi de la mémoire.
Attention, dans notre exemple l’image est retournée au navigateur sous la forme d’un flux de
données. Il faut spécifier au navigateur que les données qu’il affiche sont une image au
format PNG. Les en-têtes de la page doivent être modifiées en utilisant la fonction header
de PHP. Plusieurs en-têtes) sont disponibles pour les images :
- header("Content-type: image/png"); //format png
- header("Content-type: image/jpeg"); //format jpg
- header("Content-type: image/gif"); //format gif
- header("Content-type: image/psd"); //format psd *
- header("Content-type: image/bmp"); //format bmp
- header("Content-type: image/tiff"); //format tiff *
- header("Content-type: image/jp2"); //format jp2 *
- header("Content-type: image/iff"); //format iff *
- header("Content-type: image/vnd.wap.wbmp"); //format wbmp *
- header("Content-type: image/xbm");
- header("Content-type: application/x-shockwave-flash"); //animation flash *
PHP et GD 4
* Les librairies correspondantes doivent être installées.
En visualisant à nouveau le fichier dans votre navigateur, vous devez apercevoir un
rectangle noir. GD attribue automatiquement la couleur noire sur toute l'image si aucune
autre fonction n’est appliquée.
<?php
// Changement des en-têtes
header("Content-type: image/png");
// Largeur de l'image en pixel
$width = 50;
// Hauteur de mon image en pixel
$height = 50;
// Création de l'image en vraies couleurs
$image = imagecreatetruecolor($width, $height);
// Renvoie de l'image au format PNG vers le navigateur
imagepng($image);
// Destruction de l'image et libération de la mémoire
imagedestroy($image);
?>
PHP et GD 5
2.2 Sauvegarder l’image sur le disque dur
Il est possible à l’aide de GD d’afficher une image dans un navigateur. Mais on peut aussi
enregistrer une image sur le disque. Voici la liste des fonctions permettant d'afficher et/ou
d’enregistrer des images :
-
imagepng($image);
imagejpeg($image);
imagegd($image);
imagegd2($image);
imagegif($image);
imagewbmp($image);
imagexbm($image);
Toutes ces fonctions peuvent prendre un argument supplémentaire. Ce second argument est
le chemin vers le fichier dans lequel sera enregistré l'image. N’oubliez pas, vous devez avoir
les droits d'écriture dans le répertoire dans lequel vous sauvegardez l’image.
<?php
// Largeur de l'image en pixel
$width = 50;
// Hauteur de mon image en pixel
$height = 50;
// Création de l'image en vraies couleurs
$image = imagecreatetruecolor($width,$height);
// Création dans le répertoire images
// d'une image appelée first.png
imagepng($image, 'images/first.png');
// Destruction de l'image et libération de la mémoire
imagedestroy($image);
echo "L'enregistrement de l'image est terminée.<br/>";
echo '<img src="images/first.png"/>';
?>
PHP et GD 6
3 Manipuler les images
GD sait manipuler les images. C'est utile si on souhaite créer un album photo avec des
vignettes par exemple sans prendre chaque photo et les réduire manuellement pour créer
les vignettes. D’autres exemples de traitement d’images sont envisageables. D’une manière
générale, la manipulation d’images avec GD intervient pour supprimer les taches répétitives
sur un lot d’images.
3.1 Obtenir des informations
Il est souvent utile de connaître les dimensions d'une image. Par exemple, c'est utile si on
veut limiter la taille d'une image uploadée. La fonction getimagesize permet d’obtenir des
informations générales sur l'image en renvoyant un tableau.
$details = getimagesize($file);
Voici le contenu du tableau $details :
-
$details[0] = largeur
$details[1] = hauteur
$details[2] = type d'image
$details[3] = ligne à mettre dans la balise <img> (height=x width=y)
Le type d'image cité ci-dessus est un chiffre. Voici la liste des correspondances :
-
1 = GIF
2 = JPG
3 = PNG
4 = SWF
5 = PSD
6 = BMP
7 = TIFF (INTEL®)
8 = TIFF (MOTOROLA®)
9 = JPC
10 = JP2
11 = JPX
12 = JB2
13 = SWC
14 = IFF
Cette fonction fait partie de PHP. Il n'y a pas besoin de GD pour l'utiliser mais il est important
de signaler son existence ici.
<?php
// Récupération des infos sur l'image grâce à la fonction PHP
$infos = getimagesize('images/logo.gif');
// Affichage des informations
echo "Informations :
<li>Largeur de ".$infos[0]."px</li>
<li>Hauteur de ".$infos[1]."px</li>
<li>Type ".image_type_to_mime_type($infos[2])."</li>
<li>Suplément ".$infos[3]."</li>";
?>
PHP et GD 7
La fonction image_type_to_mime_type permet de connaître le format du fichier grâce au
troisième champ du tableau qu'a renvoyé la fonction getimagesize.
Avec GD, on doit obligatoirement ouvrir l'image et l'assigner à une variable alors qu'avec
getimagesize, on n'a pas besoin de l'attribuer à une variable. Avec GD, on ne peut obtenir
que les dimensions grâce aux fonctions imagesx et imagesy.
<?php
// Création de l'image
$image = imagecreatefromgif('images/logo.gif');
// Récupération de la largeur
$width = imagesx($image);
// Récupération de la hauteur
$height = imagesy($image);
// Destruction de l'image
imagedestroy($image);
echo "L'image a une largeur de $width px et une hauteur de $height px";
?>
Après étude de ces deux exemples, on s’aperçoit que l’utilisation de getimagesize est plus
simple et plus conviviale. Avec GD, on doit faire plus de manipulations alors qu'une seule
fonction suffit en PHP. Il est donc conseillé d'utiliser getimagesize.
PHP et GD 8
3.2 L’ouverture d’une image
Pour manipuler une image, il faut d'abord l'ouvrir. GD est pourvu d’une batterie de fonctions
permettant de récupérer le contenu d’une image. Seul inconvénient, il faut connaître
l'extension du fichier.
Les fonctions d’ouvertures sont :
- imagecreatefromgd2($file);
ouvre un fichier gd2
- imagecreatefromgd2part($file); ouvre une partie d'un fichier gd2
- imagecreatefromgd($file);
ouvre un fichier gd
- imagecreatefromgif($file);
ouvre un fichier gif
- imagecreatefromjpeg($file);
ouvre un fichier jpeg
- imagecreatefrompng($file);
ouvre un fichier png
- imagecreatefromwbmp($file); ouvre un fichier wbmp
- imagecreatefromxbm($file);
ouvre un fichier xbm
- imagecreatefromxpm($file);
ouvre un fichier xpm
Les fonctions ont toutes le même comportement, elles ne reçoivent qu'un unique argument :
le chemin de l'image avec son nom.
Voici un exemple simple d’ouverture d’une image.
<?php
// Modification des en-têtes
header('Content-type: image/gif');
// Ouverture de l'image gif
$image = imagecreatefromgif('images/logo.gif');
// Envoie vers le navigateur
imagegif($image);
// Destruction de l'image
imagedestroy($image);
?>
3.3 Redimensionner une image
Afin de créer un album photo pratique, vous aurez sans doute besoin de créer des vignettes.
Il existe deux fonctions pour réduire les images.
La première est : bool imagecopyresized($image_dest, $image_src, $dest_x, $dest_y,
$src_x, $src_y, $dest_largeur, $dest_hauteur, $src_largeur, $src_hauteur);
La seconde fonction est : bool imagecopyresampled ( resource dst_image, resource
src_image, int dst_x, int dst_y, int src_x, int src_y, int dst_w, int dst_h, int src_w, int src_h )
Pour une explication des 6 premiers arguments, reportez vous aux sections précédentes.
$dest_largeur et $dest_hauteur sont les dimensions en pixels de la zone recopiée sur la
destination. $src_largeur et $src_hauteur sont les dimensions en pixels de la zone à recopier
à partir de la source.
PHP et GD 9
<?php
header('Content-type: image/jpeg');
$ratio = 2;
// Calcul des nouvelles dimensions
list($largeur, $hauteur) = getimagesize("images/logo.gif"); //list est un
moyen plus pratique pour ne récupérer que ce qu'on veut
$n_largeur = $largeur * $ratio;
$n_hauteur = $hauteur * $ratio;
// Création de l'image de destination
$destination1 = imagecreatetruecolor($n_largeur, $n_hauteur);
$destination2 = imagecreatetruecolor($n_largeur, $n_hauteur);
// Ouverture de l'image source
$source = imagecreatefromgif("images/logo.gif");
// Redimensionnement
imagecopyresized($destination1, $source, 0, 0, 0, 0, $n_largeur,
$n_hauteur, $largeur, $hauteur);
imagecopyresampled($destination2, $source, 0, 0, 0, 0, $n_largeur,
$n_hauteur, $largeur, $hauteur);
imagegif($destination1, 'images/big-logo1.gif');
imagegif($destination2, 'images/big-logo2.gif');
imagedestroy($destination1);
imagedestroy($destination2);
imagedestroy($source);
echo '<img src="images/big-logo1.gif" />
<br/>
<img src="images/big-logo2.gif" />';
?>
L'image est réduite mais assombrie et le texte est moins joli. Le plus simple maintenant est
de rééchantilloner l'image. On doit donc utiliser l'autre fonction : imagecopyresampled. Elle
s'emploie exactement comme imagecopyresized mais donne de bien meilleur résultat.
PHP et GD 10
3.4 Fusion de deux images
GD permet d’ajouter une image à une autre image. C'est particulièrement utile pour placer
votre logo ou votre signature afin de mentionner qu'une image vous appartient. Plusieurs
fonctions sont disponibles. La première copie simplement l'image.
bool imagecopy ( resource dst_im, resource src_im, int dst_x, int dst_y, int src_x, int src_y,
int src_w, int src_h )
Copie une partie de l'image src_im sur l'image de destination dst_im, en commençant aux
coordonnées src_x, src_y et sur la largeur de src_w et la hauteur de src_h. La portion ainsi
définie sera copiée et placée aux coordonnées dst_x et dst_y.
Cette fonction ne s'occupe pas de la transparence. Ce n'est pas grâce à elle que l'on peut
fondre deux images. Pour fondre deux images, on utilise imagecopymerge.
bool imagecopymerge ( resource dst_im, resource src_im, int dst_x, int dst_y, int src_x, int
src_y, int src_w, int src_h, int pct )
Le seul argument qui diffère de la première fonction est pct. C'est la valeur entière de fusion
comprise entre 0 et 100. Si pct = 0, aucune action n'est faite, alors que si pct = 100,
imagecopymerge() se comporte exactement comme imagecopy() pour les images de
palette, tandis qu'il implémente la transparence alpha pour les images en couleur vraies.
PHP et GD 11
<?php
function superpose($img_src, $img_cop){
$image_type = array( 1 => "GIF", 2 => "JPEG", 3 => "PNG", 4 => "SWF", 5
=> "PSD", 6 => "BMP",
7 => "TIFF", 8 => "TIFF", 9 => "JPC", 10 => "JP2", 11
=> "JPX", 12 => "JB2",
13 => "SWC", 14 => "IFF");
$info_src = getimagesize($img_src);
$info_cop = getimagesize($img_cop);
$type_src = $image_type[$info_src[2]];
$type_cop = $image_type[$info_cop[2]];
$f1_src = "ImageCreateFrom".$type_src;
$f1_cop = "ImageCreateFrom".$type_cop;
$f2 = "Image".$type_src;
$i_src = $f1_src($img_src);
$i_cop = $f1_cop($img_cop);
if ($i_src && $i_cop){
$w_src = $info_src[0];
$h_src = $info_src[1];
$w_cop = $info_cop[0];
$h_cop = $info_cop[1];
$x = 0;
$y = 0;
// on place le copyright en bas à droite de l'image
$x = $w_src - $w_cop;
$y = $h_src - $h_cop;
// réalisation de la superposition
imagecopymerge($i_src, $i_cop, $x, $y, 0, 0, $w_cop, $h_cop, 100);
$name = substr($img_src, 0, strrpos($img_src,"."));
$extension = substr($img_src, strrpos($img_src,"."));
// création de l'image finale
$f2($i_src, $name."_copyright".$extension, 100);
// libération de la mémoire
imagedestroy($i_src);
imagedestroy($i_cop);
}
}
superpose('images/tux.jpg', 'images/sig_noir.gif');
?>
PHP et GD 12
4 Le dessin
GD sait dessiner des formes basiques tel que les lignes, les carrés, les cercles, les
polygones. GD ne travaille qu'en 2D, il n'y a pas de troisième dimension. Pour commencer à
dessiner, il faut connaître le système de coordonnées de GD. Pour GD, l'origine du carré est
en haut à gauche. L'axe horizontal est l'axe des abscisses (x) et l'axe vertical est l'axe des
ordonnées (y).
0,0
X
Y
Nous allons manipuler un certain nombre de ces fonctions afin de réaliser des formes
simples.
4.1 Manipuler les couleurs
Commençons par créer une couleur. La fonction imagecolorallocate n'accepte que des
valeurs en RVB (Rouge, Vert, Bleu). Les valeurs peuvent êtres saisies soit en hexadécimal
soit à l’aide d’entiers compris entre 0 et 255.
Créons un bleu fréquemment utilisé par un éditeur de logiciel célèbre. Son code hexadécimal
est #0066FF. Voici la séparation en trois canaux : Rouge = 0 ou 0x00, Vert = 102 ou 0x66,
Bleu = 255 ou 0xFF.
Les logiciels de dessins habituels donnent les deux valeurs en même temps lors d’une
sélection de couleur. Voici le code permettant de créer la couleur :
<?php
// Changement des en-têtes
header("Content-type: image/jpeg");
// Largeur et hauteur de l'image en pixel
$width = 300;
$height = 100;
// Création de l'image en vraies couleurs
$image = imagecreatetruecolor($width, $height);
$bleu = imagecolorallocate($image, 0, 102, 255);
//$bleu = imagecolorallocate($im, 0x00, 0x66, 0xff);
// Remplissage de l'image avec la couleur
imagefill($image,0,0,$bleu);
// Renvoie de l'image au format JPG vers le navigateur
imagejpeg($image);
// Destruction de l'image et libération de la mémoire
imagedestroy($image);
?>
PHP et GD 13
4.2 Manipuler les formes
Les formes de base sont disponibles dans GD. Les fonctions sont simple à utilisées et
fonctionnes toutes sur le même prototype de base : fonction (image, coordonnées, couleur).
Pour créer des formes complexes, il faut marier les différentes formes de bases.
4.2.1 Créer des lignes
<?php
// Changement des en-têtes
header("Content-type: image/jpeg");
// Largeur de l'image en pixel
$width = 300;
// Hauteur de mon image en pixel
$height = 100;
// Création de l'image en vraies couleurs
$image = imagecreatetruecolor($width, $height);
$bleu = imagecolorallocate($image, 0, 102, 255);
// Création d'une suite de lignes avec la couleur bleu
for($i = 10; $i < 300 ; $i+=10) {
imageline($image, $i, 10, 45, 90, $bleu);
}
// Renvoie de l'image au format JPG vers le navigateur
imagejpeg($image);
// Destruction de l'image et libération de la mémoire
imagedestroy($image);
?>
PHP et GD 14
4.2.1 Créer des rectangles
<?php
// Changement des en-têtes
header("Content-type: image/jpeg");
// Largeur de l'image en pixel
$width = 300;
// Hauteur de mon image en pixel
$height = 100;
// Création de l'image en vraies couleurs
$image = imagecreatetruecolor($width, $height);
$bleu = imagecolorallocate($image, 0, 102, 255);
// Création d'une suite de rectangle avec la couleur bleu
for($i = 10; $i < 300 ; $i+=30) {
imagerectangle($image, $i, 10, 40, 90, $bleu);
}
// Renvoie de l'image au format JPG vers le navigateur
imagejpeg($image);
// Destruction de l'image et libération de la mémoire
imagedestroy($image);
?>
PHP et GD 15
4.2.3 Créer des ellipses
<?php
// Changement des en-têtes
header("Content-type: image/jpeg");
// Largeur de l'image en pixel
$width = 300;
// Hauteur de mon image en pixel
$height = 100;
// Création de l'image en vraies couleurs
$image = imagecreatetruecolor($width, $height);
$bleu = imagecolorallocate($image, 0, 102, 255);
// Création d'un cercle avec la couleur bleu
imageellipse($image, 25, 50, 50, 50, $bleu);
// Création d'une elipse avec la couleur bleu
imageellipse($image, 100, 50, 150, 50, $bleu);
// Création d'un arc cercle avec la couleur bleu
imagearc($image, 175, 50, 20, 20, 0, 180, $bleu);
// Renvoie de l'image au format JPG vers le navigateur
imagejpeg($image);
// Destruction de l'image et libération de la mémoire
imagedestroy($image);
?>
PHP et GD 16
4.2.4 Créer des polygones
<?php
// Changement des en-têtes
header("Content-type: image/jpeg");
// Largeur de l'image en pixel
$width = 160;
// Hauteur de mon image en pixel
$height = 300;
// Création de l'image en vraies couleurs
$image = imagecreatetruecolor($width, $height);
$bleu = imagecolorallocate($image, 0, 102, 255);
// Tableau contenant les coordonées d'un trapèze
// Les points sont toujours des couples (x,y)
$coords = array(150,5,
5, 120,
5, 290,
150, 180);
// Création d'un polygone avec 4 points
imagepolygon($image, $coords, 4, $bleu);
// Renvoie de l'image au format JPG vers le navigateur
imagejpeg($image);
// Destruction de l'image et libération de la mémoire
imagedestroy($image);
?>
PHP et GD 17
4.3 Manipuler les textes
<?php
$img_width = 100;
$img_height = 40;
// On créer une image de 200 px sur 100
$image = imagecreatetruecolor($img_width, $img_height);
// Création des couleurs
$gris = imagecolorallocate($image, 230, 230, 230);
$bleu = imagecolorallocate($image, 0, 102, 255);
// Remplissage de l'image avec du gris
imagefill($image, 0, 0, $gris);
// Génération d'un nombre aléatoire
$nbr = rand(235684, 999999);
// Codage du nombre en md5
$md5 = md5($nbr);
// Limitation à 8 caracteres
$text = substr($md5, 0, 8);
// Nom de la police à utiliser (notez l'absence de l'extension .ttf)
$font = 'arial.ttf';
$size = 15;
$x = 5;
$y = $img_height/2;
$angle = 0;
// Création du texte
imagettftext($image, $size, $angle, $x, $y, $bleu, $font, $text);
// Dessin de l'image
header('Content-type: image/png');
imagepng($image);
imagedestroy($image);
?>
PHP et GD 18
5 Utilisation des fonctions dynamiques
L’utilisation des fonctions en PHP peut s’effectuer de manière « dynamique ». C'est-à-dire
que PHP peut construire le prototype de la fonction avant de lancer son exécution.
Cela va être intéressant pour appeler indépendamment les fonctions GD quelque soit votre
type d’image : GIF, JPEG ou PNG.
<?php
function get_extension($mine_type) {
if(empty($mine_type)) return false;
switch($mine_type) {
case 'image/gif':
return 'gif';
break;
case 'image/jpeg':
return 'jpeg';
break;
case 'image/png':
return 'png';
break;
default:
return false;
break;
}
}
// Image source et ratio
$img_src = 'blaster.jpg';
$ratio = 0.2;
// Récupération des informations sur l'image
list($width, $height, $type) = getimagesize($img_src);
// Construction du mine_type
$mine_type = image_type_to_mime_type($type);
// Calcul des tailles de la nouvelle image
$new_width = $width * $ratio;
$new_height = $height * $ratio;
// Utilisation d'une fonction dynamique
// Chargement de l'image source
$function_name = 'imagecreatefrom'.get_extension($mine_type);
$source = $function_name($img_src);
// Création de la nouvelle image
$image = imagecreatetruecolor($new_width, $new_height);
// Redimensionnement de l'image
imagecopyresampled($image, $source, 0, 0, 0, 0, $new_width , $new_height ,
$width, $height);
header('Content-type: '.$mine_type);
$function_name = 'image'.get_extension($mine_type);
$function_name($image);
imagedestroy($image);
?>
PHP et GD 19
6 Pour aller plus loin
PHP offre la possibilité via sa bibliothèque GD de construire des images à la volée grâce à
des instructions de base pour réaliser le dessin de formes et l'ajout de texte. Cependant, si
vous souhaitez créer des graphismes évolués, il faudra écrire beaucoup de code. Des
librairies graphiques de plus haut niveau sont disponibles. En générale, ces librairies
exploitent les fonctions de bases de GD et proposent des fonctionnalités comme la création
d'histogrammes complexes à l’aide de méthodes très simples à utiliser.
Voici une liste non exhaustive des librairies que vous pouvez utiliser :
ChartDirector
JpGraph
GraphViz
GraPHP-IC
http://www.advsofteng.com/
http://www.aditus.nu/jpgraph/
http://research.att.com/.../graphviz/
Vous pouvez un comparatif de ces différentes librairies à l’adresse suivante :
http://cyberzoide.developpez.com/php4/graphismes/
PHP et GD 20

Documents pareils