Files
core/ASCOfficePDFReader/JBIG2Stream.cpp

3940 lines
96 KiB
C++
Raw Blame History

#include "stdafx.h"
#include <stdlib.h>
#include <limits.h>
#include "List.h"
#include "Error.h"
#include "JArithmeticDecoder.h"
#include "JBIG2Stream.h"
//~ share these tables
#include "CCITT-Tables.h"
//------------------------------------------------------------------------
static int c_arrContextSize[4] = { 16, 13, 10, 10 };
static int c_arrRefContextSize[2] = { 13, 10 };
//------------------------------------------------------------------------
// JBIG2HuffmanTable
//------------------------------------------------------------------------
#define jbig2HuffmanLOW 0xfffffffd
#define jbig2HuffmanOOB 0xfffffffe
#define jbig2HuffmanEOT 0xffffffff
struct JBIG2HuffmanTable
{
int nValue;
unsigned int unPrefixLen;
unsigned int unRangeLen; // can also be LOW, OOB, or EOT
unsigned int unPrefix;
};
JBIG2HuffmanTable c_oHuffTableA[] =
{
{ 0, 1, 4, 0x000 },
{ 16, 2, 8, 0x002 },
{ 272, 3, 16, 0x006 },
{ 65808, 3, 32, 0x007 },
{ 0, 0, jbig2HuffmanEOT, 0 }
};
JBIG2HuffmanTable c_oHuffTableB[] =
{
{ 0, 1, 0, 0x000 },
{ 1, 2, 0, 0x002 },
{ 2, 3, 0, 0x006 },
{ 3, 4, 3, 0x00e },
{ 11, 5, 6, 0x01e },
{ 75, 6, 32, 0x03e },
{ 0, 6, jbig2HuffmanOOB, 0x03f },
{ 0, 0, jbig2HuffmanEOT, 0 }
};
JBIG2HuffmanTable c_oHuffTableC[] =
{
{ 0, 1, 0, 0x000 },
{ 1, 2, 0, 0x002 },
{ 2, 3, 0, 0x006 },
{ 3, 4, 3, 0x00e },
{ 11, 5, 6, 0x01e },
{ 0, 6, jbig2HuffmanOOB, 0x03e },
{ 75, 7, 32, 0x0fe },
{ -256, 8, 8, 0x0fe },
{ -257, 8, jbig2HuffmanLOW, 0x0ff },
{ 0, 0, jbig2HuffmanEOT, 0 }
};
JBIG2HuffmanTable c_oHuffTableD[] =
{
{ 1, 1, 0, 0x000 },
{ 2, 2, 0, 0x002 },
{ 3, 3, 0, 0x006 },
{ 4, 4, 3, 0x00e },
{ 12, 5, 6, 0x01e },
{ 76, 5, 32, 0x01f },
{ 0, 0, jbig2HuffmanEOT, 0 }
};
JBIG2HuffmanTable c_oHuffTableE[] =
{
{ 1, 1, 0, 0x000 },
{ 2, 2, 0, 0x002 },
{ 3, 3, 0, 0x006 },
{ 4, 4, 3, 0x00e },
{ 12, 5, 6, 0x01e },
{ 76, 6, 32, 0x03e },
{ -255, 7, 8, 0x07e },
{ -256, 7, jbig2HuffmanLOW, 0x07f },
{ 0, 0, jbig2HuffmanEOT, 0 }
};
JBIG2HuffmanTable c_oHuffTableF[] =
{
{ 0, 2, 7, 0x000 },
{ 128, 3, 7, 0x002 },
{ 256, 3, 8, 0x003 },
{ -1024, 4, 9, 0x008 },
{ -512, 4, 8, 0x009 },
{ -256, 4, 7, 0x00a },
{ -32, 4, 5, 0x00b },
{ 512, 4, 9, 0x00c },
{ 1024, 4, 10, 0x00d },
{ -2048, 5, 10, 0x01c },
{ -128, 5, 6, 0x01d },
{ -64, 5, 5, 0x01e },
{ -2049, 6, jbig2HuffmanLOW, 0x03e },
{ 2048, 6, 32, 0x03f },
{ 0, 0, jbig2HuffmanEOT, 0 }
};
JBIG2HuffmanTable c_oHuffTableG[] =
{
{ -512, 3, 8, 0x000 },
{ 256, 3, 8, 0x001 },
{ 512, 3, 9, 0x002 },
{ 1024, 3, 10, 0x003 },
{ -1024, 4, 9, 0x008 },
{ -256, 4, 7, 0x009 },
{ -32, 4, 5, 0x00a },
{ 0, 4, 5, 0x00b },
{ 128, 4, 7, 0x00c },
{ -128, 5, 6, 0x01a },
{ -64, 5, 5, 0x01b },
{ 32, 5, 5, 0x01c },
{ 64, 5, 6, 0x01d },
{ -1025, 5, jbig2HuffmanLOW, 0x01e },
{ 2048, 5, 32, 0x01f },
{ 0, 0, jbig2HuffmanEOT, 0 }
};
JBIG2HuffmanTable c_oHuffTableH[] =
{
{ 0, 2, 1, 0x000 },
{ 0, 2, jbig2HuffmanOOB, 0x001 },
{ 4, 3, 4, 0x004 },
{ -1, 4, 0, 0x00a },
{ 22, 4, 4, 0x00b },
{ 38, 4, 5, 0x00c },
{ 2, 5, 0, 0x01a },
{ 70, 5, 6, 0x01b },
{ 134, 5, 7, 0x01c },
{ 3, 6, 0, 0x03a },
{ 20, 6, 1, 0x03b },
{ 262, 6, 7, 0x03c },
{ 646, 6, 10, 0x03d },
{ -2, 7, 0, 0x07c },
{ 390, 7, 8, 0x07d },
{ -15, 8, 3, 0x0fc },
{ -5, 8, 1, 0x0fd },
{ -7, 9, 1, 0x1fc },
{ -3, 9, 0, 0x1fd },
{ -16, 9, jbig2HuffmanLOW, 0x1fe },
{ 1670, 9, 32, 0x1ff },
{ 0, 0, jbig2HuffmanEOT, 0 }
};
JBIG2HuffmanTable c_oHuffTableI[] =
{
{ 0, 2, jbig2HuffmanOOB, 0x000 },
{ -1, 3, 1, 0x002 },
{ 1, 3, 1, 0x003 },
{ 7, 3, 5, 0x004 },
{ -3, 4, 1, 0x00a },
{ 43, 4, 5, 0x00b },
{ 75, 4, 6, 0x00c },
{ 3, 5, 1, 0x01a },
{ 139, 5, 7, 0x01b },
{ 267, 5, 8, 0x01c },
{ 5, 6, 1, 0x03a },
{ 39, 6, 2, 0x03b },
{ 523, 6, 8, 0x03c },
{ 1291, 6, 11, 0x03d },
{ -5, 7, 1, 0x07c },
{ 779, 7, 9, 0x07d },
{ -31, 8, 4, 0x0fc },
{ -11, 8, 2, 0x0fd },
{ -15, 9, 2, 0x1fc },
{ -7, 9, 1, 0x1fd },
{ -32, 9, jbig2HuffmanLOW, 0x1fe },
{ 3339, 9, 32, 0x1ff },
{ 0, 0, jbig2HuffmanEOT, 0 }
};
JBIG2HuffmanTable c_oHuffTableJ[] =
{
{ -2, 2, 2, 0x000 },
{ 6, 2, 6, 0x001 },
{ 0, 2, jbig2HuffmanOOB, 0x002 },
{ -3, 5, 0, 0x018 },
{ 2, 5, 0, 0x019 },
{ 70, 5, 5, 0x01a },
{ 3, 6, 0, 0x036 },
{ 102, 6, 5, 0x037 },
{ 134, 6, 6, 0x038 },
{ 198, 6, 7, 0x039 },
{ 326, 6, 8, 0x03a },
{ 582, 6, 9, 0x03b },
{ 1094, 6, 10, 0x03c },
{ -21, 7, 4, 0x07a },
{ -4, 7, 0, 0x07b },
{ 4, 7, 0, 0x07c },
{ 2118, 7, 11, 0x07d },
{ -5, 8, 0, 0x0fc },
{ 5, 8, 0, 0x0fd },
{ -22, 8, jbig2HuffmanLOW, 0x0fe },
{ 4166, 8, 32, 0x0ff },
{ 0, 0, jbig2HuffmanEOT, 0 }
};
JBIG2HuffmanTable c_oHuffTableK[] =
{
{ 1, 1, 0, 0x000 },
{ 2, 2, 1, 0x002 },
{ 4, 4, 0, 0x00c },
{ 5, 4, 1, 0x00d },
{ 7, 5, 1, 0x01c },
{ 9, 5, 2, 0x01d },
{ 13, 6, 2, 0x03c },
{ 17, 7, 2, 0x07a },
{ 21, 7, 3, 0x07b },
{ 29, 7, 4, 0x07c },
{ 45, 7, 5, 0x07d },
{ 77, 7, 6, 0x07e },
{ 141, 7, 32, 0x07f },
{ 0, 0, jbig2HuffmanEOT, 0 }
};
JBIG2HuffmanTable c_oHuffTableL[] =
{
{ 1, 1, 0, 0x000 },
{ 2, 2, 0, 0x002 },
{ 3, 3, 1, 0x006 },
{ 5, 5, 0, 0x01c },
{ 6, 5, 1, 0x01d },
{ 8, 6, 1, 0x03c },
{ 10, 7, 0, 0x07a },
{ 11, 7, 1, 0x07b },
{ 13, 7, 2, 0x07c },
{ 17, 7, 3, 0x07d },
{ 25, 7, 4, 0x07e },
{ 41, 8, 5, 0x0fe },
{ 73, 8, 32, 0x0ff },
{ 0, 0, jbig2HuffmanEOT, 0 }
};
JBIG2HuffmanTable c_oHuffTableM[] =
{
{ 1, 1, 0, 0x000 },
{ 2, 3, 0, 0x004 },
{ 7, 3, 3, 0x005 },
{ 3, 4, 0, 0x00c },
{ 5, 4, 1, 0x00d },
{ 4, 5, 0, 0x01c },
{ 15, 6, 1, 0x03a },
{ 17, 6, 2, 0x03b },
{ 21, 6, 3, 0x03c },
{ 29, 6, 4, 0x03d },
{ 45, 6, 5, 0x03e },
{ 77, 7, 6, 0x07e },
{ 141, 7, 32, 0x07f },
{ 0, 0, jbig2HuffmanEOT, 0 }
};
JBIG2HuffmanTable c_oHuffTableN[] =
{
{ 0, 1, 0, 0x000 },
{ -2, 3, 0, 0x004 },
{ -1, 3, 0, 0x005 },
{ 1, 3, 0, 0x006 },
{ 2, 3, 0, 0x007 },
{ 0, 0, jbig2HuffmanEOT, 0 }
};
JBIG2HuffmanTable c_oHuffTableO[] =
{
{ 0, 1, 0, 0x000 },
{ -1, 3, 0, 0x004 },
{ 1, 3, 0, 0x005 },
{ -2, 4, 0, 0x00c },
{ 2, 4, 0, 0x00d },
{ -4, 5, 1, 0x01c },
{ 3, 5, 1, 0x01d },
{ -8, 6, 2, 0x03c },
{ 5, 6, 2, 0x03d },
{ -24, 7, 4, 0x07c },
{ 9, 7, 4, 0x07d },
{ -25, 7, jbig2HuffmanLOW, 0x07e },
{ 25, 7, 32, 0x07f },
{ 0, 0, jbig2HuffmanEOT, 0 }
};
//------------------------------------------------------------------------
// JBIG2HuffmanDecoder
//------------------------------------------------------------------------
class JBIG2HuffmanDecoder
{
public:
JBIG2HuffmanDecoder()
{
m_pStream = NULL;
Reset();
}
~JBIG2HuffmanDecoder()
{
}
void SetStream(Stream *pStream)
{
m_pStream = pStream;
}
void Reset()
{
unBuffer = 0;
unBufferLen = 0;
}
// Returns false for OOB, otherwise sets *<pnValue> and returns true.
//~ optimize this
BOOL DecodeInt(int *pnValue, JBIG2HuffmanTable *pTable)
{
unsigned int unIndex = 0, unPrefix = 0, unLen = 0;
while ( pTable[unIndex].unRangeLen != jbig2HuffmanEOT )
{
while ( unLen < pTable[unIndex].unPrefixLen )
{
unPrefix = (unPrefix << 1) | ReadBit();
++unLen;
}
if ( unPrefix == pTable[unIndex].unPrefix )
{
if ( pTable[unIndex].unRangeLen == jbig2HuffmanOOB )
{
return FALSE;
}
if ( pTable[unIndex].unRangeLen == jbig2HuffmanLOW )
{
*pnValue = pTable[unIndex].nValue - ReadBits(32);
}
else if ( pTable[unIndex].unRangeLen > 0 )
{
*pnValue = pTable[unIndex].nValue + ReadBits( pTable[unIndex].unRangeLen );
}
else
{
*pnValue = pTable[unIndex].nValue;
}
return TRUE;
}
++unIndex;
}
return FALSE;
}
unsigned int ReadBits(unsigned int unCount)
{
unsigned int unMask = (unCount == 32) ? 0xffffffff : ((1 << unCount) - 1);
unsigned int unValue;
if ( unBufferLen >= unCount )
{
unValue = (unBuffer >> (unBufferLen - unCount)) & unMask;
unBufferLen -= unCount;
}
else
{
unValue = unBuffer & ((1 << unBufferLen) - 1);
unsigned int unLeftCount = unCount - unBufferLen;
unBufferLen = 0;
while ( unLeftCount >= 8 )
{
unValue = (unValue << 8) | (m_pStream->GetChar() & 0xff);
unLeftCount -= 8;
}
if ( unLeftCount > 0 )
{
unBuffer = m_pStream->GetChar();
unBufferLen = 8 - unLeftCount;
unValue = (unValue << unLeftCount) | ((unBuffer >> unBufferLen) & ((1 << unLeftCount) - 1));
}
}
return unValue;
}
unsigned int ReadBit()
{
if ( unBufferLen == 0 )
{
unBuffer = m_pStream->GetChar();
unBufferLen = 8;
}
--unBufferLen;
return (unBuffer >> unBufferLen) & 1;
}
// Sort the table by prefix length and assign prefix values.
void BuildTable(JBIG2HuffmanTable *pTable, unsigned int unLen)
{
// stable selection sort:
// - entries with prefixLen > 0, in ascending prefixLen order
// - entry with prefixLen = 0, rangeLen = EOT
// - all other entries with prefixLen = 0
// (on entry, table[len] has prefixLen = 0, rangeLen = EOT)
unsigned int unI, unJ, unK;
for ( unI = 0; unI < unLen; ++unI )
{
for ( unJ = unI; unJ < unLen && pTable[unJ].unPrefixLen == 0; ++unJ );
if ( unJ == unLen )
{
break;
}
for ( unK = unJ + 1; unK < unLen; ++unK )
{
if ( pTable[unK].unPrefixLen > 0 && pTable[unK].unPrefixLen < pTable[unJ].unPrefixLen )
{
unJ = unK;
}
}
if ( unJ != unI )
{
JBIG2HuffmanTable oTable = pTable[unJ];
for ( unK = unJ; unK > unI; --unK )
{
pTable[unK] = pTable[unK - 1];
}
pTable[unI] = oTable;
}
}
pTable[unI] = pTable[unLen];
// assign prefixes
unI = 0;
unsigned int unPrefix = 0;
pTable[unI++].unPrefix = unPrefix++;
for ( ; pTable[unI].unRangeLen != jbig2HuffmanEOT; ++unI )
{
unPrefix <<= pTable[unI].unPrefixLen - pTable[unI - 1].unPrefixLen;
pTable[unI].unPrefix = unPrefix++;
}
}
private:
Stream *m_pStream;
unsigned int unBuffer;
unsigned int unBufferLen;
};
//------------------------------------------------------------------------
// JBIG2MMRDecoder
//------------------------------------------------------------------------
class JBIG2MMRDecoder
{
public:
JBIG2MMRDecoder()
{
m_pStream = NULL;
Reset();
}
~JBIG2MMRDecoder()
{
}
void SetStream(Stream *pStream)
{
m_pStream = pStream;
}
void Reset()
{
unBuffer = 0;
unBufferLen = 0;
unBytesReadCount = 0;
}
int Get2DCode()
{
CCITTCode *pCode = NULL;
if ( unBufferLen == 0 )
{
unBuffer = m_pStream->GetChar() & 0xff;
unBufferLen = 8;
++unBytesReadCount;
pCode = &c_arrTable2D[(unBuffer >> 1) & 0x7f];
}
else if ( unBufferLen == 8 )
{
pCode = &c_arrTable2D[(unBuffer >> 1) & 0x7f];
}
else
{
pCode = &c_arrTable2D[(unBuffer << (7 - unBufferLen)) & 0x7f];
if ( pCode->nBitsCount < 0 || pCode->nBitsCount > (int)unBufferLen )
{
unBuffer = (unBuffer << 8) | (m_pStream->GetChar() & 0xff);
unBufferLen += 8;
++unBytesReadCount;
pCode = &c_arrTable2D[(unBuffer >> (unBufferLen - 7)) & 0x7f];
}
}
if ( pCode->nBitsCount < 0 )
{
return 0;
}
unBufferLen -= pCode->nBitsCount;
return pCode->nCode;
}
int GetWhiteCode()
{
if ( unBufferLen == 0 )
{
unBuffer = m_pStream->GetChar() & 0xff;
unBufferLen = 8;
++unBytesReadCount;
}
while (1)
{
CCITTCode *pCode = NULL;
if ( unBufferLen >= 7 && ((unBuffer >> (unBufferLen - 7)) & 0x7f) == 0 )
{
unsigned int unCode;
if ( unBufferLen <= 12 )
{
unCode = unBuffer << (12 - unBufferLen);
}
else
{
unCode = unBuffer >> (unBufferLen - 12);
}
pCode = &c_arrWhiteTable1[unCode & 0x1f];
}
else
{
unsigned int unCode;
if ( unBufferLen <= 9 )
{
unCode = unBuffer << (9 - unBufferLen);
}
else
{
unCode = unBuffer >> (unBufferLen - 9);
}
pCode = &c_arrWhiteTable2[unCode & 0x1ff];
}
if ( pCode->nBitsCount > 0 && pCode->nBitsCount <= (int)unBufferLen )
{
unBufferLen -= pCode->nBitsCount;
return pCode->nCode;
}
if ( unBufferLen >= 12 )
{
break;
}
unBuffer = (unBuffer << 8) | (m_pStream->GetChar() & 0xff);
unBufferLen += 8;
++unBytesReadCount;
}
// eat a bit and return a positive number so that the caller doesn't
// go into an infinite loop
--unBufferLen;
return 1;
}
int GetBlackCode()
{
if ( unBufferLen == 0 )
{
unBuffer = m_pStream->GetChar() & 0xff;
unBufferLen = 8;
++unBytesReadCount;
}
while (1)
{
CCITTCode *pCode = NULL;
if ( unBufferLen >= 6 && ((unBuffer >> (unBufferLen - 6)) & 0x3f) == 0 )
{
unsigned int unCode;
if ( unBufferLen <= 13 )
{
unCode = unBuffer << (13 - unBufferLen);
}
else
{
unCode = unBuffer >> (unBufferLen - 13);
}
pCode = &c_arrBlackTable1[unCode & 0x7f];
}
else if ( unBufferLen >= 4 && ((unBuffer >> (unBufferLen - 4)) & 0x0f) == 0 )
{
unsigned int unCode;
if ( unBufferLen <= 12 )
{
unCode = unBuffer << (12 - unBufferLen);
}
else
{
unCode = unBuffer >> (unBufferLen - 12);
}
pCode = &c_arrBlackTable2[(unCode & 0xff) - 64];
}
else
{
unsigned int unCode;
if ( unBufferLen <= 6 )
{
unCode = unBuffer << (6 - unBufferLen);
}
else
{
unCode = unBuffer >> (unBufferLen - 6);
}
pCode = &c_arrBlackTable3[unCode & 0x3f];
}
if ( pCode->nBitsCount > 0 && pCode->nBitsCount <= (int)unBufferLen )
{
unBufferLen -= pCode->nBitsCount;
return pCode->nCode;
}
if ( unBufferLen >= 13 )
{
break;
}
unBuffer = (unBuffer << 8) | (m_pStream->GetChar() & 0xff);
unBufferLen += 8;
++unBytesReadCount;
}
// eat a bit and return a positive number so that the caller doesn't
// go into an infinite loop
--unBufferLen;
return 1;
}
unsigned int Get24Bits()
{
while ( unBufferLen < 24 )
{
unBuffer = (unBuffer << 8) | (m_pStream->GetChar() & 0xff);
unBufferLen += 8;
++unBytesReadCount;
}
return (unBuffer >> (unBufferLen - 24)) & 0xffffff;
}
void SkipTo(unsigned int unLength)
{
while ( unBytesReadCount < unLength )
{
m_pStream->GetChar();
++unBytesReadCount;
}
}
private:
Stream *m_pStream;
unsigned int unBuffer;
unsigned int unBufferLen;
unsigned int unBytesReadCount;
};
//------------------------------------------------------------------------
// JBIG2Segment
//------------------------------------------------------------------------
enum JBIG2SegmentType
{
jbig2SegBitmap,
jbig2SegSymbolDict,
jbig2SegPatternDict,
jbig2SegCodeTable
};
class JBIG2Segment
{
public:
JBIG2Segment(unsigned int unSegNum)
{
m_unSegNum = unSegNum;
}
virtual ~JBIG2Segment()
{
}
void SetSegNum(unsigned int unSegNum)
{
m_unSegNum = unSegNum;
}
unsigned int GetSegNum()
{
return m_unSegNum;
}
virtual JBIG2SegmentType GetType() = 0;
private:
unsigned int m_unSegNum;
};
//------------------------------------------------------------------------
// JBIG2Bitmap
//------------------------------------------------------------------------
struct JBIG2BitmapPtr
{
unsigned char *pDataPtr;
int nShift;
int nX;
};
class JBIG2Bitmap: public JBIG2Segment
{
public:
JBIG2Bitmap(unsigned int unSegNum, int nW, int nH): JBIG2Segment(unSegNum)
{
m_nW = nW;
m_nH = nH;
m_nLine = (nW + 7) >> 3;
if ( m_nW <= 0 || m_nH <= 0 || m_nLine <= 0 || m_nH >= (INT_MAX - 1) / m_nLine )
{
m_pData = NULL;
return;
}
// need to allocate one extra guard byte for use in Combine()
m_pData = (unsigned char *)MemUtilsMalloc(m_nH * m_nLine + 1);
m_pData[m_nH * m_nLine] = 0;
}
virtual ~JBIG2Bitmap()
{
MemUtilsFree(m_pData);
}
virtual JBIG2SegmentType GetType()
{
return jbig2SegBitmap;
}
JBIG2Bitmap *Copy()
{
return new JBIG2Bitmap( 0, this );
}
//~ optimize this
JBIG2Bitmap *GetSlice(unsigned int unX, unsigned int unY, unsigned int unW, unsigned int unH)
{
JBIG2Bitmap *pSlice = new JBIG2Bitmap( 0, unW, unH );
pSlice->ClearToZero();
for ( unsigned int unCurY = 0; unCurY < unH; ++unCurY )
{
for ( unsigned int unCurX = 0; unCurX < unW; ++unCurX )
{
if ( GetPixel( unX + unCurX, unY + unCurY ) )
{
pSlice->SetPixel( unCurX, unCurY );
}
}
}
return pSlice;
}
void Expand(int nNewH, unsigned int unPixel)
{
if ( nNewH <= m_nH || m_nLine <= 0 || nNewH >= (INT_MAX - 1) / m_nLine )
{
return;
}
// need to allocate one extra guard byte for use in combine()
m_pData = (unsigned char *)MemUtilsRealloc( m_pData, nNewH * m_nLine + 1 );
if ( unPixel )
{
memset( m_pData + m_nH * m_nLine, 0xff, (nNewH - m_nH) * m_nLine );
}
else
{
memset( m_pData + m_nH * m_nLine, 0x00, (nNewH - m_nH) * m_nLine );
}
m_nH = nNewH;
m_pData[m_nH * m_nLine] = 0;
}
void ClearToZero()
{
memset( m_pData, 0, m_nH * m_nLine );
}
void ClearToOne()
{
memset( m_pData, 0xff, m_nH * m_nLine );
}
int GetWidth()
{
return m_nW;
}
int GetHeight()
{
return m_nH;
}
int GetPixel (int nX, int nY)
{
return ( nX < 0 || nX >= m_nW || nY < 0 || nY >= m_nH ) ? 0 : ( m_pData[nY * m_nLine + (nX >> 3)] >> (7 - (nX & 7))) & 1;
}
void SetPixel (int nX, int nY)
{
m_pData[nY * m_nLine + (nX >> 3)] |= 1 << (7 - (nX & 7));
}
void ClearPixel(int nX, int nY)
{
m_pData[nY * m_nLine + (nX >> 3)] &= 0x7f7f >> (nX & 7);
}
inline void GetPixelPtr(int nX, int nY, JBIG2BitmapPtr *pPtr)
{
if ( nY < 0 || nY >= m_nH || nX >= m_nW )
{
pPtr->pDataPtr = NULL;
}
else if ( nX < 0 )
{
pPtr->pDataPtr = &m_pData[nY * m_nLine];
pPtr->nShift = 7;
pPtr->nX = nX;
}
else
{
pPtr->pDataPtr = &m_pData[nY * m_nLine + (nX >> 3)];
pPtr->nShift = 7 - (nX & 7);
pPtr->nX = nX;
}
}
inline int NextPixel (JBIG2BitmapPtr *pPtr)
{
int nPixel;
if ( !pPtr->pDataPtr )
{
nPixel = 0;
}
else if ( pPtr->nX < 0 )
{
++pPtr->nX;
nPixel = 0;
}
else
{
nPixel = (*pPtr->pDataPtr >> pPtr->nShift) & 1;
if ( ++pPtr->nX == m_nW )
{
pPtr->pDataPtr = NULL;
}
else if ( pPtr->nShift == 0 )
{
++pPtr->pDataPtr;
pPtr->nShift = 7;
}
else
{
--pPtr->nShift;
}
}
return nPixel;
}
void DuplicateRow(int nDstY, int nSrcY)
{
memcpy( m_pData + nDstY * m_nLine, m_pData + nSrcY * m_nLine, m_nLine );
}
void Combine(JBIG2Bitmap *pBitmap, int nX, int nY, unsigned int unCombOp)
{
int nY0;
if ( nY < 0 )
{
nY0 = -nY;
}
else
{
nY0 = 0;
}
int nY1;
if ( nY + pBitmap->m_nH > m_nH )
{
nY1 = m_nH - nY;
}
else
{
nY1 = pBitmap->m_nH;
}
if ( nY0 >= nY1 )
{
return;
}
int nX0;
if ( nX >= 0 )
{
nX0 = nX & ~7;
}
else
{
nX0 = 0;
}
int nX1 = nX + pBitmap->m_nW;
if ( nX1 > m_nW )
{
nX1 = m_nW;
}
if ( nX0 >= nX1 )
{
return;
}
unsigned int unS1 = nX & 7;
unsigned int unS2 = 8 - unS1;
unsigned int unM1 = 0xff >> (nX1 & 7);
unsigned int unM2 = 0xff << (((nX1 & 7) == 0) ? 0 : 8 - (nX1 & 7));
unsigned int unM3 = (0xff >> unS1) & unM2;
BOOL bOneByte = ( nX0 == ((nX1 - 1) & ~7) );
unsigned char *pSrcPtr, *pDstPtr;
for ( int nCurY = nY0; nCurY < nY1; ++nCurY )
{
// one byte per line -- need to mask both left and right side
if ( bOneByte )
{
unsigned int unSrc1, unDst;
if ( nX >= 0 )
{
pDstPtr = m_pData + ( nY + nCurY ) * m_nLine + ( nX >> 3 );
pSrcPtr = pBitmap->m_pData + nCurY * pBitmap->m_nLine;
unDst = *pDstPtr;
unSrc1 = *pSrcPtr;
switch ( unCombOp )
{
case 0: // or
unDst |= (unSrc1 >> unS1) & unM2;
break;
case 1: // and
unDst &= ((0xff00 | unSrc1) >> unS1) | unM1;
break;
case 2: // xor
unDst ^= (unSrc1 >> unS1) & unM2;
break;
case 3: // xnor
unDst ^= ((unSrc1 ^ 0xff) >> unS1) & unM2;
break;
case 4: // replace
unDst = (unDst & ~unM3) | ((unSrc1 >> unS1) & unM3);
break;
}
*pDstPtr = unDst;
}
else
{
pDstPtr = m_pData + ( nY + nCurY ) * m_nLine;
pSrcPtr = pBitmap->m_pData + nCurY * pBitmap->m_nLine + ( -nX >> 3 );
unDst = *pDstPtr;
unSrc1 = *pSrcPtr;
switch ( unCombOp )
{
case 0: // or
unDst |= unSrc1 & unM2;
break;
case 1: // and
unDst &= unSrc1 | unM1;
break;
case 2: // xor
unDst ^= unSrc1 & unM2;
break;
case 3: // xnor
unDst ^= (unSrc1 ^ 0xff) & unM2;
break;
case 4: // replace
unDst = (unSrc1 & unM2) | (unDst & unM1);
break;
}
*pDstPtr = unDst;
}
}
else // multiple bytes per line -- need to mask left side of left-most byte and right side of right-most byte
{
int nCurX;
unsigned int unSrc0, unSrc1, unSrc, unDst;
if ( nX >= 0 ) // left-most byte
{
pDstPtr = m_pData + ( nY + nCurY ) * m_nLine + ( nX >> 3 );
pSrcPtr = pBitmap->m_pData + nCurY * pBitmap->m_nLine;
unSrc1 = *pSrcPtr++;
unDst = *pDstPtr;
switch ( unCombOp )
{
case 0: // or
unDst |= unSrc1 >> unS1;
break;
case 1: // and
unDst &= (0xff00 | unSrc1) >> unS1;
break;
case 2: // xor
unDst ^= unSrc1 >> unS1;
break;
case 3: // xnor
unDst ^= (unSrc1 ^ 0xff) >> unS1;
break;
case 4: // replace
unDst = (unDst & (0xff << unS2)) | (unSrc1 >> unS1);
break;
}
*pDstPtr++ = unDst;
nCurX = nX0 + 8;
}
else
{
pDstPtr = m_pData + ( nY + nCurY ) * m_nLine;
pSrcPtr = pBitmap->m_pData + nCurY * pBitmap->m_nLine + ( -nX >> 3 );
unSrc1 = *pSrcPtr++;
nCurX = nX0;
}
// middle bytes
for ( ; nCurX < nX1 - 8; nCurX += 8 )
{
unDst = *pDstPtr;
unSrc0 = unSrc1;
unSrc1 = *pSrcPtr++;
unSrc = (((unSrc0 << 8) | unSrc1) >> unS1) & 0xff;
switch ( unCombOp )
{
case 0: // or
unDst |= unSrc;
break;
case 1: // and
unDst &= unSrc;
break;
case 2: // xor
unDst ^= unSrc;
break;
case 3: // xnor
unDst ^= unSrc ^ 0xff;
break;
case 4: // replace
unDst = unSrc;
break;
}
*pDstPtr++ = unDst;
}
// right-most byte
// note: this last byte (src1) may not actually be used, depending
// on the values of s1, m1, and m2 - and in fact, it may be off
// the edge of the source bitmap, which means we need to allocate
// one extra guard byte at the end of each bitmap
unDst = *pDstPtr;
unSrc0 = unSrc1;
unSrc1 = *pSrcPtr++;
unSrc = (((unSrc0 << 8) | unSrc1) >> unS1) & 0xff;
switch ( unCombOp )
{
case 0: // or
unDst |= unSrc & unM2;
break;
case 1: // and
unDst &= unSrc | unM1;
break;
case 2: // xor
unDst ^= unSrc & unM2;
break;
case 3: // xnor
unDst ^= (unSrc ^ 0xff) & unM2;
break;
case 4: // replace
unDst = (unSrc & unM2) | (unDst & unM1);
break;
}
*pDstPtr = unDst;
}
}
}
unsigned char *GetDataPtr()
{
return m_pData;
}
int GetDataSize()
{
return m_nH * m_nLine;
}
private:
JBIG2Bitmap(unsigned int unSegNum, JBIG2Bitmap *pBitmap): JBIG2Segment(unSegNum)
{
m_nW = pBitmap->m_nW;
m_nH = pBitmap->m_nH;
m_nLine = pBitmap->m_nLine;
if ( m_nW <= 0 || m_nH <= 0 || m_nLine <= 0 || m_nH >= (INT_MAX - 1) / m_nLine )
{
m_pData = NULL;
return;
}
// need to allocate one extra guard byte for use in Combine()
m_pData = (unsigned char *)MemUtilsMalloc( m_nH * m_nLine + 1 );
memcpy( m_pData, pBitmap->m_pData, m_nH * m_nLine );
m_pData[m_nH * m_nLine] = 0;
}
private:
int m_nW;
int m_nH;
int m_nLine;
unsigned char *m_pData;
};
//------------------------------------------------------------------------
// JBIG2SymbolDict
//------------------------------------------------------------------------
class JBIG2SymbolDict: public JBIG2Segment
{
public:
JBIG2SymbolDict::JBIG2SymbolDict(unsigned int unSegNum, unsigned int unSize): JBIG2Segment(unSegNum)
{
m_unSize = unSize;
m_ppBitmaps = (JBIG2Bitmap **)MemUtilsMallocArray( m_unSize, sizeof(JBIG2Bitmap *) );
m_pGenericRegionStats = NULL;
m_pRefinementRegionStats = NULL;
}
virtual ~JBIG2SymbolDict()
{
for ( unsigned int unIndex = 0; unIndex < m_unSize; ++unIndex )
{
delete m_ppBitmaps[unIndex];
}
MemUtilsFree( m_ppBitmaps );
if ( m_pGenericRegionStats )
{
delete m_pGenericRegionStats;
}
if ( m_pRefinementRegionStats )
{
delete m_pRefinementRegionStats;
}
}
virtual JBIG2SegmentType GetType()
{
return jbig2SegSymbolDict;
}
unsigned int GetSize()
{
return m_unSize;
}
void SetBitmap(unsigned int unIndex, JBIG2Bitmap *pBitmap)
{
m_ppBitmaps[unIndex] = pBitmap;
}
JBIG2Bitmap *GetBitmap(unsigned int unIndex)
{
return m_ppBitmaps[unIndex];
}
void SetGenericRegionStats(JArithmeticDecoderStats *pStats)
{
m_pGenericRegionStats = pStats;
}
void SetRefinementRegionStats(JArithmeticDecoderStats *pStats)
{
m_pRefinementRegionStats = pStats;
}
JArithmeticDecoderStats *GetGenericRegionStats()
{
return m_pGenericRegionStats;
}
JArithmeticDecoderStats *GetRefinementRegionStats()
{
return m_pRefinementRegionStats;
}
private:
unsigned int m_unSize;
JBIG2Bitmap **m_ppBitmaps;
JArithmeticDecoderStats *m_pGenericRegionStats;
JArithmeticDecoderStats *m_pRefinementRegionStats;
};
//------------------------------------------------------------------------
// JBIG2PatternDict
//------------------------------------------------------------------------
class JBIG2PatternDict: public JBIG2Segment
{
public:
JBIG2PatternDict(unsigned int unSegNum, unsigned int unSize): JBIG2Segment(unSegNum)
{
m_unSize = unSize;
m_ppBitmaps = (JBIG2Bitmap **)MemUtilsMallocArray( m_unSize, sizeof(JBIG2Bitmap *) );
}
virtual ~JBIG2PatternDict()
{
for ( unsigned int unIndex = 0; unIndex < m_unSize; ++unIndex )
{
delete m_ppBitmaps[unIndex];
}
MemUtilsFree( m_ppBitmaps );
}
virtual JBIG2SegmentType GetType() { return jbig2SegPatternDict; }
unsigned int GetSize()
{
return m_unSize;
}
void SetBitmap(unsigned int unIndex, JBIG2Bitmap *pBitmap)
{
m_ppBitmaps[unIndex] = pBitmap;
}
JBIG2Bitmap *GetBitmap(unsigned int unIndex)
{
return m_ppBitmaps[unIndex];
}
private:
unsigned int m_unSize;
JBIG2Bitmap **m_ppBitmaps;
};
//------------------------------------------------------------------------
// JBIG2CodeTable
//------------------------------------------------------------------------
class JBIG2CodeTable: public JBIG2Segment
{
public:
JBIG2CodeTable(unsigned int unSegNum, JBIG2HuffmanTable *pTable): JBIG2Segment(unSegNum)
{
m_pTable = pTable;
}
virtual ~JBIG2CodeTable()
{
MemUtilsFree( m_pTable );
}
virtual JBIG2SegmentType GetType()
{
return jbig2SegCodeTable;
}
JBIG2HuffmanTable *GetHuffTable()
{
return m_pTable;
}
private:
JBIG2HuffmanTable *m_pTable;
};
//------------------------------------------------------------------------
// JBIG2Stream
//------------------------------------------------------------------------
JBIG2Stream::JBIG2Stream(Stream *pStream, Object *pGlobalsStream):
FilterStream(pStream)
{
m_pPageBitmap = NULL;
m_pArithDecoder = new JArithmeticDecoder();
m_pGenericRegionStats = new JArithmeticDecoderStats(1 << 1);
m_pRefinementRegionStats = new JArithmeticDecoderStats(1 << 1);
m_pIadhStats = new JArithmeticDecoderStats(1 << 9);
m_pIadwStats = new JArithmeticDecoderStats(1 << 9);
m_pIaexStats = new JArithmeticDecoderStats(1 << 9);
m_pIaaiStats = new JArithmeticDecoderStats(1 << 9);
m_pIadtStats = new JArithmeticDecoderStats(1 << 9);
m_pIaitStats = new JArithmeticDecoderStats(1 << 9);
m_pIafsStats = new JArithmeticDecoderStats(1 << 9);
m_pIadsStats = new JArithmeticDecoderStats(1 << 9);
m_pIardxStats = new JArithmeticDecoderStats(1 << 9);
m_pIardyStats = new JArithmeticDecoderStats(1 << 9);
m_pIardwStats = new JArithmeticDecoderStats(1 << 9);
m_pIardhStats = new JArithmeticDecoderStats(1 << 9);
m_pIariStats = new JArithmeticDecoderStats(1 << 9);
m_pIaidStats = new JArithmeticDecoderStats(1 << 1);
m_pHuffDecoder = new JBIG2HuffmanDecoder();
m_pMMrDecoder = new JBIG2MMRDecoder();
pGlobalsStream->Copy( &m_oGlobalsStream );
m_pSegments = m_pGlobalSegments = NULL;
m_pCurStream = NULL;
m_pDataPtr = m_pDataEnd = NULL;
}
JBIG2Stream::~JBIG2Stream()
{
Close();
m_oGlobalsStream.Free();
delete m_pArithDecoder;
delete m_pGenericRegionStats;
delete m_pRefinementRegionStats;
delete m_pIadhStats;
delete m_pIadwStats;
delete m_pIaexStats;
delete m_pIaaiStats;
delete m_pIadtStats;
delete m_pIaitStats;
delete m_pIafsStats;
delete m_pIadsStats;
delete m_pIardxStats;
delete m_pIardyStats;
delete m_pIardwStats;
delete m_pIardhStats;
delete m_pIariStats;
delete m_pIaidStats;
delete m_pHuffDecoder;
delete m_pMMrDecoder;
delete m_pStream;
}
void JBIG2Stream::Reset()
{
// read the globals stream
m_pGlobalSegments = new CList();
if ( m_oGlobalsStream.IsStream() )
{
m_pSegments = m_pGlobalSegments;
m_pCurStream = m_oGlobalsStream.GetStream();
m_pCurStream->Reset();
m_pArithDecoder->SetStream( m_pCurStream );
m_pHuffDecoder->SetStream( m_pCurStream );
m_pMMrDecoder->SetStream( m_pCurStream );
ReadSegments();
m_pCurStream->Close();
}
// read the main stream
m_pSegments = new CList();
m_pCurStream = m_pStream;
m_pCurStream->Reset();
m_pArithDecoder->SetStream( m_pCurStream );
m_pHuffDecoder->SetStream( m_pCurStream );
m_pMMrDecoder->SetStream( m_pCurStream );
ReadSegments();
if ( m_pPageBitmap )
{
m_pDataPtr = m_pPageBitmap->GetDataPtr();
m_pDataEnd = m_pDataPtr + m_pPageBitmap->GetDataSize();
}
else
{
m_pDataPtr = m_pDataEnd = NULL;
}
}
void JBIG2Stream::Close()
{
if ( m_pPageBitmap )
{
delete m_pPageBitmap;
m_pPageBitmap = NULL;
}
if ( m_pSegments )
{
DeleteCList( m_pSegments, JBIG2Segment );
m_pSegments = NULL;
}
if ( m_pGlobalSegments )
{
DeleteCList( m_pGlobalSegments, JBIG2Segment );
m_pGlobalSegments = NULL;
}
m_pDataPtr = m_pDataEnd = NULL;
FilterStream::Close();
}
int JBIG2Stream::GetChar()
{
if ( m_pDataPtr && m_pDataPtr < m_pDataEnd )
{
return (*m_pDataPtr++ ^ 0xff) & 0xff;
}
return EOF;
}
int JBIG2Stream::LookChar()
{
if ( m_pDataPtr && m_pDataPtr < m_pDataEnd )
{
return (*m_pDataPtr ^ 0xff) & 0xff;
}
return EOF;
}
StringExt *JBIG2Stream::GetPSFilter(int nPSLevel, char *sIndent)
{
return NULL;
}
BOOL JBIG2Stream::IsBinary(BOOL bLast)
{
return m_pStream->IsBinary(TRUE);
}
void JBIG2Stream::ReadSegments()
{
unsigned int unSegNum;
while ( ReadULong(&unSegNum) )
{
// segment header flags
unsigned int unSegFlags;
if ( !ReadUByte(&unSegFlags) )
{
return;
}
unsigned int unSegType = unSegFlags & 0x3f;
// referred-to segment count and retention flags
unsigned int unRefFlags;
if ( !ReadUByte(&unRefFlags) )
{
return;
}
unsigned int unRefSegsCount = unRefFlags >> 5;
if ( 7 == unRefSegsCount )
{
int nChar1, nChar2, nChar3;
if ( EOF == ( nChar1 = m_pCurStream->GetChar()) || EOF == ( nChar2 = m_pCurStream->GetChar() ) || EOF == ( nChar3 = m_pCurStream->GetChar() ) )
{
return;
}
unRefFlags = (unRefFlags << 24) | (nChar1 << 16) | (nChar2 << 8) | nChar3;
unRefSegsCount = unRefFlags & 0x1fffffff;
for ( unsigned int unIndex = 0; unIndex < (unRefSegsCount + 9) >> 3; ++unIndex )
{
nChar1 = m_pCurStream->GetChar();
}
}
// referred-to segment numbers
unsigned int *punRefSegs = (unsigned int *)MemUtilsMallocArray( unRefSegsCount, sizeof(unsigned int) );
if ( unSegNum <= 256 )
{
for ( unsigned int unIndex = 0; unIndex < unRefSegsCount; ++unIndex )
{
if ( !ReadUByte(&punRefSegs[unIndex]) )
{
MemUtilsFree( punRefSegs );
return;
}
}
}
else if ( unSegNum <= 65536 )
{
for ( unsigned int unIndex = 0; unIndex < unRefSegsCount; ++unIndex )
{
if ( !ReadUWord(&punRefSegs[unIndex]) )
{
MemUtilsFree( punRefSegs );
return;
}
}
}
else
{
for ( unsigned int unIndex = 0; unIndex < unRefSegsCount; ++unIndex )
{
if ( !ReadULong(&punRefSegs[unIndex]) )
{
MemUtilsFree( punRefSegs );
return;
}
}
}
// segment page association
unsigned int unPage;
if ( unSegFlags & 0x40 )
{
if ( !ReadULong(&unPage) )
{
MemUtilsFree( punRefSegs );
return;
}
}
else
{
if ( !ReadUByte(&unPage) )
{
MemUtilsFree( punRefSegs );
return;
}
}
// segment data length
unsigned int unSegLength;
if ( !ReadULong(&unSegLength) )
{
MemUtilsFree( punRefSegs );
return;
}
// read the segment data
switch ( unSegType )
{
case 0:
if ( !ReadSymbolDictSegment( unSegNum, unSegLength, punRefSegs, unRefSegsCount ) )
{
MemUtilsFree( punRefSegs );
return;
}
break;
case 4:
ReadTextRegionSegment( unSegNum, FALSE, FALSE, unSegLength, punRefSegs, unRefSegsCount );
break;
case 6:
ReadTextRegionSegment( unSegNum, TRUE, FALSE, unSegLength, punRefSegs, unRefSegsCount );
break;
case 7:
ReadTextRegionSegment( unSegNum, TRUE, TRUE, unSegLength, punRefSegs, unRefSegsCount);
break;
case 16:
ReadPatternDictSegment( unSegNum, unSegLength );
break;
case 20:
ReadHalftoneRegionSegment( unSegNum, FALSE, FALSE, unSegLength, punRefSegs, unRefSegsCount );
break;
case 22:
ReadHalftoneRegionSegment( unSegNum, TRUE, FALSE, unSegLength, punRefSegs, unRefSegsCount );
break;
case 23:
ReadHalftoneRegionSegment( unSegNum, TRUE, TRUE, unSegLength, punRefSegs, unRefSegsCount );
break;
case 36:
ReadGenericRegionSegment( unSegNum, FALSE, FALSE, unSegLength );
break;
case 38:
ReadGenericRegionSegment( unSegNum, TRUE, FALSE, unSegLength );
break;
case 39:
ReadGenericRegionSegment( unSegNum, TRUE, TRUE, unSegLength );
break;
case 40:
ReadGenericRefinementRegionSegment( unSegNum, FALSE, FALSE, unSegLength, punRefSegs, unRefSegsCount );
break;
case 42:
ReadGenericRefinementRegionSegment( unSegNum, TRUE, FALSE, unSegLength, punRefSegs, unRefSegsCount );
break;
case 43:
ReadGenericRefinementRegionSegment( unSegNum, TRUE, TRUE, unSegLength, punRefSegs, unRefSegsCount );
break;
case 48:
ReadPageInfoSegment( unSegLength );
break;
case 50:
ReadEndOfStripeSegment( unSegLength );
break;
case 52:
ReadProfilesSegment( unSegLength );
break;
case 53:
ReadCodeTableSegment( unSegNum, unSegLength );
break;
case 62:
ReadExtensionSegment( unSegLength );
break;
default:
for ( unsigned int unIndex = 0; unIndex < unSegLength; ++unIndex )
{
int nChar;
if ( EOF == ( nChar = m_pCurStream->GetChar() ) )
{
MemUtilsFree( punRefSegs );
return;
}
}
break;
}
MemUtilsFree( punRefSegs );
}
return;
}
BOOL JBIG2Stream::ReadSymbolDictSegment(unsigned int unSegNum, unsigned int unLength, unsigned int *punRefSegs, unsigned int unRefSegsCount)
{
// symbol dictionary flags
unsigned int unFlags;
if ( !ReadUWord(&unFlags) )
{
return FALSE;
}
unsigned int unHuff = unFlags & 1;
unsigned int unRefAgg = (unFlags >> 1) & 1;
unsigned int unHuffDH = (unFlags >> 2) & 3;
unsigned int unHuffDW = (unFlags >> 4) & 3;
unsigned int unHuffBMSize = (unFlags >> 6) & 1;
unsigned int unHuffAggInst = (unFlags >> 7) & 1;
unsigned int unContextUsed = (unFlags >> 8) & 1;
unsigned int unContextRetained = (unFlags >> 9) & 1;
unsigned int unSDTemplate = (unFlags >> 10) & 3;
unsigned int unSDRTemplate = (unFlags >> 12) & 1;
// symbol dictionary AT flags
int arrSDATx[4], arrSDATy[4];
if ( !unHuff )
{
if ( unSDTemplate == 0 )
{
if (!ReadByte(&arrSDATx[0]) || !ReadByte(&arrSDATy[0]) || !ReadByte(&arrSDATx[1]) || !ReadByte(&arrSDATy[1]) ||
!ReadByte(&arrSDATx[2]) || !ReadByte(&arrSDATy[2]) || !ReadByte(&arrSDATx[3]) || !ReadByte(&arrSDATy[3]) )
{
return FALSE;
}
}
else
{
if ( !ReadByte(&arrSDATx[0]) || !ReadByte(&arrSDATy[0]) )
{
return FALSE;
}
}
}
// symbol dictionary refinement AT flags
int arrSDRATx[2], arrSDRATy[2];
if ( unRefAgg && !unSDRTemplate )
{
if ( !ReadByte(&arrSDRATx[0]) || !ReadByte(&arrSDRATy[0]) || !ReadByte(&arrSDRATx[1]) || !ReadByte(&arrSDRATy[1]) )
{
return FALSE;
}
}
// SDNUMEXSYMS and SDNUMNEWSYMS
unsigned int unNumExSyms, unNumNewSyms;
if ( !ReadULong(&unNumExSyms) || !ReadULong(&unNumNewSyms) )
{
return FALSE;
}
// get referenced segments: input symbol dictionaries and code tables
CList *pCodeTables = new CList();
unsigned int unNumInputSyms = 0, unI;
for ( unI = 0; unI < unRefSegsCount; ++unI )
{
JBIG2Segment *pSegment = FindSegment( punRefSegs[unI] );
if ( pSegment->GetType() == jbig2SegSymbolDict )
{
unNumInputSyms += ((JBIG2SymbolDict *)pSegment)->GetSize();
}
else if ( pSegment->GetType() == jbig2SegCodeTable )
{
pCodeTables->Append( pSegment );
}
}
// compute symbol code length
unsigned int unSymCodeLen = 0;
unI = 1;
while ( unI < unNumInputSyms + unNumNewSyms )
{
++unSymCodeLen;
unI <<= 1;
}
// get the input symbol bitmaps
JBIG2Bitmap **ppBitmaps = (JBIG2Bitmap **)MemUtilsMallocArray( unNumInputSyms + unNumNewSyms, sizeof(JBIG2Bitmap *) );
for ( unI = 0; unI < unNumInputSyms + unNumNewSyms; ++unI )
{
ppBitmaps[unI] = NULL;
}
unsigned int unK = 0, unJ;
JBIG2SymbolDict *pInputSymbolDict = NULL;
for ( unI = 0; unI < unRefSegsCount; ++unI )
{
JBIG2Segment *pSegment = FindSegment( punRefSegs[unI] );
if ( pSegment->GetType() == jbig2SegSymbolDict )
{
pInputSymbolDict = (JBIG2SymbolDict *)pSegment;
for ( unJ = 0; unJ < pInputSymbolDict->GetSize(); ++unJ )
{
ppBitmaps[unK++] = pInputSymbolDict->GetBitmap( unJ );
}
}
}
// get the Huffman tables
JBIG2HuffmanTable *pHuffDHTable = NULL, *pHuffDWTable = NULL, *pHuffBMSizeTable = NULL, *pHuffAggInstTable = NULL;
unI = 0;
if ( unHuff )
{
if ( unHuffDH == 0 )
{
pHuffDHTable = c_oHuffTableD;
}
else if ( unHuffDH == 1 )
{
pHuffDHTable = c_oHuffTableE;
}
else
{
pHuffDHTable = ((JBIG2CodeTable *)pCodeTables->GetByIndex(unI++))->GetHuffTable();
}
if ( unHuffDW == 0 )
{
pHuffDWTable = c_oHuffTableB;
}
else if ( unHuffDW == 1 )
{
pHuffDWTable = c_oHuffTableC;
}
else
{
pHuffDWTable = ((JBIG2CodeTable *)pCodeTables->GetByIndex(unI++))->GetHuffTable();
}
if ( unHuffBMSize == 0 )
{
pHuffBMSizeTable = c_oHuffTableA;
}
else
{
pHuffBMSizeTable = ((JBIG2CodeTable *)pCodeTables->GetByIndex(unI++))->GetHuffTable();
}
if ( unHuffAggInst == 0 )
{
pHuffAggInstTable = c_oHuffTableA;
}
else
{
pHuffAggInstTable = ((JBIG2CodeTable *)pCodeTables->GetByIndex(unI++))->GetHuffTable();
}
}
delete pCodeTables;
// set up the Huffman decoder
if ( unHuff )
{
m_pHuffDecoder->Reset();
}
else // set up the arithmetic decoder
{
if ( unContextUsed && pInputSymbolDict )
{
ResetGenericStats( unSDTemplate, pInputSymbolDict->GetGenericRegionStats() );
}
else
{
ResetGenericStats( unSDTemplate, NULL);
}
ResetIntStats( unSymCodeLen );
m_pArithDecoder->Start();
}
// set up the arithmetic decoder for refinement/aggregation
if ( unRefAgg )
{
if ( unContextUsed && pInputSymbolDict )
{
ResetRefinementStats( unSDRTemplate, pInputSymbolDict->GetRefinementRegionStats() );
}
else
{
ResetRefinementStats( unSDRTemplate, NULL );
}
}
// allocate symbol widths storage
unsigned int *pSymWidths = NULL;
if ( unHuff && !unRefAgg )
{
pSymWidths = (unsigned int *)MemUtilsMallocArray( unNumNewSyms, sizeof(unsigned int) );
}
unsigned int unSymHeight = 0;
unI = 0;
while ( unI < unNumNewSyms )
{
// read the height class delta height
int nDh;
if ( unHuff )
{
m_pHuffDecoder->DecodeInt( &nDh, pHuffDHTable );
}
else
{
m_pArithDecoder->DecodeInt( &nDh, m_pIadhStats );
}
if ( nDh < 0 && (unsigned int) - nDh >= unSymHeight )
{
// SyntaxError
for ( unsigned int unIndex = 0; unIndex < unNumNewSyms; ++unIndex )
{
if ( ppBitmaps[unNumInputSyms + unIndex] )
{
delete ppBitmaps[unNumInputSyms + unIndex];
}
}
MemUtilsFree( ppBitmaps );
if ( pSymWidths )
{
MemUtilsFree( pSymWidths );
}
return FALSE;
}
unSymHeight += nDh;
unsigned int unSymWidth = 0, unTotalWidth = 0;
unJ = unI;
// read the symbols in this height class
while (1)
{
// read the delta width
int nDw;
if ( unHuff )
{
if ( !m_pHuffDecoder->DecodeInt( &nDw, pHuffDWTable ) )
{
break;
}
}
else
{
if ( !m_pArithDecoder->DecodeInt( &nDw, m_pIadwStats ) )
{
break;
}
}
if ( nDw < 0 && (unsigned int) - nDw >= unSymWidth )
{
// SyntaxError
for ( unsigned int unIndex = 0; unIndex < unNumNewSyms; ++unIndex )
{
if ( ppBitmaps[unNumInputSyms + unIndex] )
{
delete ppBitmaps[unNumInputSyms + unIndex];
}
}
MemUtilsFree( ppBitmaps );
if ( pSymWidths )
{
MemUtilsFree( pSymWidths );
}
return FALSE;
}
unSymWidth += nDw;
// using a collective bitmap, so don't read a bitmap here
if ( unHuff && !unRefAgg )
{
pSymWidths[unI] = unSymWidth;
unTotalWidth += unSymWidth;
}
else if ( unRefAgg ) // refinement/aggregate coding
{
int nRefAggNum;
if ( unHuff )
{
if ( !m_pHuffDecoder->DecodeInt( &nRefAggNum, pHuffAggInstTable ) )
{
break;
}
}
else
{
if ( !m_pArithDecoder->DecodeInt( &nRefAggNum, m_pIaaiStats ) )
{
break;
}
}
#if 0 //~ This special case was added about a year before the final draft
//~ of the JBIG2 spec was released. I have encountered some old
//~ JBIG2 images that predate it.
if ( 0 )
{
#else
if ( nRefAggNum == 1 )
{
#endif
unsigned int unSymID;
int nRefDX, nRefDY, nBMSize;
if ( unHuff )
{
unSymID = m_pHuffDecoder->ReadBits( unSymCodeLen );
m_pHuffDecoder->DecodeInt( &nRefDX, c_oHuffTableO );
m_pHuffDecoder->DecodeInt( &nRefDY, c_oHuffTableO );
m_pHuffDecoder->DecodeInt( &nBMSize, c_oHuffTableA );
m_pHuffDecoder->Reset();
m_pArithDecoder->Start();
}
else
{
unSymID = m_pArithDecoder->DecodeIAID( unSymCodeLen, m_pIaidStats );
m_pArithDecoder->DecodeInt( &nRefDX, m_pIardxStats );
m_pArithDecoder->DecodeInt( &nRefDY, m_pIardyStats );
}
JBIG2Bitmap *pRefBitmap = ppBitmaps[unSymID];
ppBitmaps[unNumInputSyms + unI] = ReadGenericRefinementRegion( unSymWidth, unSymHeight, unSDRTemplate, FALSE, pRefBitmap, nRefDX, nRefDY, arrSDRATx, arrSDRATy );
}
else //~ do we need to use the bmSize value here (in Huffman mode)?
{
ppBitmaps[unNumInputSyms + unI] = ReadTextRegion( unHuff, TRUE, unSymWidth, unSymHeight, nRefAggNum, 0, unNumInputSyms + unI, NULL, unSymCodeLen, ppBitmaps, 0, 0, 0, 1, 0, c_oHuffTableF, c_oHuffTableH, c_oHuffTableK, c_oHuffTableO, c_oHuffTableO, c_oHuffTableO, c_oHuffTableO, c_oHuffTableA, unSDRTemplate, arrSDRATx, arrSDRATy );
}
}
else // non-ref/agg coding
{
ppBitmaps[unNumInputSyms + unI] = ReadGenericBitmap( FALSE, unSymWidth, unSymHeight, unSDTemplate, FALSE, FALSE, NULL, arrSDATx, arrSDATy, 0 );
}
++unI;
}
// read the collective bitmap
if ( unHuff && !unRefAgg )
{
int nBMSize;
m_pHuffDecoder->DecodeInt( &nBMSize, pHuffBMSizeTable );
m_pHuffDecoder->Reset();
JBIG2Bitmap *pCollBitmap;
if ( nBMSize == 0 )
{
pCollBitmap = new JBIG2Bitmap( 0, unTotalWidth, unSymHeight );
nBMSize = unSymHeight * ((unTotalWidth + 7) >> 3);
unsigned char *pDataPtr = pCollBitmap->GetDataPtr();
for ( unK = 0; unK < (unsigned int)nBMSize; ++unK )
{
*pDataPtr++ = m_pCurStream->GetChar();
}
}
else
{
pCollBitmap = ReadGenericBitmap( TRUE, unTotalWidth, unSymHeight, 0, FALSE, FALSE, NULL, NULL, NULL, nBMSize );
}
unsigned int unX = 0;
for ( ; unJ < unI; ++unJ )
{
ppBitmaps[unNumInputSyms + unJ] = pCollBitmap->GetSlice( unX, 0, pSymWidths[unJ], unSymHeight );
unX += pSymWidths[unJ];
}
delete pCollBitmap;
}
}
// create the symbol dict object
JBIG2SymbolDict *pSymbolDict = new JBIG2SymbolDict( unSegNum, unNumExSyms );
// exported symbol list
unI = unJ = 0;
BOOL bEx = FALSE;
while ( unI < unNumInputSyms + unNumNewSyms )
{
int nRun;
if ( unHuff )
{
m_pHuffDecoder->DecodeInt( &nRun, c_oHuffTableA );
}
else
{
m_pArithDecoder->DecodeInt( &nRun, m_pIaexStats );
}
if ( bEx )
{
for ( int nCounter = 0; nCounter < nRun; ++nCounter )
{
pSymbolDict->SetBitmap( unJ++, ppBitmaps[unI++]->Copy() );
}
}
else
{
unI += nRun;
}
bEx = !bEx;
}
for ( unI = 0; unI < unNumNewSyms; ++unI )
{
delete ppBitmaps[unNumInputSyms + unI];
}
MemUtilsFree( ppBitmaps );
if ( pSymWidths )
{
MemUtilsFree( pSymWidths );
}
// save the arithmetic decoder stats
if ( !unHuff && unContextRetained )
{
pSymbolDict->SetGenericRegionStats( m_pGenericRegionStats->Copy() );
if ( unRefAgg )
{
pSymbolDict->SetRefinementRegionStats( m_pRefinementRegionStats->Copy() );
}
}
// store the new symbol dict
m_pSegments->Append( pSymbolDict );
return TRUE;
}
void JBIG2Stream::ReadTextRegionSegment(unsigned int unSegNum, BOOL bImm, BOOL bLossless, unsigned int unLength, unsigned int *punRefSegs, unsigned int unRefSegsCount)
{
// region segment info field
unsigned int unW, unH, unX, unY, unSegInfoFlags;
if ( !ReadULong(&unW) || !ReadULong(&unH) || !ReadULong(&unX) || !ReadULong(&unY) || !ReadUByte(&unSegInfoFlags) )
{
return;
}
unsigned int unExtCombOp = unSegInfoFlags & 7;
// rest of the text region header
unsigned int unFlags;
if ( !ReadUWord(&unFlags) )
{
return;
}
unsigned int unHuff = unFlags & 1;
unsigned int unRefine = (unFlags >> 1) & 1;
unsigned int unLogStrips = (unFlags >> 2) & 3;
unsigned int unRefCorner = (unFlags >> 4) & 3;
unsigned int unTransposed = (unFlags >> 6) & 1;
unsigned int unCombOp = (unFlags >> 7) & 3;
unsigned int unDefPixel = (unFlags >> 9) & 1;
int nSOffset = (unFlags >> 10) & 0x1f;
unsigned int unTempl = (unFlags >> 15) & 1;
if ( nSOffset & 0x10 )
{
nSOffset |= -1 - 0x0f;
}
unsigned int unHuffFS = 0, unHuffDS = 0, unHuffDT = 0, unHuffRDW = 0, unHuffRDH = 0, unHuffRDX = 0, unHuffRDY = 0, unHuffRSize = 0;
if ( unHuff )
{
unsigned int unHuffFlags;
if ( !ReadUWord(&unHuffFlags) )
{
return;
}
unHuffFS = unHuffFlags & 3;
unHuffDS = (unHuffFlags >> 2) & 3;
unHuffDT = (unHuffFlags >> 4) & 3;
unHuffRDW = (unHuffFlags >> 6) & 3;
unHuffRDH = (unHuffFlags >> 8) & 3;
unHuffRDX = (unHuffFlags >> 10) & 3;
unHuffRDY = (unHuffFlags >> 12) & 3;
unHuffRSize = (unHuffFlags >> 14) & 1;
}
int arrATx[2], arrATy[2];
if ( unRefine && unTempl == 0 )
{
if ( !ReadByte(&arrATx[0]) || !ReadByte(&arrATy[0] ) || !ReadByte(&arrATx[1]) || !ReadByte(&arrATy[1]) )
{
return;
}
}
unsigned int unNumInstances;
if ( !ReadULong(&unNumInstances) )
{
return;
}
// get symbol dictionaries and tables
CList *pCodeTables = new CList();
unsigned int unNumSyms = 0;
unsigned int unIndex;
for ( unIndex = 0; unIndex < unRefSegsCount; ++unIndex )
{
JBIG2Segment *pSegment = NULL;
if ( ( pSegment = FindSegment( punRefSegs[unIndex] ) ) )
{
if ( pSegment->GetType() == jbig2SegSymbolDict )
{
unNumSyms += ((JBIG2SymbolDict *)pSegment)->GetSize();
}
else if ( pSegment->GetType() == jbig2SegCodeTable )
{
pCodeTables->Append( pSegment );
}
}
else
{
}
}
unsigned int unSymCodeLen = 0;
unIndex = 1;
while ( unIndex < unNumSyms )
{
++unSymCodeLen;
unIndex <<= 1;
}
// get the symbol bitmaps
JBIG2Bitmap **ppSyms = (JBIG2Bitmap **)MemUtilsMallocArray( unNumSyms, sizeof(JBIG2Bitmap *) );
unsigned int unSymsIndex = 0;
for ( unIndex = 0; unIndex < unRefSegsCount; ++unIndex )
{
JBIG2Segment *pSegment = NULL;
if ( ( pSegment = FindSegment( punRefSegs[unIndex] ) ) )
{
if ( pSegment->GetType() == jbig2SegSymbolDict )
{
JBIG2SymbolDict *pSymbolDict = (JBIG2SymbolDict *)pSegment;
for ( unsigned int unK = 0; unK < pSymbolDict->GetSize(); ++unK )
{
ppSyms[unSymsIndex++] = pSymbolDict->GetBitmap( unK );
}
}
}
}
// get the Huffman tables
JBIG2HuffmanTable *pHuffFSTable = NULL, *pHuffDSTable = NULL, *pHuffDTTable = NULL, *pHuffRDWTable = NULL, *pHuffRDHTable = NULL, *pHuffRDXTable = NULL, *pHuffRDYTable = NULL, *pHuffRSizeTable = NULL;
unIndex = 0;
if ( unHuff )
{
if ( unHuffFS == 0 )
{
pHuffFSTable = c_oHuffTableF;
}
else if ( unHuffFS == 1 )
{
pHuffFSTable = c_oHuffTableG;
}
else
{
pHuffFSTable = ((JBIG2CodeTable *)pCodeTables->GetByIndex(unIndex++))->GetHuffTable();
}
if ( unHuffDS == 0 )
{
pHuffDSTable = c_oHuffTableH;
}
else if ( unHuffDS == 1 )
{
pHuffDSTable = c_oHuffTableI;
}
else if ( unHuffDS == 2 )
{
pHuffDSTable = c_oHuffTableJ;
}
else
{
pHuffDSTable = ((JBIG2CodeTable *)pCodeTables->GetByIndex(unIndex++))->GetHuffTable();
}
if ( unHuffDT == 0 )
{
pHuffDTTable = c_oHuffTableK;
}
else if ( unHuffDT == 1 )
{
pHuffDTTable = c_oHuffTableL;
}
else if ( unHuffDT == 2 )
{
pHuffDTTable = c_oHuffTableM;
}
else
{
pHuffDTTable = ((JBIG2CodeTable *)pCodeTables->GetByIndex(unIndex++))->GetHuffTable();
}
if ( unHuffRDW == 0 )
{
pHuffRDWTable = c_oHuffTableN;
}
else if ( unHuffRDW == 1 )
{
pHuffRDWTable = c_oHuffTableO;
}
else
{
pHuffRDWTable = ((JBIG2CodeTable *)pCodeTables->GetByIndex(unIndex++))->GetHuffTable();
}
if ( unHuffRDH == 0 )
{
pHuffRDHTable = c_oHuffTableN;
}
else if ( unHuffRDH == 1 )
{
pHuffRDHTable = c_oHuffTableO;
}
else
{
pHuffRDHTable = ((JBIG2CodeTable *)pCodeTables->GetByIndex(unIndex++))->GetHuffTable();
}
if ( unHuffRDX == 0 )
{
pHuffRDXTable = c_oHuffTableN;
}
else if ( unHuffRDX == 1 )
{
pHuffRDXTable = c_oHuffTableO;
}
else
{
pHuffRDXTable = ((JBIG2CodeTable *)pCodeTables->GetByIndex(unIndex++))->GetHuffTable();
}
if ( unHuffRDY == 0 )
{
pHuffRDYTable = c_oHuffTableN;
}
else if ( unHuffRDY == 1 )
{
pHuffRDYTable = c_oHuffTableO;
}
else
{
pHuffRDYTable = ((JBIG2CodeTable *)pCodeTables->GetByIndex(unIndex++))->GetHuffTable();
}
if ( unHuffRSize == 0 )
{
pHuffRSizeTable = c_oHuffTableA;
}
else
{
pHuffRSizeTable = ((JBIG2CodeTable *)pCodeTables->GetByIndex(unIndex++))->GetHuffTable();
}
}
delete pCodeTables;
// symbol ID Huffman decoding table
JBIG2HuffmanTable *pSymCodeTab;
if ( unHuff )
{
m_pHuffDecoder->Reset();
JBIG2HuffmanTable arrRunLengthTab[36];
for ( unIndex = 0; unIndex < 32; ++unIndex )
{
arrRunLengthTab[unIndex].nValue = unIndex;
arrRunLengthTab[unIndex].unPrefixLen = m_pHuffDecoder->ReadBits(4);
arrRunLengthTab[unIndex].unRangeLen = 0;
}
arrRunLengthTab[32].nValue = 0x103;
arrRunLengthTab[32].unPrefixLen = m_pHuffDecoder->ReadBits(4);
arrRunLengthTab[32].unRangeLen = 2;
arrRunLengthTab[33].nValue = 0x203;
arrRunLengthTab[33].unPrefixLen = m_pHuffDecoder->ReadBits(4);
arrRunLengthTab[33].unRangeLen = 3;
arrRunLengthTab[34].nValue = 0x20b;
arrRunLengthTab[34].unPrefixLen = m_pHuffDecoder->ReadBits(4);
arrRunLengthTab[34].unRangeLen = 7;
arrRunLengthTab[35].unPrefixLen = 0;
arrRunLengthTab[35].unRangeLen = jbig2HuffmanEOT;
m_pHuffDecoder->BuildTable( arrRunLengthTab, 35 );
pSymCodeTab = (JBIG2HuffmanTable *)MemUtilsMallocArray( unNumSyms + 1, sizeof(JBIG2HuffmanTable));
for ( unIndex = 0; unIndex < unNumSyms; ++unIndex )
{
pSymCodeTab[unIndex].nValue = unIndex;
pSymCodeTab[unIndex].unRangeLen = 0;
}
unIndex = 0;
int nJ;
while ( unIndex < unNumSyms )
{
m_pHuffDecoder->DecodeInt( &nJ, arrRunLengthTab );
if ( nJ > 0x200 )
{
for ( nJ -= 0x200; nJ && unIndex < unNumSyms; --nJ )
{
pSymCodeTab[unIndex++].unPrefixLen = 0;
}
}
else if ( nJ > 0x100 )
{
for ( nJ -= 0x100; nJ && unIndex < unNumSyms; --nJ )
{
pSymCodeTab[unIndex].unPrefixLen = pSymCodeTab[unIndex - 1].unPrefixLen;
++unIndex;
}
}
else
{
pSymCodeTab[unIndex++].unPrefixLen = nJ;
}
}
pSymCodeTab[unNumSyms].unPrefixLen = 0;
pSymCodeTab[unNumSyms].unRangeLen = jbig2HuffmanEOT;
m_pHuffDecoder->BuildTable( pSymCodeTab, unNumSyms );
m_pHuffDecoder->Reset();
}
else // set up the arithmetic decoder
{
pSymCodeTab = NULL;
ResetIntStats( unSymCodeLen );
m_pArithDecoder->Start();
}
if ( unRefine )
{
ResetRefinementStats( unTempl, NULL );
}
JBIG2Bitmap *pBitmap = ReadTextRegion( unHuff, unRefine, unW, unH, unNumInstances, unLogStrips, unNumSyms, pSymCodeTab, unSymCodeLen, ppSyms, unDefPixel, unCombOp, unTransposed, unRefCorner, nSOffset, pHuffFSTable, pHuffDSTable, pHuffDTTable, pHuffRDWTable, pHuffRDHTable, pHuffRDXTable, pHuffRDYTable, pHuffRSizeTable, unTempl, arrATx, arrATy );
MemUtilsFree( ppSyms );
// combine the region bitmap into the page bitmap
if ( bImm )
{
if ( m_unPageH == 0xffffffff && unY + unH > m_unCurPageH )
{
m_pPageBitmap->Expand( unY + unH, m_unPageDefPixel );
}
m_pPageBitmap->Combine( pBitmap, unX, unY, unExtCombOp );
delete pBitmap;
}
else // store the region bitmap
{
pBitmap->SetSegNum( unSegNum );
m_pSegments->Append( pBitmap );
}
// clean up the Huffman decoder
if ( unHuff )
{
MemUtilsFree( pSymCodeTab );
}
return;
}
JBIG2Bitmap *JBIG2Stream::ReadTextRegion(BOOL bHuff, BOOL bRefine, int nW, int nH, unsigned int unNumInstances, unsigned int unLogStrips, int nNumSyms, JBIG2HuffmanTable *pSymCodeTab, unsigned int unSymCodeLen, JBIG2Bitmap **ppSyms, unsigned int unDefPixel, unsigned int unCombOp, unsigned int transposed, unsigned int refCorner, int nSOffset, JBIG2HuffmanTable *pHuffFSTable, JBIG2HuffmanTable *pHuffDSTable, JBIG2HuffmanTable *pHuffDTTable, JBIG2HuffmanTable *pHuffRDWTable, JBIG2HuffmanTable *pHuffRDHTable, JBIG2HuffmanTable *pHuffRDXTable, JBIG2HuffmanTable *pHuffRDYTable, JBIG2HuffmanTable *pHuffRSizeTable, unsigned int unTempl, int *pnATx, int *pnATy)
{
unsigned int unStrips = 1 << unLogStrips;
// allocate the bitmap
JBIG2Bitmap *pBitmap = new JBIG2Bitmap( 0, nW, nH );
if ( unDefPixel )
{
pBitmap->ClearToOne();
}
else
{
pBitmap->ClearToZero();
}
// decode initial T value
int nT;
if ( bHuff )
{
m_pHuffDecoder->DecodeInt( &nT, pHuffDTTable );
}
else
{
m_pArithDecoder->DecodeInt( &nT, m_pIadtStats );
}
nT *= -(int)unStrips;
unsigned int unInstance = 0;
int nSFirst = 0;
while ( unInstance < unNumInstances )
{
// decode delta-T
int nDeltaT;
if ( bHuff )
{
m_pHuffDecoder->DecodeInt( &nDeltaT, pHuffDTTable );
}
else
{
m_pArithDecoder->DecodeInt( &nDeltaT, m_pIadtStats );
}
nT += nDeltaT * unStrips;
// first S value
int nDS;
if ( bHuff )
{
m_pHuffDecoder->DecodeInt( &nDS, pHuffFSTable );
}
else
{
m_pArithDecoder->DecodeInt( &nDS, m_pIafsStats );
}
nSFirst += nDS;
int nCurS = nSFirst;
// read the instances
while (1)
{
// T value
if ( 1 == unStrips )
{
nDeltaT = 0;
}
else if ( bHuff )
{
nDeltaT = m_pHuffDecoder->ReadBits( unLogStrips );
}
else
{
m_pArithDecoder->DecodeInt( &nDeltaT, m_pIaitStats );
}
int nCurT = nT + nDeltaT;
// symbol ID
unsigned int unSymID;
if ( bHuff )
{
if ( pSymCodeTab )
{
int nTemp;
m_pHuffDecoder->DecodeInt( &nTemp, pSymCodeTab );
unSymID = (unsigned int)nTemp;
}
else
{
unSymID = m_pHuffDecoder->ReadBits( unSymCodeLen );
}
}
else
{
unSymID = m_pArithDecoder->DecodeIAID( unSymCodeLen, m_pIaidStats );
}
if ( unSymID >= (unsigned int)nNumSyms )
{
}
else
{
// get the symbol bitmap
JBIG2Bitmap *pSymbolBitmap = NULL;
int nReadInt;
if ( bRefine )
{
if ( bHuff )
{
nReadInt = (int)m_pHuffDecoder->ReadBit();
}
else
{
m_pArithDecoder->DecodeInt( &nReadInt, m_pIariStats );
}
}
else
{
nReadInt = 0;
}
if ( nReadInt )
{
int nRDW, nRDH, nRDX, nRDY, nBMSize;
if ( bHuff )
{
m_pHuffDecoder->DecodeInt( &nRDW, pHuffRDWTable );
m_pHuffDecoder->DecodeInt( &nRDH, pHuffRDHTable );
m_pHuffDecoder->DecodeInt( &nRDX, pHuffRDXTable );
m_pHuffDecoder->DecodeInt( &nRDY, pHuffRDYTable );
m_pHuffDecoder->DecodeInt( &nBMSize, pHuffRSizeTable );
m_pHuffDecoder->Reset();
m_pArithDecoder->Start();
}
else
{
m_pArithDecoder->DecodeInt( &nRDW, m_pIardwStats);
m_pArithDecoder->DecodeInt( &nRDH, m_pIardhStats);
m_pArithDecoder->DecodeInt( &nRDX, m_pIardxStats);
m_pArithDecoder->DecodeInt( &nRDY, m_pIardyStats);
}
int nRefDX = ( (nRDW >= 0) ? nRDW : nRDW - 1) / 2 + nRDX;
int nRefDY = ( (nRDH >= 0) ? nRDH : nRDH - 1) / 2 + nRDY;
pSymbolBitmap = ReadGenericRefinementRegion( nRDW + ppSyms[unSymID]->GetWidth(), nRDH + ppSyms[unSymID]->GetHeight(), unTempl, FALSE, ppSyms[unSymID], nRefDX, nRefDY, pnATx, pnATy );
}
else //~ do we need to use the bmSize value here (in Huffman mode)?
{
pSymbolBitmap = ppSyms[unSymID];
}
// combine the symbol bitmap into the region bitmap
//~ something is wrong here - refCorner shouldn't degenerate into
//~ two cases
unsigned int unBitmapW = pSymbolBitmap->GetWidth() - 1;
unsigned int unBitmapH = pSymbolBitmap->GetHeight() - 1;
if ( transposed )
{
switch ( refCorner )
{
case 0: // bottom left
pBitmap->Combine( pSymbolBitmap, nCurT, nCurS, unCombOp );
break;
case 1: // top left
pBitmap->Combine( pSymbolBitmap, nCurT, nCurS, unCombOp );
break;
case 2: // bottom right
pBitmap->Combine( pSymbolBitmap, nCurT - unBitmapW, nCurS, unCombOp );
break;
case 3: // top right
pBitmap->Combine( pSymbolBitmap, nCurT - unBitmapW, nCurS, unCombOp );
break;
}
nCurS += unBitmapH;
}
else
{
switch ( refCorner )
{
case 0: // bottom left
pBitmap->Combine( pSymbolBitmap, nCurS, nCurT - unBitmapH, unCombOp );
break;
case 1: // top left
pBitmap->Combine( pSymbolBitmap, nCurS, nCurT, unCombOp );
break;
case 2: // bottom right
pBitmap->Combine( pSymbolBitmap, nCurS, nCurT - unBitmapH, unCombOp );
break;
case 3: // top right
pBitmap->Combine( pSymbolBitmap, nCurS, nCurT, unCombOp );
break;
}
nCurS += unBitmapW;
}
if ( nReadInt )
{
delete pSymbolBitmap;
}
}
// next instance
++unInstance;
// next S value
if ( bHuff )
{
if ( !m_pHuffDecoder->DecodeInt( &nDS, pHuffDSTable ) )
{
break;
}
}
else
{
if ( !m_pArithDecoder->DecodeInt( &nDS, m_pIadsStats ) )
{
break;
}
}
nCurS += nSOffset + nDS;
}
}
return pBitmap;
}
void JBIG2Stream::ReadPatternDictSegment(unsigned int unSegNum, unsigned int unLength)
{
// halftone dictionary flags, pattern width and height, max gray value
unsigned int unFlags, unPatternW, unPatternH, unGrayMax;
if ( !ReadUByte(&unFlags) || !ReadUByte(&unPatternW) || !ReadUByte(&unPatternH) || !ReadULong(&unGrayMax) )
{
return;
}
unsigned int unTempl = (unFlags >> 1) & 3;
unsigned int unMMR = unFlags & 1;
// set up the arithmetic decoder
if ( !unMMR )
{
ResetGenericStats( unTempl, NULL );
m_pArithDecoder->Start();
}
// read the bitmap
int arrATx[4], arrATy[4];
arrATx[0] = -(int)unPatternW; arrATy[0] = 0;
arrATx[1] = -3; arrATy[1] = -1;
arrATx[2] = 2; arrATy[2] = -2;
arrATx[3] = -2; arrATy[3] = -2;
JBIG2Bitmap *pBitmap = ReadGenericBitmap( unMMR, (unGrayMax + 1) * unPatternW, unPatternH, unTempl, FALSE, FALSE, NULL, arrATx, arrATy, unLength - 7 );
// create the pattern dict object
JBIG2PatternDict *pPatternDict = new JBIG2PatternDict( unSegNum, unGrayMax + 1 );
// split up the bitmap
unsigned int unX = 0;
for ( unsigned int unIndex = 0; unIndex <= unGrayMax; ++unIndex )
{
pPatternDict->SetBitmap( unIndex, pBitmap->GetSlice( unX, 0, unPatternW, unPatternH ) );
unX += unPatternW;
}
// free memory
delete pBitmap;
// store the new pattern dict
m_pSegments->Append( pPatternDict );
return;
}
void JBIG2Stream::ReadHalftoneRegionSegment(unsigned int unSegNum, BOOL bImm, BOOL bLossless, unsigned int unLength, unsigned int *punRefSegs, unsigned int unRefSegsCount)
{
// region segment info field
unsigned int unW, unH, unX, unY, unSegInfoFlags;
if ( !ReadULong(&unW) || !ReadULong(&unH) || !ReadULong(&unX) || !ReadULong(&unY) || !ReadUByte(&unSegInfoFlags) )
{
return;
}
unsigned int unExtCombOp = unSegInfoFlags & 7;
// rest of the halftone region header
unsigned int unFlags;
if ( !ReadUByte(&unFlags) )
{
return;
}
unsigned int unMMR = unFlags & 1;
unsigned int unTempl = (unFlags >> 1) & 3;
unsigned int unEnableSkip = (unFlags >> 3) & 1;
unsigned int unCombOp = (unFlags >> 4) & 7;
unsigned int unGridW, unGridH, unStepX, unStepY;
int nGridX, nGridY;
if ( !ReadULong(&unGridW) || !ReadULong(&unGridH) || !ReadLong(&nGridX) || !ReadLong(&nGridY) || !ReadUWord(&unStepX) || !ReadUWord(&unStepY) )
{
return;
}
if ( unW == 0 || unH == 0 || unW >= INT_MAX / unH )
{
return;
}
if ( unGridH == 0 || unGridW >= INT_MAX / unGridH )
{
return;
}
// get pattern dictionary
if ( unRefSegsCount != 1 )
{
return;
}
JBIG2Segment *pSegment = FindSegment( punRefSegs[0] );
if ( pSegment->GetType() != jbig2SegPatternDict )
{
return;
}
JBIG2PatternDict *pPatternDict = (JBIG2PatternDict *)pSegment;
unsigned int unBPP = 0;
unsigned int unIndex = 1;
while ( unIndex < pPatternDict->GetSize() )
{
++unBPP;
unIndex <<= 1;
}
unsigned int unPatternW = pPatternDict->GetBitmap(0)->GetWidth();
unsigned int unPatternH = pPatternDict->GetBitmap(0)->GetHeight();
// set up the arithmetic decoder
if ( !unMMR )
{
ResetGenericStats( unTempl, NULL );
m_pArithDecoder->Start();
}
// allocate the bitmap
JBIG2Bitmap *pBitmap = new JBIG2Bitmap( unSegNum, unW, unH );
if ( unFlags & 0x80 ) // HDEFPIXEL
{
pBitmap->ClearToOne();
}
else
{
pBitmap->ClearToZero();
}
// compute the skip bitmap
JBIG2Bitmap *pSkipBitmap = NULL;
if ( unEnableSkip )
{
pSkipBitmap = new JBIG2Bitmap( 0, unGridW, unGridH );
pSkipBitmap->ClearToZero();
for ( unsigned int unM = 0; unM < unGridH; ++unM )
{
for ( unsigned int unN = 0; unN < unGridW; ++unN )
{
int nCurX = nGridX + unM * unStepY + unN * unStepX;
int nCurY = nGridY + unM * unStepX - unN * unStepY;
if ( ((nCurX + (int)unPatternW) >> 8) <= 0 || (nCurX >> 8) >= (int)unW || ((nCurY + (int)unPatternH) >> 8) <= 0 || (nCurY >> 8) >= (int)unH )
{
pSkipBitmap->SetPixel( unN, unM );
}
}
}
}
// read the gray-scale image
unsigned int *pGrayImage = (unsigned int *)MemUtilsMallocArray( unGridW * unGridH, sizeof(unsigned int) );
memset( pGrayImage, 0, unGridW * unGridH * sizeof(unsigned int) );
int arrATx[4], arrATy[4];
arrATx[0] = unTempl <= 1 ? 3 : 2; arrATy[0] = -1;
arrATx[1] = -3; arrATy[1] = -1;
arrATx[2] = 2; arrATy[2] = -2;
arrATx[3] = -2; arrATy[3] = -2;
for ( int nBitIndex = unBPP - 1; nBitIndex >= 0; --nBitIndex )
{
JBIG2Bitmap *pGrayBitmap = ReadGenericBitmap( unMMR, unGridW, unGridH, unTempl, FALSE, unEnableSkip, pSkipBitmap, arrATx, arrATy, -1 );
unIndex = 0;
for ( unsigned int unM = 0; unM < unGridH; ++unM )
{
for ( unsigned int unN = 0; unN < unGridW; ++unN )
{
int nBit = pGrayBitmap->GetPixel( unN, unM ) ^ (pGrayImage[unIndex] & 1);
pGrayImage[unIndex] = (pGrayImage[unIndex] << 1) | nBit;
++unIndex;
}
}
delete pGrayBitmap;
}
// decode the image
unIndex = 0;
for ( unsigned int unM = 0; unM < unGridH; ++unM )
{
int nCurX = nGridX + unM * unStepY;
int nCurY = nGridY + unM * unStepX;
for ( unsigned int unN = 0; unN < unGridW; ++unN )
{
if ( !( unEnableSkip && pSkipBitmap->GetPixel( unN, unM ) ) )
{
JBIG2Bitmap *pPatternBitmap = pPatternDict->GetBitmap( pGrayImage[unIndex] );
pBitmap->Combine( pPatternBitmap, nCurX >> 8, nCurY >> 8, unCombOp );
}
nCurX += unStepX;
nCurY -= unStepY;
++unIndex;
}
}
MemUtilsFree( pGrayImage );
if ( pSkipBitmap )
{
delete pSkipBitmap;
}
// combine the region bitmap into the page bitmap
if ( bImm )
{
if ( m_unPageH == 0xffffffff && unY + unH > m_unCurPageH )
{
m_pPageBitmap->Expand( unY + unH, m_unPageDefPixel );
}
m_pPageBitmap->Combine( pBitmap, unX, unY, unExtCombOp );
delete pBitmap;
}
else // store the region bitmap
{
m_pSegments->Append( pBitmap );
}
return;
}
void JBIG2Stream::ReadGenericRegionSegment(unsigned int unSegNum, BOOL bImm, BOOL bLossless, unsigned int unLength)
{
// region segment info field
unsigned int unW, unH, unX, unY, unSegInfoFlags;
if ( !ReadULong(&unW) || !ReadULong(&unH) || !ReadULong(&unX) || !ReadULong(&unY) || !ReadUByte(&unSegInfoFlags) )
{
return;
}
unsigned int unExtCombOp = unSegInfoFlags & 7;
// rest of the generic region segment header
unsigned int unFlags;
if ( !ReadUByte(&unFlags) )
{
return;
}
unsigned int unMMR = unFlags & 1;
unsigned int unTempl = (unFlags >> 1) & 3;
unsigned int unTpgdOn = (unFlags >> 3) & 1;
// AT flags
int arrATx[4], arrATy[4];
if ( !unMMR )
{
if ( unTempl == 0 )
{
if ( !ReadByte(&arrATx[0]) || !ReadByte(&arrATy[0]) || !ReadByte(&arrATx[1]) || !ReadByte(&arrATy[1]) ||
!ReadByte(&arrATx[2]) || !ReadByte(&arrATy[2]) || !ReadByte(&arrATx[3]) || !ReadByte(&arrATy[3]) )
{
return;
}
}
else
{
if ( !ReadByte(&arrATx[0]) || !ReadByte(&arrATy[0]) )
{
return;
}
}
}
// set up the arithmetic decoder
if ( !unMMR )
{
ResetGenericStats( unTempl, NULL );
m_pArithDecoder->Start();
}
// read the bitmap
JBIG2Bitmap *pBitmap = ReadGenericBitmap( unMMR, unW, unH, unTempl, unTpgdOn, FALSE, NULL, arrATx, arrATy, unMMR ? 0 : unLength - 18 );
// combine the region bitmap into the page bitmap
if ( bImm )
{
if ( m_unPageH == 0xffffffff && unY + unH > m_unCurPageH )
{
m_pPageBitmap->Expand( unY + unH, m_unPageDefPixel);
}
m_pPageBitmap->Combine( pBitmap, unX, unY, unExtCombOp );
delete pBitmap;
}
else // store the region bitmap
{
pBitmap->SetSegNum( unSegNum );
m_pSegments->Append( pBitmap );
}
return;
}
JBIG2Bitmap *JBIG2Stream::ReadGenericBitmap(BOOL bMMR, int nW, int nH, int unTempl, BOOL bTpgdOn, BOOL bUseSkip, JBIG2Bitmap *pSkip, int *pnATx, int *pnATy, int nMMrDataLength)
{
JBIG2Bitmap *pBitmap = new JBIG2Bitmap( 0, nW, nH );
pBitmap->ClearToZero();
if ( bMMR ) //----- MMR decode
{
m_pMMrDecoder->Reset();
int *pRefLine = (int *)MemUtilsMallocArray( nW + 2, sizeof(int) );
int *pCodingLine = (int *)MemUtilsMallocArray( nW + 2, sizeof(int) );
pCodingLine[0] = pCodingLine[1] = nW;
for ( int nY = 0; nY < nH; ++nY )
{
// copy coding line to ref line
int nIndex;
for ( nIndex = 0; pCodingLine[nIndex] < nW; ++nIndex )
{
pRefLine[nIndex] = pCodingLine[nIndex];
}
pRefLine[nIndex] = pRefLine[nIndex + 1] = nW;
// decode a line
int nRefIndex = 0; // nB1 = pRefLine[refI]
int nCodingIndex = 0; // nA1 = pCodingLine[codingI]
int nA0 = 0;
do
{
int nCode1 = m_pMMrDecoder->Get2DCode();
switch ( nCode1 )
{
case Pass_2D:
if ( pRefLine[nRefIndex] < nW )
{
nA0 = pRefLine[nRefIndex + 1];
nRefIndex += 2;
}
break;
case Horiz_2D:
{
int nCode2, nCode3;
if ( nCodingIndex & 1 )
{
nCode1 = 0;
do
{
nCode1 += nCode3 = m_pMMrDecoder->GetBlackCode();
} while ( nCode3 >= 64 );
nCode2 = 0;
do
{
nCode2 += nCode3 = m_pMMrDecoder->GetWhiteCode();
} while ( nCode3 >= 64 );
}
else
{
nCode1 = 0;
do
{
nCode1 += nCode3 = m_pMMrDecoder->GetWhiteCode();
} while ( nCode3 >= 64 );
nCode2 = 0;
do
{
nCode2 += nCode3 = m_pMMrDecoder->GetBlackCode();
} while ( nCode3 >= 64 );
}
if ( nCode1 > 0 || nCode2 > 0 )
{
nA0 = pCodingLine[nCodingIndex++] = nA0 + nCode1;
nA0 = pCodingLine[nCodingIndex++] = nA0 + nCode2;
while ( pRefLine[nRefIndex] <= nA0 && pRefLine[nRefIndex] < nW )
{
nRefIndex += 2;
}
}
}
break;
case Vert0_2D:
nA0 = pCodingLine[nCodingIndex++] = pRefLine[nRefIndex];
if ( pRefLine[nRefIndex] < nW )
{
++nRefIndex;
}
break;
case VertR1_2D:
nA0 = pCodingLine[nCodingIndex++] = pRefLine[nRefIndex] + 1;
if ( pRefLine[nRefIndex] < nW )
{
++nRefIndex;
while ( pRefLine[nRefIndex] <= nA0 && pRefLine[nRefIndex] < nW )
{
nRefIndex += 2;
}
}
break;
case VertR2_2D:
nA0 = pCodingLine[nCodingIndex++] = pRefLine[nRefIndex] + 2;
if ( pRefLine[nRefIndex] < nW )
{
++nRefIndex;
while ( pRefLine[nRefIndex] <= nA0 && pRefLine[nRefIndex] < nW )
{
nRefIndex += 2;
}
}
break;
case VertR3_2D:
nA0 = pCodingLine[nCodingIndex++] = pRefLine[nRefIndex] + 3;
if ( pRefLine[nRefIndex] < nW )
{
++nRefIndex;
while ( pRefLine[nRefIndex] <= nA0 && pRefLine[nRefIndex] < nW )
{
nRefIndex += 2;
}
}
break;
case VertL1_2D:
nA0 = pCodingLine[nCodingIndex++] = pRefLine[nRefIndex] - 1;
if ( nRefIndex > 0 )
{
--nRefIndex;
}
else
{
++nRefIndex;
}
while ( pRefLine[nRefIndex] <= nA0 && pRefLine[nRefIndex] < nW )
{
nRefIndex += 2;
}
break;
case VertL2_2D:
nA0 = pCodingLine[nCodingIndex++] = pRefLine[nRefIndex] - 2;
if ( nRefIndex > 0 )
{
--nRefIndex;
}
else
{
++nRefIndex;
}
while ( pRefLine[nRefIndex] <= nA0 && pRefLine[nRefIndex] < nW )
{
nRefIndex += 2;
}
break;
case VertL3_2D:
nA0 = pCodingLine[nCodingIndex++] = pRefLine[nRefIndex] - 3;
if ( nRefIndex > 0 )
{
--nRefIndex;
}
else
{
++nRefIndex;
}
while ( pRefLine[nRefIndex] <= nA0 && pRefLine[nRefIndex] < nW )
{
nRefIndex += 2;
}
break;
default:
break;
}
} while ( nA0 < nW );
pCodingLine[nCodingIndex++] = nW;
// convert the run lengths to a bitmap line
nIndex = 0;
while ( pCodingLine[nIndex] < nW )
{
for ( int nX = pCodingLine[nIndex]; nX < pCodingLine[nIndex + 1]; ++nX )
{
pBitmap->SetPixel( nX, nY );
}
nIndex += 2;
}
}
if ( nMMrDataLength >= 0 )
{
m_pMMrDecoder->SkipTo( nMMrDataLength );
}
else
{
if ( m_pMMrDecoder->Get24Bits() != 0x001001 )
{
}
}
MemUtilsFree( pRefLine );
MemUtilsFree( pCodingLine );
}
else //----- arithmetic decode
{
// set up the typical row context
unsigned int unLtpCX = 0;
if ( bTpgdOn )
{
switch ( unTempl )
{
case 0:
unLtpCX = 0x3953; // 001 11001 0101 0011
break;
case 1:
unLtpCX = 0x079a; // 0011 11001 101 0
break;
case 2:
unLtpCX = 0x0e3; // 001 1100 01 1
break;
case 3:
unLtpCX = 0x18a; // 01100 0101 1
break;
}
}
BOOL bLtp = 0;
unsigned int unCX = 0, unCX0 = 0, unCX1 = 0, unCX2 = 0;
JBIG2BitmapPtr oCXPtr0, oCXPtr1;
JBIG2BitmapPtr oATPtr0, oATPtr1, oATPtr2, oATPtr3;
for ( int nY = 0; nY < nH; ++nY )
{
// check for a "typical" (duplicate) row
if ( bTpgdOn )
{
if ( m_pArithDecoder->DecodeBit( unLtpCX, m_pGenericRegionStats ) )
{
bLtp = !bLtp;
}
if ( bLtp )
{
pBitmap->DuplicateRow( nY, nY - 1 );
continue;
}
}
switch ( unTempl )
{
case 0:
// set up the context
pBitmap->GetPixelPtr( 0, nY - 2, &oCXPtr0 );
unCX0 = pBitmap->NextPixel( &oCXPtr0 );
unCX0 = (unCX0 << 1) | pBitmap->NextPixel( &oCXPtr0 );
pBitmap->GetPixelPtr( 0, nY - 1, &oCXPtr1 );
unCX1 = pBitmap->NextPixel( &oCXPtr1 );
unCX1 = (unCX1 << 1) | pBitmap->NextPixel( &oCXPtr1 );
unCX1 = (unCX1 << 1) | pBitmap->NextPixel( &oCXPtr1 );
unCX2 = 0;
pBitmap->GetPixelPtr( pnATx[0], nY + pnATy[0], &oATPtr0 );
pBitmap->GetPixelPtr( pnATx[1], nY + pnATy[1], &oATPtr1 );
pBitmap->GetPixelPtr( pnATx[2], nY + pnATy[2], &oATPtr2 );
pBitmap->GetPixelPtr( pnATx[3], nY + pnATy[3], &oATPtr3 );
// decode the row
for ( int nX = 0; nX < nW; ++nX )
{
// build the context
unCX = (unCX0 << 13) | (unCX1 << 8) | (unCX2 << 4) | (pBitmap->NextPixel( &oATPtr0 ) << 3) | (pBitmap->NextPixel( &oATPtr1 ) << 2) | (pBitmap->NextPixel( &oATPtr2 ) << 1) | pBitmap->NextPixel( &oATPtr3 );
int nPixel;
if ( bUseSkip && pSkip->GetPixel( nX, nY ) ) // check for a skipped pixel
{
nPixel = 0;
}
else if ( ( nPixel = m_pArithDecoder->DecodeBit( unCX, m_pGenericRegionStats ) ) ) // decode the pixel
{
pBitmap->SetPixel( nX, nY );
}
// update the context
unCX0 = ((unCX0 << 1) | pBitmap->NextPixel( &oCXPtr0 )) & 0x07;
unCX1 = ((unCX1 << 1) | pBitmap->NextPixel( &oCXPtr1 )) & 0x1f;
unCX2 = ((unCX2 << 1) | nPixel) & 0x0f;
}
break;
case 1:
// set up the context
pBitmap->GetPixelPtr( 0, nY - 2, &oCXPtr0 );
unCX0 = pBitmap->NextPixel( &oCXPtr0 );
unCX0 = (unCX0 << 1) | pBitmap->NextPixel( &oCXPtr0 );
unCX0 = (unCX0 << 1) | pBitmap->NextPixel( &oCXPtr0 );
pBitmap->GetPixelPtr( 0, nY - 1, &oCXPtr1 );
unCX1 = pBitmap->NextPixel( &oCXPtr1 );
unCX1 = (unCX1 << 1) | pBitmap->NextPixel( &oCXPtr1 );
unCX1 = (unCX1 << 1) | pBitmap->NextPixel( &oCXPtr1 );
unCX2 = 0;
pBitmap->GetPixelPtr( pnATx[0], nY + pnATy[0], &oATPtr0 );
// decode the row
for ( int nX = 0; nX < nW; ++nX )
{
// build the context
unCX = (unCX0 << 9) | (unCX1 << 4) | (unCX2 << 1) | pBitmap->NextPixel( &oATPtr0 );
int nPixel;
if ( bUseSkip && pSkip->GetPixel( nX, nY ) ) // check for a skipped pixel
{
nPixel = 0;
}
else if ( ( nPixel = m_pArithDecoder->DecodeBit( unCX, m_pGenericRegionStats ) ) ) // decode the pixel
{
pBitmap->SetPixel( nX, nY );
}
// update the context
unCX0 = ((unCX0 << 1) | pBitmap->NextPixel( &oCXPtr0 )) & 0x0f;
unCX1 = ((unCX1 << 1) | pBitmap->NextPixel( &oCXPtr1 )) & 0x1f;
unCX2 = ((unCX2 << 1) | nPixel) & 0x07;
}
break;
case 2:
// set up the context
pBitmap->GetPixelPtr( 0, nY - 2, &oCXPtr0 );
unCX0 = pBitmap->NextPixel( &oCXPtr0 );
unCX0 = (unCX0 << 1) | pBitmap->NextPixel( &oCXPtr0 );
pBitmap->GetPixelPtr( 0, nY - 1, &oCXPtr1 );
unCX1 = pBitmap->NextPixel( &oCXPtr1 );
unCX1 = (unCX1 << 1) | pBitmap->NextPixel( &oCXPtr1 );
unCX2 = 0;
pBitmap->GetPixelPtr( pnATx[0], nY + pnATy[0], &oATPtr0 );
// decode the row
for ( int nX = 0; nX < nW; ++nX )
{
// build the context
unCX = (unCX0 << 7) | (unCX1 << 3) | (unCX2 << 1) | pBitmap->NextPixel( &oATPtr0 );
int nPixel;
if ( bUseSkip && pSkip->GetPixel( nX, nY ) ) // check for a skipped pixel
{
nPixel = 0;
}
else if ( ( nPixel = m_pArithDecoder->DecodeBit( unCX, m_pGenericRegionStats ) ) ) // decode the pixel
{
pBitmap->SetPixel( nX, nY );
}
// update the context
unCX0 = ((unCX0 << 1) | pBitmap->NextPixel( &oCXPtr0 )) & 0x07;
unCX1 = ((unCX1 << 1) | pBitmap->NextPixel( &oCXPtr1 )) & 0x0f;
unCX2 = ((unCX2 << 1) | nPixel) & 0x03;
}
break;
case 3:
// set up the context
pBitmap->GetPixelPtr( 0, nY - 1, &oCXPtr1 );
unCX1 = pBitmap->NextPixel( &oCXPtr1 );
unCX1 = (unCX1 << 1) | pBitmap->NextPixel( &oCXPtr1 );
unCX2 = 0;
pBitmap->GetPixelPtr( pnATx[0], nY + pnATy[0], &oATPtr0 );
// decode the row
for ( int nX = 0; nX < nW; ++nX )
{
// build the context
unCX = (unCX1 << 5) | (unCX2 << 1) | pBitmap->NextPixel( &oATPtr0 );
int nPixel;
if ( bUseSkip && pSkip->GetPixel( nX, nY ) ) // check for a skipped pixel
{
nPixel = 0;
}
else if ( ( nPixel = m_pArithDecoder->DecodeBit( unCX, m_pGenericRegionStats ) ) ) // decode the pixel
{
pBitmap->SetPixel( nX, nY );
}
// update the context
unCX1 = ((unCX1 << 1) | pBitmap->NextPixel( &oCXPtr1 )) & 0x1f;
unCX2 = ((unCX2 << 1) | nPixel) & 0x0f;
}
break;
}
}
}
return pBitmap;
}
void JBIG2Stream::ReadGenericRefinementRegionSegment(unsigned int unSegNum, BOOL bImm, BOOL bLossless, unsigned int unLength, unsigned int *punRefSegs, unsigned int unRefSegsCount)
{
unsigned int unW, unH, unX, unY, unSegInfoFlags;
// region segment info field
if ( !ReadULong( &unW ) || !ReadULong( &unH ) || !ReadULong( &unX ) || !ReadULong( &unY ) || !ReadUByte( &unSegInfoFlags ) )
{
return;
}
unsigned int unExtCombOp = unSegInfoFlags & 7;
// rest of the generic refinement region segment header
unsigned int unFlags;
if ( !ReadUByte( &unFlags ) )
{
return;
}
unsigned int unTempl = unFlags & 1;
unsigned int unTpgrOn = (unFlags >> 1) & 1;
// AT flags
int arrATx[2], arrATy[2];
if ( !unTempl )
{
if ( !ReadByte( &arrATx[0] ) || !ReadByte( &arrATy[0] ) || !ReadByte( &arrATx[1] ) || !ReadByte( &arrATy[1] ) )
{
return;
}
}
// resize the page bitmap if needed
if ( unRefSegsCount == 0 || bImm )
{
if ( m_unPageH == 0xffffffff && unY + unH > m_unCurPageH )
{
m_pPageBitmap->Expand( unY + unH, m_unPageDefPixel );
}
}
// get referenced bitmap
JBIG2Bitmap *pRefBitmap = NULL;
if ( unRefSegsCount > 1 )
{
return;
}
if ( unRefSegsCount == 1 )
{
JBIG2Segment *pSegment = FindSegment( punRefSegs[0] );
if ( pSegment->GetType() != jbig2SegBitmap )
{
return;
}
pRefBitmap = (JBIG2Bitmap *)pSegment;
}
else
{
pRefBitmap = m_pPageBitmap->GetSlice( unX, unY, unW, unH );
}
// set up the arithmetic decoder
ResetRefinementStats( unTempl, NULL );
m_pArithDecoder->Start();
// read
JBIG2Bitmap *pBitmap = ReadGenericRefinementRegion( unW, unH, unTempl, unTpgrOn, pRefBitmap, 0, 0, arrATx, arrATy );
if ( bImm ) // combine the region bitmap into the page bitmap
{
m_pPageBitmap->Combine( pBitmap, unX, unY, unExtCombOp );
delete pBitmap;
}
else // store the region bitmap
{
pBitmap->SetSegNum( unSegNum );
m_pSegments->Append( pBitmap );
}
// delete the referenced bitmap
if ( unRefSegsCount == 1 )
{
DiscardSegment( punRefSegs[0] );
}
else
{
delete pRefBitmap;
}
return;
}
JBIG2Bitmap *JBIG2Stream::ReadGenericRefinementRegion(int nW, int nH, int nTempl, BOOL bTpgrOn, JBIG2Bitmap *pRefBitmap, int nRefDX, int nRefDY, int *pnAtx, int *pnAty)
{
JBIG2Bitmap *pBitmap = new JBIG2Bitmap( 0, nW, nH );
pBitmap->ClearToZero();
// Typical row context
unsigned int unLtpCX;
if ( nTempl )
{
unLtpCX = 0x008;
}
else
{
unLtpCX = 0x0010;
}
BOOL bLtp = 0;
unsigned int unCx0, unCx2, unCx3, unCx4;
JBIG2BitmapPtr oCxPtr0, oCxPtr1, oCxPtr2, oCxPtr3, oCxPtr4, oCxPtr5, oCxPtr6;
for ( int nY = 0; nY < nH; ++nY )
{
if ( nTempl )
{
// set up the context
pBitmap->GetPixelPtr( 0, nY - 1, &oCxPtr0 );
unCx0 = pBitmap->NextPixel( &oCxPtr0 );
pBitmap->GetPixelPtr(-1, nY, &oCxPtr1 );
pRefBitmap->GetPixelPtr( - nRefDX, nY - 1 - nRefDY, &oCxPtr2 );
pRefBitmap->GetPixelPtr( -1 - nRefDX, nY - nRefDY, &oCxPtr3 );
unCx3 = pRefBitmap->NextPixel( &oCxPtr3 );
unCx3 = (unCx3 << 1) | pRefBitmap->NextPixel( &oCxPtr3 );
pRefBitmap->GetPixelPtr( -nRefDX, nY + 1 - nRefDY, &oCxPtr4 );
unCx4 = pRefBitmap->NextPixel( &oCxPtr4 );
// set up the typical prediction context
unsigned int unTpgrCX0 = 0, unTpgrCX1 = 0, unTpgrCX2 = 0;
JBIG2BitmapPtr oTpgrCXPtr0, oTpgrCXPtr1, oTpgrCXPtr2;
if ( bTpgrOn )
{
pRefBitmap->GetPixelPtr( - 1 - nRefDX, nY - 1 - nRefDY, &oTpgrCXPtr0 );
unTpgrCX0 = pRefBitmap->NextPixel( &oTpgrCXPtr0 );
unTpgrCX0 = (unTpgrCX0 << 1) | pRefBitmap->NextPixel( &oTpgrCXPtr0 );
unTpgrCX0 = (unTpgrCX0 << 1) | pRefBitmap->NextPixel( &oTpgrCXPtr0 );
pRefBitmap->GetPixelPtr( - 1 - nRefDX, nY - nRefDY, &oTpgrCXPtr1 );
unTpgrCX1 = pRefBitmap->NextPixel( &oTpgrCXPtr1 );
unTpgrCX1 = (unTpgrCX1 << 1) | pRefBitmap->NextPixel( &oTpgrCXPtr1 );
unTpgrCX1 = (unTpgrCX1 << 1) | pRefBitmap->NextPixel( &oTpgrCXPtr1 );
pRefBitmap->GetPixelPtr( - 1 - nRefDX, nY + 1 - nRefDY, &oTpgrCXPtr2 );
unTpgrCX2 = pRefBitmap->NextPixel( &oTpgrCXPtr2 );
unTpgrCX2 = (unTpgrCX2 << 1) | pRefBitmap->NextPixel( &oTpgrCXPtr2 );
unTpgrCX2 = (unTpgrCX2 << 1) | pRefBitmap->NextPixel( &oTpgrCXPtr2 );
}
for ( int nX = 0; nX < nW; ++nX )
{
// update the context
unCx0 = ((unCx0 << 1) | pBitmap->NextPixel(&oCxPtr0)) & 7;
unCx3 = ((unCx3 << 1) | pRefBitmap->NextPixel(&oCxPtr3)) & 7;
unCx4 = ((unCx4 << 1) | pRefBitmap->NextPixel(&oCxPtr4)) & 3;
if ( bTpgrOn )
{
// update the typical predictor context
unTpgrCX0 = ((unTpgrCX0 << 1) | pRefBitmap->NextPixel(&oTpgrCXPtr0)) & 7;
unTpgrCX1 = ((unTpgrCX1 << 1) | pRefBitmap->NextPixel(&oTpgrCXPtr1)) & 7;
unTpgrCX2 = ((unTpgrCX2 << 1) | pRefBitmap->NextPixel(&oTpgrCXPtr2)) & 7;
// check for a "typical" pixel
if ( m_pArithDecoder->DecodeBit( unLtpCX, m_pRefinementRegionStats ) )
{
bLtp = !bLtp;
}
if ( unTpgrCX0 == 0 && unTpgrCX1 == 0 && unTpgrCX2 == 0 )
{
pBitmap->ClearPixel(nX, nY);
continue;
}
else if ( unTpgrCX0 == 7 && unTpgrCX1 == 7 && unTpgrCX2 == 7 )
{
pBitmap->SetPixel(nX, nY);
continue;
}
}
// build the context
unsigned int unCx = (unCx0 << 7) | (pBitmap->NextPixel( &oCxPtr1 ) << 6) | (pRefBitmap->NextPixel(&oCxPtr2) << 5) | (unCx3 << 2) | unCx4;
// decode the pixel
int nPix;
if ( ( nPix = m_pArithDecoder->DecodeBit( unCx, m_pRefinementRegionStats ) ) )
{
pBitmap->SetPixel(nX, nY);
}
}
}
else
{
// set up the context
pBitmap->GetPixelPtr( 0, nY-1, &oCxPtr0 );
unCx0 = pBitmap->NextPixel( &oCxPtr0 );
pBitmap->GetPixelPtr(-1, nY, &oCxPtr1 );
pRefBitmap->GetPixelPtr(-nRefDX, nY-1-nRefDY, &oCxPtr2 );
unCx2 = pRefBitmap->NextPixel( &oCxPtr2 );
pRefBitmap->GetPixelPtr(-1-nRefDX, nY-nRefDY, &oCxPtr3 );
unCx3 = pRefBitmap->NextPixel( &oCxPtr3 );
unCx3 = (unCx3 << 1) | pRefBitmap->NextPixel( &oCxPtr3 );
pRefBitmap->GetPixelPtr(-1-nRefDX, nY+1-nRefDY, &oCxPtr4 );
unCx4 = pRefBitmap->NextPixel( &oCxPtr4 );
unCx4 = (unCx4 << 1) | pRefBitmap->NextPixel( &oCxPtr4 );
pBitmap->GetPixelPtr( pnAtx[0], nY + pnAty[0], &oCxPtr5 );
pRefBitmap->GetPixelPtr( pnAtx[1]-nRefDX, nY + pnAty[1]-nRefDY, &oCxPtr6 );
// set up the typical prediction context
unsigned int unTpgrCX0 = 0, unTpgrCX1 = 0, unTpgrCX2 = 0;
JBIG2BitmapPtr oTpgrCXPtr0, oTpgrCXPtr1, oTpgrCXPtr2;
if ( bTpgrOn )
{
pRefBitmap->GetPixelPtr( - 1 - nRefDX, nY - 1 - nRefDY, &oTpgrCXPtr0 );
unTpgrCX0 = pRefBitmap->NextPixel( &oTpgrCXPtr0 );
unTpgrCX0 = (unTpgrCX0 << 1) | pRefBitmap->NextPixel( &oTpgrCXPtr0 );
unTpgrCX0 = (unTpgrCX0 << 1) | pRefBitmap->NextPixel( &oTpgrCXPtr0 );
pRefBitmap->GetPixelPtr( -1 - nRefDX, nY - nRefDY, &oTpgrCXPtr1 );
unTpgrCX1 = pRefBitmap->NextPixel( &oTpgrCXPtr1 );
unTpgrCX1 = (unTpgrCX1 << 1) | pRefBitmap->NextPixel( &oTpgrCXPtr1 );
unTpgrCX1 = (unTpgrCX1 << 1) | pRefBitmap->NextPixel( &oTpgrCXPtr1 );
pRefBitmap->GetPixelPtr( - 1 - nRefDX, nY + 1 - nRefDY, &oTpgrCXPtr2 );
unTpgrCX2 = pRefBitmap->NextPixel( &oTpgrCXPtr2 );
unTpgrCX2 = (unTpgrCX2 << 1) | pRefBitmap->NextPixel( &oTpgrCXPtr2 );
unTpgrCX2 = (unTpgrCX2 << 1) | pRefBitmap->NextPixel( &oTpgrCXPtr2 );
}
for ( int nX = 0; nX < nW; ++nX )
{
// update the context
unCx0 = ((unCx0 << 1) | pBitmap->NextPixel(&oCxPtr0)) & 3;
unCx2 = ((unCx2 << 1) | pRefBitmap->NextPixel(&oCxPtr2)) & 3;
unCx3 = ((unCx3 << 1) | pRefBitmap->NextPixel(&oCxPtr3)) & 7;
unCx4 = ((unCx4 << 1) | pRefBitmap->NextPixel(&oCxPtr4)) & 7;
if ( bTpgrOn )
{
// update the typical predictor context
unTpgrCX0 = ((unTpgrCX0 << 1) | pRefBitmap->NextPixel(&oTpgrCXPtr0)) & 7;
unTpgrCX1 = ((unTpgrCX1 << 1) | pRefBitmap->NextPixel(&oTpgrCXPtr1)) & 7;
unTpgrCX2 = ((unTpgrCX2 << 1) | pRefBitmap->NextPixel(&oTpgrCXPtr2)) & 7;
// check for a "typical" pixel
if ( m_pArithDecoder->DecodeBit( unLtpCX, m_pRefinementRegionStats ) )
{
bLtp = !bLtp;
}
if ( unTpgrCX0 == 0 && unTpgrCX1 == 0 && unTpgrCX2 == 0 )
{
pBitmap->ClearPixel(nX, nY);
continue;
}
else if ( unTpgrCX0 == 7 && unTpgrCX1 == 7 && unTpgrCX2 == 7 )
{
pBitmap->SetPixel(nX, nY);
continue;
}
}
// build the context
unsigned int unCx = (unCx0 << 11) | (pBitmap->NextPixel( &oCxPtr1 ) << 10) | (unCx2 << 8) | (unCx3 << 5) | (unCx4 << 2) | (pBitmap->NextPixel( &oCxPtr5 ) << 1) | pRefBitmap->NextPixel( &oCxPtr6 );
// decode the pixel
int nPix;
if ( ( nPix = m_pArithDecoder->DecodeBit(unCx, m_pRefinementRegionStats ) ) )
{
pBitmap->SetPixel(nX, nY);
}
}
}
}
return pBitmap;
}
void JBIG2Stream::ReadPageInfoSegment(unsigned int unLength)
{
unsigned int unResX, unResY, unFlags, unStriping;
if ( !ReadULong( &m_unPageW ) || !ReadULong( &m_unPageH ) || !ReadULong( &unResX ) || !ReadULong( &unResY ) || !ReadUByte( &unFlags ) || !ReadUWord( &unStriping ) )
{
return;
}
m_unPageDefPixel = (unFlags >> 2) & 1;
m_unDefCombOp = (unFlags >> 3) & 3;
if ( 0xffffffff == m_unPageH )
{
m_unCurPageH = unStriping & 0x7fff;
}
else
{
m_unCurPageH = m_unPageH;
}
m_pPageBitmap = new JBIG2Bitmap( 0, m_unPageW, m_unPageH );
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if ( m_unPageDefPixel )
{
m_pPageBitmap->ClearToOne();
}
else
{
m_pPageBitmap->ClearToZero();
}
return;
}
void JBIG2Stream::ReadEndOfStripeSegment(unsigned int unLength)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
for ( unsigned int unIndex = 0; unIndex < unLength; ++unIndex )
{
m_pCurStream->GetChar();
}
}
void JBIG2Stream::ReadProfilesSegment (unsigned int unLength)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
for ( unsigned int unIndex = 0; unIndex < unLength; ++unIndex )
{
m_pCurStream->GetChar();
}
}
void JBIG2Stream::ReadCodeTableSegment(unsigned int unSegNum, unsigned int unLength)
{
unsigned int unFlags;
int nLowVal, nHighVal;
if ( !ReadUByte(&unFlags) || !ReadLong(&nLowVal) || !ReadLong(&nHighVal) )
{
return;
}
unsigned int unOOB = unFlags & 1;
unsigned int unPrefixBits = ((unFlags >> 1) & 7) + 1;
unsigned int unRangeBits = ((unFlags >> 4) & 7) + 1;
m_pHuffDecoder->Reset();
unsigned int unHuffTabSize = 8;
JBIG2HuffmanTable *pHuffTable = (JBIG2HuffmanTable *)MemUtilsMallocArray( unHuffTabSize, sizeof(JBIG2HuffmanTable) );
unsigned int unIndex = 0;
int nVal = nLowVal;
while ( nVal < nHighVal )
{
if ( unIndex == unHuffTabSize )
{
unHuffTabSize *= 2;
pHuffTable = (JBIG2HuffmanTable *)MemUtilsReallocArray( pHuffTable, unHuffTabSize, sizeof(JBIG2HuffmanTable) );
}
pHuffTable[unIndex].nValue = nVal;
pHuffTable[unIndex].unPrefixLen = m_pHuffDecoder->ReadBits( unPrefixBits );
pHuffTable[unIndex].unRangeLen = m_pHuffDecoder->ReadBits( unRangeBits );
nVal += 1 << pHuffTable[unIndex].unRangeLen;
++unIndex;
}
if ( unIndex + unOOB + 3 > unHuffTabSize )
{
unHuffTabSize = unIndex + unOOB + 3;
pHuffTable = (JBIG2HuffmanTable *)MemUtilsReallocArray( pHuffTable, unHuffTabSize, sizeof(JBIG2HuffmanTable) );
}
pHuffTable[unIndex].nValue = nLowVal - 1;
pHuffTable[unIndex].unPrefixLen = m_pHuffDecoder->ReadBits( unPrefixBits );
pHuffTable[unIndex].unRangeLen = jbig2HuffmanLOW;
++unIndex;
pHuffTable[unIndex].nValue = nHighVal;
pHuffTable[unIndex].unPrefixLen = m_pHuffDecoder->ReadBits( unPrefixBits );
pHuffTable[unIndex].unRangeLen = 32;
++unIndex;
if ( unOOB )
{
pHuffTable[unIndex].nValue = 0;
pHuffTable[unIndex].unPrefixLen = m_pHuffDecoder->ReadBits( unPrefixBits );
pHuffTable[unIndex].unRangeLen = jbig2HuffmanOOB;
++unIndex;
}
pHuffTable[unIndex].nValue = 0;
pHuffTable[unIndex].unPrefixLen = 0;
pHuffTable[unIndex].unRangeLen = jbig2HuffmanEOT;
m_pHuffDecoder->BuildTable( pHuffTable, unIndex );
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
m_pSegments->Append( new JBIG2CodeTable( unSegNum, pHuffTable ) );
return;
}
void JBIG2Stream::ReadExtensionSegment(unsigned int unLength)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
for ( unsigned int unIndex = 0; unIndex < unLength; ++unIndex )
{
m_pCurStream->GetChar();
}
}
JBIG2Segment *JBIG2Stream::FindSegment (unsigned int unSegNum)
{
JBIG2Segment *pSegment = NULL;
for ( int nIndex = 0; nIndex < m_pGlobalSegments->GetLength(); ++nIndex )
{
pSegment = (JBIG2Segment *)m_pGlobalSegments->GetByIndex(nIndex);
if ( pSegment->GetSegNum() == unSegNum )
{
return pSegment;
}
}
for ( int nIndex = 0; nIndex < m_pSegments->GetLength(); ++nIndex )
{
pSegment = (JBIG2Segment *)m_pSegments->GetByIndex(nIndex);
if ( pSegment->GetSegNum() == unSegNum )
{
return pSegment;
}
}
return NULL;
}
void JBIG2Stream::DiscardSegment(unsigned int unSegNum)
{
JBIG2Segment *pSegment = NULL;
for ( int nIndex = 0; nIndex < m_pGlobalSegments->GetLength(); ++nIndex )
{
pSegment = (JBIG2Segment *)m_pGlobalSegments->GetByIndex(nIndex);
if ( pSegment->GetSegNum() == unSegNum )
{
m_pGlobalSegments->Delete(nIndex);
return;
}
}
for ( int nIndex = 0; nIndex < m_pSegments->GetLength(); ++nIndex )
{
pSegment = (JBIG2Segment *)m_pSegments->GetByIndex(nIndex);
if ( pSegment->GetSegNum() == unSegNum )
{
m_pSegments->Delete(nIndex);
return;
}
}
}
void JBIG2Stream::ResetGenericStats(unsigned int unTempl, JArithmeticDecoderStats *pPrevStats)
{
int nSize = c_arrContextSize[unTempl];
if ( pPrevStats && pPrevStats->GetContextSize() == nSize )
{
if ( m_pGenericRegionStats->GetContextSize() == nSize )
{
m_pGenericRegionStats->CopyFrom( pPrevStats );
}
else
{
delete m_pGenericRegionStats;
m_pGenericRegionStats = pPrevStats->Copy();
}
}
else
{
if ( m_pGenericRegionStats->GetContextSize() == nSize )
{
m_pGenericRegionStats->Reset();
}
else
{
delete m_pGenericRegionStats;
m_pGenericRegionStats = new JArithmeticDecoderStats(1 << nSize);
}
}
}
void JBIG2Stream::ResetRefinementStats(unsigned int unTempl, JArithmeticDecoderStats *pPrevStats)
{
int nSize = c_arrRefContextSize[unTempl];
if ( pPrevStats && pPrevStats->GetContextSize() == nSize )
{
if ( m_pRefinementRegionStats->GetContextSize() == nSize )
{
m_pRefinementRegionStats->CopyFrom( pPrevStats );
}
else
{
delete m_pRefinementRegionStats;
m_pRefinementRegionStats = pPrevStats->Copy();
}
}
else
{
if ( m_pRefinementRegionStats->GetContextSize() == nSize )
{
m_pRefinementRegionStats->Reset();
}
else
{
delete m_pRefinementRegionStats;
m_pRefinementRegionStats = new JArithmeticDecoderStats(1 << nSize);
}
}
}
void JBIG2Stream::ResetIntStats(int nSymCodeLen)
{
m_pIadhStats->Reset();
m_pIadwStats->Reset();
m_pIaexStats->Reset();
m_pIaaiStats->Reset();
m_pIadtStats->Reset();
m_pIaitStats->Reset();
m_pIafsStats->Reset();
m_pIadsStats->Reset();
m_pIardxStats->Reset();
m_pIardyStats->Reset();
m_pIardwStats->Reset();
m_pIardhStats->Reset();
m_pIariStats->Reset();
if ( m_pIaidStats->GetContextSize() == 1 << (nSymCodeLen + 1) )
{
m_pIaidStats->Reset();
}
else
{
delete m_pIaidStats;
m_pIaidStats = new JArithmeticDecoderStats( 1 << (nSymCodeLen + 1) );
}
}
BOOL JBIG2Stream::ReadUByte(unsigned int *pBuffer)
{
int nChar;
if ( EOF == ( nChar = m_pCurStream->GetChar() ) )
{
return FALSE;
}
*pBuffer = (unsigned int)nChar;
return TRUE;
}
BOOL JBIG2Stream::ReadByte ( int *pBuffer)
{
int nChar;
if ( EOF == ( nChar = m_pCurStream->GetChar() ) )
{
return FALSE;
}
*pBuffer = nChar;
if ( nChar & 0x80 )
{
*pBuffer |= -1 - 0xff;
}
return TRUE;
}
BOOL JBIG2Stream::ReadUWord(unsigned int *pBuffer)
{
int nChar0, nChar1;
if ( EOF == ( nChar0 = m_pCurStream->GetChar() ) || EOF == ( nChar1 = m_pCurStream->GetChar() ) )
{
return FALSE;
}
*pBuffer = (unsigned int)((nChar0 << 8) | nChar1);
return TRUE;
}
BOOL JBIG2Stream::ReadULong(unsigned int *pBuffer)
{
int nChar0, nChar1, nChar2, nChar3;
if ( EOF == ( nChar0 = m_pCurStream->GetChar() ) || EOF == ( nChar1 = m_pCurStream->GetChar() ) ||
EOF == ( nChar2 = m_pCurStream->GetChar() ) || EOF == ( nChar3 = m_pCurStream->GetChar() ) )
{
return FALSE;
}
*pBuffer = (unsigned int)((nChar0 << 24) | (nChar1 << 16) | (nChar2 << 8) | nChar3);
return TRUE;
}
BOOL JBIG2Stream::ReadLong ( int *pBuffer)
{
int nChar0, nChar1, nChar2, nChar3;
if ( EOF == (nChar0 = m_pCurStream->GetChar() ) || EOF == (nChar1 = m_pCurStream->GetChar() ) ||
EOF == (nChar2 = m_pCurStream->GetChar() ) || EOF == (nChar3 = m_pCurStream->GetChar() ) )
{
return FALSE;
}
*pBuffer = ((nChar0 << 24) | (nChar1 << 16) | (nChar2 << 8) | nChar3);
if ( nChar0 & 0x80 )
{
*pBuffer |= -1 - (int)0xffffffff;
}
return TRUE;
}