PDA

View Full Version : I'm sure I'm making a stupid mistake...


SirDavidGuy
24th July 2002, 03:24
...but this DCT algorithm doesn't produce correct results. I'm doing it according to the version found here. (http://www.stanford.edu/~udara/SOCO/lossy/jpeg/Image15.jpg)

Note: This code currently sets all input values to 1, and prints the output to a file called "DCT.txt".

Yes, I do know that the code is very messy and unoptimized... so shoot me.

This was originally posted to the DivX.com forums, where a suggestion to go to XviD's forums was posted, but the XviD forum is apparently down right now. I knew there were some programmers here, so here I am...

Since part of the code is: "[i.]", I'll have to post it as an attachment (So it has to get approved)...

What am I doing wrong?

Uploaded the source here. (http://sirdavidguy.tripod.com/index2.html)

Nic
24th July 2002, 09:18
LoL....Me & Everwicked had a very similar discussion not too long ago. try PM'ing EW on his board, he knows the pitfalls from reading that algorithm quite well :)

-Nic

ps
Use some reference code to aid you (if you dont have any already):


#define DCTSIZE (8)
typedef short DCTELEM;

/* The cosine lookup tables for idct_reference and fdct_reference */
/* coslu[a][b] = C(b)/2 * cos[(2a+1)b*pi/16] */
double coslu[8][8];
float cosluf[8][8];
double res[8][8];

/* Routine to initialise the reference-DCT cosine lookup table */
void ref_dct_init(void)
{
int a,b;
double tmp;

for(a=0;a<8;a++)
{
for(b=0;b<8;b++)
{
tmp = cos((double)((a+a+1)*b) * (3.14159265358979323846 / 16.0));

if(b==0)
tmp /= sqrt(2.0);

coslu[a][b] = tmp * 0.5;
cosluf[a][b] = tmp * 0.5;
}
}
}


void fdct_reference (short *block)
{
int x,y,u,v;
double tmp, tmp2;

for (v=0; v<8; v++)
{
for (u=0; u<8; u++)
{
tmp = 0.0;
for (y=0; y<8; y++)
{
tmp2 = 0.0;
for (x=0; x<8; x++)
{
tmp2 += (double) block[(y*DCTSIZE) + x] * coslu[x][u];
}
tmp += coslu[y][v] * tmp2;
}
res[v][u] = tmp;
}
}

// Do the rounding (from double -> DCTELEM (short) )
for (v=0; v<8; v++)
{
for (u=0; u<8; u++)
{
tmp = res[v][u];
if (tmp < 0.0)
{
x = - ((int) (0.5 - tmp));
}
else
{
x = (int) (tmp + 0.5);
}
block[(v*DCTSIZE)+u] = (DCTELEM) x;
}
}
}


void idct_reference (short *block)
{
int x,y,u,v;
double tmp, tmp2;

for (y=0; y<8; y++)
{
for (x=0; x<8; x++)
{
tmp = 0.0;
for (v=0; v<8; v++)
{
tmp2 = 0.0;
for (u=0; u<8; u++)
{
tmp2 += (double) block[(v*DCTSIZE)+u] * coslu[x][u];
}
tmp += coslu[y][v] * tmp2;
}
res[y][x] = tmp;
}
}

// Do the rounding (from double -> DCTELEM (short) )
for (v=0; v<8; v++)
{
for (u=0; u<8; u++)
{
tmp = res[v][u];
if (tmp < 0.0)
{
x = - ((int) (0.5 - tmp));
}
else
{
x = (int) (tmp + 0.5);
}
block[(v*DCTSIZE)+u] = (DCTELEM) x;
}
}
}

void printblock(short *block)
{
for ( int i = 0; i != 8; i++ )
{
for ( int j = 0; j != 8; j++ )
{
printf("%03d ", block[(i*8)+j]);
}
printf("\n");
}
printf("\n");
}

SirDavidGuy
24th July 2002, 14:16
Will PM everwicked.

Thanks for the example code, btw.