Question :
Principe des GdkPixbufs.
Réponse:
Le GdkPixbuf est une structure dans laquelle on va pouvoir trouver différentes informations sur l'image ainsi que les données brutes de l'image.
Il existe plusieures manières de créer une image dans un GdkPixbuf:
- Soit en déclarant une image vierge.
- Soit en copiant toute ou partie d'une image existante.
- Soit en chargeant une image depuis un support (DD, CD, DVD ...).
Une fois créée, les données brutes sont accessibles avec la fonction guchar *gdk_pixbuf_get_pixels(const GdkPixbuf *pixbuf);.
Comment sont ordonnées les données?
-----------------------------------
Il est important de savoir qu'une image n'est pas forcément codée avec 3 octets par pixels. On peut aussi en utiliser 4! Donc avant de vouloir "triturer" ces données il faut connaître l'encodage. Pour cela on dispose de la fonction int gdk_pixbuf_get_n_channels(const GdkPixbuf *pixbuf); qui nous renverra le nombre d'octet par pixel.
A quoi peut bien servir ce quatrième octet?
-------------------------------------------
Cet octet permet de gérer la transparence de l'image. Vous pouvez l'ignorer si cette information ne vous sert à rien. La gestion de la transparence est un autre sujet que ne sera traîté ici.
Comment accéder aux données?
----------------------------
Pour accéder aux données, rien de plus simple si on peut dire. Le pixel en haut à gauche se trouve aux adresses suivantes :
// Récupération du pointeur sur les données brutes.
guchar *pixel=gdk_pixbuf_get_pixels(pixbuf);
// Récupération des composantes du pixel de coordonnées (0,0)
guchar red, green, blue;
red=pixel[0];
green=pixel[1];
blue=pixel[2];
Tout ceci c'est bien joli, mais comment faire si la couleur est codée sur 4 octets? pixel[3] correspond alors à l'information de transparence. Ignorez-le.
Automatisation d'accés.
-----------------------
Admettons que nous disposions d'une image de 100x50. Comment accéder rapidement à tout pixel de cette image? Je vous donne ici le code d'une fonction simple qui vous renvoie les composantes des coordonnées d'un pixel transmises.
Cette fonction renvoie FALSE si vous donnez une coordonnée hors image ou lorsque l'image vaut NULL.
gboolean gdkpixbuf_get_colors_by_coordinates(GdkPixbuf *pixbuf, gint x, gint y, guchar *red, guchar *green, guchar *blue)
{
guchar *pixel=NULL;
gint channel=0;
gint width=0;
if (!pixbuf) return FALSE;
if (x<0 || y<0) return FALSE;
if (x>gdk_pixbuf_get_width(pixbuf)) return FALSE;
if (y>gdk_pixbuf_get_height(pixbuf)) return FALSE;
pixel=gdk_pixbuf_get_pixels(pixbuf);
channel=gdk_pixbuf_get_n_channels(pixbuf);
width=gdk_pixbuf_get_width(pixbuf);
*red = pixel[(x*channel)+(y*width*channel)];
*green = pixel[(x*channel)+(y*width*channel)+1];
*blue = pixel[(x*channel)+(y*width*channel)+2];
return TRUE;
}
Dans le même ordre d'idée on peut "inverser" cette fonction pour afficher un pixel. Voila une autre fonction qui à le même déroulement mais qui cette fois affecte une couleur à un pixel.
gboolean gdkpixbuf_set_colors_by_coordinates(GdkPixbuf *pixbuf, gint x, gint y, guchar red, guchar green, guchar blue)
{
guchar *pixel=NULL;
gint channel=0;
gint width=0;
if (!pixbuf) return FALSE;
if (x<0 || y<0) return FALSE;
if (x>gdk_pixbuf_get_width(pixbuf)) return FALSE;
if (y>gdk_pixbuf_get_height(pixbuf)) return FALSE;
pixel=gdk_pixbuf_get_pixels(pixbuf);
channel=gdk_pixbuf_get_n_channels(pixbuf);
width=gdk_pixbuf_get_width(pixbuf);
pixel[(x*channel)+(y*width*channel)] = red;
pixel[(x*channel)+(y*width*channel)+1] = green;
pixel[(x*channel)+(y*width*channel)+2] = blue;
return TRUE;
}
Conclusion.
-----------
Le GdkPixbuf est la base de tout traîtement d'image sérieux avec GTK+. The Gimp en est le répresentant. Plutôt que d'essayer de "monter une usine à gaz" en empilant des GtkImage dans des GtkTable et autres GtkBox, je vous enclins à vous pencher un peu sur cette manière de "dessiner". De nombreuses fonctions sont à votre disposition pour manipuler des GdkPixbuf. Leur affichage final ne pose aucun problème puisque vous pouvez les intégrer directement dans un GtkDrawingArea ou bien les "convertir" en GtkImage.
Partager