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

📄 jpg2kmqencoder.cpp

📁 JPEG里MQ算术编码测试程序 编解码器 C
💻 CPP
字号:
#include "stdafx.h"
#include "common.h"
#include "jpg2kmqencoder.h"
#include "JPG2KMQEState.h"

long CJPG2KMQEncoder::m_pBarTable[47] =
{ 
	0x5601, 0x3401, 0x1801, 0x0AC1, 0x0521, 0x0221,
	0x5601, 0x5401, 0x4801, 0x3801, 0x3001, 0x2401, 0x1C01, 0x1601,
	0x5601, 0x5401, 0x5101, 0x4801, 0x3801, 0x3401, 0x3001, 0x2801,
	0x2401, 0x2201, 0x1C01, 0x1801, 0x1601, 0x1401, 0x1201, 0x1101,
	0x0AC1, 0x09C1, 0x08A1, 0x0521, 0x0441, 0x02A1, 0x0221, 0x0141,
	0x0111, 0x0085, 0x0049, 0x0025, 0x0015, 0x0009, 0x0005, 0x0001,
	0x5601 
};

CJPG2KMQETransition CJPG2KMQEncoder::m_TransitionTable[94];

static class CMQEncoderInit {
public: 
	CMQEncoderInit()
	{ 
			CJPG2KMQEncoder::InitializeTransitionTable(); 
	}
} _do_it;

void CJPG2KMQEncoder::InitializeTransitionTable()
{
	int Sigma_mps[47] =
	{ 
		1, 2, 3, 4, 5,38, 7, 8, 9,10,11,12,13,29,15,16,17,18,19,20,21,22,23,24,
		25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,45,46
	};

	int Sigma_lps[47] =
	{ 
		1, 6, 9,12,29,33, 6,14,14,14,17,18,20,21,14,14,15,16,17,18,19,19,20,21,
		22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,46
	};

	for (long n=0; n < 94; n++)
	{
		long s, new_s;
		int Sigma, new_Sigma;

		s = n & 1;
		Sigma = n >> 1;

		// Build MPS transition state first.
		new_Sigma = Sigma_mps[Sigma];
		new_s = s; // No switch on MPS transition.
		CJPG2KMQEncoder::m_TransitionTable[n].m_mps.InitEncoder(new_Sigma,new_s);
		// Now build the LPS transition state.
		new_Sigma = Sigma_lps[Sigma];
		new_s = s;
		if ((CJPG2KMQEncoder::m_pBarTable[Sigma] == 0x5601) && (Sigma != 46))
			new_s = 1-s;
		CJPG2KMQEncoder::m_TransitionTable[n].m_lps.InitEncoder(new_Sigma,new_s);
	}
}

CJPG2KMQEncoder::~CJPG2KMQEncoder(void)
{
}

void CJPG2KMQEncoder::Start(LPBYTE  pBuffer, int bMQSegment)
{
	m_bActive = 1;
	m_bTruncationPointFound = 0;
	this->m_bMQSegment = bMQSegment;
	m_pBufStart = pBuffer; // First byte will always be discarded
	m_bCheckedOut = 0;
	if (bMQSegment)
	{
		m_A = MQE_A_MIN;  
		m_C = 0; 
		m_t=12; 
		m_temp=0;
		m_pBufNext = m_pBufStart - 1;
		m_nOverwrittenByte = *m_pBufNext;
	}
	else
	{
		m_pBufNext = m_pBufStart;
		m_t=8; 
		m_temp = 0;
	}
}

LPBYTE  CJPG2KMQEncoder::Terminate(int bOptimal)
{
	LPBYTE  pBufLimit;
	/* 
		Perform easy MQ terminating flush (see Section 12.3.1 of the book
		by Taubman and Marcellin). 
	*/
	if (this->m_bMQSegment)
	{ 
		long save_A = m_A; // Need these quantities for later calculating
		long save_C = m_C; // optimal truncation lengths.
		long save_t = m_t;
		long save_temp = m_temp;
		LPBYTE save_buf_next = m_pBufNext;

		int n_bits = MQE_CARRY_POS-15-m_t; // Number of bits we need to flush.
		m_C <<= m_t; // Move the next 8 available bits into the partial byte.
		while (n_bits > 0)
		{
			TransferByte();
			n_bits -= m_t; // New value of t is the number of bits just transferred
			m_C <<= m_t;
		}
		TransferByte(); // Flush the temp byte buffer.
		pBufLimit = m_pBufNext;
		if (bOptimal)
		{ // Restore previous state so that `FindTtruncationPoint' works.
			m_A = save_A; m_C = save_C; m_t = save_t; m_temp = save_temp;
			m_pBufNext = save_buf_next;
		}
		// Prepare to restore the overwritten byte.
		m_pBufStart[-1] = m_nOverwrittenByte;
	}
	else
	{ // Perform raw terminating flush.
		long save_t = m_t;
		long save_temp = m_temp;
		LPBYTE save_buf_next = m_pBufNext;
		if (bOptimal)
		{ // For optimal truncation later on, pad with 1's.
			if (m_t != 8)
			{
				for (; m_t > 0; m_t--)
					m_temp = (m_temp<<1) + 1;
				*(m_pBufNext++) = (BYTE) m_temp;
			}
		}
		else
		{ // For error resilient termination, pad with alternating 0/1 sequence
			if (m_temp == 0xFF)
			{ // Safest to include stuff bit for resilient raw termination
				*(m_pBufNext++) = (BYTE) m_temp;
				m_temp = 0;
				m_t = 7;
			}
			if (m_t != 8)
			{
				for (int pad=0; m_t > 0; m_t--, pad=1-pad)
					m_temp = (m_temp<<1) + pad;
				*(m_pBufNext++) = (BYTE) m_temp;
			}
		}
		pBufLimit = m_pBufNext;
		if (bOptimal)
		{ // Restore previous state so that `FindTtruncationPoint' works.
			m_t = save_t; 
			m_temp = save_temp; 
			m_pBufNext = save_buf_next;
		}
	}

	CJPG2KMQEncoder *pScan = this;
	while (pScan->m_pPrev != NULL)
		pScan = pScan->m_pPrev;
	for (; pScan != this; pScan=pScan->m_pNext)
		if (!pScan->m_bTruncationPointFound)
			pScan->FindTruncationPoint(pBufLimit);

	m_bActive = 0;

	if (bOptimal)
		this->FindTruncationPoint(pBufLimit);
	else
	{ // Discard any trailing FF, but that is all.
		if ((m_pBufNext > m_pBufStart) && (m_pBufNext[-1] == 0xFF))
			m_pBufNext--;
		m_bTruncationPointFound = 1;
	}

	return m_pBufNext;
}

void CJPG2KMQEncoder::TransferByte()
{
	// Can't propagate carry past this byte; need a bit stuff
	if (m_temp == 0xFF){
		*(m_pBufNext++) = (BYTE) m_temp;
		m_temp = m_C >> MQE_MSBS_POS; // Transfer 7 bits plus any carry bit
		m_C &= MQE_MSBS_CLEAR;
		m_t = 7;
	}
	else{
		m_temp += (m_C>>MQE_CARRY_POS) & 1; // Propagate any carry bit from C to temp
		m_C &= ~MQE_CARRY_BIT; // Reset the carry bit
		*(m_pBufNext++) = (BYTE) m_temp;
		// Decoder will see this as a bit stuff
		if (m_temp == 0xFF) 
		{
			m_temp = (m_C>>MQE_MSBS_POS);
			m_C &= MQE_MSBS_CLEAR;
			m_t = 7;
		}
		else
		{
			m_temp = (m_C>>MQE_PARTIAL_POS);
			m_C &= MQE_PARTIAL_CLEAR;
			m_t = 8;
		}
	}
}

/* 
使用12.3.2节的算法来找F_min.
为了应付32位字长度的限制,按照下面的方发来描述量化的Cr-R_F以及Ar+Cr-R_F:
Cr-R_F = C_low + C_high*2^{27}
Cr+Ar-R_F = CplusA_low + CplusA_high*2^{27}
在迭代查找F_min的过程终,每个迭代移位量化
*/
void CJPG2KMQEncoder::FindTruncationPoint(LPBYTE plimit)
{
	if (m_bMQSegment)
	{ 
		BYTE save_byte = m_pBufStart[-1];
		m_pBufStart[-1] = 0; // Need this for algorithm to work in all cases

		long C_low = m_C<<m_t;
		long CplusA_low = (m_C+m_A)<<m_t;
		long C_high = m_temp;
		long CplusA_high = m_temp;
		if (C_low & MQE_CARRY_BIT)
		{ 
			C_high++; 
			C_low -= MQE_CARRY_BIT; 
		}

		if (CplusA_low & MQE_CARRY_BIT)
		{ 
			CplusA_high++; 
			CplusA_low -= MQE_CARRY_BIT; 
		}

		int s = 8;
		int F_min = 0;

		while ((C_high > 0xFF) || (CplusA_high <= 0xFF))
		{
			F_min++;
			/* Augment R_F (Bear in mind that the high quantities always
			hold the most significant 8 bits of the S_F-bit nominal
			word sizes.  Instead of successively decreasing S_F by s,
			we are leaving S_F the same and successively up-shifting
			the words by s -- same thing. */

			m_temp = *(m_pBufNext++);
			C_high -= m_temp << (8-s);
			CplusA_high -= m_temp << (8-s);

			// Shift Cr-R_F up by s bit positions
			C_high <<= s;
			C_high += C_low >> (MQE_CARRY_POS-s);
			C_low <<= s;
			C_low &= ~(((long)(-1))<<MQE_CARRY_POS);

			// Shift Cr+Ar-R_F up by s bit positions
			CplusA_high <<= s;
			CplusA_high += CplusA_low >> (MQE_CARRY_POS-s);
			CplusA_low <<= s;
			CplusA_low &= ~(((long)(-1))<<MQE_CARRY_POS);

			// Find new value of s
			if (m_temp == 0xFF)
				s = 7;
			else
				s = 8;
		}
		m_pBufStart[-1] = save_byte;
	}
	/* 
	Raw segment.  Nothing to do other than marking the existence of any
	partially completed byte and then executing the common code below to
	discard trailing strings of 1's, which will be synthesized by the
	decoder. 
	*/
	else{
		if (m_t != 8)
			m_pBufNext++;
	}

	// Discard trailing FF's or FF7F pairs.
	if ((m_pBufNext > m_pBufStart) && (m_pBufNext[-1] == 0xFF))
		m_pBufNext--;
	while (((m_pBufNext-m_pBufStart) >= 2)  &&
		(m_pBufNext[-1] == 0x7F) && (m_pBufNext[-2] == 0xFF))
		m_pBufNext -= 2;

	m_bTruncationPointFound = 1;
}

void CJPG2KMQEncoder::MQEncode(long symbol, CJPG2KMQEState &state)
{
	long p_bar =state.m_p_bar_mps & 0x7FFF;
	m_A -= p_bar;
	if (((symbol ^ state.m_p_bar_mps) & JP2K_INT32_MIN) == 0)
	{ // Coding an MPS
		if (m_A >= MQE_A_MIN)
		{ // No renormalization and hence no conditional exchange
			m_C += p_bar;
		}
		else
		{ // Renormalization is required.
			if (m_A < p_bar)
				m_A = p_bar; // Conditional exchange
			else
				m_C += p_bar;
			state = state.m_pTransition->m_mps;
			do {
				m_A += m_A; m_C += m_C; m_t--;
				if (m_t == 0)
					TransferByte();
			} while (m_A < MQE_A_MIN);
		}
	}
	else
	{ // Coding an LPS; renormalization is inevitable
		if (m_A < p_bar)
			m_C += p_bar; // Conditional exchange
		else
			m_A = p_bar;
		state = state.m_pTransition->m_lps;
		do {
			m_A += m_A; 
			m_C += m_C; 
			m_t--;
			if (m_t == 0)
				TransferByte();
		} while (m_A < MQE_A_MIN);
	}
}

// Encodes a 2 bit run length, MSB first
void CJPG2KMQEncoder::MQEncodeRun(long run)
{
	CJPG2KMQEState state; 
	state.InitEncoder(46,0);
	MQEncode((run&2)<<30,state);
	MQEncode(run<<31,state);
}

/* Note that symbol must be 0 or 1. */
void CJPG2KMQEncoder::RawEncode(long symbol)
{
	if (m_t == 0)
	{
		*(m_pBufNext++) = (BYTE) m_temp;
		m_t = (m_temp == 0xFF)?7:8;
		m_temp = 0;
	}
	m_temp = (m_temp<<1) + symbol;
	m_t--;
}

void	CJPG2KMQEncoder::TransferByte(long &C,long &t,long &temp,LPBYTE &store)
{
	temp += C>>MQE_CARRY_POS; /* Saves comparisons to add the carry first */
	if (temp >= 0xFF)
	{
		*(store++) = (BYTE) 0xFF;
		temp = (temp | 0xFF)>>1; /* Holds 0x7F unless had FF and a carry */
		temp &= (C>>MQE_MSBS_POS); /* Clear carry if temp not initially FF */
		C &= MQE_MSBS_CLEAR;
		t = 7;
	}
	else
	{
		*(store++) = (BYTE) temp;
		temp = (C>>MQE_PARTIAL_POS) & 0xFF; /* Still need to clear carry */
		C &= MQE_PARTIAL_CLEAR;
		t = 8;
	}
}

void CJPG2KMQEncoder::MQEncode(long &lps_p_bar,CJPG2KMQEState &state,long &A,
						long &C,long &t,long &temp,LPBYTE &store)
{
	/* Note: incoming symbol must be in `lps_p_bar' as 0 or KDU_INT32_MIN */
	lps_p_bar ^= (state).m_p_bar_mps;
	A -= lps_p_bar;
	if (A >= MQE_A_MIN)
	{ /* Symbol is MPS and (A-p_bar) >= 2^15, meaning no renormalization */
		C += lps_p_bar;
	}
	else
	{ /* Renormalization is inevitable and conditional exchange possible */
		if (lps_p_bar >= 0)
		{ /* Symbol is MPS, but A-p_bar < 2^15. */
			if (A < lps_p_bar)
				A = lps_p_bar; /* Conditional exchange */
			else 
				C = C + lps_p_bar;
			state = (state).m_pTransition->m_mps;
		}
		else
		{ /* Symbol is LPS, so A-p_bar is necessarily less than 2^15 */
			A &= JP2K_INT32_MAX;
			lps_p_bar &= JP2K_INT32_MAX;
			if (A < lps_p_bar)
				C = C + lps_p_bar; /* Conditional exchange */
			else
				A = lps_p_bar;
			state = (state).m_pTransition->m_lps;
		} 
		do {
			A += A; C += C;
			if ((--t)==0)
				TransferByte(C,t,temp,store);
		} while (A < MQE_A_MIN);
	}
}

void CJPG2KMQEncoder::MQEncodeRun(long &run,long &A,long &C,
								  long &t,long &temp,LPBYTE &store)
{
	A -= 0x5601;
	if (((run & 2)==0) && (A >= MQE_A_MIN))
	{ /* Symbol is MPS and no renormalization is required. */
		C += 0x5601;
	}
	else
	{ /* Renormalization is required. */
		if ((run & 2) == 0)
		{ /* Symbol is an MPS */
			if (A < 0x5601)
				A = 0x5601; /* Conditional exchange */
			else
				C += 0x5601;
		}
		else
		{ /* Symbol is an LPS */
			if (A < 0x5601)
				C += 0x5601; /* Conditional exchange */
			else
				A = 0x5601;
		} 
		do {
			A += A; C += C; t--;
			if (t == 0)
				TransferByte(C,t,temp,store);
		} while (A < MQE_A_MIN);
	}
	A -= 0x5601;
	if (((run & 1)==0) && (A >= MQE_A_MIN))
	{ /* Symbol is MPS and no renormalization is required. */
		C += 0x5601;
	}
	else
	{ /* Renormalization is required. */
		if ((run & 1) == 0)
		{ /* Symbol is an MPS */
			if (A < 0x5601)
				A = 0x5601; /* Conditional exchange */ 
			else
				C += 0x5601;
		} 
		else
		{ /* Symbol is an LPS */
			if (A < 0x5601)
				C += 0x5601; /* Conditional exchange */
			else
				A = 0x5601;
		} 
		do {
			A += A; C += C; t--;
			if (t == 0)
				TransferByte(C,t,temp,store);
		} while (A < MQE_A_MIN);
	}
}

void CJPG2KMQEncoder::RawEncode(long &symbol,long &t,long &temp,LPBYTE &store)
{
	if (t==0)
	{
		*(store++) = (BYTE) temp;
		temp = (temp+1)>>8; /* Evaluates to 1 if `temp' was FF, else 0. */
		t = 8-temp;
		temp = 0;
	}
	temp += temp + symbol;
	t--;
}

⌨️ 快捷键说明

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