📄 dct.cpp
字号:
#include "dct.h"
#define PI 3.141593
//double (*Dct)[8][8];
//int N=(width/8)*(height/8);
//Dct=new double[N][8][8];
////delete []Dct;
////Dct=NULL;
blstype dctqt(ptype **P,unsigned int width, unsigned int height, btype (*&Q)[8][8], int mode, int level, bool adaptor, btype QTable[8][8]) {
//construct double dct[][][]
double (*dct)[8][8]=NULL;
blstype n=DivisionFdct(P,width,height,dct);
//if mode==3 hestigram dct->construct btype Q[][][]
Q=new btype[n][8][8];
if (3==mode) {
HistQuan(dct,Q,n,6);
for (int i=0; i<8; i++)
for (int j=0; j<8; j++)
QTable[i][j]=1;
QTable[0][0]=16;
}
else {
mode2table(mode,65,QTable);
if (adaptor) {
modifyQTable(dct,n,QTable);
}
Quantization(dct, Q, QTable, n);
}
//else { choose mode (qtable)
// if adaptor modify(qtable) according to dct[][][]
// quantify dct->construct btype Q[][][]
// send out qtable, n
// }
//send out Q
delete []dct;
return n;
}
int idctqt(btype Q[][8][8], ptype ** &P, unsigned int height, unsigned int width,
int mode, btype QTable[8][8]){
//if mode==4 ihestigram Q2[][8][8] only dc
//else iquantization with the giving qtable Q2[][][]
//idct -> **p
// if (4==mode) {
// HistIQuan(
P = new ptype *[height];
if (!P) {
printf("Allocate height error.\n");
return 1;
}
for (unsigned int j=0; j<height; j++) {
P[j]=new ptype [width];
if (!P[j]) {
printf("Allocate width error.\n");
return 1;
}
}
double va[8][8];
ptype vb[8][8];
unsigned int nrow=height/8;
unsigned int ncolumn=width/8;
blstype NM=nrow*ncolumn;
for(unsigned int i=0;i<NM;i++)
{
for(int u=0;u<8;u++)
for(int v=0;v<8;v++)
va[u][v]=Q[i][u][v]*QTable[u][v];
Idct(va,vb);
for(int u=0;u<8;u++)
for(int v=0;v<8;v++)
P[i/ncolumn*8+u][i%ncolumn*8+v]=vb[u][v]; //[(i/ncolumn*8+u)*column+i%ncolumn*8+v]
}
return 0;
}
void modifyQTable(double dct[][8][8], blstype N, btype QTable[8][8]) {
double sum_of_ac[8][8];//交流系数和
double avg_of_ac[8][8];//交流系数平均值
double max_of_acavg=0;//AC平均值中的最大值
//double Q2[8][8]={{1,1,1,1,1,1,1,1},{1,1,1,1,1,1,1,1},{1,1,1,1,1,1,1,1},{1,1,1,1,1,1,1,1},{1,1,1,1,1,1,1,1},{1,1,1,1,1,1,1,1},{1,1,1,1,1,1,1,1},{1,1,1,1,1,1,1,1}};//定义一个量化表
//double Q[8][8]={{16,11,10,16,24,40,51,61},{12,12,14,19,26,58,60,55},{4,13,16,24,40,57,69,56},{14,17,22,29,51,87,80,62},{18,22,37,56,68,109,103,77},{24,35,55,64,81,104,113,92},{49,64,78,87,103,121,120,101},{72,92,95,98,112,100,103,99}};//定义一个量化表
double modifac[8][8];//矫正系数
//double Q_modified[8][8];//修正后的量化表
for(int i=0;i<8;i++)
{
for(int j=0;j<8;j++)
{
sum_of_ac[i][j]=0;
for(blstype n=0;n<N;n++)
{
if((i+j)!=0)
{
sum_of_ac[i][j]+=abs(dct[n][i][j]);
}
else
{
sum_of_ac[i][j]=0;
}
}
avg_of_ac[i][j]=sum_of_ac[i][j]/double(N);
if (avg_of_ac[i][j]>max_of_acavg)
max_of_acavg=avg_of_ac[i][j];
}
}
for(int i=0;i<8;i++)
{
for(int j=0;j<8;j++)
{
if(avg_of_ac[i][j]!=0)
{
modifac[i][j]=avg_of_ac[i][j]*sqrt(double(i*i+j*j))/max_of_acavg;
QTable[i][j]=btype(QTable[i][j]/modifac[i][j]);
}
}
}
}
blstype DivisionFdct(ptype **a, unsigned int width, unsigned int height, double (* &Dct)[8][8])
{
unsigned int nrow,ncolumn;
btype va[8][8];
nrow=height/8;
ncolumn=width/8;
blstype NM=nrow*ncolumn;
Dct=new double[NM][8][8];
for(unsigned int i=0;i<NM;i++)
{
for(int j=0;j<8;j++)
{
for(int k=0;k<8;k++)
{
va[j][k]=a[i/ncolumn*8+j][i%ncolumn*8+k];
}
}
Fdct(va,Dct[i]);
}
return NM;
}
void AcdseeTable(btype QTable[8][8],int n)
{
int Table[8][8]={ 20, 13, 12, 20, 30, 50, 63, 76,
15, 15, 17, 23, 32, 72, 75, 68,
17, 16, 20, 30, 50, 71, 86, 70,
17, 21, 27, 36, 63,108,100, 77,
22, 27, 46, 70, 85,136,128, 96,
30, 43, 68, 80,101,130,141,115,
61, 80, 97,108,8,151,150,126,
90,115,118,122,140,125,128,123};
char Jpeg[8][8]={ 16,11,10,16,24,40,51,61,12,12,14,19,26,58,60,55,
14,13,16,24,40,57,69,56,14,17,22,29,51,87,80,62,
18,22,37,56,68,109,103,77,24,35,55,64,81,104,113,92,
49,64,78,87,103,121,120,101,72,92,95,98,112,100,103,99};
for(int i=0;i<8;i++)
{
for(int j=0;j<8;j++)
{
if((n<0)||(n>100))
QTable[i][j]=btype(Jpeg[i][j]);
else
QTable[i][j]=btype(1+(Table[i][j]-1)*n/100);
}
}
}
void mode2table(int mode, int level, btype QTable[8][8]){
switch (mode) {
case 1:
for (int i=0;i<8;i++)
for (int j=0;j<8;j++)
QTable[i][j]=level; //均匀
break;
case 2:
for (int i=0;i<8;i++)
for (int j=0;j<8;j++)
QTable[i][j]=10+8*(i+j); //变步长
break;
//case 3:
// AcdseeTable(QTable,level);
// break;
default:
AcdseeTable(QTable,101);
//for (int i=0;i<8;i++)
// for (int j=0;j<8;j++)
// QTable[i][j]=JPEGTable[i][j];//标准量化表
}
}
void Quantization(double Dct[][8][8], btype QuanTable[][8][8], btype QTable[8][8], blstype NM)
{
for(blstype i=0;i<NM;i++)
{
for(int j=0;j<8;j++)
{
for(int k=0;k<8;k++)
{
if(Dct[i][j][k]>0)
QuanTable[i][j][k]=btype(Dct[i][j][k]/QTable[j][k]+0.5);
else
QuanTable[i][j][k]=btype(Dct[i][j][k]/QTable[j][k]-0.5);
}
}
}
}
void HistQuan(double va[][8][8],btype vb[][8][8],blstype NM,int grade)
{
for(blstype i=0;i<NM;i++)
Histogram(va[i],vb[i],grade);
}
//BOOL IQuantization(btype (*QuanTable)[8][8], double (*Dct)[8][8], btype QTable[8][8], blstype NM)
//{
// for(unsigned int i=0;i<NM;i++)
// {
// for(int u=0;u<8;u++)
// for(int v=0;v<8;v++)
// Dct[i][u][v]=QuanTable[i][u][v]*QTable[u][v];
// }
// return true;
//}
//
//BOOL IdctCombination(double (*Dct)[8][8], ptype **a, unsigned int width, unsigned int height)
//{
// unsigned int nrow=height/8;
// unsigned int ncolumn=width/8;
// blstype NM=nrow*ncolumn;
//
// for(unsigned int i=0;i<NM;i++)
// {
// ptype vb[8][8];
// Idct(Dct[i],vb);
// for(int u=0;u<8;u++)
// for(int v=0;v<8;v++)
// a[i/ncolumn*8+u][i%ncolumn*8+v]=vb[u][v];
// }
// return true;
//}
void Fdct(btype va[][8],double vb[][8])
{
double c;
double CosTable[8][8]={1.0,0.98078528040323,0.92387953251129,0.83146961230255,0.70710678118655,0.55557023301960,0.38268343236509,0.19509032201613,
1.0,0.83146961230255,0.38268343236509,-0.19509032201613,-0.70710678118655,-0.98078528040323,-0.92387953251129,-0.55557023301960,
1.0,0.55557023301960,-0.38268343236509,-0.98078528040323,-0.70710678118655,0.19509032201613,0.92387953251129,0.83146961230255,
1.0,0.19509032201613,-0.92387953251129,-0.55557023301960,0.70710678118655,0.83146961230255,-0.38268343236509,-0.98078528040323,
1.0,-0.19509032201613,-0.92387953251129,0.55557023301960,0.70710678118655,-0.83146961230255,-0.38268343236509,0.98078528040323,
1.0,-0.55557023301960,-0.38268343236509,0.98078528040323,-0.70710678118655,-0.19509032201613,0.92387953251129,-0.83146961230255,
1.0,-0.83146961230255,0.38268343236509,0.19509032201613,-0.70710678118655,0.98078528040323,-0.92387953251129,0.55557023301960,
1.0,-0.98078528040323,0.92387953251129,-0.83146961230255,0.70710678118655,-0.55557023301960,0.38268343236509,-0.19509032201613};
for(int u=0;u<8;u++)
{
for(int v=0;v<8;v++)
{
vb[u][v]=0.0;
for(int j=0;j<8;j++)
for(int k=0;k<8;k++)
vb[u][v]=vb[u][v]+va[j][k]*CosTable[j][u]*CosTable[k][v];
if((0==u)&&(0==v))
c=0.5;
else if((0==u)||(0==v))
c=1/sqrt(2.0);
else
c=1.0;
vb[u][v]=c*vb[u][v]/4.0;
}
}
}
void Idct(double va[8][8],ptype vb[][8])
{
double c,d;
double CosTable[8][8]={1.0,0.98078528040323,0.92387953251129,0.83146961230255,0.70710678118655,0.55557023301960,0.38268343236509,0.19509032201613,
1.0,0.83146961230255,0.38268343236509,-0.19509032201613,-0.70710678118655,-0.98078528040323,-0.92387953251129,-0.55557023301960,
1.0,0.55557023301960,-0.38268343236509,-0.98078528040323,-0.70710678118655,0.19509032201613,0.92387953251129,0.83146961230255,
1.0,0.19509032201613,-0.92387953251129,-0.55557023301960,0.70710678118655,0.83146961230255,-0.38268343236509,-0.98078528040323,
1.0,-0.19509032201613,-0.92387953251129,0.55557023301960,0.70710678118655,-0.83146961230255,-0.38268343236509,0.98078528040323,
1.0,-0.55557023301960,-0.38268343236509,0.98078528040323,-0.70710678118655,-0.19509032201613,0.92387953251129,-0.83146961230255,
1.0,-0.83146961230255,0.38268343236509,0.19509032201613,-0.70710678118655,0.98078528040323,-0.92387953251129,0.55557023301960,
1.0,-0.98078528040323,0.92387953251129,-0.83146961230255,0.70710678118655,-0.55557023301960,0.38268343236509,-0.19509032201613};
for(int j=0;j<8;j++)
{
for(int k=0;k<8;k++)
{
d=0.0;
for(int u=0;u<8;u++)
{
for(int v=0;v<8;v++)
{
if((0==u)&&(0==v))
c=0.5;
else if((0==u)||(0==v))
c=1/sqrt(2.0);
else
c=1.0;
d=d+c*va[u][v]*CosTable[j][u]*CosTable[k][v];
}
}
if(d<=0)
vb[j][k]=0;
else {
d=d/4+0.5;
if (d>255)
vb[j][k]=255;
else
vb[j][k]=ptype(d);
}
}
}
}
void Histogram(double va[][8],btype vb[][8],int grade)
{
int n=0;
int m=0;
double sum=0;
//grade=6;
double positive[64];
int positive1[64];
double negative[64];
int negative1[64];
for(int i=0;i<8;i++)
for(int j=0;j<8;j++)
vb[i][j]=0;
for(int i=0;i<8;i++)
{
for(int j=0;j<8;j++)
{
if(va[i][j]<0)
{
negative[m]=va[i][j];
negative1[m]=i*8+j;
m++;
sum=sum-va[i][j];
}
else
{
positive[n]=va[i][j];
positive1[n]=i*8+j;
n++;
sum=sum+va[i][j];
}
}
}
if(va[0][0]<0)
sum=sum+va[0][0];
else
sum=sum-va[0][0];
sum=sum/(grade-1.0);
for(int i=0;i<n-1;i++)
{
int taxisover=0;
for(int j=0;j<n-1-i;j++)
{
if(positive[j]>positive[j+1])
{
double tem=positive[j];
positive[j]=positive[j+1];
positive[j+1]=tem;
int tem1=positive1[j];
positive1[j]=positive1[j+1];
positive1[j+1]=tem1;
taxisover=1;
}
}
if(!taxisover)
break;
}
for(int i=0;i<m-1;i++)
{
int taxisover=0;
for(int j=0;j<m-1-i;j++)
{
if(negative[j]<negative[j+1])
{
double tem=negative[j];
negative[j]=negative[j+1];
negative[j+1]=tem;
int tem1=negative1[j];
negative1[j]=negative1[j+1];
negative1[j+1]=tem1;
taxisover=1;
}
}
if(!taxisover)
break;
}
if(positive[n-1]>(-negative[m-1]))
n--;
else
m--;
int nn=0;
int mm=0;
int position;
double sum1=0;
while(sum1<sum)
{
if(nn>=n)
{
sum1=sum1-negative[mm];
position=negative1[mm];
vb[position/8][position%8]=0;
mm++;
}
else if(mm>=m)
{
sum1=sum1+positive[nn];
position=positive1[nn];
vb[position/8][position%8]=0;
nn++;
}
else if(positive[nn]<(-negative[mm]))
{
sum1=sum1+positive[nn];
position=positive1[nn];
vb[position/8][position%8]=0;
nn++;
}
else
{
sum1=sum1-negative[mm];
position=negative1[mm];
vb[position/8][position%8]=0;
mm++;
}
if((nn>=n)&&(mm>=m))
break;
}
if(va[0][0]>0)
vb[0][0]=btype(va[0][0]/16+0.5);
else
vb[0][0]=btype(va[0][0]/16-0.5);
sum1=0;
for(int i=nn;i<n;i++)
sum1=sum1+positive[i];
sum1=sum1/sum;
int positivegrade=int(sum1+0.5);
int negativegrade=grade-2-positivegrade;
for(int k=0;k<positivegrade;k++)
{
if(nn>=n)
{
position=positive1[n-1];
vb[position/8][position%8]=btype(positive[n-1]+0.5);
break;
}
if(k==(positivegrade-1))
{
sum1=0;
for(int i=nn;i<n;i++)
sum1=sum1+positive[i];
sum1=sum1/(n-nn);
for(;nn<n;nn++)
{
position=positive1[nn];
vb[position/8][position%8]=btype(sum1+0.5);
}
break;
}
sum1=0;
int nnn=nn;
for(;nn<n;)
{
sum1=sum1+positive[nn];
nn++;
if(sum1>sum)
break;
}
btype dd=btype(sum1/(nn-nnn)+0.5);
for(int i=nnn;i<nn;i++)
{
position=positive1[i];
vb[position/8][position%8]=dd;
}
}
for(int k=0;k<negativegrade;k++)
{
if(mm>=m)
{
position=negative1[m-1];
vb[position/8][position%8]=btype(negative[m-1]-0.5);
break;
}
if(k==(negativegrade-1))
{
sum1=0;
for(int i=mm;i<m;i++)
sum1=sum1+negative[i];
sum1=sum1/(m-mm);
for(;mm<m;mm++)
{
position=negative1[mm];
vb[position/8][position%8]=btype(sum1-0.5);
}
break;
}
sum1=0;
int mmm=mm;
for(;mm<m;)
{
sum1=sum1+negative[mm];
mm++;
if((-sum1)>sum)
break;
}
btype dd=btype(sum1/(mm-mmm)-0.5);
for(int i=mmm;i<mm;i++)
{
position=negative1[i];
vb[position/8][position%8]=dd;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -