vendredi 6 juillet 2018

Chapitre 39 :Modification du curseur de la souris et chargement d’une image BMP


Nous reprenons un chapitre du document xlibbook pour montrer comment modifier la forme du curseur de la souris. J’ai ajouté à l’exemple donné le chargement et l’affichage d’une image au format BMP.
Dans ce programme, j’ai aussi essayé d’améliorer la gestion des évènements en stockant en fin de structure X11 des fenêtres, l’adresse de la procédure de gestion des évènements à appeler pour la fenêtre concernée. Pour cela nous déclarons une table des fenêtres crées avec autant de structure Fenêtre que de fenêtres plus une. La dernière servira de borne d’arrêt lors de la recherche.
Comme dans le programme précédent, nous reprenons les définitions des bitmap du curseur de la souris et de son masque données par le tutoriel sous la forme d’une série de .byte.
Dans le code, nous reprenons comme auparavant les procédures de connexion au serveur, de chargement des polices et des couleurs (même si nous n’en avons pas l’utilité dans ce programme), la création de la fenêtre principale et la création des contextes graphiques. Nous modifions la procédure de création des images pour convertir les 2 images du curseur à partir de leur définition de la .data.
Remarque : dans la création de la fenêtre principale, j’ai voulu tester la possibilité d’avoir une icone de la fenêtre sous la forme d’une image. J’ai donc créée avec le logiciel bitmap une image que j’ai chargée dans la procèdure lectureimage. Puis j’ai passé le pointeur crée à la fonction XSetStandardProperties. Mais cela n’a rien changé lors de l’affichage de la fenêtre (même en réduisant celle-ci). Dès que j’aurais un peu plus de temps, j’essaierai de trouver le problème (ou peut être que le serveur XWing ne prends pas cela en compte !!!)
Nous ajoutons ensuite la création du curseur de la souris par l’appel à la fonction X11 XCreatePixmapCursor à laquelle nous passons les 2 images précédemment créées. Ceci permet de faire apparaitre le curseur sur des fonds différents.
Ensuite, nous créons 3 fenêtres à l’intérieur de la fenêtre principale, les 2 premières comme sur l’exemple du tutoriel, la 3ième en bas à droite servira à afficher l’image de l’icône créée pour la fenêtre principale. Ceci afin de vérifier que l’image lue depuis le fichier et convertie était correcte.
Pour la 4ième fenêtre, nous allons d’abord charger une image au format bmp (Coquelicots.bmp) stockée dans le même répertoire que le programme afin de récupérer ses dimensions. Celles-ci nous serviront à créer la fenêtre exactement à la même taille. Pour la lecture et le chargement d’une image BMP, vous vous souvenez peut être que j’avais déjà fait cela pour l’afficher par l’intermédiaire du frameBuffer. J’ai donc récupéré le code écrit à ce moment là, je l’ai adapté et rendu plus autonome (pour pouvoir être réutilisé dans d’autres programmes ou dans une librairie). Les buffers nécessaires sont adaptées à la taille de l’image lue et crées sur le tas (voir un post précédent sur l’allocation mémoire sur le tas). Ainsi le programme appelant, n’a pas à se préoccuper d’allouer de la place pour l’image. Il faut 2 buffers pour stocker les codes RGB de chaque pixel car le stockage au format BMP est inversé par rapport à l’image réelle. Il y a aussi quelques subtilités dans la longueur de chaque ligne pour ce format d’image. Je vous laisse le soin de lire les commentaires si vous voulez améliorer cette partie !!!!
Vous remarquerez que dans chaque procédure de création de fenêtre, nous stockons dans la structure l’adresse de la fonction à appeler pour chaque évènement.
Ainsi dans la procédure de gestion des évènements, nous nous contentons de balayer la table des fenêtres pour retrouver la structure de la fenêtre concernée, puis de récupérer l’adresse de la fonction dans le registre r2 et nous appelons la procédure par l’utilisation de l’instruction blx r2.  Ensuite dans chaque fonction, nous pouvons tester plus précisément l’événement détecté et réagir en conséquence. Pour les 3 premières fenêtres secondaires, nous ne faisons rien et pour la 4ième, nous testons l’évènement expose pour ré afficher l’image bmp si la fenêtre a été masquée.
A l’exécution, en balayant les différentes fenêtres et le bandeau haut, vous voyez les changement de forme du curseur et sa lisibilité parfaite quelle que soit le fond.
Vous voyez que l’image BMP s’affiche correctement avec les bonnes couleurs mais qu’il y a quand même un certain délai. En lisant les explications du tutoriel, on s’aperçoit que la fonction XCreateImage crée l’image sur le poste client (donc le raspberry) et que c’est la fonction XPutImage qui la transfère sur le serveur ce qui peut prendre un certain temps !!
Exercice : Chercher une image d’un beau bouton, la mettre au format .bmp, puis la charger dans un programme et l’afficher dans une fenêtre bouton.
                Améliorer le code précédent en cherchant une image d’un bouton appuyé et afficher cette image lorsque l’on a cliqué sur le bouton (et bien sûr réafficher l’image du premier bouton lorsque la souris quitte le bouton).
                Dans le tutoriel de Ross Maloney, il montre un exemple de chargement d’une image en couleur avec un format XPM. Je n’ai pas réussi à utiliser cette fonction car il doit falloir une librairie particulière. Pour créer des images de ce format il faut charger sur le Raspberry le package pixmap et utiliser le logiciel pixmap (même principe que bitmap). Donc exercice : chercher la librairie qui permet d’utiliser les fonctions XPM, programmez un exemple d’affichage d’une image de ce format (voir l’exemple du tutoriel).

Je terminerais avec ce programme les exemples d'utilisation de X11. Je vous laisse le soin de découvrir toutes les autres possibilités. 
Je reprendrais ce blog à la fin des vacances.

Chapitre 38 : gestion des images avec X11


Nous allons commencer à partir de l’exemple du tutoriel de Ross Maloney (encore merci pour son document) de créer une image en noir et blanc à partir de sa définition sous la forme d’une suite d’octets. Nous allons aussi y ajouter la lecture d’une image toujours en noir et blanc à partir d’un fichier.
En effet en lisant, le tutoriel je me suis aperçu que l’on pouvait facilement créer des images en noir et blanc avec le logiciel bitmap. En première recherche, ce programme ne figurait pas sur mon raspberry. En fait il fait partie du package x11-apps qu’il faut installer avec la commande sudo apt-get install x11-apps. La prise en main du logiciel est rapide vu sa simplicité. J’ai donc créée une image d’un simple cercle que j’ai enregistré dans un fichier img2 dans le même répertoire que notre programme. J’ai vu dans un document sur internet que cette image pouvait avoir l’extension .btm. C’est peut être une bonne idée pour repérer ce type de fichier !!
Pour la création à partir de sa définition, j’ai repris exactement les codes donnés dans le tutoriel. Je n’ai pas trouvé comment coder une instruction sur plusieurs lignes alors j’ai ajouté autant de .byte que de lignes de codes nécessaires.
Dans notre programme, nous reprenons la séquence de programmation des fonctions X11 : ouverture connexion serveur, chargement des polices, création de la fenêtre principale, création des contextes graphiques et gestion des évènements. Le fond de la fenêtre principale est de couleur rouge, le code RGB est récupéré par appel de la fonction XAllocNamedColor après avoir cherché le colormap par défaut par la fonction XDefaultColormap. Ceci est fait pour montrer l’utilisation de ces fonctions car j’aurais pu donner directement le code RGB de la couleur rouge. Ici le nom de la couleur demandé est « red » et il faudrait trouver aussi le nom de toutes les autres couleurs possibles (en anglais !!). Bonne recherche.
 Nous ajoutons une routine de création de l’image à partir de sa définition en appelant la fonction XCreatePixmapFromBitmapData.
Nous ajoutons aussi une routine de lecture du fichier image img2 en appelant la fonction XReadBitmapFile. Ces 2 fonctions retournent un pointeur vers une structure pixmap qui va nous permettre l’affichage.
Ensuite dans la gestion des évènements, nous ne gérons que la fermeture et le clic des boutons de la souris. Si le bouton 1 (le gauche) est cliqué, nous affichons à l’endroit du clic l’image créée à partir de sa définition (et identique à celle du tutoriel) sinon nous affichons l’image lue à partir du fichier img2. Cette image est un cercle blanc sur fond rouge. Vous remarquerez que si vous cliquez sur une image 1 avec le bouton droit, le cercle blanc est bien dans un petit carré rouge.
Voici le résultat :


Autre remarque : les boutons centre et droit de la souris sont numérotés 2 et 3.
Vous pouvez aussi inverser dans la création des contextes graphiques les valeurs Background et Foreground pour inverser les images. Vous pouvez aussi modifier la couleur de ces 2 paramètres car en effet les images bitmap ne sont constituées que de 0 et de 1 sans signification de couleurs et c’est le contexte graphique qui va donner la valeur des couleurs pour le 0 et pour le 1.
Pour l’explication du codage d’une image, veuillez vous reportez à la documentation disponible sur internet (mais il vaut mieux utiliser le logiciel bitmap sur le  raspberry)