📄 jpg2kmqencoder.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 + -