PDA

Voir la version complète : conversion pixel 8bit en pixel 16bits ?


Nesgba
23/01/2006, 19h54
salut a tous,

j'ai un chi probleme, j'arrive pas a convertir convenablement une image 8bits en image 16bits.
j'ai peut etre pas bien compris le methode mais je me demande ou je doit mettre les couleurs de ma palette 8bits ?
je recupere comment la couleur d'un pixel sur 8 bits ? sachant qu'il a une couleur palette sur 16 bits.

je suis tombé sur des algo de fou sur le net Oo surtout pour la reduction de couleur genre 16bits->8bits.

voila si vous avez des pistes. :unsure:

birslip
23/01/2006, 20h14
Tu peux faire un truc comme ça je pense:

image_16bit[i] = palette[image_8bit[i]] | (1 << (15));

J'espère que c'est ça que tu voulais :whst:

Japi
23/01/2006, 20h24
co toi sur IRC, j'ai un truc pour toi pour resoudre cette histoire.

Nesgba
23/01/2006, 20h42
Tu peux faire un truc comme ça je pense:

image_16bit[i] = palette[image_8bit[i]] | (1 << (15));

J'espère que c'est ça que tu voulais :whst:

Oo mais c'est pas possible ca la palette ne contient que 256 couleurs et une image contient quelques milliers de pixels. ta variable i va largement depasser la palette dispo.
et seul 255 pixels seront pris en compte.
je vais tester en cas.

merci quand meme birslip ;)

japi je me connecte ce soir ;)

[edit] ah non birslip j'ai parlé trop vite j'avai pas bien matté le code, je vais tester ca peut ptet le faire :)

Mollusk
23/01/2006, 21h15
lol, je me disais aussi qu'il n'y avait pas de rapport entre i et la taille de la palette...

Dr.Vince
23/01/2006, 23h59
Tu peux faire un truc comme ça je pense:

image_16bit[i] = palette[image_8bit[i]] | (1 << (15));

J'espère que c'est ça que tu voulais :whst:

bah ouais, je suis d'accord avec birslip, à priori c'est ça mais on peut faire un tout petit peu mieux, surtout pour un maniaque de l'optimisation come toi Nes ;)


image_16bit[i] = palette[image_8bit[i]] | 0x4000 ;

Mollusk
24/01/2006, 00h01
normalement le compilo remplace 1<<15 par 0x4000 à la compilation ;)

edit : et puis sur gba t'as pas besoin de l'activer le 15ème bit me semble, c'est que pour DS ca

Nesgba
24/01/2006, 03h24
merci pour vos reponses.

voila j'ai testé vos methodes avec quelques variantes mais helas le meilleur resultat que j'obtien ressemble a ca:
http://img66.imageshack.us/img66/8302/essai3fw.png

notez que certaines lignes de pixels sont presques bonnes donc on approche du but ;), il manque une division ou un decalage quelque part a mon avis.
apres a savoir ou ?? je cherche encore :)

voici le code:

// buffer soft
unsigned short IRIS_IN_EWRAM BufferImageModeDessin [120*80] ;
unsigned short temp ;

// copie dans le buffer d'une image 8bits de 120x80 pixels
for(x=0;x<120;x++)
for(y=0;y<80;y++){
temp = Image_bitmap8[y*120+x] ;
BufferImageModeDessin [y*120+x] = Image_palette[temp] ;}

// copie sur l'ecran en mode 5
for(x=0;x<120;x++)
for(y=0;y<80;y++)
ActualVideoBuffer[y*160+x] = BufferImageModeDessin[y*120+x] ;

bien sur rien n'est optimisé, c'est juste pour tester. si vous avez une idée d'ou le probleme peut provenir.
activer ou pas le 15 eme bit ne sert a rien apparement, par contre sur les autres ca fait des nuances differantes c'est marran ^^.

mastertop101
24/01/2006, 03h51
jai surement pas bien compris mais pourquoi tu fais pas une version de l'image en 8bit et une autre en 16 bit ?:blink:

Nesgba
24/01/2006, 03h59
jai surement pas bien compris mais pourquoi tu fais pas une version de l'image en 8bit et une autre en 16 bit ?:blink:
parcque je veut une image qui ne contient que 256 couleurs (pour une question de taille d'image car en + j'ajoute une compression a l'image en mode 4 et que j'ai pas besoin de 32768 couleurs) et que j'ai besoin de passer en mode 5 parcque j'ai devellopé des effets sur image (nottament de transition d'une image a une autre, fondu enchainé dans une video ...) qui sont prevu pour ce mode la et qui se limitent pas a 256 couleurs, ca donne des trucs super moche en mode 4.

ca explique la taille que j'utilise pour mes images (120x80) car avec toutes ces operations meme avec l'IWRAM et en passant a 20 fps j'ai du mal a bien faire tourner mes videos d'intro de jeu. ;)

alala ce qui faut pas faire pour gagner quelques centaines de ko :)

yopyop
24/01/2006, 08h46
/mode mechantON

Je veux pas dire mais même pour un code pas optimisé c’est pas jolie jolie. :p
Par exemple inverse tes for. Il vaut mieux faire varier les colonnes avant les lignes il y a certain compilo qui « voit » qu’il y a une boucle de 120 multiplication et optimise pour toi et ça vaut surtout pour la deuxième copie parce que la premier en une boule c’est fait ce qui donne en gros :


// buffer soft
unsigned short IRIS_IN_EWRAM BufferImageModeDessin [120*80] ;
unsigned short temp ;

// copie dans le buffer d'une image 8bits de 120x80 pixels
for(x=0;x<120 * 80;x++){
temp = Image_bitmap8[x] ;
BufferImageModeDessin [x] = Image_palette[temp] ;}

unsigned short Y1, Y2 ;
// copie sur l'ecran en mode 5
for(y=0;y<80;y++)
{
Y1 = y*160; //le compilo devrait le faire mais bon ça coûte rien.
Y2 = y*120;
for(x=0;x<120;x++)
ActualVideoBuffer[Y1+x] = BufferImageModeDessin[Y2+x] ;
}


//mode mechantOFF
Sinon pourquoi ça ne marche pas je ne sais pas du tout. Si Image_palette est bien un short[] et Image_bitmap8 un char [] c’est parfait.
Désolé de pas faire avancer je chmilblique mais je voulais te taquiner grand fou de l’optimisation va.:devil:

Yopyop

Ps dsl je ne me suis pas levé du bon pied et en plus je suis en retard maintenant.

Mollusk
24/01/2006, 10h17
Image_bitmap8[] est bien déclaré en char ? (comme yopyop l'a dit), à part ca je vois pas trop :/

Alekmaul
24/01/2006, 10h30
Ce n'est pas un problème d'adressage de pixel comme en mode 4 ?
C'est à dire qu'il faut combiner les pixels X et X+1 et n'adresser qu'en short les données ?

Mollusk
24/01/2006, 10h33
unsigned short IRIS_IN_EWRAM BufferImageModeDessin [120*80] ;

Donc il utilise bien un short pour écrire dans le buffer... D'ailleurs, ca irait peut-etre plus vite en prenant un pointeur sur chaque buffer de type int et en copiant 32bit par 32bit, vous pensez pas (pour Mr Nes qui aime optimiser à fond :) )

edit :


unsigned int *Buffer = (unsigned int*)BufferImageModeDessin ;
unsigned int *VideoBuf = (unsigned int*)ActualVideoBuffer;
for(y=0;y<80;y++)
{
Y1 = y*80; //le compilo devrait le faire mais bon ça coûte rien.
Y2 = y*60;
for(x=0;x<60;x++)
VideoBuf [Y1+x] = Buffer [Y2+x] ;
}


C'est pas mieux comme ca ?

re-edit : ton video buffer tu l'as bien mis en short et pas int à la base ?

Alekmaul
24/01/2006, 10h37
Nan, je suis d'accord Mollusk qu'il fait tout en short (de ce temps là, il va prendre froid d'ailleur le petit nesgba ... :p ) mais ce que je dis c'est qu'il faut mettre les pixels X et X+1 ensembles et adresser uniquement que par 2 pixels à la fois et non 1 seul, comme en mode 4.

Mollusk
24/01/2006, 10h43
si tu bosses en short (ok, en hiver c'est chaud, je te l'accorde), tu n'as pas a adresser 2 pixels à fois (quoi que c'est plus rapide, comme j'ai marqué).

Le 2 pixels, c'est uniquement si tu bosses en mode4 (c'est pour ca qu'un plot point par point serait plus rapide en mode 3 qu'en mode 4, puisqu'en mode 4 faut chopper la couleur de l'autre pixel avant et replacer les 2 pixels en meme temps...)

Brunni
24/01/2006, 11h42
Exactement, et en EWRAM un accès 32 bits est 3 cycles plus lent qu'un accès 16 bits, donc on perd vite l'intérêt de faire des copies 32 bits s'il faut en plus faire des opérations supplémentaires... ;)
Après pour convertir une image 8 bits avec palette 16 bits -> image 16 bits, il n'y a aucune raison que le code d'en dessus ne marche pas. Voici comment tu peux faire plus simplement:
void convertit_image(u8 *imgsrc, u16 *palette, u16 *imgdst, u32 imglen)
{
while (imglen--)
{
*imgdst++ = palette[*imgsrc++];
}
}
Si on veut directement la mettre dans le buffer vidéo, en version optimisée comme Nes aime bien: :p
void blit_img8on16(const u8 *imgsrc, const u16 *pal, u32 x0, u32 y0, u32 w, u32 h)
{
u32 i;
u16 *buf;
while (h--) {
buf = (u16*)ActualBuffer + y0 * 160 + x0;
i=w;
while (i--)
*buf++ = pal[*imgsrc++];
y0++;
}
}
imgsrc : image source 8 bits
pal : palette 16 bits
ActualBuffer : ton buffer vidéo
x0, y0 : positions où dessiner l'image
w, h : largeur, hauteur de l'image
Je n'ai pas testé ce code mais ça devrait aller ^^

Mollusk
24/01/2006, 12h59
simple, clair, efficace... du Brunni bien de chez nous :)

par contre je savais pas que ca serait plus lent de faire par 32bit :/

Japi
24/01/2006, 14h16
en EWRAM oui, mais en IWRAM, l'acces 32bits est pas plus rapide que le 16? j'avais un tableau qui reprenait ça, faut que je le retrouve.
Sinon, là, c'est pour le plaisir qu'il optimise (un peu aussi ^^) mais parce que il a pas trop le choix.

Brunni
24/01/2006, 14h18
Mollusk> En fait j'ai pas dit que ce serait vraiment plus lent, juste que vu que l'EWRAM est en 16 bits, les accès 32 bits sont divisés en deux, et sont donc assez peu avantageux (pas beaucoup, mais un peu quand même :p).
Mais à ça il faut rajouter le temps d'exécution des instructions, donc si tu fais deux accès 16 ce sera plus lent que un de 32, par contre si tu dois faire des opérations en plus en 32 (que tu n'aurais pas besoin en 16) alors là tu perds l'avantage. Par exemple pour plotter un seul pixel 16 bits, tu peux l'écrire ainsi en 16 bits:
u16 *VideoBuffer = (u16*)0x6000000;
void DessPixel(u32 x, u32 y, u16 pixel) {
VideoBuffer[(y<<8) - (y<<4) + x] = pixel;
}
Mais en 32 bits:
u32 *VideoBuffer = (u32*)0x6000000;
void DessPixel(u32 x, u32 y, u16 pixel) {
u32 *ptr = VideoBuffer + (y<<7) - (y<<3) + (x>>1);
*ptr = (*ptr & (0xffff0000 >> ((x&1)<<4))) | (pixel << ((x&1)<<4));
}
Ben là inutile de préciser que la version 32 bits est plus lente, tandis que sur de la RAM 32 bits ça pourrait être discutable... (enfin là pas mais dans certains cas oui :p)
[Edit] Japi> Oui l'IWRAM est 32 bits (1 cycle pour tous les types d'accès).

yopyop
24/01/2006, 14h44
Moi je dis BRAVO !!

Mais je crois qu’il faut quand même faire attention aux pointeurs à la sortie des fonctions.

yopyop

edit cf post de 10h

Mollusk
24/01/2006, 15h31
Brunni, j'ai pas compris là... Ici il pourrait plotter 2 pixels d'un coup (les 2 cote à cote), alors pourquoi se priver ? Ca permettrait de diviser par 2 le nombre de boucles...

Brunni
24/01/2006, 15h52
Oui bien sûr, on s'est mal compris ;)
En fait s'il convertit son image 8 -> 16 puis qu'il copie l'image 16 bits en mémoire vidéo, là il peut le faire deux pixels d'un coup et ce sera effectivement plus rapide.
Par contre s'il écrit directement le resultat en mémoire vidéo sans passer par l'étape de conversion (il gagnera beaucoup de RAM & vitesse comme ça), ben là il est obligé de plotter un pixel à la fois ;)

Mollusk
24/01/2006, 15h53
lol, autant pour moi :)

Nesgba
27/01/2006, 15h04
bon les gars desolé pour ce topic.
merci a tous pour vos conseils, mais je sais d'ou vien le probleme depuis le depart, mon code etais bon mais ce qui ne passai pas c'etait... GBAGraphics :unsure:

c'est la premiere fois qu'il me fait ce coup la Oo je comprend pas pourquoi une image générée avec gbagraphics ne passe pas alors qu'une générée avec mon convertisseur perso ou meme gfx2gba est affichée normalement Oo

Mollusk
27/01/2006, 15h08
c'est quoi ton convertisseur maison ? :p

Brunni
27/01/2006, 15h12
J'aimerais bien que tu postes si possible les deux résultats pour que je puisse les comparer :blink:

Nesgba
29/01/2006, 02h20
J'aimerais bien que tu postes si possible les deux résultats pour que je puisse les comparer :blink:
desolé c'est entierement ma faute j'ai meme pas imaginé que tu pouvai stocker ton tableau en 2D, donc je fesai comme pour afficher un tableau 1D donc incompatibilité ;)

je vais egalement convertir en 2D ca me fait une multiplicationen moin c'est deja ca de gagné :).

mollusk: ben oui un convertisseur, mais fait a la maison, un gfx2gba pour mode 4 et 3 special video (j'ai pas encore integré de compression).