这个 2D DCT 代码实际上是如何工作的?

How does this 2D DCT code actually work?

代码如下:

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];
    }
}

取自listing2.c https://unix4lyfe.org/dct/

我只有 1 个问题,我们将行填写为 rows[j][i],然后读出 rows[i][j]。根据 2D DCT 公式,我们转置 DCT 矩阵而不是实际数据。为什么要转置实际数据?

如果我假设 xpos 为水平索引,ypos 为垂直索引,则以下内容为真。

函数 dct_1d(*,*,*); 仅适用于 一维数组 (此处为 inout)。您被带走的是由于 indexing 此处 C2d 数组 的杂耍(特别是 rows 这里)。

通过在第一个 for 块中简单地交换变量 ij,相同的代码可以重写如下,这在您尝试时具有物理意义(看评论):

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 */
    }
}