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

📄 code_mul.c

📁 本程序可以对文件进行算术编码处理 解码处理等
💻 C
字号:
/* CODE_MUL.C - ARITHMETIC ENCODING/DECODING, USING MULTIPLY/DIVIDE. */

#include <stdio.h>

#define global extern

#include "code.h"


/* CURRENT STATE OF THE ENCODING/DECODING. */

static code_value low;		/* Start of current coding region, in [0,1) */

static code_value range;	/* Size of region, normally kept in the     */
				/* interval [1/4,1/2]                       */

static code_value value;	/* Currently-seen code value, in [0,1)      */

static int bits_to_follow;	/* Number of opposite bits to output after  */
				/* the next bit                             */

static div_value F;		/* Common factor used, in interval [1/4,1)  */

static code_value split_region();


/* LOCAL PROCEDURES. */

static int        find_symbol   (freq_value []);
static void       narrow_region (freq_value [], int, int);
static code_value split_region  (freq_value, freq_value);
static void       push_out_bits (void);
static void       discard_bits  (void);


/* OUTPUT BIT PLUS FOLLOWING OPPOSITE BITS. */

#define bit_plus_follow(bit) \
do { \
    output_bit(bit);				/* Output the bit.          */\
    while (bits_to_follow>0) {			/* Output bits_to_follow    */\
        output_bit(!(bit));			/* opposite bits. Set       */\
        bits_to_follow -= 1;			/* bits_to_follow to zero.  */\
    } \
} while (0) 


/* START ENCODING A STREAM OF SYMBOLS. */

void start_encoding(void)
{   
    low = Code_half;				/* Use half the code region */
    range = Code_half;				/* (wastes first bit as 1). */
    bits_to_follow = 0;				/* No opposite bits follow. */
}


/* START DECODING A STREAM OF SYMBOLS. */

void start_decoding(void)
{   
    int i;

    value = input_bit();			/* Check that first bit     */
    if (value!=1) {				/* is a 1.                  */
        fprintf(stderr,"Bad input file (1)\n");
        exit(1);
    }

    for (i = 1; i<Code_bits; i++) { 		/* Fill the code value with */
        value += value;				/* input bits.              */
        value += input_bit();
    }

    low = Code_half;				/* Use half the code region */
    range = Code_half;				/* (first bit must be 1).   */
}


/* ENCODE A SYMBOL. */

void encode_symbol(symbol,cum_freq)
    int symbol;			/* Symbol to encode                         */
    freq_value cum_freq[];	/* Cumulative symbol frequencies            */
{
    narrow_region(cum_freq,symbol,0);		/* Narrow coding region.    */
    push_out_bits();				/* Output determined bits.  */
}


/* ENCODE A BIT. */

void encode_bit(bit,freq0,freq1)
    int bit;			/* Bit to encode (0 or 1)                   */
    freq_value freq0;           /* Frequency for 0 bit                      */
    freq_value freq1;           /* Frequency for 1 bit                      */
{
    code_value split;

    if (freq1>freq0) {				/* Encode bit when most     */
        split = split_region(freq0,freq1);	/* probable symbol is a 1.  */
        if (bit) { low += split; range -= split; }
        else     { range = split;  }
    }

    else {					/* Encode bit when most     */
        split = split_region(freq1,freq0);	/* probable symbol is a 0.  */
        if (bit) { range = split;  }
        else     { low += split; range -= split; }
    }

    push_out_bits();				/* Output determined bits.  */
}


/* DECODE THE NEXT SYMBOL. */

int decode_symbol(cum_freq)
    freq_value cum_freq[];	/* Cumulative symbol frequencies            */
{
    int symbol;			/* Symbol decoded                           */

    symbol = find_symbol(cum_freq);		/* Find decoded symbol.     */
    narrow_region(cum_freq,symbol,1);		/* Narrow coding region.    */
    discard_bits();				/* Discard output bits.     */

    return symbol;
}


/* DECODE A BIT. */

int decode_bit(freq0,freq1)
    freq_value freq0;           /* Frequency for 0 bit                      */
    freq_value freq1;           /* Frequency for 1 bit                      */
{
    code_value split;
    int bit;

    if (freq1>freq0) {				/* Decode bit when most     */
        split = split_region(freq0,freq1);	/* probable symbol is a 1.  */
        bit = value-low >= split;
        if (bit) { low += split; range -= split; }
        else     { range = split;  }
    }

    else {					/* Decode bit when most     */
        split = split_region(freq1,freq0);	/* probable symbol is a 0.  */
        bit = value-low < split;
        if (bit) { range = split;  }
        else     { low += split; range -= split; }
    }

    discard_bits();				/* Discard output bits.     */

    return bit;
}


/* DETERMINE DECODED SYMBOL FROM INPUT VALUE. */

static int find_symbol(cum_freq)
    freq_value cum_freq[];	/* Cumulative symbol frequencies            */
{
    freq_value cum;		/* Cumulative frequency calculated          */
    int symbol;			/* Symbol decoded                           */

    F = range / cum_freq[0];			/* Compute common factor.   */

    cum = (value-low) / F;			/* Compute target cum freq. */
    for (symbol = 1; cum_freq[symbol]>cum; symbol++) ; /* Then find symbol. */

    return symbol;
}


/* NARROW CODING REGION TO THAT ALLOTTED TO SYMBOL. */

static void narrow_region(cum_freq,symbol,have_F)
    freq_value cum_freq[];	/* Cumulative symbol frequencies            */
    int symbol;			/* Symbol decoded                           */
    int have_F;			/* Is F already computed?                   */
{
    code_value T;		/* Temporary value                          */

    if (!have_F) F = range / cum_freq[0];	/* Compute common factor.   */

    if (symbol==1) {				/* Narrow range for symbol  */
        T = F * cum_freq[symbol];		/* at the top.              */
        low += T;
        range -= T;
    }

    else {					/* Narrow range for symbol  */
        T = F * cum_freq[symbol];               /* not at the top.          */
        low += T;
        range = F * cum_freq[symbol-1] - T; 
    }
}


/* FIND BINARY SPLIT FOR CODING REGION. */

static code_value split_region(freq_b,freq_t)
    freq_value freq_b;		/* Frequency for symbol in bottom half      */
    freq_value freq_t;		/* Frequency for symbol in top half         */
{
    return freq_b * (range / (freq_b+freq_t)); 
}


/* OUTPUT BITS THAT ARE NOW DETERMINED. */

static void push_out_bits(void)
{
    while (range<=Code_quarter) {

        if (low>=Code_half) {			/* Output 1 if in top half.*/
            bit_plus_follow(1);
            low -= Code_half;			/* Subtract offset to top.  */
        }

        else if (low+range<=Code_half) {	/* Output 0 in bottom half. */
            bit_plus_follow(0);		
	} 

        else {			 		/* Output an opposite bit   */
            bits_to_follow += 1;		/* later if in middle half. */
            low -= Code_quarter;		/* Subtract offset to middle*/
        } 

        low += low;				/* Scale up code region.    */
        range += range;
    }
}


/* DISCARD BITS THE ENCODER WOULD HAVE OUTPUT. */

static void discard_bits(void)
{
    while (range<=Code_quarter) {

        if (low>=Code_half) {			/* Expand top half.         */
            low -= Code_half;			/* Subtract offset to top.  */
            value -= Code_half;
        }

        else if (low+range<=Code_half) {	/* Expand bottom half.      */
            /* nothing */
	} 

        else {			 		/* Expand middle half.      */
            low -= Code_quarter;		/* Subtract offset to middle*/
            value -= Code_quarter;
        } 

        low += low;				/* Scale up code region.    */
        range += range;

        value += value;				/* Move in next input bit.  */
        value += input_bit();
    }
}


/* FINISH ENCODING THE STREAM. */

void done_encoding(void)
{   
    for (;;) {

        if (low+(range>>1)>=Code_half) {	/* Output a 1 if mostly in  */
            bit_plus_follow(1);			/* top half.                */
            if (low<Code_half) {
                range -= Code_half-low;
                low = 0;
            }
            else {
                low -= Code_half;
            }
        }

        else {					/* Output a 0 if mostly in  */
            bit_plus_follow(0);			/* bottom half.             */
            if (low+range>Code_half) {
                range = Code_half-low;
            }
        }

        if (range==Code_half) break;		/* Quit when coding region  */
						/* becomes entire interval. */
        low += low;
        range += range;				/* Scale up code region.    */
    }
}

⌨️ 快捷键说明

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