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

📄 jpg2kmqdecoder.cpp

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

long CJPG2KMQDecoder::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 CJPG2KMQDecoder::m_TransitionTable[94];

void CJPG2KMQDecoder::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.
		m_TransitionTable[n].m_mps.InitDecoder(new_Sigma,new_s);
		// Now build the LPS transition state.
		new_Sigma = Sigma_lps[Sigma];
		new_s = s;
		if ((m_pBarTable[Sigma] == 0x5601) && (Sigma != 46))
			new_s = 1-s;
		m_TransitionTable[n].m_lps.InitDecoder(new_Sigma,new_s);
	}
}

void CJPG2KMQDecoder::Start(LPBYTE pBuffer, int nSegmentLength, int bMQSegment)
{
	m_bActive = 1;
	m_bMQSegment = bMQSegment;
	m_pBufStart = m_pBufNext = pBuffer;
	m_nSegmentLength = nSegmentLength;
	m_OverwrittenBytes[0] = pBuffer[nSegmentLength];
	m_OverwrittenBytes[1] = pBuffer[nSegmentLength+1];
	pBuffer[nSegmentLength] = pBuffer[nSegmentLength+1] = 0xFF; // Force termination
	m_bCheckedOut = 0;
	if (bMQSegment)
	{
		m_nS = m_temp = m_C = m_t = 0;
		FillLsbs();
		m_C <<= m_t;
		FillLsbs();
		m_C <<= 7;
		m_t -= 7;
		m_A = MQD_A_MIN;
	}
	else
	{
		m_t=0; m_temp = 0;
	}
}

/*****************************************************************************/
/* CJPG2KMQDecoder::finish*/
/*****************************************************************************/
int CJPG2KMQDecoder::Finish(int nCheckErterm)
{
	int failure = false;

	if (nCheckErterm && m_bMQSegment)
	{ // Check correct termination of MQ segment.
		if (m_pBufNext <= (m_pBufStart+m_nSegmentLength))
			failure = true; // We never read the terminating marker code
		else
		{
			m_nS++; // Include first FF of marker code as a synthesized FF.
			if (m_t == 0)
			{ 
				m_nS++; 
				m_t = 8; 
			}
			if ((m_nS < 2) || (m_nS > 3) || ((m_C>>(24-m_t)) != 0))
				failure = true;
		}
	}
	else if (nCheckErterm)
	{ // Check correct termination of raw segment.
		long x = 0x55;
		if ((m_pBufNext < (m_pBufStart+m_nSegmentLength)) &&
			(m_temp == 0xFF) && (m_t == 0))
		{ // Last byte may have been created by bit stuff.
			m_temp = *(m_pBufNext++); 
			m_t = 8; 
			x = 0x2A;
		}
		if ((m_pBufNext != (m_pBufStart+m_nSegmentLength)) ||
			((m_temp & ~((-1)<<m_t)) != (x>>(8-m_t))))
			failure = true;
	}

	m_pBufStart[m_nSegmentLength] = m_OverwrittenBytes[0];
	m_pBufStart[m_nSegmentLength+1] = m_OverwrittenBytes[1];
	m_bActive = false;
	m_pBufStart = m_pBufNext = NULL;
	return !failure;
}

void CJPG2KMQDecoder::FillLsbs()
{
	if (m_temp == 0xFF)
	{ // Need to check for termination
		m_temp = *(m_pBufNext++);
		if (m_temp > 0x8F)
		{ // Termination marker found.
			m_temp = 0xFF;
			m_pBufNext--;
			m_t = 8;
			m_nS++; // Increment S for each synthesized FF after 1'st byte of marker
		}
		else
		{ // Bit stuff found
			m_temp <<= 1;
			m_t = 7;
		}
	}
	else
	{
		m_temp = *(m_pBufNext++);
		m_t = 8;
	}
	m_C += m_temp;
}

/* 
Direct implementation of the first version given in Section 17.1.1 of the
book by Taubman and Marcellin.  The macro implements the second
version of the decoding algorithm, which is substantially less
fathomable. 
*/
void CJPG2KMQDecoder::MQDecode(long &symbol, CJPG2KMQEState &state)

{
	symbol = state.m_p_bar_mps & 1; // Set to MPS for now.
	long shifted_p_bar = state.m_p_bar_mps - symbol;
	m_A -= shifted_p_bar;
	if (m_C >= shifted_p_bar)
	{ // Upper sub-interval selected
		m_C -= shifted_p_bar;
		if (m_A < MQD_A_MIN)
		{ // Need renormalization and perhaps conditional exchange
			if (m_A < shifted_p_bar)
			{ // Conditional exchange; LPS decoded
				symbol = 1-symbol;
				state = state.m_pTransition->m_lps;
			}
			else
			{ // MPS decoded
				state = state.m_pTransition->m_mps;
			}
			do {
				if (m_t == 0)
					FillLsbs();
				m_A += m_A; 
				m_C += m_C; 
				m_t--;
			} while (m_A < MQD_A_MIN);
		}
	}
	else
	{ // Lower sub-interval selected; renormalization is inevitable
		if (m_A < shifted_p_bar)
		{ // Conditional exchange; MPS decoded
			state = state.m_pTransition->m_mps;
		}
		else
		{ // LPS decoded
			symbol = 1-symbol;
			state = state.m_pTransition->m_lps;
		}
		m_A = shifted_p_bar;
		do {
			if (m_t == 0)
				FillLsbs();
			m_A += m_A;
			m_C += m_C; 
			m_t--;
		} while (m_A < MQD_A_MIN);
	}
}

/*****************************************************************************/
/*CJPG2KMQDecoder::mq_decode_run*/
/*****************************************************************************/
void CJPG2KMQDecoder::MQDecodeRun(long &run)
{
	CJPG2KMQEState state;
	long symbol;

	state.InitDecoder(46,0);
	MQDecode(symbol,state);
	run = symbol + symbol;
	MQDecode(symbol,state);
	run += symbol;
}

/*****************************************************************************/
/*CJPG2KMQDecoder::raw_decode*/
/*****************************************************************************/
void CJPG2KMQDecoder::RawDecode(long &symbol)
{
	if (m_t == 0){
		if (m_temp == 0xFF){
			// Need to check for terminating marker, FFFF
			m_temp = *(m_pBufNext++);
			if (m_temp == 0xFF)
			{ 
				m_pBufNext--; 
				m_t = 8; 
			}
			else
				m_t = 7;
		}
		else{ 
			m_temp = *(m_pBufNext++); 
			m_t = 8; 
		}
	}
	m_t--;
	symbol = (m_temp>>m_t)&1;
}

void	CJPG2KMQDecoder::FillLsbs(long &C,long &t,long &temp,LPBYTE &store,long &S)
{
	t = 8;
	if (temp == 0xFF)
	{ /* Only need to check for termination inside here. */
		temp = *(store++); 
		if (temp > 0x8F) /* Termination marker: remain here indefinitely. */
		{ temp = 0xFF; store--; S++; }
		else
		{ t = 7; C += temp; } /* This way, we add two copies of `temp' */
	}
	else
		temp = *(store++);
	C += temp;
}

void CJPG2KMQDecoder::MQDecode(long &symbol,CJPG2KMQEState &state,long &A,long &C,
								long &D,long &t,long &temp,LPBYTE &store,long &S)
{
	symbol = (state).m_p_bar_mps;
	D -= symbol; 
	symbol &= 1; 
	D += symbol;
	if (D < 0)
	{ /* Non-CDP decoding follows. Renormalization is inevitable. */
		A += D; 
		C += D;
		D = (state).m_p_bar_mps - symbol;
		if (C >= 0) /* True if and only if C_active >= 0 */
		{ /* Upper sub-interval selected; must have A < A_min. */
			if (A < D)
			{ /* Conditional exchange; LPS is decoded */
				symbol = 1-symbol;
				state = (state).m_pTransition->m_lps;
			}
			else
			{ /* MPS is decoded */
				state = (state).m_pTransition->m_mps;
			}
		}
		else
		{ /* Lower sub-interval selected */
			C += D; /* Put back p_bar */
			if (A < D)
			{ /* Conditional exchange; MPS is decoded */
				state = (state).m_pTransition->m_mps;
			}
			else
			{ /* LPS is decoded. */
				symbol = 1-symbol;
				state = (state).m_pTransition->m_lps;
			}
			A = D;  /* Remeber that D is p_bar here. */
		}
		do {
			if (t == 0)
				FillLsbs(C,t,temp,store,S);
			A += A; 
			C += C; 
			t--; 
		} while (A < MQD_A_MIN);
		D = A-MQD_A_MIN;
		if (C < D)
			D = C; 
		A -= D; 
		C -= D; /* We will add D back again at the next non-CDP. */
	}
}

void CJPG2KMQDecoder::MQDecodeRun(long &run,long &A,long &C,long &D,
								long &t,long &temp,LPBYTE &store,long &S)
{
	run = 0;
	D -= 0x00560100; 
	if (D < 0)
	{ /* Non-CDP decoding follows. Renormalization is inevitable. */
		A += D; C += D;
		if (C >= 0) /* True if and only if C_active >= 0 */
		{ /* Upper sub-interval selected; must have A < A_min. */
			if (A < 0x00560100)
				run = 2; 
		}
		else
		{ /* Lower sub-interval selected */
			C += 0x00560100; /* Put back p_bar */ 
			if (A >= 0x00560100) 
				run = 2; 
			A = 0x00560100;
		}
		do {
			if (t == 0)
				FillLsbs(C,t,temp,store,S);
			A += A; 
			C += C; 
			t--; 
		} while (A < MQD_A_MIN);
		D = A-MQD_A_MIN;
		if (C < D)
			D = C; 
		A -= D; 
		C -= D; /* We will add D back again at the next non-CDP. */
	}
	D -= 0x00560100; 
	if (D < 0)
	{ /* Non-CDP decoding follows. Renormalization is inevitable. */
		A += D; C += D;
		if (C >= 0) /* True if and only if C_active >= 0 */
		{ /* Upper sub-interval selected; must have A < A_min. */
			if (A < 0x00560100)
				run++; 
		}
		else
		{ /* Lower sub-interval selected */
			C += 0x00560100; /* Put back p_bar */ 
			if (A >= 0x00560100) 
				run++; 
			A = 0x00560100;
		}
		do {
			if (t == 0)
				FillLsbs(C,t,temp,store,S);
			A += A; C += C; t--; 
		} while (A < MQD_A_MIN);
		D = A-MQD_A_MIN;
		if (C < D)
			D = C; 
		A -= D; C -= D; /* We will add D back again at the next non-CDP. */
	}
}

void CJPG2KMQDecoder::RawDecode(long &symbol,long &t,long &temp,LPBYTE &store)
{
	if (t == 0)
	{
		t = 8;
		if (temp == 0xFF)
		{ /* Need to check for terminating marker (we use FFFF). */
			temp = *(store++); 
			if (temp == 0xFF)
				store--; 
			else 
				t = 7; 
		}
		else
			temp = *(store++);
	}
	t--;
	symbol = (temp>>t) & 1;
}

⌨️ 快捷键说明

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