Merci Millie, je vois que tu as publie ce code en 2006 mais 20 ans plus tard il est quand meme plus simple et efficace que celui que j'ai bidouille pendant 1h avec ChatGPT.
Citation:
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 /*permet de déterminer la valeur d'un pixel au position x,y*/ Uint32 inline SDL_LirePixel(SDL_Surface* surface, int x, int y) { int bpp = surface->format->BytesPerPixel; Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp; switch(bpp) { case 1: return *p; case 2: return *(Uint16 *)p; case 3: if(SDL_BYTEORDER == SDL_BIG_ENDIAN) return p[0] << 16 | p[1] << 8 | p[2]; else return p[0] | p[1] << 8 | p[2] << 16; case 4: return *(Uint32 *)p; default: return 0; } } /*permet d'écrire un pixel au position x,y*/ void inline SDL_EcrirePixel(SDL_Surface* surface, int x, int y, Uint32 pixel) { int bpp = surface->format->BytesPerPixel; Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp; switch(bpp) { case 1: *p = pixel; break; case 2: *(Uint16 *)p = pixel; break; case 3: if(SDL_BYTEORDER == SDL_BIG_ENDIAN) { p[0] = (pixel >> 16) & 0xff; p[1] = (pixel >> 8) & 0xff; p[2] = pixel & 0xff; } else { p[0] = pixel & 0xff; p[1] = (pixel >> 8) & 0xff; p[2] = (pixel >> 16) & 0xff; } break; case 4: *(Uint32 *)p = pixel; break; } }
[Edit] il faut noter que l'on parcourt la surface de destination et non la surface d'origine pour forcer chaque pixel de destination a avoir une couleur à peu près correct (à peu près comme une rotation en informatique est dans la plupart des cas non bijective). Alors que si l'on parcourait les pixels de la surface d'origine, déterminait les positions de sa position, il pourrait y avoir des trous noirs dans la surface de destination.
[Edit] Voici la version qui ne déborde pas sur les bords et qui ajuste la taille de la surface de destination :
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68 /*effectue une rotation centrale, alloue automatiquement la mémoire*/ SDL_Surface* SDL_RotationCentralN(SDL_Surface* origine, float angle) { SDL_Surface* destination; int i; int j; Uint32 couleur; int mx, my, mxdest, mydest; int bx, by; float angle_radian; float tcos; float tsin; double largeurdest; double hauteurdest; /* détermine la valeur en radian de l'angle*/ angle_radian = -angle * M_PI / 180.0; /*pour éviter pleins d'appel, on stocke les valeurs*/ tcos = cos(angle_radian); tsin = sin(angle_radian); /*calcul de la taille de l'image de destination*/ largeurdest= ceil(origine->w * fabs(tcos) + origine->h * fabs(tsin)), hauteurdest= ceil( origine->w * fabs(tsin) + origine->h * fabs(tcos)), /* * alloue la mémoire à l'espace de destination, attention, * la surface est de même taille */ destination = SDL_CreateRGBSurface(SDL_HWSURFACE, largeurdest, hauteurdest, origine->format->BitsPerPixel, origine->format->Rmask, origine->format->Gmask, origine->format->Bmask, origine->format->Amask); /*on vérifie que la mémoire a été allouée*/ if(destination==NULL) return NULL; /*calcul du centre des images*/ mxdest = destination->w/2.; mydest = destination->h/2.; mx = origine->w/2.; my = origine->h/2.; for(j=0;j<destination->h;j++) for(i=0;i<destination->w;i++) { /* on détermine la valeur de pixel qui correspond le mieux pour la position * i,j de la surface de destination */ /* on détermine la meilleure position sur la surface d'origine en appliquant * une matrice de rotation inverse */ bx = (ceil (tcos * (i-mxdest) + tsin * (j-mydest) + mx)); by = (ceil (-tsin * (i-mxdest) + tcos * (j-mydest) + my)); /* on vérifie que l'on ne sort pas des bords*/ if (bx>=0 && bx< origine->w && by>=0 && by< origine->h) { couleur = SDL_LirePixel(origine, bx, by); SDL_EcrirePixel(destination, i, j, couleur); } } return destination; }