Programme de dessin Bitmap → Super Drawstat
Posté le 12/09/2018 19:20
Suite aux débats mené sur ce topic pour concevoir un algo capable de convertir une image bitmap en MDS (Multi DrawStat), j'ai été frustré qu'aucune solution viable n'ait encore vu le jour pour permettre de convertir une image bitmap en un SDS (Super Drawstat), ce qui est différent.
J'ai donc tenté de mettre au point un programme en Javascript qui permettrait de faire cela manuellement. Voici ce que j'obtins dans un premier lieu :
Un programme à peu près fonctionnel au CSS bâclé, avec un script assez laid. Cliquez dans le canvas pour y poser des points, desquels découleront les lignes de votre dessin. Les points de couleur différente ne sont pas liés entre eux.
Inconvénient majeur de ce programme : vous n'avez pas la possibilité de voir se tracer les lignes ! Je peux vous dire que c'est chiant de dessiner un sprite à l'aveuglette et de devoir attendre de voir le dessin sur calto pour connaître le résultat. GRRRR !
J'ai donc implémenté une fonction pour tracer les lignes pixel par pixel en m'appuyant sur l'algorithme de Bresenham. J'ai rajouté aussi deux lignes de CSS et voici le résultat :
Le tracé rouge correspond à la ligne qui joint le dernier point au curseur, ce qui permet de visualiser en direct la ligne qu'on s'apprête à tracer.
Seulement, j'ai un problème. Le résultat oncalc diffère de ce que trace mon programme ! Gargl !
Pour vous donner une idée, voici le script en JS :
function plotLine(firstX, firstY, secondX, secondY, cc) {
if (Math.abs(secondY - firstY) < Math.abs(secondX - firstX)) {
//Si la différence entre les abscisses est plus grandes que la différence entre les ordonnées...
if (firstX > secondX) {
//Si le premier point a une abscisse plus grande que le deuxième, on inverse.
plotLineLow(secondX, secondY, firstX, firstY, cc);
} else {
plotLineLow(firstX, firstY, secondX, secondY, cc);
}
} else {
//Autrement, on utilise plotLineHigh.
if (firstY > secondY) {
//Si le premier point a une ordonnée plus grande que le deuxième, on inverse.
plotLineHigh(secondX, secondY, firstX, firstY, cc);
} else {
plotLineHigh(firstX, firstY, secondX, secondY, cc);
}
}
}
Voici ensuite les fonctions plotLineHigh et plotLineLow. Je doute que vous n'ayez besoin de les lire.
function plot(X, Y, cc) {
cc.fillRect(X,Y,1,1);
}
function plotLineLow(firstX, firstY, secondX, secondY, cc) {
var dx = secondX - firstX;
var dy = secondY - firstY;
var yi = 1;
if (dy < 0) { yi = -1; dy = -dy; }
var D = 2*dy - dx;
console.log ("dx = " + dx + " | dy = " + dy + " | D = " + D);
var y = firstY;
for (var x = firstX; x <= secondX; x++) {
plot(x, y, cc);
if (D > 0) {
y += yi;
D -= 2*dx;
}
D += 2 * dy;
}
}
function plotLineHigh(firstX, firstY, secondX, secondY, cc) {
var dx = secondX - firstX;
var dy = secondY - firstY;
var xi = 1;
if (dx < 0) { xi = -1; dx = -dx; }
var D = 2*dx - dy;
console.log ("dx = " + dx + " | dy = " + dy + " | D = " + D);
var x = firstX;
for (var y = firstY; y <= secondY; y++) {
plot(x, y, cc);
if (D > 0) {
x += xi;
D -= 2*dy;
}
D += 2*dx;
}
}
En gros, la fonction
linePlot permet de tracer la ligne, comme vous vous en doutez. Elle utilise deux fonctions différentes :
plotLineLow quand l'écart entre les abscisses des deux points est plus grand que l'écart entre leurs ordonnées (comprend donc les lignes horizontales), et
plotLineHigh dans le cas inverse.
Seulement, je me demande si j'ai choisi le bon algorithme (il me semble que oui) et aussi si l'erreur ne se situerait pas dans le fait que plotLine inverse les points A et B si B a une abscisse/ordonnée plus basse que A.
J'ai besoin de vos conseils !
Fichier joint
Citer : Posté le 12/09/2018 19:34 | #
Casio utilise bien l'algo de Bresenham, mais je crois bien que DS avait dit que les points sont inversés (et l'ordre compte pour les lignes en diagonale). Pour vérifier, trace juste une ligne de 3x2.
Sinon tu peux toujours copier coller l'algo de BIDE ou de DS et l'adapter pour le JS (je pense que celui de BIDE serait le mieux, la syntaxe est quasi pareille).
Ecrivez vos programmes basic sur PC avec BIDE
Citer : Posté le 12/09/2018 19:35 | #
Le Bresenham de la calculatrice est une variante dont les paramètres initiaux sont un peu ajustés. T'as regardé la fonction de Darks dans son générateur de MDS ?
Citer : Posté le 12/09/2018 19:37 | #
Non, je n'ai pas regardé. Je ne sais pas trop comment je peux aller voir tout ça ><
Citer : Posté le 12/09/2018 19:41 | #
Apparemment :
Citer : Posté le 12/09/2018 19:48 | #
Donc il a utilisé ça ? https://pypi.org/project/bresenham/
Citer : Posté le 12/09/2018 19:49 | #
Tout à fait
Citer : Posté le 12/09/2018 19:50 | #
Et merde, je n'ai plus Git. Est-ce possible de consulter le code source sans avoir recours au git clone ?
Citer : Posté le 12/09/2018 19:51 | #
Tu peux juste prendre celle là :
https://git.planet-casio.com/Zezombye/BIDE/blob/master/src/zezombye/BIDE/MultiDrawstatGenerator.java#L358
Ecrivez vos programmes basic sur PC avec BIDE
Citer : Posté le 12/09/2018 19:51 | #
Dans Download files à droite, tu peux télécharger le fichier .whl et ensuite pip3 install truc.whl pour installer le module
(Tu peux aussi accéder au code, mais s'il marche pour Darks, il marchera pour toi aussi.)
Citer : Posté le 12/09/2018 19:54 | #
En fait je pense que j'ai trouvé : https://github.com/encukou/bresenham/blob/master/bresenham.py
Alors c'est exactement ça que DS a utilisé pour son programme ? Mais il avait pas dû inverser des trucs pour que ça corresponde bien ?
Citer : Posté le 12/09/2018 19:55 | #
Dans le code de Darks sur le Gitlab, c'est utilisé verbatim. Vois par toi-même : https://git.planet-casio.com/Dark-Storm/sprite-optimizer/blob/master/sprite-optimizer.py#L32
Citer : Posté le 13/09/2018 10:33 | #
Je dois avouer que j'aurai du commenter un peu plus ce code. Je vais essayer de faire ça ce soir.
Bref, en tout cas, comme Lephe l'a indiqué, j'utilise un "vrai" bresenham pour générer mes lignes. Mais une fois que j'ai besoin de les dessiner, j'inverse le sens dans le code pour Casio :
ligne_casio = ((x', y'), (x, y))
C'est à la ligne #127 que j'effectue cette permutation.
Mais oui, le code n'est pas très clair en l'état actuel, je vais le clarifier.
Citer : Posté le 13/09/2018 12:51 | #
Ah, merci pour cette indication. Je vais faire quelques essais et je vous dirai si j'ai abouti au résultat escompté.
Ajouté le 13/09/2018 à 15:58 :
C'est bon, j'ai réussi !
Ajouté le 13/09/2018 à 16:03 :
Oh, dites : si je soigne un peu plus le CSS et que je peaufine deux ou trois trucs, ça vous dit de mettre cet outil en ligne sur le site ? Ça pourrait s'avérer utile !
Citer : Posté le 13/09/2018 18:48 | #
On pourrait le mettre sur tools.planet-casio.com... ah en fait non, pas sûr qu'on ait encore les accès !
Ouais, c'est faisable, vraiment NP.
Est-ce que tu as une description un peu concise de l'algorithme en tous cas ? J'admets ne pas avoir le temps de me plonger dans ton code... en quoi est-ce que ça diffère de la méthode de Darks par exemple ?
Citer : Posté le 13/09/2018 19:03 | #
Si tu veux, je pourrai rédiger un topic pour indiquer comment s'en servir de manière détaillée.
En gros, il s'agit d'un logiciel de dessin. L'utilisateur importe une image (l'image de son sprite), zoome comme bon lui semble, puis clique sur le canvas pour tracer des points et des lignes. Il dessine donc des lignes avec un code couleur (les lignes avec des couleurs différentes ne sont pas reliées entre elles). En cliquant, on peut voir le nombre de points.
Enfin, une fois le travail terminé, il n'y a plus qu'à cliquer sur "Générer le code" pour obtenir la liste à insérer directement dans le programme. Contrairement à BIDE ou au Sprite Optimizer, ce programme fournit une liste de coordonnées pour réaliser un Super Drawstat, et non un MDS. On peut les obtenir sous la forme { 1.01, 5.12, 6.08... ou bien sous forme de coordonnées complexes.
Le problème, maintenant, c'est que j'ai réalisé mon programme en local : la manière avec laquelle je récupère les images avec le <input type="file"> ne fonctionnerait pas une fois que le programme sera en ligne, sur un serveur. En gros, le input se contente de me retourner le nom de l'image quand je l'utilise, autrement dit ça ne fonctionne que si l'image se trouve dans le même dossier.
Citer : Posté le 13/09/2018 19:04 | #
Si t'as mis des chemins relatifs (genre /img/truc.png) ça ira parfaitement bien.
Ecrivez vos programmes basic sur PC avec BIDE
Citer : Posté le 13/09/2018 19:05 | #
Aaaah oui, c'est vrai, c'est manuel. J'avais oublié cela ! C'est bon de me le rappeler.
Citer : Posté le 13/09/2018 19:28 | #
Si t'as mis des chemins relatifs (genre /img/truc.png) ça ira parfaitement bien.
Nope, il faut que l'image que tu veux traiter soit dans le même dossier que le .html
Les images du css, à la rigueur osef, c'est facilement adaptable.
Y'a pas moyen d'importer l'image en local ?
Citer : Posté le 13/09/2018 19:45 | #
Il semblerait qu'avec l'attribut baseURI, c'est possible :
file:///D:/BACKUP16-08-2018/Projet%20RPG/Sprite/SpriteGenerator.html
Citer : Posté le 13/09/2018 20:05 | #
C'est commenté, j'ai push les modifs à l'instant