Paintual – visualisation de la construction des effets en temps réel

Version 0.0.8 !

Threading

Ça n’était pas prévu mais je me suis mis à chercher pourquoi les effets dans Paintual n’étaient visible qu’une fois le travail complété alors que le dessin se met à jour sur le canevas en temps réel (ou à peu près). J’ai trouvé mais ça été assez compliqué à mettre en oeuvre.

En gros, la façon dont le .NET Framework est conçu, tout ce qui concerne le visuel est contenu dans un “thread“. On peut passer tous les calculs et opérations de l’engin de l’application (les calculs de dessin) à un ou plusieurs “threads” pour bénéficier du travail en concurrence sur les différents coeurs du processeur. Mais on ne peut pas facilement appeler des méthodes d’un thread à l’autre, il faut passer par des délégués et une gestion d’événements (enfin c’est ce que j’ai trouvé à date).

J’avais résolu le problème pour le dessin : un thread s’occupe de calculer les opérations de dessin et les inscrire sur le canevas et le thread principal où réside l’interface utilisateur demandait un rafraîchissement de l’image à toutes les 35 millisecondes. Puisque le code de calcul du dessin pouvait modifier le fichier image sans rien demander à l’interface et que l’interface avait accès au fichier image en même temps, la mise à jour ne posait aucun problème particulier. Pour que le dessin s’affiche en “temps réel” (ou à peu près), il fallait un autre thread qui contenait une horloge et à chaque 35 millisecondes, le thread envoyait un signal à l’interface pour le rafraîchissement.

Pour les effets je n’avais tout simplement pas mis la mécanique en place. Mais il y a une différence majeure. Les effets travaillent sur une copie de l’image, l’originale — toujours visible de l’interface — ne changeait pas tout au long du processus d’exécution de l’effet. Une fois l’effet terminé, la copie remplaçait l’originale et ensuite l’interface était mis à jour.

En déplaçant le code d’exécution de l’effet sur un autre thread, il n’y avait plus moyen à partir de celui-ci de pouvoir communiquer à l’interface qu’il devait y avoir un dernier rafraîchissement de l’image une fois la copie de travail remplaçait l’image d’origine, ce qui laissait une image incomplète à l’écran. Bien embêtant car l’utilisateur attendrait inutilement.

La solution que j’ai mise en place est de demander à l’interface d’écouter l’effet émettre un événement de fin de travail et de procéder à la mise à jour finale de l’image. Le code n’est pas élégant du tout : difficile à suivre (une chance que j’ai mis quelques commentaires). Cette nuit j’ai pensé à un système qui centraliserait mieux ces requêtes entre threads inspiré de ceci https://github.com/domenic/extensions/blob/master/WindowsFormsInvokingExtensions.cs  mais j’étais trop enthousiaste et fébrile de jouer avec le nouvel effet basé sur des particules.

Particules

J’ai probablement mentionné une de ces vidéos précédemment :
– https://www.youtube.com/watch?v=BjoM9oKOAKY
– https://www.youtube.com/watch?v=sor1nwNIP9A

Elles font aussi référence à d’autres vidéos (les liens sont sur les pages Youtubes). Toutes ensemble on y apprend comment jouer avec des particules, des vecteurs et des “vector flow fields” (que je pense que ça se traduit par champs de vecteurs).

En gros l’idée est que chaque particule contient des informations sur sa localisation sur le dessin à produire ainsi qu’une direction de déplacement entre chaque opération de traçage.

Quand j’ai commencé à coder tout ça je craignais tomber dans un truc délirant et compliqué pour finalement me rendre compte que c’était finalement assez simple. On peut trouver quantité d’exemples de code sur Internet : je voulais cependant construire mon propre petit engin de particules.

Les différents paramètres que j’ai imaginés devaient me permettre de créer ce genre d’effet :

watercolor sample

À la place j’ai obtenu des effets filetés, des cheveux, des racines. C’est bien joli quand même et j’ai poursuivi mon code.

radial 02

Scanner Glitch

J’ai pensé utiliser cette technique pour donner l’impression des scans glitches dont j’ai parlé auparavant. Pour l’instant le résultat est approximatif à ce que j’avais imaginé quoique, encore, bien joli en soi. Il y a tout un domaine de paramètres à explorer, ce que la vidéo ci-dessous veut montrer.

Les déviations des particules sont le résultat d’addition de vecteurs propres aux particules et ceux du vector flowfield généré à partir d’une image de bruit de Perlin aux dimensions identiques à l’image à traiter. L’intensité lumineuse des pixels de bruit détermine un angle de déviation des particules. Les propriétés de la VisualPropertyPage “Seed”, “Frequency” et “Octaves” déterminent la qualité et l’intensité du bruit. “Angular Spread” (en degrés) permet à la particule de dévier plus ou moins selon l’ouverture de l’angle en plus de la déviation imposée par le vector flowfield. “Steps” est le nombre de fois que toute l’image est balayée par les particules. Avec une valeur de 1, un seul jet de particules (de gauche à droite) est émis. Chaque particule suit les directives des vecteurs à leur pleine intensité. Lorsque le nombre est plus élevé, chaque étape produit aussi autant de particules mais leur transparence et l’intensité des vecteurs est diminué en rapport avec le nombre d’étapes pour donner une composition plus floue par superpositions successives, liant l’image d’origine avec le tracé des particules de la dernière étape.

Combiné avec le fait que maintenant Paintual peut présenter les effets en construction en temps réel, l’ensemble rend ma petite application beaucoup plus attrayante.

Radial

Revenant à l’idée de diffusion des particules dans un esprit de diffusion de l’aquarelle sur le papier, Radial propose comme je l’ai mentionné plus tôt, des cheveux ou des racines selon les valeurs des paramètres.

En gros on a “Seed”, “Frequency” et “Octaves” puisque ici aussi le bruit de Perlin sert à générer des déviations. On a aussi “Steps” mais contrairement à l’effet Scanner Glitch, la transparence reste la même pour chaque étape, l’intensité des vecteurs n’est pas affectée. Il n’y a que superpositions. Les variations sont déterminées par des valeurs aléatoires attachées à chaque particule. Ces valeurs aléatoires étant mal prise en charge (c’est mon code qui est défectueux) j’ai ajouté une propriété “Expansion” qui ouvre l’angle de dispersion davantage. Il y a aussi “Life”, la durée de vie de chaque particule. Plus la valeur de vie est élevée, plus la particule va voyager sur le canevas.

Une couleur fixe est choisie au départ et elle est modifiée avec des valeurs aléatoires au cours du traçage. Contrairement à Scanner Glitch, les couleurs des particules ne sont pas extraites de l’image. C’est juste un choix de programmation pour l’instant : des paramètres à ajouter plus tard.

Bogues

Tout ça ne va pas sans ajouter son lot de bogues à ceux qui étaient déjà là. Il faut à nouveau être bien indulgent avec cette petite créature de code.

Il y aussi quelque chose que je peux mettre dans la catégorie bogues : aucun indicateur qui permet à l’utilisateur de savoir si les opérations sont terminées. En mode développement, on peut voir le graphique des ressources du processeur changer et nous donner une indication précise. Quelque chose à ajouter dans une prochaine version.

Vidéo

Pour terminer, une autre vidéo, faite ce matin pour illustrer le nouveau terreau fertile dans lequel j’ai plongé avec les particules et les vecteurs.

Performance

Les effets avec particules se prêtent particulièrement bien au parallélisme (multi-threading) puisque les actions de chacune sont très limitées dans l’espace du canevas (un pixel modifié par particule).

GitHub

Le projet est maintenant disponible sur GitHub, code source et version installable 0.0.8  .

Paintual – Scanner Glitch

Laissons de côté les ennuis de l’interface graphique et ajoutons des effets. Inspiré par cette vidéo https://www.youtube.com/watch?v=sor1nwNIP9A (qui dure presque trois heures !), j’ai ajouté un système particulaire à Paintual. Un système primitif, tout simple, qui m’a conduit à tenter de reproduire, partiellement, les effets de numérisation comme on peut voir dans https://belisssle.com/2018/07/04/controlled-glitches/  https://belisssle.com/2018/07/05/push/ et https://belisssle.com/2018/07/10/more-scans/ . Évidemment toute l’imprécision du mouvement de glissement de la feuille sur le scanner et la finesse du grain de numérisation ne sont pas reproduits dans le nouvel effet “Scanner Glitch”, en revanche cet effet propose son propre univers de textures.

Le code fonctionne en gros comme suit : pour chaque particule, elle prend la couleur d’un pixel. On assigne à la particule une petite trajectoire à suivre. À l’arrivée, elle dépose la couleur sur le pixel où elle se trouve et copie la couleur de l’image d’origine à ses nouvelles coordonnées. Le processus est répété de gauche à droite pour toutes les rangées de pixels. Les trajectoires sont déterminées par les intensités lumineuses de pixels situés aux mêmes endroits que les particules mais venant d’une image de bruit de Perlin paramétrisable.

Pour ajouter à la fluidité du fini, toute l’opération de traçage est exécutée plusieurs fois, au choix, et à chaque passe la valeur de transparence passe de presque transparent à opaque.

Les images ci-dessous sont le résultat de superposition d’images traitées sur les originaux.

J’ai quelques changements et corrections à faire au code avant de le porter sur GitHub, dans quelques jours au plus.

 

_DSC4085

Image d’origine

_DSC4085 gl 01

Glitch 1

_DSC4085 gl 02

Glitch 2

_DSC4085 gl 03

Glitch 3

_DSC4085 gl 04

Glitch 4

_DSC4085 gl 05

Glitch 5

2018073001

Glitch from another image 1

2018073002

Glitch from another image 2

2018073003

Glitch from another image 3

Paintual 0.0.7

Le problème sur GitHub persiste toujours mais avec un petit détour en n’utilisant pas SSL ça fonctionne. Donc sur GitHub on a la version 0.0.7 qui consiste essentiellement en des améliorations concernant la validation des champs de saisie de la VirtualPropertyPage. Des icônes-signaux sont affichées si des informations sont manquantes ou incorrectes. Cependant, pas d’icône encore pour le champ de répertoire,  tout comme il n’y a pas ce mécanisme dans la VirtuaPropertyPage lorsqu’on utilise l’effet de bruit de Perlin. C’est une question de type de propriété : texte, nombre entier (int), nombre décimal (double), etc. Chacun est un cas à traiter et comme la mécanique de l’ensemble fonctionne, me suffit de l’appliquer à tous les cas. Mais une chose à la fois 🙂

Petit bogue lorsqu’on a utilisé l’outil QuickSelect et qu’on passe à l’effet de bruit de Perlin: la marquise de sélection ne disparaît pas (zut!).

Le formulaire des préférences prend forme parce que je travaille à rendre l’interface bilingue et il faut spécifier à l’application où se trouvera le dictionnaire des étiquettes (Fichier / File, Ouvrir / Open, etc.) français-anglais qui n’est en fait qu’un fichier XML qui contient les étiquettes dans les deux langues.

Pour revenir à GitHub, il ne faut pas tenir compte des projets EngineC et EngineCLI qui ne compilent pas. Une petite erreur de ma part de les avoir ajouté trop vite sans vérifier. Finalement, un installable de la version 0.0.7 est disponible ici : https://github.com/belisssle/Paintual/releases/tag/0.0.7

Et puis si vous aimez la petite musique, la voici en entier :

* * *

The problem on GitHub still persists but with a little trick up my sleeve (bypassing SSL) it works. So on GitHub we have version 0.0.7 which mainly consists of improvements concerning the validation of the input fields in the VirtualPropertyPage. Flags are displayed if information is missing or incorrect. However, there is still no flag for the directory field, just as there is no such mechanism in the VirtuaPropertyPage when using the Perlin noise effect. It’s a matter of property type: text, integer (int), decimal (double), and so on. Each is a case to be treated individually and as the global mechanics works, it is just a matter for me to complete/code all cases. But one thing at a time 🙂

A little bug when using the QuickSelect tool and switching to the Perlin noise effect: the marquee selection does not go away (damn!).

The preferences form takes shape because I am working on making the interface bilingual and it is necessary to specify within the application where the labels dictionary (File / File, Open / Open, etc.) is located. The French-English dictionary is in fact a simple XML file containing labels in both languages.

Back to GitHub, do not pay attention to EngineC and EngineCLI projects: they do not compile but they don’t prevent the application from running. A small mistake of mine to have added these too quickly without checking. Finally, an installable version 0.0.7 is available here: https://github.com/belisssle/Paintual/releases/tag/0.0.7

 

Paintual de retour sur GitHub

Un obscur problème de certificat SSL. Plusieurs segments de réponse étaient applicables à d’autres modes d’utilisation de GitHub (moi j’avais GitHub Desktop). Donc j’ai désinstallé GitHub Desktop pour installer Git et ensuite TortoiseGit (j’aurais pu prendre n’importe quel autre “shell”). Désactivé la vérification SSL (je sais c’est pas prudent mais pour tester faut parfois risquer) et ça fonctionné.

Sur GitHub on peut trouver la plus récente version du code source de Paintual mais sans ses fichiers d’installation. Il y a également des fichiers que j’avais retiré du projet mais puisqu’ils étaient resté dans le répertoire de développement, ils se sont retrouvés sur GitHub : un autre pépin à régler.

Me resterait à télécharger le code à partir de GitHub et le faire fonctionner dans VisualStudio pour voir si cette version publique compile et exécute correctement. À faire plus tard car là à 2h30 c’est presque le temps de dire que la journée est terminée 🙂

Ajout 2018-07-24

J’ai vérifié et la version publique du code source compile correctement et le projet peut être exécuté. Il y reste les deux répertoires Avalon qui ne sont plus utilisés et que, pour une raison X, je n’arrive pas à faire disparaître. Un petit problème à résoudre à la fois 🙂

En résumé, le problème n’est pas résolu mais j’ai compris un peu mieux ce qui se passe et j’ai pu trouver une voie d’évitement temporaire. Étant donné que Paintual n’est pas un projet très important, je doute qu’une personne mal intentionné se donne la peine de monitorer mes transferts de fichiers et les corrompre, ce que le mécanisme SSL permet d’éviter si j’ai bien compris.