Bonjour à tous,
J'ai un tableau où chaque élément correspond à l'intensité d'un pixel. Je souhaiterai afficher dans une fenêtre l'image associée mais je ne sais pas comment faire ceci. Pouvez vous m'aidez s'il vous plaît ?
Version imprimable
Bonjour à tous,
J'ai un tableau où chaque élément correspond à l'intensité d'un pixel. Je souhaiterai afficher dans une fenêtre l'image associée mais je ne sais pas comment faire ceci. Pouvez vous m'aidez s'il vous plaît ?
Pour répondre simplement il te faut passer par une bibliothèque capable de gérer l'environnement graphique que tu utilises. Pour ma part c'est Gtk+. Mais il y en a d'autres...
J'utilise la SDL mais après je ne sais pas comment procéder pour m'afficher l'image.
J'imagine qu'il faut passer par ces fonctions :
http://wiki.libsdl.org/moin.cgi/CategoryPixels
J'ai trouvé plutôt cette fonction qui me semble plus adaptée à ce que tu recherches :
SDL_ConvertPixels();.
Bonsoir,
Avec la SDL le plus simple serait de créer une SDL_Surface avec tes pixels afin de l'afficher.
j'ai trouvé une solution, la voici :
Cependant j'ai un souci avec le redimensionnement de l'image.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 void affiche(double **I,int nrow,int ncol) { int i,j,k=0; // ######## affichage de l'image a l'ecran ########################## SDL_Surface *ecran = NULL, *lignes[nrow*ncol]={NULL}; SDL_Rect position; SDL_Init(SDL_INIT_VIDEO); ecran = SDL_SetVideoMode(nrow,ncol, 32, SDL_HWSURFACE|SDL_RESIZABLE); for (i = 0 ; i <nrow*ncol; ++i) lignes[i] = SDL_CreateRGBSurface(SDL_HWSURFACE,1,1, 32, 0, 0, 0, 0); SDL_WM_SetCaption("Picture SDL", NULL); SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 0, 0, 0)); // la couleur de l'ecran est noir for (i = 0 ; i < nrow; ++i){ for(j=0;j<ncol;++j,++k){ position.x = j; // Les lignes sont à gauche (abscisse de 0) position.y = i; // La position verticale dépend du numéro de la ligne SDL_FillRect(lignes[k], NULL, SDL_MapRGB(ecran->format, I[i][j],I[i][j],I[i][j])); SDL_BlitSurface(lignes[k], NULL, ecran, &position); }} SDL_Flip(ecran); pause(); for (i = 0 ; i <nrow*ncol; ++i) // N'oubliez pas de libérer les 199*199 surfaces SDL_FreeSurface(lignes[i]); SDL_Quit(); return; } void pause() { int continuer = 1; SDL_Event event; while (continuer) { SDL_WaitEvent(&event); switch(event.type) { case SDL_QUIT: continuer = 0; } } }
Pouvez vous m'aider ?
Bonsoir,
Pour moi, tu peux déjà simplifier ta fonction, en te passant de la variable lignes:
Ensuite, quel est ton problème de redimensionnement? Et comment se présente le paramètre I que tu passes à la fonction?Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 void affiche(double **I,int nrow,int ncol) { int i,j; //,k=0; // ######## affichage de l'image a l'ecran ########################## SDL_Surface *ecran = NULL; //, *lignes[nrow*ncol]={NULL}; SDL_Rect position; SDL_Init(SDL_INIT_VIDEO); ecran = SDL_SetVideoMode(nrow,ncol, 32, SDL_HWSURFACE|SDL_RESIZABLE); // for (i = 0 ; i <nrow*ncol; ++i) // lignes[i] = SDL_CreateRGBSurface(SDL_HWSURFACE,1,1, 32, 0, 0, 0, 0); SDL_WM_SetCaption("Picture SDL", NULL); SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 0, 0, 0)); // la couleur de l'ecran est noir position.w=position.h=1; for (i = 0 ; i < nrow; ++i){ for(j=0;j<ncol;++j) { // ,++k){ position.y = i; // La position verticale dépend du numéro de la ligne position.x = j; // Les lignes sont à gauche (abscisse de 0) // SDL_FillRect(lignes[k], NULL, SDL_MapRGB(ecran->format, I[i][j],I[i][j],I[i][j])); // SDL_BlitSurface(lignes[k], NULL, ecran, &position); SDL_FillRect(ecran,&position,SDL_MapRGB(ecran->format, I[i][j],I[i][j],I[i][j])); }} SDL_Flip(ecran); pause(); // for (i = 0 ; i <nrow*ncol; ++i) // N'oubliez pas de libérer les 199*199 surfaces // SDL_FreeSurface(lignes[i]); SDL_Quit(); return; }
Ok ça marche aussi,
En fait mon paramètre I est une matrice de double qui contient les valeurs des pixels en niveau de gris d'une image.
Le souci de redimensionnement c'est que lorsque j'affiche mon image de taille 199*199, je souhaiterai agrandir la fenêtre.
La fenêtre change bien de dimension mais l'image reste à la même taille.
Je souhaiterai que l'image se redimensionne avec la fenêtre.
Par contre j'ai pas compris cette instruction :
position.w=position.h=1;
Pouvez vous me l'expliquer ?
Sans être présomptueux, le contraire m'eut étonné :DCitation:
Ok ça marche aussi
SDL_FillRect remplit une portion de surface (ecran en l'occurence) avec un rectangle. Ce rectangle est défini par position.x et position.y pour les coordonnées du coin supérieur gauche, et par position.w et position.h pour ce qui est des largeur et hauteur du rectangle. Comme tu ne remplis qu'un pixel, w=h=1.Citation:
Par contre j'ai pas compris cette instruction :
position.w=position.h=1;
Pouvez vous me l'expliquer ?
Si, par exemple, w=10 et h=35, une surface de 10 pixels de largeur et de 35 pixels de hauteur serait remplie avec la couleur demandée.
Pour ce qui est du redimensionnement, c'est un peu plus délicat*. Il faut d'abord, via un event, repérer le fait que l'utilisateur change la taille de la fenêtre. Ensuite, il faut récupérer la nouvelle taille (plus grande ou plus petite), et appliquer une fonction de redimensionnement à l'image, qui s'appelle rotozoomSurface(...). Cette fonction n'est pas disponible en standard avec SDL, mais bien dans un set de fonctions qui s'appelle SDL_gfx, que tu peux télécharger ici (voir le click here dans la page :P)Citation:
Le souci de redimensionnement c'est que lorsque j'affiche mon image de taille 199*199, je souhaiterai agrandir la fenêtre.
Je souhaiterai que l'image se redimensionne avec la fenêtre.
Si tu as besoin de plus d'explications, n'hésite pas.
Edgar.
* cela changera la physionomie de ton programme. Mais bon, rien de bien compliqué, uniquement quelques aménagements.
Bonjour,
Avec les informations que nous avons actuellement, la bibliothèque des bibliothèques plus évolués que la SDL aurait été préférable. Je pense à Qt ou GTK ou autre du même genre. Je dis cela, car tout ce que l'on a vu jusqu'à maintenant, ne justifie toujours pas le choix de la SDL. Sauf si vous voulez refaire quelques routines bas niveau, mais cela pas du tout le cas.
Sinon, bonne continuation.
Bonjour à tous,
Je me permet de ré-ouvrir ce topic car j'ai un problème d'affichage avec certaines images en utilisant la méthode que vous m'avez préconisé.
J'arrive à afficher des images de faibles résolutions mais quand il s'agit d'images de plus grandes tailles chez moi ça ne fonctionne pas.
La taille de l'image testée est de 1920 X 2560, pouvez-vous m'aidez svp ?
C'est un peu vague. Qu'et-ce qui ne fonctionne pas?Citation:
chez moi ça ne fonctionne pas
Je viens de tester ceci
qui fonctionne très bien. Evidemment, la fenêtre ouverte est nettement plus grande que la surface de l'écran.Code:ecran = SDL_SetVideoMode(1920,2560, 32, SDL_HWSURFACE|SDL_DOUBLEBUF);
En fait la fenêtre s'affiche, cependant l'image ne s'affiche pas dans la fenêtre.
Ce qui est bizarre avec des résolutions plus faible l'image s'affiche.
Je pense que le problème est la :
vu que lorsque je modifie la couleur de la fenetre :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13 position.w=position.h=1; for (i = 0 ; i < nrow; ++i){ for(j=0;j<ncol;++j){ position.x = j; // Les lignes sont à gauche (abscisse de 0) position.y = i; // La position verticale dépend du numéro de la ligne SDL_FillRect(ecran,&position,SDL_MapRGB(ecran->format,I[i][j],I[i][j],I[i][j])); }} SDL_Flip(ecran); pause();
La fenêtre est blanche sans l'image à l'intérieur.Code:
1
2 SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 255, 255, 255));
Ceci fonctionne parfaitement chez moi:
Jai supprimé tous les tests d'erreur pour plus de clarté.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 #define WIDTH 1920 #define HEIGHT 2560 int main(int argc,char *argv[]) { SDL_Surface *ecran; SDL_Rect position; int i,j; double *img; img=malloc(WIDTH*HEIGHT*sizeof(double)); /* Génération des pixels */ for(i=0;i<WIDTH;i++) for(j=0;j<HEIGHT;j++) *(img+i*WIDTH+j)=rand()%256; /* Création de la fenêtre et mise en noir */ SDL_Init(SDL_INIT_VIDEO); ecran=SDL_SetVideoMode(WIDTH,HEIGHT,32,SDL_HWSURFACE|SDL_DOUBLEBUF); // |SDL_RESIZABLE); SDL_FillRect(ecran,NULL,SDL_MapRGB(ecran->format,0,0,0)); /* Remplissage de la fenêtre */ position.w=position.h=1; for (i=0;i<WIDTH;++i) for(j=0;j<HEIGHT;++j) { position.x=i; position.y=j; SDL_FillRect(ecran,&position,SDL_MapRGB(ecran->format,*(img+i*WIDTH+j),*(img+i*WIDTH+j),*(img+i*WIDTH+j))); } SDL_Flip(ecran); pause(); free(img); SDL_FreeSurface(ecran); SDL_Quit(); return(0); }
Ne sachant pas comment ton tableau était construit, je ne me suis pas posé de question sur
mais es-tu bien sur de tes assignations? Car, évidemment, pour un tableau carré (133x133) une erreur ne se verra pas, mais pour un tableau rectangulaire...Code:
1
2
3
4 for (i = 0 ; i < nrow; ++i){ for(j=0;j<ncol;++j){ position.x = j; // Les lignes sont à gauche (abscisse de 0) position.y = i; // La position verticale dépend du numéro de la ligne
Bonjour,
Est ce que l'image est bien chargée ?
Peut on voir le code que vous utilisez ?
Après avoir réfléchi sur vos derniers propos j'ai trouvé l'erreur.
Elle se situe là :
il faut intechanger nrow et ncol, ncol correspond pour moi à votre width.Code:
1
2 ecran = SDL_SetVideoMode(nrow,ncol, 32, SDL_HWSURFACE|SDL_RESIZABLE);
Maintenant mon image dépasse la dimension de mon écran ce qui est normale.
Il n'existe pas un moyen plus simple que ce que vous avez exposé, pour pouvoir redimensionner ma fenêtre en même temps que l'image ?
J'aimerai pouvoir la regarder dans des dimensions moins grandes ?
Pensez vous que pour des opérations de traitement d'images il serait mieux d'utiliser GTK au lieu de la SDL ?
Modifier la taille de l'image n'a rien de bien sorcier. Il y a juste une étape supplémentaire: il faut construire l'image de base dans une SDL_Surface. Cette surface de base ne sera jamais modifiée, c'est par extrapolation de celle-ci que l'on génèrera une surface d'une autre taile.
Voici l'enchainement des tâches (je prends comme exemple la variable img créée dans une autre réponse):
1) Création de la surface de base
Pour afficher l'image suivant sa taille:Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 /* Creation de l'image orignale */ SDL_Surface *createImg(double *img) { int i,j; SDL_Surface *simg; SDL_Rect position; simg=SDL_CreateRGBSurface(SDL_HWSURFACE,WIDTH,HEIGHT,32,0,0,0,0); position.w=position.h=1; for (i=0;i<WIDTH;++i) for(j=0;j<HEIGHT;++j) { position.x=i; position.y=j; SDL_FillRect(simg,&position,SDL_MapRGB(simg->format,*(img+i*HEIGHT+j),*(img+i*HEIGHT+j),*(img+i*HEIGHT+j))); } return(simg); }
Et pour gérer les events:Code:
1
2
3
4
5
6
7
8
9
10
11
12
13 void displayImg(SDL_Surface **ecran,SDL_Surface *src,int width,int height) { SDL_Surface *newSurf; if(*ecran!=NULL) SDL_FreeSurface(*ecran); if(src->w!=width || src->h!=height) newSurf=rotozoomSurfaceXY(src,0.,(double)width/(double)src->w,(double)height/(double)src->h,1); else newSurf=src; *ecran=SDL_SetVideoMode(newSurf->w,newSurf->h,32,SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_RESIZABLE); SDL_BlitSurface(newSurf,NULL,*ecran,NULL); SDL_Flip(*ecran); if(newSurf!=src) SDL_FreeSurface(newSurf); }
Enfin, le main:Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 /* Traitement des event */ void treatEvent(SDL_Surface **ecran,SDL_Surface *img) { int done; SDL_Event event; done=0; while(!done) { SDL_WaitEvent(&event); switch(event.type) { case SDL_QUIT: done=1; break; case SDL_KEYDOWN: switch(event.key.keysym.sym) { case SDLK_ESCAPE: done=1; break; case SDLK_1: case SDLK_KP1: displayImg(ecran,img,WIDTH,HEIGHT); break; case SDLK_2: case SDLK_KP2: if(event.key.keysym.mod&KMOD_CTRL) displayImg(ecran,img,WIDTH*2,HEIGHT*2); else displayImg(ecran,img,WIDTH/2,HEIGHT/2); break; // // etc... // default: break; } break; case SDL_VIDEORESIZE: displayImg(ecran,img,event.resize.w,event.resize.h); break; } } }
Il faut ajouterCode:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 int main(int argc,char *argv[]) { SDL_Surface *ecran,*imgSurf; double *img; SDL_Init(SDL_INIT_VIDEO); img=malloc(WIDTH*HEIGHT*sizeof(double)); generateImg(img); imgSurf=createImg(img); ecran=NULL; displayImg(&ecran,imgSurf,WIDTH,HEIGHT); treatEvent(&ecran,imgSurf); free(img); SDL_FreeSurface(imgSurf); SDL_FreeSurface(ecran); SDL_Quit(); return(0); }
et linker avec la librairieCode:#include <sdl_rotozoom.h>
Pour GTK, je n'en sais rien, je ne connais pas (encore) cette librairie (c'est dans les bagages pour l'été).Code:sdlgfx.lib
Edgar.
Bonjour,
Je vous remercie ça fonctionne ;).
Cependant j'ai un petit souci avec la gestion des événements. J'aimerai savoir comment puis-je faire pour afficher que des images qui ont une résolution inférieur à celle de l'écran. C'est à dire si la résolution de l'image dépasse celle de l'écran, la taille de cette dernière devient celle de l'écran.
Tu charge l'image, tu regarde sa taille, tu la compare avec celle de l'écran, et si dans une des deux dimensions (largeur ou hauteur) elle dépasse, tu redimensionne.