%huffencode函数对输入矩阵vector进行Huffman编码,返回编码后的数据及相关信息
function [zipped,info]=huffencode(vector)
if ~isa(vector,'uint8')%确定输入矩阵是uint8格式
error('input argument must be a uint8 vector');
end
[m,n]=size(vector);%求输入矩阵的行列数
vector=vector(:)';%将矩阵按列转换成一列后转至,成为一个行向量(其中存放灰度值)
f=frequency(vector);%计算各符号出现的概率
symbols=find(f~=0);%返回概率矩阵中非零元素的位置向量,作为符号向量
f=f(symbols);%非零概率位置上的概率值组成非零概率行向量
[f,sortindex]=sort(f);%将符号按照出现的概率从小到大排序,并保留非零概率向量位置索引
fs=f;
symbols=symbols(sortindex);%读出原位置向量中的值(即概率向量中的位置),得到按概率排序后的符号向量
len=length(symbols);%读取位置向量的长度
symbols_index=num2cell(1:len);%生成从1开始以1递增,1行len列的细胞型矩阵
codeword_tmp=cell(len,1);%创建一个len行1列的细胞型变量用于存放码字
while length(f)>1 %生成Huffman树,得到二进制码字编码表
index1=symbols_index{1};
index2=symbols_index{2};
codeword_tmp(index1)=addnode(codeword_tmp(index1),uint8(0));%添加节点且该分支按0标记
codeword_tmp(index2)=addnode(codeword_tmp(index2),uint8(1));%添加节点且该分支按1标记
f=[sum(f(1:2)) f(3:end)];%求出两个最小概率之和,列出其他概率,组成一个新的行向量
symbols_index=[{[index1,index2]} symbols_index(3:end)];%合并已编码的符号索引
[f,sortindex]=sort(f);%将新的概率向量按照概率从小到大排序
symbols_index=symbols_index(sortindex);%得到新的索引表
end
codeword=cell(256,1);
codeword(symbols)=codeword_tmp;%各符号二进制码字按原符号位存入细胞型矩阵
len=0;
for i=1:length(symbols)%得到各符号码长矩阵
wordlen(i)=length(codeword_tmp{i});
end
avawordlen=fs*wordlen';%计算平均码长
Hlog=log2(fs)';
H=-(fs*Hlog);%计算信息熵
for index=1:length(vector) %得到整个图像各点灰度值转化为二进制码字后的总比特数
len=len+length(codeword{double(vector(index))+1});
end
string=repmat(uint8(0),1,len);%创建元素数与总比特数一致的行向量
pointer=1;%定义指针变量
for index=1:length(vector) %对输入图像进行编码
code=codeword{double(vector(index))+1};%对应符号的二进制码字给code
len=length(code);%读取码字长度
string(pointer+(0:len-1))=code;%将二进制码字存入行向量中
pointer=pointer+len;%指针移移位
end
% 将二进制编码按照每8位生成一个新字符。
len=length(string);
zp=8-mod(len,8);
if zp>0
string=[string uint8(zeros(1,zp))];%不足8位的在后补零
end
codeword=codeword(symbols);%码字按符号概率放入列向量中
codelen=zeros(size(codeword));%创建与列向量元素数相同的列向量
weights=2.^(0:23);
maxcodelen=0;
for index=1:length(codeword)
len=length(codeword{index});%读二进制码字长度
if len>0
code=sum(weights(codeword{index}==1));%计算二进制码字对应的十进制数
code=bitset(code,len+1);%将码字最高位的上一位置1
codeword{index}=code;
codelen(index)=len;%码字长度存入列向量中
end
end
codeword=[codeword{:}];%转化为行向量
%计算压缩后的向量
cols=length(string)/8;
string=reshape(string,8,cols);
weights=2.^(0:7);
zipped=uint8(weights*double(string));
%码表存储到一个稀疏矩阵
huffcodes=sparse(1,1);
for index=1:nnz(codeword)
huffcodes(codeword(index),1)=symbols(index);
end
%返回编码参数
info.zeropad=zp;%info.zeropad是添加的比特数
info.huffcodes=huffcodes;%info.huffcodes是Huffman码字表
info.length=length(vector);%info.length是灰度化图像矩阵长度
info.rows=m;%info.rows是灰度化图像行数
info.cols=n;%info.cols是灰度化图像列数
info.avalen=avawordlen;%info.ratio是平均码长
info.ratio=8/avawordlen;%info.ratio是压缩比
info.h=H;%info.h是信息熵
info.ce=H/avawordlen;%info.ce是计算编码效率