Probleme d'affichage image OpenGL

Bonjour à tous.

Voila j’ai deux petits problèmes avec OpenGL.

Pour le premier, je voudrais, au milieu d’un programme, affiché mon image et qu’ensuite le programme continu.
J’utilise ce code (test est la structure ou toutes les info sont stockées):

[U]Main:[/U]
/************************************* Initialization OpenGL ***************************************/
/* Initialize GLUT state - glut will take any command line arguments
that pertain to it or X Windows */
glutInit(&argc, argv);

/* Select type of Display mode: Single buffer, RGB color*/
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
/***************************************************************************************************/

Chargement de l'image

/******************* Display the image thanks to OpenGL *************************/
glutInitWindowSize(test.Largeur(), test.Hauteur());

/* the window starts at the upper left corner of the screen */
glutInitWindowPosition(0,0);

/* Open a window */
window1 = glutCreateWindow(test.GetNom());

/* Initialize our window. */
InitGL();

/* Register the function to do all our OpenGL drawing. */
glutDisplayFunc(&DrawScene);

/* Start Event Processing Engine */
glutMainLoop();
/***************************************************************************/

[U]Fonction drawscene:[/U]
/* The main drawing function. */
void DrawScene(){
 	// Clear The Screen 
	glClear(GL_COLOR_BUFFER_BIT);

	glDrawPixels( test.Hauteur(), test.Largeur(), GL_LUMINANCE, GL_UNSIGNED_BYTE, test.GetImage() );

	/* don't wait! start processing buffered OpenGL routines */
    glFlush ();
}

Mon problème est que le programme s’arrête quand il exécute glutMainLoop().
Je pense que c’est normal, le problème c’est que si je le met à la fin, mon programme affiche les images qu’a la fin.
Et j’aimerais qu’elle s’affiche au fur et à mesure (En faite j’ai plusieurs images à afficher au fur et a mesure).

Est-ce qu’il y a une fonction pour afficher l’image et continuer le programme après ??
Comme mettre l’image en fond en faite.

Mon second problème est l’image affichée. Elle n’est bonne.
Voici ce que ca donne:

http://osiris.ubishops.ca/~achollet/Affichage/Image_Deforme.JPG

Comme vous pouvez le voir elle est toute étirée !!
l’image originale est Lena.pgm, en P2.

La je pense que j’ai un souci avec ma fonction d’affichage:
glDrawPixels( test.Hauteur(), test.Largeur(), GL_LUMINANCE, GL_UNSIGNED_BYTE, test.GetImage() );

Est-ce que vous sauriez résoudre ca?
(J’ai essayé en inversant Hauteur et Largeur mais ca n’a rien changé ou en mettant GL_BYTE mais la ca m’a sorti une exception à l’éxécution)
Comme matrice je lui envoi la matrice de l’image et elle est sous forme de byte*.

Merci beaucoup pour votre aide !!!

J’essaye de bien comprendre?

Déjà, bien qu’OpenGL soit bien pour ça, je dirais qu’une partie de tes complications vient du fait que tu utilises Glut & OpenGL pour afficher ton image, alors qu’il y a par exemple GTK ou QT qui sont soit OpenSource soit gratuit en utilisation non commerciale, et qui ont certainement des composants images.

Maintenant, supposant que tu voudras pas en changer,

  1. glutMainLoop() = boucle infinie. C’est normal que si tu met du code derrière, il ne se passe rien, sauf si tu fais une ligne de code qui dit à la boucle de se terminer (via exit, etc)
  2. quand tu dis fur et à mesure, je comprend que tu veux qu’elle s’affiche petit à petit - soit pendant son chargement?

Sinon, ta fonction d’affichage - DrawScene - est là pour afficher (ou réafficher) tout ce que tu veux

Pour le reste, pose toi la question de ce que renvoie test.GetImage().

www.opengl.org…

J’ai pas vu d’indication sur l’ordonnancement du tableau, mais vu la gueule de ton image, tes pixels sont stockés dans le tableau de gauche à droite, puis de haut en bas (en gros: d’abord la première ligne, ensuite la seconde). Essaye en changeant la façon dont c’est stocké, ie:

unsigned char c[] = test.GetImage();

c[0] = pixel 0, 0 (y, x)
c[1] = pixel 1, 0 (y, x)

Au lieu de

c[0] = pixel 0, 0 (y, x)
c[1] = pixel 0, 1 (y, x)

Oki !!

Merci pour ta réponse.

Pour changer de façon d’afficher, j’en utilisais une autre avant, mais la c’est pour un projet que je doit utiliser openGL donc non je peux pas changer :frowning:

En faite pour mes images, mon programme se lance, l’utilisateur rentre le nom d’une image et la je veux qu’elle s’affiche, ensuite, le programme fait des modif sur l’image (genre la floute) et je veux que l’image floutée s’affiche à coté.

si j’utilise une ligne de code pour arreter la boucle infinie (glutMainLoop) je suppose que ca va m’enlever la premiere image ??

il n’y a pas un moyen pour la mettre par exemple en fond qu’elle soit affichée tout le temps ??

Pour le tableau, je vais esasyer de changer la facon dont sont stockés les pixels !!

Merci beaucoup pour ton aide en tout cas !!!

Hé bien, voici un exemple - à corriger, parce que tu bosses en 2D - de ce que tu peux faire :

j’ai par contre supposé que la taille de la fenêtre est de 2 fois la largeur.

Tu fais ça dans ta fonction void DrawScene().

glDrawPixels( test.Hauteur(), test.Largeur(), GL_LUMINANCE, GL_UNSIGNED_BYTE, test.GetImageFLOUE() );
glPushMatrix();
  glTranslatef(test.largeur, 0, 0);
  glDrawPixels( test.Hauteur(), test.Largeur(), GL_LUMINANCE, GL_UNSIGNED_BYTE, test.GetImageFLOUE() );
glPopMatrix();

Tu peux aussi avec Glut ouvrir deux fenêtres, ça requiert plus de technique, mais c’est tout à fait possible.

Salut

Je vais esayer ce que tu me dis.
Mais ca va me permettre d’afficher une fenetre, puis de continuer à utiliser mon programme en la laissant ouverte? Parce-que je sais comment ouvrir deux fenêtres, c’est pas ca le probleme, mon probleme c’est plutot de pas utiliser glutMainLoop je pense ?

Sinon, pour mon autre probleme, en faite, j’arrive bien à afficher une image en P5 mais pas une image en P2 (Je vous ai mis un exemple de ce que ca fait avec une P2 dans mon premier post !!!) !!
alors que j’utilise la même façon de stocker les pixels !!

Est-ce que quelqu’un saurait d’ou cela peut provenir ??

Merci d’avance !!

P2 c’est juste du P5 format ascii (texte lisible?)

Si oui, tu as certainement un problème là dedans, dans la façon dont tu lis tes bytes.

De mémoire:

unsigned char* p = new char[width*height];
for (unsigned int i = 0; i < width*height; ++i) {
  int j = 0;
  input >> j; // lire un entier (scanf("%d", &j) si pas c++)
  p[i] = (unsigned char) j; // TODO vérif si j in [0, 255]
}

Au passage, tu passes les paramètres à l’envers:

glDrawPixels( [b]test.Hauteur()[/b], [b]test.Largeur()[/b],...)

C’est largeur, puis hauteur. Vérifie juste que ton tableau fasse bien largeur*hauteur bytes, et ça passera.

Comprend moi bien, car je vais pas y aller par quatre chemins : si tu fais de l’interface graphique, que ce soit en C, Java, Python, etc… tu as toujours une boucle infinie pour vider la liste des événements (= afficher scène, déplacement de souris, etc)

glutMainLoop() ne fait ni plus ni moins que cela : si tu ne l’utilises pas, pas d’interface graphique.

Considère en gros qu’après glutMainLoop() tu ne fais plus rien.

ie:

int main() {
  init();
  glutMainLoop();
  return 0;
}

C’est à ton code d’initialisation de :

  1. initialiser correctement ce qui doit l’être
  2. créer des gestionnaires d’événements, c’est à dire de dire à glut de faire appel à une de tes fonctions pour gérer un événements lambda.

Pour info:

API de Glut en Python (les fonctions sont réutilisables en C, sans trop de choses à revoir, tu as aussi un man en C, qui doit traîner sur la toile) :

pyopengl.sourceforge.net…

Notamment:

pyopengl.sourceforge.net…

Toutes les fonctions qui finissent par Func sont pratiquement toutes des fonctions pour installer un gestionnaire d’événements.

Et sinon, tu dois avoir plein de tuto sur Glut qui traîne sur le net.

Salut !!

Merci pour ta réponse !!

Par contre je seche toujours sur mon histoire de P2. Je comprend pas pourquoi je l’ai mal.

J’ai un tableau de byte à la base: byte * Matrice;
Avec le P5, je li direct un byte donc je le met tel quel dans mon tableau, ensuite pas de souci !!
Avec le P2 je récupere un int. Je le met dans le tableau mais ca me donne un truc bizarre !!!

La j’essaye donc de convertir mes int en byte pour pouvoir les ranger dans le tableau comme je fais avec le P5 !!
Comment je fais pour mettre mes int en byte ??? Bien sur je suis en C++ !!!

J’ai essayé de les mettre en unsigned char mais ca n’a rien changé !!
Faut-il que je change le type de mon tableau en unsigned char ?? Mais dans ce cas j’ai peur que ca foute en l’air on P5 !!
Ca m’arrangerait de pouvoir convertir mes int en byte :stuck_out_tongue:

Edit: J’ai essayé en mettant mon tableau en unsigned char mais ca ne change rien !!!
Donc la je vois pas !!
Je dois pas ranger ce qu’il faut dans le tableau. Pourtant je lis un int, je le cast en unsigned char et je le range dans le tableau !!
Edité le 14/02/2008 à 00:56

byte = sous type de int

Ton problème c’est dans l’ordre de stockage. Regarde ton image, tu le verras tout de suite. Tu mets les lignes à la place des colonnes, et les colonnes à la place des lignes.

Oui j’ai changé déja un truc ca fait plus tout a fait la même chose.

Mais mon proleme c’est que je stocke les pixels de la meme maniere pour une P2 et pour une P5 !!!
Avec la P5 pas de probleme et avec la P2 c’est tout déformé !!!

En faite j’ai l’impression que la fonction drawpixel comprend mal ma matrice.
C’est comme si la premiere ligne de l’image originale était allongée et qu’elle débordait sur la deuxieme ligne !!!

Est-ce qu’il faudrait que je change un argument de drawpixel ?? Si oui lequel et comment ?? j’ai essayé plusieurs possiilités mais ca n’a rien changé !!!

Merci de votre aide

Hum.

Dans les deux cas, P2 & P5 tu utilises le même code d’affichage, et ça marche?

Si oui, alors c’est que dans le cas P2 tu stockes mal.

Donne le cas de ton lecteur de P2 / P5, on verra. Sinon, GL est con : tu lui files un tableau, il l’affiche ligne par ligne.

Dans mon code, je lis tous les données (int pour une P2 et byte pour une P5) et je les met dans mon tableau a une dimension.

Voila mon code:

     //If the filetype is P2
		if (strcmp (fileType, "P2") == 0 )
	        {	
                	while(fe >> val) //loop until the end. Je lis tous les int les uns apres les autres
			{
					Matrice[(i*largeur)+j]= val ;//copy the byte into Matrice
    					j++;
    					if(j%largeur==0)//increment the number of line
    					{
						i++;
						j=0;
   					}
			}
		}
		
		//If the filetype is P5
		else if(strcmp (fileType, "P5") == 0 )
		{	//loop for all the pixels
               for (i=0; i<hauteur ; ++i) 
			{
				for(j=0; j<largeur ; j++)  
				{
					Matrice[(i*largeur)+j]=fe.get();//copy the byte into Matrice
				}
			}  						
		}

Ce code e permet de stocker tous les pixels.
Apres je fais des traitements dessus, et je passe ca a la fonction drawpixel pour qu’elle affiche. (Avant de le passer à drawpixel, je fais un petit traitement sinon j’ai on imae à l’envers, je crois que c’est parce-que opengl li l’image bizarrmeent)
Avec le P5 pas de souci, avec le P2 ca me ait un truc tout étiré en diagonale !!!

Est-ce que tu vois d’ou ca peut venir ??

Je dois avouer ne pas trop aimer le code qui lit le P2 voire l’autre (pas de sécurisation de ce que tu lis au final…)

if (strcmp (fileType, "P2") == 0) {
  for (unsigned int k = 0, m = hauteur*largeur; k < m; ++k) {
      fe >> val;
      if (fe.fail() || val < 0 || val > 255) {
        // XXX gestion des erreurs
      }
      Matrice[k] = (unsigned char) val;
  }
} else if(strcmp (fileType, "P5") == 0 ) {
  fe.read(Matrice, largeur*hauteur);
  if (fe.fail()) {
    // XXX gestion des erreurs
  }
}
  1. P2: j’aime pas trop le coup de j % largeur == 0, donc je l’ai viré, et remplacé par une double boucle (k = index dans le tableau, ça évite une multiplication, l’addition étant plus simple)
  2. P5: j’aime pas lire 1 byte par 1 byte quand tu peux tout lire, les données étant dans le même ordre (ie: ligne par ligne)

Essaye.

PS: Entre nous: mon code pour les PGM/PPM, c’est ça (et ça date) :



typedef struct {
  uchar *pix;
	unsigned int nbl, nbc, nbg;
	char *comment;
} ImgPGM;

ImgPGM* OpenFile( const char *file )
{
	unsigned int comlen = 0, i= 0, j = 0;
	char c = 0;
	char buffer[BUFFER_SIZE] = "";
	char comment[BUFFER_SIZE] = "";
	char type[2] = "";
	
	unsigned int pixlen;
	unsigned int nbl = 0;
	unsigned int nbc = 0;
	unsigned int nbg = 0;
	
	ImgPGM *img = NULL;
	
	Modes mode = MODE_ERROR;
	
	FILE* f = fopen( file, "rb" );
	
	if ( f == NULL )
		return NULL;
	
	if ( fread( type, sizeof(char), 2, f ) < 2 )
		{
			fclose(f);
			return NULL;
		}

	if ( type[0] == 'P' )
		mode = GetMode( type[1] );
	
	if ( mode == MODE_ERROR )
		{
			fclose( f );
			return NULL;
		}
	
	while ( !feof( f ) )
		{
			c = fgetc( f );
			if ( c == '#' )
				{
					if ( nbl == 0 && nbc == 0 && nbg == 0 )
						{
							if ( fgets( buffer, BUFFER_SIZE,  f ) != NULL )
								{
									for ( i = comlen, j = 0; buffer[j] != '\0'; i++, j++ ) 
										comment[i] = buffer[j];
									comlen += j;
									buffer[comlen] = '\0';
								}
						}
					else
						{
							fprintf( stderr, "Erreur fichier malformé (commentaire après informations sur la taille)\n" );
							fclose( f );
							return NULL;
						}
				}
			/* ne fait rien simplement */
			else if ( isspace( c ) )
				;
			/* si on a un digit, c'est que l'on commence la partie lecture de taille : on le remet sur le fichier,
				 afin de pouvoir lire un entier correct. */
			else
				{
					fseek( f, -1, SEEK_CUR );
					if ( fscanf( f, "%u", &nbc ) != 1 )
						{
							ERROR_MSG("Impossible de lire nbc!" );
							fclose( f );
							return NULL;
						}
					while ( isspace( c = fgetc( f ) ) )
						;
					fseek( f, -1, SEEK_CUR );					
					if ( fscanf( f, "%u", &nbl ) != 1 )
						{
							ERROR_MSG("Impossible de lire nbl!" );
							fclose( f );
							return NULL;
						}
					while ( isspace( c = fgetc( f ) ) )
						;
					fseek( f, -1, SEEK_CUR );					
					if ( fscanf( f, "%u", &nbg ) != 1 )
						{
							ERROR_MSG("Impossible de lire nbg!" );
							fclose( f );
							return NULL;
						}
					c = fgetc( f );
					if ( c != '\n' )
						{
							ERROR_MSG("Ligne invalide..." );
							fclose( f );
							return NULL;
						}
					/* le reste dépend du mode */
					break;
				} 
		}
	
	/* glop : on alloue */
	pixlen = nbc*nbl;
	img = AllocPGM( nbc, nbl, nbg, comlen );
	
	if ( img == NULL )
		{
			ERROR_MSG( "Erreur alloc..." );
			fclose( f );
			return NULL;
		}
	
	if ( img->comment != NULL )
		strcpy( img->comment, comment );
	
	/* brutalement : on lit les octets, en priant que ce soit bien 8 bits par octets... sinon ben tant pis ! */
	switch ( mode )
		 {
		 case MODE_GRAY_RAW:
			 if ( fread( img->pix, sizeof(uchar), pixlen, f ) < pixlen )
				 {
						 ERROR_MSG( "pas assez d'octets ... Image invalide" );
						 fclose( f );
						 FreePGM( &img );
						 return NULL;
				 }
			 break;
		 case MODE_GRAY_ASCII:
			 i = 0;
			 
			 for ( i = 0; i < pixlen; i++ )
				 {
					 if ( fscanf( f, "%u", &j ) != 1 || j > 255 )
						 {
							 ERROR_MSG( "nombre invalide" );
							 fclose( f );
							 FreePGM( &img );
							 return NULL;
						 }
					 *(img->pix+i) = (uchar) j;
					 while ( isspace( c = fgetc( f ) ) )
						 ;
					 fseek( f, -1, SEEK_CUR ); 
				 }
			 if ( !feof( f ) )			 
				 while ( isspace( c = fgetc( f ) ) )
					 ;
			 if ( !feof( f ) )
				 {
					 ERROR_MSG( "il y a encore des trucs après le dernier nombre" );
					 fclose( f );
					 FreePGM( &img );
					 return NULL;
				 }
			 break;
		 default: break;
		 }
	fclose( f );
	return img;
}

Jamais mis en place dans OpenGL, mais l’ordre de stockage est le même