Retourner une surface sdl

4/5 (3 avis)

Snippet vu 5 190 fois - Téléchargée 17 fois

Contenu du snippet

Dans votre logiciel de dessin préféré, vous avez en général les options "retournement vertical" et "retournement horizontal" qui permettent de retourner l'image

Par exemple si l'image c'est ':)' elle deviendra '(:' une fois retournée

Cette source propose de faire pareil en SDL. Je ne mets que le retournement horizontal, car le vertical n'est pas compliqué à faire après.

Source / Exemple :


void retournementHorizontal(SDL_Surface* surface) {
	int y, i;
	Uint8 *pixel1, *pixel2;

	if (surface == NULL) return;

	SDL_LockSurface(surface);

	// on prend chaque ligne une par une
	for (int y = 0; y < surface->h; y++) {
		// pixel1 pointe vers le premier pixel de la ligne
		pixel1 = (Uint8*)surface->pixels + y * surface->pitch;
		// pixel2 pointe après le dernier pixel de la ligne
		pixel2 = pixel1 + surface->w * surface->format->BytesPerPixel;

		// on fait se rapprocher les pointeurs, et dès qu'ils se touchent (au milieu), c'est fini pour cette ilgne
		while (pixel1 < pixel2) {
			pixel2 -= surface->format->BytesPerPixel;

			// on échange les valeurs *pixel1 et *pixel2 avec une petite boucle
			for (i = 0; i < surface->format->BytesPerPixel; i++) {
				Uint8 tmp = *(pixel2 + i);

  • (pixel2 + i) = *(pixel1 + i);
  • (pixel1 + i) = tmp;
} pixel1 += surface->format->BytesPerPixel; } } SDL_UnlockSurface(surface); } SDL_Surface* copierEtRetourner(SDL_Surface* s) { // la fonction SDL_ConvertSurface permet de dupliquer facilement une surface SDL_Surface* nouv = SDL_ConvertSurface(s, s->format, s->flags); if (nouv != NULL) retournementHorizontal(nouv); return nouv; }

Conclusion :


Le principe de l'algorithme est de prendre chaque ligne une à une.
On créé alors un pointeur au début de la ligne et un à la fin, puis on se fait se rapprocher les pointeurs l'un de l'autre (celui du début avance, celui de la fin recule) tout en inversant à chaque fois les pixels.

La seule difficulté est qu'il ne faut pas copier octet par octet car dans le cas d'une image 16, 24 ou 32 bits cela inverserait les couleurs.
On avance/recule en fait les pointeurs de <surface->format->BytesPerPixel> octets, et pour copier chaque pixel on fait une petite boucle.

Je pense que pour optimiser le code on peut :
- sortir la variable "tmp" de la boucle (<Uint32 tmp = *((Uint32*)pixel2)>) puis utiliser les opérations bit par bit pour assigner sa valeur dans pixel1, mais il faudrait gérer le big/little endian et ça peut devenir compliqué

- utiliser les templates en C++ pour avoir des pointeurs dont le type correspond au format de chaque pixel mais à ce moment l'appel de fonction serait moins générique, il faudrait quelque chose du genre "retourner<Uint16>(surface)" pour une surface 16 bits par exemple

Le retournement vertical est facile à faire avec "pixel2 = pixel1 + surface->h * surface->format->pitch" et en avançant/reculant les pointeurs de "surface->format->pitch" à chaque fois
Ajouter un commentaire Commentaires
shorzy Messages postés 94 Date d'inscription jeudi 23 novembre 2000 Statut Membre Dernière intervention 1 juin 2013
5 sept. 2009 à 13:39
sous Qt, il suffit de changer la Matrice
: 1 Ligne de Code
lui88 Messages postés 28 Date d'inscription lundi 12 janvier 2009 Statut Membre Dernière intervention 22 juin 2009
17 mars 2009 à 18:10
oui excellent programme , je suis d'accord avec toi JPR74 celà et assez rare pour sa que je mets une bonne note ;) .
bonne continuation ;)
JPR74 Messages postés 9 Date d'inscription mercredi 1 août 2007 Statut Membre Dernière intervention 16 mars 2009
16 mars 2009 à 10:45
Bonjour,

Quel plaisir de trouver un programme dont les explications et les commentaires sont écrits en français correct !
Je le signale car cela est assez rare et mérite un commentaire.
Les explications, claires et bien placées, aident à comprendre le fonctionnement du programme et permettront son extension.
Cordialement,
JPR

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.