mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-06-05 21:59:17 +02:00
JBIG2 - arithmetic decoder bugfixing
This commit is contained in:
@@ -351,11 +351,23 @@ static constexpr PDFJBIG2ArithmeticDecoderQeValue JBIG2_ARITHMETIC_DECODER_QE_VA
|
||||
{ 0x56010000, 46, 46, 0 }
|
||||
};
|
||||
|
||||
uint32_t PDFJBIG2ArithmeticDecoder::readByte(size_t context, PDFJBIG2ArithmeticDecoderState* state)
|
||||
{
|
||||
uint32_t byte = 0;
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
byte = (byte << 1) | readBit(context, state);
|
||||
}
|
||||
|
||||
return byte;
|
||||
}
|
||||
|
||||
void PDFJBIG2ArithmeticDecoder::perform_INITDEC()
|
||||
{
|
||||
// Used figure G.1, in annex G, of specification
|
||||
uint32_t B = m_reader->readUnsignedByte();
|
||||
m_c = (B ^ 0xFF) << 16;
|
||||
m_lastByte = B;
|
||||
m_c = B << 16;
|
||||
perform_BYTEIN();
|
||||
m_c = m_c << 7;
|
||||
m_ct -= 7;
|
||||
@@ -365,24 +377,26 @@ void PDFJBIG2ArithmeticDecoder::perform_INITDEC()
|
||||
void PDFJBIG2ArithmeticDecoder::perform_BYTEIN()
|
||||
{
|
||||
// Used figure G.3, in annex G, of specification
|
||||
const uint32_t B = m_reader->readUnsignedByte();
|
||||
if (B == 0xFF)
|
||||
if (m_lastByte == 0xFF)
|
||||
{
|
||||
const uint32_t B1 = m_reader->look(8);
|
||||
if (B1 > 0x8F)
|
||||
{
|
||||
m_c += 0xFF00;
|
||||
m_ct = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_c = m_c + (0xFE00 - (B << 9));
|
||||
m_c = m_c + (B1 << 9);
|
||||
m_ct = 7;
|
||||
m_reader->readUnsignedByte();
|
||||
m_lastByte = m_reader->readUnsignedByte();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_c = m_c + (0xFF00 - (B << 8));
|
||||
const uint32_t B = m_reader->readUnsignedByte();
|
||||
m_lastByte = B;
|
||||
m_c = m_c + (B << 8);
|
||||
m_ct = 8;
|
||||
}
|
||||
}
|
||||
@@ -402,8 +416,11 @@ uint32_t PDFJBIG2ArithmeticDecoder::perform_DECODE(size_t context, PDFJBIG2Arith
|
||||
const uint32_t Qe = QeInfo.Qe;
|
||||
m_a -= Qe;
|
||||
|
||||
if (m_c < m_a)
|
||||
if (m_c >= Qe)
|
||||
{
|
||||
// We are substracting this value according figure E.15 in the specification
|
||||
m_c -= Qe;
|
||||
|
||||
if ((m_a & 0x80000000) == 0)
|
||||
{
|
||||
// We must perform MPS_EXCHANGE algorithm, according to figure E.16, in annex E, of specification
|
||||
@@ -430,9 +447,6 @@ uint32_t PDFJBIG2ArithmeticDecoder::perform_DECODE(size_t context, PDFJBIG2Arith
|
||||
}
|
||||
else
|
||||
{
|
||||
m_c -= m_a;
|
||||
m_a = Qe;
|
||||
|
||||
// We must perform LPS_EXCHANGE algorithm, according to figure E.17, in annex E, of specification
|
||||
if (m_a < Qe)
|
||||
{
|
||||
@@ -447,6 +461,8 @@ uint32_t PDFJBIG2ArithmeticDecoder::perform_DECODE(size_t context, PDFJBIG2Arith
|
||||
}
|
||||
state->setQeRowIndexAndMPS(context, QeInfo.newLPS, MPS);
|
||||
}
|
||||
|
||||
m_a = Qe;
|
||||
}
|
||||
|
||||
// Perform RENORMD algorithm, according to figure E.18, in annex E, of specification
|
||||
@@ -1454,4 +1470,9 @@ std::vector<PDFJBIG2HuffmanTableEntry> PDFJBIG2HuffmanCodeTable::buildPrefixes(c
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t PDFJBIG2ArithmeticDecoderState::getQe(size_t context) const
|
||||
{
|
||||
return JBIG2_ARITHMETIC_DECODER_QE_VALUES[getQeRowIndex(context)].Qe;
|
||||
}
|
||||
|
||||
} // namespace pdf
|
||||
|
@@ -43,7 +43,7 @@ enum class PDFJBIG2BitOperation
|
||||
/// state is stored as 8-bit value, where only 7 bits are used. 6 bits are used
|
||||
/// to store Qe value index (current row in the table, number 0-46), and lowest 1 bit
|
||||
/// is used to store current MPS value (most probable symbol - 0/1).
|
||||
class PDFJBIG2ArithmeticDecoderState
|
||||
class PDFFORQTLIBSHARED_EXPORT PDFJBIG2ArithmeticDecoderState
|
||||
{
|
||||
public:
|
||||
explicit inline PDFJBIG2ArithmeticDecoderState() = default;
|
||||
@@ -72,6 +72,10 @@ public:
|
||||
return m_state[context] >> 1;
|
||||
}
|
||||
|
||||
/// Returns Qe value for row index, according to document ISO/IEC 14492:2001,
|
||||
/// annex E, table E.1 (Qe values and probability estimation process).
|
||||
inline uint32_t getQe(size_t context) const;
|
||||
|
||||
/// Returns current bit value of MPS (most probable symbol)
|
||||
inline uint8_t getMPS(size_t context) const
|
||||
{
|
||||
@@ -96,13 +100,14 @@ private:
|
||||
/// of decoder described in document ISO/IEC 14492:2001, T.88, annex G (arithmetic decoding
|
||||
/// procedure). It uses 32-bit fixed point arithmetic instead of 16-bit fixed point
|
||||
/// arithmetic described in the specification (it is much faster).
|
||||
class PDFJBIG2ArithmeticDecoder
|
||||
class PDFFORQTLIBSHARED_EXPORT PDFJBIG2ArithmeticDecoder
|
||||
{
|
||||
public:
|
||||
explicit inline PDFJBIG2ArithmeticDecoder(PDFBitReader* reader) :
|
||||
m_c(0),
|
||||
m_a(0),
|
||||
m_ct(0),
|
||||
m_lastByte(0),
|
||||
m_reader(reader)
|
||||
{
|
||||
|
||||
@@ -110,6 +115,11 @@ public:
|
||||
|
||||
void initialize() { perform_INITDEC(); }
|
||||
uint32_t readBit(size_t context, PDFJBIG2ArithmeticDecoderState* state) { return perform_DECODE(context, state); }
|
||||
uint32_t readByte(size_t context, PDFJBIG2ArithmeticDecoderState* state);
|
||||
|
||||
uint32_t getRegisterC() const { return m_c; }
|
||||
uint32_t getRegisterA() const { return m_a; }
|
||||
uint32_t getRegisterCT() const { return m_ct; }
|
||||
|
||||
private:
|
||||
/// Performs INITDEC operation as described in the specification
|
||||
@@ -136,6 +146,9 @@ private:
|
||||
/// Number of current unprocessed bits.
|
||||
uint32_t m_ct;
|
||||
|
||||
/// Last processed byte
|
||||
uint8_t m_lastByte;
|
||||
|
||||
/// Data source to read from
|
||||
PDFBitReader* m_reader;
|
||||
};
|
||||
|
@@ -89,7 +89,7 @@ private:
|
||||
|
||||
/// Bit-reader, which can read n-bit unsigned integers from the stream.
|
||||
/// Number of bits can be set in the constructor and is constant.
|
||||
class PDFBitReader
|
||||
class PDFFORQTLIBSHARED_EXPORT PDFBitReader
|
||||
{
|
||||
public:
|
||||
using Value = uint64_t;
|
||||
|
Reference in New Issue
Block a user