Ian H. Witten、Radford M. Neal和John G. Cleary在1987年发表了一篇启发性的论文。论文中描述了一种基于整数运算的通用算术编码器,而且还给出了由计算错误导致的效率低下的分析。以下源代码来自于这篇论文:《基于算术编码的数据压缩》(Arithmetic Coding For Data Compression)。该论文的下载地址:http://www.sachingarg.com/compression/entropy_coding/acm87_arithmetic_coding.pdf

  编码函数和解码函数的伪代码:

/* ARITHMETIC ENCODING ALGORITHM. */

/* Call encode_symbol repeatedly for each symbol in the message.           */
/* Ensure that a distinguished "terminator" symbol is encoded last, then   */
/* transmit any value in the range [low, high).                            */

encode_symbol(symbo1, cum_freq)
    range = high - low
    high = low + range*cum_freq[symbol-1]
    low   = low + range*cum-freq[symbol]

/* ARITHMETIC DECODING ALGORITHM. */

/* "Value" is the number that has been received.                           */
/* Continue calling decode-symbol until the terminator symbol is returned. */

decode_symbol(cum_freq)
    find symbol such that
        cum_freq[symbol] <= (value-low)/(high-low) < cum_freq[symbol-1]
                            /* This ensures that value lies within the new */
                            /* [low, high) range that will be calculated by */
                            /* the following lines of code.                 */

range = high - low
    high = low + range*cum_freq[symbol-1]
    low   = low + range*cum_freq[symbol]
    return symbol

  算术编码器和解码器的C语言实现:

arithmetic_coding.h
─────────────────────────────────────────
/* DECLARATIONS USED FOR ARITHMETIC ENCODING AND DECODING */

/* SIZE OF ARITHMETIC CODE VALUES. */

#define Code_value_bits 16              /* Number of bits in a code value   */
typedef long code_value;                /* Type of an arithmetic code value */

#define Top_value (((long)1<<Code_value_bits)-1)      /* Largest code value */

/* HALF AND QUARTER POINTS IN THE CODE VALUE RANGE. */

#define First_qtr (Top_value/4+1)       /* Point after first quarter        */
#define Half      (2*First_qtr)         /* Point after first half           */
#define Third_qtr (3*First_qtr)         /* Point after third quarter        */
─────────────────────────────────────────

model.h
─────────────────────────────────────────
/* INTERFACE TO THE MODEL. */

/* THE SET OF SYMBOLS THAT MAY BE ENCODED. */

#define No_of_chars 256                 /* Number of character symbols      */
#define EOF_symbol (No_of_chars+1)      /* Index of EOF symbol              */

#define No_of_symbols (No_of_chars+1)   /* Total number of symbols          */

/* TRANSLATION TABLES BETWEEN CHARACTERS AND SYMBOL INDEXES. */

int char_to_index[No_of_chars];         /* To index from character          */
unsigned char index_to_char[No_of_symbols+1]; /* To character from index    */

/* CUMULATIVE FREQUENCY TABLE. */

#define Max_frequency 16383             /* Maximum allowed frequency count */
                                        /*   2^14 - 1                       */
int cum_freq[No_of_symbols+1];          /* Cumulative symbol frequencies    */
─────────────────────────────────────────

encode.c
─────────────────────────────────────────
/* MAIN PROGRAM FOR ENCODING. */

#include <stdio.h>
#include "model.h"

main()
{   start_model();                             /* Set up other modules.     */
    start_outputing_bits();
    start_encoding();
    for (;;) {                                 /* Loop through characters. */
        int ch; int symbol;
        ch = getc(stdin);                      /* Read the next character. */
        if (ch==EOF) break;                    /* Exit loop on end-of-file. */
        symbol = char_to_index[ch];            /* Translate to an index.    */
        encode_symbol(symbol,cum_freq);        /* Encode that symbol.       */
        update_model(symbol);                  /* Update the model.         */
    }
    encode_symbol(EOF_symbol,cum_freq);        /* Encode the EOF symbol.    */
    done_encoding();                           /* Send the last few bits.   */
    done_outputing_bits();
    exit(0);
}
─────────────────────────────────────────

arithmetic_encode.c
─────────────────────────────────────────
/* ARITHMETIC ENCODING ALGORITHM. */

#include "arithmetic_coding.h"

static void bit_plus_follow();   /* Routine that follows                    */

/* CURRENT STATE OF THE ENCODING. */

static code_value low, high;    /* Ends of the current code region          */
static long bits_to_follow;     /* Number of opposite bits to output after */
                                /* the next bit.                            */

/* START ENCODING A STREAM OF SYMBOLS. */

start_encoding()
{   low = 0;                            /* Full code range.                 */
    high = Top_value;
    bits_to_follow = 0;                 /* No bits to follow next.          */
}

/* ENCODE A SYMBOL. */

encode_symbol(symbol,cum_freq)
    int symbol;                 /* Symbol to encode                         */
    int cum_freq[];             /* Cumulative symbol frequencies            */
{   long range;                 /* Size of the current code region          */
    range = (long)(high-low)+1;
    high = low +                                /* Narrow the code region   */
      (range*cum_freq[symbol-1])/cum_freq[0]-1; /* to that allotted to this */
    low = low +                                 /* symbol.                  */
      (range*cum_freq[symbol])/cum_freq[0];
    for (;;) {                                  /* Loop to output bits.     */
        if (high<Half) {
            bit_plus_follow(0);                 /* Output 0 if in low half. */
        }
        else if (low>=Half) {                   /* Output 1 if in high half.*/
            bit_plus_follow(1);
            low -= Half;
            high -= Half;                       /* Subtract offset to top. */
        }
        else if (low>=First_qtr                 /* Output an opposite bit   */
              && high<Third_qtr) {              /* later if in middle half. */
            bits_to_follow += 1;
            low -= First_qtr;                   /* Subtract offset to middle*/
            high -= First_qtr;
        }
        else break;                             /* Otherwise exit loop.     */
        low = 2*low;
        high = 2*high+1;                        /* Scale up code range.     */
    }
}

/* FINISH ENCODING THE STREAM. */

done_encoding()
{   bits_to_follow += 1;                       /* Output two bits that      */
    if (low<First_qtr) bit_plus_follow(0);     /* select the quarter that   */
    else bit_plus_follow(1);                   /* the current code range    */
}                                              /* contains.                 */

/* OUTPUT BITS PLUS FOLLOWING OPPOSITE BITS. */

static void bit_plus_follow(bit)
    int bit;
{   output_bit(bit);                           /* Output the bit.           */
    while (bits_to_follow>0) {
        output_bit(!bit);                      /* Output bits_to_follow     */
        bits_to_follow -= 1;                   /* opposite bits. Set        */
    }                                          /* bits_to_follow to zero.   */
}
─────────────────────────────────────────

decode.c
─────────────────────────────────────────
/* MAIN PROGPAM FOR DECODING. */

#include <stdio.h>
#include "model.h"

main ()
{   start_model();                              /* Set up other modules.    */
    start_inputing_bits();
    start_decoding();
    for (;;) {                                  /* Loop through characters. */
        int ch; int symbol;
        symbol = decode_symbol(cum_freq);       /* Decode next symbol.      */
        if (symbol==EOF_symbol) break;          /* Exit loop if EOF symbol. */
        ch = index_to_char[symbol];             /* Translate to a character.*/
        putc(ch,stdout);                        /* Write that character.    */
        update_model(symbol);                   /* Update the model.        */
    }
    exit(0);
}
─────────────────────────────────────────

arithmetic_decode.c
─────────────────────────────────────────
/* ARITHMETIC DECODING ALGORITHM. */

#include "arithmetic_coding.h"

/* CURRENT STATE OF THE DECODING. */

static code_value value;        /* Currently-seen code value                */
static code_value low, high;    /* Ends of current code repion              */

/* START DECODING A STREAM OF SYMBOLS. */

start_decoding()
{   int i;
    value = 0;                                  /* Input bits to fill the   */
    for (i = 1; i<=Code_value_bits; i++) {      /* code value.              */
        value = 2*value+input_bit();
    }
    low = 0;                                    /* Full code range.         */
    high = Top_value;
}

/* DECODE THE NEXT SYMBOL. */

int decode_symbol(cum_freq)
    int cum_freq[];             /* Cumulative symbol frequencies            */
{   long range;                 /* Size of current code region              */
    int cum;                    /* Cumulative frequency calculated          */
    int symbol;                 /* Symbol decoded */
    range = (long)(high-low)+1;
    cum =                                       /* Find cum freq for value. */
      (((long)(value-low)+1)*cum_freq[0]-1)/range;
    for (symbol = 1; cum_freq[symbol]>cum; symbol++) ; /* Then find symbol. */
    high = low +                                /* Narrow the code region   */
      (range*cum_freq[symbol-1])/cum_freq[0]-1; /* to that allotted to this */
    low = low +                                 /* symbol.                  */
      (range*cum_freq[symbol])/cum_freq[0];
    for (;;) {                                  /* Loop to get rid of bits. */
        if (high<Half) {
            /* nothing */                       /* Expand low half.         */
        }
        else if (low>=Half) {                   /* Expand high half.        */
            value -= Half;
            low -= Half;                        /* Subtract offset to top. */
            high -= Half;
        }
        else if (low>=First_qtr                 /* Expand middle half.      */
              && high<Third_qtr) {
            value -= First_qtr;
            low -= First_qtr;                   /* Subtract offset to middle*/
            high -= First_qtr;
        }
        else break;                             /* Otherwise exit loop.     */
        low = 2*low;
        high = 2*high+1;                        /* Scale up code range.     */
        value = 2*value+input_bit();            /* Move in next input blt. */
    }
    return symbol;
}

bit_input.c
─────────────────────────────────────────
/* BIT INPUT ROUTINES. */

#include <stdio.h>
#include "arithmetic_coding.h"

/* THE BIT BUFFER. */

static int buffer;              /* Bits waiting to be input                 */
static int bits_to_go;          /* Number of bits still in buffer           */
static int garbage_bits;        /* Number of bits past end-of-file          */

/* INITIALIZE BIT INPUT. */

start_inputing_bits()
{   bits_to_go = 0;                             /* Buffer starts out with   */
    garbage_bits = 0;                           /* no bits in it.           */
}

/* INPUT A BIT. */

int input_bit()
{   int t;
    if (bits_to_go==0) {                        /* Read the next byte if no */
        buffer = getc(stdin);                   /* bits are left in buffer. */
        if (buffer==EOF) {
            garbage_bits += 1;                      /* Return arbitrary bits*/
            if (garbage_bits>Code_value_bits-2) {   /* after eof, but check */
                fprintf(stderr,"Bad input file/n"); /* for too many such.   */
                exit(-1);
            }
        }
        bits_to_go = 8;
    }
    t = buffer&1;                               /* Return the next bit from */
    buffer >>= 1;                               /* the bottom of the byte. */
    bits_to_go -= 1;
    return t;
}
─────────────────────────────────────────

bit_output.c
─────────────────────────────────────────
/* BIT OUTPUT ROUTINES. */

#include <stdio.h>

/* THE BIT BUFFER. */

static int buffer;               /* Bits buffered for output                */
static int bits_to_go;           /* Number of bits free in buffer           */

/* INITIALIZE FOR BIT OUTPUT. */

start_outputing_bits()
{   buffer = 0;                                 /* Buffer is empty to start */
    bits_to_go = 8;                             /* with.                    */
}

/* OUTPUT A BIT. */

output_bit(bit)
    int bit;
{   buffer >>= 1;                               /* Put bit in top of buffer.*/
    if (bit) buffer |= 0x80;
    bits_to_go -= 1;
    if (bits_to_go==0) {                        /* Output buffer if it is   */
        putc(buffer,stdout);                    /* now full.                */
        bits_to_go = 8;
    }
}

/* FLUSH OUT THE LAST BITS. */

done_outputing_bits()
{   putc(buffer>>bits_to_go,stdout);
}
─────────────────────────────────────────

  静态模型和自适应模型的程序调用:

fixed_model.c
─────────────────────────────────────────
/* THE FIXED SOURCE MODEL */

#include "model.h"

int freq[No_of_symbols+1] = (
   0,
   1,   1,   1,   1,   1,   1,   1,   1,   1,   1, 124,   1,   1,   1,   1,   1,
   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,

/*      !    "    #    $    %    &    '    (    )    *    +    ,    -    .    / */
1236,   1, 21,   9,   3,   1, 25, 15,   2,   2,   2,   1, 79, 19, 60,   1,

/* 0    1    2    3    4    5    6    7    8    9    :    ;    <    =    >    ? */
15, 15,   8,   5,   4,   7,   5,   4,   4,   6,   3,   2,   1,   1,   1,   1,

/* @    A    B    C    D    E    F    G    H    I    J    K    L    M    N    O */
   1, 24, 15, 22, 12, 15, 10,   9, 16, 16,   8,   6, 12, 23, 13, 11,

/* P    Q    R    S    T    U    V    W    X    Y    Z    [    /    ]    ^    _ */
14,   1, 14, 28, 29,   6,   3, 11,   1,   3,   1,   1,   1,   1,   1,   3,

/* '    a    b    c    d    e    f    g    h    i    j    k    l    m    n    o */
   1, 491, 85, 173, 232, 744, 127, 110, 293, 418,   6, 39, 250, 139, 429, 446,

/* p    q    r    s    t    u    v    w    x    y    z    {    |    }    ~      */
111,   5, 388, 375, 531, 152, 57, 97, 12, 101,   5,   2,   1,   2,   3,   1,

1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
   1
};

/* INITIALIZE THE MODEL. */

start_model()
{   int 1;
    for (i = 0; i<No_of_chars; i++) {           /* Set up tables that       */
        char_to_index[i] = i+1;                 /* translate between symbol */
        index_to_char[i+1] = i;                 /* indexes and characters. */
    }
    cum_freq[No_of_symbols] = 0;
    for (i = No_of_symbols; i>0; i--) {        /* Set up cumulative        */
        cum_freq[i-1] = cum_freq[i] + freq[i]; /* frequency counts.        */
    }
    if (cum_freq[0] > Max_frequency) abort();   /* Check counts within limit*/
}

/* UPDATE THE MODEL TO ACCOUNT FOR A NEW SYMBOL. */

update_model(symbol)
    int symbol;
{                                               /* Do nothing. */
}
─────────────────────────────────────────

adaptive_model.c
─────────────────────────────────────────
/* THE ADAPTIVE SOURCE MODEL */

#include "modol.h"

int freq[No_of_symbols+1];       /* symbol frequencies                      */

/* INITIALIZE THE MODEL. */

start_model()
{   int i;
    for (i = 0; i<No_of_chars; i++) {           /* Set up tables that       */
        char_to_index[i] = i+1;                 /* translate between symbol */
        index_to_char[i+1] = i;                 /* indexes and characters. */
    }
    for (i = 0; i<=No_of_symbols; i++) {        /* Set up initial frequency */
        freq[i] = 1;                            /* counts to be one for all */
        cum_freq[i] = No_of_symbols-i;          /* symbols.                 */
    }
    freq[0] = 0;                                /* Freq[0] must not be the */
}                                               /* same as freq[1].         */

/* UPDATE THE MODEL TO ACCOUNT FOR A NEW SYMBOL. */

update_model(symbol)
    int symbol;                 /* Index of new symbol                      */
{   int i;                      /* New index for symbol                     */
    if (cum_freq[0]==Max_frequency) {           /* See if frequency counts */
        int cum;                                /* are at their maximum.    */
        cum = 0;
        for (i = No_of_symbols; i>=0; i--) {    /* If so, halve all the     */
            freq[i] = (freq[i]+1)/2;            /* counts (keeping them     */
            cum_freq[i] = cum;                  /* non-zero).               */
            cum += freq[i];
        }
    }
    for (i = symbol; freq[i]==freq[i-1]; i--) ; /* Find symbol's new index. */
    if (i<symbol) {
        int ch_i, ch_symbol;
        ch_i = index_to_char[i];                /* Update the translation   */
        ch_symbol = index_to_char[symbol];      /* tables if the symbol has */
        index_to_char[i] = ch_symbol;           /* moved.                   */
        index_to_char[symbol] = ch_i;
        char_to_index[ch_i] = symbol;
        char_to_index[ch_symbol] = i;
    }
    freq[i] += 1;
    while (i>0) {                               /* Increment the frequency */
        i -= 1;                                 /* count for the symbol and */
        cum_freq[i] += 1;                       /* update the cumulative    */
    }                                           /* frequencies.             */
}

算术编码(Arithmetic Coding)源代码相关推荐

  1. (Matlab源码)Matlab实现算术编码(Arithmetic coding)超级详解(每一段代码都可以看懂)

    1.代码功能 输入:一个字符串 输出: codeword(码值) codeword所占的位数 2.代码框图 3.代码超详解 统计字符串中的字符种类,调用函数,放入数组b中. b=unique(str1 ...

  2. (含Matlab源码)算术编码(arithmetic coding)的underflow问题

    0.文章结构 文章的行文逻辑如下,看官可以根据需要跳读,节省时间. 1.介绍underflow和overflow. 2.underflow问题起源 3.underflow问起探索 4.underflo ...

  3. 算术编码(Arithmetic coding)

    算术编码 算术编码 简介 思想 示例 小结 算术编码 简介 算术编码是图像压缩的主要算法之一. 是一种无损数据压缩方法,也是一种熵编码的方法.和其它熵编码方法不同的地方在于,其他的熵编码方法通常是把输 ...

  4. Arithmetic Code 算术编码

    Principle: 算术编码的原理是非常直白的.在算术编码中我们考虑对[消息序列整体]进行编码,以这里的消息序列[210]为例,其落在概率区间[0.68,0.712]中.然后我们需要用二进制编码去表 ...

  5. [转]算术编码+统计模型=数据压缩 - 第二部分:统计模型

    转自:http://deercrane.spaces.live.com/blog/cns!8BEF692B75EB8095!189.entry 算术编码 + 统计模型 = 数据压缩 - 第二部分:统计 ...

  6. H.266/VVC技术学习:算术编码

    算术编码是一种常用的变长编码方法,和Huffman编码类似,也是对出现概率大的符号赋予短码,出现概率小的符号赋予长码,但算术编码不是简单的将每个信源符号映射成一个码字,而是对整个输入序列分配一个码字, ...

  7. 算术编码原理与实现【转载】

    1. 算术编解码原理 编码 与哈夫曼编码一样,算数编码是熵编码的一种,是基于数据中字符出现的概率,给不同字符以不同的编码. 算数编码的原理我个人感觉其实并不太容易用三言两语直观地表达出来,其背后的数学 ...

  8. 5.3 Python图像处理之图像编码-算术编码

    5.3 Python图像处理之图像编码-算术编码 文章目录 5.3 Python图像处理之图像编码-算术编码 1 算法原理 2 代码 3 效果 1 算法原理 算术编码在图像数据压缩标准(如JPEG,J ...

  9. 算术编码(多媒体实验一)

    算术编码(xdu多媒体实验一) 前言 详细原理 源代码 前言 算术编码(多媒体实验一) sklearn主成分分析pca用python实现(多媒体实验二) BOW图像检索corel数据集(多媒体实验三) ...

最新文章

  1. 1012. 数字分类 java_PAT-B-1012. 数字分类(Java)
  2. 导航,头部,CSS基础
  3. 微软职位内部推荐-Senior SDE
  4. jmeter之图片上传
  5. 快看!你连接世界的新入口,在那朵云上
  6. 2021年11月国产数据库排行榜:openGauss闯入前三,Kingbase流行度与日俱增,TDengine厚积薄发
  7. Code Pages Supported by Windows
  8. 婚姻是一堂需要认真学习的课程
  9. vs 执行单个文件,如cpp
  10. 【操作系统⑩】——进程死锁【银行家算法+详细样例 进程死锁的预防机制、避免机制、检测与解决】
  11. excel 中英文 显示星期,月份
  12. 手机app访问服务器数据库数据库文件夹,手机app怎么访问服务器数据库
  13. 搜索功能支持大小写模糊查询
  14. 12.8 Font 对象
  15. 基于主从博弈的智能小区电动汽车充电管理及代理商定价策略
  16. Thymeleaf实现页面静态化
  17. 第一章 计算机系统概述
  18. Android 微信分享与QQ分享功能(原生实现)
  19. pandas+plt操作练习(统计高等数学竞赛获奖)
  20. 我的元旦是这么过来的

热门文章

  1. 【转】0.SharePoint服务器端对象模型 之 序言
  2. 如何将C语言翻译成汇编语言,如何把汇编语言转换成C语言
  3. 字节流转化为文件流_字节流转成字符串之后,在通过字符串转成字节流后的文件为什么会不一样?...
  4. idea全局搜索搜不全的BUG
  5. cas引出的ABA问题?如何解决?- 理解原子引用、时间戳(版本号)原子引用
  6. REVERSE-PRACTICE-BUUCTF-24
  7. 【leetcodeMySQL每周一练】- 5道题带你练习mysql
  8. 【CodeForces - 520C】DNA Alignment (快速幂,思维)
  9. 【POJ - 1664】放苹果 (递归经典题 或 dp 或 母函数)
  10. C语言编程中关于负数的%运算的判定。