Paintual, blocage

Travaillant sur quelques projets de front, Paintual est un peu, beaucoup, mis à l’écart. Et comme je n’y mets pas une attention soutenue, il y a des portions de code que je dois améliorer et qui me causent des ennuis parce que je ne me souviens plus exactement de la mécanique que j’y ai mise en place.

Alors vient le temps de s’aider d’outils exprès pour ce genre de chose. En fait c’est le contraire que j’aurais dû faire, mais ce n’est pas tellement grave puisque c’est un projet qui existe essentiellement pour que je crée mes outils de création d’images: je ne le conçoit pas en premier pour être un “outil pour tous” mais s’il peut éventuellement servir à d’autres ça sera tant mieux 🙂

J’aurais dû “architecturer” certaines portions du code avant de coder, ainsi j’aurais eu un plan à suivre. Mais la plupart du temps je dois faire des essais et voir si telle idée peut se concrétiser en code. Une fois le code fait, je passe à autre chose sans prendre le temps de documenter (mis à part les précieux commentaires dans le code).

Documenter le code de façon à pouvoir, d’un coup d’oeil, voir ce qu’il contient, ce qui s’y passe et comment les différentes pièces interagissent, c’est le travail d’UML. Je ne suis pas un grand fan de la symbolique visuelle d’UML que je ne trouve pas très intuitive ni très élégante. En plus j’ai essayé plusieurs outils de création de graphiques UML et ils m’ont déçu, à part Visio, qui coûte assez cher et que je trouve encombrant comme la plupart des autres qui tentent de lier les graphiques au code dans un esprit d’automatisation qui, pour les petits projets sur lesquels je travaille, est plus nuisible pour moi pour l’instant.

Alors j’ai fait une autre recherche d’outils UML et suis tombé sur Visual Paradigm. La version complète permet de gérer tous les aspects du développement logiciel (avec un coût) mais la version “Community Edition”, gratuite, me donne l’essentiel pour ce qui est d’UML. Alors je le mets à l’essai.

Et je me rends compte que j’ai oublié presque tout d’UML: trop d’années sans y toucher.

Tout ça pour dire que je m’applique à mettre en format graphique certains aspects de Paintual de manière à ce que je puisse m’y retrouver et corriger les bogues qui restent afin d’avoir, enfin, un outil de sélection de portions d’images, comme je l’ai mentionné dans des posts précédents.

Ci-dessous, un petit exemple de graphique séquentiel en UML en construction (mais il ne faut pas considérer cet exemple comme un modèle à suivre: je réapprends).

VisualPropertyPage 2018-05-12 01

Visual Paradigm me donne un rendu graphique qui me convient. Ça pourrait être visuellement plus raffiné mais le but n’est pas de créer des oeuvres mais des plans de travail. J’aime que les diagrammes ne sont pas liés au code mais peut-être plus tard je changerai d’idée 🙂

En regardant le code “évoluer” visuellement à partir de la commande de l’utilisateur (actor) je verrai où mon code accroche et me cause souci.

Les diagrammes de séquence ne représentent jamais l’ensemble des activités possibles d’une application mais des segments de fonctionnalités. Ils doivent clairs et détaillés sans tomber dans un excès de présentation d’informations. C’est souvent à ce niveau où je tombais dans le piège de la “surdocumentation”.

Dans un tout autre ordre d’idées, j’ai installé Python sur mon ordi et ai commencé à jouer avec les “neural networks”. Je me suis procuré pour quelques dollars seulement ce livre: https://www.amazon.ca/gp/product/B01EER4Z4G , une introduction en douceur sur les neural networks et sur Python. Je vise éventuellement à pouvoir créer des GANs (Generative Adversarial Networks) car ils permettent de générer des images ou des effets et ce que j’ai vu à date me stupéfie au plus haut point d’autant que c’est en ligne avec ce que je voulais réaliser avec Paintual (mais avec des moyens tout à fait autres au départ). Ai-je déjà mentionné les travaux de Mario Klingemann ( https://twitter.com/quasimondo), c’est à voir ! Le livre en question ne va pas jusque là mais on commence par le commencement.

* * *

Working concurrently on a few projects, Paintual is being put aside a little, well a lot. And since I am not regularly into it, there are portions of code I must improve and that causes me trouble because I do not remember exactly the mechanics that I put in place.

There comes the time where some tools designed among other things for this situation could be of great help. In fact it’s the opposite that I should have done, but it’s not so bad since it’s a project that exists essentially for me to create my tools for image composition and editing: I do not conceive it first to be a “tool for everyone” but if it can be of help to other in the future, why not 🙂

I should have architectured some portions of the code before coding, so I would have had a plan to follow. But most of the time I have to experiment and see if an idea can be translated into code. Once the code is done, I move on without taking the time to document (aside from the valuable comments in the code).

Documenting the code so that one can see at a glance what’s in it, what’s going on and how the different parts interact, that’s the work of UML. I am not a big fan of the visual symbols used in UML because I do not find them very intuitive nor very elegant. In addition I tried several UML graphics tools and they disappointed me, apart from Visio, which is quite expensive and I find it bulky like most others which try to link graphics to code in a spirit of automation that, for the small projects I’m working on, is more cumbersome for me than helpful at this time.

So I did another search for UML tools and came across Visual Paradigm. The full version allows you to manage all aspects of software development (with a cost) but the “Community Edition” free version gives me the essentials for UML. So I put it to the test.

And I realize that I forgot almost everything I knew about UML: too many years without using it.

All that to say that I apply myself to put in graphical format some aspects of Paintual so that I can find and correct the remaining bugs in order to have, finally, a tool for easily and quickly selecting multiple portions of images, as I mentioned in previous posts.

Above is a small example of an UML sequence diagram under construction (but this example should not be considered as a model to follow: I am learning again).

Visual Paradigm gives me a graphical rendering that suits me. It could be visually more refined but the goal is not to create works of art but working/workable plans. I like that the diagrams are not linked to the code but maybe I’ll change my mind later 🙂

Looking at the diagram, I can see the code visually “working” from the command of the user (actor) to the result provided by the application. I will then see where my code is faulty and be able to apply a solution.

Sequence diagrams never represent all the possible activities of an application at once but specific segments of functionalities. They must be clear and detailed without overflowing with  information. It is often there that I fail and fall into the trap of “overdocumentation”.

In another note, I installed Python on my computer and started playing with neural networks. I bought this book for just a few dollars: https://www.amazon.ca/gp/product/B01EER4Z4G, a gentle introduction to neural networks and Python. My goal is to be able one day to create Generative Adversarial Networks (GANs) because they can generate images or effects that are amazing and is quite in line with what I envisioned with Paintual (but with completely different means at the beginning). Have I already mentioned the work of Mario Klingemann (https://twitter.com/quasimondo), this is a must see! The book in question does not go that far but the beginning is where everything starts.

 

Paintual, un outil de sélection

English ?  see below after the video frame 🙂

Et une aventure !

Je n’avais pas pensé que quelque chose d’aussi simple en apparence puisse demander autant de travail : du code pour créer un cadre de sélection rectangulaire, le déplacer et le redimensionner. J’avais pourtant pris soin de bien réfléchir avant de commencer, tenter d’entrevoir les écueils possibles. Et pourtant…

Mais j’ai réussi. En premier j’ai eu la bonne idée que ce cadre de sélection soit dessiné sur un canevas différent de celui sur lequel se trouve l’image, laissant ainsi le soin à WPF de redessiner l’image lorsque le cadre est déplacé. C’était une bonne affaire, d’autant que WPF peut redessiner beaucoup plus vite que si j’avais écrit tout le code à cet effet. Le canevas sur lequel je dessine le cadre de sélection s’appelle “SelectionGlass” avec comme idée principale d’appliquer virtuellement une plaque de verre sur l’image et de tracer par-dessus. Cette plaque aurait les mêmes dimensions que l’image et serait positionnée au même endroit. Ça aussi c’était facile.

J’avais pensé qu’en cliquant avec la souris et en maintenant le bouton enfoncé j’amorçais le travail de traçage du cadre de sélection. Au fur et à mesure que la souris se déplace, les dimensions du cadre sont mises à jour en temps réel. Ça aussi, ça allait bien. Je pouvais calculer la position des quatre coins du cadre et leur superposer des poignées de modification.

Une fois le cadre dessiné, il me fallait ajouter du code pour pouvoir le déplacer. Facile aussi : le cadre est une instance de System.Windows.Rectangle, une classe graphique qui contient tous les événements gérables de la souris, du stylet ou “touch”. Donc simplement réagir à MouseDown, MouseMove et MouseUp et ça allait bien. Tout en déplaçant le rectangle, les poignées suivaient, pas automatiquement, mais 4 lignes de code et c’était tout ce qu’il fallait.

Redimensionner le cadre. Les petites poignées étant aussi des instances de System.Windows.Rectangle je pensais que simplement d’utiliser une tactique MouseDown, MouseMove et MouseUp devrait suffire. Mais c’était sans compter le fait que même si on clique sur une poignée et qu’on commence à la déplacer, si le code de gestion de retraçage du rectangle et de positionnement des autres poignées n’est pas assez rapide, la souris vient à quitter la poignée et puis ça ne fait plus le travail comme on veut. D’étranges bogues apparaissent. Pour conserver la fluidité, il faut passer le contrôle de la poignée à la “SelectionGlass” qui prend, elle, toute la surface et donc garde contact avec la souris. Étape réussie.

Mais si l’utilisateur diminue la dimension du cadre au point où sa taille devient nulle ou qu’il se trouve renversé (effet miroir) là c’est du sérieux. Parce que chaque poignée est responsable d’un ensemble de modifications possibles (ex.: la poignée du coin inférieur droit peut agrandir le cadre vers la droite et vers le bas ou le rapetisser vers la gauche ou le haut ; le coin opposé en diagonale ne bouge pas tandis que les deux autres sont repositionnés en accord avec la poignée en mouvement, ouf !), il m’aurait fallu gérer quatre cas, chacun avec ses petites particularités.

Il m’est venu l’idée de considérer chaque poignée comme étant tout simplement une rotation du cadre. Ainsi si l’utilisateur déplaçait la poignée supérieure gauche, il suffisait de créer une rotation virtuelle dans le code (dont l’effet est invisible pour l’utilisateur) de manière à pouvoir travailler la transformation comme si c’était le code de la poignée  du coin inférieure droit. Vous êtes un peu perdu ? Moi aussi j’ai été perdu, et plus d’une fois.

Pour bien réussir ces transformations virtuelles, rien de tel que de travailler avec des vecteurs et des matrices. Si vous comprenez l’anglais, cette série de vidéos est très claire :  https://www.youtube.com/watch?v=fNk_zzaMoSs. Le .NET Framework propose des classes pour travailler vecteurs et matrices mais au même moment je suis tombé sur cette librairie Accord.Net qui offre une quantité de fonctionnalités diverses vraiment impressionnante. Alors, bon on ajoute la librairie au projet et on peut travailler en moins de deux avec vecteurs et matrices. Ça a bien fonctionné mais je me suis emberlificoté avec les positions, les séquences, les inversions, etc.

C’était long, mais j’ai réussi, et le code est assez clair. Une dernière chose : le cadre de sélection doit se repositionner de lui-même lorsqu’on zoome l’image et aussi lorsqu’on joue avec les barres de défilement. Détails qui se sont réglés en moins de deux (quoique mes barres de défilement nécessitent un peu de polissage).

Il me reste à faire le code qui permet la sauvegarde des sélections d’images.

Au bout du compte, j’aurai travaillé pas mal d’heures pour me faire un outil qui devrait me permettre de sauver beaucoup de temps à court terme : ouvrir une image, sélectionner une partie, cliquer sur “Entrée” ou même simplement double cliquer sur la sélection et sauvegarder avec un nom de fichier séquentiel généré automatiquement. Répéter.

* * *

And an adventure!

I did not anticipate that something so simple in appearance could require so much work: code to create a rectangular selection box, move and resize it. Though I was careful to have a work plan before starting in order to foresee any pitfalls, well…

But I succeeded. At first I had the good idea that this selection frame be drawn on a different canvas from the one on which the image is, thus leaving it to WPF to redraw the image when the selection frame is moved. It was a good deal, especially since WPF can redraw much faster than if I had written all the code for that purpose. The canvas on which I draw the selection frame is called SelectionGlass with the main idea to virtually apply a glass plate on the image and draw a selection over it. This plate would have the same dimensions as the image and would be positioned at the same place. That was easy too.

I thought that by clicking with the mouse and holding down the button I can start drawing the selection frame. As the mouse moves, the frame dimensions are updated in real time. That was good too. I could calculate the position of the four corners of the frame and superimpose them with resizing handles.

Once the frame was drawn, I had to add code to move it. Easy too: the frame is an instance of System.Windows.Rectangle, a graphics class that contains all the manageable events of the mouse, stylus or “touch.” So I just needed to add code to react to MouseDown, MouseMove and MouseUp and it was fine. While moving the rectangle, the handles followed, not automatically, but 4 lines of code sufficed.

Resizing the frame. The small handles being also instances of System.Windows.Rectangle I thought that simply using MouseDown, MouseMove and MouseUp event handlers should suffice. But it was without considering the fact that even if one clicks on a handle and starts to move it, if the management code of tracing and positioning the selection rectangle is not fast enough, the mouse gets to leave the handle and then it does not do the job any more. Strange bugs appear. To maintain fluidity, it is necessary to pass the control of the handle to the “SelectionGlass” which occupies all the surface and thus keeps in touch with the mouse. Successful step.

But if the user decreases the size of the selection frame to the point where its size becomes zero or is reversed (mirror effect) then there’s a problem. Because each handle is responsible for a set of possible modifications (eg: the handle on the bottom right corner can enlarge the frame to the right and down or shrink it to the left or the top, the opposite corner diagonally does not move while the other two are repositioned in accordance with the moving handle, phew!), I would have had to manage four cases, each with its peculiarities, and the reverse/mirror effect.

It occurred to me that if I consider each handle as four variants of the same movement and modification by virtually rotating the rectangle, I could simplify the code since I would have only one case to manage instead of four. That required to calculate transformations on the background while showing the adapted result for each handle. Something not easy to explain this in a few words and also not easy to code as I was not experienced with thinking those transformations.

To succeed in calculating these virtual transformations with a little help with vectors and matrices. This video series is very clear on the topic: https://www.youtube.com/watch?v=fNk_zzaMoSs. The .NET Framework offers classes to work with vectors and matrices, but at the same time I came across this Accord.Net library which offers an impressive number of features. So, I added the library to the project and could work with vectors and matrices in no time. It worked well but I got all mixed up more than once with positions, sequences, inversions, etc.

It took quite some time, but I succeeded, and the code is pretty clear. One last thing: the selection frame must reposition and resize itself when zooming the image and also when playing with the scroll bars. Details that I could settle easily (although my scroll bars require some fine tuning).

I still have to make the code that allows saving the image selections.

In the end, I will have worked many hours to build a tool that should allow me to save a lot of time in the short term: open an image, make a selection, click on “Enter” or even double click on the selection which is to be saved with an automatically generated sequential file name. Repeat.