Retourner une surface sdl

Soyez le premier à donner votre avis sur cette source.

Snippet vu 5 048 fois - Téléchargée 16 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

A voir également

Ajouter un commentaire Commentaires
Messages postés
94
Date d'inscription
jeudi 23 novembre 2000
Statut
Membre
Dernière intervention
1 juin 2013

sous Qt, il suffit de changer la Matrice
: 1 Ligne de Code
Messages postés
28
Date d'inscription
lundi 12 janvier 2009
Statut
Membre
Dernière intervention
22 juin 2009

oui excellent programme , je suis d'accord avec toi JPR74 celà et assez rare pour sa que je mets une bonne note ;) .
bonne continuation ;)
Messages postés
9
Date d'inscription
mercredi 1 août 2007
Statut
Membre
Dernière intervention
16 mars 2009

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.