[SPIP 1.9 et GD2] Toujours à la recherche d’applications inédites des filtres de SPIP, je vous propose aujourd’hui de franchir une nouvelle étape : un filtre qui ne sert rigoureusement à rien !
À rien pour traiter une image, certes, mais dans une galerie de photos, ça peut produire un petit effet assez pro... Et il n’est pas impossible que, par la suite, nous trouvions un usage à la méthode développée ici [1].
L’idée est d’extraire d’une photographie les informations de couleur de tous ses pixels et de les afficher dans un graphique synthétique, que l’on nomme habituellement un histogramme. Partons de l’image suivante :

elle nous donne l’histogramme suivant :

Le graphique se lit ainsi :
— en fond d’image, la courbe grise indique la répartition des niveaux de gris ;
— par dessus, trois courbes colorées indiquent les répartitions de rouge, vert et bleu ;
— pour chaque courbe, l’axe horizontal de gauche à droite parcourt les intensités de 0 à 255 ; pour le gris, par exemple, 0 est le noir, 255 est le blanc ; et verticalement, la « hauteur » de la courbe indique la densité de ce niveau de couleur, c’est-à-dire le nombre de pixels qui correspondent à ce niveau.
Par exemple, ici, pour le gris comme pour les trois composantes, on a des pics d’intensité situés aux alentours de l’intensité 200 ; ce qui signifie qu’un grand nombre de pixels ont une couleur proche du gris 78% (relativement clair, donc). On constate également qu’il n’y a quasiment pas de pixels avec des intensités supérieures à 220 ; ce qui signifie qu’il n’y a quasiment pas de pixels très clairs dans l’image (l’image n’a pas de zones très claires ou blanches).
Voici notre filtre image_histo :
function image_histo($im) {
$image = valeurs_image_trans($im, "courbes", "gif");
if (!$image) return("");
$x_i = $image["largeur"];
$y_i = $image["hauteur"];
$im = $image["fichier"];
$dest = $image["fichier_dest"];
$creer = $image["creer"];
if ($creer) {
$im = $image["fonction_imagecreatefrom"]($im);
$im_ = imagecreatetruecolor(258, 130);
@imagealphablending($im_, false);
@imagesavealpha($im_,true);
$color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 0 );
imagefill ($im_, 0, 0, $color_t);
$col_poly = imagecolorallocate($im_,0,0,0);
imagepolygon
($im_,
array ( 0,
0,
257,
0,
257,
129,
0,
129 ),
4,
$col_poly);
for ($x = 0; $x < $x_i; $x++) {
for ($y=0; $y < $y_i; $y++) {
$rgb = ImageColorAt($im, $x, $y);
$a = ($rgb >> 24) & 0xFF;
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;
$a = (127-$a) / 127;
$a=1;
$gris =
round($a*
($r+
$g+
$b) /
3);
$val_gris[$gris] ++;
$val_r[$r] ++;
$val_g[$g] ++;
$val_b[$b] ++;
}
}
$rapport = (127/$max);
$gris = imagecolorallocate($im_, 160, 160, 160);
for ($i = 0; $i < 256; $i++) {
$val =
127 -
round(max(0,
$val_gris[$i]) *
$rapport); imageline
($im_,
$i+1,
128,
$i+1,
$val+1,
$gris);
}
$bleu = imagecolorallocate($im_, 0, 0, 255);
for ($i = 0; $i < 256; $i++) {
$val =
127 -
round(max(0,
$val_b[$i]) *
$rapport);
if ($i==0) imagesetpixel ($im_, $i+1, $val+1, $bleu);
else imageline($im_, $i, $val_old+1, $i+1, $val+1, $bleu);
$val_old = $val;
}
$green = imagecolorallocate($im_, 0, 255, 0);
for ($i = 0; $i < 256; $i++) {
$val =
127 -
round(max(0,
$val_g[$i]) *
$rapport);
if ($i==0) imagesetpixel ($im_, $i+1, $val+1, $green);
else imageline($im_, $i, $val_old+1, $i+1, $val+1, $green);
$val_old = $val;
}
$rouge = imagecolorallocate($im_, 255, 0, 0);
for ($i = 0; $i < 256; $i++) {
$val =
127 -
round(max(0,
$val_r[$i]) *
$rapport);
if ($i==0) imagesetpixel ($im_, $i+1, $val+1, $rouge);
else imageline($im_, $i, $val_old+1, $i+1, $val+1, $rouge);
$val_old = $val;
}
$image["fonction_image"]($im_, "$dest");
imagedestroy($im_);
imagedestroy($im);
}
return "<img src='$dest' style='width: 258px; height: 130px;' />";
}
La première partie détermine le nom et gère le système de cache pour l’image résultante. La seule particularité ici est que l’on travaille avec une image qui ne découle pas directement, pour ses dimensions, de l’image d’origine. C’est un graphique de taille fixe que l’on créée.
La double boucle, habituelle, parcourt l’image pixel par pixel :
for ($x = 0; $x < $x_i; $x++) {
for ($y=0; $y < $y_i; $y++) {
$rgb = ImageColorAt($im, $x, $y);
$a = ($rgb >> 24) & 0xFF;
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;
$a = (127-$a) / 127;
$a=1;
$gris =
round($a*
($r+
$g+
$b) /
3);
$val_gris[$gris] ++;
$val_r[$r] ++;
$val_g[$g] ++;
$val_b[$b] ++;
}
}
$rapport = (127/$max);
On stocke les informations d’intensité dans des tableaux ($val_gris, $val_r...). À la fin de la double boucle, on détermine la valeur maximale de tous ces tableaux, de façon à pouvoir, ensuite, dessiner la valeur maximale à 127 pixels du bas de l’image.
C’est dans un deuxième temps, dans quatre boucles successives, de 0 à 255, que l’on parcourt les niveaux d’intensité pour dessiner nos quatre courbes.
Voici un autre exemple :

qui donne :

Septembre 2006
Afficher l’histogramme d’une image
ced (cedricos75 chez yahoo.fr)
Merci pour le boulot !
Décembre 2006
Afficher l’histogramme d’une image
besoin d’aide (papillonnal chez yahoo.fr)
bonjour pour vous ;
j’aimerai bien savoir un programme pour historamme d’image avec langage c
merci
Janvier 2007
Afficher l’histogramme d’une image
Elioscope
Voila une belle maniére de programmer des trucs inutiles
Février 2007
Afficher l’histogramme d’une image
Stef (Cont chez ct-sur-art-logic.info)
Une fonction qui me sera bien utile, ne serait-ce que pour évaluer des photos non retouchées, posées sur le site un peu trop rapidement. Grand Merci, je l’adopte !
Juillet 2007
Afficher l’histogramme d’une image
Je ne trouve pas comment modifier la couleur de fond de l’histogramme ? j’aimerai virer le blanc pour le remplacer par du transparent. C’est jouable ? Et si ce n’est pas jouable en changer la couleur ?
Avril 2008
Afficher l’histogramme d’une image
Gezus
Salut et merci pour cette contrib bien pratique !
J’ai intégré l’histogramme au code de la galerie Walma, cela marche à merveille.
Cependant j’aimerais savoir si quelqu’un à une idée de la lourdeur ou du temps d’exécution coté serveur pour le calcul de cet histogramme.
Fait-il appel à des fonctions des librairies GD2 ou Imagick ? ou simplement en Javascript brut ?
Pour voir l’intégration faite à Walma :
http://gezus.homelinux.com/spip.php ?page=walma&id_article=129
D’avance merci
Avril 2008
Changer couleur de fond de l’histogramme
Gezus
Salut, réponse à la question posée plus haut :
Comment changer la couleur de fond de l’histogramme ?
Reponse modifier cette ligne :
(ligne 17)
$color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 0 ) ;
Si vous mettez 55 à la place de 255 partout cela donne un fond gris foncé à l’histo... après c’est à modifier à votre guise.
Avril 2008
Afficher l’histogramme d’une image
ARNO*
@Gesuz
C’est en GD2. La lourdeur du calcul est relativement importante ; elle dépend des dimensions de l’image, puisqu’on extrait la couleur de chaque point de l’image. Cependant, une fois que le calcul est réalisé pour une image, le résultat est sauvegardé dans un fichier qui n’est plus recalculé. Donc aucune lourdeur pour le serveur une fois que ça a été calculé une fois.
Avril 2008
Afficher l’histogramme d’une image
Gezus
Royal Arno !
Merci pour tes précisions, très bonne idée de stocker l’histogramme pour ne pas le recalculer.
Puis-je te demander comment est stocké l’histogramme ?
si c’est l’image qui est stockée, ou ?
si ce sont les données brutes de l’histogramme, sont elles récupérables par une fonction portant sur le document ?
Aussi, si je comprend bien l’interêt de passer le filtre image_reduire400 avant le filtre image_histo permet de calculer l’histogramme sur une réduction de l’image à 400 pixels : Donc cela allège le travail de calcul de l’histogramme (mais celui-ci est un peu plus approximatif du coup).
Merci pour ton aide.
PS : je ne sais pas si c’est toi Arno qui est à l’origine ce bien joli site "Paris-Beyrouth", pour dire que c’est une réussite tant au plan graphique que de son contenu.
Avril 2008
Afficher l’histogramme d’une image
ARNO*
@Gezus
De mémoire et en relisant mon code ci-dessus, c’est le fichier GIF résultant qui est stocké. Pas les données brutes de l’histogramme, qui ne sont exportées nulle part.
En revanche, il est possible de s’inspirer du principe exposé ici pour travailler automatiquement à partir des données de l’histogramme. C’est par exemple le principe exposé dans « Correction automatique ».
Pour la réduction, oui c’est une bonne idée. Note que si ton image fait, au final, 400x300 pixels, ça te fait quand même un calcul sur 120 000 pixels. On réparti les informations de ces 120 000 pixels sur 256 échantillons. Donc oui on perd en précision, mais le résultat ne doit pas être non plus aberrant.
Mai 2008
Afficher l’histogramme d’une image
zeina ghannoum (fromliban chez hotmail.com)
salut ! j’aimerai bien savoir un programme pour histogramme d’image en matlab
4 janvier
Afficher l’histogramme d’une image
zelo
Intéressant, je viens de coder un truc du même genre mais moins sophistiqué (avec la librairie artichow).
http://www.electronika.fr/blog/ ?p=301
@+
il y a 4 mois
Afficher l’histogramme d’une image
denys (densy-p chez wanadoo.fr)
Il me semble que le code d’affichage d’un histogramme n’est pas complet.
Aurais-tu la possibilité de m’indiquer l’implémentation de cette fonction dans un script php.
Merci d’avance
il y a 4 mois
Afficher l’histogramme d’une image
lili (n_rah chez yahoo.fr)
je voudré ce meme code avec matlab 6p5
si vous pouviez m’aidez ça se seré trop sympa de votr part chui vrément dans le pétrin !!
merci