| 12
 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