gusucode.com > 基于matlab的JPEG彩色图像编码解码源码程序 > 基于matlab的JPEG彩色图像编码解码源码程序/code/JPEGEncode.m
function [OneColorCode]=JPEGEncode(I,quantizationFactor,quantizationTable) I=double(I);%扩展范围 I=I-128;%电平平移128 [row,column]=size(I);%图像的大小 blockCount=row*column/64;%8*8分块数 %dct2变换:把ImageSub分成8*8像素块,分别进行dct2变换,得变换系数矩阵Coef I=blkproc(I,[8 8],'dct2(x)'); %JPEG建议量化矩阵 quantizationMatrix=quantizationFactor.*quantizationTable; I=blkproc(I,[8 8],'round(x./P1)',quantizationMatrix);%%向靠近的整数取圆整 %DC系数的DPCM编码 for i=row-7:-8:1 for j=column-7:-8:1 if j==1 if i~=1 %不是第一个DC系数 I(i,j)=I(i,j)-I(i-8,column-7); end else I(i,j)=I(i,j)-I(i,j-8); end end end %DC系数的扫描,求出它的位数 DCCounts=zeros(16,1); DCs=zeros(blockCount,2);%存储扫描的DC系数 n=0; pixel=0;%保存当前扫描的像素值 for i=1:8:row for j=1:8:column n=n+1; if I(i,j)==0 bitNumber=0; else bitNumber=floor(log2(abs(I(i,j))))+1;%求Z(k)的二进制位数 end if bitNumber>15 disp('error'); end DCs(n,:)=[bitNumber I(i,j)]; DCCounts(bitNumber+1)=DCCounts(bitNumber+1)+1; end end %DC系数的范式huffman编码 existSs=[];%保存DC系数的位数的频数不为零的 SCounts=[];%保存相应的频数 S2T=zeros(16,1);%所有可能的DC系数位数与existSs数组元素(即DC树节点)的映射关系,DC系数最高15位 n=0; sum=0; for i=1:16 if DCCounts(i)>0 n=n+1; existSs=[existSs i-1]; SCounts=[SCounts DCCounts(i)]; sum=sum+DCCounts(i); S2T(i)=n; end end DCTree=huffman(existSs,SCounts,sum); %AC系数的游长编码,并对编码单元频数统计 ACCounts=zeros(256,1); ACs{row/8,column/8}=[];%用细胞数组存储每个块的的AC游长编码 n=0; for i=1:8:row for j=1:8:column n=n+1; Z=block2zigzag(I(i:(i+7),j:(j+7))); %找到最后一个非零数的位置 lastNonzero=0; for k=64:-1:1 if Z(k)~=0 lastNonzero=k; break; end end zeroCount=0; AC=[]; %游长编码 if lastNonzero==0 || lastNonzero==1 AC=[0 0 0];%EOB ACCounts(1)=ACCounts(1)+1; else for k=2:lastNonzero if (Z(k)==0 && zeroCount<16) zeroCount=zeroCount+1; elseif (Z(k)==0 && zeroCount==16); AC=[AC;[15 0 0]];%ZRL ACCounts(15*16+1)=ACCounts(15*16+1)+1; zeroCount=1; elseif (Z(k)~=0 && zeroCount==16) bitNumber=floor(log2(abs(Z(k))))+1;%求Z(k)的二进制位数 AC=[AC;[15 0 0];[0 bitNumber Z(k)]]; ACCounts(15*16+1)=ACCounts(15*16+1)+1; ACCounts(bitNumber+1)=ACCounts(bitNumber+1)+1; zeroCount=0; else bitNumber=floor(log2(abs(Z(k))))+1;%求Z(k)的二进制位数 AC=[AC;[zeroCount bitNumber Z(k)]]; ACCounts(zeroCount*16+bitNumber+1)=ACCounts(zeroCount*16+bitNumber+1)+1; zeroCount=0; end end AC=[AC;[0 0 0]];%EOB ACCounts(1)=ACCounts(1)+1; end ACs{ceil(i/8),ceil(j/8)}=AC;%将该AC存入到细胞数组中 end end %对游长编码后的AC系数进行范式huffman编码 %找出频数大于零的游长编码单元,存入一个新的数组 existRSs=[];%保存频数不为零的游长编码单元 RSCounts=[];%保存游长编码单元的频数 RS2T=zeros(256,1);%所有256个可能的游长编码单元与existRSs数组元素(即AC树节点)的映射关系,0表示无元素与之对应,AC系数位数最高为15位 n=0; sum=0; for i=1:256 if ACCounts(i)>0 n=n+1; existRSs(n)=i-1; RSCounts(n)=ACCounts(i); sum=sum+ACCounts(i); RS2T(i)=n; end end ACTree=huffman(existRSs,RSCounts,sum); %进行编码 %对头部编码 Header=dec2bin(row,16);%图像像素的行数(2个字节) Header=[Header,dec2bin(column,16)];%图像像素的列数(2个字节) %Header=[Header,'00000000','00000000','00000000','00000000'];%预留图像文件的位数 integerPart=floor(quantizationFactor);%取出整数部分 decimalPart=floor((quantizationFactor-integerPart)*100);%取出小数点后两位 Header=[Header,dec2bin(integerPart,8),dec2bin(decimalPart,8)];%存储量化因子 %对DC系数的huffman表存储 [SSSSInOrder codeLengths codeCounts]=sortTreeCode(DCTree,(length(DCTree)+1)/2);%求出DC系数SSSS的编码的范式递增序列 %SSSS的编码(按位数划分)数量以1个字节存入到huffman表的头部 n=1; for i=1:16 %SSSS的编码位数为1~16,每种位数的编码的个数最多16个 if n<=length(codeLengths)&&codeLengths(n)==i Header=[Header,dec2bin(codeCounts(n),8)]; n=n+1; else Header=[Header,'00000000'];% end end %将每个编码代表的实际值存入huffman表 for i=1:length(SSSSInOrder) Header=[Header,dec2bin(SSSSInOrder{i}.value,8)]; end %对AC系数的huffman表存储 %首先清空用于DC系数huffman表存储的变量 codesInOrder=[]; codeLengths=[]; codeCounts=[]; [RRRRSSSSInOrder codeLengths codeCounts]=sortTreeCode(ACTree,(length(ACTree)+1)/2);%求出AC系数RRRRSSSS的编码的范式递增序列 %每种RRRRSSSS的编码(按位数划分)数量以2个字节存入到huffman表的头部 n=1; for i=1:256 %RRRRSSSS的编码位数为1~256,每种位数的编码的个数最多256个 if n<=length(codeLengths)&&codeLengths(n)==i Header=[Header,dec2bin(codeCounts(n),8)]; n=n+1; else Header=[Header,'00000000']; end end %将每个编码代表的实际值存入huffman表 for i=1:length(RRRRSSSSInOrder) Header=[Header,dec2bin(RRRRSSSSInOrder{i}.value,8)]; end %对每一块进行编码 Body='';%所有块的编码 Blocks{row/8,column/8}=[];%每个块的编码 n=0; for i=1:row/8 for j=1:column/8 n=n+1; %对DC系数进行编码 code=DCTree(S2T(DCs(n,1)+1)).code;%取出SSSS的编码 if DCs(n,2)>0 Blocks{i,j}=[Blocks{i,j},code,dec2bin(DCs(n,2))]; elseif DCs(n,2)<0 Blocks{i,j}=[Blocks{i,j},code,dec2bin(bitcmp(-DCs(n,2),DCs(n,1)),DCs(n,1))]; else %DC差值为零,不需要对DC差值(0)进行编码 Blocks{i,j}=[Blocks{i,j},code]; end %对AC系数进行编码 AC=ACs{i,j}; for k=1:length(AC(:,1)) code=ACTree(RS2T(AC(k,1)*16+AC(k,2)+1)).code;%取出RRRRSSSS的编码 if AC(k,3)>0 Blocks{i,j}=[Blocks{i,j},code,dec2bin(AC(k,3))]; elseif AC(k,3)<0 Blocks{i,j}=[Blocks{i,j},code,dec2bin(bitcmp(-AC(k,3),AC(k,2)),AC(k,2))]; else %AC(k,3)=0 编码为ZRL或者EOB,不需要对AC值进行编码 Blocks{i,j}=[Blocks{i,j},code]; end end Body=[Body,Blocks{i,j}]; end end OneColorCode=[Header,Body];%合并文件头与文件体 %FileCode(33:64)=dec2bin(length(FileCode),32);%更改文件位数 end