快速DCT运算(查表替换法)
现在的视频及通用图像压缩都无法逾越DCT运算,因为效果好。近来测试编解码发现这一部分非常慢,DCT运算是耗速大户,所以先对其改进,查阅了几乎所有的提速方案,我倾向于查表替换法,这种方法是先将耗时的运算提取出来,先期运算,需要时替换,提高了即时运算速度。
原程序:
void __fastcall CDCT::FDCT(double fOutPut[][8], BYTE bzInPut[][8])//正向离散余玄变换 { double ALPHA, BETA, tmp; int u,v,i,j; for(u = 0; u < 8; u++) { for(v = 0; v < 8; v++) { if(u == 0) ALPHA = sqrt(1.0 / 8.0); else ALPHA = sqrt(2.0 / 8.0); if(v == 0) BETA = sqrt(1.0 / 8.0); else BETA = sqrt(2.0 / 8.0); tmp = 0.0; for(i = 0; i < 8; i++) for(j = 0; j < 8; j++) { tmp += bzInPut[i][j] * cos((2 * i + 1) * u * PI / 16) * cos((2 * j + 1) * v * PI / 16); } fOutPut[u][v] = ALPHA * BETA * tmp; } } } void __fastcall CDCT::IDCT(BYTE bzOutPut[][8], int czInPut[][8])//反向离散余玄变换 { double ALPHA, BETA, tmp; int u,v,i,j; for(i = 0; i < 8; i++) { for( j = 0; j < 8; j++) { tmp = 0.0; for(u = 0; u < 8; u++) { for(v = 0; v < 8; v++) { if(u == 0) ALPHA = sqrt(1.0 / 8.0); else ALPHA = sqrt(2.0 / 8.0); if(v == 0) BETA = sqrt(1.0 / 8.0); else BETA = sqrt(2.0 / 8.0); tmp += ALPHA * BETA * czInPut[u][v] * cos((2 * i + 1) * u * PI / 16) * cos((2 * j + 1) * v * PI / 16); } } if(tmp < 0) tmp = 0; if(tmp > 255) tmp = 255; bzOutPut[i][j] = (BYTE)tmp; } } }
提速后的:
__fastcall CDCT::CDCT(void)//初始参数 { int u,v,i,j; C0 = sqrt(1.0 / 8.0); C1 = sqrt(2.0 / 8.0); for(u = 0; u < 8; u++) { for(v = 0; v < 8; v++) { for(i = 0; i < 8; i++) for(j = 0; j < 8; j++) { C2[u][i] = cos((2 * i + 1) * u * PI / 16.0); C3[v][j] = cos((2 * j + 1) * v * PI / 16.0); } } } } void __fastcall CDCT::FDCT(double fOutPut[][8], BYTE bzInPut[][8])//正向离散余玄变换 { double ALPHA, BETA, tmp; int u,v,i,j; for(u = 0; u < 8; u++) { for(v = 0; v < 8; v++) { if(u == 0) ALPHA = C0; else ALPHA = C1; if(v == 0) BETA = C0; else BETA = C1; tmp = 0.0; for(i = 0; i < 8; i++) for(j = 0; j < 8; j++) { tmp += bzInPut[i][j] * C2[u][i] * C3[v][j]; } fOutPut[u][v] = ALPHA * BETA * tmp; } } } void __fastcall CDCT::IDCT(BYTE bzOutPut[][8], int czInPut[][8])//反向离散余玄变换 { double ALPHA, BETA, tmp; int u,v,i,j; for(i = 0; i < 8; i++) { for( j = 0; j < 8; j++) { tmp = 0.0; for(u = 0; u < 8; u++) { for(v = 0; v < 8; v++) { if(u == 0) ALPHA = C0; else ALPHA = C1; if(v == 0) BETA = C0; else BETA = C1; tmp += ALPHA * BETA * czInPut[u][v] * C2[u][i] * C3[v][j]; } } if(tmp < 0) tmp = 0; if(tmp > 255) tmp = 255; bzOutPut[i][j] = (BYTE)tmp; } } }
因为做的是一个类,所以在类建立时,初始化了参数,增加了查表替换变量。
double C0,C1,C2[8][8],C3[8][8];
在不改原基础上,进行替换,明显感觉提速,原来压缩一幅图像需要抽袋烟的时间,感觉很漫长,现在几秒,已经有改进啦。别家的瞬间打开,我家的要几秒,这要看视频几秒一帧也太搞笑了,不循规蹈矩将自主就要付出代价。后续还要提速,不然无法实用。