⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arith07.m

📁 算术编码
💻 M
📖 第 1 页 / 共 2 页
字号:
function varargout = Arith07(xC)
% Arith07     Arithmetic encoder or decoder 
% Vectors of integers are arithmetic encoded, 
% these vectors are collected in a cell array, xC.
% If first argument is a cell array the function do encoding,
% else decoding is done.
%
% [y, Res] = Arith07(xC);                    % encoding
% y = Arith07(xC);                           % encoding
% xC = Arith07(y);                           % decoding
% ------------------------------------------------------------------% Arguments:
%  y        a column vector of non-negative integers (bytes) representing 
%           the code, 0 <= y(i) <= 255. 
%  Res      a matrix that sum up the results, size is (NumOfX+1)x4
%           one line for each of the input sequences, the columns are
%           Res(:,1) - number of elements in the sequence
%           Res(:,2) - unused (=0) 
%           Res(:,3) - bits needed to code the sequence
%           Res(:,4) - bit rate for the sequence, Res(:,3)/Res(:,1)
%           Then the last line is total (which include bits needed to store NumOfX)
%  xC       a cell array of column vectors of integers representing the
%           symbol sequences. (should not be to large integers)
%           If only one sequence is to be coded, we must make the cell array
%           like: xC=cell(2,1); xC{1}=x; % where x is the sequence
% ------------------------------------------------------------------
% Note: this routine is extremely slow since it is all Matlab code
% SOME NOTES ON THE FUNCTION  
% This function is almost like Arith06, but some important changes have
% been done. Arith06 is buildt almost like Huff06, but this close connection
% is removed in Arith07. This imply that to understand the way Arith06
% works you should read the dokumentation for Huff06 and especially the
% article on Recursive Huffman Coding. To understand how Arith07 works it is 
% only confusing to read about the recursive Huffman coder, Huff06.
%
% Arith07 code each of the input sequences in xC in sequence, the
% method used for each sequence depends on what kind (xType) the 
% sequence is. We have
%  xType  Explanation
%   0     Empty sequence (L=0)
%   1     Only one symbol (L=1) and x>1
%   9     Only one symbol (L=1) and x=0/1
%  11     Only one symbol (L=1) and x<0
%   2     all symbols are equal, L>1, x(1)=x(2)=...=x(L)>1
%   8     all symbols are equal, L>1, x(1)=x(2)=...=x(L)=0/1
%  10     all symbols are equal, L>1, x(1)=x(2)=...=x(L)<0
%   3     non-negative integers, 0<=x(l)<=1000
%   4     not to large integers, -1000<=x(l)<=1000
%   5     large non-negative integers possible, 0<=x(l)
%   6     also possible with large negative numbers
%   7     A binary sequence, x(l)=0/1. 
% Many functions are defined in this m-file:
%  PutBit, GetBit     read and write bit from/to bitstream
%  PutABit, GetABit   Arithmetic encoding of a bit, P{0}=P{1}=0.5
%  PutVLIC, GetVLIC   Variable Length Integer Code
%  PutS(x,S,C), GetS(S,C)  A symbol x, which is in S, is aritmetic coded
%                     according to the counts given by C.
%                     Ex: A binary variable with the givene probabilities
%                     P{0}=0.8 and P{1}=0.2, PutS(x,[0,1],[4,1]).
%  PutN(x,N), GetN(N) Arithmetic coding of a number x in range 0<=x<=N where
%                     we assume equal probability, P{0}=P{1}=...=P{N}=1/(N+1)

%----------------------------------------------------------------------
% Copyright (c) 1999-2001.  Karl Skretting.  All rights reserved.
% Hogskolen in Stavanger (Stavanger University), Signal Processing Group
% Mail:  karl.skretting@tn.his.no   Homepage:  http://www.ux.his.no/~karlsk/
% 
% HISTORY:
% Ver. 1.0  19.05.2001  KS: Function made (based on Arith06 and Huff06)
%----------------------------------------------------------------------

% these global variables are used to read from or write to the compressed sequence
global y Byte BitPos      
% and these are used by the subfunctions for arithmetic coding
global high low range ub hc lc sc K code

Mfile='Arith07';
K=24;  % number of bits to use in integers  (4 <= K <= 24)
Display=1;      % display progress and/or results

% check input and output arguments, and assign values to arguments
if (nargin < 1); 
   error([Mfile,': function must have input arguments, see help.']); 
end
if (nargout < 1); 
   error([Mfile,': function must have output arguments, see help.']); 
end

if (~iscell(xC))
   Encode=0;Decode=1;
   y=xC(:);            % first argument is y
   y=[y;0;0;0;0];      % add some zeros to always have bits available
else
   Encode=1;Decode=0;
   NumOfX = length(xC);
end

Byte=0;BitPos=1;         % ready to read/write into first position
low=0;high=2^K-1;ub=0;   % initialize the coder
code=0;
% we just select some probabilities which we belive will work quite well   
TypeS=[  3,  4,  5,  7,  6,  1,  9, 11,  2,  8, 10,  0];
TypeC=[100, 50, 50, 50, 20, 10, 10, 10,  4,  4,  2,  1];

if Encode
   Res=zeros(NumOfX,4);
   % initalize the global variables
   y=zeros(10,1);    % put some zeros into y initially
   % start encoding, first write VLIC to give number of sequences
   PutVLIC(NumOfX);
   % now encode each sequence continuously
   Ltot=0;
   for num=1:NumOfX
      x=xC{num};
      x=full(x(:));        % make sure x is a non-sparse column vector
      L=length(x);
      Ltot=Ltot+L;
      y=[y(1:Byte);zeros(50+2*L,1)];  % make more space available in y
      StartPos=Byte*8-BitPos+ub;      % used for counting bits
      % find what kind of sequenqe we have, save this in xType
      if (L==0)
         xType=0;
      elseif L==1
         if (x==0) | (x==1)       % and it is 0/1
            xType=9; 
         elseif (x>1)             % and it is not 0/1 (and positive)
            xType=1;
         else                     % and it is not 0/1 (and negative) 
            xType=11;
         end
      else
         % now find some more info about x 
         maxx=max(x);
         minx=min(x);
         rangex=maxx-minx+1;
         if (rangex==1)                    % only one symbol
            if (maxx==0) | (maxx==1)       % and it is 0/1
               xType=8; 
            elseif (maxx>1)                % and it is not 0/1 (and positive)
               xType=2;
            else                           % and it is not 0/1 (and negative) 
               xType=10;
            end
         elseif (minx == 0) & (maxx == 1)   % a binary sequence
            xType=7;
         elseif (minx >= 0) & (maxx <= 1000)
            xType=3;
         elseif (minx >= 0) 
            xType=5;
         elseif (minx >= -1000) & (maxx <= 1000)
            xType=4;
         else
            xType=6;
         end
      end        % if (L==0)
      if Display >= 2
         disp([Mfile,': sequence ',int2str(num),' has xType=',int2str(xType)]);
      end
      % 
      if sum(xType==[4,6])        % negative values are present          
         I=find(x);               % non-zero entries in x
         Sg=(sign(x(I))+1)/2;     % the signs will be needed later, 0/1
         x=abs(x);   
      end
      if sum(xType==[5,6])        % we take the logarithms of the values          
         I=find(x);               % non-zero entries in x
         xa=x;                    % additional bits
         x(I)=floor(log2(x(I)));
         xa(I)=xa(I)-2.^x(I);
         x(I)=x(I)+1;
      end
      %  now do the coding of this sequence
      PutS(xType,TypeS,TypeC);
      if (xType==1)       % one symbol and x=x(1)>1
         PutVLIC(x-2);
      elseif (xType==2)   % L>1 but only one symbol, x(1)=x(2)=...=x(L)>1
         PutVLIC(L-2);
         PutVLIC(x(1)-2);
      elseif sum(xType==[3,4,5,6])  % now 'normalized' sequences: 0 <= x(i) <= 1000
         PutVLIC(L-2);     
         M=max(x);
         PutN(M,1000);         % some bits for M
         % initialize model
         T=[ones(M+2,1);0];
         Tu=flipud((-1:(M+1))');   % (-1) since ESC never is used in Tu context
         % and code the symbols in the sequence x
         for l=1:L
            sc=T(1);
            m=x(l); 
            hc=T(m+1);lc=T(m+2);
            if hc==lc      % unused symbol, code ESC symbol first
               hc=T(M+2);lc=T(M+3);
               EncodeSymbol;      % code escape with T table
               sc=Tu(1);hc=Tu(m+1);lc=Tu(m+2);  % symbol with Tu table
               Tu(1:(m+1))=Tu(1:(m+1))-1;       % update Tu table
            end
            EncodeSymbol;  % code actual symbol with T table (or Tu table)
            % update T table, MUST be identical in Encode and Decode
            % this avoid very large values  in T even if sequence is very long
            T(1:(m+1))=T(1:(m+1))+1; 
            if (rem(l,5000)==0)  
               dT=T(1:(M+2))-T(2:(M+3));
               dT=floor(dT*7/8+1/8);
               for m=(M+2):(-1):1; T(m)=T(m+1)+dT(m); end;
            end
         end          % for l=1:L
         % this end the "elseif sum(xType==[3,4,5,6])"-clause
      elseif (xType==7)   % L>1 and   0 <= x(i) <= 1
         PutVLIC(L-2);
         EncodeBin(x,L);    % code this sequence a special way
      elseif (xType==8)   % L>1 and   0 <= x(1)=x(2)=...=x(L) <= 1
         PutVLIC(L-2);
         PutABit(x(1));
      elseif (xType==9)   % L=1 and   0 <= x(1) <= 1
         PutABit(x(1));
      elseif (xType==10)       % L>1 and  x(1)=x(2)=...=x(L) <= -1
         PutVLIC(L-2);
         PutVLIC(-1-x(1));
      elseif (xType==11)       % L=1 and   x(1) <= -1
         PutVLIC(-1-x);
      end         % if (xType==1)   
      % additional information should be coded as well
      if 0         % first the way it is not done any more
         if sum(xType==[4,6])           % sign must be stored          
            for i=1:length(Sg); PutABit(Sg(i)); end;   
         end
         if sum(xType==[5,6])        % additional bits must be stored          
            for i=1:L
               for ii=(x(i)-1):(-1):1
                  PutABit(bitget(xa(i),ii));
               end
            end
         end
      else         % this is how we do it
         if sum(xType==[4,6])           % sign must be stored          
            EncodeBin(Sg,length(I));    % since length(I)=length(Sg)
         end
         if sum(xType==[5,6])        % additional bits must be stored          
            b=zeros(sum(x)-length(I),1);  % number of additional bits
            bi=0;
            for i=1:L
               for ii=(x(i)-1):(-1):1
                  bi=bi+1;
                  b(bi)=bitget(xa(i),ii);
               end
            end
            if (bi~=(sum(x)-length(I)))
               error([Mfile,': logical error, bi~=(sum(x)-length(I)).']); 
            end
            EncodeBin(b,bi);    % since bi=(sum(x)-length(I))
         end
      end
      %
      EndPos=Byte*8-BitPos+ub;    % used for counting bits
      bits=EndPos-StartPos;
      Res(num,1)=L;
      Res(num,2)=0;
      Res(num,3)=bits;
      if L>0; Res(num,4)=bits/L; else Res(num,4)=bits; end;
      if Display
         disp([Mfile,': Sequence ',int2str(num),' of ',int2str(L),' symbols ',...
               'encoded using ',int2str(bits),' bits.']);
      end
   end         % for num=1:NumOfX
   % flush the arithmetic coder
   PutBit(bitget(low,K-1));     
   ub=ub+1;
   while ub>0
      PutBit(~bitget(low,K-1));
      ub=ub-1;
   end
   % flush is finished
   y=y(1:Byte);   
   varargout(1) = {y};
   if (nargout >= 2) 
      % now calculate results for the total
      Res(NumOfX+1,1)=Ltot;
      Res(NumOfX+1,2)=0;
      Res(NumOfX+1,3)=Byte*8;
      if (Ltot>0); Res(NumOfX+1,4)=Byte*8/Ltot; else Res(NumOfX+1,4)=Byte*8; end;
      varargout(2) = {Res}; 
   end
end         % if Encode

if Decode
   for k=1:K
      code=code*2;
      code=code+GetBit;   % read bits into code
   end
   NumOfX=GetVLIC;   % first read number of sequences
   xC=cell(NumOfX,1);
   for num=1:NumOfX
      % find what kind of sequenqe we have, xType, stored first in sequence
      xType=GetS(TypeS,TypeC);
      % now decode the different kind of sequences, each the way it was stored 
      if (xType==0)       % empty sequence, no more symbols coded
         x=[];
      elseif (xType==1)       % one symbol and x=x(1)>1
         x=GetVLIC+2;
      elseif (xType==2)   % L>1 but only one symbol, x(1)=x(2)=...=x(L)>1
         L=GetVLIC+2;
         x=ones(L,1)*(GetVLIC+2);
      elseif sum(xType==[3,4,5,6])  % now 'normalized' sequences: 0 <= x(i) <= 1000
         L=GetVLIC+2;
         x=zeros(L,1);
         M=GetN(1000);      % M is max(x)
         % initialize model
         T=[ones(M+2,1);0];
         Tu=flipud((-1:(M+1))');   % (-1) since ESC never is used in Tu context
         % and decode the symbols in the sequence x
         for l=1:L
            sc=T(1);
            range=high-low+1;
            count=floor(( (code-low+1)*sc-1 )/range);
            m=2; while (T(m)>count); m=m+1; end; 
            hc=T(m-1);lc=T(m);m=m-2;
            RemoveSymbol;
            if (m>M)     % decoded ESC symbol, find symbol from Tu table
               sc=Tu(1);range=high-low+1;
               count=floor(( (code-low+1)*sc-1 )/range);
               m=2; while (Tu(m)>count); m=m+1; end; 
               hc=Tu(m-1);lc=Tu(m);m=m-2;
               RemoveSymbol;
               Tu(1:(m+1))=Tu(1:(m+1))-1;   % update Tu table
            end
            x(l)=m;
            % update T table, MUST be identical in Encode and Decode
            % this avoid very large values  in T even if sequence is very long
            T(1:(m+1))=T(1:(m+1))+1; 
            if (rem(l,5000)==0)  
               dT=T(1:(M+2))-T(2:(M+3));
               dT=floor(dT*7/8+1/8);
               for m=(M+2):(-1):1; T(m)=T(m+1)+dT(m); end;
            end
         end          % for l=1:L
         % this end the "elseif sum(xType==[3,4,5,6])"-clause
      elseif (xType==7)   % L>1 and   0 <= x(i) <= 1
         L=GetVLIC+2;
         x=DecodeBin(L);    % decode this sequence a special way
      elseif (xType==8)   % L>1 and   0 <= x(1)=x(2)=...=x(L) <= 1
         L=GetVLIC+2;
         x=ones(L,1)*GetABit;
      elseif (xType==9)   % L=1 and   0 <= x(1) <= 1
         x=GetABit;
      elseif (xType==10)       % L>1 and  x(1)=x(2)=...=x(L) <= -1
         L=GetVLIC+2;
         x=ones(L,1)*(-1-GetVLIC);
      elseif (xType==11)       % L=1 and   x(1) <= -1
         x=(-1-GetVLIC);
      end         % if (xType==0)   
      % additional information should be decoded as well
      L=length(x);
      I=find(x);
      if 0
         if sum(xType==[4,6])           % sign must be retrieved          
            Sg=zeros(size(I));
            for i=1:length(I); Sg(i)=GetABit; end;   % and the signs   (0/1)
            Sg=Sg*2-1;                               % (-1/1)
         end
         if sum(xType==[5,6])        % additional bits must be retrieved
            xa=zeros(L,1);
            for i=1:L
               for ii=2:x(i)
                  xa(i)=2*xa(i)+GetABit;
               end
            end
            x(I)=2.^(x(I)-1);
            x=x+xa;
         end
      else
         if sum(xType==[4,6])           % sign must be retrieved          
            Sg=DecodeBin(length(I));    % since length(I)=length(Sg)
            Sg=Sg*2-1;                  % (-1/1)
         end
         if sum(xType==[5,6])        % additional bits must be retrieved
            bi=sum(x)-length(I);     % number of additional bits
            b=DecodeBin(bi);  
            bi=0;
            xa=zeros(L,1);
            for i=1:L
               for ii=2:x(i)
                  bi=bi+1;
                  xa(i)=2*xa(i)+b(bi);
               end
            end
            x(I)=2.^(x(I)-1);
            x=x+xa;
         end
      end
      if sum(xType==[4,6])           % sign must be used          
         x(I)=x(I).*Sg;
      end
      % now x is the retrieved sequence      
      xC{num}=x;
   end         % for num=1:NumOfX
   varargout(1) = {xC}; 
end

return     % end of main function, Arith07
%----------------------------------------------------------------------
%----------------------------------------------------------------------

% --- The functions for binary sequences: EncodeBin and DecodeBin -------
% These function may call themselves recursively
function EncodeBin(x,L)
global y Byte BitPos
global high low range ub hc lc sc K code

Display=0;
x=x(:);
if (length(x)~=L); error('EncodeBin: length(x) not equal L.'); end;

% first we try some different coding methods to find out which one
% that might do best. Many more methods could have been tried, for
% example methods to check if x is a 'byte' sequence, or if the bits
% are grouped in other ways. The calling application is the best place
% to detect such dependencies, since it will (might) know the process and
% possible also its statistical (or deterministic) properties.
% Here we just check some few coding methods: direct, split, diff, diff+split
% The main variables used for the different methods are:
%  direct: x, I, J, L11, b0
%  split: x is split into x1 and x2, L1, L2, b1 is bits needed
%  diff: x3 is generated from x, I3, J3 L31, b2
%  diff+split: x3 is split into x4 and x5, L4, L5, b3
%

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -