img2calc : images Python affichables avec zoom !
Posted: 26 May 2021, 09:56
Nous t'avions déjà parlé d'img2calc, notre service universel et gratuit de conversion d'images pour calculatrices.
La semaine dernière, nous rajoutions la gestion des scripts Python à img2calc.
Tu pouvais convertir ton image en un script Python compatible au choix avec l'une des bibliothèques de tracé par pixels offertes par nos calculatrices :
Les images obtenues telles qu'inscrites dans les scripts générés sont optimisées en taille. À ce sujet, nous te renvoyons à l'article précédent.
Leur affichage s'effectue via une fonction
Nos images étant compressées en RLE leur affichage s'effectue la plupart du temps à coups d'appels à la primitive fill_rect(x, y, largeur, hauteur) afin de tracer des lignes horizontales, c'est-à-dire des rectangles de 1 pixel de hauteur.
Il n'y a que la bibliothèque casioplot qui ne fournit pas de telle primitive, et pour laquelle on effectue à la place une boucle d'appels à la primitive set_pixel().
La semaine dernière, nous rajoutions la gestion des scripts Python à img2calc.
Tu pouvais convertir ton image en un script Python compatible au choix avec l'une des bibliothèques de tracé par pixels offertes par nos calculatrices :
- ti_draw (TI-Nspire CX II)
- graphic (TI-Nspire CX II avec KhiCAS, TI-Nspire CX avec KhiCAS et NumWorks avec KhiCAS)
- nsp (TI-Nspire avec Micropython)
- ti_graphics (TI-83 Premium CE et TI-84 Plus CE éditions Python)
- casioplot (Casio Graph 90/35+E II, fx-9750/9860GIII et fx-CG50)
- hpprime (HP Prime)
- kandinsky (NumWorks)
Les images obtenues telles qu'inscrites dans les scripts générés sont optimisées en taille. À ce sujet, nous te renvoyons à l'article précédent.
Leur affichage s'effectue via une fonction
draw_image(rle, x0, y0, w, pal, itransp=-1)
incluse dans les scripts en question, avec :- rle : les données image compressées en RLE
- x0 et y0 : les coordonnées en pixels du coin supérieur gauche où commencer l'affichage de l'image
- w : la largeur en pixels de l'image
- pal : la palette de couleurs à utiliser pour l'affichage de l'image
- itransp : l'index dans la palette d'une éventuelle couleur transparente, ou sinon -1
Nos images étant compressées en RLE leur affichage s'effectue la plupart du temps à coups d'appels à la primitive fill_rect(x, y, largeur, hauteur) afin de tracer des lignes horizontales, c'est-à-dire des rectangles de 1 pixel de hauteur.
Il n'y a que la bibliothèque casioplot qui ne fournit pas de telle primitive, et pour laquelle on effectue à la place une boucle d'appels à la primitive set_pixel().
Puisque les performances dépendent essentiellement du nombre d'appels à fill_rect(), pourquoi se contenter juste de tracer des rectangles de 1 pixel de hauteur ?
Voici déjà aujourd'hui une évolution significative de la fonction draw_image(), avec désormais la gestion des zooms horizontaux et verticaux via 2 paramètres nommés zoomx et zoomy.
Pour cela nous jouons enfin sur le paramètre de hauteur de la primitive fill_rect() :
En conséquence, de nouvelles possibilités d'effets spéciaux pour l'affichage de sprites dans tes projets Python !
Voici déjà aujourd'hui une évolution significative de la fonction draw_image(), avec désormais la gestion des zooms horizontaux et verticaux via 2 paramètres nommés zoomx et zoomy.
Pour cela nous jouons enfin sur le paramètre de hauteur de la primitive fill_rect() :
- Code: Select all
def draw_image(rle, x0, y0, w, pal, zoomx=1, zoomy=1, itransp=-1):
i, x = 0, 0
w *= zoomx
x0, y0 = int(x0), int(y0)
nvals = len(pal)
nbits = 0
nvals -= 1
while(nvals):
nvals >>= 1
nbits += 1
maskval = (1 << nbits) - 1
maskcnt = (0xFF >> nbits >> 1) << nbits
while i<len(rle):
v = rle[i]
mv = v & maskval
c = (v & maskcnt) >> nbits
if (v & 0b10000000 or nbits == 8):
i += 1
c |= rle[i] << (7 - nbits + (nbits == 8))
c = (c + 1) * zoomx
while c:
cw = min(c, w - x)
if mv != itransp:
fill_rect(x0 + x, y0, cw, zoomy, pal[mv])
c -= cw
x = (x + cw) % w
y0 += x == 0 and zoomy
i += 1
En conséquence, de nouvelles possibilités d'effets spéciaux pour l'affichage de sprites dans tes projets Python !
Nous nous proposons de suite de te montrer ce que ça donne avec l'image transparente ci-contre de 64×64 pixels.
Voici les appels draw_image() que nous allons exécuter, de quoi remplir une bonne partie de l'écran :
Pour mesurer de plus les performances, nous engloberons le code précédent d'appels à la bibliothèque time lorsque présente :
Voici les appels draw_image() que nous allons exécuter, de quoi remplir une bonne partie de l'écran :
- Code: Select all
draw_image(image, 0, 0, 64, palette, zoomx=1, zoomy=1, itransp=0)
draw_image(image, 64, 0, 64, palette, zoomx=2, zoomy=1, itransp=0)
draw_image(image, 0,64, 64, palette, zoomx=1, zoomy=2, itransp=0)
draw_image(image, 64,64, 64, palette, zoomx=2, zoomy=2, itransp=0)
draw_image(image, 192, 0, 64, palette, zoomx=2, zoomy=3, itransp=0)
Pour mesurer de plus les performances, nous engloberons le code précédent d'appels à la bibliothèque time lorsque présente :
- Code: Select all
from time import monotonic
t0 = monotonic()
...
print(monotonic() - t0)
Sur les TI-Nspire CX II, la bibliothèque time intégrée ne fournit pas de méthode monotonic(), mais il suffit d'utiliser la méthode ticks_ms() à la place. Avec la bibliothèque ti_draw, l'affichage prend très exactement 7,23s.
Une solution est toutefois de convertir notre image pour la bibliothèque graphic offerte par KhiCAS, le logiciel intégré de Mathématiques et Sciences installable sur TI-Nspire CX II et TI-Nspire CX. Ici la bibliothèque time mesure des performances extraordinaires, de l'ordre de la milliseconde, rendant cette fois-ci justice au matériel.
Cela confirme en passant que le problème de performances lorsque l'on utilise la bibliothèque ti_draw officielle n'est pas de la faute de notre code.
Des performances toujours aussi décevantes, absolument pas au niveau du matériel de cette machine.
Une solution est toutefois de convertir notre image pour la bibliothèque graphic offerte par KhiCAS, le logiciel intégré de Mathématiques et Sciences installable sur TI-Nspire CX II et TI-Nspire CX. Ici la bibliothèque time mesure des performances extraordinaires, de l'ordre de la milliseconde, rendant cette fois-ci justice au matériel.
Cela confirme en passant que le problème de performances lorsque l'on utilise la bibliothèque ti_draw officielle n'est pas de la faute de notre code.
Avec la bibliothèque casioplot de la Casio Graph 90+E, l'affichage prend dans les 2,26s. Mesurées au chronomètre vu que nous n'avons pas ici de bibliothèque time intégrée.
Le script généré pour Graph 90+E est également compatible Graph 35+E II, s'exécutant ici dans les 5,82s.
Mais img2calc a également été prévu pour ça. Il te permet de générer un script plus optimal si tu choisis spécifiquement de convertir pour la Graph 35+E II. Dans ce cas tu obtiens une version monochrome bien plus agréable de ton image, de plus indexée selon une palette de seulement 2 couleurs (noir et blanc). Cela permet justement à notre compression RLE d'utiliser 1 seul bit pour coder la couleur, et donc 6 bits pour coder sur le même octet jusqu'à 1+64=65 répétitions de pixels (le 8ème bit étant utilisé pour indiquer d'inclure l'octet suivant dans le codage des répétitions). Avec toutes ces optimisations en plus d'un meilleur affichage et d'une consommation très inférieure de mémoire heap (tas), ici c'est seulement 3,50s !
Des performances donc bien meilleures que le modèle précédent. C'est d'autant plus honorable que nous avons ici un matériel inférieur, et même pas de primitive fill_rect().
Qu'est-ce que ce serait si Casio consentait à nous rajouter une primitive fill_rect() dans une prochaine mise à jour...
Qu'est-ce que ce serait si Casio consentait à nous rajouter une primitive fill_rect() dans une prochaine mise à jour...
Le script généré pour Graph 90+E est également compatible Graph 35+E II, s'exécutant ici dans les 5,82s.
Mais cela n'affiche ici que des ombres chinoises, l'écran Graph 35+E II étant monochrome.
Et alors imagine si nous avions converti une image disposant d'un fond ni transparent ni blanc, nous n'aurions quasiment obtenu que du noir...
Et alors imagine si nous avions converti une image disposant d'un fond ni transparent ni blanc, nous n'aurions quasiment obtenu que du noir...
Mais img2calc a également été prévu pour ça. Il te permet de générer un script plus optimal si tu choisis spécifiquement de convertir pour la Graph 35+E II. Dans ce cas tu obtiens une version monochrome bien plus agréable de ton image, de plus indexée selon une palette de seulement 2 couleurs (noir et blanc). Cela permet justement à notre compression RLE d'utiliser 1 seul bit pour coder la couleur, et donc 6 bits pour coder sur le même octet jusqu'à 1+64=65 répétitions de pixels (le 8ème bit étant utilisé pour indiquer d'inclure l'octet suivant dans le codage des répétitions). Avec toutes ces optimisations en plus d'un meilleur affichage et d'une consommation très inférieure de mémoire heap (tas), ici c'est seulement 3,50s !
Sur NumWorks N0110 avec la bibliothèque kandinsky, l'affichage prend 5,632s mesurées à l'aide de la bibliothèque time.
Sur NumWorks N0110 aussi on peut installer KhiCAS. Bien que disposant de sa propre bibliothèque graphic, notons que KhiCAS dispose d'une compatibilité avec kandinsky et que l'on peut donc exécuter directement le même script. Ici le même affichage ne prend plus que 0,524s.
Sur NumWorks N0110 aussi on peut installer KhiCAS. Bien que disposant de sa propre bibliothèque graphic, notons que KhiCAS dispose d'une compatibilité avec kandinsky et que l'on peut donc exécuter directement le même script. Ici le même affichage ne prend plus que 0,524s.
La HP Prime G2 et sa bibliothèque graphique hpprime affichent pour leur part en 0,109s.
Pas de bibliothèque time pour chronométrer le tracé ici, mais il suffit à la place de faire appel à la fonction TICKS() intégrée au langage HPPPL via
Pas de bibliothèque time pour chronométrer le tracé ici, mais il suffit à la place de faire appel à la fonction TICKS() intégrée au langage HPPPL via
hpprime.eval("TICKS()")
.Enfin, la bibliothèque ti_graphics des TI-83 Premium CE Edition Python, TI-84 Plus CE-T Python Edition et TI-84 Plus CE Python se traîne lamentablement en affichant en 3mins 14,565s, une véritable catastrophe.
Mais ce n'est pas la faute de notre code, puisque c'est le même que sur tous les modèles précédents, au seul nom d'appel de la primitive graphique près.
Mais ce n'est pas la faute de notre code, puisque c'est le même que sur tous les modèles précédents, au seul nom d'appel de la primitive graphique près.
Liens img2calc :