Retourner une surface sdl

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

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.