// 8x8 DCT를 수행하는 함수
void DCT(int nBlockSize, // DCT를 수행할 block의 size
int nWidth, int nHeight, // 수행할 영상의 가로,세로 크기
double* pInput, // double형 입력영상
double* pOutput){ // double형 출력영상
int row_index, col_index; // 가로,세로 index
int m, n, x, y; // Block DCT에 사용될 index 변수
double result; // 연산 결과값을 임시로 저장할 변수
double Cu, Cv; // DCT 계수값을 저장하는 변수
printf(" [%d x %d DCT START] \n",nBlockSize, nBlockSize);
for (row_index = 0; row_index < nWidth/nBlockSize; row_index++){ // 영상의 가로를 따라 연산 수행 (한번에 BlockSize만큼 건너뛰면서 이동)
for(col_index = 0; col_index < nHeight/nBlockSize; col_index++){ // 영상의 세로를 따라 연산 수행 (한번에 BlockSize만큼 건너뛰면서 이동)
for(m = 0; m < nBlockSize; m++){
for(n = 0; n < nBlockSize; n++){
result = 0.0; // 매번 연산 후 결과값 초기화
for(x = 0; x < nBlockSize; x++){
for(y = 0; y < nBlockSize; y++){
result += (double)cos((((2*(double)x+1)*(double)m*PI)/(nBlockSize*2)))
*cos((((2*(double)y+1)*(double)n*PI)/(nBlockSize*2)))*pInput[((row_index*nBlockSize)+x)+((col_index*nBlockSize)+y)*nWidth];
}
} // m, n에 따른 계수값 결정
if(m==0) Cu = 1.0/sqrt(2.0);
else Cu = 1.0;
if(n==0) Cv = 1.0/sqrt(2.0);
else Cv = 1.0;
pOutput[(row_index*nBlockSize+m)+(col_index*nBlockSize+n)*nWidth] =
result*((Cu*sqrt((double)2.0/nBlockSize)*Cv*sqrt((double)2.0/nBlockSize)));
}
}
}
}
printf(" [%d x %d DCT Complete] \n",nBlockSize, nBlockSize);
return;
}
// 양자화 행렬을 이용한 양자화 함수
void Quantization(int nBlockSize, int nWidth, int nHeight, double* pInput, double* pOutput){
double dTemp = 0.0; // 임시로 결과값을 저장할 변수 선언
printf("[Quantization Processing Start]\n");
for ( int row_index = 0; row_index < nWidth; row_index += nBlockSize){
for (int col_index = 0; col_index < nHeight; col_index += nBlockSize){ // 가로, 세로 모두 BlockSize 만큼 이동
dTemp = 0.0; // 결과를 임시로 저장할 변수 초기화
// 각 Block의 값을 양자화 배열의값으로 나누어 양자화 실행
for (int x = 0; x < nBlockSize; x++){
for (int y = 0; y < nBlockSize; y++){ // 계산 결과값을 임시 변수에 저장
dTemp = (pInput[(row_index+x)+(col_index+y)*nWidth]/Q_Matrix[x+y*nBlockSize]); // 임시 변수를 출력배열에 저장
pOutput[(row_index+x)+(col_index+y)*nWidth] = dTemp;
}
}
}
}
printf("[Quantization Complete]\n");
return;
}
// 양자화 행렬을 이용한 역양자화 함수
void InverseQuantization (int nBlockSize, int nWidth, int nHeight, double* pInput, double* pOutput){
double dTemp = 0.0; // 임시로 결과값을 저장할 변수 선언
printf("[Inverse Quantization Processing start]\n");
for(int row_index = 0; row_index < nWidth; row_index += nBlockSize){
for(int col_index = 0; col_index < nHeight; col_index += nBlockSize){ // 각 Block별로 실행
dTemp = 0.0; // 임시 결과값 초기화
for(int x = 0; x < nBlockSize; x++){
for(int y = 0; y < nBlockSize; y++ ){ // 각 Block내의 값을 해당하는 양자화 값을 곱하여 역양자화 진행
dTemp = pInput[(row_index+x)+(col_index+y)*nWidth]*Q_Matrix[x+y*nBlockSize];
pOutput[(row_index+x)+(col_index+y)*nWidth] = dTemp;
}
}
}
}
printf("[Inverse Quantization Complete]\n");
return;
}
// 8x8 Inverse DCT 수행하는 함수
void IDCT (int nBlockSize, // Block Size
int nWidth, int nHeight, // 가로,세로 크기
double* pInput, double* pOutput){
double Cu, Cv; // 계수값 선언
double result; // 결과값 선언
printf(" [ %d x %d IDCT START ]\n", nBlockSize, nBlockSize);
for (int row_index = 0; row_index < nWidth/nBlockSize; row_index++){
for(int col_index = 0; col_index < nHeight/nBlockSize; col_index++){
for(int m = 0; m < nBlockSize; m++){
for(int n = 0; n < nBlockSize; n++){
result = 0.0; // 결과값 초기화
for(int x = 0; x < nBlockSize; x++){
for(int y = 0; y < nBlockSize; y++){ // x, y에 따른 계수값 결정
if(x==0) Cu = 1.0/sqrt(2.0);
else Cu = 1.0;
if(y==0) Cv = 1.0/sqrt(2.0);
else Cv = 1.0; // Block별 결과값 계산
result += ((Cu*Cv))*cos((((2*(double)m+1)*(double)x*PI)/(nBlockSize*2.0)))*cos((((2*(double)n+1)*(double)y*PI )
/(nBlockSize*2.0)))*pInput[(row_index*nBlockSize+x)+(col_index*nBlockSize+y)*nWidth]*sqrt(2.0/nBlockSize)*sqrt(2.0/nBlockSize);
}
} // 계산된 결과를 출력 배열에 저장
pOutput[(row_index*nBlockSize+m)+(col_index*nBlockSize+n)*nWidth]=result;
}
}
}
}
printf(" [ %d x %d IDCT Complete ] \n", nBlockSize, nBlockSize);
return;
}