[XviD-devel] warp_gen.c for testing GMC

skal xvid-devel@xvid.org
20 Nov 2002 17:21:45 +0100


--=-gPI24JGsYtLaB38BKprD
Content-Type: text/plain
Content-Transfer-Encoding: 7bit


	Hi,

	while trying to understand what was intended (if anything
	was) for GMC interpolation (section 7.8.4-5), I've come
	with something that may be useful for testing GMC ME. Attached
	is a small generator of warped synthetic images. It's not
	at all exact, norm-wise. Tested under linux only.

	bye,
		Skal


--=-gPI24JGsYtLaB38BKprD
Content-Disposition: attachment; filename=warp_gen.c
Content-Transfer-Encoding: quoted-printable
Content-Type: text/x-c; name=warp_gen.c; charset=ISO-8859-1

//////////////////////////////////////////////////////////
// warp_gen.c
//
//  1-2-3 pts warp generator.
// Usage: warp_gen [number-of-pts] [number-of-frames-to-generate]
//////////////////////////////////////////////////////////

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <math.h>

#define WIDTH  256
#define HEIGHT 256
uint8_t Y_Pic[HEIGHT][WIDTH];
uint8_t U_Pic[HEIGHT/2][WIDTH/2];
uint8_t V_Pic[HEIGHT/2][WIDTH/2];

uint8_t Y_Ref[HEIGHT][WIDTH];
uint8_t U_Ref[HEIGHT/2][WIDTH/2];
uint8_t V_Ref[HEIGHT/2][WIDTH/2];

typedef struct {
  int x, y;
} VECT;

int Nb_Pts;
VECT Pts[4];
VECT Po, dU, dV, dw;

#define ln_PREC 4
#define PREC  (1<<ln_PREC)        // -th pel unit

//////////////////////////////////////////////////////////

static void PGM_Out()
{
  int k;

  fprintf(stdout, "P5\n\n%d %d\n255\n", WIDTH, HEIGHT*3/2 );
  for(k=3D0; k<HEIGHT; ++k)
    fwrite(Y_Pic[k], WIDTH, 1, stdout);
  for(k=3D0; k<HEIGHT/2; ++k) {
    fwrite(U_Pic[k], WIDTH/2, 1, stdout);
    fwrite(V_Pic[k], WIDTH/2, 1, stdout);
  }
}

//////////////////////////////////////////////////////////

static void Build_Texture()
{
  int x,y;
  for(y=3D0; y<HEIGHT; ++y)
    for(x=3D0; x<WIDTH; ++x)
      Y_Ref[y][x] =3D (x^y)&0xff;
  for(y=3D0; y<HEIGHT/2; ++y)
    for(x=3D0; x<WIDTH/2; ++x) {
      U_Ref[y][x] =3D (4*(x^y)+ 25)&0xff;
      V_Ref[y][x] =3D (4*(x^y)+113)&0xff;
    }
}

static void Random_Pts(float t)
{
  static const float Amp[4] =3D { 16.530f, 16.123f,   38.641f, 6.245f };
  static const float Phi[4] =3D {  0.500f,  1.100f,    2.000f, 0.427f };
  static const float Omg[4] =3D {  1.5f,    1.230f,    0.650f, 0.427f };
  static const VECT  Po[4] =3D { {-10,-10}, {10,-10}, {-10, 10}, { 10,10 } =
};
  int i;
  for(i=3D0; i<4; ++i) {
    float x, y;
    x =3D Amp[i]*cos(Omg[i]*t + Phi[i]) + Po[i].x;
    y =3D Amp[i]*sin(Omg[i]*t + Phi[i]) + Po[i].y;
    Pts[i].x =3D (int)( x*PREC );
    Pts[i].y =3D (int)( y*PREC );
//    fprintf( stderr, "#%d (%d,%d)\n", i, Pts[i].x, Pts[i].y );
  }
}

//////////////////////////////////////////////////////////

#define FIX 8

static void Invert_Matrix()
{
  const int SCALEX =3D WIDTH << FIX;
  const int SCALEY =3D HEIGHT << FIX;

    // convert to vectors in PREC-th pel unit
  Pts[1].x =3D Pts[1].x +  PREC*WIDTH;
  Pts[1].y =3D Pts[1].y +           0;
  Pts[2].x =3D Pts[2].x +           0;
  Pts[2].y =3D Pts[2].y + PREC*HEIGHT;
  Pts[3].x =3D Pts[3].x + Pts[2].x + Pts[1].x;
  Pts[3].y =3D Pts[3].y + Pts[2].y + Pts[1].y;

  Po.x =3D Pts[0].x;
  Po.y =3D Pts[0].y;
  switch(Nb_Pts) {
    case 1:
      dU.x =3D PREC*(1<<FIX); dU.y =3D 0;
      dV.x =3D 0;             dV.y =3D PREC*(1<<FIX);
    break;
    case 2:
    {
      int Norm =3D (Pts[1].x*Pts[1].x + Pts[1].y*Pts[1].y) / (PREC*PREC);
      if (Norm=3D=3D0) Norm =3D 1;  // ahem...
      dU.x =3D (Pts[1].x*SCALEX)/Norm;  dU.y =3D (Pts[1].y*SCALEY)/Norm;
      dV.x =3D-(Pts[1].y*SCALEX)/Norm;  dV.y =3D (Pts[1].x*SCALEY)/Norm;
    }
    break;
    case 3:
    {
      int Det =3D (Pts[1].x*Pts[2].y - Pts[2].x*Pts[1].y) / (PREC*PREC);
      if (Det=3D=3D0) Det =3D 1;  // ahem...
      dU.x =3D (Pts[2].y*SCALEX)/Det;  dU.y =3D-(Pts[2].x*SCALEY)/Det;
      dV.x =3D-(Pts[1].y*SCALEX)/Det;  dV.y =3D (Pts[1].x*SCALEY)/Det;
    }
    break;
    case 4:
      dU.x =3D 0; dU.y =3D 0;
      dV.x =3D 0; dV.y =3D 0;
    break;
  }
}

static void Warp()
{
  int x, y;
  int uo, vo, u, v;

  if (Nb_Pts<4)
  {
    uo =3D -(dU.x*Po.x + dU.y*Po.y) >> ln_PREC;
    vo =3D -(dV.x*Po.x + dV.y*Po.y) >> ln_PREC;
    for(y=3D0; y<HEIGHT; ++y) {
      u =3D uo; v =3D vo;
      uo +=3D dU.y; vo +=3D dV.y;
      for(x=3D0; x<WIDTH; ++x) {
        int xx =3D u >> (ln_PREC+FIX);
        int yy =3D v >> (ln_PREC+FIX);
        if (xx<0) xx =3D 0;
        else if (xx>=3DWIDTH) xx =3D WIDTH-1;
        if (yy<0) yy =3D 0;
        else if (yy>=3DHEIGHT) yy =3D HEIGHT-1;
        Y_Pic[y][x] =3D Y_Ref[yy][xx];
        u +=3D dU.x;
        v +=3D dV.x;
      }
    }
    uo =3D -(Po.x/2*dU.x + Po.y/2*dU.y) >> ln_PREC;
    vo =3D -(Po.x/2*dV.x + Po.y/2*dV.y) >> ln_PREC;
    for(y=3D0; y<HEIGHT/2; ++y) {
      u =3D uo; v =3D vo;
      uo +=3D dU.y; vo +=3D dV.y;
      for(x=3D0; x<WIDTH/2; ++x) {
        int xx =3D u >> (ln_PREC+FIX);
        int yy =3D v >> (ln_PREC+FIX);
        if (xx<0) xx =3D 0;
        else if (xx>=3DWIDTH/2) xx =3D WIDTH/2-1;
        if (yy<0) yy =3D 0;
        else if (yy>=3DHEIGHT/2) yy =3D HEIGHT/2-1;
        U_Pic[y][x] =3D U_Ref[yy][xx];
        V_Pic[y][x] =3D V_Ref[yy][xx];
        u +=3D dU.x;
        v +=3D dV.x;
      }
    }
  }
}

//////////////////////////////////////////////////////////

int main(int argc, char *argv[])
{
  int Nb_Frames =3D 100;
  float t =3D 0.;
  Nb_Pts =3D 3;

  if (argc>1) Nb_Pts =3D atoi(argv[1]);
  if (argc>2) Nb_Frames =3D atoi(argv[2]);
 =20
  Build_Texture();
  if (Nb_Pts>4) Nb_Pts =3D 4;
  else if (Nb_Pts<1) Nb_Pts =3D 1;

  while(Nb_Frames-->0)
  {
    Random_Pts(t);
    Invert_Matrix();
    Warp();
    PGM_Out();
    t +=3D .05f;
  }
  return 0;
}

//////////////////////////////////////////////////////////

--=-gPI24JGsYtLaB38BKprD--