Images et Transformations
Bon, voilà un petit tutorial sur comment faire des transformations, principalement rotation et scaling, et quelques petits détails insignifiants avec ça. Il est très probable que vous connaissiez déjà tout ce que j'expliquerai ici donc ne vous étonnez pas si c'est le cas

J'ai décidé de réaliser ce mini-tutorial quand en codant une rotation toute bête, je me suis aperçu, que bah, il y avait une (vraiment) minuscule subtilité. J'ai donc cherché sur un bout de papier le pourquoi du comment et j'ai pensé que ça pourrait être utile à quelques uns. Et quitte a expliquer quelque chose, autant faire un truc qui soit plus consistant qu'une simple explication des rotations... (d'autant plus qu'on peut les combiner a un scaling en même temps

A ) Représentation des images (Pixels, toussa....)
Bon, je suppose que tout le monde sait ce qu'est un pixel donc je ne vais pas m'attarder sur cette partie...
Pour faire simple, une image est une matrice de pixels, chaque pixel étant un point de l'image, qu'on peut assimiler à un petit carré de dimensions 1x1, avec sa position et sa couleur propre... Il y aurait certainement plus a dire que ça, mais je ne pense pas que ça soit si important. J'améliorerais ça si jamais ce n'est pas assez clair

Bon je ne pense pas qu'il y ait quelque chose a ajouter à celà, peut être les formats de pixels les plus courants si ça intéresse du monde...
B ) Dimensions et coordonnées en pixels
Tout d'abord un pixel... Il a deux coordonnées (On travaille en 2d... En 3d, avec des textures volumiques par exemple, il en aurait 3) et une couleur (j'ai un peu de mal à imaginer un pixel avec plus d'une couleur

Il nous faut aussi un moyen pour bien repérer les pixels, alors utilisons une grille (en rouge ici) pour laquelle chaque intersection correspond à un pixel (en jaune)

Maintenant prenons une image plus grande, et prenons deux pixels A(xa, ya) et B(xb, yb). Si tout va bien ces deux pixels forment un rectangle... ou au moins une ligne... ou au pire un point. On trouve donc
largeur = |xb - xa| + 1
hauteur = |yb - ya| + 1
Attaquons nous au calcul des coordonnées du centre d'un rectangle. Le centre pouvant être vu comme l'isobarycentre des quatre points du rectangle, nous en déduisons ces formules:
x = (gauche + droite) / 2Ou encore
y = (haut + bas) / 2
x = gauche + (largeur - 1) / 2
y = haut + (hauteur - 1) / 2
C ) Translations
Ici aucun problème, c'est tout bête

Imaginons que vous avez un pixel au point M(x, y) que vous voulez déplacer d'un vecteur u(xu, yu), vous ajoutez simplement les coordonnées du vecteur à celles de votre pixel et c'est bon.
x = x + xu
y = y + yu
Evidemment, les translations d'images fonctionnent de manière semblable, les images étant elle-mêmes composées de pixels

D ) Clipping
Bon, petit bonus qui n'a pas énormément à voir, mais qui se combine généralement très bien avec tout ce qui est rotation/scaling, et qui plus est, qui va de paire avec la translation.
Le clipping (le découpage quoi) ça consiste à réduite le dessin d'une image, un sprite généralement, à un rectangle donné, qui est généralement au maximum égal à celui de l'imge dans laquelle vous dessinez.
C'est simple, vous testez les coordonnées de chaque pixel. Si le pixel est dans le rectangle, vous continuez à dessiner, sinon vous passez au suivant ou vous arrêtez (a voir en fonction des cas). Rapellez vous les calculs de largeur et hauteur et tout ira bien.
Il est généralement utile de définir une fonction qui s'occupera de tester tout cela pour vous dans vos programme afin de diminuer la redondance du code.
E ) Le redimensionnement (scaling)
Etirer/Compresser une image... idée étrange... ça va certainement être super moche ! Bah oui peut être un peu, mais c'est très pratique, principalement pour les jeux vidéos.
Le principe, vous le connaissez, on dessine une image (ou une partie) dans un rectangle plus petit ou plus grand, en l'étirant ou en la compressant de manière à ce qu'elle rentre dans le rectangle.
Maintenant, comment faire ça ? encore une fois ça n'est pas très difficile.
A priori deux méthodes s'offrent à vous: (On considère une partie d'image comme une image)
1 - Pour chaque pixel de l'image source, trouver le pixel correspondant de l'image de destination et en changer la couleur
2 - La même chose, mais en sens inverse, c'est à dire qu'on prend chaque pixel de la destination et on regarde quel pixel de la source on doit utiliser afin de connaître sa couleur
Pour des raisons logiques on préfèrera la deuxième méthode. La première méthode, si on y regarde de plus près, se contente de dessiner un pixel de destination pour un pixel source, donc si l'image de destination est plus grade, on verra du 'vide' entre les pixels, et pour une image plus petite, il y aura du chevauchement de 'pixels'
Voilà le pseudo-code pour la méthode 2:
EtirerImage(Source, Destination) Pour Chaque Pixel de Destination X = Pixel.X * Source.Largeur / Destination.Largeur Y = Pixel.Y * Source.Hauteur / Destination.Hauteur Pixel.Couleur = Source.Pixel(X, Y).Couleur Fin Fin
Pour finir, notez que certaines filtres tels que entre autres bilinear, trilinear et bicubic, permettent d'avoir un redimensionnement plus lisse en utilisant les couleurs des pixels adjacents dans l'image source pour la détermination de la couleur de chaque pixel de l'image de destination. La technique de redimensionnement exposée ici quand a elle se nomme "pixel resize" du fait qu'en quelque sorte on agrandit les pixels.
F ) La rotation
La rotation... Souvenez vous de vos cours de mathématiques si lointains (ou pas)... Pour une rotation nous avons besoin d'un centre de rotation et d'un angle de rotation. Pas bien compliqué jusqu'ici.
Maintenant, le choix du centre de rotation. C'est à vous de voir, ça peut être le centre de l'image, le centre d'un rectangle, un point quelconque, ou tout autre chose, cela dépend vraiment de l'image et de ce que vous voulez faire.
Attention toutefois a bien choisir votre centre de rotation si vous ne voulez pas obtenir un résultat erroné ^^
A présent, concentrons nous sur le problème de la rotation en elle même. Nous avons ici aussi le choix entre deux méthodes, qui sont les mêmes que précédement, et pour les mêmes raisons la première est éliminée.
Lors de la rotation, nous avons juste a appliquer nos formules de rotation, en tenant compte du recentrage. Attention toutefois, car nous travaillons de la destination vers la source, donc notre angle devrait être inversé... Mais étant donné que les ordonnées sont inversées par rapport à la trigonométrie classique, nous pouvons conserver notre angle

TournerImage(Source, Destination, Angle) Pour Chaque Pixel de Destination X = (Pixel.X - Destination.Centre.X) * Cos(Angle) - (Pixel.Y - Destination.Centre.Y) * Sin(Angle) + Source.Centre.X Y = (Pixel.Y - Destination.Centre.Y) * Cos(Angle) + (Pixel.X - Destination.Centre.X) * Sin(Angle) + Source.Centre.Y Pixel.Couleur = Source.Pixel(X, Y).Couleur Fin Fin
G ) Remerciements
- Ethaniel (voir les posts en dessous)