{"id":22,"date":"2012-04-11T18:49:00","date_gmt":"2012-04-11T18:49:00","guid":{"rendered":"http:\/\/cyol.fr\/blogwp\/?p=22"},"modified":"2015-04-14T16:08:12","modified_gmt":"2015-04-14T14:08:12","slug":"php-librairie-gd-et-retouche-d-images","status":"publish","type":"post","link":"https:\/\/cyol.fr\/blog\/post\/php-librairie-gd-et-retouche-d-images\/","title":{"rendered":"PHP : librairie GD et retouche d&rsquo;images"},"content":{"rendered":"<p><img decoding=\"async\" style=\"float: left; margin: 0 1em 1em 0;\" title=\"Elephpant, mar. 2013\" src=\"\/blog\/wp-content\/uploads\/billets\/icones\/elephpant100.png\" alt=\"Elephpant\" \/>Aujourd&rsquo;hui on va parler d\u00e9veloppement, mais pas java ni android, d\u00e9veloppement PhP.<\/p>\n<p>Je fais du Jeu de R\u00f4les par forum, \u00e0 Shadowrun, nous commen\u00e7ons une campagne o\u00f9 les PJ ont un compte sur le r\u00e9seau social P2.0 et qu&rsquo;ils devront \u00ab\u00a0entretenir\u00a0\u00bb. Plusieurs indices entrent en jeu pour donner un indice Global au compte, histoire de rentre le truc plus immersif, je veux que les PJ voient leur indice de fa\u00e7on simple claire et pr\u00e9cise, tout en gardant la main dessus.<\/p>\n<p><!--more--><\/p>\n<p>Hors sur le forum o\u00f9 j&rsquo;op\u00e8re en tant que MJ, les possibilit\u00e9s sont limit\u00e9s (pour qui n&rsquo;est pas admin, ce qui n&rsquo;est pas mon cas) :<\/p>\n<p>J&rsquo;ai la main sur :<\/p>\n<ul>\n<li>Les posts que j&rsquo;\u00e9cris<\/li>\n<li>Les posts que mes joueurs \u00e9crivent (je suis mod\u00e9rateur sur ma partie)<\/li>\n<li>Mon avatar<\/li>\n<li>Mon profil (mots cl\u00e9s sous l&rsquo;avatar)<\/li>\n<li>Ma signature<\/li>\n<\/ul>\n<p>Et malheureusement je n&rsquo;ai pas la main sur les endroits qui semblent les plus int\u00e9ressants pour ce que je veux faire :<\/p>\n<ul>\n<li>L&rsquo;avatar de chaque PJ<\/li>\n<li>Le profil de chaque PJ<\/li>\n<li>La signature de chaque PJ<\/li>\n<\/ul>\n<p>Je peux toujours demander aux joueurs de mettre \u00e0 jour un de ces \u00e9l\u00e9ments si besoin, mais cela me g\u00e8ne car je ne suis pas certain d&rsquo;avoir le r\u00e9pondant pour que tous les PJs soient \u00e0 jour en m\u00eame temps, ni m\u00eame simplement que ce soit fait. Du coup, j&rsquo;ai penser \u00e0 demander aux joueur de ne faire qu&rsquo;une modification : qu&rsquo;ils fassent pointer l&rsquo;url de leur avatar vers un url que je leur ai donn\u00e9. Je retoucherais l&rsquo;image et la mettrait \u00e0 jour. Probl\u00e8me, je ne suis pas \u00e0 l&rsquo;aise avec les logiciel de retouches d&rsquo;images et du coup \u00e7a me prend trop de temps. De plus sur GIMP, je n&rsquo;ai pas trouv\u00e9 un moyen simple de mettre \u00e0 jour des calques contenant du texte sans avoir \u00e0 rouvrir l&rsquo;image et modifier chaque calque \u00e0 la main. J&rsquo;aurais aim\u00e9 pouvoir lier l&rsquo;image \u00e0 un fichier texte ou xml o\u00f9 il irait chercher l&rsquo;info \u00e0 afficher.<\/p>\n<p>Apr\u00e8s y avoir r\u00e9fl\u00e9chi un moment, j&rsquo;ai trouv\u00e9 un compromis (et on en arrive enfin au rapport avec le titre du billet) : les avatars peuvent pointer vers un fichier .php si leur \u00ab\u00a0headers\u00a0\u00bb les identifie comme image. Et avec la librairie GD de PhP on peut faire de la manipulation d&rsquo;image. Et l\u00e0, je ma\u00eetrise plus.<\/p>\n<p>Alors tout d&rsquo;abord, le lien vers le tuto qui va bien : <a title=\"Site du Z\u00e9ro : Tutoriel Cr\u00e9er des images en PHP\" href=\"http:\/\/www.siteduzero.com\/tutoriel-3-14597-creer-des-images-en-php.html\" hreflang=\"fr\">http:\/\/www.siteduzero.com\/tutoriel-3-14597-creer-des-images-en-php.html<\/a> (au passage : Le <a title=\"Site du Z\u00e9ro : Le site pour d\u00e9butants o\u00f9 tout est expliqu\u00e9... \u00e0 partir de Z\u00e9ro !\" href=\"http:\/\/www.siteduzero.com\/\" hreflang=\"fr\">Site du Z\u00e9ro<\/a> fait partie de mes r\u00e9f\u00e9rences quand je me pose une question en programmation, m\u00eame sur un langage que je ma\u00eetrise comme PhP. Les tuto y sont tr\u00e8s clairs et partent toujours de &#8230; z\u00e9ro (!) du coup, au final fonctionnent toujours car aucune \u00e9tape n&rsquo;est pass\u00e9e sous silence sous pr\u00e9texte \u00ab\u00a0tout le monde sait \u00e7a, pas besoin d&rsquo;en parler\u00a0\u00bb.)<\/p>\n<h3>Premi\u00e8re \u00e9tape :<\/h3>\n<p>S&rsquo;assurer que notre h\u00e9bergement permet de manipuler les images avec PhP : Cr\u00e9er un fichier avec juste le phpinfo :<\/p>\n<pre class=\"brush:php\">&lt;?php phpinfo();<\/pre>\n<p>Et chercher si la librairie GD est activ\u00e9e (enable)<\/p>\n<p><a href=\"https:\/\/cyol.fr\/blog\/wp-content\/uploads\/billets\/php-librairie-gd-et-retouche-d-images\/GDactif_dans_phpinfo.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-136\" title=\"GDactif_dans_phpinfo\" src=\"https:\/\/cyol.fr\/blog\/wp-content\/uploads\/billets\/php-librairie-gd-et-retouche-d-images\/GDactif_dans_phpinfo.png\" alt=\"Librairie GD active dans phpinfo\" width=\"650\" height=\"368\" srcset=\"https:\/\/cyol.fr\/blog\/wp-content\/uploads\/billets\/php-librairie-gd-et-retouche-d-images\/GDactif_dans_phpinfo.png 650w, https:\/\/cyol.fr\/blog\/wp-content\/uploads\/billets\/php-librairie-gd-et-retouche-d-images\/GDactif_dans_phpinfo-300x169.png 300w, https:\/\/cyol.fr\/blog\/wp-content\/uploads\/billets\/php-librairie-gd-et-retouche-d-images\/GDactif_dans_phpinfo-150x84.png 150w, https:\/\/cyol.fr\/blog\/wp-content\/uploads\/billets\/php-librairie-gd-et-retouche-d-images\/GDactif_dans_phpinfo-400x226.png 400w\" sizes=\"auto, (max-width: 650px) 100vw, 650px\" \/><\/a>(Petite astuce si vous \u00eates en h\u00e9bergement mutualis\u00e9 chez OVH : pour que la suite fonctionne bien et que vous ne tombiez pas sur une erreur 500, assurez vous que vous \u00eates en php 5.)<\/p>\n<h3>Seconde \u00e9tape :<\/h3>\n<p>Il faut que notre .php soit identifi\u00e9 comme image, il faut d\u00e9finir les headers qui vont bien :<\/p>\n<pre class=\"brush:php\">header('Content-Type: image\/png');<\/pre>\n<p>L\u00e0 j&rsquo;ai mis png, mais on peut aussi mettre jpeg si on veut.<\/p>\n<h3>Troisi\u00e8me \u00e9tape : cr\u00e9ation d&rsquo;une image \u00e0 partir d&rsquo;une autre<\/h3>\n<p>Mes PJ ont d\u00e9j\u00e0 leur avatar, il ne m&rsquo;appartient pas de leur en imposer un, du coup, je vais me servir du leur comme base de l&rsquo;image : $imagename valant \u00ab\u00a0chemin\/vers\/image.png\u00a0\u00bb<\/p>\n<pre class=\"brush:php\">&lt;?php header('Content-Type: image\/png'); $imagename = \"avatar_cyol.png\"; \/\/G\u00e9n\u00e9rer l'image $image = @imagecreatefrompng($imagename); \/\/Ici on mettra le reste du code qu'on va voir ensuite \/\/Afficher l'image en tant que PNG imagepng($image);<\/pre>\n<p>Si j&rsquo;avais eu un jpeg en source, \u00e7a aurait \u00e9t\u00e9 la fonction <a title=\"PhP : Fonction imagecreatefromjpeg\" href=\"http:\/\/www.php.net\/manual\/fr\/function.imagecreatefromjpeg.php\">imagecreatefromjpeg<\/a>. Le deuxi\u00e8me lien qui va bien pour tout ce qui va suivre : <a title=\"R\u00e9f\u00e9rence PHP : Librairie GD\" href=\"http:\/\/www.php.net\/manual\/fr\/ref.image.php\">http:\/\/www.php.net\/manual\/fr\/ref.image.php<\/a> (Il faut toujours lire la doc, m\u00eame si c&rsquo;est moins facile d&rsquo;acc\u00e8s qu&rsquo;un tutoriel, \u00e7a aide grandement pour aller plus loin que ce que peut proposer un tutoriel)<\/p>\n<table>\n<thead>\n<tr>\n<th>Image<br \/>\nde base<\/th>\n<th>L&rsquo;image<br \/>\nvia PhP<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-135\" title=\"avatar_cyol\" src=\"https:\/\/cyol.fr\/blog\/wp-content\/uploads\/billets\/php-librairie-gd-et-retouche-d-images\/avatar_cyol.png\" alt=\"avatar_cyol.png\" width=\"90\" height=\"90\" \/><\/td>\n<td><img decoding=\"async\" title=\"avatar_cyol en PhP\" src=\"https:\/\/cyol.fr\/blog\/wp-content\/uploads\/billets\/php-librairie-gd-et-retouche-d-images\/etape3.php\" alt=\"avatar_cyol en PhP\" \/><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>Quatri\u00e8me \u00e9tape : cr\u00e9ation des crayons de couleur<\/h3>\n<p>Pour pouvoir \u00e9crire sur l&rsquo;image il faut des \u00ab\u00a0crayons\u00a0\u00bb, on les d\u00e9fini avec la fonction <a title=\"PhP : Fonction imagecolorallocate\" href=\"http:\/\/www.php.net\/manual\/fr\/function.imagecolorallocate.php\">imagecolorallocate<\/a>. (Quand je disais qu&rsquo;on va plus loin avec la doc : en regardant imagecolorallocate, je trouve <a title=\"PhP : Fonction imagecolorallocatealpha\" href=\"http:\/\/www.php.net\/manual\/fr\/function.imagecolorallocatealpha.php\">imagecolorallocatealpha<\/a> qui propose en plus un argument pour g\u00e9rer la transparence !)<\/p>\n<p>Le premier argument est l&rsquo;image que vous avez cr\u00e9\u00e9 (dans mon cas en utilisant imagecreatefrompng), les 3 suivants sont le code RVB (Rouge Vert Bleu)<\/p>\n<pre class=\"brush:php\">$noir  = imagecolorallocate($image, 0, 0, 0);\r\n$blanc = imagecolorallocate($image, 255, 255, 255);\r\n$rouge = imagecolorallocate($image, 255, 0, 0);\r\n$bleu  = imagecolorallocate($image, 0, 0, 255);\r\n$vert  = imagecolorallocate($image, 0, 255, 0);\r\n$orange = imagecolorallocate($image, 255, 128, 0);\r\n$bleuclair = imagecolorallocate($image, 156, 227, 254);<\/pre>\n<p>En l&rsquo;\u00e9tat ils ne font rien, mais ils vont nous servir pour la suite. Si j&rsquo;ai utilis\u00e9 l&rsquo;analogie des crayons de couleur ce n&rsquo;est pas par hasard. Il faut maintenant les prendre pour \u00e9crire et dessiner !<\/p>\n<p>(Note : je dis \u00ab\u00a0En l&rsquo;\u00e9tat ils ne font rien\u00a0\u00bb, ce n&rsquo;est pas enti\u00e8rement vrai, c&rsquo;est non visible dans mon cas o\u00f9 je cr\u00e9er une image \u00e0 partir d&rsquo;une autre, mais le premier imagecolorallocate d\u00e9clar\u00e9 va aussi devenir la couleur de fond de l&rsquo;image.)<\/p>\n<h3>Cinqui\u00e8me \u00e9tape : \u00e9crire<\/h3>\n<p>Pour \u00e9crire, c&rsquo;est la fonction <a title=\"PhP : Fonction imagestring\" href=\"http:\/\/www.php.net\/manual\/fr\/function.imagestring.php\">imagestring<\/a> qui va \u00eatre utilis\u00e9. Le premier argument est toujours notre image, le second est la taille de la police : entre 1 petit et 5 grand. Il est possible de mettre d&rsquo;autres valeurs qu&rsquo;on aura d\u00e9fini auparavant avec d&rsquo;autres fonctions, allez lire la doc, je n&rsquo;ai pas utilis\u00e9.<\/p>\n<p>Les arguments 3 et 4 sont les coordonn\u00e9es X et Y du coin en haut \u00e0 gauche de la zone d&rsquo;\u00e9criture. Ces coordonn\u00e9es sont en \u00ab\u00a0nombre de pixel\u00a0\u00bb par rapport au coin en haut \u00e0 gauche de l&rsquo;image qui est le 0,0<\/p>\n<p>Enfin, les deux derniers argument sont respectivement : le texte \u00e0 \u00e9crire et le Crayon de couleur qu&rsquo;on veut utiliser !<\/p>\n<pre class=\"brush:php\">imagestring($image, 2, 60, 75, \"P2:\", $noir); imagestring($image, 2, 59, 74, \"P2:\", $blanc);<\/pre>\n<p>Pourquoi j&rsquo;\u00e9cris 2 fois avec 1pixel de d\u00e9calage ? Pour faire un l\u00e9ger effet Ombr\u00e9 !<\/p>\n<table>\n<thead>\n<tr>\n<th>Image<br \/>\nde base<\/th>\n<th>L&rsquo;image<br \/>\nvia PhP<\/th>\n<th>Sans<br \/>\nombr\u00e9<\/th>\n<th>Avec<br \/>\nombr\u00e9<\/th>\n<th>Final<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><img decoding=\"async\" title=\"avatar_cyol.png\" src=\"https:\/\/cyol.fr\/blog\/wp-content\/uploads\/billets\/php-librairie-gd-et-retouche-d-images\/avatar_cyol.png\" alt=\"avatar_cyol.png\" \/><\/td>\n<td><img decoding=\"async\" title=\"avatar_cyol en PhP\" src=\"https:\/\/cyol.fr\/blog\/wp-content\/uploads\/billets\/php-librairie-gd-et-retouche-d-images\/etape3.php\" alt=\"avatar_cyol en PhP\" \/><\/td>\n<td><img decoding=\"async\" title=\"avatar_cyol en PhP\" src=\"https:\/\/cyol.fr\/blog\/wp-content\/uploads\/billets\/php-librairie-gd-et-retouche-d-images\/etape5.1.php\" alt=\"avatar_cyol en PhP\" \/><\/td>\n<td><img decoding=\"async\" title=\"avatar_cyol en PhP\" src=\"https:\/\/cyol.fr\/blog\/wp-content\/uploads\/billets\/php-librairie-gd-et-retouche-d-images\/etape5.2.php\" alt=\"avatar_cyol en PhP\" \/><\/td>\n<td><img decoding=\"async\" title=\"avatar_cyol en PhP\" src=\"https:\/\/cyol.fr\/blog\/wp-content\/uploads\/billets\/php-librairie-gd-et-retouche-d-images\/etape5.3.php\" alt=\"avatar_cyol en PhP\" \/><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>Sixi\u00e8me \u00e9tape : dessiner<\/h3>\n<p>On va dessiner des formes, moi ce qui m&rsquo;int\u00e9resse c&rsquo;est du rectangle plein pour faire des barres de progression, du coup j&rsquo;utilise <a title=\"PhP: Fonction imagefilledrectangle\" href=\"http:\/\/www.php.net\/manual\/fr\/function.imagefilledrectangle.php\">imagefilledrectangle<\/a>($image, $x1, $y1, $x2, $y2, $couleur);<\/p>\n<p>$x1, $y1 sont les coordonn\u00e9es du coin haut gauche et $x2, $y2 les coordonn\u00e9es du coin bas droit. $couleur est le Crayon de couleur qu&rsquo;on veut utiliser. Vu que je veux un effet de barre de progression il me faut une premi\u00e8re barre noire qui sera le 100% et par dessus une barre de couleur qui couvrira le %.<\/p>\n<pre class=\"brush:php\">$x1 = 5;\r\n$x2 = 30;\r\n$y1 = 4;\r\n$y2 = 6;\r\nimagefilledrectangle($image, $x1+1, $y1+1, $x2+1, $y2+1, $noir);\r\n\/\/scores\r\n$proximite\u00a0 = 50;\r\n$xpr = round(($x2*$proximite)\/100)+ $x1;\r\nimagefilledrectangle($image, $x1, $y1, $xpr, $y2 , $rouge);<\/pre>\n<p>Et voil\u00e0 !<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/cyol.fr\/blog\/wp-content\/uploads\/billets\/php-librairie-gd-et-retouche-d-images\/etape6.php\" alt=\"image finale\" \/><\/p>\n<p>Note : Si j&rsquo;ajoute $x1 \u00e0 le $xpr calcul\u00e9 \u00e0 partir de $x2 c&rsquo;est pour bien prendre en compte qu&rsquo;on ne part pas de 0 mais bien de 5.<\/p>\n<p>Et voil\u00e0 comment on peut faire de la manipulation d&rsquo;image avec la librairie GD de PhP. Il existe \u00e9videmment plein d&rsquo;autres fonctions pour faire plus de choses, mais l\u00e0 je ne me suis int\u00e9ress\u00e9 qu&rsquo;\u00e0 atteindre mon but de rajouter sur l&rsquo;avatar de mes PJ \u00e0 Shadowrun leur indice P2.<\/p>\n<p><a title=\"Code source de l\u2019image finale du billet \u00ab\u00a0PHP : librairie GD et retouche d\u2019images\u00a0\u00bb\" href=\"https:\/\/cyol.fr\/blog\/pagecode-source-de-l-image-finale-du-billet-php-librairie-gd-et-retouche-d-images\/\">Vous pouvez voir le code source final<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Aujourd&rsquo;hui on va parler d\u00e9veloppement, mais pas java ni android, d\u00e9veloppement PhP. Je fais du Jeu de R\u00f4les par forum, \u00e0 Shadowrun, nous commen\u00e7ons une campagne o\u00f9 les PJ ont un compte sur le r\u00e9seau social P2.0 et qu&rsquo;ils devront \u00ab\u00a0entretenir\u00a0\u00bb. [&#8230;]<\/p>\n","protected":false},"author":1,"featured_media":110,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,7,6],"tags":[22,23,60,61,19],"class_list":["post-22","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-developpement","category-jeu-de-role","category-php","tag-forum","tag-jeu","tag-librairie-gd","tag-manipulation-d-image","tag-shadowrun","odd"],"_links":{"self":[{"href":"https:\/\/cyol.fr\/blog\/wp-json\/wp\/v2\/posts\/22","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cyol.fr\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cyol.fr\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cyol.fr\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cyol.fr\/blog\/wp-json\/wp\/v2\/comments?post=22"}],"version-history":[{"count":9,"href":"https:\/\/cyol.fr\/blog\/wp-json\/wp\/v2\/posts\/22\/revisions"}],"predecessor-version":[{"id":1543,"href":"https:\/\/cyol.fr\/blog\/wp-json\/wp\/v2\/posts\/22\/revisions\/1543"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cyol.fr\/blog\/wp-json\/wp\/v2\/media\/110"}],"wp:attachment":[{"href":"https:\/\/cyol.fr\/blog\/wp-json\/wp\/v2\/media?parent=22"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cyol.fr\/blog\/wp-json\/wp\/v2\/categories?post=22"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cyol.fr\/blog\/wp-json\/wp\/v2\/tags?post=22"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}