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

📄 adaarithcoder.cpp

📁 自适应算术编码的实现
💻 CPP
字号:
//  AdaArithCoder.cpp :  自适应算术编码器和解码器的类实现
// 
//  Author:    Shen Hongwei
//  Date:      Nov.10, 2005
//  Location:  Beijing, China
// 

#include "StdAfx.h"
#include ".\adaarithcoder.h"

AdaArithCoder::AdaArithCoder(void)
{
}

AdaArithCoder::~AdaArithCoder(void)
{
}

// AdaArithCoder初始化函数
// 参数:
//    BitIO * bit_in:    输入bit流
//    BitIO * bit_out:   输出bit流
// 返回值
//    void
void AdaArithCoder::Init(BitIO * bit_in, BitIO * bit_out)
{	
	Coder::Init(bit_in, bit_out);

	L = 0;
	U = TOP_VALUE;

	TotalCount = 0;
	CumCount[0] = 0;
	for (int i =1; i < tbSize+1; i++) {  // 初始状态为等概率
		TotalCount += 1;
        CumCount[i] = TotalCount;
	}
}

// AdaArithCoder初始化函数
// 参数:
//    BitIO * bit_in:    输入bit流
//    BitIO * bit_out:   输出bit流
//    unsigned long i_leng:  输入文件的长度, by bits
// 返回值:  void
void AdaArithCoder::Init(BitIO * in, BitIO * out, unsigned long i_leng) 
{
	this->Init(in, out);
	this->in_leng = i_leng;
}

// 使用自适应算术编码对输入bit流编码,并写到输出bit流中,直至输入bit流结束
// 参数:   void
// 返回值: int
//      1,  正常结束
//    其他,出错(尚未考虑)
int  AdaArithCoder::Run(void)
{
	unsigned char  symbol;
	unsigned long  count = 0;
	int   Scale3 = 0;
	char  b;
	char  c;

	while (this->bit_reader->ReadAByte(c))
	{
		assert(L<=U);
		memcpy(&symbol, &c, 1);
		count++; 

		TagType oldL=L, oldU=U;
		L = oldL + ((oldU-oldL+1U) * (unsigned long)CumCount[symbol]) / TotalCount;
		U = oldL + ((oldU-oldL+1U) * (unsigned long)CumCount[symbol+1]) / TotalCount - 1U;

		if (count + 1 > this->in_leng)  // 处理被压缩数据的最后一个字符
		{
			b = MSB(L);
			bit_writer->Write(&b, 1);
		    int  Scale3Save = Scale3;
			while(Scale3 > 0)
			{
				char complement = ~b;
				bit_writer->Write(&complement, 1);
				Scale3--;
			}

			for (int i = Scale3 + 1; i<8*this->tagSize; i++)
			{
				L<<=1;
				b = MSB(L);
			    bit_writer->Write(&b, 1);
			}

			b = 0;
			for (int i = 0; i< Scale3Save; i++)
			    bit_writer->Write(&b, 1);

			this->bit_writer->FlushEnd();

			return(1);
		}

		b = MSB(L);
		bool e3flag = this->CheckE3();
		while( MSB(U) == b || e3flag)
		{
			if( !e3flag) {
				bit_writer->Write(&b, 1);
				L <<= 1;
				L &= AND_LSB_MASK;
				U <<= 1;
				U |= LSB_MASK;

				while(Scale3 > 0)
				{
					char complement = ~b;
					bit_writer->Write(&complement, 1);
					Scale3--;
				}
			} else {   // E3 condition holds
				L <<= 1;
				L &= AND_LSB_MASK;
				U <<= 1;
				U |= LSB_MASK;
				L ^= MSB_MASK;
				U ^= MSB_MASK;
				Scale3++;
			}

            b = MSB(L);
			e3flag = this->CheckE3();
		}

		this->Count(symbol);
	}

	this->bit_writer->FlushEnd();

	return (1);
}

// 统计各个字符出现的次数
void AdaArithCoder::Count(unsigned char c)   
{
	if (this->TotalCount >= TOP_VALUE>>2) {
		TotalCount >>= 1;
		for (int i=0; i< this->tbSize+1; i++)
			this->CumCount[i] >>= 1;
	}

	TotalCount ++;
	for (int i=c+1; i<this->tbSize+1; i++)
		this->CumCount[i] ++;

	unsigned long adjust = 0;
	for (int i=1; i< this->tbSize+1; i++) {
		if (this->CumCount[i] <= this->CumCount[i-1])
			adjust++;
		this->CumCount[i] += adjust;
	}

	TotalCount += adjust;
}

// Dummy function for the time being
bool AdaArithCoder::GenNextCode()
{
	return true;
}

// Dummy function for the time being
void AdaArithCoder::SetDebugMode(int mode)
{
	;
}

AdaArithDecoder::AdaArithDecoder(void)
{
}

AdaArithDecoder::~AdaArithDecoder(void)
{
}

// AdaArithDecoder初始化函数
// 参数:
//    BitIO * bit_in:    输入bit流
//    BitIO * bit_out:   输出bit流
// 返回值
//    void
void AdaArithDecoder::Init(BitIO * bit_in, BitIO * bit_out)
{	
	Coder::Init(bit_in, bit_out);

	L = 0;
	U = TOP_VALUE;
	TotalCount = 0;
	CumCount[0] = 0;
	for (int i =1; i < tbSize+1; i++) {  // 初始状态为等概率
		TotalCount += 1;
        CumCount[i] = TotalCount;
	}
}

// AdaArithDecoder初始化函数
// 参数:
//    BitIO * bit_in:    输入bit流
//    BitIO * bit_out:   输出bit流
//    unsigned long i_leng:  输入文件的长度, by bits
// 返回值:  void
void AdaArithDecoder::Init(BitIO * in, BitIO * out, unsigned long i_leng) 
{
	this->Init(in, out);
	this->in_leng = i_leng;  // in_leng是数据未被压缩时的长度,by bytes
}

bool AdaArithDecoder::ReadATag(TagType & tag)
{
	char c[sizeof(tag)];

	for (int i=sizeof(tag)-1; i>=0; i--) 
	{
    	if (bit_reader->ReadAInversedByte(c[i]) == false)
		    return false;
	}

	memcpy(&tag, c, sizeof(tag));

	return true;
}

// 使用自适应算术编码对输入bit流解码,并写到输出bit流中,直至输入bit流结束
// 参数:   void
// 返回值: int
//      1,  正常结束
//    其他,出错(尚未考虑)
int  AdaArithDecoder::Run(void)
{
	char symbol;
	int  Scale3 = 0;
	unsigned long count = 0;

	TagType tag;
	if (this->ReadATag(tag) == false)
		return -1;

	while (1)
	{
		int k=0;
		TagType tag_count;
		tag_count = ((tag - L + 1U)*(unsigned long)(TotalCount) - 1U)/(unsigned long)((U-L+1U));
		assert(tag_count <= TotalCount);

		while ( tag_count >= CumCount[k])
			k++;

		k--;

		assert(k<=255&&k>=0);

		unsigned char x = k;
		char value = x;
		// this->CompareWithOriginal(&value); // for debug
		this->bit_writer->Write((char*)&x, 8);
		count++;
		if (count == this->in_leng)
		{	
			this->bit_writer->FlushEnd();
			return(1);
		}

		TagType oldL=L, oldU=U;
		L = (TagType)(oldL + ((oldU-oldL+1U)* (unsigned long)CumCount[x]) / TotalCount);
		U = (TagType) (oldL + ((oldU-oldL+1U)* (unsigned long)CumCount[x+1]) / TotalCount - 1U);
		
		this->Count(x);

		char b = MSB(L);
		bool e3flag = this->CheckE3();
		while( b == MSB(U) || e3flag)
		{
			if( !e3flag) {
				L <<= 1;
				L &= AND_LSB_MASK;
				U <<= 1;
				U |= LSB_MASK;
				tag <<= 1;
				if (this->bit_reader->ReadABit((char*)&tag,0) == -1 )
					return 0;
			} else {   // E3 condition holds
				L <<= 1;
				L &= AND_LSB_MASK;
				U <<= 1;
				U |= LSB_MASK;
				tag <<= 1;
				if (this->bit_reader->ReadABit((char*)&tag,0) == -1 )
					return 0;
				L ^= MSB_MASK;
				U ^= MSB_MASK;
				tag ^= MSB_MASK;
			}

            b = MSB(L);
			e3flag = this->CheckE3();
		}
	}

	this->bit_writer->FlushEnd();

	return (1);
}

// 统计各个字符出现的次数
void AdaArithDecoder::Count(unsigned char c)   
{
	if (this->TotalCount >= TOP_VALUE>>2) {
		TotalCount >>= 1;
		for (int i=0; i< this->tbSize+1; i++)
			this->CumCount[i] >>= 1;
	}

	TotalCount ++;
	for (int i=c+1; i<this->tbSize+1; i++)
		this->CumCount[i] ++;

	unsigned long adjust = 0;
	for (int i=1; i< this->tbSize+1; i++) {
		if (this->CumCount[i] <= this->CumCount[i-1])
			adjust++;
		this->CumCount[i] += adjust;
	}

	TotalCount += adjust;
}

void AdaArithDecoder::CompareWithOriginal(char * value)  // for debug
{
	static flag=0;
	static fstream fs_in;	
	static long count = 1;

	if (!flag) {
    	fs_in.open("e:\\tmp\\05.mpga", ios_base::in | ios_base::binary);    // becomes "r" (open existing file for reading)
		flag = 1;
	}

	count++;
	char c;
	fs_in.get(c);
	// shw add for debug
	if (value[0] != c) {
		printf("!!! count = %d\n", count);
		getchar();
		exit(0);
	}
	assert(value[0]==c);
}

// Dummy function for the time being
bool AdaArithDecoder::GenNextCode()
{
	return true;
}

// Dummy function for the time being
void AdaArithDecoder::SetDebugMode(int mode)
{
	;
}

⌨️ 快捷键说明

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