Voici un exemple d'utilisation de gd2 en php. Ce script permet d'appliquer un masque de transparence à une image.
Ce script a été écrit suite à une question intéressante sur les forums d'apachefrance.com
Il s'agissait à la base de faire des angles arrondis aux images et puis, les fonctionnalités ont tellement dégénérées que j'ai décidé d'écrire cette page pour vous présenter le script ...
Ce script peut fonctionner de plusieurs manières. On l'inclut en attribut src des balises img dela façon suivante:
<img src="arrondi.php?img=pic.jpg&mask=mask.png&bg_r=216&bg_g=252&bg_b=216" />
arrondi.php peut être précédé d'un chemin absolu ou relatif selon le répertoire où il se trouve, par rapport à la page dans laquelle on l'utilise.
Voyons les paramètres:
Placez arrondi.php et un masque mask.png par défaut dans un répertoire de votre site. Créez un sous répertoire cache dans le quel le script doit pouvoir écrire (autorisation en exécution et écriture pour tous ou chmod 777 pour être sûr).
C'est tout !
arrondi.php
<?php if (!isset($_GET["img"])) die('missing img parameter'); if (strstr("http://", $_GET["img"])) die('Only for internal use'); if (strstr("http://", $_GET["mask"])) die('Only for internal use'); // On regarde si l'utilisateur utilise IE ou autre chose if (strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE')) { $isIE = true; } else { $isIE = false; } $src = array(); // On vérifie l'existence de l'image $src['file'] = $_GET['img']; if (!file_exists($src['file'])) die('Image does not exist'); // On regarde si l'utilisateur a spécifié une couleur de fond if (isset($_GET['bg_r']) && isset($_GET['bg_g']) && isset($_GET['bg_b'])) { $src['img_bgcolor']['r'] = intval($_GET['bg_r']); $src['img_bgcolor']['g'] = intval($_GET['bg_g']); $src['img_bgcolor']['b'] = intval($_GET['bg_b']); } // On se procure les infos sur l'image (taille/type mime) $src['infos'] = getimagesize($src['file']); // On charge le masque $src['maskfile'] = (isset($_GET['mask']) ? $_GET['mask'] : "./mask.png"); $src['origmask'] = imagecreatefrompng($src['maskfile']); // On Vérifie l'existence du masque if (!file_exists($src['maskfile'])) die('mask file does not exist'); // On cherche l'image en cache $src['cache_file'] = "./cache/".md5($src['file'].$src['maskfile']); if (isset($src['img_bgcolor'])) { $src['cache_file'] .= "r".$src['img_bgcolor']['r']; $src['cache_file'] .= "g".$src['img_bgcolor']['g']; $src['cache_file'] .= "b".$src['img_bgcolor']['b']; } else { $src['cache_file'] .= (($isIE)?"IE":""); } if (file_exists($src['cache_file']) && (intval(filemtime($src['file'])) < intval(filemtime($src['cache_file']))) && (intval(filemtime($src['maskfile'])) < intval(filemtime($src['cache_file'])))) { // Si on a l'image traitée en cache // Et que l'image source n'est pas plus récente que celle en cache // on l'envoie ! if (!isset($src['img_bgcolor'])) { header ("Content-Type: image/png"); } else { header ("Content-Type: image/jpeg"); } readfile($src['cache_file']); exit(); } // Sinon on continue le traitement // On se procure la taille du masque $src['origmask_info'] = getimagesize($src['maskfile']); // On crée un masque à la bonne taille $src['mask'] = imagecreatetruecolor ($src['infos'][0], $src['infos'][1]); // On y copie le masque de départ imagealphablending($src['mask'], FALSE); imagecopyresized( $src['mask'], $src['origmask'], 0, 0, 0, 0, $src['infos'][0], $src['infos'][1], $src['origmask_info'][0], $src['origmask_info'][1]); // On se débarasse du masque de départ imagedestroy($src['origmask']); // On charge l'image de départ en fonction de son type switch($src['infos']['mime']) { case 'image/jpg': case 'image/jpeg': $src['img'] = imagecreatefromjpeg($src['file']); break; case 'image/gif': $tmp = imagecreatefromgif($src['file']); $src['img'] = imagecreatetruecolor($src['infos'][0], $src['infos'][1]); imagecopy ($src['img'], $tmp, 0, 0, 0, 0, $src['infos'][0], $src['infos'][1]); imagedestroy($tmp); break; case 'image/png': $src['img'] = imagecreatefrompng($src['file']); break; default: exit(); } imagealphablending($src['img'], isset($src['img_bgcolor'])); // Pour IE, on passe en mode indéxé // Et on dit que la couleur se trouvant en 0,0 sera la couleur transparente ... if ($isIE && !isset($src['img_bgcolor'])) { imagetruecolortopalette($src['img'], FALSE, 256); $trans_color = imagecolorat($src['img'], 0, 0); imagecolortransparent($src['img'], $trans_color); } // On affecte à chaque pixel de l'image // la valeur de l'alpha dans le masque // et éventuellement la couleur de fond mélangée for ($i=0; $i<$src['infos'][0]; ++$i) { for ($j=0; $j<$src['infos'][1]; ++$j) { if ($isIE && !isset($src['img_bgcolor'])) { $pxl = imagecolorsforindex( $src['mask'], imagecolorat($src['mask'], $i, $j)); $pxl_alpha = $pxl['alpha']; if ($pxl_alpha>=120) imagesetpixel($src['img'], $i, $j, $trans_color); } else { $pxl_alpha = imagecolorsforindex( $src['mask'], imagecolorat($src['mask'], $i, $j)); $pxl_color = imagecolorsforindex( $src['img'], imagecolorat($src['img'], $i, $j)); if (!isset($src['img_bgcolor'])) $color = imagecolorallocatealpha ( $src['img'], $pxl_color['red'], $pxl_color['green'], $pxl_color['blue'], $pxl_alpha['alpha']); else $color = imagecolorallocatealpha ( $src['img'], $src['img_bgcolor']['r'], $src['img_bgcolor']['g'], $src['img_bgcolor']['b'], 127-$pxl_alpha['alpha']); imagesetpixel($src['img'], $i, $j, $color); } } } // Pas besoin de sauver l'alpha si on a affaire à IE, // il n'en tient pas compte ... if (!$isIE) { imagesavealpha($src['img'], TRUE); } // On crée le fichier en cache if (!isset($src['img_bgcolor'])) { imagepng($src['img'], $src['cache_file']); } else { imagejpeg($src['img'], $src['cache_file']); } imagedestroy($src['img']); imagedestroy($src['mask']); // On envoi le header et l'image du cache if (!isset($src['img_bgcolor'])) { header("Content-Type: image/png"); } else { header("Content-Type: image/jpeg"); } readfile($src['cache_file']); ?>
Le script détecte le browser utilisé vie l'entête "User-Agent" pour voir si on a affaire à Internet Explorer ou non. Ce test est nécessaire car IE ne gère pas correctement les images png comportant une couche alpha ...
Le script gère un cache dans lequel il stocke toutes les images qui lui ont été demandées, en fonction du browser, de la couleur de fond et du masque appliqué. Ceci accélère le traitement, l'application du masque de transparence étant relativement long, il est mieux de ne le faire qu'une fois.
En l'absence des composantes de couleurs de fond, le script envoit un PNG RVB avec couche alpha sur 7 bits si le browser utilisé n'est pas IE et un simple png indéxé avec une couleur transparente (comme un GIF) s'il s'agit d'un internaute utilisant IE. Autant dire qu'en utilisant Firefox ou Opera, on obtient une image beaucoup mieux finie ...
Si les composantes de fond sont spécifiées, le script crée un jpg en mélangeant la couleur de fond spéfifiée en fonction du masque alpha. Ceci donne une qualité équivalente au PNG RVBA et une taille très inférieure pour les images. En revanche, le résultat n'est parfait que sur un fond uni ...
L'arrondi
Le feu de l'amour
Le Zaz :-)
a+