Probleme chargement d'image

[Résolu]
Signaler
-
 Merci -
Bonjour
Je poste de sujet pour vous exposer un probleme que j'ai rencontrer lors s'une séance de programmation C
J'utiliser la bibliotheque SDL2_image
fonction.c
SDL_Texture *SDL_LoadTexture(App app, char *filename)
{
if (filename == NULL)
{
SDL_CleanApp(app);
SDL_ExitWithError("Veuillez entrer un nom de fichier valide");
}
SDL_Texture *texture;
texture = IMG_LoadTexture(app->renderer, filename);
return texture;
}


main.c
Application application;
PlayerElement player_element;

App app;
Player player;

app = NULL;
player = NULL;

app = &application;
if (app == NULL)
SDL_ExitWithError("impossible de generer l'application");
printf("La generation de l'application est une reussite !\n");
player = &player_element;
if (player == NULL)
SDL_ExitWithError("impossible de generer le player");
printf("La generation du player est une reussite !\n");
/*-----------------------------------------------------------------------*/
player_element.x = SDL_PLAYER_SPAWNPOINT_X;
player_element.y = SDL_PLAYER_SPAWNPOINT_Y;
player_element.texture = SDL_LoadTexture(app, "player.png");
/*-----------------------------------------------------------------------*/


Lorsque que je lance mon programme dans la console celui ci afficher :
console :
La generation de l'application est une reussite !
La generation du player est une reussite

commande de lancement du programme :
>> gcc src/*.c -o bin/prog -I include -L lib -lmingw32 -lSDL2main -lSDL2_image -lSDL2

J'ai put constater que le probleme venait expressement de la fonction IMG_LoadTexture en faisant diffrerent test.

Merci d'avance pour votre aide bonne journée



Configuration: Windows / Chrome 94.0.4606.71

3 réponses

Messages postés
5630
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
13 octobre 2021
950
Salut patedecampagne1,

Tu ne postes pas un exemple de code minimal nous permettant de reproduire ton problème.

Le code que tu postes dans main.c est très parcellaire. Les tests qu'il fait vont systématiquement réussir, car ils consistent à tester que les variables de ton main ont bien une adresse différente de NULL. Tu ne montres pas que tu fasses une initialisation correcte de la SDL ni comment tu tentes d'afficher quelque chose au moyen de la texture que tu es censé avoir chargé, ce qui sont des conditions au succès d'un affichage quelconque.

Ensuite, tu nous donnes le code de ta fonction SDL_LoadTexture(), dans laquelle tu fais un appel à la fonction IMG_LoadTexture() qui est une fonction de la bibliothèque SDL_Image.

Si cette fonction échoue, elle va renvoyer un pointeur NULL et la fonction SDL_GetError() va renvoyer une chaîne de caractères indiquant la cause de l'erreur.

Tu devrais :
  • récupérer la valeur de retour de la fonction
  • tester cette valeur, et si elle est égale à NULL, afficher un message d'erreur et arrêter ton programme


    (...)
    texture = IMG_LoadTexture(app->renderer, filename);
    if (texture == NULL) {
           fprintf(stderr, "Erreur chargement image : %s\n", SDL_GetError());
           exit(EXIT_FAILURE);
    }
    return texture;
}


Dal

Merci pour ta reponse
je te fournit donc mon code entier pour que tu puisse reproduire le probleme
main.c
#include "header.h"

int main(int argc, char *argv[])
{
/*-----------------------------------------------------------------------*/
	Application application;
	PlayerElement player_element;

	App app;
	Player player;
	
	app = NULL;
	player = NULL;

	app = &application;
	if (app == NULL)
		SDL_ExitWithError("impossible de generer l'application");
	printf("La generation de l'application est une reussite !\n");
	player = &player_element;
	if (player == NULL)
		SDL_ExitWithError("impossible de generer le player");
	printf("La generation du player est une reussite !\n");
/*-----------------------------------------------------------------------*/
	player_element.x = SDL_PLAYER_SPAWNPOINT_X;
	player_element.y = SDL_PLAYER_SPAWNPOINT_Y;
	player_element.texture = SDL_LoadTexture(app, "player.png");
/*-----------------------------------------------------------------------*/

	SDL_InitApp(app);

	while (1)
	{
		SDL_RenderAppPrepare(app);

		SDL_AppDoInput(app);

		SDL_RenderAppPresent(app);

		SDL_Delay(16);
	}

	return 1;
}


fonction.c

#include "header.h"

void SDL_ExitWithError(const signed char *message)
{
	SDL_Log("ERROR : %s > %s\n", message, SDL_GetError());
	SDL_Quit();
	exit(EXIT_FAILURE);
}

void SDL_InitApp(App app)
{
	if (SDL_Init(SDL_INIT_VIDEO) != 0)
		SDL_ExitWithError("impossible d'initialiser la bibliotheque SDL2");
	printf("L'initialisation de la bibliotheque SDL2 est une reussite !\n");
	app->window = NULL;
	app->window = SDL_CreateWindow(SDL_WINDOW_TITLE, SDL_WINDOW_POSITION_X, SDL_WINDOW_POSITION_Y, SDL_SCREEN_WIDTH, SDL_SCREEN_HEIGHT, SDL_WINDOW_FLAG);
	if (app->window == NULL)
		SDL_ExitWithError("impossible de generer la fenetre SDL2");
	printf("La generation de la fenetre est une reussite !\n");
	app->renderer = NULL;
	app->renderer = SDL_CreateRenderer(app->window, -1, SDL_RENDERER_FLAG);
	if (app->renderer == NULL)
	{
		SDL_CleanApp(app);
		SDL_ExitWithError("impossible de generer le rendu SDL2");
	}
	printf("La generation du rendu SDL2 est une reussite !\n");
	return;
}

void SDL_CleanApp(App app)
{
	if (app->renderer != NULL)
		SDL_DestroyRenderer(app->renderer);
	if (app->window != NULL)
		SDL_DestroyWindow(app->window);
	return;
}

void SDL_RenderAppPrepare(App app)
{
	SDL_SetRenderDrawColor(app->renderer, SDL_RENDERDRAW_R, SDL_RENDERDRAW_G, SDL_RENDERDRAW_B, SDL_RENDERDRAW_ALPHA);
	SDL_RenderClear(app->renderer);
	return;
}

void SDL_RenderAppPresent(App app)
{
	SDL_RenderPresent(app->renderer);
}

void SDL_AppDoInput(App app)
{
	SDL_Event event;
	while (SDL_PollEvent(&event))
	{
		switch (event.type)
		{
			case SDL_QUIT:
				SDL_CleanApp(app);
				exit(1);
				break;
			default:
				break;
		}
	}
}

SDL_Texture *SDL_LoadTexture(App app, char *filename)
{
	SDL_Texture *texture;
	if ((texture = IMG_LoadTexture(app->renderer, filename)) == NULL)
		SDL_ExitWithError("impossible de charger la texture");
	return texture;
}

void SDL_AppBlitTexture(App app, SDL_Texture *texture, int x, int y)
{
	SDL_Rect dest;
	dest.x = x;
	dest.y = y;
	SDL_QueryTexture(texture, NULL, NULL, &dest.w, &dest.h);
	SDL_RenderCopy(app->renderer, texture, NULL, &dest);
	return;
}


header.h

#ifndef __HEADER__H__
#define __HEADER__H__

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <SDL.h>
#include <SDL_image.h>

#include "def.h"
#include "objects.h"

void SDL_ExitWithError(const signed char *message);
void SDL_InitApp(App app);
void SDL_CleanApp(App app);
void SDL_RenderAppPrepare(App app);
void SDL_RenderAppPresent(App app);
void SDL_AppDoInput(App app);
SDL_Texture *SDL_LoadTexture(App app, char *filename);
void SDL_AppBlitTexture(App app, SDL_Texture *texture, int x, int y);


#endif


def.h

#ifndef __DEF__H__
#define __DEF__H__

#define SDL_SCREEN_WIDTH 800
#define SDL_SCREEN_HEIGHT 600 

#define SDL_WINDOW_TITLE "SDL2"
#define SDL_WINDOW_POSITION_X SDL_WINDOWPOS_CENTERED
#define SDL_WINDOW_POSITION_Y SDL_WINDOWPOS_CENTERED
#define SDL_WINDOW_FLAG 0

#define SDL_RENDERER_FLAG SDL_RENDERER_SOFTWARE

#define SDL_RENDERDRAW_R 45
#define SDL_RENDERDRAW_G 68
#define SDL_RENDERDRAW_B 255
#define SDL_RENDERDRAW_ALPHA 255

#define SDL_PLAYER_SPAWNPOINT_X 100
#define SDL_PLAYER_SPAWNPOINT_Y 100
#define SDL_PLAYER_TEXTURE "player.png"

#endif


objects.h

#ifndef __OBJECTS__H__
#define __OBJECTS__H__

typedef struct Application
{
	SDL_Window *window;
	SDL_Renderer *renderer;
	int up;
	int down;
	int left;
	int right;
} Application, *App;

typedef struct PlayerElement
{
	int x;
	int y;
	SDL_Texture *texture;
} PlayerElement, *Player;


#endif


command.txt

gcc src/*.c -o bin/prog -I include -L lib -lmingw32 -lSDL2main -lSDL2_image -lSDL2
.\bin\prog.exe




Ce code passe au compilateur mais crash au lancement avec l'affichage annoncer au dernier poste
Merci de votre aide
Messages postés
5630
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
13 octobre 2021
950
Alors, j'avais demandé un "exemple de code minimal", pas 200+ lignes.

Quoi qu'il en soit, le code complet de main montre que :
  • tu déclares
    Application application;
    mais tu n'initialises pas son contenu
  • tu mets dans
    App app;
    l'adresse de
    application;
    , App étant en fait de type pointeur sur Application (un typedef qui masque un type pointeur, c'est pas terrible, en passant)


voilà le typedef :

typedef struct Application
{
 SDL_Window *window;
 SDL_Renderer *renderer;
 int up;
 int down;
 int left;
 int right;
} Application, *App;
  • tu passes app, qui pointe sur la struct non initialisée, à ta fonction :


SDL_Texture *SDL_LoadTexture(App app, char *filename)
{
 SDL_Texture *texture;
 if ((texture = IMG_LoadTexture(app->renderer, filename)) == NULL)
  SDL_ExitWithError("impossible de charger la texture");
 return texture;
}


En l'absence d'initialisation, app->renderer contient n'importe quoi.

Or, le prototype de la fonction IMG_LoadTexture() est :

SDL_Texture *IMG_LoadTexture(SDL_Renderer *renderer, const char *file)


et suppose que tu passes un pointeur sur SDL_Renderer valide, ce qui n'est pas le cas et ce qui provoque certainement le crash que tu vois.

Tu n'initialises le contenu pointé par app qu'en ligne 29 de ton main() quand tu appelles
SDL_InitApp(app);
...

En effet, dans fonction.c , on peut voir que la fonction
void SDL_InitApp(App app)
, en autres initialisations, appelle SDL_CreateRenderer() et range le pointeur obtenu dans
app->renderer
.

Tu ne peux pas appeler ta fonction
SDL_LoadTexture()
avant
SDL_InitApp(app);
...

Dal
Messages postés
5630
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
13 octobre 2021
950
Est-ce que ma réponse ci-dessus répond à ta question ?

N.B. :
Il y a une coquille dans ma prose ci-dessus : "en autres initialisations" -> "entre autres initialisations" ... même si, je pense, cela reste compréhensible :-P
>
Messages postés
5630
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
13 octobre 2021

En effet tu m'a permit de régler mon problème
Merci a toi tu m'a bien aider.
Je viendrais sans doute reposer des question sur le forum en cas d'imprévus.
Merci et bonne continuation