Nouveau site-utilitaire aujourd'hui: art-dump maker
Le principe est d'accoler des images pour constituer un "art dump", c'est à dire une seule image les regroupant toutes. C'est souvent utilisé par les dessinateurs pour éviter d'uploader 40 esquisses/croquis/images qu'ils jugent pas terribles.
Ces expressions ont été faites par http://doragon-hane.deviantart.com/ pour Dracca. C'est un exemple d'utilisation des art-dump: poster 1 image sur deviantart pour chaque expression, c'est long, chiant et cela spam les watchers. D'où le artdump.
Disponible à cette adresse: https://xenos.reinom.com/art-dump-maker/
Techniquement, c'est "juste" un canvas dans lequel je dessine les images. Rien n'est uploadé: le sélecteur de fichier sert à ajouter des images à la liste à dumper (cf les sources JS) via URL.createObjectURL(this.files[i]) et un simple document.createElement('img') pour chacune d'elle. Une fois l'utilisateur satisfait de cette liste (il peut virer des images via un .removeChild), il lance la génération.
La partie la plus complexe a alors été de déterminer un algorithme de placement des images. Initialement, je voulais en implémenter un s'approchant de "comment agencer des rectangles de taille différente dans le plus petit rectangle possible". Mais l'implémentation était compliquée...
Du coup, j'ai tenté autrement: créer un canvas vide (0x0) et ajouter chaque image une à une. Si deux images se surperposent, on tire une nouvelle position. Si aucune position ne marche, on élargit le canvas. Mais la durée de traitement explose (même en essayant d'optimiser façon "ne tirer que des positions avec des chances de marcher").
J'ai donc appliqué une nouvelle idée qui m'est venue en observant un des premiers essais de dump: je pars d'un canvas 0x0, et je définis des "positions potentielles", la première étant "coin haut gauche de l'image à ajouter en 0;0". A chaque image à rajouter, je teste toutes les positions acceptables. Si l'image rentre dans l'une d'elles, alors je l'ajoute à cette endroit. Si l'image ne rentre nulle part, j'élargis le canvas (soit en largeur, de la même largeur que l'image à rajouter, et je réitère l'algo, soit en hauteur, selon le même principe). Enfin, quand une image est rajoutée dans le dump, elle crée 8 nouvelle "positions potentielles" qui remplacent la position précédente.
De cette manière, les images sont toujours jointives par au moins 1 bord, et le canvas est à peu près de la taille minimale possible. Note que j'ordonne aussi les images de la plus grande à la plus petite (à peu près, histoire de laisser un peu "d'aléatoire" bien que celui-ci soit en fait du faux aléatoire, à base de sinus, car Array.sort(callback) requière une callback qui soit déterministe donc exempte de tout Math.random).
J'ai aussi rajouté un scale down des images car Firefox plante sinon quand le canvas devient trop grand (et Opera est en rade aussi). Pour la sauvegarde du fichier, une simple ancre HTML suffit, alors un attribut "download" et un "href" valant l'URL du Blob du contenu du canvas
C'est encore potentiellement améliorable, mais ce sera suffisant pour l'instant
Le principe est d'accoler des images pour constituer un "art dump", c'est à dire une seule image les regroupant toutes. C'est souvent utilisé par les dessinateurs pour éviter d'uploader 40 esquisses/croquis/images qu'ils jugent pas terribles.
Ces expressions ont été faites par http://doragon-hane.deviantart.com/ pour Dracca. C'est un exemple d'utilisation des art-dump: poster 1 image sur deviantart pour chaque expression, c'est long, chiant et cela spam les watchers. D'où le artdump.
Disponible à cette adresse: https://xenos.reinom.com/art-dump-maker/
Techniquement, c'est "juste" un canvas dans lequel je dessine les images. Rien n'est uploadé: le sélecteur de fichier sert à ajouter des images à la liste à dumper (cf les sources JS) via URL.createObjectURL(this.files[i]) et un simple document.createElement('img') pour chacune d'elle. Une fois l'utilisateur satisfait de cette liste (il peut virer des images via un .removeChild), il lance la génération.
La partie la plus complexe a alors été de déterminer un algorithme de placement des images. Initialement, je voulais en implémenter un s'approchant de "comment agencer des rectangles de taille différente dans le plus petit rectangle possible". Mais l'implémentation était compliquée...
Du coup, j'ai tenté autrement: créer un canvas vide (0x0) et ajouter chaque image une à une. Si deux images se surperposent, on tire une nouvelle position. Si aucune position ne marche, on élargit le canvas. Mais la durée de traitement explose (même en essayant d'optimiser façon "ne tirer que des positions avec des chances de marcher").
J'ai donc appliqué une nouvelle idée qui m'est venue en observant un des premiers essais de dump: je pars d'un canvas 0x0, et je définis des "positions potentielles", la première étant "coin haut gauche de l'image à ajouter en 0;0". A chaque image à rajouter, je teste toutes les positions acceptables. Si l'image rentre dans l'une d'elles, alors je l'ajoute à cette endroit. Si l'image ne rentre nulle part, j'élargis le canvas (soit en largeur, de la même largeur que l'image à rajouter, et je réitère l'algo, soit en hauteur, selon le même principe). Enfin, quand une image est rajoutée dans le dump, elle crée 8 nouvelle "positions potentielles" qui remplacent la position précédente.
De cette manière, les images sont toujours jointives par au moins 1 bord, et le canvas est à peu près de la taille minimale possible. Note que j'ordonne aussi les images de la plus grande à la plus petite (à peu près, histoire de laisser un peu "d'aléatoire" bien que celui-ci soit en fait du faux aléatoire, à base de sinus, car Array.sort(callback) requière une callback qui soit déterministe donc exempte de tout Math.random).
J'ai aussi rajouté un scale down des images car Firefox plante sinon quand le canvas devient trop grand (et Opera est en rade aussi). Pour la sauvegarde du fichier, une simple ancre HTML suffit, alors un attribut "download" et un "href" valant l'URL du Blob du contenu du canvas
C'est encore potentiellement améliorable, mais ce sera suffisant pour l'instant