#include "stdafx.h"
#include "DCT.h"
#include <stdio.h>
#include <math.h>
#define PI 3.1415926
#define SAFE_DELETE(p) \
if (p) \
{ \
delete []p; \
p = NULL; \
}
void swap(double &a,double &b)
{
double temp;
temp = a;
a = b;
b = temp;
}
CDCT::CDCT()
{
m_pCos_Temp = NULL;
m_pdata_2D_Temp = NULL;
}
CDCT::~CDCT()
{
SAFE_DELETE(m_pCos_Temp);
SAFE_DELETE(m_pdata_2D_Temp);
}
int CDCT::FDCT_1D(double *pdata, int bitlen)
{
int hr = 0;
if (pdata == NULL || bitlen <= 0)
{
return 1;
}
int Len = 1<<bitlen;
double Coef = sqrt(2.0/Len);
FDCT_1D_No_Param(pdata, bitlen);
for (int i = 0; i < Len; ++i)
{
pdata[i] = Coef * pdata[i];
}
return hr;
}
int CDCT::FDCT_2D(double *pdata, int bitrow, int bitcol)
{
int hr = 0;
if (pdata == NULL || bitrow <= 0 || bitcol <= 0)
{
return 1;
}
int row = 1 << bitrow;
int col = 1 << bitcol;
double coef = 2.0f / sqrt( (double)(row*col) );
Initial_2D_Param(row, col);
for (int i_row = 0; i_row < row; ++i_row)
{
FDCT_1D_No_Param( pdata + i_row*col, bitcol);
}
for (int i_col = 0; i_col < col; ++i_col)
{
for (int i_row = 0; i_row < row; ++i_row)
{
m_pdata_2D_Temp[ i_row ] = pdata[ i_row*col + i_col ];
}
FDCT_1D_No_Param(m_pdata_2D_Temp, bitrow);
for (int i_row = 0; i_row < row; ++i_row)
{
pdata[ i_row*col + i_col ] = m_pdata_2D_Temp[i_row] * coef;
}
}
return hr;
}
int CDCT::Initial_1D_Param(int len)
{
int hr = 0;
return hr;
}
int CDCT::Initial_2D_Param(int row, int col)
{
int hr = 0;
if (row <= 0 || col <= 0)
{
return 1;
}
SAFE_DELETE(m_pdata_2D_Temp);
m_pdata_2D_Temp = new double[row];
if (m_pdata_2D_Temp == NULL)
{
hr = 1;
}
return hr;
}
int CDCT::FDCT_1D_No_Param(double *pdata, int bitlen)
{
int hr = 0;
if (pdata == NULL || bitlen <= 0)
{
return 1;
}
Initial_DCT_Param(bitlen);
DCTForward(pdata, bitlen);
DCTBackward(pdata, bitlen);
FBitReverse(pdata, bitlen);
pdata[0] = 1 / sqrt(2.0) * pdata[0];
return hr;
}
int CDCT::Initial_DCT_Param(int bitlen)
{
int hr = 0;
if (bitlen <= 0)
{
return 1;
}
int Len = 1 << bitlen;
SAFE_DELETE(m_pCos_Temp);
m_pCos_Temp = new double[Len];
for (int i = 0; i < Len>>1; ++i)
{
m_pCos_Temp[Len-i-1] = (double)(2*i + 1);
}
int EndStart = 0;
int Factor = 0;
for (int i = 0; i < bitlen - 1; ++i)
{
EndStart = 1 << (bitlen - 1 - i);
Factor = 1 << (i + 1);
for (int j = 0; j < EndStart>>1; ++j )
{
m_pCos_Temp[EndStart-j-1] = Factor * m_pCos_Temp[Len-j-1];
}
}
for (int i = 0; i < Len; ++i)
{
m_pCos_Temp[i] = 2.0 * cos(m_pCos_Temp[i] * PI / (Len<<1) );
}
return hr;
}
int CDCT::DCTForward(double *pdata, int bitlen)
{
int hr = 0;
if (pdata == NULL || bitlen <= 0)
{
return 1;
}
int Len = 1<<bitlen;
double Temp1 = 0.0;
double Temp2 = 0.0;
int Wings, HalfWing, WingLen;
for (int i_bitlen = 0; i_bitlen < bitlen; ++i_bitlen)
{
Wings = 1<<i_bitlen;
WingLen = Len>>i_bitlen;
HalfWing = WingLen>>1;
for (int i_Wing = 0; i_Wing < Wings; ++i_Wing)
{
for (int i_HalfWing = 0; i_HalfWing < HalfWing; ++i_HalfWing)
{
Temp1 = pdata[ i_Wing * WingLen + i_HalfWing ];
Temp2 = pdata[ (i_Wing+1) * WingLen - 1 - i_HalfWing];
if (i_Wing%2)
{
swap(Temp1, Temp2);
}
pdata[ i_Wing*WingLen + i_HalfWing ] = Temp1 + Temp2;
pdata[ (i_Wing+1) * WingLen - 1 - i_HalfWing ] = (Temp1 - Temp2) * m_pCos_Temp[WingLen-1-i_HalfWing];
}
}
}
return hr;
}
int CDCT::DCTBackward(double *pdata, int bitlen)
{
int hr = 0;
if (pdata == NULL || bitlen <= 0)
{
return 1;
}
int Len = 1<<bitlen;
int Wings, HalfWing, WingLen, Temp1, Temp2;
for (int i_bitlen = bitlen-1; i_bitlen >= 0; --i_bitlen)
{
Wings = 1<<i_bitlen;
WingLen = 1<<(bitlen-i_bitlen);
HalfWing = WingLen>>1;
for (int i_Wing = 0; i_Wing < Wings; ++i_Wing)
{
for (int i_HalfWing = 0; i_HalfWing < HalfWing; ++i_HalfWing)
{
if (i_HalfWing == 0)
{
pdata[HalfWing + i_Wing*WingLen] *= 0.5;
}
else
{
Temp1 = BitReverse(i_HalfWing, bitlen-i_bitlen-1);
Temp2 = BitReverse(i_HalfWing-1, bitlen-i_bitlen-1);
pdata[HalfWing + i_Wing*WingLen + Temp1] -= pdata[HalfWing + i_Wing*WingLen + Temp2];
}
}
}
}
return hr;
}
int CDCT::FIDCT_1D(double *pdata, int bitlen)
{
int hr = 0;
if (pdata == NULL || bitlen <= 0)
{
return 1;
}
int Len = 1<<bitlen;
double Coef = sqrt((double)Len/2.0);
for (int i = 0; i < Len; ++i)
{
pdata[i] = Coef * pdata[i];
}
FIDCT_1D_No_Param(pdata, bitlen);
return hr;
}
int CDCT::FIDCT_2D(double *pdata, int bitrow, int bitcol)
{
int hr = 0;
if (pdata == NULL || bitrow <= 0 || bitcol <= 0)
{
return 1;
}
int row = 1 << bitrow;
int col = 1 << bitcol;
double coef = sqrt((double)(row*col)) / 2.0;
Initial_2D_Param(row, col);
for (int i_row = 0; i_row < row; ++i_row)
{
FIDCT_1D_No_Param( pdata + i_row*col, bitcol);
}
for (int i_col = 0; i_col < col; ++i_col)
{
for (int i_row = 0; i_row < row; ++i_row)
{
m_pdata_2D_Temp[ i_row ] = pdata[ i_row*col + i_col ];
}
FIDCT_1D_No_Param(m_pdata_2D_Temp, bitrow);
for (int i_row = 0; i_row < row; ++i_row)
{
pdata[ i_row*col + i_col ] = m_pdata_2D_Temp[i_row] * coef;
}
}
return hr;
}
int CDCT::FIDCT_1D_No_Param(double *pdata, int bitlen)
{
int hr = 0;
if (pdata == NULL || bitlen <= 0)
{
return 1;
}
Initial_IDCT_Param(bitlen);
pdata[0] = sqrt(2.0) * pdata[0];
FBitReverse(pdata, bitlen);
IDCTForward(pdata, bitlen);
IDCTBackward(pdata, bitlen);
return hr;
}
int CDCT::Initial_IDCT_Param(int bitlen)
{
int hr = 0;
if (bitlen <= 0)
{
return 1;
}
int Len = 1 << bitlen;
SAFE_DELETE(m_pCos_Temp);
m_pCos_Temp = new double[Len];
for (int i = 0; i < Len>>1; ++i)
{
m_pCos_Temp[Len-i-1] = (double)(2*i + 1);
}
int EndStart = 0;
int Factor = 0;
for (int i = 0; i < bitlen - 1; ++i)
{
EndStart = 1 << (bitlen - 1 - i);
Factor = 1 << (i + 1);
for (int j = 0; j < EndStart>>1; ++j )
{
m_pCos_Temp[EndStart-j-1] = Factor * m_pCos_Temp[Len-j-1];
}
}
for (int i = 0; i < Len; ++i)
{
m_pCos_Temp[i] = 1.0 / (2.0 * cos(m_pCos_Temp[i] * PI / (Len<<1) ));
}
return hr;
}
int CDCT::IDCTBackward(double *pdata, int bitlen)
{
int hr = 0;
if (pdata == NULL || bitlen <= 0)
{
return 1;
}
int Len = 1<<bitlen;
double Temp1 = 0.0;
double Temp2 = 0.0;
int Wings, HalfWing, WingLen;
for (int i_bitlen = bitlen-1; i_bitlen >= 0; --i_bitlen)
{
Wings = 1<<i_bitlen;
WingLen = Len>>i_bitlen;
HalfWing = WingLen>>1;
for (int i_Wing = 0; i_Wing < Wings; ++i_Wing)
{
for (int i_HalfWing = 0; i_HalfWing < HalfWing; ++i_HalfWing)
{
Temp1 = pdata[ i_Wing * WingLen + i_HalfWing ];
Temp2 = pdata[ (i_Wing+1) * WingLen - 1 - i_HalfWing] * m_pCos_Temp[WingLen-1-i_HalfWing];
if (i_Wing%2)
{
pdata[ i_Wing*WingLen + i_HalfWing ] = (Temp1 - Temp2) * 0.5;
pdata[ (i_Wing+1) * WingLen - 1 - i_HalfWing ] = (Temp1 + Temp2) * 0.5;
}
else
{
pdata[ i_Wing*WingLen + i_HalfWing ] = (Temp1 + Temp2) * 0.5;
pdata[ (i_Wing+1) * WingLen - 1 - i_HalfWing ] = (Temp1 - Temp2) * 0.5;
}
}
}
}
return hr;
}
int CDCT::IDCTForward(double *pdata, int bitlen)
{
int hr = 0;
if (pdata == NULL || bitlen <= 0)
{
return 1;
}
int Len = 1<<bitlen;
int Wings, HalfWing, WingLen, Temp1, Temp2;
for (int i_bitlen = 0; i_bitlen <bitlen; ++i_bitlen)
{
Wings = 1<<i_bitlen;
WingLen = 1<<(bitlen-i_bitlen);
HalfWing = WingLen>>1;
fo