精华内容
下载资源
问答
  • Huffman解码

    2011-03-26 16:36:00
    main() 函数是瞎写的。。。   #include typedef struct _HuffmanNode { char charactor;...}HuffmanNode,*HuffmanTree; typedef char** HuffmanCode; void recognizeANe

    main() 函数是瞎写的。。。

     

     

    展开全文
  • 主要基于软硬件协同设计的方法,实现MP3的Huffman解码模块。提出的解决方案不仅可以实现对MP3的Huffman模块的高效解码,同样也可以应用于WMA、AAC等其他音频格式的Huffman模块,在保证高效的同时,兼顾了模块的通用...
  • huffman解码程序

    2007-11-02 09:02:57
    huffman解码程序 <br>解压密码:里面有,见注释部分
  • 基于JPEG图像解码的高速Huffman解码电路
  • 快速Huffman解码

    2017-07-27 12:46:30
    最近需要把采集到的图像数据进行压缩,节省存储空间。综合考虑压缩比和速度,决定采用静态Huffman编码...于是去gzip的代码里面找了一下,在一个叫unpack.c的文件里发现了Huffman解码的实现,gzip的解码确实很高效,...

    最近需要把采集到的图像数据进行压缩,节省存储空间。综合考虑压缩比和速度,决定采用静态Huffman编码,使用预先计算好的字典对数据进行压缩,这样压缩速度可以非常高,使用多线程之后可以进行实时压缩,但解压速度比较慢。

    于是去gzip的代码里面找了一下,在一个叫unpack.c的文件里发现了Huffman解码的实现,gzip的解码确实很高效,其中的原因,简单来说就是多用内存,少用循环。

    假设我们要压缩的字符串是“ABBBCC”,计算得到Huffman编码如下:

    字符计数编码
    A100
    B31
    C201

    编码后的二进制串是 0011101

    要对编码后的字符串进行解码,比较容易想到的方法是这样的,构造这么一个字典

    编码字符
    1B
    00A
    01C

    这个字典是原始的编码表按字符编码的长度进行排序,解码的时候就在字典里面顺序地查找编码

    对于这个例子而言是这样一个过程

    对二进制串0011101从左往右解码,先尝试编码1(对应字符B),发现不对,因为最左边是0,因此再尝试字典的第二个编码00(对应A),发现是正确的,最左边就是00,因此解码出字符A,将二进制串左移两位得到11101,继续从B的编码1开始尝试。最后能解码出ABBBCC这个原始编码。

    这个解码方法的问题就是每解码一个字符串都要在字典里面循环一遍,效率不高。

    gzip的方法

    对于我们的例子gzip会构造这么一个字典

    索引索引编码编码字符
    2101B
    3111B
    00000A
    10101C

    这个字典的特点就是有索引,因此查找编码的时候不用循环,而是计算索引直接定位到对应的编码。字典的构造方法是根据编码生成索引编码,所有索引编码的长度是相同的,从二叉树的角度来看就是把所有的子树都补到同样的长度,然后所有非编码节点(如11)都和其父节点(如1)对应同一个字符(如B)。

    这个方法同样也是一种空间换时间的方法,随着编码长度的增加,内存消耗会指数增长,因此当编码太长时,gzip会使用多个字典,将长编码放在一些单独的字典里面,减小内存消耗。

    展开全文
  • JPEG解码:huffman解码

    2012-03-18 02:08:00
    huffman解码是JPEG图片解码里面的关键步骤,也是最复杂的一步。在fsm模块中DHT状态下读取的不仅仅是huffman表,还有另外两个表,一个是存放1-16不同码长的最小编码的一个表,另一个是存放最小编码的地址的表。在...

    huffman解码是JPEG图片解码里面的关键步骤,也是最复杂的一步。在fsm模块中DHT状态下读取的不仅仅是huffman表,还有另外两个表,一个是存放1-16不同码长的最小编码的一个表,另一个是存放最小编码的地址的表。在huffman解码中需要用到这两个表,还有在本模块也集成了反量化模块。

    huffman解码的步骤:

    (1):判断解码数据的类型选择与之对应的表。

    (2):进行码长的判断。

    (3):计算DHT地址。

    (4):从DHT表中读取数据。

    (5):若为DC数据需要进行DPCM解码。

    对于一个huffman解码器应包含3个独立的存储器:

    (1):存放各个长度对应的最小编码。

    (2):存储各个长度对应码字的最小地址。

    (3):存储解码符号(DHT表)

    代码如下:

     

    `timescale 1ps / 1ps
    module hm_dec(
                  clk,
                  rst_n, 
                  
                  image_en, 
                  zig_zagIDLE,                       
                  datain_en,      
                  datain,   
                    
                  huffman_en,
                  huffman_color, 
                  huffman_count, 
                  huffman_mincode,    
                  huffman_mincodeaddr,
                  
               
                  dhtrd_color,          
                  dhtrd_addr,         
                  dhtrd_zero,           
                  dhtrd_width, 
                           
                  dqtrd_color,          
                  dqtrd_addr,         
                  dqtrd_data,           
          
                  unit_en,    
                  use_bit,      
                  use_width,    
                  dataout_en,          
                  dataout_count,       
                  dataout         
                  );                                 
    
    input  clk;//时钟信号
    input rst_n;//复位信号  低电平有效
    
    input           image_en;//fsm模块读到SOS,开始huffman解码
    input           zig_zagIDLE;//zig_zag模块空闲,允许解码
    input           datain_en;//输入数据使能       
    input [31:0]    datain;//输入的数据,从regdata模块得到 
          
    input           huffman_en; //huffman表使能
    input [1:0]     huffman_color;//huffman表类型
    input [3:0]     huffman_count;//huffman表的深度:0-16
    input [15:0]    huffman_mincode;//huffman表中不同长度对应的最小编码  
    input [7:0]     huffman_mincodeaddr;//huffman表的最小编码的首地址 
    
    output [1:0]    dhtrd_color;//dht表类型
    output [7:0]    dhtrd_addr;//dht表地址         
    input [3:0]     dhtrd_zero;//dht表读取的0的个数            
    input [3:0]     dhtrd_width;//dht读取的有效数据的长度           
    
    output          dqtrd_color;//dqt表的类型
    output [5:0]    dqtrd_addr;//dqt表的地址
    input [7:0]     dqtrd_data;//dqt表的数据
    
    output          use_bit;//以位传输数据
    output [6:0]    use_width;//使用数据的位宽   
         
    //output [2:0]    dataout_color;//解码数据的类型
    output [5:0]    dataout_count;//解码数据计数
    output          dataout_en;//数据输出使能
    output [15:0]   dataout;//输出数据       
    output          unit_en;//一个单元64个数据解码完成
    //--------------------------------------------------------------------------
    //huffman 存储器,一个用于存储最小的编码,一个用于存储最小编码对应的首地址
    reg [15:0]      ram0_Y_DC [0:15];  
    reg [15:0]      ram0_Y_AC [0:15];  
    reg [15:0]      ram0_C_DC [0:15];  
    reg [15:0]      ram0_C_AC [0:15];  
    
    reg [7:0]       ram1_Y_DC [0:15]; 
    reg [7:0]       ram1_Y_AC [0:15]; 
    reg [7:0]       ram1_C_DC [0:15]; 
    reg [7:0]       ram1_C_AC [0:15]; 
    
    always @(posedge clk or negedge rst_n)
     begin
            if(!rst_n) 
            begin
            	 ram0_Y_DC[0 ]<=16'd0; 
            	 ram0_Y_DC[1 ]<=16'd0; 
            	 ram0_Y_DC[2 ]<=16'd0; 
            	 ram0_Y_DC[3 ]<=16'd0; 
            	 ram0_Y_DC[4 ]<=16'd0; 
            	 ram0_Y_DC[5 ]<=16'd0; 
            	 ram0_Y_DC[6 ]<=16'd0; 
            	 ram0_Y_DC[7 ]<=16'd0; 
            	 ram0_Y_DC[8 ]<=16'd0; 
            	 ram0_Y_DC[9 ]<=16'd0; 
            	 ram0_Y_DC[10]<=16'd0; 
            	 ram0_Y_DC[11]<=16'd0; 
            	 ram0_Y_DC[12]<=16'd0; 
            	 ram0_Y_DC[13]<=16'd0; 
            	 ram0_Y_DC[14]<=16'd0; 
            	 ram0_Y_DC[15]<=16'd0; 
               
               ram0_Y_AC[0 ]<=16'd0;
               ram0_Y_AC[1 ]<=16'd0;
               ram0_Y_AC[2 ]<=16'd0;
               ram0_Y_AC[3 ]<=16'd0;
            	 ram0_Y_AC[4 ]<=16'd0; 
               ram0_Y_AC[5 ]<=16'd0;
               ram0_Y_AC[6 ]<=16'd0; 
               ram0_Y_AC[7 ]<=16'd0; 
               ram0_Y_AC[8 ]<=16'd0; 
               ram0_Y_AC[9 ]<=16'd0; 
               ram0_Y_AC[10]<=16'd0; 
               ram0_Y_AC[11]<=16'd0; 
               ram0_Y_AC[12]<=16'd0; 
               ram0_Y_AC[13]<=16'd0; 
               ram0_Y_AC[14]<=16'd0;
               ram0_Y_AC[15]<=16'd0;   
               
               ram0_C_DC[0 ]<=16'D0;
               ram0_C_DC[1 ]<=16'D0; 
               ram0_C_DC[2 ]<=16'D0; 
               ram0_C_DC[3 ]<=16'D0; 
               ram0_C_DC[4 ]<=16'D0; 
               ram0_C_DC[5 ]<=16'D0; 
               ram0_C_DC[6 ]<=16'D0; 
               ram0_C_DC[7 ]<=16'D0; 
               ram0_C_DC[8 ]<=16'D0;
               ram0_C_DC[9 ]<=16'D0; 
               ram0_C_DC[10]<=16'D0; 
               ram0_C_DC[11]<=16'D0; 
               ram0_C_DC[12]<=16'D0; 
               ram0_C_DC[13]<=16'D0; 
               ram0_C_DC[14]<=16'D0; 
               ram0_C_DC[15]<=16'D0;  
               
               ram0_C_AC[0 ]<=16'd0;
               ram0_C_AC[1 ]<=16'd0;
               ram0_C_AC[2 ]<=16'd0;
               ram0_C_AC[3 ]<=16'd0;
               ram0_C_AC[4 ]<=16'd0;
               ram0_C_AC[5 ]<=16'd0;
               ram0_C_AC[6 ]<=16'd0;
               ram0_C_AC[7 ]<=16'd0;
               ram0_C_AC[8 ]<=16'd0;
               ram0_C_AC[9 ]<=16'd0;
               ram0_C_AC[10]<=16'd0;
               ram0_C_AC[11]<=16'd0;
               ram0_C_AC[12]<=16'd0;
               ram0_C_AC[13]<=16'd0;
               ram0_C_AC[14]<=16'd0;
               ram0_C_AC[15]<=16'd0;  
               
            	 ram1_Y_DC[0 ]<=8'd0; 
            	 ram1_Y_DC[1 ]<=8'd0; 
            	 ram1_Y_DC[2 ]<=8'd0; 
            	 ram1_Y_DC[3 ]<=8'd0; 
            	 ram1_Y_DC[4 ]<=8'd0; 
            	 ram1_Y_DC[5 ]<=8'd0; 
            	 ram1_Y_DC[6 ]<=8'd0; 
            	 ram1_Y_DC[7 ]<=8'd0; 
            	 ram1_Y_DC[8 ]<=8'd0; 
            	 ram1_Y_DC[9 ]<=8'd0; 
            	 ram1_Y_DC[10]<=8'd0; 
            	 ram1_Y_DC[11]<=8'd0; 
            	 ram1_Y_DC[12]<=8'd0; 
            	 ram1_Y_DC[13]<=8'd0; 
            	 ram1_Y_DC[14]<=8'd0; 
            	 ram1_Y_DC[15]<=8'd0; 
               
               ram1_Y_AC[0 ]<=8'd0;
               ram1_Y_AC[1 ]<=8'd0;
               ram1_Y_AC[2 ]<=8'd0;
               ram1_Y_AC[3 ]<=8'd0;
            	 ram1_Y_AC[4 ]<=8'd0; 
               ram1_Y_AC[5 ]<=8'd0;
               ram1_Y_AC[6 ]<=8'd0; 
               ram1_Y_AC[7 ]<=8'd0; 
               ram1_Y_AC[8 ]<=8'd0; 
               ram1_Y_AC[9 ]<=8'd0; 
               ram1_Y_AC[10]<=8'd0; 
               ram1_Y_AC[11]<=8'd0; 
               ram1_Y_AC[12]<=8'd0; 
               ram1_Y_AC[13]<=8'd0; 
               ram1_Y_AC[14]<=8'd0;
               ram1_Y_AC[15]<=8'd0;   
               
               ram1_C_DC[0 ]<=8'D0;
               ram1_C_DC[1 ]<=8'D0; 
               ram1_C_DC[2 ]<=8'D0; 
               ram1_C_DC[3 ]<=8'D0; 
               ram1_C_DC[4 ]<=8'D0; 
               ram1_C_DC[5 ]<=8'D0; 
               ram1_C_DC[6 ]<=8'D0; 
               ram1_C_DC[7 ]<=8'D0; 
               ram1_C_DC[8 ]<=8'D0;
               ram1_C_DC[9 ]<=8'D0; 
               ram1_C_DC[10]<=8'D0; 
               ram1_C_DC[11]<=8'D0; 
               ram1_C_DC[12]<=8'D0; 
               ram1_C_DC[13]<=8'D0; 
               ram1_C_DC[14]<=8'D0; 
               ram1_C_DC[15]<=8'D0;  
               
               ram1_C_AC[0 ]<=8'd0;
               ram1_C_AC[1 ]<=8'd0;
               ram1_C_AC[2 ]<=8'd0;
               ram1_C_AC[3 ]<=8'd0;
               ram1_C_AC[4 ]<=8'd0;
               ram1_C_AC[5 ]<=8'd0;
               ram1_C_AC[6 ]<=8'd0;
               ram1_C_AC[7 ]<=8'd0;
               ram1_C_AC[8 ]<=8'd0;
               ram1_C_AC[9 ]<=8'd0;
               ram1_C_AC[10]<=8'd0;
               ram1_C_AC[11]<=8'd0;
               ram1_C_AC[12]<=8'd0;
               ram1_C_AC[13]<=8'd0;
               ram1_C_AC[14]<=8'd0;
               ram1_C_AC[15]<=8'd0; 
             end 
     
            else 
            begin
                if(huffman_en ==2'b1)    //选择table类型和设置数据
                begin
                    if(huffman_color ==2'b00)   //Y_DC
                     begin
                        ram0_Y_DC[huffman_count]  <= huffman_mincode;
                        ram1_Y_DC[huffman_count] <= huffman_mincodeaddr;
                    end 
                    else if(huffman_color ==2'b01) //Y_AC
                    begin
                        ram0_Y_AC[huffman_count]  <= huffman_mincode;
                        ram1_Y_AC[huffman_count] <= huffman_mincodeaddr;
                    end 
                    else if(huffman_color ==2'b10) //C_DC
                    begin
                        ram0_C_DC[huffman_count]  <= huffman_mincode;
                        ram1_C_DC[huffman_count] <= huffman_mincodeaddr;
                    end else 
                    begin                               //C_AC
                        ram0_C_AC[huffman_count]  <= huffman_mincode;
                        ram1_C_AC[huffman_count] <= huffman_mincodeaddr;
                    end
                end
            end
        end
        
    //--------------------------------------------------------------------------
    // fsm
    //--------------------------------------------------------------------------
    reg [3:0]   state;       
    reg [31:0]  data_reg;    
    
    
    reg [15:0]  ram0 [0:15];
    reg [7:0]   ram1 [0:15];
    
    reg [3:0]  length;       
    reg [15:0]  mincode;     
    reg [7:0]   mincodeaddr;
    reg [15:0]  data_number; 
    
    reg [2:0]   state_color;
    reg [6:0]   state_count;
    
    reg         out_en;      
    reg [3:0]   out_zero;    
    reg [15:0]  code_value;  
    wire [15:0] code_value_p;   
    
    reg [6:0]   use_width_r;      
    reg signed [31:0] pre_data [0:2];
    
    wire [15:0] sub_code;
    
    parameter Idle  = 4'h0;
    parameter s1    = 4'h1;
    parameter s2    = 4'h2;
    parameter s3    = 4'h3;
    parameter s4    = 4'h4;
    parameter s5    = 4'h5;
    parameter s6    = 4'h6;
    parameter s7    = 4'h7;
    
    function [15:0] value_sel;
            input [3:0]   dhtrd_width;
            input [31:0]  data_reg;
            begin
                case (dhtrd_width)
                    4'h0: value_sel = 16'h0000;
                    4'h1: value_sel = {15'h0000, data_reg[31]};
                    4'h2: value_sel = {14'h0000, data_reg[31:30]};
                    4'h3: value_sel = {13'h0000, data_reg[31:29]};
                    4'h4: value_sel = {12'h000,  data_reg[31:28]};
                    4'h5: value_sel = {11'h000,  data_reg[31:27]};
                    4'h6: value_sel = {10'h000,  data_reg[31:26]};
                    4'h7: value_sel = {9'h000,   data_reg[31:25]};
                    4'h8: value_sel = {8'h00,    data_reg[31:24]};
                    4'h9: value_sel = {7'h00,    data_reg[31:23]};
                    4'hA: value_sel = {6'h00,    data_reg[31:22]};
                    4'hB: value_sel = {5'h00,    data_reg[31:21]};
                    4'hC: value_sel = {4'h0,     data_reg[31:20]};
                    4'hD: value_sel = {3'h0,     data_reg[31:19]};
                    4'hE: value_sel = {2'h0,     data_reg[31:18]};
                    4'hF: value_sel = {1'h0,     data_reg[31:17]};
                endcase
            end
        endfunction
        assign code_value_p = value_sel(dhtrd_width, data_reg);
              
        function [15:0] subcode_sel;
            input [3:0]  dhtrd_width;
            begin
            case (dhtrd_width)
                4'h0: subcode_sel = 16'hFFFF;
                4'h1: subcode_sel = 16'hFFFE;
                4'h2: subcode_sel = 16'hFFFC;
                4'h3: subcode_sel = 16'hFFF8;
                4'h4: subcode_sel = 16'hFFF0;
                4'h5: subcode_sel = 16'hFFE0;
                4'h6: subcode_sel = 16'hFFC0;
                4'h7: subcode_sel = 16'hFF80;
                4'h8: subcode_sel = 16'hFF00;
                4'h9: subcode_sel = 16'hFE00;
                4'hA: subcode_sel = 16'hFC00;
                4'hB: subcode_sel = 16'hF800;
                4'hC: subcode_sel = 16'hF000;
                4'hD: subcode_sel = 16'hE000;
                4'hE: subcode_sel = 16'hC000;
                4'hF: subcode_sel = 16'h8000;
            endcase
        end
    endfunction
    assign sub_code = subcode_sel(dhtrd_width);
        
    always @(posedge clk or negedge rst_n)
     begin
            if(!rst_n) begin
                state            <= Idle;
                data_reg         <= 32'h00000000;
                state_count      <= 6'd0;
                state_color      <=3'd0;
                out_en           <= 1'b0;
                pre_data[0]      <= 32'h00000000;
                pre_data[1]      <= 32'h00000000;
                pre_data[2]      <= 32'h00000000;
                use_width_r        <= 7'h00;
                length<=4'd0;
            end 
            else 
            begin
                case (state)
                	//准备状态
                    Idle: 
                    begin
                        if(image_en == 1'b1) //开始解码
                            state <= s1;
                        else                  //设置DC的初始值
                        begin
                         pre_data[0] <= 32'h00000000;
                         pre_data[1] <= 32'h00000000;
                         pre_data[2] <= 32'h00000000;
                        end
                        out_en      <= 1'b0;
                        state_color    <= 3'b000;
                        state_count   <= 6'd0;
                    end
                    
                    //从数据读入模块读入32位需要解码的数据。判断此次解
                    //数据是DC数据还是AC数据,同时选择相应的码表
                    s1:                          
                    begin
                        if(image_en == 1'b0) 
                        begin
                            state     <= Idle;
                        end 
                        else 
                        if(datain_en == 1'b1 & zig_zagIDLE == 1'b1)//输入数据使能,并且zig_zag存储器空闲
                         begin
                            state     <= s2;
                            data_reg <= datain;
                        end
                        out_en <= 1'b0;
                        if(state_color[2] == 1'b0) //此时解码的为亮度数据
                        begin
                            if(state_count == 0)//此时解码的为DC数据
                             begin
                                ram0[0]  <= ram0_Y_DC[0];
                                ram1[0]  <= ram1_Y_DC[0];
                                ram0[1]  <= ram0_Y_DC[1];
                                ram1[1]  <= ram1_Y_DC[1];
                                ram0[2]  <= ram0_Y_DC[2];
                                ram1[2]  <= ram1_Y_DC[2];
                                ram0[3]  <= ram0_Y_DC[3];
                                ram1[3]  <= ram1_Y_DC[3];
                                ram0[4]  <= ram0_Y_DC[4];
                                ram1[4]  <= ram1_Y_DC[4];
                                ram0[5]  <= ram0_Y_DC[5];
                                ram1[5]  <= ram1_Y_DC[5];
                                ram0[6]  <= ram0_Y_DC[6];
                                ram1[6]  <= ram1_Y_DC[6];
                                ram0[7]  <= ram0_Y_DC[7];
                                ram1[7]  <= ram1_Y_DC[7];
                                ram0[8]  <= ram0_Y_DC[8];
                                ram1[8]  <= ram1_Y_DC[8];
                                ram0[9]  <= ram0_Y_DC[9];
                                ram1[9]  <= ram1_Y_DC[9];
                                ram0[10]  <= ram0_Y_DC[10];
                                ram1[10]  <= ram1_Y_DC[10];
                                ram0[11]  <= ram0_Y_DC[11];
                                ram1[11]  <= ram1_Y_DC[11];
                                ram0[12]  <= ram0_Y_DC[12];
                                ram1[12]  <= ram1_Y_DC[12];
                                ram0[13]  <= ram0_Y_DC[13];
                                ram1[13]  <= ram1_Y_DC[13];
                                ram0[14]  <= ram0_Y_DC[14];
                                ram1[14]  <= ram1_Y_DC[14];  
                                ram0[15]  <= ram0_Y_DC[15];  
                                ram1[15]  <= ram1_Y_DC[15];  
                            end
                             else //此时解码的为AC数据
                             begin
                                ram0[0]  <= ram0_Y_AC[0];
                                ram1[0]  <= ram1_Y_AC[0];
                                ram0[1]  <= ram0_Y_AC[1];
                                ram1[1]  <= ram1_Y_AC[1];
                                ram0[2]  <= ram0_Y_AC[2];
                                ram1[2]  <= ram1_Y_AC[2];
                                ram0[3]  <= ram0_Y_AC[3];
                                ram1[3]  <= ram1_Y_AC[3];
                                ram0[4]  <= ram0_Y_AC[4];
                                ram1[4]  <= ram1_Y_AC[4];
                                ram0[5]  <= ram0_Y_AC[5];
                                ram1[5]  <= ram1_Y_AC[5];
                                ram0[6]  <= ram0_Y_AC[6];
                                ram1[6]  <= ram1_Y_AC[6];
                                ram0[7]  <= ram0_Y_AC[7];
                                ram1[7]  <= ram1_Y_AC[7];
                                ram0[8]  <= ram0_Y_AC[8];
                                ram1[8]  <= ram1_Y_AC[8];
                                ram0[9]  <= ram0_Y_AC[9];
                                ram1[9]  <= ram1_Y_AC[9];
                                ram0[10]  <= ram0_Y_AC[10];
                                ram1[10]  <= ram1_Y_AC[10];
                                ram0[11]  <= ram0_Y_AC[11];
                                ram1[11]  <= ram1_Y_AC[11];
                                ram0[12]  <= ram0_Y_AC[12];
                                ram1[12]  <= ram1_Y_AC[12];
                                ram0[13]  <= ram0_Y_AC[13];
                                ram1[13]  <= ram1_Y_AC[13];
                                ram0[14]  <= ram0_Y_AC[14];
                                ram1[14]  <= ram1_Y_AC[14];  
                                ram0[15]  <= ram0_Y_AC[15];  
                                ram1[15]  <= ram1_Y_AC[15];  
                            end
                        end 
                        else //此时解码的为色度数据
                        begin
                            if(state_count == 0)//此时解码的为DC数据
                             begin
                                ram0[0]  <= ram0_C_DC[0];    
                                ram1[0]  <= ram1_C_DC[0];    
                                ram0[1]  <= ram0_C_DC[1];    
                                ram1[1]  <= ram1_C_DC[1];    
                                ram0[2]  <= ram0_C_DC[2];    
                                ram1[2]  <= ram1_C_DC[2];    
                                ram0[3]  <= ram0_C_DC[3];    
                                ram1[3]  <= ram1_C_DC[3];    
                                ram0[4]  <= ram0_C_DC[4];    
                                ram1[4]  <= ram1_C_DC[4];    
                                ram0[5]  <= ram0_C_DC[5];    
                                ram1[5]  <= ram1_C_DC[5];    
                                ram0[6]  <= ram0_C_DC[6];    
                                ram1[6]  <= ram1_C_DC[6];    
                                ram0[7]  <= ram0_C_DC[7];    
                                ram1[7]  <= ram1_C_DC[7];    
                                ram0[8]  <= ram0_C_DC[8];    
                                ram1[8]  <= ram1_C_DC[8];    
                                ram0[9]  <= ram0_C_DC[9];    
                                ram1[9]  <= ram1_C_DC[9];    
                                ram0[10]  <= ram0_C_DC[10];  
                                ram1[10]  <= ram1_C_DC[10];  
                                ram0[11]  <= ram0_C_DC[11];  
                                ram1[11]  <= ram1_C_DC[11];  
                                ram0[12]  <= ram0_C_DC[12];  
                                ram1[12]  <= ram1_C_DC[12];  
                                ram0[13]  <= ram0_C_DC[13];  
                                ram1[13]  <= ram1_C_DC[13];  
                                ram0[14]  <= ram0_C_DC[14];  
                                ram1[14]  <= ram1_C_DC[14];  
                                ram0[15]  <= ram0_C_DC[15];  
                                ram1[15]  <= ram1_C_DC[15];  
                            end
                             else //此时解码的为AC数据
                             begin
                                ram0[0]  <= ram0_C_AC[0];    
                                ram1[0]  <= ram1_C_AC[0];    
                                ram0[1]  <= ram0_C_AC[1];    
                                ram1[1]  <= ram1_C_AC[1];    
                                ram0[2]  <= ram0_C_AC[2];    
                                ram1[2]  <= ram1_C_AC[2];    
                                ram0[3]  <= ram0_C_AC[3];    
                                ram1[3]  <= ram1_C_AC[3];    
                                ram0[4]  <= ram0_C_AC[4];    
                                ram1[4]  <= ram1_C_AC[4];    
                                ram0[5]  <= ram0_C_AC[5];    
                                ram1[5]  <= ram1_C_AC[5];    
                                ram0[6]  <= ram0_C_AC[6];    
                                ram1[6]  <= ram1_C_AC[6];    
                                ram0[7]  <= ram0_C_AC[7];    
                                ram1[7]  <= ram1_C_AC[7];    
                                ram0[8]  <= ram0_C_AC[8];    
                                ram1[8]  <= ram1_C_AC[8];    
                                ram0[9]  <= ram0_C_AC[9];    
                                ram1[9]  <= ram1_C_AC[9];    
                                ram0[10]  <= ram0_C_AC[10];  
                                ram1[10]  <= ram1_C_AC[10];  
                                ram0[11]  <= ram0_C_AC[11];  
                                ram1[11]  <= ram1_C_AC[11];  
                                ram0[12]  <= ram0_C_AC[12];  
                                ram1[12]  <= ram1_C_AC[12];  
                                ram0[13]  <= ram0_C_AC[13];  
                                ram1[13]  <= ram1_C_AC[13];  
                                ram0[14]  <= ram0_C_AC[14];  
                                ram1[14]  <= ram1_C_AC[14];  
                                ram0[15]  <= ram0_C_AC[15];  
                                ram1[15]  <= ram1_C_AC[15];  
                            end
                        end
                    end
                    
                    // compare table 进行码长的判断
                    s2: 
                    begin
                        state     <= s3;
                        if(data_reg[31:16] < ram0[0])  
                                length<=1'b0;
                        else  if(data_reg[31:16] < ram0[1])  
                              length<=4'd1;
                        else  if(data_reg[31:16] < ram0[2])  
                              length<=4'd2;
                        else  if(data_reg[31:16] < ram0[3])  
                              length<=4'd3;
                        else  if(data_reg[31:16] < ram0[4]) 
                              length<=4'd4; 
                        else  if(data_reg[31:16] < ram0[5]) 
                              length<=4'd5; 
                        else  if(data_reg[31:16] < ram0[6])  
                              length<=4'd6;
                        else  if(data_reg[31:16] < ram0[7])  
                              length<=4'd7;
                        else  if(data_reg[31:16] < ram0[8])  
                              length<=4'd8;
                        else  if(data_reg[31:16] < ram0[9])  
                              length<=4'd9;
                        else  if(data_reg[31:16] < ram0[10]) 
                              length<=4'd10;
                        else  if(data_reg[31:16] < ram0[11]) 
                              length<=4'd11;
                        else  if(data_reg[31:16] < ram0[12]) 
                              length<=4'd12;
                        else  if(data_reg[31:16] < ram0[13]) 
                              length<=4'd13;
                        else  if(data_reg[31:16] < ram0[14]) 
                              length<=4'd14;
                        else  if(data_reg[31:16] < ram0[15]) 
                              length<=4'd15;
                        else  
                              length<=4'd16;                          
                    end
                    
                    // 找出同等长度的码字的最小编码和首地址
                    s3:
                    begin
                        state <= s4;
                        case (length)
                            1: 
                              begin
                                mincode     <= {15'h0000,ram0[0][15]};//同等长度的最小的码字
                                mincodeaddr <= ram1[0];              //同等码长的最小码字存储地址
                                data_number  <= {15'h0000,data_reg[31]};//数据
                                data_reg <= {data_reg[30:0],1'b0};     //把判断码长的那不部分移植出去
                            end
                            2: begin
                                mincode     <= {14'h0000,ram0[1][15:14]};
                                mincodeaddr <= ram1[1];
                                data_number  <= {14'h0000,data_reg[31:30]};
                                data_reg <= {data_reg[29:0],2'b00};
                            end
                            3: begin
                                mincode     <= {13'h0000,ram0[2][15:13]};
                                mincodeaddr <= ram1[2];
                                data_number  <= {13'h0000,data_reg[31:29]};
                                data_reg <= {data_reg[28:0],3'b000};
                            end
                            4: begin
                                mincode     <= {12'h000,ram0[3][15:12]};
                                mincodeaddr <= ram1[3];
                                data_number  <= {12'h000,data_reg[31:28]};
                                data_reg <= {data_reg[27:0],4'h0};
                            end
                            5: begin
                                mincode     <= {11'h000,ram0[4][15:11]};
                                mincodeaddr <= ram1[4];
                                data_number  <= {11'h000,data_reg[31:27]};
                                data_reg <= {data_reg[26:0],5'h00};
                            end
                            6: begin
                                mincode     <= {10'h000,ram0[5][15:10]};
                                mincodeaddr <= ram1[5];
                                data_number  <= {10'h000,data_reg[31:26]};
                                data_reg <= {data_reg[25:0],6'h00};
                            end
                            7: begin
                                mincode     <= {9'h000,ram0[6][15:9]};
                                mincodeaddr <= ram1[6];
                                data_number  <= {9'h000,data_reg[31:25]};
                                data_reg <= {data_reg[24:0],7'h00};
                            end
                            8: begin
                                mincode     <= {8'h00,ram0[7][15:8]};
                                mincodeaddr <= ram1[7];
                                data_number  <= {8'h00,data_reg[31:24]};
                                data_reg <= {data_reg[23:0],8'h00};
                            end
                            9: begin
                                mincode     <= {7'h00,ram0[8][15:7]};
                                mincodeaddr <= ram1[8];
                                data_number  <= {7'h00,data_reg[31:23]};
                                data_reg <= {data_reg[22:0],9'h000};
                            end
                            10: begin
                                mincode     <= {6'h00,ram0[9][15:6]};
                                mincodeaddr <= ram1[9];
                                data_number  <= {6'h00,data_reg[31:22]};
                                data_reg <= {data_reg[21:0],10'h000};
                            end
                            11: begin
                                mincode     <= {5'h00,ram0[10][15:5]};
                                mincodeaddr <= ram1[10];
                                data_number  <= {5'h00,data_reg[31:21]};
                                data_reg <= {data_reg[20:0],11'h000};
                            end
                            12: begin
                                mincode     <= {4'h0,ram0[11][15:4]};
                                mincodeaddr <= ram1[11];
                                data_number  <= {4'h0,data_reg[31:20]};
                                data_reg <= {data_reg[19:0],12'h000};
                            end
                            14: begin
                                mincode     <= {3'h0,ram0[12][15:3]};
                                mincodeaddr <= ram1[12];
                                data_number  <= {3'h0,data_reg[31:19]};
                                data_reg <= {data_reg[18:0],13'h0000};
                            end
                            14: begin
                                mincode     <= {2'h0,ram0[13][15:2]};
                                mincodeaddr <= ram1[13];
                                data_number  <= {2'h0,data_reg[31:18]};
                                data_reg <= {data_reg[17:0],14'h0000};
                            end
                            15: begin
                                mincode     <= {1'h0,ram0[14][15:1]};
                                mincodeaddr <= ram1[14];
                                data_number  <= {1'h0,data_reg[31:17]};
                                data_reg <= {data_reg[16:0],15'h0000};
                            end
                            16: begin
                                mincode     <= ram0[15];
                                mincodeaddr <= ram1[15];
                                data_number  <= data_reg[31:16] ;
                                data_reg <= {data_reg[15:0],16'h0000};
                            end
                        endcase
                    end
    
                    s4:
                    if (zig_zagIDLE)
                      state<=s5;
                      
                    s5:
                     begin
                        state     <= s6;
                        out_zero     <= dhtrd_zero;         //0 的个数
                        use_width_r    <= length+dhtrd_width ;//本次消耗的代码的长度
                        if(state_count == 0)            //第一个数据
                        begin
                            out_en   <= 1'b1;
                        end 
                        else 
                        begin
                            if(dhtrd_zero == 4'h0 & dhtrd_width == 4'h0) 
                            begin
                                state_count    <= 6'd63;
                                out_en       <= 1'b0;
                            end 
                            else 
                            if(dhtrd_zero == 4'hF & dhtrd_width == 4'h0)
                             begin
                                state_count    <= state_count + 6'd15;
                                out_en      <= 1'b0;
                            end 
                            else
                             begin
                                state_count    <= state_count + dhtrd_zero;
                                out_en      <= 1'b1;
                            end
                        end
                          
                        if(data_reg[31] == 1'b0 & dhtrd_width != 0) //判断符号
                        begin
                            code_value <= (code_value_p | sub_code) + 16'h0001;
                        end else begin
                            code_value <= code_value_p;
                        end
                    end
                    
                    //对DC系数解码
                    s6:
                     begin
                        state <= s7;
                        if(state_count == 0)
                         begin
                            if(state_color[2] == 1'b0)//Y:直流系数与前个系数相加的结果
                            begin
                                code_value   <= code_value + pre_data[0][15:0];
                                pre_data[0]  <= code_value + pre_data[0];
                            end 
                            else 
                            begin
                                if(state_color[0] == 1'b0) //CB:直流系数与前个系数相加的结果
                                begin
                                    code_value   <= code_value + pre_data[1][15:0];
                                    pre_data[1]  <= code_value + pre_data[1];
                                end 
                                else                          //CR:直流系数与前个系数相加的结果
                                begin
                                    code_value   <= code_value + pre_data[2][15:0];
                                    pre_data[2]  <= code_value + pre_data[2];
                                end
                            end
                        end
                    end
                    
                    s7: 
                    begin
                        out_en <= 1'b0;
                        if(state_count <6'd63) begin
                            state         <= s1;
                            state_count    <= state_count +6'd1;
                        end else begin
                            state_count  <= 6'd0;
                            if(state_color == 5) begin
                                state_color    <= 3'b000;
                                state         <= s1;
                            end else begin
                                state         <= s1;
                                state_color    <= state_color +3'd1;
                            end
                        end
                    end
                endcase
            end
        end
        
        assign dhtrd_color[1]      = state_color[2];
        assign dhtrd_color[0]      = state_count != 6'd0;
        assign dhtrd_addr        = data_number - mincode + mincodeaddr;
    
        assign dqtrd_color         = state_color[2];
        assign dqtrd_addr        = state_count[5:0];
    
        assign use_bit     = state == s6;
    
        assign dataout_en     = (out_en == 1'b1 & state == s7);
        assign dataout_count      = state_count;
        assign dataout       = dqtrd_data * code_value;
        assign use_width=use_width_r;
        assign unit_en    = (state == s7) & (state_count == 6'd63);
    
    endmodule
    

     

     

    ram
    //huffman 存储器,一个用于存储最小的编码,一个用于存储最小编码对应的首地址
    reg [15:0] ram0_Y_DC [0:15];
    reg [15:0] ram0_Y_AC [0:15];
    reg [15:0] ram0_C_DC [0:15];
    reg [15:0] ram0_C_AC [0:15];

    reg [7:0] ram1_Y_DC [0:15];
    reg [7:0] ram1_Y_AC [0:15];
    reg [7:0] ram1_C_DC [0:15];
    reg [7:0] ram1_C_AC [0:15];

    always @(posedge clk or negedge rst_n)
    begin
    if(!rst_n)
    begin
    ram0_Y_DC[0 ]<=16'd0;
    ram0_Y_DC[1 ]<=16'd0;
    ram0_Y_DC[2 ]<=16'd0;
    ram0_Y_DC[3 ]<=16'd0;
    ram0_Y_DC[4 ]<=16'd0;
    ram0_Y_DC[5 ]<=16'd0;
    ram0_Y_DC[6 ]<=16'd0;
    ram0_Y_DC[7 ]<=16'd0;
    ram0_Y_DC[8 ]<=16'd0;
    ram0_Y_DC[9 ]<=16'd0;
    ram0_Y_DC[10]<=16'd0;
    ram0_Y_DC[11]<=16'd0;
    ram0_Y_DC[12]<=16'd0;
    ram0_Y_DC[13]<=16'd0;
    ram0_Y_DC[14]<=16'd0;
    ram0_Y_DC[15]<=16'd0;

    ram0_Y_AC[0 ]<=16'd0;
    ram0_Y_AC[1 ]<=16'd0;
    ram0_Y_AC[2 ]<=16'd0;
    ram0_Y_AC[3 ]<=16'd0;
    ram0_Y_AC[4 ]<=16'd0;
    ram0_Y_AC[5 ]<=16'd0;
    ram0_Y_AC[6 ]<=16'd0;
    ram0_Y_AC[7 ]<=16'd0;
    ram0_Y_AC[8 ]<=16'd0;
    ram0_Y_AC[9 ]<=16'd0;
    ram0_Y_AC[10]<=16'd0;
    ram0_Y_AC[11]<=16'd0;
    ram0_Y_AC[12]<=16'd0;
    ram0_Y_AC[13]<=16'd0;
    ram0_Y_AC[14]<=16'd0;
    ram0_Y_AC[15]<=16'd0;

    ram0_C_DC[0 ]<=16'D0;
    ram0_C_DC[1 ]<=16'D0;
    ram0_C_DC[2 ]<=16'D0;
    ram0_C_DC[3 ]<=16'D0;
    ram0_C_DC[4 ]<=16'D0;
    ram0_C_DC[5 ]<=16'D0;
    ram0_C_DC[6 ]<=16'D0;
    ram0_C_DC[7 ]<=16'D0;
    ram0_C_DC[8 ]<=16'D0;
    ram0_C_DC[9 ]<=16'D0;
    ram0_C_DC[10]<=16'D0;
    ram0_C_DC[11]<=16'D0;
    ram0_C_DC[12]<=16'D0;
    ram0_C_DC[13]<=16'D0;
    ram0_C_DC[14]<=16'D0;
    ram0_C_DC[15]<=16'D0;

    ram0_C_AC[0 ]<=16'd0;
    ram0_C_AC[1 ]<=16'd0;
    ram0_C_AC[2 ]<=16'd0;
    ram0_C_AC[3 ]<=16'd0;
    ram0_C_AC[4 ]<=16'd0;
    ram0_C_AC[5 ]<=16'd0;
    ram0_C_AC[6 ]<=16'd0;
    ram0_C_AC[7 ]<=16'd0;
    ram0_C_AC[8 ]<=16'd0;
    ram0_C_AC[9 ]<=16'd0;
    ram0_C_AC[10]<=16'd0;
    ram0_C_AC[11]<=16'd0;
    ram0_C_AC[12]<=16'd0;
    ram0_C_AC[13]<=16'd0;
    ram0_C_AC[14]<=16'd0;
    ram0_C_AC[15]<=16'd0;

    ram1_Y_DC[0 ]<=8'd0;
    ram1_Y_DC[1 ]<=8'd0;
    ram1_Y_DC[2 ]<=8'd0;
    ram1_Y_DC[3 ]<=8'd0;
    ram1_Y_DC[4 ]<=8'd0;
    ram1_Y_DC[5 ]<=8'd0;
    ram1_Y_DC[6 ]<=8'd0;
    ram1_Y_DC[7 ]<=8'd0;
    ram1_Y_DC[8 ]<=8'd0;
    ram1_Y_DC[9 ]<=8'd0;
    ram1_Y_DC[10]<=8'd0;
    ram1_Y_DC[11]<=8'd0;
    ram1_Y_DC[12]<=8'd0;
    ram1_Y_DC[13]<=8'd0;
    ram1_Y_DC[14]<=8'd0;
    ram1_Y_DC[15]<=8'd0;

    ram1_Y_AC[0 ]<=8'd0;
    ram1_Y_AC[1 ]<=8'd0;
    ram1_Y_AC[2 ]<=8'd0;
    ram1_Y_AC[3 ]<=8'd0;
    ram1_Y_AC[4 ]<=8'd0;
    ram1_Y_AC[5 ]<=8'd0;
    ram1_Y_AC[6 ]<=8'd0;
    ram1_Y_AC[7 ]<=8'd0;
    ram1_Y_AC[8 ]<=8'd0;
    ram1_Y_AC[9 ]<=8'd0;
    ram1_Y_AC[10]<=8'd0;
    ram1_Y_AC[11]<=8'd0;
    ram1_Y_AC[12]<=8'd0;
    ram1_Y_AC[13]<=8'd0;
    ram1_Y_AC[14]<=8'd0;
    ram1_Y_AC[15]<=8'd0;

    ram1_C_DC[0 ]<=8'D0;
    ram1_C_DC[1 ]<=8'D0;
    ram1_C_DC[2 ]<=8'D0;
    ram1_C_DC[3 ]<=8'D0;
    ram1_C_DC[4 ]<=8'D0;
    ram1_C_DC[5 ]<=8'D0;
    ram1_C_DC[6 ]<=8'D0;
    ram1_C_DC[7 ]<=8'D0;
    ram1_C_DC[8 ]<=8'D0;
    ram1_C_DC[9 ]<=8'D0;
    ram1_C_DC[10]<=8'D0;
    ram1_C_DC[11]<=8'D0;
    ram1_C_DC[12]<=8'D0;
    ram1_C_DC[13]<=8'D0;
    ram1_C_DC[14]<=8'D0;
    ram1_C_DC[15]<=8'D0;

    ram1_C_AC[0 ]<=8'd0;
    ram1_C_AC[1 ]<=8'd0;
    ram1_C_AC[2 ]<=8'd0;
    ram1_C_AC[3 ]<=8'd0;
    ram1_C_AC[4 ]<=8'd0;
    ram1_C_AC[5 ]<=8'd0;
    ram1_C_AC[6 ]<=8'd0;
    ram1_C_AC[7 ]<=8'd0;
    ram1_C_AC[8 ]<=8'd0;
    ram1_C_AC[9 ]<=8'd0;
    ram1_C_AC[10]<=8'd0;
    ram1_C_AC[11]<=8'd0;
    ram1_C_AC[12]<=8'd0;
    ram1_C_AC[13]<=8'd0;
    ram1_C_AC[14]<=8'd0;
    ram1_C_AC[15]<=8'd0;
    end

    else
    begin
    if(huffman_en ==2'b1) //选择table类型和设置数据
    begin
    if(huffman_color ==2'b00) //Y_DC
    begin
    ram0_Y_DC[huffman_count] <= huffman_mincode;
    ram1_Y_DC[huffman_count] <= huffman_mincodeaddr;
    end
    else if(huffman_color ==2'b01) //Y_AC
    begin
    ram0_Y_AC[huffman_count] <= huffman_mincode;
    ram1_Y_AC[huffman_count] <= huffman_mincodeaddr;
    end
    else if(huffman_color ==2'b10) //C_DC
    begin
    ram0_C_DC[huffman_count] <= huffman_mincode;
    ram1_C_DC[huffman_count] <= huffman_mincodeaddr;
    end else
    begin //C_AC
    ram0_C_AC[huffman_count] <= huffman_mincode;
    ram1_C_AC[huffman_count] <= huffman_mincodeaddr;
    end
    end
    end
    end

     

    对需要用到的存储器声明,其中ram0是存放最小编码的码字,ram1是存放最小编码的地址,根据输入的数据的不同选择对应的ram。

    这里声明8个ram为4对,即亮度直流存储器,亮度交流存储器,色度直流存储器,色度交流存储器。

     

    IDLE
            //准备状态
    Idle:
    begin
    if(image_en == 1'b1) //开始解码
    state <= s1;
    else //设置DC的初始值
    begin
    pre_data[0] <= 32'h00000000;
    pre_data[1] <= 32'h00000000;
    pre_data[2] <= 32'h00000000;
    end
    out_en <= 1'b0;
    state_color <= 3'b000;
    state_count <= 6'd0;
    end

     

    就绪状态:当FSM模块读到SOS标记表示开始解码。转入下个状态。与此同时设置3个DC系数的初值。因为DC采用的是DPCM编码是一种差分编码,对于第一个DC系数保存其值,对于以后的每个DC系数不保存他的值而是保存他与前个系数的差值,所以在解码到DC系数时应加上前一个DC系数的值,但是第一个DC系数时没有前一个值的所以这里初始化3个寄存器为0,pre_data.他们分别保存的为Y,CB,CR的DC差值。

     

    S1
                  //从数据读入模块读入32位需要解码的数据。判断此次解
    //数据是DC数据还是AC数据,同时选择相应的码表
    s1:
    begin
    if(image_en == 1'b0)
    begin
    state <= Idle;
    end
    else
    if(datain_en == 1'b1 & zig_zagIDLE == 1'b1)//输入数据使能,并且zig_zag存储器空闲
    begin
    state <= s2;
    data_reg <= datain;
    end
    out_en <= 1'b0;
    if(state_color[2] == 1'b0) //此时解码的为亮度数据
    begin
    if(state_count == 0)//此时解码的为DC数据
    begin
    ram0[0] <= ram0_Y_DC[0];
    ram1[0] <= ram1_Y_DC[0];
    ram0[1] <= ram0_Y_DC[1];
    ram1[1] <= ram1_Y_DC[1];
    ram0[2] <= ram0_Y_DC[2];
    ram1[2] <= ram1_Y_DC[2];
    ram0[3] <= ram0_Y_DC[3];
    ram1[3] <= ram1_Y_DC[3];
    ram0[4] <= ram0_Y_DC[4];
    ram1[4] <= ram1_Y_DC[4];
    ram0[5] <= ram0_Y_DC[5];
    ram1[5] <= ram1_Y_DC[5];
    ram0[6] <= ram0_Y_DC[6];
    ram1[6] <= ram1_Y_DC[6];
    ram0[7] <= ram0_Y_DC[7];
    ram1[7] <= ram1_Y_DC[7];
    ram0[8] <= ram0_Y_DC[8];
    ram1[8] <= ram1_Y_DC[8];
    ram0[9] <= ram0_Y_DC[9];
    ram1[9] <= ram1_Y_DC[9];
    ram0[10] <= ram0_Y_DC[10];
    ram1[10] <= ram1_Y_DC[10];
    ram0[11] <= ram0_Y_DC[11];
    ram1[11] <= ram1_Y_DC[11];
    ram0[12] <= ram0_Y_DC[12];
    ram1[12] <= ram1_Y_DC[12];
    ram0[13] <= ram0_Y_DC[13];
    ram1[13] <= ram1_Y_DC[13];
    ram0[14] <= ram0_Y_DC[14];
    ram1[14] <= ram1_Y_DC[14];
    ram0[15] <= ram0_Y_DC[15];
    ram1[15] <= ram1_Y_DC[15];
    end
    else //此时解码的为AC数据
    begin
    ram0[0] <= ram0_Y_AC[0];
    ram1[0] <= ram1_Y_AC[0];
    ram0[1] <= ram0_Y_AC[1];
    ram1[1] <= ram1_Y_AC[1];
    ram0[2] <= ram0_Y_AC[2];
    ram1[2] <= ram1_Y_AC[2];
    ram0[3] <= ram0_Y_AC[3];
    ram1[3] <= ram1_Y_AC[3];
    ram0[4] <= ram0_Y_AC[4];
    ram1[4] <= ram1_Y_AC[4];
    ram0[5] <= ram0_Y_AC[5];
    ram1[5] <= ram1_Y_AC[5];
    ram0[6] <= ram0_Y_AC[6];
    ram1[6] <= ram1_Y_AC[6];
    ram0[7] <= ram0_Y_AC[7];
    ram1[7] <= ram1_Y_AC[7];
    ram0[8] <= ram0_Y_AC[8];
    ram1[8] <= ram1_Y_AC[8];
    ram0[9] <= ram0_Y_AC[9];
    ram1[9] <= ram1_Y_AC[9];
    ram0[10] <= ram0_Y_AC[10];
    ram1[10] <= ram1_Y_AC[10];
    ram0[11] <= ram0_Y_AC[11];
    ram1[11] <= ram1_Y_AC[11];
    ram0[12] <= ram0_Y_AC[12];
    ram1[12] <= ram1_Y_AC[12];
    ram0[13] <= ram0_Y_AC[13];
    ram1[13] <= ram1_Y_AC[13];
    ram0[14] <= ram0_Y_AC[14];
    ram1[14] <= ram1_Y_AC[14];
    ram0[15] <= ram0_Y_AC[15];
    ram1[15] <= ram1_Y_AC[15];
    end
    end
    else //此时解码的为色度数据
    begin
    if(state_count == 0)//此时解码的为DC数据
    begin
    ram0[0] <= ram0_C_DC[0];
    ram1[0] <= ram1_C_DC[0];
    ram0[1] <= ram0_C_DC[1];
    ram1[1] <= ram1_C_DC[1];
    ram0[2] <= ram0_C_DC[2];
    ram1[2] <= ram1_C_DC[2];
    ram0[3] <= ram0_C_DC[3];
    ram1[3] <= ram1_C_DC[3];
    ram0[4] <= ram0_C_DC[4];
    ram1[4] <= ram1_C_DC[4];
    ram0[5] <= ram0_C_DC[5];
    ram1[5] <= ram1_C_DC[5];
    ram0[6] <= ram0_C_DC[6];
    ram1[6] <= ram1_C_DC[6];
    ram0[7] <= ram0_C_DC[7];
    ram1[7] <= ram1_C_DC[7];
    ram0[8] <= ram0_C_DC[8];
    ram1[8] <= ram1_C_DC[8];
    ram0[9] <= ram0_C_DC[9];
    ram1[9] <= ram1_C_DC[9];
    ram0[10] <= ram0_C_DC[10];
    ram1[10] <= ram1_C_DC[10];
    ram0[11] <= ram0_C_DC[11];
    ram1[11] <= ram1_C_DC[11];
    ram0[12] <= ram0_C_DC[12];
    ram1[12] <= ram1_C_DC[12];
    ram0[13] <= ram0_C_DC[13];
    ram1[13] <= ram1_C_DC[13];
    ram0[14] <= ram0_C_DC[14];
    ram1[14] <= ram1_C_DC[14];
    ram0[15] <= ram0_C_DC[15];
    ram1[15] <= ram1_C_DC[15];
    end
    else //此时解码的为AC数据
    begin
    ram0[0] <= ram0_C_AC[0];
    ram1[0] <= ram1_C_AC[0];
    ram0[1] <= ram0_C_AC[1];
    ram1[1] <= ram1_C_AC[1];
    ram0[2] <= ram0_C_AC[2];
    ram1[2] <= ram1_C_AC[2];
    ram0[3] <= ram0_C_AC[3];
    ram1[3] <= ram1_C_AC[3];
    ram0[4] <= ram0_C_AC[4];
    ram1[4] <= ram1_C_AC[4];
    ram0[5] <= ram0_C_AC[5];
    ram1[5] <= ram1_C_AC[5];
    ram0[6] <= ram0_C_AC[6];
    ram1[6] <= ram1_C_AC[6];
    ram0[7] <= ram0_C_AC[7];
    ram1[7] <= ram1_C_AC[7];
    ram0[8] <= ram0_C_AC[8];
    ram1[8] <= ram1_C_AC[8];
    ram0[9] <= ram0_C_AC[9];
    ram1[9] <= ram1_C_AC[9];
    ram0[10] <= ram0_C_AC[10];
    ram1[10] <= ram1_C_AC[10];
    ram0[11] <= ram0_C_AC[11];
    ram1[11] <= ram1_C_AC[11];
    ram0[12] <= ram0_C_AC[12];
    ram1[12] <= ram1_C_AC[12];
    ram0[13] <= ram0_C_AC[13];
    ram1[13] <= ram1_C_AC[13];
    ram0[14] <= ram0_C_AC[14];
    ram1[14] <= ram1_C_AC[14];
    ram0[15] <= ram0_C_AC[15];
    ram1[15] <= ram1_C_AC[15];
    end
    end
    end

    S1状态是对存储器的选择,解码到不同的数据时候把他对应的存储器的值搬运到解码用到的存储器中,方便使用。当反量化模块处于空闲时,转入下个状态。

     

    S2
                    
    // compare table 进行码长的判断
    s2:
    begin
    state <= s3;
    if(data_reg[31:16] < ram0[0])
    length<=1'b0;
    else if(data_reg[31:16] < ram0[1])
    length<=4'd1;
    else if(data_reg[31:16] < ram0[2])
    length<=4'd2;
    else if(data_reg[31:16] < ram0[3])
    length<=4'd3;
    else if(data_reg[31:16] < ram0[4])
    length<=4'd4;
    else if(data_reg[31:16] < ram0[5])
    length<=4'd5;
    else if(data_reg[31:16] < ram0[6])
    length<=4'd6;
    else if(data_reg[31:16] < ram0[7])
    length<=4'd7;
    else if(data_reg[31:16] < ram0[8])
    length<=4'd8;
    else if(data_reg[31:16] < ram0[9])
    length<=4'd9;
    else if(data_reg[31:16] < ram0[10])
    length<=4'd10;
    else if(data_reg[31:16] < ram0[11])
    length<=4'd11;
    else if(data_reg[31:16] < ram0[12])
    length<=4'd12;
    else if(data_reg[31:16] < ram0[13])
    length<=4'd13;
    else if(data_reg[31:16] < ram0[14])
    length<=4'd14;
    else if(data_reg[31:16] < ram0[15])
    length<=4'd15;
    else
    length<=4'd16;
    end


    S2状态是对码长的判断,对每个不同长度的最小编码进行比较,找到解码数据的长度。例如:判断码长是否为1,先拿解码的最高位与长度为1的最小编码比较,若小于最小编码,则长度为0,如大于最小编码则长度>=1。再判断码长是否为2,拿解码的高2位与长度为2的最小编码比较,若小于最小编码则长度为1,若大于最小编码则长度>=2,以此类推,知道找到码长。

    S3
                   // 找出同等长度的码字的最小编码和首地址
    s3:
    begin
    state <= s4;
    case (length)
    1:
    begin
    mincode <= {15'h0000,ram0[0][15]};//同等长度的最小的码字
    mincodeaddr <= ram1[0]; //同等码长的最小码字存储地址
    data_number <= {15'h0000,data_reg[31]};//数据
    data_reg <= {data_reg[30:0],1'b0}; //把判断码长的那不部分移植出去
    end
    2: begin
    mincode <= {14'h0000,ram0[1][15:14]};
    mincodeaddr <= ram1[1];
    data_number <= {14'h0000,data_reg[31:30]};
    data_reg <= {data_reg[29:0],2'b00};
    end
    3: begin
    mincode <= {13'h0000,ram0[2][15:13]};
    mincodeaddr <= ram1[2];
    data_number <= {13'h0000,data_reg[31:29]};
    data_reg <= {data_reg[28:0],3'b000};
    end
    4: begin
    mincode <= {12'h000,ram0[3][15:12]};
    mincodeaddr <= ram1[3];
    data_number <= {12'h000,data_reg[31:28]};
    data_reg <= {data_reg[27:0],4'h0};
    end
    5: begin
    mincode <= {11'h000,ram0[4][15:11]};
    mincodeaddr <= ram1[4];
    data_number <= {11'h000,data_reg[31:27]};
    data_reg <= {data_reg[26:0],5'h00};
    end
    6: begin
    mincode <= {10'h000,ram0[5][15:10]};
    mincodeaddr <= ram1[5];
    data_number <= {10'h000,data_reg[31:26]};
    data_reg <= {data_reg[25:0],6'h00};
    end
    7: begin
    mincode <= {9'h000,ram0[6][15:9]};
    mincodeaddr <= ram1[6];
    data_number <= {9'h000,data_reg[31:25]};
    data_reg <= {data_reg[24:0],7'h00};
    end
    8: begin
    mincode <= {8'h00,ram0[7][15:8]};
    mincodeaddr <= ram1[7];
    data_number <= {8'h00,data_reg[31:24]};
    data_reg <= {data_reg[23:0],8'h00};
    end
    9: begin
    mincode <= {7'h00,ram0[8][15:7]};
    mincodeaddr <= ram1[8];
    data_number <= {7'h00,data_reg[31:23]};
    data_reg <= {data_reg[22:0],9'h000};
    end
    10: begin
    mincode <= {6'h00,ram0[9][15:6]};
    mincodeaddr <= ram1[9];
    data_number <= {6'h00,data_reg[31:22]};
    data_reg <= {data_reg[21:0],10'h000};
    end
    11: begin
    mincode <= {5'h00,ram0[10][15:5]};
    mincodeaddr <= ram1[10];
    data_number <= {5'h00,data_reg[31:21]};
    data_reg <= {data_reg[20:0],11'h000};
    end
    12: begin
    mincode <= {4'h0,ram0[11][15:4]};
    mincodeaddr <= ram1[11];
    data_number <= {4'h0,data_reg[31:20]};
    data_reg <= {data_reg[19:0],12'h000};
    end
    14: begin
    mincode <= {3'h0,ram0[12][15:3]};
    mincodeaddr <= ram1[12];
    data_number <= {3'h0,data_reg[31:19]};
    data_reg <= {data_reg[18:0],13'h0000};
    end
    14: begin
    mincode <= {2'h0,ram0[13][15:2]};
    mincodeaddr <= ram1[13];
    data_number <= {2'h0,data_reg[31:18]};
    data_reg <= {data_reg[17:0],14'h0000};
    end
    15: begin
    mincode <= {1'h0,ram0[14][15:1]};
    mincodeaddr <= ram1[14];
    data_number <= {1'h0,data_reg[31:17]};
    data_reg <= {data_reg[16:0],15'h0000};
    end
    16: begin
    mincode <= ram0[15];
    mincodeaddr <= ram1[15];
    data_number <= data_reg[31:16] ;
    data_reg <= {data_reg[15:0],16'h0000};
    end
    endcase
    end

    S3状态是找到与解码数据同长度的最小编码和最小编码的地址,从而解出DHT表的地址,方法为:解码数据-最小编码+最小编码的地址(data_number-mincode+mincodeaddr)

    S4
                    s4:
    if (zig_zagIDLE)
    state<=s5;

    s4状态为过渡状态。

     

    S5
                   s5:
    begin
    state <= s6;
    out_zero <= dhtrd_zero; //0 的个数
    use_width_r <= length+dhtrd_width ;//本次消耗的代码的长度
    if(state_count == 0) //第一个数据
    begin
    out_en <= 1'b1;
    end
    else
    begin
    if(dhtrd_zero == 4'h0 & dhtrd_width == 4'h0)
    begin
    state_count <= 6'd63;
    out_en <= 1'b0;
    end
    else
    if(dhtrd_zero == 4'hF & dhtrd_width == 4'h0)
    begin
    state_count <= state_count + 6'd15;
    out_en <= 1'b0;
    end
    else
    begin
    state_count <= state_count + dhtrd_zero;
    out_en <= 1'b1;
    end
    end

    if(data_reg[31] == 1'b0 & dhtrd_width != 0) //判断符号
    begin
    code_value <= (code_value_p | sub_code) + 16'h0001;
    end else begin
    code_value <= code_value_p;
    end
    end


    S5状态是对解码数据的符号的判断,huffman编码负数的表示与正常的表示方法不一样,例如:10编为1010,-10变为0101,正数和负数互为取反,所以在解到负数的时候要转化过来,我们知道-10在计算机中保存为 1...110(1010取反加1),为了得到正确的结果,若解码到负数,则把负数的高位设置为1,然后再加一,(code_value <= (code_value_p | sub_code) + 16'h0001),0101高位设为1变为1...101,再加上1,变为1...110,和上面结果一样,在Verilog里面定义了两个函数来实现上述操作,如下:

    function
    function [15:0] value_sel;
    input [3:0] dhtrd_width;
    input [31:0] data_reg;
    begin
    case (dhtrd_width)
    4'h0: value_sel = 16'h0000;
    4'h1: value_sel = {15'h0000, data_reg[31]};
    4'h2: value_sel = {14'h0000, data_reg[31:30]};
    4'h3: value_sel = {13'h0000, data_reg[31:29]};
    4'h4: value_sel = {12'h000, data_reg[31:28]};
    4'h5: value_sel = {11'h000, data_reg[31:27]};
    4'h6: value_sel = {10'h000, data_reg[31:26]};
    4'h7: value_sel = {9'h000, data_reg[31:25]};
    4'h8: value_sel = {8'h00, data_reg[31:24]};
    4'h9: value_sel = {7'h00, data_reg[31:23]};
    4'hA: value_sel = {6'h00, data_reg[31:22]};
    4'hB: value_sel = {5'h00, data_reg[31:21]};
    4'hC: value_sel = {4'h0, data_reg[31:20]};
    4'hD: value_sel = {3'h0, data_reg[31:19]};
    4'hE: value_sel = {2'h0, data_reg[31:18]};
    4'hF: value_sel = {1'h0, data_reg[31:17]};
    endcase
    end
    endfunction
    assign code_value_p = value_sel(dhtrd_width, data_reg);

    function [15:0] subcode_sel;
    input [3:0] dhtrd_width;
    begin
    case (dhtrd_width)
    4'h0: subcode_sel = 16'hFFFF;
    4'h1: subcode_sel = 16'hFFFE;
    4'h2: subcode_sel = 16'hFFFC;
    4'h3: subcode_sel = 16'hFFF8;
    4'h4: subcode_sel = 16'hFFF0;
    4'h5: subcode_sel = 16'hFFE0;
    4'h6: subcode_sel = 16'hFFC0;
    4'h7: subcode_sel = 16'hFF80;
    4'h8: subcode_sel = 16'hFF00;
    4'h9: subcode_sel = 16'hFE00;
    4'hA: subcode_sel = 16'hFC00;
    4'hB: subcode_sel = 16'hF800;
    4'hC: subcode_sel = 16'hF000;
    4'hD: subcode_sel = 16'hE000;
    4'hE: subcode_sel = 16'hC000;
    4'hF: subcode_sel = 16'h8000;
    endcase
    end
    endfunction
    assign sub_code = subcode_sel(dhtrd_width);


    第一个函数是取有效的编码,第二个函数是对编码的高位置1处理,只有编码为负数才用到,具体操作为:若编码的有效长度为3,则第一个函数是取数据的高三位存到32位寄存器中(本设计中数据是32位传输)的低3位,高位为0,函数2是把高29为置1,低3位置0,如编码为负数,则函数一与函数而相或操作即可实现功能。

     

    S6
                   //对DC系数解码
    s6:
    begin
    state <= s7;
    if(state_count == 0)
    begin
    if(state_color[2] == 1'b0)//Y:直流系数与前个系数相加的结果
    begin
    code_value <= code_value + pre_data[0][15:0];
    pre_data[0] <= code_value + pre_data[0];
    end
    else
    begin
    if(state_color[0] == 1'b0) //CB:直流系数与前个系数相加的结果
    begin
    code_value <= code_value + pre_data[1][15:0];
    pre_data[1] <= code_value + pre_data[1];
    end
    else //CR:直流系数与前个系数相加的结果
    begin
    code_value <= code_value + pre_data[2][15:0];
    pre_data[2] <= code_value + pre_data[2];
    end
    end
    end
    end

    S6是对DC系数进行DPCM解码,实际的DC系数为本次解到的DC系数与上次的DC系数相加的结果,并且保存本次实际的DC系数。

     

    S7
                   
    s7:
    begin
    out_en <= 1'b0;
    if(state_count <6'd63) begin
    state <= s1;
    state_count <= state_count +6'd1;
    end else begin
    state_count <= 6'd0;
    if(state_color == 5) begin
    state_color <= 3'b000;
    state <= s1;
    end else begin
    state <= s1;
    state_color <= state_color +3'd1;
    end
    end
    end

    S7是最后一个状态,对各个计数器的值进行设置。

    View Code
     1   assign dhtrd_color[1]      = state_color[2];
    2 assign dhtrd_color[0] = state_count != 6'd0;
    3 assign dhtrd_addr = data_number - mincode + mincodeaddr;
    4
    5 assign dqtrd_color = state_color[2];
    6 assign dqtrd_addr = state_count[5:0];
    7
    8 assign use_bit = state == s6;
    9
    10 assign dataout_en = (out_en == 1'b1 & state == s7);
    11 assign dataout_count = state_count;
    12 assign dataout = dqtrd_data * code_value;
    13 assign use_width=use_width_r;
    14 assign unit_en = (state == s7) & (state_count == 6'd63);

    最后对各个端口赋值,13行即完成一次反量化,解码得到数据与量化表数据相乘即可得到。
     

    在这里提一下JPEG数据的流程:压缩比为4:1:1,即每次来6个数据块为一个为一个单元,每个数据块为8*8=64个数据,来的顺序为:Y,Y,Y,Y,CB,CR.其中每个Y,CB,CR都是64个数据。

     

    转载于:https://www.cnblogs.com/tony1224/archive/2012/03/18/2404268.html

    展开全文
  • 考虑到嵌入式设备资源的有限性,提出一种基于四叉树的Huffman解码优化算法.解码过程中,先将Huffman码表表示成四叉树结构,据此重建为一维数组,并充分利用数值计算代替判断与跳转操作.为测试本算法解码性能,将其应用于...
  • 基于硬件实现的huffman解码算法,由于一般的huffman解码算法不适于硬件实现本文特提出此算法
  • Huffman解码、编码

    2012-11-20 09:05:59
    定义Huffman树T并初始化T。提示手动输入文本文件或者加载已存在的文本文件,然后程序进入主菜单Main Menue(),根据输入的选择项调用相应的函数、实现相应的逻辑功能。
  • 表2,查此表可以对jpeg做解码: 序号 Bits位数 码字长度 码字 DHT权值 Size(数值bits宽度) Additionnal Bits (实际保存的数据) DC-value(DCT量化后的数据) 1 2bits 2 00 0x0 0x00 0 0 2 3bits 3 010 0x2 0x01 1 0 ...

    DHT Huffuman表格式

    --------------------------------------------------------------------------
    名称      字节数     值       说明
    --------------------------------------------------------------------------
    段标识       1        FF
    段类型       1        C4
    段长度       2                    其值=19+n(当只有一个HT表时)
      (以下为段内容)
    HT信息      1                    0-3位:HT号
                                                 4位: HT类型, 0=DC表,1=AC表
                     5-7位:必须=0
    HT位表      16                  这16个数的和应该≤256
    HT值表       n                   n=表头16个数的和
    --------------------------------------------------------------------------

    读取Huffman

    FF C4 01 A2 00 00 01 05 01 01 01 01 01 01 00 00 00 00 00 00 00 00 01 02 03 04 05 06 07 08 09 0A 0B

    FF C4:Huffman表识别码

    01 A2:DHT表长度(01~0B的字节数)

    00:4bit=0,为DC表;低3bit=0,HT号为0;表示DC直流0号表

    00 01 05 01 01 01 01 01 01 00 00 00 00 00 00 00:DHT不同bits位数的码字数量,数据之和表示叶子节点数目:1+5+1+1+1+1+1+1 = 12;

    00 01 02 03 04 05 06 07 08 09 0A 0B:编码内容,即每个叶子节点下的编码值

    构建Huffman

    读取到Huffman表的数据之后,就需要构建Huffman树了。其具体规则如下:

      (a)第一个编码的数字必定为0;如果第一个编码的位数为1,就被编码为0;如果第一个编码的位数为2,就被编码为00;如果第一个编码的位数为3,就被编码为000。。。

      (b)从第二个编码开始,如果它和它前面编码具有相同的位数,则当前编码是它前面的编码加1;如果它的编码位数比它前面的编码位数大,则当前编码时它前面的编码加1之后再在后面添加若干个0,直到满足编码位数的长度为止。

    还是以上面的数据00 01 05 01 01 01 01 01 01 00 00 00 00 00 00 00为例:

    第1个字节00表示没有位数为1的编码;

    第2个字节01表示位数为2的编码有2个;由于没有位数为1的编码,因此这里位数为2的编码中的第一个为00;

    第3个字节05表示位数为3的编码有5个;因此,这里位数为3的编码中的第一个为00+1=01,然后添加1个“0”,得到010;位数为3的编码中的第二个为010+1=011;第三个为011+1=100;第四个为100+1=101;第五个为101+1=110;

    第4个字节01表示位数为4的编码有1个;因此,这里位数为4的编码中的第一个为110+1=111,然后添加1个“0”,得到1110;

    第5个字节01表示位数为5的编码有1个;因此,这里位数为5的编码中的第一个为1110+1=1111,然后添加1个“0”,得到11110;

    依次类推,得到如下Huffman树,表1:

    Y(luminance亮度)-DC

     

    序号(bits位数)

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    相同Bits位的个数

    0

    1

    5

    1

    1

    1

    1

    1

    1

    0

    0

    0

    0

    0

    0

    0

    说明

    没有位数为1的编码

    1个2bits

    5个3bits

    1个4bits

    1个5bits

    1个6bits

    1个7bits

    1个8bits

    1个9bits

    没有位数为10的编码

    没有位数为11的编码

    没有位数为12的编码

    没有位数为13的编码

    没有位数为14的编码

    没有位数为15的编码

    没有位数为16的编码

    码字(二进制)

    00

    (00+1)<<1

    ==>

    010

    011

    100

    101

    110

    (110+1)<<1

    ==>

    1110

    (1110+1)<<1

    ==>

    1111 0

    (11110+1)<<1

    ==>

    1111 10

    (111110+1)<<1

    ==>

    1111 110

    (1111110+1)<<1

    ==>

    1111 1110

    (11111110+1)<<1

    ==>

    1111 1111 0

    根据Huffman树,建立DHT权值与实际保存数据与DCT量化后数据 表2,查此表可以对jpeg做解码:

    序号

    Bits位数

    码字长度

    码字

    DHT权值

    Size(数值bits宽度)

    Additionnal Bits

    (实际保存的数据)

    DC-value(DCT量化后的数据)

    1

    2bits

    2

    00

    0x0

    0x00

    0

    0

    2

    3bits

    3

    010

    0x2

    0x01

    1

    0

    1

    -1

    1

    3

    3

    011

    0x3

    0x02

    2

    00,01

    10,11

    -3,-2

    2,3

    4

    3

    100

    0x4

    0x03

    3

    000,001,010,011

    100,101,110,111

    -7,-6,-5,-4

    4,5,6,7

    5

    3

    101

    0x5

    0x04

    4

    0000,…,0111

    1000,…,1111

    -15,…,-8

    8,…,15

    6

    3

    110

    0x6

    0x05

    5

    0000 0,…,01111

    1000 0,…,11111

    -31,…,-16

    16,…,31

    7

    4bits

    4

    1110

    0xE

    0x06

    6

    0000 00,…,011111

    1000 00,…,111111

    -64,…,-32

    32,…,64

    8

    5bits

    5

    1111 0

    0x1E

    0x07

    7

    0000 000,…

    …,1111 111

    -127,…,-64

    64,…,127

    9

    6bits

    6

    1111 10

    0x3E

    0x08

    8

    0000 0000,…

    …,1111 1111

    -255,…,-128

    128,…,255

    A

    7bits

    7

    1111 110

    0x7E

    0x09

    9

    0000 0000 0,…

    …,1111 1111 1

    -511,…,-256

    256,…,511

    B

    8bits

    8

    1111 1111

    0xFE

    0x0A

    A

    0000 0000 00,…

    …,1111 1111 11

    -1023,…,-512

    512,…,1023

    C

    9bits

    9

    1111 1111 0

    0x1FE

    0x0B

    B

    0000 0000 000,…

    …,1111 1111 111

    -2047,…,-1024

    1024,…,2047

    高4bits:保留零的个数

    低4bits:接着的数据位长

    0n

    负数

    正数

    -(1<<(n+1)-1) ~ -(1<<n)

    (1<<n) ~ (1<<(n+1)-1)

    DHT权值表中,高4bit表示零保留的个数,低4bit表示接着的数据位长。

    Huffman:DC实际值 -> Size[编码长度] -> 权值 -> bitstring{.Len;   .value;}

    Encode: DC实际值 -> DQT量化 -> ZigZag扫描 ->(Y:DPCM编码,CbCr)->  huffman -> write

     

    根据Huffman系数,或者读取Huffman系数,重建Huffman表:

    static BYTE std_dc_luminance_nrcodes[17]={0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0};

    static BYTE std_dc_luminance_values[12]={0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};

    static BYTE std_dc_chrominance_nrcodes[17]={0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0};

    static BYTE std_dc_chrominance_values[12]={0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};

    static BYTE std_ac_luminance_nrcodes[17]={0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d };

    static BYTE std_ac_luminance_values[162]=

      { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa };

    static BYTE std_ac_chrominance_nrcodes[17]={0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77};

    static BYTE std_ac_chrominance_values[162]=

    { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa };

    依照上述重建Huffman表的方法,可得:

    DHT-Y-DC

    DHT-Y-AC

    DHT-CbCr-DC

    DHT-CbCr-AC

    序号

    相同Bits位数的:码字个数

    相同bits位数:码字起始

    相同bits位数:码字结束

    相同Bits位数的:码字个数

    相同bits位数:码字起始

    相同bits位数:码字结束

    相同Bits位数的:码字个数

    相同bits位数:码字起始

    相同bits位数:码字结束

    相同Bits位数的:码字个数

    相同bits位数:码字起始

    相同bits位数:码字结束

    1 

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    2

    1

    0

    0

    2

    0

    0x1

    3

    0

    0x2

    2

    0

    0x1

    3

    5

    0x2

    0x6

    1

    0x4

    0x4

    1

    0x6

    0x6

    1

    0x4

    0x4

    4

    1

    0xE

    0xE

    3

    0xA

    0xC

    1

    0xE

    0xE

    2

    0xA

    0xB

    5

    1

    0x1E

    0x1E

    3

    0x1A

    0x1C

    1

    0x1E

    0x1E

    4

    0x18

    0x1B

    6

    1

    0x3E

    0x3E

    2

    0x3A

    0x3B

    1

    0x3E

    0x3E

    4

    0x38

    0x3B

    7

    1

    0x7E

    0x7E

    4

    0x78

    0x7B

    1

    0x7E

    0x7E

    3

    0x78

    0x7A

    8

    1

    0xFE

    0xFE

    3

    0xF8

    0xFA

    1

    0xFE

    0xFE

    4

    0xF6

    0xF9

    9

    1

    0x1FE

    0x1FE

    5

    0x1F6

    0x1FA

    1

    0x1FE

    0x1FE

    7

    0x1F4

    0x1FA

    10

    0

    0

    0

    5

    0x3F6

    0x3FA

    1

    0x3FE

    0x3FE

    5

    0x3F6

    0x3FA

    11

    0

    0

    0

    4

    0x7F6

    0x7F9

    1

    0x7FE

    0x7FE

    4

    0x7F6

    0x7F9

    12

    0

    0

    0

    4

    0xFF4

    0xFF7

    0

    0

    0

    4

    0xFF4

    0xFF7

    13

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    14

    0

    0

    0

    0

    0

    0

    0

    0

    0

    1

    0x3FE0

     0x3FE0

    15

    0

    0

    0

    1

    0x7FC0

    0x7FC0

    0

    0

    0

    2

    0x7FC2

    0x7FC3

    此时,得到Huffman的size(码字bit位数)与code(相同bit位数的编码值)表。由此可进行Huffman的解码过程:

    1)        将待解码数据转换成二进制的数据流;

    2)        遍历表Huffman_size、Huffman_code,从待解码二进制数据流中寻找到长度与Huffman_size相等,内容与Huffman_code相等的二进制数据段,并记录下表的ID(即:是在表的第几个数据中寻找到的);

    3)        将此ID 值除以16,其商为cnt(指之前有cnt个0),其余数即为取数长度Len;

    4)        在二进制的数据流中,从与Huffman_code相同的数据流后,开始取数,取数长度为第3步得到的Len,假设取得的数据为data;

    5)        根据data的值,转换得到相应的解码数据de_data。(根据最高位,为1则为相应的数,为0则取反后的负值。例,data=100,则解码后数据de_data值为4;data=010,解码后数据de_data为-5;

    6)        写上de_data的值,并在前面添加上cnt个0。至此,解码完成。

    示例数据讲解

     长度01 A2后面的字节: 00 表示Y-DC, tablenum=0; 10表示Y-AC, tablenum=1;01表示Cb-DC,tablenum=2;11表示Cb-AC,tablenum=3;

    后面的数据依次是bits位数的个数表,bits位数表(码表);

    根据这个重建Huffman表,得到size与code表;

    DHT后面是SOS数据,实际的数据流从E2 E8 A2 8A F9 93 F7 开始

    Huffman解码时,每次读取32bit数据,此次前4字节数据为E2 E8 A2 8A,转换城二进制数据为:

    1110 0010 1110 1000 1010 0010 10000 1010

    首次编码的数据一定是Y-DC,所以这里可跟表2匹配:匹配二进制数据的长度与Huffman_size相等,内容与Huffman_code相等的二进制数据段,记录下Huffman的ID号,此时匹配上的1110, 码字长度为4,对应的DHT权值为6,即后面需要读取6 bits数据(001011)作为该组数据,对应的实际DCT量化后的数据值为-53。【(001011对应10进制数据为11) 故数据为:11- (1<<6)  ==> -53 】,此次计算共用的bit位数为4+6 = 10,所以下一组数据从偏移10bits开始,依次类推,可得出下如下数据:

    1110 0010 11    101 0001    010 0     010 1     0000 1010

    二进制数据1110 0010 11 101 0001010 0010 10000

    1010 后面读byte数据,补足32bit,再做Huffman解码,如:

    1010 (F9)(93) (F7)

    ...
    实际数值-53-14-1100...
    说明4bits码字,6bits数据3bits码字,4bits数据3bits码字,1bits数据3bits码字,1bits数据2bits数据...

    当数据长度不够时,可从后面读取byte的数据以填充,以补足32 bits数据做Huffman解码。 

     Y-AC,Cb-DC,Cb-AC也依次类推得到相应的数据值。

    展开全文
  • 题目链接 /* The structure of the node is typedef struct node { int freq; char data; node * left; node * right; }node; */ void decode_huff(node * root,string s) ... char str[50
  • JPEG中Huffman解码详解

    千次阅读 2014-06-05 21:18:26
    本文即是讲如何根据这两张表,对Huffman编码的数据进行解码。 二、解码过程 1) 将待解码数据转换成二进制的数据流; 2) 遍历表Huffman_size、Huffman_code,从待解码二进制数据流中寻找到长度与Huff
  • 1 不同标准中的huffman解码原理 1.1标准MP3的huffman解码原理 在MP3即mpeg-1 audio标准中,无噪声编码模块的输入是一组576个己量化的频谱数据。无噪声编码首先对频谱进行无噪声的动态范围压缩。编码模块最多可以...
  • 为了提高Huffman解码的效率和实时性,采用并行处理技术和改进的Huffman并行解码算法,设计基于现场可编程门阵列FPGA的Huffman并行解码器。在不考虑Huffman编码长度的情况下,解码器通过插入流水线结构的方法将...
  • Huffman编码解码

    万次阅读 多人点赞 2016-06-05 14:06:49
    Huffman编码解码霍夫曼(Huffman)编码问题也就是最优编码问题,通过比较权值逐步构建一颗Huffman树,再由Huffman树进行编码、解码。其步骤是先构建一个包含所有节点的线性表,每次选取最小权值的两个节点,生成一个...
  • huffman解码

    2010-03-16 06:30:21
    C语言编写,可实现对输入字符串的huffman编码解码,编码输出为比特流,解码输出为原字符串
  • 3.附件中的"编解码源码.rar.huff"为该程序的源码(VC6.0),如想查看,须先用该程序进行Huffman解码为rar文件,再rar解压; 4.文件拖曳到程序界面上默认是进行"Base64编码为图片"功能; 5.注意:所有功能的执行都是单...
  • Huffman编码的解码

    2018-09-02 13:28:04
    关于Huffman编码和KMP的知识请看我的这两篇文章:Huffman编码、KMP。 #include&... Huffman解码: 为什么把这个单独提出来,是因为我想把它和KMP结合起来使用。 */ class Node { public: char c; ...
  • 3.附件中的"编解码源码.rar.huff"为该程序的源码(VC6.0),如想查看,须先用该程序进行Huffman解码为rar文件,再rar解压; 4.文件可以拖曳到程序界面上进行操作; 5.注意:所有功能的执行都是单线程的,因此对于大文件...
  • Huffman编码与解码_C语言实现

    万次阅读 多人点赞 2017-04-16 10:22:22
    哈夫曼编码(Huffman Coding),是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异...本次实验用C语言实现了Huffman编码器、Huffman解码器。
  • huffman 编码 解码 可以直接应用的很好的程序
  • Huffman解码

    2017-05-01 22:14:49
    1.Huffman编码 (1) Huffman Coding (霍夫曼编码)是一种无失真编码的编码方式,Huffman编码是可变字长编码(VLC)的一种。 (2) Huffman 编码基于信源的概率统计模型,它的基本思路是,出现概率大的信源符号编长码,...
  • 本程序利用Java实现以下功能: 1、读取一行或多行数据,统计出现的所有字母的...2、构造huffman树 3、生成出现字母的编码表 4、对输入的数据进行编码输出 5、输入编码结果,对编码结果进行解码,得到原来的输入数据。
  • huffman编码解码

    2009-06-12 01:51:33
    文本输入输出,输入文件为:in.txt 编码输出文件为:out1.txt 解码输出文件为:out2.txt

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,262
精华内容 2,504
关键字:

huffman解码