gint : un noyau pour développer des add-ins
Posté le 20/02/2015 17:30
Ce topic fait partie de la série de topics du fxSDK.
En plus des options de programmation intégrée comme le Basic Casio ou Python, la plupart des calculatrices Casio supportent des
add-ins, des programmes natifs très polyvalents avec d'excellentes performances. Les add-ins sont généralement programmés en C/C++ avec l'aide d'un ensemble d'outils appelé SDK.
Plusieurs SDK ont été utilisés par la communauté avec le temps. D'abord le
fx-9860G SDK de Casio avec fxlib pour Graph monochromes (plus maintenu depuis longtemps). Puis le
PrizmSDK avec libfxcg pour Prizm et Graph 90+E (encore un peu actif sur Cemetech). Et plus récemment celui que je maintiens, le
fxSDK, dont gint est le composant principal.
gint est un unikernel, ce qui veut dire qu'il embarque essentiellement un OS indépendant dans les add-ins au lieu d'utiliser les fonctions de l'OS de Casio. Ça lui permet beaucoup de finesse sur le contrôle du matériel, notamment la mémoire, le clavier, l'écran et les horloges ; mais aussi de meilleures performances sur le dessin, les drivers et la gestion des interruptions, plus des choses entièrement nouvelles comme le moteur de gris sur Graph monochromes.
Les sources de gint sont sur la forge de Planète Casio :
dépôt Gitea Lephenixnoir/gint
Aperçu des fonctionnalités
Les fonctionnalités phares de gint (avec le fxSDK) incluent :
- Toutes vos images et polices converties automatiquement depuis le PNG, sans code à copier (via fxconv)
- Un contrôle détaillé du clavier, avec un GetKey() personnalisable et un système d'événements à la SDL
- Une bibliothèque standard C plus fournie que celle de Casio (voir fxlibc), et la majorité de la bibliothèque C++
- Plein de raccourcis pratiques, comme pour afficher la valeur d'une variable : dprint(1,1,"x=%d",x)
- Des fonctions de dessin, d'images et de texte optimisées à la main et super rapides, surtout sur Graph 90+E
- Des timers très précis (60 ns / 30 µs selon les cas, au lieu des 25 ms de l'OS), indispensables pour les jeux
- Captures d'écran et capture vidéo des add-ins par USB, en temps réel (via fxlink)
Avec quelques mentions spéciales sur les Graph monochromes :
Un moteur de gris pour faire des jeux en 4 couleurs !
La compatibilité SH3, SH4 et Graph 35+E II, avec un seul fichier g1a
Une API Unix/POSIX et standard C pour accéder au système de fichiers (Graph 35+E II seulement)
Et quelques mentions spéciales sur les Graph 90+E :
Une nouvelle police de texte, plus lisible et économe en espace
Le dessin en plein écran, sans les bordures blanches et la barre de statut !
Un driver écran capable de triple-buffering
Une API Unix/POSIX et standard C pour accéder au système de fichiers
Galerie d'add-ins et de photos
Voici quelques photos et add-ins réalisés avec gint au cours des années !
Arena (2016) — Plague (2021)
Rogue Life (2021)
Momento (2021)
Communication avec le PC (cliquez pour agrandir)
Utiliser gint pour développer des add-ins
Les instructions pour installer et utiliser gint sont données dans les divers tutoriels recensés dans le
topic du fxSDK. Il y a différentes méthodes de la plus automatique (GiteaPC) à la plus manuelle (compilation/installation de chaque dépôt). Le fxSDK est compatible avec Linux, Mac OS, et marche aussi sous Windows avec l'aide de WSL, donc normalement tout le monde est couvert
Notez en particulier qu'il y a des
tutoriels de développement qui couvrent les bases ; tout le reste est expliqué dans les en-têtes (fichiers
.h) de la bibliothèque que vous pouvez
consulter en ligne, ou dans les ajouts aux changelogs ci-dessous.
Changelog et informations techniques
Pour tester les fonctionnalités et la compatibilité de gint, j'utilise un add-in de test appelé gintctl (
dépôt Gitea Lephenixnoir/gintctl). Il contient aussi une poignée d'utilitaires d'ordre général.
Ci-dessous se trouve la liste des posts indiquant les nouvelles versions de gint, et des liens vers des instructions/tutoriels supplémentaires qui accompagnent ces versions.
Anecdotes et bugs pétés
Ô amateurs de bas niveau, j'espère que vous ne tomberez pas dans les mêmes pièges que moi.
TODO list pour les prochaines versions (2023-04-03)
gint 2.11
- Changements de contextes CPU. À reprendre du prototype de threading de Yatis pour permettre l'implémentation d'un véritable ordonnanceur. Demandé par si pour faire du threading Java.
- Applications USB. Ajouter le support de descripteurs de fichiers USB. Potentiellement pousser jusqu'à avoir GDB pour debugger.
- Support de scanf() dans la fxlibc. Codé par SlyVTT, plus qu'à nettoyer et fusionner.
Non classé
- Regarder du côté serial (plus facile que l'USB) pour la communication inter-calculatrices (multijoueur) et ultimement l'audio (libsnd de TSWilliamson).
- Un système pour recompiler des add-ins mono sur la Graph 90+E avec une adaptation automatique.
- Support des fichiers en RAM pour pouvoir utiliser l'API haut-niveau sur tous les modèles et éviter la lenteur de BFile à l'écriture quand on a assez de RAM.
Citer : Posté le 20/12/2021 18:51 | #
Prépare ta soirée, je vais bientôt poster la v0.9B qui sera "almost done", la v1.0 sera la version avec tous les niveaux dispos et la fin de l'histoire afin de ne pas tout "teaser" avant ...
Wow j'ai vu ça c'est génial ! Je le teste ce soir après manger.
Je suis en train de finaliser l'API. En gros non seulement je veux m'assurer que toutes les fonctions de base sont fournies, mais aussi que toutes les fonctionnalités offertes par BFile de base sont couvertes histoire qu'utiliser BFile soit vraiment inutile sur la Graph 35+E II et la Graph 90+E.
Pour information, l'API Unix actuelle supporte les fonctions suivantes :
Note que l'API des descripteurs de fichiers supporte des descripteurs customisés, ce qui permettra à terme d'ajouter des fichiers en RAM (facile) et des descripteurs de fichiers pour communiquer par USB (facile aussi a priori). Ou des trucs à la demande... et bien sûr tu pourras toujours faire fdopen(3) dessus et derrière ça roule comme sur un OS sérieux.
Le but dans l'immédiat est de rajouter l'API pour les répertoires. Note qu'il n'y a pas d'API standardisée pour lire depuis une répertoire au niveau syscall (Linux utilise l'obsolète readdir(2), ou désormais getdents(2), mais c'est tout caché). À la place, gint fournit directement les fonctions POSIX, à savoir opendir(3), readdir(3) etc. J'ai quasiment fini de coder et tester :
Pour l'instant il n'y a pas de plan de supporter un truc plus avancé comme scandir(3) ou glob(3), mais ça viendra peut-être plus tard. La deadline que je vise se compte en jours tout au plus.
Une fois que ça ce sera fait (mon espoir secret est que ce soit le cas ce soir) je retourne sur <stdio.h> dont j'ai codé les toutes bases (la structure FILE et le buffering).
Citer : Posté le 20/12/2021 20:38 | #
Super, tu avances bien.
Avec ça tu auras une API compatible standard C, c'est nickel.
Bon courage pour le test
Citer : Posté le 21/12/2021 10:34 | #
Super ! Ça va bien simplifier la gestion des fichiers ! Bravo
Citer : Posté le 21/12/2021 10:35 | #
Merci. Que sur la Graph 35+E II et Graph 90+E pour l'instant. Le vieux système de fichiers est trop mauvais pour supporter une telle interface. Après ce sera toujours possible d'ouvrir des fichiers en RAM et de faire majoritairement pareil je pense, à voir.
Citer : Posté le 21/12/2021 10:42 | #
Ohhh pas de problèmes pour moi tu sais... avec ma nouvelle 90E+ je suis au gout du jour désormais
Citer : Posté le 21/12/2021 10:45 | #
Ok bien reçu
Citer : Posté le 23/12/2021 01:22 | #
Tout ce qui est mentionné dans ce message est maintenant poussé, et testé plutôt en détail.
Je pense qu'il me manque encore un genre de stat() pour pouvoir supporter tout <stdio.h> mais pour l'instant on va dire que ça peut attendre.
Citer : Posté le 23/12/2021 08:40 | #
Du coup l'API de fichiers est complète et fonctionnelle maintenant ? Et gint passe à une nouvelle version ?
Citer : Posté le 23/12/2021 09:22 | #
Quasiment ouais ! Niveau gint c'est à peu près bon, j'attends juste de voir si j'ai besoin de stat() etc. Mais une nouvelle version est imminente en effet.
Côté fxlibc il y a encore <stdio.h> à supporter (fopen() et compagnie).
Citer : Posté le 23/12/2021 11:10 | #
Super j'attendais ça avec impatience depuis quelques jours
Cependant j'ai de petites erreurs. J'inclus fnctl.h, sys/stat.h, unistd.h et O_WRONLY n'est pas trouvé par gcc. Si je remplace par 0 ça compile, mais close et open sont indéfinis. Faut mettre à jour autre chose que gint ? Inclure d'autres headers ? Merci d'avance
Logs complets :
Consolidate compiler generated dependencies of target proj
[ 3%] Building C object CMakeFiles/proj.dir/src/input.c.obj
/home/kdx/projects/jtmm2/src/input.c: In function ‘input_init’:
/home/kdx/projects/jtmm2/src/input.c:22:52: error: ‘O_WRONLY’ undeclared (first use in this function)
22 | if (log) input.fd_log = open("jtmm2.demo", O_WRONLY);
| ^~~~~~~~
/home/kdx/projects/jtmm2/src/input.c:22:52: note: each undeclared identifier is reported only once for each function it appears in
make[3]: *** [CMakeFiles/proj.dir/build.make:132: CMakeFiles/proj.dir/src/input.c.obj] Error 1
make[2]: *** [CMakeFiles/Makefile2:83: CMakeFiles/proj.dir/all] Error 2
make[1]: *** [Makefile:91: all] Error 2
make: *** [Makefile:2: all] Error 2
Consolidate compiler generated dependencies of target proj
[ 3%] Building C object CMakeFiles/proj.dir/src/input.c.obj
[ 6%] Linking C executable proj
/home/kdx/.local/share/giteapc/Lephenixnoir/sh-elf-gcc/lib/gcc/sh3eb-elf/11.1.0/../../../../sh3eb-elf/bin/ld: CMakeFiles/proj.dir/src/input.c.obj: in function `_input_deinit':
input.c:(.text+0x24): undefined reference to `_close'
/home/kdx/.local/share/giteapc/Lephenixnoir/sh-elf-gcc/lib/gcc/sh3eb-elf/11.1.0/../../../../sh3eb-elf/bin/ld: CMakeFiles/proj.dir/src/input.c.obj: in function `_input_init':
input.c:(.text+0x6c): undefined reference to `_open'
collect2: error: ld returned 1 exit status
make[3]: *** [CMakeFiles/proj.dir/build.make:396: proj] Error 1
make[2]: *** [CMakeFiles/Makefile2:83: CMakeFiles/proj.dir/all] Error 2
make[1]: *** [Makefile:91: all] Error 2
make: *** [Makefile:2: all] Error 2
Citer : Posté le 23/12/2021 11:12 | #
Ah pardon j'ai oublié de spécifier que les en-têtes et une partie des définitions sont dans la fxlibc ! Ça fait partie du standard POSIX et compte tenue de l'approche qu'on a prise avec Yatis c'est défini dans la fxlibc même si les détails sont implémentés dans gint.
Si tu veux la motivation c'est que Yatis pourra implémenter pareil dans Vhex et ensuite les abstractions construites par-dessus (comme fopen()) il en bénéficiera dans Vhex sans avoir à les recoder.
Citer : Posté le 31/12/2021 10:58 | #
Nouvelle version : gint 2.7.0
Une assez grosse release qui contient surtout des corrections de bugs ainsi que -tenez-vous bien- le support pour le système de fichiers !
Release associée du fxSDK : fxSDK 2.7.0
Release associée de la fxlibc : fxlibc 1.3.0
Ajouts :
Changements :
Corrections de bugs :
Support des API Unix et standard pour le système de fichiers
Sur les calculatrices avec Fugue (ie. Graph 35+E II et Graph 90+E), gint supporte l'accès au système de fichiers par les API Unix et une partie du standard POSIX. N'oubliez pas de faire un world switch pour accéder au système de fichiers.
Les headers <unistd.h>, <fcntl.h>, <dirent.h> et <sys/stat.h> sont fournis par la fxlibc, tandis que le code est fourni par gint.
Pour ce qui est des fichiers, gint implémente les fonctions suivantes :
Et côté répertoires :
Ça veut dire que, sur Graph 90+E au moins, personne ne devrait plus jamais avoir à s'embêter avec BFile
Citer : Posté le 31/12/2021 11:26 | #
Excellent, super maj
Citer : Posté le 10/01/2022 14:43 | #
Après avoir bataillé 4 jours, j'ai fini par mettre le doigt sur un bug qui était passé inaperçu durant la précédente mise à jour.
(Pour ceux qui se demandent comment ce genre de choses arrive, c'est assez facile : ça marche très bien pendant des jours, parfois des semaines ou des mois, et tout à coup ça crashe parce que les étoiles se sont «alignées» pour permettre la manifestation du bug. Et là je sors mon manteau, ma pipe, ma loupe et ma déprime jusqu'à ce que le crash élusif mène à une explication concrète.)
Donc l'origine de ce bug c'est un détail que j'avais oublié depuis longtemps et qui est qu'on ne peut pas écrire dans un fichier depuis la ROM (virtualisée ou pas) ; les données qu'on envoie doivent être dans la RAM. On ne sait pas exactement pourquoi, parce que l'explication dépend de plein de détails cachés de l'OS. Le truc c'est que plein de choses sont dans la ROM. Par exemple :
// ^^^^^^^^^^^^^^^^^
// Ça c'est dans la ROM!
Donc voilà un de mes tests a crashé Jeudi pour ça et j'ai compris ce matin. Du coup j'ai modifié write() pour que si on lui demande d'écrire depuis la ROM il se débrouille pour copier d'abord les données vers la RAM (par blocs ou d'un coup selon combien de mémoire est disponible à ce moment-là), ce qui est transparent pour vous.
Un nouveau patch de gint arrivera donc sous peu, le temps que tout ça soit bien testé.
Citer : Posté le 19/03/2022 21:20 | #
Petit tutoriel que je lierai dans le changelog : comment utiliser les flux standards (stdin/stdout/stderr) dans gint. Pour rappel, les flux standards sont les "fichiers" qui lient le programme à (habituellement) votre terminal, et qui sont utilisé par printf(), scanf(), etc.
Dans gint, les flux standards existent, mais il n'y a pas pour autant de terminal intégré. Par défaut, stdin() ne transmet juste aucun texte, et stdout/stderr mettent tout le texte qu'ils reçoivent à la poubelle.
Vous pouvez cependant les fermer/rouvrir pour récupérer chaque lecture/écriture dans une fonction de votre choix. La façon de faire ça est de définir un nouveau type de fichier avec vos propres fonctions de lecture/écriture, et de rouvrir les descripteurs de fichiers des flux standards avec ces types-là. Oui le mécanisme permet de faire des fichiers à la Linux, pour l'USB, écrire en RAM, etc.
Regardons à quoi ressemble le mécanisme pour stdio/stderr (les flux où on écrit, eg. avec printf()). D'abord il faut définir la fonction d'écriture, qui a le même prototype que write() :
{
/* On vient de recevoir le texte [buf] de longueur [size]. C'est le moment de
l'enregister, l'afficher, etc. */
/* [data] est un paramètre personnalisé, voir ci-dessous. */
}
Ensuite on définit le type de fichiers qu'on va attribuer à stdout/stderr, pour lequel on n'implémente aucune autre fonction.
.read = NULL,
.write = stdouterr_write,
.lseek = NULL,
.close = NULL,
};
Et enfin on est prêts à rouvrir les descripteurs avec ce nouveau type. Le second paramètre est enregistré dans le descripteur et passé à la fonction via le paramètre data. Ici je l'ignore, je mets NULL.
#include <unistd.h>
close(STDOUT_FILENO);
close(STDERR_FILENO);
open_generic(&stdouterr_type, NULL, STDOUT_FILENO);
open_generic(&stdouterr_type, NULL, STDERR_FILENO);
Et voilà, à partir de maintenant printf() et toute la compagnie envoient vers notre fonction stdouterr_write() et on peut faire ce qu'on veut dedans.
Pour stdin, c'est pareil sauf que c'est la fonction de lecture qu'on modifie :
{
/* On nous demande de fournir [size] caractères dans [buf]. Dans un terminal
on demanderait à l'utilisateur de taper quelque chose (+ buffer) */
}
fs_descriptor_type_t stdin_type = {
.read = stdin_read,
.write = NULL,
.lseek = NULL,
.close = NULL,
};
close(STDIN_FILENO);
open_generic(&stdin_type, NULL, STDIN_FILENO);
Et voilà, je suis sûr que ce sera utile pour porter des programmes et/ou garder du code cross-platform bien en place
Citer : Posté le 19/03/2022 21:36 | # | Fichier joint
Nouvelle version : gint 2.7.1
Une version assez mineure côté gint, mais côté fxlibc tout le support pour les fichiers de <stdio.h> a été ajouté (fopen(), fprintf(), etc). Jetez d'abord un œil là-bas, puis regardez les infos ci-dessous !
Release associée du fxSDK : fxSDK 2.7.1
Release associée de la fxlibc : fxlibc 1.4.0
Le support des flux standards a été ajouté dans la libc, ce qui signifie que maintenant printf() marche. Par contre, le texte n'arrive nulle part par défaut, c'est à vous de définir une fonction pour le récupérer.
Mini-tutoriel : Utiliser les flux standard.
Assez peu de changements donc :
C'est tout pour cette fois, mais pour la prochaine version je prévois de revamp un peu bopti sur Graph 90+E pour vous donner enfin les fonctions de redimensionnement, miroir horizontal/vertical, etc. que vous me demandez souvent, sous une forme efficace (pas juste ce que libimg donne qui n'est qu'à moitié convaincant).
Citer : Posté le 19/03/2022 21:43 | #
Yo, ça c'est de la release tout tombe d'un coup, c'est Noel avant l'heure.
Je plussoie pour les fonctions sur les sprites.
Citer : Posté le 20/03/2022 11:27 | #
J'ai réécrit le topic pour donner un meilleur aperçu des fonctionnalités, et ajouté quelques exemples.
Yo, ça c'est de la release tout tombe d'un coup, c'est Noel avant l'heure.
Je plussoie pour les fonctions sur les sprites.
Merci ! Pour les sprites je vais commencer par récupérer les formats optimisés que j'utilise dans Azur, puisque le code de dessin là-bas (qui est beaucoup plus récent et utilise des subtilités d'assembleur beaucoup plus pointues que j'ai maîtrisées récemment) est franchement mieux.
Mon objectif principal est d'avoir des "fonctions génériques" pour manipuler les images, idéalement pour reprendre la structure de dessin classique et ensuite pouvoir faire des extensions à la pelle sans avoir à manipuler beaucoup de code à chaque fois.
Quelques exemples de trucs qui passeraient bien dans le format générique : miroir vertical/horizontal, remplacement d'une couleur par une autre (pour les images monochromes par exemple), certains effets de distorsion horizontale verticale (division de la taille par une puissance de 2 par exemple), et si je m'en sors bien peut-être même agrandissement par facteurs entiers (voire tout ça combiné lol). Ce genre d'effets pourrait se faire directement à l'affichage sans copier les images.
À côté de ça, je veux aussi ajouter une vraie API pour lire/modifier les pixels et les images, avec les transformations classiques (redimensionnement arbitraire nearest-neighbor, changements de luminosité, saturation, etc). Essentiellement fusionner libimg dans gint, en supportant au passage les formats à palette (le format interne 16-bit de libimg est pas assez performant en général).
Il y aura clairement deux types de transformations, celles qui n'ajoutent pas de nouvelles couleurs ou les modifient juste sans en changer le nombre, et donc passent bien sur les formats à palette ; et celles qui les changent complètement, et donc ne passeront que sur les formats 16-bit (par exemple redimensionnement avec interpolation, alpha blending, etc).
Voilà, comme d'hab je profite d'une demande simple pour remédier à des problèmes un peu plus profonds d'une façon un peu ambitieuse. Ce sera pas immédiat du coup ; désolé. Sur le moyen/long terme ce sera bénéfique, promis.
Citer : Posté le 21/03/2022 23:20 | # | Fichier joint
Alright donc voici un début de plan pour les histoires des images.
Situation actuelle : le code de bopti est... en assembleur. Assez mauvais pour de l'assembleur avec mes connaissances actuelles. La version du dessin que j'ai codée dans Azur est d'une beauté infinie à côté... et probablement 2 fois plus rapide sur le CPU. Mon plan est de récupérer le code d'Azur pour le passer dans gint parce que ça sert à rien d'améliorer du code que j'ai déjà refait en mieux.
Je ne sais pas quel gain de vitesse réel je peux attendre de ce transfert parce qu'Azur dessine dans la XRAM (qui est très rapide) alors que bopti dessine dans la RAM. Si la RAM est le facteur limitant, alors il n'y a peut-être pas vraiment de marge à grignoter. Mais ça reste la seule option sérieuse, surtout si on prend en compte l'overclock.
Les formats : actuellement bopti a 4 formats : RGB565, RGB565A, P8 et P4. Les deux formats à palette, P8 et P4, ont tous les deux la transparence intégrée et il se trouve que c'est ce qui coûte le plus cher en termes de perfs. Azur spécialise P8 et deux variations P8_RGB565 et P8_RGB565A qui font ce que vous imaginez. En plus de ça, il réduit la palette de 256 entrées à juste ce qui est nécessaire à la conversion, ce qui devrait être évident. Et enfin, il numérote les couleurs à partir de -128 au lieu de 0 parce que ça économise un demi-cycle par pixel durant la lecture de la palette. P4 est aussi spécialisé en P4_RGB565 et P4_RGB565A même si là il n'y a que l'absence de transparence qui change. Je compte faire suivre ces formats dans gint, ce qui ne change rien de l'extérieur.
Fusion de libimg : une fois ces formats bien posés et fixés, je compte exposer dans l'API gint de quoi accéder aux informations, pixels etc. des images, plus essentiellement les fonctions de libimg (dépôt) qui est actuellement figée au RGB565A, ce qui est vraiment pas suffisant en perfs. À cela on peut ajouter des redimensionnements quelconques comme dans la démo récente, des changements de palette, et autres joyeusetés. Bien sûr des conversions de format, même si je promets pas que l'encodage 16-bit → palette soit super élégant.
Il y aura clairement deux types de transformations ; celles qui ne changent pas le nombre de couleurs et seront donc disponibles pour transformer les images P8_* et P4_*, et celles qui changent le nombre de couleurs (redimensionnement avec interpolation, alpha blending, etc) et qui ne seront naturellement disponibles que sur les images RGB565 et RGB565A.
QOI : Il est question de supporter le format QOI (issue). Ça me plaît bien. Je ne pense pas que ce soit sérieusement possible de décoder le QOI au rendu en temps raisonnable, mais je suis chaud pour essayer. Dans tous les cas il sera toujours possible de décoder en bopti_image_t dans la RAM au lancement de l'add-in, ce qui économise de la place dans le G3A, qui est presque plus rare que la RAM.
Effets dynamiques : Et le plus gros (que je mets à la fin juste à cause du gros tableau ci-dessous), les effets dynamiques : les transformations qu'on fait à la volée en affichant, sans créer de nouvelle image. Je vous mets le tableau puis j'explique ce que ça veut dire.
Pour chaque format et chaque transformation j'ai indiqué :
Les effets considérés sont les suivants (je prends les suggestions) :
Vous pouvez voir que dans l'ensemble y'a pas mal de trucs accessibles en performance, mais comment structurer le code pour les faire marcher sans tout dupliquer toutes les 3 lignes est un casse-tête potentiel. On sent, en arrière-plan, une logique se dégager avec un très beau modèle de transformations à côté duquel je ne veux pas passer sans réfléchir, mais qui ne serait clairement pas trivial à obtenir.
Notez que pour les fonctions qui modifient les images (pour faire comme libimg) c'est un peu pareil, y'a un squelette générique pour parcourir les pixels d'une image et faire des transformations, et pour que les transformations aillent vite et bien il faut qu'elles soient en assembleur et bien optimisées. Pour que le squelette soit réutilisable et que chaque transformation réimplémente pas tout, faut pas s'y prendre n'importe comment.
Stade actuel : réflexion.
Citer : Posté le 21/03/2022 23:59 | #
C’est un très beau programme que tout cela.
En idées supplémentaires :
Isolation de chacune des composantes d’une image
Conersion en niveau de gris
Blender une images avec un fond avec un niveau alpha
Mais c’est peut être trop spécifique (et très clairement non prioritaire...)
Citer : Posté le 22/03/2022 00:26 | #
Joli programme ! Les effets dynamiques vont certainement ouvrir de nouveaux horizons, j'adore tout ce que tu prévois !
Je suis très hype pour QOI ! À la fois pour les options que ça donne pour la compression de l'add-in, et pour la flexibilité des projets.
Il serait potentiellement très utile d'avoir l'option de charger des ressources QOI externes en tant que bopti :
Le transfert d'un add-in peut devenir lent quand le projet grossit, transférer uniquement les ressources modifiées ferait gagner beaucoup (beaucoup !) de temps
SDL2_image supportera QOI avec sa prochaine release, il serait potentiellement beaucoup plus facile d'écrire des jeux cross platform complets avec le standard QOI et les fonctionnalités d'IO toutes fraîches de gint. Je dis ça, je dis rien
Mon effet favori de libimg est img_dye, qui remplace tous les pixels opaques par une couleur spécifiée. C'était très pratique pour faire des effets
Tu as listé les deux flips séparèment, est-ce que ça veut dire qu'ils auront des fonctions dédiées ? D'intuition je me serais attendu à une fonction unique qui prend une combinaison de flags (IMG_FLIP_NONE ou IMG_FLIP_HORI | IMG_FLIP_VERT par exemple). Je suis curieux.