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 69 70 71 72 73 74 75 76
|
struct Matrice2x3 {
float _00, _01, _02; // first column
float _10, _11, _12; // second column
};
struct Image {
long width;
long height;
size_t lineStride; // pour passer d'une ligne à une autre dans les données (égal à width dans la plupart des cas, mais de nombreuses images ont du 'padding' pour avoir des nombres de pixels multiple de 4 ou 8, quand ce n'est pas carrément une puissance de 2)
Pixel* data;
};
inline Pixel Safe_GetPixel(const Image& src, int x, int y)
{
return (x >= 0 && x < src.width) && (y >= 0 && y < src.height) ? src.data[x+y*lineStride] : Pixel(0) // or anything
}
void TraitementImage(Image& dest, const Image& src, const Matrice2x3& transform)
{
Pixel* destLine = dest.data;
for (int destLineIdx = 0; (destLineIdx < dest.height); ++destLineIdx) {
// calcul des invariants pour cette boucle
float dstY = float(destLineIdx) + 0.5f;
float baseSrcX = dstY * transform._01 + transform._02;
float baseSrcY = dstY * transform._11 + transform._12;
// préparation boucle sur les colonnes
Pixel* dest = destLine;
for (int destColIdx = 0; (destColIdx < dest.width); ++destColIdx) {
// calcul des invariants pour cette boucle
float dstX = float(destColIdx) + 0.5f;
float srcX = dstX * transform._00 + baseSrcX ;
float srcY = dstX * transform._10 + baseSrcY;
// et hop !
*dest++ = Safe_GetPixel(src,(int)srcX,(int)srcY);
}
// on passe à la ligne suivante
destLine += dest.lineStride;
}
}
//
// Implémentation du mirroir... facile...
//
void MirroirX(Image& dest, const Image& src)
{
Matrice2x3 mirrorX = { -1.0f, 0.0f, src.width, 0.0f, 1.0f, 0.0f };
TraitementImage(dest,src,mirrorX);
}
//
// Implémentation de la rotation autour du centre
// on pourrait rajouter une fonction intermediaire pour une rotation autour de n'importe quel point
//
void RotationCentre(Image& dest, const Image& src, float radians)
{
float centerX = float(width) * .5f + .5f;
float centerY = float(height) * .5f + .5f;
Matrice2x3 rotation;
rotation._00 = rotation._11 = cos(radians);
rotation._10 = sin(radians);
rotation._01 = -rotation._10;
// le compilo fait cette 'optimisation' très bien... c'est juste plus lisible
float one_minus_cos = 1.f - rotation._00;
rotation._02 = centerX * one_minus_cos + centerY * rotation._10;
rotation._12 = centerY * one_minus_cos + centerX * rotation._01;
TraitementImage(dest,src,rotation);
} |
Partager