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

📄 acfile.cpp

📁 算术编码的仿真实例
💻 CPP
字号:
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//                                                                           -
//                       ****************************                        -
//                        ARITHMETIC CODING EXAMPLES                         -
//                       ****************************                        -
//                                                                           -
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//                                                                           -
// Simple file compression using arithmetic coding                           -
//                                                                           -
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//                                                                           -
// Version 1.00  -  April 25, 2004                                           -
//                                                                           -
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//                                                                           -
//                                  WARNING                                  -
//                                 =========                                 -
//                                                                           -
// The only purpose of this program is to demonstrate the basic principles   -
// of arithmetic coding. It is provided as is, without any express or        -
// implied warranty, without even the warranty of fitness for any particular -
// purpose, or that the implementations are correct.                         -
//                                                                           -
// Permission to copy and redistribute this code is hereby granted, provided -
// that this warning and copyright notices are not removed or altered.       -
//                                                                           -
// Copyright (c) 2004 by Amir Said (said@ieee.org) &                         -
//                       William A. Pearlman (pearlw@ecse.rpi.edu)           -
//                                                                           -
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


// - - Inclusion - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

#include <stdlib.h>

#include "arithmetic_codec.h"


// - - Constants - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

const char * W_MSG = "cannot write to file";
const char * R_MSG = "cannot read from file";

const unsigned NumModels  = 16;                          // MUST be power of 2

const unsigned FILE_ID    = 0xB8AA3B29U;

const unsigned BufferSize = 65536;


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// - - Prototypes  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

void Encode_File(char * data_file_name,
                 char * code_file_name);

void Decode_File(char * code_file_name,
                 char * data_file_name);


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// - - Main function - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

int main(int numb_arg, char * arg[])
{
                                                       // define program usage
  if ((numb_arg != 4) || (arg[1][0] != '-') || 
     ((arg[1][1] != 'c') && (arg[1][1] != 'd'))) {
    puts("\n\t Compression parameters:   acfile -c data_file compressed_file");
    puts("\n\t Decompression parameters: acfile -d compressed_file new_file\n");
    exit(0);
  }

  if (arg[1][1] == 'c')
    Encode_File(arg[2], arg[3]);
  else
    Decode_File(arg[2], arg[3]);

  return 0;
}


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// - - Implementations - - - - - - - - - - - - - - - - - - - - - - - - - - - -

void Error(const char * s)
{
  fprintf(stderr, "\n Error: %s.\n\n", s);
  exit(1);
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

unsigned Buffer_CRC(unsigned bytes,
                    unsigned char * buffer)
{
  static const unsigned CRC_Gen[8] = {        // data for generating CRC table
    0xEC1A5A3EU, 0x5975F5D7U, 0xB2EBEBAEU, 0xE49696F7U,
    0x486C6C45U, 0x90D8D88AU, 0xA0F0F0BFU, 0xC0A0A0D5U };

  static unsigned CRC_Table[256];            // table for fast CRC computation

  if (CRC_Table[1] == 0)                                      // compute table
    for (unsigned k = CRC_Table[0] = 0; k < 8; k++) {
      unsigned s = 1 << k, g = CRC_Gen[k];
      for (unsigned n = 0; n < s; n++) CRC_Table[n+s] = CRC_Table[n] ^ g;
    }

                                  // computes buffer's cyclic redundancy check
  unsigned crc = 0;
  if (bytes)
    do {
      crc = (crc >> 8) ^ CRC_Table[(crc&0xFFU)^unsigned(*buffer++)];
    } while (--bytes);
  return crc;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

FILE * Open_Input_File(char * file_name)
{
  FILE * new_file = fopen(file_name, "rb");
  if (new_file == 0) Error("cannot open input file");
  return new_file;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

FILE * Open_Output_File(char * file_name)
{
  FILE * new_file = fopen(file_name, "rb");
  if (new_file != 0) {
    fclose(new_file);
    printf("\n Overwrite file %s? (y = yes, otherwise quit) ", file_name);
    char line[128];
    gets(line);
    if (line[0] != 'y') exit(0);
  }
  new_file = fopen(file_name, "wb");
  if (new_file == 0) Error("cannot open output file");
  return new_file;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

void Save_Number(unsigned n, unsigned char * b)
{                                                   // decompose 4-byte number
  b[0] = (unsigned char)( n        & 0xFFU);
  b[1] = (unsigned char)((n >>  8) & 0xFFU);
  b[2] = (unsigned char)((n >> 16) & 0xFFU);
  b[3] = (unsigned char)( n >> 24         );
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

unsigned Recover_Number(unsigned char * b)
{                                                    // recover 4-byte integer
  return unsigned(b[0]) + (unsigned(b[1]) << 8) + 
        (unsigned(b[2]) << 16) + (unsigned(b[3]) << 24);
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

void Encode_File(char * data_file_name,
                 char * code_file_name)
{
                                                                 // open files
  FILE * data_file = Open_Input_File(data_file_name);
  FILE * code_file = Open_Output_File(code_file_name);

                                                  // buffer for data file data
  unsigned char * data = new unsigned char[BufferSize];

  unsigned nb, bytes = 0, crc = 0;       // compute CRC (cyclic check) of file
  do {
    nb = fread(data, 1, BufferSize, data_file);
    bytes += nb;
    crc ^= Buffer_CRC(nb, data);
  } while (nb == BufferSize);

                                                      // define 12-byte header
  unsigned char header[12];
  Save_Number(FILE_ID, header);
  Save_Number(crc,      header + 4);
  Save_Number(bytes,    header + 8);
  if (fwrite(header, 1, 12, code_file) != 12) Error(W_MSG);
                                                            // set data models
  Adaptive_Data_Model dm[NumModels];
  for (unsigned m = 0; m < NumModels; m++) dm[m].set_alphabet(256);

  Arithmetic_Codec encoder(BufferSize);                  // set encoder buffer

  rewind(data_file);                               // second pass to code file

  unsigned context = 0;
  do {

    nb = (bytes < BufferSize ? bytes : BufferSize);
    if (fread(data, 1, nb, data_file) != nb) Error(R_MSG);   // read file data

    encoder.start_encoder();
    for (unsigned p = 0; p < nb; p++) {                       // compress data
      encoder.encode(data[p], dm[context]);
      context = unsigned(data[p]) & (NumModels - 1);
    }

    encoder.write_to_file(code_file);  // stop encoder & write compressed data

  } while (bytes -= nb);

                                                          // done: close files
  fflush(code_file);
  unsigned data_bytes = ftell(data_file), code_bytes = ftell(code_file);
  printf(" Compressed file size = %d bytes (%6.2f:1 compression)\n",
    code_bytes, double(data_bytes) / double(code_bytes));
  fclose(data_file);
  fclose(code_file);

  delete [] data;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

void Decode_File(char * code_file_name,
                 char * data_file_name)
{
                                                                 // open files
  FILE * code_file = Open_Input_File(code_file_name);
  FILE * data_file  = Open_Output_File(data_file_name);

                                   // read file information from 12-byte header
  unsigned char header[12];
  if (fread(header, 1, 12, code_file) != 12) Error(R_MSG);
  unsigned fid   = Recover_Number(header);
  unsigned crc   = Recover_Number(header + 4);
  unsigned bytes = Recover_Number(header + 8);

  if (fid != FILE_ID) Error("invalid compressed file");

                                                  // buffer for data file data
  unsigned char * data = new unsigned char[BufferSize];
                                                            // set data models
  Adaptive_Data_Model dm[NumModels];
  for (unsigned m = 0; m < NumModels; m++) dm[m].set_alphabet(256);

  Arithmetic_Codec decoder(BufferSize);                  // set encoder buffer

  unsigned nb, new_crc = 0, context = 0;                    // decompress file
  do {

    decoder.read_from_file(code_file); // read compressed data & start decoder

    nb = (bytes < BufferSize ? bytes : BufferSize);
                                                            // decompress data
    for (unsigned p = 0; p < nb; p++) {
      data[p] = (unsigned char) decoder.decode(dm[context]);
      context = unsigned(data[p]) & (NumModels - 1);
    }
    decoder.stop_decoder();

    new_crc ^= Buffer_CRC(nb, data);                // compute CRC of new file
    if (fwrite(data, 1, nb, data_file) != nb) Error(W_MSG);

  } while (bytes -= nb);


  fclose(data_file);                                     // done: close files
  fclose(code_file);

  delete [] data;
                                                   // check if file is correct
  if (crc != new_crc) Error("incorrect file CRC");
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

⌨️ 快捷键说明

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