/** * */ #include #include #include #include "dct.h" #include "qcif.h" #include "quantizer.h" /****************************************************************************/ /* Pi */ #define PI 3.14159265 /****************************************************************************/ #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE 1 #endif /****************************************************************************/ /* cosine coefficient values */ #define C1 (cos (PI / 16)) #define C2 (cos ((2 * PI) / 16)) #define C3 (cos ((3 * PI) / 16)) #define C4 (cos ((4 * PI) / 16)) #define C5 (cos ((5 * PI) / 16)) #define C6 (cos ((6 * PI) / 16)) #define C7 (cos ((7 * PI) / 16)) /* DCT addition nodes, form of N */ #define N11 (f[0] + f[7]) #define N12 (f[1] + f[6]) #define N13 (f[2] + f[5]) #define N14 (f[3] + f[4]) #define N15 (f[3] - f[4]) #define N16 (f[2] - f[5]) #define N17 (f[1] - f[6]) #define N18 (f[0] - f[7]) #define N21 (N11 + N14) #define N22 (N12 + N13) #define N23 (N12 - N13) #define N24 (N11 - N14) #define N25 (N15) #define N26 ((N17 - N16) * C4) #define N27 ((N17 + N16) * C4) #define N28 (N18) #define N31 ((N21 + N22) * C4) #define N32 ((N21 - N22) * C4) #define N33 (N23 * C6 + N24 * C2) #define N34 (N24 * C6 - N23 * C2) #define N35 (N25 + N26) #define N36 (N25 - N26) #define N37 (N28 - N27) #define N38 (N28 + N27) /* IDCT addition nodes, form of IN */ #define IN31 (F[0]) #define IN32 (F[4]) #define IN33 (F[2]) #define IN34 (F[6]) #define IN35 (F[1] * C7 - F[7] * C1) #define IN36 (F[5] * C3 - F[3] * C5) #define IN37 (F[5] * C5 + F[3] * C3) #define IN38 (F[1] * C1 + F[7] * C7) #define IN21 ((IN31 + IN32) * C4) #define IN22 ((IN31 - IN32) * C4) #define IN23 (IN33 * C6 - IN34 * C2) #define IN24 (IN34 * C6 + IN33 * C2) #define IN25 (IN35 + IN36) #define IN26 (IN35 - IN36) #define IN27 (IN38 - IN37) #define IN28 (IN38 + IN37) #define IN11 (IN21 + IN24) #define IN12 (IN22 + IN23) #define IN13 (IN22 - IN23) #define IN14 (IN21 - IN24) #define IN15 (IN25) #define IN16 ((IN27 - IN26) * C4) #define IN17 ((IN27 + IN26) * C4) #define IN18 (IN28) /****************************************************************************/ /* 1-D DCT across a row or column, horizontal should be TRUE or FALSE */ void compute_1d_dct (DctBlock *block, int horizontal, int row_col) { double f[8]; double F2[8]; int i; for (i = 0; i < 8; i++) { if (horizontal) f[i] = block->f[row_col][i]; else f[i] = block->f[i][row_col]; } /* calculate transforms using common addition nodes */ F2[0] = N31; F2[4] = N32; F2[2] = N33; F2[6] = N34; F2[1] = N35 * C7 + N38 * C1; F2[5] = N36 * C3 + N37 * C5; F2[3] = N37 * C3 - N36 * C5; F2[7] = N38 * C7 - N35 * C1; for (i = 0; i < 8; i++) { if (horizontal) block->f[row_col][i] = F2[i] / 2.0; else block->f[i][row_col] = F2[i] / 2.0; } } /* 1-D IDCT across a row or column, horizontal should be TRUE or FALSE */ void compute_1d_idct (DctBlock *block, int horizontal, int row_col) { double f[8]; double F[8]; int i; for (i = 0; i < 8; i++) { if (horizontal) F[i] = block->f[row_col][i] * 2.0; else F[i] = block->f[i][row_col] * 2.0; } /* calculate transforms using common addition nodes */ f[0] = IN11 + IN18; f[1] = IN12 + IN17; f[2] = IN13 + IN16; f[3] = IN14 + IN15; f[4] = IN14 - IN15; f[5] = IN13 - IN16; f[6] = IN12 - IN17; f[7] = IN11 - IN18; /* note that when converting back, we scale by a factor of 2/N = 2/8 */ for (i = 0; i < 8; i++) { if (horizontal) block->f[row_col][i] = f[i] / 4.0; else block->f[i][row_col] = f[i] / 4.0; } } /****************************************************************************/ void dct_block_free (DctBlock *block) { free (block); } DctBlock *dct_block_init () { DctBlock *block = (DctBlock *)malloc (sizeof (DctBlock)); int i, j; for (i = 0; i < 8; i++) { for (j = 0; j < 8; j++) block->f[i][j] = 0.0; } return block; } DctBlock *dct_block_new_char (char *row0, char *row1, char *row2, char *row3, char *row4, char *row5, char *row6, char *row7, int offset) { char *crow[8]; double drow[8][8]; int i, j; /* for looping convenience */ crow[0] = row0; crow[1] = row1; crow[2] = row2; crow[3] = row3; crow[4] = row4; crow[5] = row5; crow[6] = row6; crow[7] = row7; for (i = 0; i < 8; i++) { for (j = 0; j < 8; j++) drow[i][j] = (double)crow[i][j]; } return dct_block_new_double (drow[0], drow[1], drow[2], drow[3], drow[4], drow[5], drow[6], drow[7], offset); } DctBlock *dct_block_new_double (double *row0, double *row1, double *row2, double *row3, double *row4, double *row5, double *row6, double *row7, int offset) { DctBlock *block = dct_block_init (); double *drow[8]; int i, j; /* for looping convenience */ drow[0] = row0; drow[1] = row1; drow[2] = row2; drow[3] = row3; drow[4] = row4; drow[5] = row5; drow[6] = row6; drow[7] = row7; for (i = 0; i < 8; i++) { for (j = 0; j < 8; j++) block->f[i][j] = drow[i][j + offset]; } return block; } void dct_block_print (DctBlock *block) { int i; printf ("DCT Block:\n"); for (i = 0; i < 8; i++) printf ("[ %6.1f %6.1f %6.1f %6.1f %6.1f %6.1f %6.1f %6.1f ]\n", block->f[i][0], block->f[i][1], block->f[i][2], block->f[i][3], block->f[i][4], block->f[i][5], block->f[i][6], block->f[i][7]); } void dct_block_quantize (DctBlock *block) { int i, j; for (i = 0; i < 8; i++) { for (j = 0; j < 8; j++) block->f[i][j] = quantize (block->f[i][j]); } } /****************************************************************************/ DctFrame *dct_frame_init () { return (DctFrame *)malloc (sizeof (DctFrame)); } DctFrame *dct_frame_new (double **components) { } /****************************************************************************/ void compute_dct (DctBlock *block) { int i; /* computer 1-D horizontal DCTs */ for (i = 0; i < 8; i++) compute_1d_dct (block, TRUE, i); /* computer 1-D vertical DCTs */ for (i = 0; i < 8; i++) compute_1d_dct (block, FALSE, i); } void compute_idct (DctBlock *block) { int i; /* compute 1-D vertical IDCTs */ for (i = 0; i < 8; i++) compute_1d_idct (block, FALSE, i); /* compute 1-D horizontal IDCTs */ for (i = 0; i < 8; i++) compute_1d_idct (block, TRUE, i); } /****************************************************************************/