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

时间:2017-04-09 17:27:04

标签: c dct

以下是代码:

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

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

的listing2.c

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

1 个答案:

答案 0 :(得分:1)

如果我假设xpos为水平索引而ypos为垂直索引,则以下情况属实。

函数dct_1d(*,*,*);仅适用于 1-d数组(此处为inout)。您所带走的是由于 C 2d数组indexing jugglery(在此处特别是rows)。

通过在第一个i块中简单地交换变量jfor,可以按照以下方式重写相同的代码,这将使您在尝试时具有物理意义(请参阅注释):

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