jpg2kmqencoder.h

来自「JPEG里MQ算术编码测试程序 编解码器 C」· C头文件 代码 · 共 214 行

H
214
字号
#pragma once

#include "common.h"

class CJPG2KMQEState;
class CJPG2KMQETransition;

class CJPG2KMQEncoder
{
public:
	CJPG2KMQEncoder(void)
	{
		m_bActive = 0;
		m_pBufStart = m_pBufNext = NULL;
		m_pPrev = m_pNext = NULL;
	}
	~CJPG2KMQEncoder(void);

	/* 
	开始一个新的MQ或RAW码字段节。在开始的时候,pBuffer指向第一个码字节
	写的位置。然而,小心的是,MQ码字段需要访问pBuffer前面的位置。
	在这个位置的值是临时保存的,并且仅仅在Terminate成员调用的时候恢复。
	为了允许访问pBuffer[-1],调用者应该注意分配码字空间。
	这个buffer应该足够容纳压缩的输出。如果用户决定buffer需要增加,
	使用augment_buffer函数。这个策略允许缓冲区的大小测试和潜在的
	函数调用从时间关键的代码中删除。
	*/
	void Start(LPBYTE pBuffer, int bMQSegment);

	/* 
	返回字start调用以后当前对象使用的buffer数量。
	函数主要用来判断是否需要判断缓冲区重建;这里不是尝试判断截断长度。
	*/
	int GetBytesUsed()
	{ 
		return (int)(m_pBufNext - m_pBufStart);
	}

	/* 
	如果需要增加缓冲区大小的时候使用该函数。
	首先你必须创建新的缓冲区并且复制缓冲区的内容到新的缓冲区中,然后
	为使用该缓冲区的每个MQ Encoder调用该函数。
	对象将更改其内部指针。pOldHandle和pNewHandle指针应该原来缓冲区和新
	分配的缓冲区的开始位置。
	*/
	void AugmentBuffer(LPBYTE pOldHandle, LPBYTE pNewHandle)
	{
		if (m_pBufStart == NULL)
			return; // Encoder finished working with buffer
		m_pBufStart += (pNewHandle-pOldHandle);
		m_pBufNext += (pNewHandle-pOldHandle);
	}

	/* 
	在超过当前编码过程时候,使用这个函数来连续编码段。
	这在拥有同一个码字段的编码对象之间安装内部引用,从而便于
	后来的截断点的计算。
	*/
	void Continues(CJPG2KMQEncoder *pPrev)
	{
		*this = *pPrev;
		m_pPrev = pPrev; pPrev->m_pNext = this;
		pPrev->m_bActive = 0;
	}

	/* 
	该函数产生这个对象产生的额外码字节,在连续链表上先前对象的连续点。
	如果可能,函数为这个对象调用截断点优化算法,并且为那些没有截断点
	的在连续列表中的对象也调用这个算法。
	对于那些活动的对象或到目前位置产生少于5个额外字节的其他对象连续的
	对象不能使用该算法。
	如果截断点不可能,final参数设置为false并且函数返回一个合理的较低的
	bound,其实是在连续点之前的放入的字节数量(或缓冲区的开始)。返回
	值应该是非负的。
	*/
	int GetIncrementalLength(int &bFinal)
	{
		if(!m_bTruncationPointFound)
		{
			CJPG2KMQEncoder * pScanAhead = this;
			while (pScanAhead->m_pNext != NULL) 
				pScanAhead = pScanAhead->m_pNext;

			CJPG2KMQEncoder *pScanBack = pScanAhead;
			for (; pScanBack != NULL; pScanBack=pScanBack->m_pPrev)
			{
				if (pScanBack->m_bTruncationPointFound)
					break;
				if ((!pScanBack->m_bActive) &&
					((pScanAhead->m_pBufNext - pScanBack->m_pBufNext) >= 5))
					pScanBack->FindTruncationPoint(pScanAhead->m_pBufNext);
			}
		}
		bFinal = m_bTruncationPointFound;
		if (m_pPrev == NULL)
			return (int)(m_pBufNext - m_pBufStart);
		else
			return (int)(m_pBufNext - m_pPrev->m_pBufNext);
	}

	LPBYTE Terminate(int bOptimal);

	/* 
	在一个码字段的最后一个元素上调用该函数。目的是复位段中的所有
	对象来准备后面调用Start函数。
	*/
	void Finish()
	{
		CJPG2KMQEncoder *pScan, *pNextScan;
		for (pScan=this; pScan != NULL; pScan = pNextScan)
		{
			pNextScan = pScan->m_pPrev;
			pScan->m_pNext = pScan->m_pPrev = NULL;
			pScan->m_bTruncationPointFound = false;
			pScan->m_pBufStart = pScan->m_pBufNext = NULL;
		}	
	}

public: // Functions to check out state information for use with fast macros
	inline void CheckOut(long &A, long &C,long &t, long &temp, LPBYTE &ppStore)
	{ // Use this form for MQ codeword segments.
		A = this->m_A; 
		C = this->m_C;
		t = this->m_t; 
		temp = this->m_temp; 
		ppStore = this->m_pBufNext;
	}

	inline void CheckOut(long &t, long &temp, LPBYTE &ppStore)
	{ // Use this form for raw codeword segments.
		m_bCheckedOut = 1;
		t = this->m_t; 
		temp = this->m_temp; 
		ppStore = this->m_pBufNext;
	}

	inline void CheckIn(long A, long C,long t, long temp, LPBYTE ppStore)
	{ // Use this form for MQ codeword segments.
		m_bCheckedOut = 0;
		this->m_A = A; 
		this->m_C = C;
		this->m_t = t; 
		this->m_temp = temp; 
		this->m_pBufNext = ppStore;
	}

	inline void CheckIn(long t, long temp, LPBYTE ppStore)
	{ // Use this form for raw codeword segments.
		m_bCheckedOut = 0;
		this->m_t = t; 
		this->m_temp = temp; 
		this->m_pBufNext = ppStore;
	}

public:
	/* Note that symbol must be 0 or KDU_INT32_MIN */
	void MQEncode(long symbol, CJPG2KMQEState &state);

	//instead of macro
	void MQEncode(long &lps_p_bar,CJPG2KMQEState &state,long &A,
		long &C,long &t,long &temp,LPBYTE &store);

	
	//instead of macro
	void MQEncodeRun(long &run,long &A,long &C,long &t,long &temp,LPBYTE &store); 

	// Encodes a 2 bit run length, MSB first
	void MQEncodeRun(long run); 

	/* Note that symbol must be 0 or 1. */
	void RawEncode(long symbol);

	//instead of macro
	void RawEncode(long &symbol,long &t,long &temp,LPBYTE &store);

private:
	/* Used by the `MQEncode' member function. */
	void	TransferByte();

	void	TransferByte(long &C,long &t,long &temp,LPBYTE &store);

public: // Probability estimation state machine.
	static long m_pBarTable[47]; // Normalized LPS probabilities

	static CJPG2KMQETransition m_TransitionTable[94]; // See def'n of `mqe_transition'

	static void InitializeTransitionTable();

private: // Internal functions
	/* 
	这个函数在Terminate中自动被调用来为连续的码字段检查最优的截断点。
	(也可以用到非连续的码字段上来检查最小的段长度)。这个函数在
	GetFinalLength中也被调用。
	pLimit参数指向已经终止的码字段最后一个字节后面;仅仅访问该位置
	前的访问是合法的。
	*/
	void FindTruncationPoint(LPBYTE plimit);

private:
	long m_A; // Only the least significant 16 bits of A are used
	long m_C; // Holds a 28 bit number (including the carry bit)
	long m_t;   // This is "t_bar" in the book
	long m_temp; // This is "T_bar" in the book
	LPBYTE m_pBufStart;
	LPBYTE m_pBufNext;
	BYTE m_nOverwrittenByte;
	int m_bCheckedOut;
	int m_bMQSegment;
	int m_bActive;
	int m_bTruncationPointFound;
	CJPG2KMQEncoder *m_pPrev; // Point from which coding continues in same segment
	CJPG2KMQEncoder *m_pNext; // Point to which coding continues in next segment
};

⌨️ 快捷键说明

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