| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 6609 人关注过本帖, 1 人收藏
标题:JPEG 编解码中的 dct 变换
只看楼主 加入收藏
chopin_bin
Rank: 1
等 级:新手上路
帖 子:2
专家分:0
注 册:2010-8-31
收藏
得分:0 
建议你参看一下x264的8点二维DCT变换算法,基本上都是加法和位移就能得到结果了
2010-08-31 14:21
RockCarry
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:13
帖 子:662
专家分:58
注 册:2005-8-5
收藏
得分:0 
我的是采用的 AN&N 的 DCT 算法,并且将浮点运算转换为了定点运算,用到的也就是加法和移位。如果不考虑采用使用处理器专门提供的 SIMD 指令(例如 SSE),这应该是 C 语言所能写出的比较快的算法了。其实这个也不是我的功劳,我也是参考了 libjpeg 才写出来的。x264 里面的代码我没看过,但是就从算法来讲应该都是差不多的,只是在具体优化上的不同了,比如结合特定的处理器架构,采用专门的汇编指令进行优化。
2010-09-24 12:58
BlueGuy
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:29
帖 子:4476
专家分:4055
注 册:2009-4-18
收藏
得分:0 
先收藏了, 以后可能会用的上。

我就是真命天子,顺我者生,逆我者死!
2010-09-24 16:06
TOL2318tol
Rank: 1
等 级:新手上路
帖 子:1
专家分:0
注 册:2011-5-9
收藏
得分:0 
顶斑竹
2011-05-09 14:44
我是菜鸟哦
Rank: 6Rank: 6
等 级:贵宾
威 望:22
帖 子:921
专家分:209
注 册:2007-5-4
收藏
得分:0 
我现在初步学习BMP转换JPG,转换的图像不对。。。不知道为什么。。。。

偶是菜鸟鸟偶惧WHO?!!!!
2011-07-05 17:13
我是菜鸟哦
Rank: 6Rank: 6
等 级:贵宾
威 望:22
帖 子:921
专家分:209
注 册:2007-5-4
收藏
得分:0 
这是我的转换代码。。。。请斑竹指点下。。。
long B2J()
{
  if(type==24)
  {
    JPG a;
    long i,j,c,k;
    long m,n,tp;
    long u,v,x,y;//用于二维DCT变换
    float cv,cu,pi;
    unsigned char count;
    double sum[6]={0};
    unsigned char R,G,B;
    signed char *Y,*U,*V;
    signed char MCU[6][64]={0};
    signed char Q_DCT[6][64]={0};
    float DCT[6][64]={0};
    short sgn;
    signed char Z[64]={0};
    signed char transt[317]={0};
    signed char PreDC[3]={0};
    //int location=0,run=0;
    unsigned char run=0;
    int  r_tp=0;
    long r_len=0;


    bit *buff;
    //unsigned char y,u,v;

    unsigned char ZigZag[64]={0,1,5,6,14,15,27,28,
                         2,4,7,13,16,26,29,42,
                         3,8,12,17,25,30,41,43,
                         9,11,18,24,31,40,44,53,
                         10,19,23,32,39,45,52,54,
                         20,22,33,38,46,51,55,60,
                         21,34,37,47,50,56,59,61,
                         35,36,48,49,57,58,62,63
                        };

    pi=(float)11.25;
    c=h;
    k=w;
    while(c%16!=0) c++;
    while(k%16!=0) k++;

    Y=new signed char[c*k];//获取BMP主要图像信息
    U=new signed char[c*k];
    V=new signed char[c*k];
    memset(Y,0,c*k);
    memset(U,0,c*k);
    memset(V,0,c*k);

    p_temp=new unsigned char[c*k*3>>1];//4:1:1比例最大为一半,记录最后的编码
    memset(p_temp,0,c*k*3>>1);

    buff=new bit[c*k*12];
    for(i=0;i<c*k*12;i++)
        buff[i].a =1;
    //YUV
    for(i=0;i<h;i++)
    {
        for(j=0;j<w;j++)
        {
            R=p_data[i*wf+3*j+2];//Y
            G=p_data[i*wf+3*j+1];//U
            B=p_data[i*wf+3*j];//V
            Y[i*w+j]=0.2990*R+0.5870*G+0.1140*B;
            U[i*w+j]=-0.1687*R-0.3313*G+0.5000*B;
            V[i*w+j]=0.5000*R-0.4187*G-0.0813*B;   
        }
    }
    //4:1:1 sample
    for(i=0;i<c>>4;i++)
        for(j=0;j<k>>4;j++)
        {
            for(n=i*8;n<i*8+8;n++)
                for(m=j*8;m<j*8+8;m++)
                {
                    tp=(n-i*8)*8+(m-j*8);
                    MCU[0][tp]=Y[n*k+m]-128;
                    MCU[1][tp]=Y[n*k+m+8]-128;
                    MCU[2][tp]=Y[(n+8)*k+m]-128;
                    MCU[3][tp]=Y[(n+8)*k+m+8]-128;
                    MCU[4][tp]=U[2*n*k+2*m];
                    MCU[5][tp]=V[2*n*k+2*m];
                }

            /*   
                printf("************************MCU\n*****************");
                for(count=0;count<6;count++)
                {
                    printf("MCU编号%d\n",count);
                    for(y=0;y<64;y++)
                        {
                            if(1) printf("%d ",MCU[count][y]);
                            if((y+1)%8==0) printf("\n");

                    }

                }
                            getch();
                            printf("\n");
            */
          //DCT
                for(v=0;v<8;v++)
                {
                    if(v==0) cv=1/sqrt(2);
                    else     cv=1;

                    for(u=0;u<8;u++)
                    {
                        if(u==0)    cu=1/sqrt(2);
                        else    cu=1;

                        for(count=0;count<6;count++)
                            sum[count]=0;

                        for(y=0;y<8;y++)
                            for(x=0;x<8;x++)
                            {
                                for(count=0;count<6;count++)
                                    sum[count]=sum[count]+MCU[count][y*8+x]*cos((2*x+1)*u*pi)*cos((2*y+1)*v*pi);
                                    
                            }

                            for(count=0;count<6;count++)
                            {
                                DCT[count][v*8+u]=sum[count]*cu*cv/4;
                            }                                
                    }
                }



            //Q
                for(count=0;count<6;count++)
                {
                    for(y=0;y<64;y++)
                        {
                            if(DCT[count][y]>0) sgn=1; else sgn=-1;
                            if(count<4)    Q_DCT[count][y]=(DCT[count][y]+sgn*a.dqt0.QT[y]/2)/a.dqt0.QT[y];
                            if(count>3)    Q_DCT[count][y]=(DCT[count][y]+sgn*a.dqt1.QT[y]/2)/a.dqt1.QT[y];
                            //if(1) printf("%d ",Q_DCT[count][y]);
                            //if((y+1)%8==0) printf("\n");
                            //getch();
                            //printf("\n");
                        }
                    //printf("************\n");
                }
                //ZigZag
                for(count=0;count<6;count++)
                {


                    for(y=0;y<64;y++)
                    {
                        Z[ZigZag[y]]=Q_DCT[count][y];
                    }
                    //Z字编码显示
                    /*
                    printf("原Q块\n");
                    for(y=0;y<64;y++)
                    {
                        printf("%5d",Q_DCT[count][y]);
                        if((y+1)%8==0) printf("\n");
                    }
                    printf("编码块\n");
                    for(y=0;y<64;y++)
                    {
                        printf("%5d",Z[y]);
                        if((y+1)%8==0) printf("\n");
                    }
                    getch();*/
                    memcpy(Q_DCT[count],Z,64);
                }

            //HuffmanEncoder
            for(count=0;count<6;count++)
            {
                run=0;//记录一个8*8像素块的过渡段行程
                //过渡DC
                if(count<4)
                {
                    transt[run+1]=Q_DCT[count][0]-PreDC[0];
                    x=0;
                    while(abs(transt[run+1])>>x!=0) x++;
                    transt[run]=x;
                    PreDC[0]=Q_DCT[count][0];//记录当前DC为下一次差分做准备
                }
                if(count==4)
                {
                    transt[run+1]=Q_DCT[count][0]-PreDC[1];
                    x=0;
                    while(abs(transt[run+1])>>x!=0) x++;
                    transt[run]=x;
                    PreDC[1]=Q_DCT[count][0];//记录当前DC为下一次差分做准备               
                }
                if(count==5)
                {
                    transt[run+1]=Q_DCT[count][0]-PreDC[2];
                    x=0;
                    while(abs(transt[run+1])>>x!=0) x++;
                    transt[run]=x;
                    PreDC[2]=Q_DCT[count][0];//记录当前DC为下一次差分做准备               
                }
                run=run+2;
               
                x=0;
                //过渡AC
                for(y=1;y<64;y++)
                {
                    if(Q_DCT[count][y]==0)
                    {
                        x++;
                        if(x>15)//x=16
                        {
                            r_tp=y+1;
                            while(Q_DCT[count][r_tp]==0 && r_tp<64)    r_tp++;
                            if(r_tp==64)
                            {
                                transt[run]=transt[run+1]=0;//00标记结尾
                                run=run+2;
                                y=64;
                                goto transt_end;//标记结束编码
                            }
                            else
                            {
                                transt[run]=15;
                                transt[run+1]=0;
                                transt[run+2]=0;
                                run=run+3;
                                x=0;//重新计0
                            }
                           
                        }
                    }
                    else
                    {
                        transt[run]=x;//记录0个数
                        x=0;
                        while(abs(Q_DCT[count][y])>>x!=0) x++;
                        transt[run+1]=x;//记录区间
                        transt[run+2]=Q_DCT[count][y];
                        x=0;//记录下一个行程
                        run=run+3;
                    }               

                }
                    if(Q_DCT[count][63]==0)
                    {
                        transt[run]=transt[run+1]=0;//00标记结尾
                        run=run+2;
                    }
transt_end:;
                /*
                //过渡块显示输出
                for(y=0;y<64;y++)
                {
                            if(1) printf("%d ",Q_DCT[count][y]);
                            if((y+1)%8==0) printf("\n");                    
                }
                            if(count<4) printf("亮度块");
                            if(count==4)   printf("色度块");
                            if(count==5)   printf("深度块");
                            printf("****************************\n");

                for(y=0;y<run;y++)
                if(1) printf("%d ",transt[y]);
                printf("\n对应中间编码,共%d个\n",run);
                getch();
               
                */
               
                //过渡段编码
                //p_temp,buff,transt,x,y,r_tp,r_len

                unsigned char b_cmp=0;
                unsigned short *DCtable,*ACtable;
                unsigned char *DCL;//,*ACL;
               
                //unsigned char *DCtable,*ACtable;
                if(count<4)
                {
                    DCtable=a.DCTY.C ;
                    DCL=a.DCTY.L;
                    ACtable=a.ACTY.C ;
                    //ACL=a.dhtac0.sum;
                }
                else
                {
                    DCtable=a.DCTC.C ;
                    DCL=a.DCTC.L;
                    ACtable=a.ACTC.C ;
                    //ACL=a.dhtac0.sum;
                }
                //DC
                //r_len=0;
                x=DCL[transt[0]];
                while(x!=0)
                {
                    x--;
                    buff[r_len++].a=DCtable[transt[0]]>>x;
                }
               
                x=transt[0];
                if(transt[1]<0)  b_cmp=((unsigned char)0x01 <<x)-1-abs(transt[1]);
                else b_cmp=transt[1];
                while(x!=0)
                {
                    x--;
                    buff[r_len++].a=b_cmp>>x;
                }

                //AC
                for(y=2;y<run-2;y=y+3)
                {
                    x=0;
                    r_tp=transt[y]*16+transt[y+1];//RRRRSSSS
                    

                    if(r_tp==1 || (r_tp==0 && count>3) ||(r_tp==2 && count<4)) x=2;
                    else
                    while(ACtable[r_tp]>>x!=0) x++;
                    
                    //x=ACL[r_tp];

                    while(x!=0)
                    {
                        x--;
                        buff[r_len++].a=ACtable[r_tp]>>x;
                    }   
                    
                    x=transt[y+1];
                    if(transt[y+2]<0)  b_cmp=((unsigned char)0x01 <<x)-1-abs(transt[y+2]);
                    else b_cmp=transt[y+2];
                    while(x!=0)
                    {
                        x--;
                        buff[r_len++].a=b_cmp>>x;
                    }
                }
                //结尾
                    x=0;
                    r_tp=0;//RRRRSSSS
                    

                    if(count>3)
                        x=2;
                    else
                        x=4;

                    while(x!=0)
                    {
                        x--;
                        buff[r_len++].a=ACtable[r_tp]>>x;
                    }

            }               
        }
        
        //开始转换字节
        r_tp=0;
        while(r_len%8==0)
        {
            r_len++;
            r_tp=1;
        }
        y=0;
        for(x=0;x<r_len;x=x+8)
        {
            p_temp[y]=((unsigned char)buff[x].a<<7)+((unsigned char)buff[x+1].a<<6)+((unsigned char)buff[x+2].a<<5)+((unsigned char)buff[x+3].a<<4)+((unsigned char)buff[x+4].a<<3)+((unsigned char)buff[x+5].a<<2)+((unsigned char)buff[x+6].a<<1)+(unsigned char)buff[x+7].a;
            
            if(p_temp[y]==0xFF)
            {
                p_temp[y+1]=0x00;
                y=y+2;
            }
            else
                y=y+1;
        }
        if(r_tp==1) //如果有位填充需要补FF
        {
            p_temp[y++]=0xFF;
            p_temp[y++]=0x00;
        }
            printf("\n转换长度%ld",y);
    //delete []p_temp;p_temp=0;//由于不是正常处理图像,所以需要清空指针
    delete []buff;
    return y;
    //exit(0);
  }
  else
          return -1;
}


偶是菜鸟鸟偶惧WHO?!!!!
2011-07-05 17:16
lucy1289
Rank: 1
等 级:新手上路
帖 子:5
专家分:0
注 册:2012-6-5
收藏
得分:0 
楼主你好,我是一个初学者,在高图像压缩,现在代码有问题,可以和你交流一下吗?
2012-06-05 10:57
快速回复:JPEG 编解码中的 dct 变换
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.018815 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved