Here is the code:
void dct(const tga_image *tga, double data[8][8],
const int xpos, const int ypos)
{
int i,j;
double in[8], out[8], rows[8][8];
/* transform rows */
for (j=0; j<8; j++)
{
for (i=0; i<8; i++)
in[i] = (double) pixel(tga, xpos+i, ypos+j);
dct_1d(in, out, 8);
for (i=0; i<8; i++) rows[j][i] = out[i];
}
/* transform columns */
for (j=0; j<8; j++)
{
for (i=0; i<8; i++)
in[i] = rows[i][j];
dct_1d(in, out, 8);
for (i=0; i<8; i++) data[i][j] = out[i];
}
}
It is taken from listing2.c found at https://unix4lyfe.org/dct/
I have just 1 question, we fill in rows as rows[j][i] but then read it out rows[i][j]. As per the 2D DCT formula we transpose the DCT matrix and not the actual data. Why is the actual data being transposed?
If I assume xpos
as horizontal index and ypos
as vertical index, then the following is true.
The function dct_1d(*,*,*);
works on only 1-d arrays (here in
and out
). What you are getting carried away by is due to the indexing
jugglery for 2d arrays in C here (in particular rows
here).
By a simple swap of variables i
and j
in the first for
block, the same code can be rewritten as follows which will make physical sense as you are trying (see the comments):
void dct(const tga_image *tga, double data[8][8],
const int xpos, const int ypos)
{
int i,j; /* as in matrix[i][j] */
double in[8], out[8], rows[8][8];
/* transform rows (each is running horizontally with j) */
for (i=0; i<8; i++)
{
for (j=0; j<8; j++)
in[j] = (double) pixel(tga, xpos+j, ypos+i); /* fill current row i */
/* Note above xpos in an image is horizontal as j is in a matrix[i][j] in c and
vice versa. (The fallacy that you will make is the following: You will think that
xpos corresponds to i and ypos corresponds to j, which is incorrect.) */
dct_1d(in, out, 8); /* transform current row i */
for (j=0; j<8; j++) rows[i][j] = out[j]; /* copy back current row i */
}
/* transform columns (each is running vertically with i) */
for (j=0; j<8; j++)
{
for (i=0; i<8; i++)
in[i] = rows[i][j]; /* fill current column j */
dct_1d(in, out, 8); /* transform current column j */
for (i=0; i<8; i++) data[i][j] = out[i]; /* copy back current column j */
}
}