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