我的jpeg解码的代码

[复制链接]
2374|0
 楼主| 四叶草 发表于 2007-12-12 20:12 | 显示全部楼层 |阅读模式
我的代码结果不正确,我想实现的就是在只有一个Y向量的情况下解压出图片出来,因为这样比较简单。虽然我基本上都测试了一下各个函数,都是正如我所期望的结果,但结果还是不正确,未知错误原因,希望高手赐教。<br />//前面查文件头的部分比较简单,我也已经验证过了,所以这里不多说<br />find(addDC0,Y[0],&num);//num先为0,经过此步读取DC的值之后为1<br />while(num!=64)&nbsp;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&nbsp;char&nbsp;b=0;b&lt63;b++)&nbsp;Y[0][b&gt&gt3][b%8]+=128;//据说需要把所<br />//有的都加上128<br />//如此计算一共四个矩阵,即把上面的Y[0],分别变成Y[1]等,得出16*16的图片然后display()出来,display代码如下:<br />unsigned&nbsp;char&nbsp;num,x,y,b=0;<br />for(num=0;num&lt4;num++)for(y=0;y&lt8;y++)<br />or(x=0;x&lt8;x++)//<br />pDC-&gtSetPixelV(500+x+((num%2)&lt&lt3),250+y+((num/2)&lt&lt3),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&nbsp;addr,&nbsp;unsigned&nbsp;char&nbsp;matr[][8],unsigned&nbsp;char*&nbsp;mnum)<br />{int&nbsp;bnum=1,qnum=1,c,con=1;<br />&nbsp;long&nbsp;lv=0,da;<br />&nbsp;bool&nbsp;fin=1,fst=1;<br />&nbsp;//deb=buf;<br />&nbsp;fseek(fp,addr,SEEK_SET);<br />&nbsp;while(bnum&lt=16&&fin)<br />&nbsp;{da=buf&gt&gt(16-bnum);<br />&nbsp;c=fgetc(fp);//c为读入的对应位数的码字数,bnum表示现在的位数<br />&nbsp;if(!c)&nbsp;{bnum++;continue;}//0则继续,con保证多个c=0后lv的位数仍无误<br />&nbsp;if(c&&(!fst))////lv!=0<br />&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(lv==~(0xffff&lt&ltbnum))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{lv++;&nbsp;lv=lv&lt&lt(bnum-con);}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lv++;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v=lv&lt&lt(bnum-con+1);}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;qnum++;<br />&nbsp;if(lv==da)<br />{//找到了<br />buf=shift(bnum,buf);//break;找到的话fin应该等于0,使能fin=0;<br />//////////读取权值<br />unsigned&nbsp;char&nbsp;Q=GetW(addr,qnum);////之后把它低4位读出数据&nbsp;&nbsp;&nbsp;&nbsp;<br />mat(Q,matr,mnum);//形成矩阵<br />buf=shift(Q&0x0f,buf);//该函数把buffer移一定的位,有必要则读入文件的下一个数,在此为减少篇幅,略,我也验证过是正确的,<br />fin=0;//结束循环<br />continue;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;for(--c;c;c--)<br />&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;lv++;<br />&nbsp;&nbsp;&nbsp;&nbsp;qnum++;<br />&nbsp;&nbsp;&nbsp;&nbsp;if(lv==da)<br />&nbsp;&nbsp;&nbsp;&nbsp;{//找到了<br />&nbsp;&nbsp;&nbsp;&nbsp;buf=shift(bnum,buf);//break;找到的话fin应该等于0,使能fin=0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//////////读取权值<br />&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;char&nbsp;Q=GetW(addr,qnum);////之后把它低4位读出数据<br />&nbsp;&nbsp;&nbsp;&nbsp;mat(Q,matr,mnum);<br />&nbsp;&nbsp;&nbsp;&nbsp;buf=shift(Q&0x0f,buf);<br />&nbsp;&nbsp;&nbsp;&nbsp;fin=0;<br />&nbsp;&nbsp;&nbsp;&nbsp;break;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;con=++bnum;<br />&nbsp;}////<br />&nbsp;if(fst&&c)<br />&nbsp;&nbsp;&nbsp;&nbsp;{fst=0;<br />&nbsp;&nbsp;&nbsp;&nbsp;if(lv==da)<br />&nbsp;&nbsp;&nbsp;&nbsp;{//找到了<br />&nbsp;&nbsp;&nbsp;&nbsp;buf=shift(bnum,buf);//break;找到的话fin应该等于0,使能fin=0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//////////读取权值<br />&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;char&nbsp;Q=GetW(addr,qnum);////之后把它低4位读出数据<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;mat(Q,matr,mnum);<br />&nbsp;&nbsp;&nbsp;&nbsp;buf=shift(Q&0x0f,buf);<br />&nbsp;&nbsp;&nbsp;&nbsp;fin=0;<br />&nbsp;&nbsp;&nbsp;&nbsp;continue;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;for(--c;c;c--)<br />&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;lv++;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;qnum++;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(lv==da)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{//找到了<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buf=shift(bnum,buf);//break;找到的话fin应该等于0,使能fin=0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//////////读取权值<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;char&nbsp;Q=GetW(addr,qnum);////之后把它低4位读出数据<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mat(Q,matr,mnum);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buf=shift(Q&0x0f,buf);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fin=0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;//bnum等于1为测试用<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;con=++bnum;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;}<br />//停止时bnum等于17<br />}<br />quant函数分别乘以表中的数据,比较简单,我已验证过了。<br />zigzag为://把63个分量重排<br />zigzag(unsigned&nbsp;char&nbsp;o[][8],&nbsp;unsigned&nbsp;char&nbsp;r[][8])<br />{unsigned&nbsp;char&nbsp;x=0,y=0,i=0;<br />&nbsp;bool&nbsp;add=0,direct=1;<br />&nbsp;while(!(x==7&&y==7))<br />&nbsp;{r[y][x]=o[i&gt&gt3][i%8];//应该是正确的<br />&nbsp;&nbsp;i++;<br />&nbsp;&nbsp;if(y==0&&!add)<br />&nbsp;{x++;add=1;direct=0;continue;}<br />&nbsp;if(x==0&&y!=7&&!add)<br />&nbsp;{y++;add=1;direct=1;continue;}<br />&nbsp;&nbsp;if(x==7&&!add)<br />&nbsp;&nbsp;{y++;add=1;direct=0;continue;}<br />&nbsp;&nbsp;if(y==7&&!add)<br />&nbsp;&nbsp;{x++;add=1;direct=1;continue;}<br />&nbsp;if(direct)<br />&nbsp;{y--;x++;add=0;}<br />&nbsp;else<br />&nbsp;{x--;y++;add=0;}<br />&nbsp;}<br />&nbsp;r[7][7]=o[7][7];<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />}<br />:Toggle(unsigned&nbsp;char&nbsp;a[][8])<br />{unsigned&nbsp;char&nbsp;t=0;//从第一行开始隔行正负纠正<br />&nbsp;unsigned&nbsp;char&nbsp;i=1;<br />&nbsp;for(;t&lt8;t+=2)<br />&nbsp;{for(;i&lt8;i++)<br />&nbsp;{if(a[t])<br />&nbsp;&nbsp;&nbsp;&nbsp;{if((a[t]&0x80)==0x80)&nbsp;a[t]=a[t]&0x7f;<br />&nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;a[t]=a[t]|0x80;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;}<br />&nbsp;}<br />}<br />IDCT(unsigned&nbsp;char&nbsp;p[][8],unsigned&nbsp;char&nbsp;r[][8])<br />{unsigned&nbsp;int&nbsp;u,v,i,j,f1,f2;<br />float&nbsp;t=0;<br />for(i=0;i&lt8;i++)<br />&nbsp;&nbsp;&nbsp;&nbsp;for(j=0;j&lt8;j++)<br />&nbsp;&nbsp;&nbsp;&nbsp;{for(u=0;u&lt8;u++)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(v=0;v&lt8;v++)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;f1=((i&lt&lt2)+1)&gt&gt4;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f2=((j&lt&lt2)+1)&gt&gt4;<br />&nbsp;&nbsp;&nbsp;&nbsp;t+=C(u)*C(v)*p[v]*cos(f1*u*3.14)*cos(f2*v*3.14);<br />&nbsp;&nbsp;&nbsp;&nbsp;//C(u)我已经定义了非0为1/2,0时为0.7&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;r[j]=(int)t;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br />最后就是display了,display的时候把RGB都按照公式算出来,希望高手指点迷津,可以帮我也测试一下。谢谢。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

71

主题

109

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部