我的代码结果不正确,我想实现的就是在只有一个Y向量的情况下解压出图片出来,因为这样比较简单。虽然我基本上都测试了一下各个函数,都是正如我所期望的结果,但结果还是不正确,未知错误原因,希望高手赐教。<br />//前面查文件头的部分比较简单,我也已经验证过了,所以这里不多说<br />find(addDC0,Y[0],&num);//num先为0,经过此步读取DC的值之后为1<br />while(num!=64) find(addAC0,Y[0],&num);//当读取完63的AC之后跳出,详<br />///细的介绍在后面<br />quant(Y[0],0);<br />zigzag(Y[0],B);//zigzag编码<br />Toggle(Y[0]);//隔行正负矫正<br />IDCT(B,Y[0]);//反离散余弦变换<br />for(unsigned char b=0;b<63;b++) Y[0][b>>3][b%8]+=128;//据说需要把所<br />//有的都加上128<br />//如此计算一共四个矩阵,即把上面的Y[0],分别变成Y[1]等,得出16*16的图片然后display()出来,display代码如下:<br />unsigned char num,x,y,b=0;<br />for(num=0;num<4;num++)for(y=0;y<8;y++)<br />or(x=0;x<8;x++)//<br />pDC->SetPixelV(500+x+((num%2)<<3),250+y+((num/2)<<3),RGB(Y[num][y][x]+1.4*(128-128),Y[num][y][x]-0.34*(128-128)-0.71*(128-128),Y[num][y][x]+1.77*(128-128)));//其中由于只有一个分量所以在公式中的Cb、Cr都用128代替了,以上便绘了一个16*16的图片出来,可惜不正确<br /><br />find函数的作用是找出对应的权值并建立矩阵。先把buffer(buffer里面为jpg数据段里的内容)里面高位的每次加一位地取出,即第一次取最高位,第二次取最高位和次高位,放入da变量中,lv储存的是编码最后的值,如果da==lv即找到了编码,读出权值为第几个(qnum),在对应表的地址+16+第几个权值即为对应的权值,不对则qnum++,以表示到下一个权值了,lv也对应地做处理,具体代码如下<br />find(int addr, unsigned char matr[][8],unsigned char* mnum)<br />{int bnum=1,qnum=1,c,con=1;<br /> long lv=0,da;<br /> bool fin=1,fst=1;<br /> //deb=buf;<br /> fseek(fp,addr,SEEK_SET);<br /> while(bnum<=16&&fin)<br /> {da=buf>>(16-bnum);<br /> c=fgetc(fp);//c为读入的对应位数的码字数,bnum表示现在的位数<br /> if(!c) {bnum++;continue;}//0则继续,con保证多个c=0后lv的位数仍无误<br /> if(c&&(!fst))////lv!=0<br /> {<br /> if(lv==~(0xffff<<bnum))<br /> {lv++; lv=lv<<(bnum-con);}<br /> else<br /> {<br /> lv++;<br /> v=lv<<(bnum-con+1);}<br /> qnum++;<br /> if(lv==da)<br />{//找到了<br />buf=shift(bnum,buf);//break;找到的话fin应该等于0,使能fin=0;<br />//////////读取权值<br />unsigned char Q=GetW(addr,qnum);////之后把它低4位读出数据 <br />mat(Q,matr,mnum);//形成矩阵<br />buf=shift(Q&0x0f,buf);//该函数把buffer移一定的位,有必要则读入文件的下一个数,在此为减少篇幅,略,我也验证过是正确的,<br />fin=0;//结束循环<br />continue;<br /> }<br /> for(--c;c;c--)<br /> { lv++;<br /> qnum++;<br /> if(lv==da)<br /> {//找到了<br /> buf=shift(bnum,buf);//break;找到的话fin应该等于0,使能fin=0;<br /> //////////读取权值<br /> unsigned char Q=GetW(addr,qnum);////之后把它低4位读出数据<br /> mat(Q,matr,mnum);<br /> buf=shift(Q&0x0f,buf);<br /> fin=0;<br /> break;<br /> }<br /> }<br /> con=++bnum;<br /> }////<br /> if(fst&&c)<br /> {fst=0;<br /> if(lv==da)<br /> {//找到了<br /> buf=shift(bnum,buf);//break;找到的话fin应该等于0,使能fin=0;<br /> //////////读取权值<br /> unsigned char Q=GetW(addr,qnum);////之后把它低4位读出数据<br /> <br /> mat(Q,matr,mnum);<br /> buf=shift(Q&0x0f,buf);<br /> fin=0;<br /> continue;<br /> }<br /> for(--c;c;c--)<br /> { lv++;<br /> qnum++;<br /> if(lv==da)<br /> {//找到了<br /> buf=shift(bnum,buf);//break;找到的话fin应该等于0,使能fin=0;<br /> //////////读取权值<br /> unsigned char Q=GetW(addr,qnum);////之后把它低4位读出数据<br /> mat(Q,matr,mnum);<br /> buf=shift(Q&0x0f,buf);<br /> fin=0;<br /> break;//bnum等于1为测试用<br /> }<br /> }<br /> con=++bnum;<br /> }<br /> }<br />//停止时bnum等于17<br />}<br />quant函数分别乘以表中的数据,比较简单,我已验证过了。<br />zigzag为://把63个分量重排<br />zigzag(unsigned char o[][8], unsigned char r[][8])<br />{unsigned char x=0,y=0,i=0;<br /> bool add=0,direct=1;<br /> while(!(x==7&&y==7))<br /> {r[y][x]=o[i>>3][i%8];//应该是正确的<br /> i++;<br /> if(y==0&&!add)<br /> {x++;add=1;direct=0;continue;}<br /> if(x==0&&y!=7&&!add)<br /> {y++;add=1;direct=1;continue;}<br /> if(x==7&&!add)<br /> {y++;add=1;direct=0;continue;}<br /> if(y==7&&!add)<br /> {x++;add=1;direct=1;continue;}<br /> if(direct)<br /> {y--;x++;add=0;}<br /> else<br /> {x--;y++;add=0;}<br /> }<br /> r[7][7]=o[7][7];<br /> <br />}<br />:Toggle(unsigned char a[][8])<br />{unsigned char t=0;//从第一行开始隔行正负纠正<br /> unsigned char i=1;<br /> for(;t<8;t+=2)<br /> {for(;i<8;i++)<br /> {if(a[t])<br /> {if((a[t]&0x80)==0x80) a[t]=a[t]&0x7f;<br /> else a[t]=a[t]|0x80;<br /> }<br /> }<br /> }<br />}<br />IDCT(unsigned char p[][8],unsigned char r[][8])<br />{unsigned int u,v,i,j,f1,f2;<br />float t=0;<br />for(i=0;i<8;i++)<br /> for(j=0;j<8;j++)<br /> {for(u=0;u<8;u++)<br /> for(v=0;v<8;v++)<br /> { f1=((i<<2)+1)>>4;<br /> f2=((j<<2)+1)>>4;<br /> t+=C(u)*C(v)*p[v]*cos(f1*u*3.14)*cos(f2*v*3.14);<br /> //C(u)我已经定义了非0为1/2,0时为0.7 }<br /> r[j]=(int)t;<br /> }<br />}<br />最后就是display了,display的时候把RGB都按照公式算出来,希望高手指点迷津,可以帮我也测试一下。谢谢。 |
|