JPEG压缩编解码程序%%使用matlab2013b软件进行仿真测试。测试图片在文档最后方。functionjpegCompress%以离散余弦变换(DCT)为基础,对灰度图像进行有损压缩及重建jpeg算法%该算法过程主要包括以下几个部分:1.读取图像;2.DCT变换;3.量化;4.Z形扫描;5.huffman编码;%6.huffman解码;7.反Z形扫描;8.反量化;9.反DCT变换;10.输出图像;11.计算压缩性能。clearall;%设定量化因子quality。%quality为量化因子,默认值为1。决定了截去的系数和压缩比,增加quality的值,可增大压缩比,使压缩编码后的图像占用存储空间更小。quality=input('请输入量化参数(数值型,默认为1)=');ifisempty(quality)quality=1;endifquality=0error('请输入大于0的数字!');end%1.获取图像ticI=imread('coin128.tif');%I=imread('cameraman128.tif');%I=imread('cameraman256.tif');%I=imread('finger256.bmp');%I=imread('fingerprint256.bmp');%I=imread('lena512.bmp');%读入读一幅灰度图像disp('读取图像时间:');toc%2.DCT变换ticOriginalImage=double(I);%图像数据类型转换[am,an]=size(OriginalImage);%得到图像的大小ImageSub=OriginalImage-128;%为实现DCT变换,每个像素值都减去128,即像素层次移动-128fun1=@dct2;TCM=blkproc(ImageSub,[8,8],fun1);%使用dct2函数进行二维DCT变换,得到变换系数矩阵TCMdisp('DCT变换时间:');toc%3.量化ticQ=[1611101624405161121214192658605514131624405769561417222951878062182237566810910377243555648110111392496478871031211201017292959811210010399]*quality;%亮度量化表TCM_Q=blkproc(TCM,[8,8],'round(x./P1)',Q);%对图像进行量化,得到量化后的TCM,即TCM_Q。disp('量化时间:');toc%4.Z形扫描ticTCM_Q_col=im2col(TCM_Q,[8,8],'distinct');%将每个8*8数据块的量化系数排成列向量,得到64*数据块总数大小的矩阵TCM_Q_col。Num_col=size(TCM_Q_col,2);%得到TCM_Q_col的列数,即数据块的个数Num_col。order=[192310172518...11451219263341...34272013671421...2835424957504336...292215816233037...4451585952453831...2432394653606154...4740485562635664];TCM_Q_colZ=TCM_Q_col(order,:);%用z型扫描方式对变换系数重新排列disp('Z形扫描时间:');toc%5.编码tic%5.1直流编码,dc为直流系数表,dcdpcm为直流差值编码表dc=zeros(Num_col,1);dcdpcm=zeros(Num_col,1);forj=1:Num_coldc(j)=TCM_Q_colZ(1,j);%将DC系数排列到一个矢量中enddcdpcm(1)=dc(1);forj=2:Num_coldcdpcm(j)=dc(j)-dc(j-1);%求DC系数的DPCM编码enddcdmax=max(dcdpcm);%最大直流dcdmin=min(dcdpcm);%最小直流dch=histc(dcdpcm,[dcdmin:dcdmax]);%统计各个值的直方图dcnum=length(dcdpcm);dcp=dch/dcnum;%计算各个值的概率dcsymbols=[dcdmin:dcdmax];%直流分量值[dcdict,dcavglen]=huffmandict(dcsymbols,dcp);%生成字典dcdict,计算平均码长dcencoded=huffmanenco(dcdpcm,dcdict);%对DC系数的DPCM进行Huffman编码,得到直流编码dcencoded%5.2交流编码%将非零AC元素重新排列放到ac中,每一列均以eob作为结束,共有count个非零元素eob=max(ImageSub(:))+1;%创建一个块结束符号num=numel(TCM_Q_colZ)+size(TCM_Q_col,2);ac=zeros(num,1);count=0;forj=1:Num_coli=max(find(TCM_Q_colZ(:,j)));%find函数为寻找yy函数中非零元素的位置,max函数为取里面的最大值,若无非零元素或者为空,返回emptyifisempty(i)i=1;endp=count+1;q=p+i-1;ifi==1ac(q)=eob;endac(p:q)=[TCM_Q_colZ(2:i,j);eob];count=q;endac((count+1):end)=[];%删除ac中的无用元素acmax=max(ac);%最大交流acmin=min(ac);%最小交流ach=histc(ac,[acmin:acmax]);%统计各个值的直方图acnum=length(ac);acp=ach/acnum;%计算各个值的概率acsymbols=[acmin:acmax];%交流分量值[acdict,acavglen]=huffmandict(acsymbols,acp);%生成字典dcdict,计算平均码长acencoded=huffmanenco(ac,acdict);%对AC系数进行Huffman编码,得到交流编码acencodeddisp('编码时间:');toc%6.解码tic%6.1直流解码dcdecoded=huffmandeco(dcencoded,dcdict);%直流Huffman解码%根据直流解码恢复直流分量,并放入TCM_Q_colZ_Rec的第一行TCM_Q_colZ_Rec(1,1)=dcdecoded(1);fori=2:Num_colTCM_Q_colZ_Rec(1,i)=TCM_Q_colZ_Rec(1,i-1)+dcdecoded(i);%计算第i列直流分量,并将直流分量放入TCM_Q_colZ_Rec的第i列第1行。end%6.2交流解码acdecoded=huffmandeco(acencoded,acdict);%交流Huffman解码%根据交流解码恢复交流分量,放入TCM_Q_colZ_Rec的第2-64行j=1;%j用来记录第几列k=2;%k用来记录第几行maxk=1;count=0;%count用来记录连续不等于eob的个数,当count=63时,下一个eob仅作为结束符,不解码。fori=1:size(acdecoded)ifacdecoded(i)==eobTCM_Q_colZ_Rec(k:64,j)=0;j=j+1;k=2;elseTCM_Q_colZ_Rec(k,j)=acdecoded(i);k=k+1;endenddisp('解码时间:');toc%7.反Z型扫描ticorder2=[1341011212236...2591220233537...68131924343849...714182533394850...1517263240475158...1627314146525759...2830424553566063...2943445455616264];TCM_Q_col_Rec=TCM_Q_colZ_Rec(order2,:);%用反z型扫描方式对变换系数重新排列TCM_Q_Rec=col2im(TCM_Q_col_Rec,[8,8],[am,an],'distinct');%将TCM_Q_col_Rec的每个列向量排成8*8数据块,将矩阵变为图像size。disp('反Z形扫描时间:');toc%8.反量化ticTCM_Rec=blkproc(TCM_Q_Rec,[8,8],'round(x.*P1)',Q);%对矩阵TCM_Q_Rec进行反量化。disp('反量化时间:');toc%9.反DCT变换ticfun2=@idct2;ImageSub_Rec=blkproc(TCM_Rec,[8,8],fun2);%使用idct2函数进行二维反DCT变换,得到ImageSub_RecReconImage=double(ImageSub_Rec)+128;disp('反DCT变换时间:');toc%10.输出图像ticsubplot(1,2,1);imagesc(I);colormap(gray);title('原始图像');subplot(1,2,2);imagesc(ReconImage);colormap(gray);title('重建图像');disp('输出图像时间:');toc%11.计算压缩性能encoded_lenght=numel(dcencoded)+numel(acencoded);%编码长度AverageBit=encoded_lenght/am/an;%计算编码比特率(每个像素所占的比特数)CompressionRatio=am*an*8/encoded_lenght;%计算压缩倍数(原图大小与压缩后的比值)e=double(I)-double(ReconImage);MSE=sqrt(sum(e(:).^2)/(an*am));%均方误差:指参数估计值与参数真值之差平方的期望值,记为MSEPSNR=10*log(255*255/MSE)/log(10);%计算峰值信噪比(dB)%输出编码比特率、压缩比、峰值信噪比。disp('编码比特率:');disp(AverageBit);disp('压缩比:');disp(CompressionRatio);disp('峰值信噪比(dB)');disp(PSNR);end测试图片:coin128.tifcameraman128.tifCameraman256.tiflena512.bmp