1

Étendre la couche alpha

16 avril 2006
par ARNO*

[SPIP 1.9 et GD2] Nous avons déjà réalisé des filtres manipulant la couche alpha (les informations de transparence d’une image PNG 24) :
— image_contour_alpha « sélectionne » les zones de transition de transparence et leur applique une couleur (on « dessine » ainsi les zones entre les pixels visibles et les pixels transparents d’une image d’origine) ;
— image_podpod créé des zones différenciées de transparence à partir d’une image qui n’a pas forcément de couche alpha ;
— le filtre d’estampage image_estampage_alpha, à l’inverse, fabrique une image en niveaux de gris (sans transparence) à partir des informations de transparence.

On a donc désormais l’habitude de manipuler la couche alpha d’une image pour réaliser des effets spécifiques. Pour les habitués de Photoshop, cette façon de procéder n’est pas totalement nouvelle : dans Photoshop, la « sélection » est elle-même une couche (habituellement dénommée alpha), que l’on peut d’ailleurs sauvegarder en tant que « couche » indépendante.

Poursuivons dans cette logique, et ajoutons un nouveau filtre, qui va nous permettre d’étendre ou de réduire une zone alpha. Comme souvent dans de tels filtres, l’usage immédiat concerne les images typographiques, puisque ce sont les principales images PNG transparentes que l’on peut créer automatiquement avec SPIP.

Voici le code du filtre, à installer comme toujours dans mes_fonctions.php :

  1. function image_etendre_alpha($im, $coul='000000', $trait=2)
  2. {
  3.         $image = valeurs_image_trans($im, "etendre-$coul-$trait");
  4.         if (!$image) return("");
  5.  
  6.         include_ecrire("filtres");
  7.         $couleurs = couleur_hex_to_dec($coul);
  8.         $dr= $couleurs["red"];
  9.         $dv= $couleurs["green"];
  10.         $db= $couleurs["blue"];
  11.        
  12.         $x_i = $image["largeur"];
  13.         $y_i = $image["hauteur"];
  14.        
  15.         $im = $image["fichier"];
  16.         $dest = $image["fichier_dest"];
  17.        
  18.         $creer = $image["creer"];
  19.  
  20.         if ($creer) {
  21.                 $im = $image["fonction_imagecreatefrom"]($im);
  22.                 $im_ = imagecreatetruecolor($x_i, $y_i);
  23.                 @imagealphablending($im_, false);
  24.                 @imagesavealpha($im_,true);
  25.                 $color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 127 );
  26.                 imagefill ($im_, 0, 0, $color_t);
  27.  
  28.                 $dist = abs($trait);
  29.                 for ($x = 0; $x < $x_i; $x++) {
  30.                         for ($y=0; $y < $y_i; $y++) {
  31.                        
  32.                                 $rgb = ImageColorAt($im, $x, $y);
  33.                                 $a = ($rgb >> 24) & 0xFF;
  34.                                 $r = ($rgb >> 16) & 0xFF;
  35.                                 $g = ($rgb >> 8) & 0xFF;
  36.                                 $b = $rgb & 0xFF;
  37.                                
  38.                                 $dif = false;
  39.                                 if ($trait > 0) $m = 127;
  40.                                 else $m = 0;
  41.                                 $t = 0;
  42.  
  43.                                 for ($ix = -1*$dist; $ix <= $dist; $ix++) {
  44.                                         for ($iy = -1*$dist; $iy <= $dist; $iy++) {
  45.                                                 $x2 = max(min($x+$ix, $x_i-1),0);
  46.                                                 $y2 = max(min($y+$iy, $y_i-1),0);
  47.                                        
  48.                                                 $rgb2 = ImageColorAt($im, $x2, $y2);
  49.                                                 $a2 = ($rgb2 >> 24) & 0xFF;
  50.                                                 $r2 = ($rgb2 >> 16) & 0xFF;
  51.                                                 $g2 = ($rgb2 >> 8) & 0xFF;
  52.                                                 $b2 = $rgb2 & 0xFF;
  53.  
  54.                                                 $dx = $x2-$x;
  55.                                                 $dy = $y2-$y;
  56.                                                
  57.                                                 if ($dx == 0 AND $dy == 0) {
  58.                                                         $d = 0;
  59.                                                 }
  60.                                                 else if (!$mem[$dx][$dy]) {
  61.                                                         $d = sqrt(($dx)*($dx)+($dy)*($dy)) / 1.4;
  62.                                                         $mem[$dx][$dy] = $d;                           
  63.                                                 } else {
  64.                                                         $d = $mem[$dx][$dy];
  65.                                                 }
  66.  
  67.                                                 if ($d <= abs($trait)) {
  68.                                                         if ($trait > 0) $m = min($m, $a2);
  69.                                                         else $m = max($m, $a2);
  70.                                                 }                                              
  71.                                         }
  72.                                 }
  73.  
  74.                                 $color = ImageColorAllocateAlpha( $im_, $dr, $dv, $db , round($m) );
  75.                                 imagesetpixel ($im_, $x, $y, $color);                           }
  76.                 }
  77.                 $image["fonction_image"]($im_, "$dest");
  78.         }
  79.  
  80.         $class = $image["class"];
  81.         if (strlen($class) > 1) $tags=" class='$class'";
  82.         $tags = "$tags alt='".$image["alt"]."'";
  83.         $style = $image["style"];
  84.        
  85.         return "<img src='$dest'$tags />";
  86. }

Télécharger

Le filtre s’utilise, essentiellement, sur une image typographique. Par exemple :

  1. [(#TITRE
  2.         |image_typo{police=big_noodle_titling.ttf,taille=80})]
  3. [(#TITRE
  4.         |image_typo{police=big_noodle_titling.ttf,taille=80}
  5.                 |image_etendre_alpha{ffffff,2})]
  6. [(#TITRE
  7.         |image_typo{police=big_noodle_titling.ttf,taille=80}
  8.                 |image_etendre_alpha{ffffff,-2})]

Télécharger

(J’utilise pour cet exemple la police Big Noodle Titling, disponible gratuitement en ligne.

Les deux paramètres sont :
— la couleur de « remplissage » des zones alpha non transparentes ; la couleur d’origine de l’image est donc totalement indifférente (comme dans le cas de image_contour_alpha) ;
— l’« épaisseur » de l’extension de la couche alpha.

L’épaisseur est un entier (le nombre de pixels), qui peut être supérieur ou inférieur à zéro :
— épaisseur positive : la zone alpha est étendue ;
— épaisseur négative : la zone alpha est réduite.

Attention ! Ce filtre est lourd ! Plus vous augmentez l’épaisseur, plus vous augmentez le temps de calcul. En cas de calculs trop longs pour votre hébergement, réalisez plusieurs « extensions » à la suite, en cumulant ainsi les épaisseurs (deux extensions de deux pixels équivalent à une extension de 4 pixels, mais avec une sauvegarde en cache entre les deux, ce qui permet souvent de réaliser l’effet en deux recalculs de la page).

Évidemment, le filtre ne devient réellement intéressant que lorsqu’il est utilisé en conjonction avec d’autres effets. Notamment en superposant différents « rendus » du même titre (comme dans l’exemple de l’ombre portée).

(Et pour une fois, je ne vous fournis pas le code des squelettes SPIP, je vous laisse expérimenter... Revoyez notamment les effets d’ombre et les titres en relief.)

Puisque c’est de saison, concluons avec un titre en chocolat :

Qui êtes-vous ?
Votre message

Ce formulaire accepte les raccourcis SPIP [->url] {{gras}} {italique} <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.