• 数据压缩之Polar编码实现详解


        Polar编码与范式Huffman编码类似,也是根据一个静态频率统计表来为各个符号分配前缀码来实现压缩。但Polar编码的构造算法不需要用Huffman的树结构,实现起来非常简单,而且大多数情况下压缩效果不会比Huffman差多少。
        Polar编码和范式Huffman编码的差别只在计算每个符号的编码长度上,这里举一个例子说明Polar编码的算法:

        假设拿到这样一个频率表:

        符号    频率
        A       190
        B       38
        C       185
        D       70
        E       253
        Total   736

        首先要按每个符号的频率降序排序:

        符号    频率
        E       253
        A       190
        C       185
        D       70
        B       38
        Total   736

        第二步,每个符号频率值按2的整数次幂向下取整,Total按2的整数次幂向上取整:

        符号    频率
        E       128
        A       128
        C       128
        D       64
        B       32
        Total   480
        Total‘  1024

        第三步也就是最关键的一步,进行前两步操作后,实际的频率总和Total必然不大于取整后的频率和Total',现在我们从上到下看,对每个符号的频率,如果它倍增后实际总和不超过Total',就对它进行倍增操作:

        符号    频率    倍增后
        E       128     256
        A       128     256
        C       128     256
        D       64      128
        B       32      64
        Total   480     960
        Total‘  1024

        第一轮操作,每个符号都满足了倍增的条件,而最终的实际频率和仍然不大于Total',我们再进行一轮相同的操作:

        符号    频率    倍增后  第二轮倍增操作后
        E       128     256     256
        A       128     256     256
        C       128     256     256
        D       64      128     128
        B       32      64      128
        Total   480     960     1024
        Total‘  1024

        第二轮操作中只有最后一个符号满足倍增的条件,并且最后的实际频率和正好等于Total',这时候操作结束,最后可以简单地用以下公式得出每个符号的编码长度:

      CodeLen(x) = Log2(Total / Freq(x))

    用公式算出每个符号的编码长度:

        符号    频率    倍增后  第二轮倍增操作后    所求编码长度
        E       128     256     256                 Log2(1024 / 256) = 2
        A       128     256     256                 Log2(1024 / 256) = 2
        C       128     256     256                 Log2(1024 / 256) = 2
        D       64      128     128                 Log2(1024 / 128) = 3
        B       32      64      128                 Log2(1024 / 128) = 3
        Total   480     960     1024
        Total‘  1024

        至此Polar编码算法结束。

     有了每个符号的编码长度之后,我们就可以用范式Huffman编码类似的方法为每个符号分配前缀编码,进一步实现对数据的压缩了。

        最后提供一个完整的运用Polar编码进行无损数据压缩的简单实现,为了提高压缩率,我们对输入的数据先进行了一次MTF变换处理,使得最终的压缩率接近gzip。

      1 /*******************************************************************************
      2  * RichSelian's nooblike compressor: MTF + Polar coding
      3  ******************************************************************************/
      4 #include <stdio.h>
      5 #include <string.h>
      6 
      7 /*******************************************************************************
      8  * POLAR Coder
      9  ******************************************************************************/
     10 #define POLAR_SYMBOLS   256 /* should be even */
     11 #define POLAR_MAXLEN    15  /* should be less than 16, so we can pack two length values into a byte */
     12 
     13 #define M_round_down(x)     while((x)&(-(x)^(x))) { (x) &= (-(x)^(x)); }
     14 #define M_round_up(x)       while((x)&(-(x)^(x))) { (x) &= (-(x)^(x)); } (x) <<= 1;
     15 #define M_int_swap(x, y)    {int (_)=(x); (x)=(y); (y)=(_);}
     16 
     17 int polar_make_leng_table(const int* freq_table, int* leng_table) {
     18     int symbols[POLAR_SYMBOLS];
     19     int i;
     20     int s;
     21     int total;
     22     int shift = 0;
     23 
     24     memcpy(leng_table, freq_table, POLAR_SYMBOLS * sizeof(int));
     25 
     26 MakeTablePass:
     27     /* sort symbols */
     28     for(i = 0; i < POLAR_SYMBOLS; i++) {
     29         symbols[i] = i;
     30     }
     31     for(i = 0; i < POLAR_SYMBOLS; i++) {
     32         if(i > 0 && leng_table[symbols[i - 1]] < leng_table[symbols[i]]) {
     33             M_int_swap(symbols[i - 1], symbols[i]);
     34             i -= 2;
     35         }
     36     }
     37 
     38     /* calculate total frequency */
     39     total = 0;
     40     for(i = 0; i < POLAR_SYMBOLS; i++) {
     41         total += leng_table[i];
     42     }
     43 
     44     /* run */
     45     M_round_up(total);
     46     s = 0;
     47     for(i = 0; i < POLAR_SYMBOLS; i++) {
     48         M_round_down(leng_table[i]);
     49         s += leng_table[i];
     50     }
     51     while(s < total) {
     52         for(i = 0; i < POLAR_SYMBOLS; i++) {
     53             if(s + leng_table[symbols[i]] <= total) {
     54                 s += leng_table[symbols[i]];
     55                 leng_table[symbols[i]] *= 2;
     56             }
     57         }
     58     }
     59 
     60     /* get code length */
     61     for(i = 0; i < POLAR_SYMBOLS; i++) {
     62         s = 2;
     63         if(leng_table[i] > 0) {
     64             while((total / leng_table[i]) >> s != 0) {
     65                 s += 1;
     66             }
     67             leng_table[i] = s - 1;
     68         } else {
     69             leng_table[i] = 0;
     70         }
     71 
     72         /* code length too long -- scale and rebuild table */
     73         if(leng_table[i] > POLAR_MAXLEN) {
     74             shift += 1;
     75             for(i = 0; i < POLAR_SYMBOLS; i++) {
     76                 if((leng_table[i] = freq_table[i] >> shift) == 0 && freq_table[i] > 0) {
     77                     leng_table[i] = 1;
     78                 }
     79             }
     80             goto MakeTablePass;
     81         }
     82     }
     83     return 0;
     84 }
     85 
     86 int polar_make_code_table(const int* leng_table, int* code_table) {
     87     int i;
     88     int s;
     89     int t1;
     90     int t2;
     91     int code = 0;
     92 
     93     memset(code_table, 0, POLAR_SYMBOLS * sizeof(int));
     94 
     95     /* make code for each symbol */
     96     for(s = 1; s <= POLAR_MAXLEN; s++) {
     97         for(i = 0; i < POLAR_SYMBOLS; i++) {
     98             if(leng_table[i] == s) {
     99                 code_table[i] = code;
    100                 code += 1;
    101             }
    102         }
    103         code *= 2;
    104     }
    105 
    106     /* reverse each code */
    107     for(i = 0; i < POLAR_SYMBOLS; i++) {
    108         t1 = 0;
    109         t2 = leng_table[i] - 1;
    110         while(t1 < t2) {
    111             code_table[i] ^= (1 & (code_table[i] >> t1)) << t2;
    112             code_table[i] ^= (1 & (code_table[i] >> t2)) << t1;
    113             code_table[i] ^= (1 & (code_table[i] >> t1)) << t2;
    114             t1++;
    115             t2--;
    116         }
    117     }
    118     return 0;
    119 }
    120 
    121 int polar_make_decode_table(const int* leng_table, const int* code_table, int* decode_table) {
    122     int i;
    123     int c;
    124 
    125     for(c = 0; c < POLAR_SYMBOLS; c++) {
    126         if(leng_table[c] > 0) {
    127             for(i = 0; i + code_table[c] < 65536; i += (1 << leng_table[c])) {
    128                 decode_table[i + code_table[c]] = c;
    129             }
    130         }
    131     }
    132     return 0;
    133 }
    134 
    135 /*******************************************************************************
    136  * MTF Transformer
    137  ******************************************************************************/
    138 unsigned char mtf_queue[65536][256];
    139 unsigned char mtf_ch1 = 0;
    140 unsigned char mtf_ch2 = 0;
    141 unsigned char mtf_ch3 = 0;
    142 
    143 #define M_mtf_hashctx ((unsigned)(mtf_ch1*131313131 + mtf_ch2*13131 + mtf_ch3) % 65536)
    144 
    145 int mtf_transformer_init() {
    146     int i;
    147 
    148     for(i = 0; i < sizeof(mtf_queue); i++) {
    149         mtf_queue[i / 256][i % 256] = i % 256;
    150     }
    151     return 0;
    152 }
    153 
    154 int mtf_encode(int c) {
    155     int i;
    156 
    157     for(i = 0; i < 256; i++) {
    158         if(mtf_queue[M_mtf_hashctx][i] == c) {
    159             memmove(mtf_queue[M_mtf_hashctx] + 1, mtf_queue[M_mtf_hashctx], i);
    160             mtf_queue[M_mtf_hashctx][0] = c;
    161             break;
    162         }
    163     }
    164     mtf_ch3 = mtf_ch2;
    165     mtf_ch2 = mtf_ch1;
    166     mtf_ch1 = c;
    167     return i;
    168 }
    169 
    170 int mtf_decode(int i) {
    171     int c;
    172 
    173     c = mtf_queue[M_mtf_hashctx][i];
    174     memmove(mtf_queue[M_mtf_hashctx] + 1, mtf_queue[M_mtf_hashctx], i);
    175     mtf_queue[M_mtf_hashctx][0] = c;
    176 
    177     mtf_ch3 = mtf_ch2;
    178     mtf_ch2 = mtf_ch1;
    179     mtf_ch1 = c;
    180     return c;
    181 }
    182 
    183 /*******************************************************************************
    184  * MAIN
    185  ******************************************************************************/
    186 int main(int argc, char** argv) {
    187     static unsigned char idata[100000];
    188     static unsigned char odata[120000]; /* never overflow */
    189     int inpos;
    190     int inlen;
    191     int outpos;
    192     int outlen;
    193     int i;
    194     int freq_table[256];
    195     int code_table[256];
    196     int leng_table[256];
    197     int code_len = 0;
    198     int code_buf = 0;
    199     int decode_table[65536];
    200 
    201     mtf_transformer_init();
    202 
    203     /* compress */
    204     if(argc == 2 && strcmp(argv[1], "e") == 0) {
    205         /* init frequency table */
    206         while((inlen = fread(idata, 1, sizeof(idata), stdin)) > 0) {
    207             outlen = 0;
    208             memset(freq_table, 0, sizeof(freq_table));
    209 
    210             for(i = 0; i < inlen; i++) {
    211                 idata[i] = mtf_encode(idata[i]);
    212                 freq_table[idata[i]] += 1;
    213             }
    214 
    215             /* write length table */
    216             polar_make_leng_table(freq_table, leng_table);
    217             for(i = 0; i < POLAR_SYMBOLS; i += 2) {
    218                 odata[outlen++] = leng_table[i] * 16 + leng_table[i + 1];
    219             }
    220 
    221             /* encode */
    222             polar_make_code_table(leng_table, code_table);
    223             for(i = 0; i < inlen; i++) {
    224                 code_buf += code_table[idata[i]] << code_len;
    225                 code_len += leng_table[idata[i]];
    226                 while(code_len > 8) {
    227                     odata[outlen++] = code_buf % 256;
    228                     code_buf /= 256;
    229                     code_len -= 8;
    230                 }
    231             }
    232             if(code_len > 0) {
    233                 odata[outlen++] = code_buf;
    234                 code_buf = 0;
    235                 code_len = 0;
    236             }
    237             fwrite(&outlen, sizeof(outlen), 1, stdout);
    238             fwrite(&inlen,  sizeof(inlen),  1, stdout);
    239             fwrite(odata, 1, outlen, stdout);
    240         }
    241         return 0;
    242     }
    243 
    244     /* decompress */
    245     if(argc == 2 && strcmp(argv[1], "d") == 0) {
    246         while(1) {
    247             code_buf = 0;
    248             code_len = 0;
    249 
    250             /* read inlen/outpos */
    251             if(fread(&outlen, sizeof(outlen), 1, stdin) != 1 || fread(&inlen, sizeof(inlen), 1, stdin) != 1) {
    252                 break;
    253             }
    254             fread(odata, 1, outlen, stdin);
    255             inpos = 0;
    256             outpos = 0;
    257 
    258             /* read length table */
    259             for(i = 0; i < POLAR_SYMBOLS; i += 2) {
    260                 leng_table[i] =     odata[outpos] / 16;
    261                 leng_table[i + 1] = odata[outpos] % 16;
    262                 outpos++;
    263             }
    264 
    265             /* decode */
    266             polar_make_code_table(leng_table, code_table);
    267             polar_make_decode_table(leng_table, code_table, decode_table);
    268 
    269             while(inpos < inlen) {
    270                 while(outpos < outlen && code_len < POLAR_MAXLEN) {
    271                     code_buf += odata[outpos++] << code_len;
    272                     code_len += 8;
    273                 }
    274                 i = decode_table[code_buf % 65536];
    275 
    276                 idata[inpos++] = mtf_decode(i);
    277                 code_buf >>= leng_table[i];
    278                 code_len -=  leng_table[i];
    279             }
    280             fwrite(idata, 1, inpos, stdout);
    281         }
    282         return 0;
    283     }
    284 
    285     fprintf(stderr, "%s\n", "Usage: polar [e|d] <input >output");
    286     return 0;
    287 }
  • 相关阅读:
    优化你的手机游戏
    vuforia 结合 unity3d 开发 AR 的 androidAPP 总结
    self._raiseerror(v) File "D:GameDevelopmentPython27libxmletreeElementTree.py", line 1506, in _raiseerror
    自定义TexturePacker插件导出自己的plist文件
    还原TexturePacker plist 文件以及图片的方法 (切开各小图片)
    no module named firefly.master.master
    c#比较器 排序
    python ——面向对象进阶(反射,双下线方法,静态方法,类方法)
    python——模块和包 需要注意的地方
    举例详解Python中的split()函数的使用方法
  • 原文地址:https://www.cnblogs.com/richselian/p/2763162.html
Copyright © 2020-2023  润新知