Posté le 10/01/2022 10:32
Planète Casio v4.3 © créé par Neuronix et Muelsaco 2004 - 2024 | Il y a 232 connectés | Nous contacter | Qui sommes-nous ? | Licences et remerciements
Planète Casio est un site communautaire non affilié à Casio. Toute reproduction de Planète Casio, même partielle, est interdite.
Les programmes et autres publications présentes sur Planète Casio restent la propriété de leurs auteurs et peuvent être soumis à des licences ou copyrights.
CASIO est une marque déposée par CASIO Computer Co., Ltd
Citer : Posté le 10/01/2022 10:36 | #
Lephe va sûrement faire un pavé, mais le format bopti est documenté ici : https://gitea.planet-casio.com/Lephenixnoir/gint/src/branch/master/include/gint/display-cg.h#L80
Citer : Posté le 10/01/2022 10:39 | #
Merci Dark Storm,
En effet
J'ai appuyé sur entrée et en relisant ma question, je me suis dit : "t'es C.N, regarde dans la structure de bopti_image_t".
Je vais essayer de jeter un oeil donc.
Merci bcp.
Sly
Citer : Posté le 10/01/2022 10:48 | #
Techniquement ça fait pas partie de l'API, mais comme les formats risquent pas vraiment de changer, tu peux le faire oui.
Le format est décrit ici. Comme tu peux le voir, si tu as une image p4 standard, il "suffit" de regarder les 32 premières entrées de data[] pour avoir la palette.
La difficulté, c'est que tu ne peux pas modifier la variable puisqu'elle est constante (issue de la conversion de fxconv). Si tu veux t'en sortir, il faudra donc dupliquer l'image, ce qui nécessite de connaître la taille totale des données.
Cette fonction (de tête) devrait te dupliquer une image :
{
size_t size = sizeof(*img);
if(img->profile == 0 || img->profile == 1) // PX_RGB565, PX_RGB565A
size += img->width * img->height * 2;
else if(img->profile == 2) // PX_P8
size += img->width * img->height;
else if(img->profile == 3) // PX_P4
size += ((img->width + 1) / 2) * img->height;
else return NULL;
bopti_image_t *newimg = malloc(size);
if(!newimg) return NULL;
memcpy(newimg, img, size);
return newimg;
}
Et ensuite tu peux modifier soit les pixels soit la palette.
Comme tu peux le voir ça manque un peu de partie publique (les noms des profils sont privés par exemple), je me note d'améliorer ça.
Citer : Posté le 10/01/2022 11:33 | #
OK Merci Lephé, effectivement ca aurait coincé si fxconv génère des data sous forme de constantes.
Du coup, il faudra aussi que je pense bien à faire une libération de mémoire à la fin pour pas avoir une fuite (chose qu'on fait pas du coup avec une image issue de fxconv.
Pour info, à toute fin utile, si cela peut intéresser quelqu'un d'autre, le niveau de gris correspondant à une couleur (R,G,B) est obtenu en calculant la moyenne M=(R+G+B)/3 et en appliquant cette couleur moyenne sur chaque composante (RGB)-->(M,M,M). Il s'agit ensuite de faire le morphing entre la couleur initiale et la couleur finale avant chaque appel à dimage()/dupdate() sur un nombre N d'itérations pour avoir le véritable effet de fondu.
A plus et merci
Sly
Citer : Posté le 10/01/2022 11:35 | #
Excellent ! Tu ne peux pas échapper à l'allocation RAM, mais tu peux toujours te donner une unique copie pour tout le programme et la modifier à chaque fois que tu en as besoin. Maintenant que j'y pense, tu peux faire mieux : fxconv supporte un attribut section qui te permet de mettre l'image dans la RAM :
type: bopti-image
section: .data
Auquel cas la variable est en lecture-écriture. J'ai en tête un cas peut-être où ça pourrait ne pas marcher (alignment), si tu essaies et que ça crashe signale-le moi et je corrigerai le truc immédiatement.
Edit : pour la luminosité, le facteur 1/3 partout c'est pas hyper hyper fidèle, y'a d'autres pondérations qui reflètent un peu mieux la perception de l'oeil humain.
Citer : Posté le 10/01/2022 11:45 | #
Ok, je vais essayer avec la section .data.
Pour le niveau de gris, c'est la version simple en effet.
il y a aussi la méthode de la luminance/chrominance, mais ce sera certainement pus lourd en calculs, donc si le rendu avec la moyenne passe, ce sera bien. Par contre si j'ai un résultat vraiment "dégueulasse", j'essaierai de l'implémenter.
Comme d'hab', il faut aviser en fonction
@+
Sly
Citer : Posté le 10/01/2022 13:12 | #
En effet. Le risque c'est que si tu fais un fondu progressif, ie. tu pars de la couleur originale pour aller vers la moyenne (pondérée ou pas) tu as plutôt envie de préserver la luminosité durant toute la transition. Sinon, ton image risque de s'assombrir/éclaircir visuellement au passage.
Je le mentionne parce que les coefficients habituels sont assez loin du 1/3, par exemple le standard CCIR 601 (genre YCbCr) la formule est plutôt 0.299 R + 0.587 G + 0.114 B. Après y'a aussi le gamma qui s'en mêle.
Note (si jamais le 1/3 ne passe pas bien) que toutes ces multiplications sont aussi rapides à faire que 1/3, surtout que tes nombres sont tous petits (0..31 pour R/B et 0..63 pour B), tu as une myriade d'options, de multiplier puis faire un décalage de bits, à utiliser une table. Tu devrais vraiment pas avoir de problèmes de perfs à première vue (après si tu fais ça sur des très grandes surfaces genre tout l'écran ça se complique).
Citer : Posté le 10/01/2022 13:27 | #
En fait je pense que je vais faire un pré-calcul de la palette, stocker les itérations pour ensuite juste faire un "dump" de la palette à utiliser dans l'image juste avant de l'afficher. Comme ça pas de problème de vitesse et ca devrait pas utiliser trop trop de mémoire (du moins ca devrait rester raisonnable). Je me cantonnerai donc aux formats P4 et P8 le RGBA565 serait je pense trop lourd en calcul.
Je te dirai quand je me serai mis dessus (peut-être ce soir ou demain), car là je passe le "polish" sur les niveaux de ML, la v1.0A est imminente. (j'avoue que j'avais sous estimé le temps de Beta test et d'écriture des niveaux )
Sly
Citer : Posté le 10/01/2022 13:29 | #
Bonne idée ! Avec ce niveau d'attention au détail ça promet d'être beau
Citer : Posté le 10/01/2022 15:18 | #
Bon, j'ai tenté ça:
mon image arrive dans la variable village via un "extern bopti_image_t village;"
Je précise que l'image est codé en p8 via fxconv.
Je trifouille la palette (version goret pour le moment, on fera plus complexe après si j'arrive à faire fonctionner ):
memcpy( palette, village.data, 512 ); // je sauvegarde la palette pour y revenir si besoin
uint16_t paletteNB[256];
for( unsigned char k=0; k<=255; k++)
{
unsigned char B = (unsigned char) (palette[k] & 0b0000000000011111);
unsigned char G = (unsigned char) ((palette[k] & 0b0000011111100000) >> 5);
unsigned char R = (unsigned char) ((palette[k] & 0b1111100000000000) >> 11);
unsigned char Moy = (R+G+B)/3;
paletteNB[k] = (uint16_t) (((Moy>>3) << 11) | ((Moy>>2) << 5 ) | (Moy>>3));
}
memcpy( village.data, paletteNB, 512 );
Et là l'émulateur freeze. J'ai pas tenté sur la machine physique, je voudrais pas la briquer
Je sais pas si c'est mon code qui est pourri ou si je tombe dans le cas que tu craignais Lephé.
Une idée ?
Citer : Posté le 10/01/2022 15:28 | #
Il faut copier l'image avant de modifier la palette, sinon les données sont constantes (pour faire simple). Ce commit d'un de nos projets abandonnés fait juste ça
(pour 90+E, mais le format a l'air assez similaire).Edit : t'es sous 90+E en fait my bad
Citer : Posté le 10/01/2022 15:34 | #
Rappelle-moi le range d'un unsigned char ? :P
Aussi note que ça ne sert à rien de prendre des types autre que int pour toutes tes variables temporaires, ça te fait payer des extensions (calculs) en plus et tu ne gagnes pas un seul octet de mémoire.
Enfin je crois que ton G va de 0 à 63 plutôt que de 0 à 31 comme R et B donc le calcul n'est probablement pas la moyenne que tu imagines
(Je suis en train de penser que du coup tu peux faire (R + G + B) / 4, ce qui va plus vite, et qui donne plus de poids au vert comme dans les formules discutées précédemment)
Citer : Posté le 10/01/2022 15:47 | #
Rappelle-moi le range d'un unsigned char ? :P
Bon c'est officiel je suis un *$#&*ù£ !!!
Merci, du coup ça marche ....
Mais c'est juste immonde et hyper sombre, on va donc faire la version évoluée
Ca je savais pas, merci pour l'info. Je vais optimiser un peu alors.
(Je suis en train de penser que du coup tu peux faire (R + G + B) / 4, ce qui va plus vite, et qui donne plus de poids au vert comme dans les formules discutées précédemment)
oui je gère tout en RGB565. Je vais essayer avec la luminance "officielle" et avec la division par 4 pour voir ce qui est le mieux.
Citer : Posté le 12/01/2022 00:28 | #
En jouant avec... une correction importante sur ma fonction de plus tôt :
{
size_t size = sizeof(*img);
if(img->profile == 0 || img->profile == 1) // PX_RGB565, PX_RGB565A
size += img->width * img->height * 2;
else if(img->profile == 2) // PX_P8
size += 512 + img->width * img->height;
// ^^^^^
else if(img->profile == 3) // PX_P4
size += 32 + ((img->width + 1) / 2) * img->height;
// ^^^^
else return NULL;
bopti_image_t *newimg = malloc(size);
if(!newimg) return NULL;
memcpy(newimg, img, size);
return newimg;
}
J'avais oublié de compter les palettes dans la taille totale.
Citer : Posté le 12/01/2022 08:03 | #
Ah oui effectivement ;-)
Ca arrive même aux meilleurs ...
Citer : Posté le 12/01/2022 08:07 | #
Surtout quand on écrit de tête ! Aïe aïe aïe...