Files
core/ASCOfficePDFReader/Stream.cpp

5467 lines
119 KiB
C++

#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <limits.h>
#include <string.h>
#include <ctype.h>
#include "MemoryUtils.h"
#include "File.h"
#include "Constants.h"
#include "Object.h"
#include "Lexer.h"
#include "GState.h"
#include "Stream.h"
#include "CCITT-Tables.h"
#include "JPXStream.h"
#include "JBIG2Stream.h"
//#define USE_ZLIB // Äëÿ äåêîäèðîâàíèÿ ïîòîêîâ â Flate èñïîëüçóåì Zlib èëè âíóòðåííèé äåêîäåð
//---------------------------------------------------------------------------------------------------------------
// Stream (îñíîâíîé êëàññ)
//---------------------------------------------------------------------------------------------------------------
Stream::Stream()
{
m_nRef = 1;
}
Stream::~Stream()
{
}
void Stream::Close()
{
}
int Stream::GetRawChar()
{
// TO DO : Error "Internal: called GetRawChar() on non-predictor stream"
return EOF;
}
char *Stream::GetLine(char *sBuffer, int nSize)
{
int nIndex;
if ( LookChar() == EOF )
return NULL;
for (nIndex = 0; nIndex < nSize - 1; ++nIndex )
{
int nChar = GetChar();
if ( nChar == EOF || nChar == '\n' )
break;
if ( nChar == '\r' )
{
if ( ( nChar = LookChar() ) == '\n' )
GetChar();
break;
}
sBuffer[nIndex] = nChar;
}
sBuffer[nIndex] = '\0';
return sBuffer;
}
StringExt *Stream::GetPSFilter(int nPSLevel, char *sIndent)
{
return new StringExt();
}
Stream *Stream::AddFilters(Object *pDict)
{
Object oTemp;
Object oParms, params2;
Stream *pStream = this;
pDict->DictLookup("Filter", &oTemp);
if ( oTemp.IsNull() )
{
oTemp.Free();
pDict->DictLookup("F", &oTemp);
}
pDict->DictLookup("DecodeParms", &oParms);
if ( oParms.IsNull() )
{
oParms.Free();
pDict->DictLookup("DP", &oParms);
}
if ( oTemp.IsName() )
{
pStream = ApplyFilter( oTemp.GetName(), pStream, &oParms);
}
else if ( oTemp.IsArray() )
{
for (int nIndex = 0; nIndex < oTemp.ArrayGetLength(); ++nIndex)
{
Object oItem, oItemParams;
oTemp.ArrayGet( nIndex, &oItem);
if ( oParms.IsArray() )
oParms.ArrayGet( nIndex, &oItemParams);
else
oItemParams.InitNull();
if ( oItem.IsName() )
{
pStream = ApplyFilter( oItem.GetName(), pStream, &oItemParams);
}
else
{
// TO DO: Error "Bad filter name"
pStream = new EOFStream( pStream );
}
oItem.Free();
oItemParams.Free();
}
}
else if ( !oTemp.IsNull() )
{
// TO DO: Error "Bad 'Filter' attribute in stream"
}
oTemp.Free();
oParms.Free();
return pStream;
}
Stream *Stream::ApplyFilter(char *sName, Stream *pStream, Object *pParams)
{
if ( !strcmp( sName, "ASCIIHexDecode") || !strcmp( sName, "AHx") )
{
pStream = new ASCIIHexStream(pStream);
}
else if ( !strcmp( sName, "ASCII85Decode" ) || !strcmp( sName, "A85") )
{
pStream = new ASCII85Stream(pStream);
}
else if ( !strcmp( sName, "LZWDecode" ) || !strcmp( sName, "LZW") )
{
int nPredictor = 1;
int nColumns = 1;
int nColors = 1;
int nBitsPerComponent = 8;
int nEarlyChange = 1;
if ( pParams->IsDict() )
{
Object oTemp;
pParams->DictLookup("Predictor", &oTemp);
if ( oTemp.IsInt() )
nPredictor = oTemp.GetInt();
oTemp.Free();
pParams->DictLookup("Columns", &oTemp);
if ( oTemp.IsInt() )
nColumns = oTemp.GetInt();
oTemp.Free();
pParams->DictLookup("Colors", &oTemp);
if ( oTemp.IsInt() )
nColors = oTemp.GetInt();
oTemp.Free();
pParams->DictLookup("BitsPerComponent", &oTemp);
if ( oTemp.IsInt() )
nBitsPerComponent = oTemp.GetInt();
oTemp.Free();
pParams->DictLookup("EarlyChange", &oTemp);
if ( oTemp.IsInt() )
nEarlyChange = oTemp.GetInt();
oTemp.Free();
}
pStream = new LZWStream( pStream, nPredictor, nColumns, nColors, nBitsPerComponent, nEarlyChange);
}
else if ( !strcmp( sName, "RunLengthDecode" ) || !strcmp( sName, "RL") )
{
pStream = new RunLengthStream(pStream);
}
else if ( !strcmp( sName, "CCITTFaxDecode" ) || !strcmp( sName, "CCF") )
{
int nK = 0;
BOOL bEndOfLine = FALSE;
BOOL bByteAlign = FALSE;
int nColumns = 1728;
int nRows = 0;
BOOL bEndOfBlock = TRUE;
BOOL bBlackIs1 = FALSE;
if ( pParams->IsDict() )
{
Object oTemp;
pParams->DictLookup("K", &oTemp);
if ( oTemp.IsInt() )
nK = oTemp.GetInt();
oTemp.Free();
pParams->DictLookup("EndOfLine", &oTemp);
if ( oTemp.IsBool() )
bEndOfLine = oTemp.GetBool();
oTemp.Free();
pParams->DictLookup("EncodedByteAlign", &oTemp);
if ( oTemp.IsBool() )
bByteAlign = oTemp.GetBool();
oTemp.Free();
pParams->DictLookup("Columns", &oTemp);
if ( oTemp.IsInt() )
nColumns = oTemp.GetInt();
oTemp.Free();
pParams->DictLookup("Rows", &oTemp);
if ( oTemp.IsInt() )
nRows = oTemp.GetInt();
oTemp.Free();
pParams->DictLookup("EndOfBlock", &oTemp);
if ( oTemp.IsBool() )
bEndOfBlock = oTemp.GetBool();
oTemp.Free();
pParams->DictLookup("BlackIs1", &oTemp);
if ( oTemp.IsBool() )
bBlackIs1 = oTemp.GetBool();
oTemp.Free();
// TO DO: Äîáàâèòü ÷òåíèå ïîëÿ "DamagedRowsBeforeError"
}
pStream = new CCITTFaxStream( pStream, nK, bEndOfLine, bByteAlign, nColumns, nRows, bEndOfBlock, bBlackIs1);
}
else if ( !strcmp( sName, "DCTDecode" ) || !strcmp( sName, "DCT") )
{
int nColorTransform = -1;
if ( pParams->IsDict() )
{
Object oTemp;
if ( pParams->DictLookup("ColorTransform", &oTemp)->IsInt() )
nColorTransform = oTemp.GetInt();
oTemp.Free();
}
pStream = new DCTStream( pStream, nColorTransform);
}
else if ( !strcmp( sName, "FlateDecode" ) || !strcmp( sName, "Fl" ) )
{
int nPredictor = 1;
int nColors = 1;
int nBitsPerComponent = 8;
int nColumns = 1;
if ( pParams->IsDict() )
{
Object oTemp;
pParams->DictLookup("Predictor", &oTemp);
if ( oTemp.IsInt() )
nPredictor = oTemp.GetInt();
oTemp.Free();
pParams->DictLookup("Colors", &oTemp);
if ( oTemp.IsInt() )
nColors = oTemp.GetInt();
oTemp.Free();
pParams->DictLookup("BitsPerComponent", &oTemp);
if ( oTemp.IsInt() )
nBitsPerComponent = oTemp.GetInt();
oTemp.Free();
pParams->DictLookup("Columns", &oTemp);
if ( oTemp.IsInt() )
nColumns = oTemp.GetInt();
oTemp.Free();
}
#ifdef USE_ZLIB
pStream = new FlateZlibStream( pStream, nPredictor, nColumns, nColors, nBitsPerComponent );
#else
pStream = new FlateStream( pStream, nPredictor, nColumns, nColors, nBitsPerComponent);
#endif
}
else if ( !strcmp( sName, "JBIG2Decode" ) )
{
Object oJBIG2Globals;
if ( pParams->IsDict() )
{
pParams->DictLookup("JBIG2Globals", &oJBIG2Globals);
}
// TO DO: Ñäåëàòü äàííûé ôèëüòð
pStream = new JBIG2Stream( pStream, &oJBIG2Globals );
oJBIG2Globals.Free();
}
else if ( !strcmp( sName, "JPXDecode" ) )
{
pStream = new JPXStream(pStream);
}
else
{
// TO DO: Error "Unknown filter"
pStream = new EOFStream(pStream);
}
return pStream;
}
//---------------------------------------------------------------------------------------------------------------
// BaseStream
//---------------------------------------------------------------------------------------------------------------
BaseStream::BaseStream(Object *pDict)
{
m_pDict = *pDict;
}
BaseStream::~BaseStream()
{
m_pDict.Free();
}
//---------------------------------------------------------------------------------------------------------------
// FilterStream
//---------------------------------------------------------------------------------------------------------------
FilterStream::FilterStream(Stream *pStream)
{
m_pStream = pStream;
}
FilterStream::~FilterStream()
{
}
void FilterStream::Close()
{
m_pStream->Close();
}
void FilterStream::SetPos(unsigned int unPos, int nDirection)
{
// TO DO: Error "Internal: called SetPos() on FilterStream"
}
//---------------------------------------------------------------------------------------------------------------
// ImageStream
//---------------------------------------------------------------------------------------------------------------
ImageStream::ImageStream(Stream *pStream, int nWidth, int nComponents, int nBitsPerComponent)
{
int nLineSize = 0;
m_pStream = pStream;
m_nWidth = nWidth;
m_nComponentsPerPixel = nComponents;
m_nBitsPerComponent = nBitsPerComponent;
m_nComponentsPerLine = m_nWidth * m_nComponentsPerPixel;
if ( 1 == m_nBitsPerComponent )
{
nLineSize = (m_nComponentsPerLine + 7) & ~7;
}
else
{
nLineSize = m_nComponentsPerLine;
}
m_pLineBuffer = (unsigned char *)MemUtilsMallocArray( nLineSize, sizeof(unsigned char));
m_nLinePos = m_nComponentsPerLine;
}
ImageStream::~ImageStream()
{
MemUtilsFree(m_pLineBuffer);
}
void ImageStream::Reset()
{
m_pStream->Reset();
}
BOOL ImageStream::GetPixel(unsigned char *pPixel)
{
if ( m_nLinePos >= m_nComponentsPerLine )
{
GetNextLine();
m_nLinePos = 0;
}
for (int nIndex = 0; nIndex < m_nComponentsPerPixel; ++nIndex )
{
pPixel[nIndex] = m_pLineBuffer[m_nLinePos++];
}
return TRUE;
}
unsigned char *ImageStream::GetNextLine()
{
if ( m_nBitsPerComponent == 1 )
{
for ( int nIndex = 0; nIndex < m_nComponentsPerLine; nIndex += 8)
{
int nChar = m_pStream->GetChar();
m_pLineBuffer[nIndex + 0] = (unsigned char)((nChar >> 7) & 1);
m_pLineBuffer[nIndex + 1] = (unsigned char)((nChar >> 6) & 1);
m_pLineBuffer[nIndex + 2] = (unsigned char)((nChar >> 5) & 1);
m_pLineBuffer[nIndex + 3] = (unsigned char)((nChar >> 4) & 1);
m_pLineBuffer[nIndex + 4] = (unsigned char)((nChar >> 3) & 1);
m_pLineBuffer[nIndex + 5] = (unsigned char)((nChar >> 2) & 1);
m_pLineBuffer[nIndex + 6] = (unsigned char)((nChar >> 1) & 1);
m_pLineBuffer[nIndex + 7] = (unsigned char)(nChar & 1);
}
}
else if ( m_nBitsPerComponent == 8 )
{
for ( int nIndex = 0; nIndex < m_nComponentsPerLine; ++nIndex )
{
m_pLineBuffer[nIndex] = m_pStream->GetChar();
}
}
else
{
unsigned long nBitMask = (1 << m_nBitsPerComponent) - 1;
unsigned long nTemp = 0;
int nBits = 0;
for ( int nIndex = 0; nIndex < m_nComponentsPerLine; ++nIndex )
{
if ( nBits < m_nBitsPerComponent )
{
nTemp = (nTemp << 8) | (m_pStream->GetChar() & 0xff);
nBits += 8;
}
m_pLineBuffer[nIndex] = (unsigned char)( ( nTemp >> (nBits - m_nBitsPerComponent) ) & nBitMask );
nBits -= m_nBitsPerComponent;
}
}
return m_pLineBuffer;
}
void ImageStream::SkipLine()
{
int nCount = ( m_nComponentsPerLine * m_nBitsPerComponent + 7 ) >> 3;
for ( int nIndex = 0; nIndex < nCount; ++nIndex )
{
m_pStream->GetChar();
}
}
//---------------------------------------------------------------------------------------------------------------
// StreamPredictor
//---------------------------------------------------------------------------------------------------------------
StreamPredictor::StreamPredictor(Stream *pStream, int nPredictor, int nWidth, int nComponents, int nBitsPerComponent)
{
m_pStream = pStream;
m_nPredictor = nPredictor;
m_nWidth = nWidth;
m_nComponentsPerPixel = nComponents;
m_nBitsPerComponent = nBitsPerComponent;
m_pLineBuffer = NULL;
m_bSuccess = FALSE;
m_nComponentsPerLine = m_nWidth * m_nComponentsPerPixel;
// Patch1
m_nBytesPerPixel = ( m_nComponentsPerPixel * m_nBitsPerComponent + 7) >> 3;
m_nBytesPerLine = (( m_nComponentsPerLine * m_nBitsPerComponent + 7 ) >> 3) + m_nBytesPerPixel;
if ( m_nWidth <= 0 || m_nComponentsPerPixel <= 0 || m_nBitsPerComponent <= 0 || m_nComponentsPerPixel >= GrColorMaxComps || m_nBitsPerComponent > 16 || m_nWidth >= INT_MAX / m_nComponentsPerPixel || m_nComponentsPerLine >= ( INT_MAX - 7 ) / m_nBitsPerComponent )
return; // m_bSuccess = FALSE;
// End Patch1
if ( m_nBytesPerLine <= 0 )
return; // m_bSuccess = FALSE;
m_pLineBuffer = (unsigned char *)MemUtilsMalloc(m_nBytesPerLine);
memset(m_pLineBuffer, 0, m_nBytesPerLine);
m_nLinePos = m_nBytesPerLine;
m_bSuccess = TRUE;
}
StreamPredictor::~StreamPredictor()
{
MemUtilsFree(m_pLineBuffer);
}
int StreamPredictor::LookChar()
{
if ( m_nLinePos >= m_nBytesPerLine )
{
if ( !GetNextLine() )
{
return EOF;
}
}
return m_pLineBuffer[m_nLinePos];
}
int StreamPredictor::GetChar()
{
if ( m_nLinePos >= m_nBytesPerLine )
{
if ( !GetNextLine() )
{
return EOF;
}
}
return m_pLineBuffer[m_nLinePos++];
}
BOOL StreamPredictor::GetNextLine()
{
int nCurPredictor = 1;
int nLeft, nTop, nTopLeft, nCur, nLeftDiff, nTopDiff, nTopLeftDiff;
int nChar;
// PNG prediction
if ( m_nPredictor >= 10 )
{
if ( ( nCurPredictor = m_pStream->GetRawChar() ) == EOF )
{
return FALSE;
}
nCurPredictor += 10;
}
else
{
nCurPredictor = m_nPredictor;
}
// ×èòàåì ïî ñòðîêå, ïðèìåíÿÿ PNG (byte) ôèëüòðàöèþ(prediction)
unsigned char arrTopLeftBuf[ GrColorMaxComps * 2 + 1 ];
memset( arrTopLeftBuf, 0, m_nBytesPerPixel + 1);
for (int nIndex = m_nBytesPerPixel; nIndex < m_nBytesPerLine; ++nIndex)
{
for (int nJ = m_nBytesPerPixel; nJ > 0; --nJ)
{
arrTopLeftBuf[nJ] = arrTopLeftBuf[nJ - 1];
}
arrTopLeftBuf[0] = m_pLineBuffer[nIndex];
if ( ( nChar = m_pStream->GetRawChar() ) == EOF )
{
if ( nIndex > m_nBytesPerPixel )
{
// this ought to return false, but some (broken) PDF files
// contain truncated image data, and Adobe apparently reads the
// last partial line
break;
}
return FALSE;
}
switch ( nCurPredictor )
{
case 11: // PNG Sub
m_pLineBuffer[nIndex] = m_pLineBuffer[nIndex - m_nBytesPerPixel] + (unsigned char)nChar;
break;
case 12: // PNG Up
m_pLineBuffer[nIndex] = m_pLineBuffer[nIndex] + (unsigned char)nChar;
break;
case 13: // PNG Average
m_pLineBuffer[nIndex] = ((m_pLineBuffer[nIndex - m_nBytesPerPixel] + m_pLineBuffer[nIndex]) >> 1) + (unsigned char)nChar;
break;
case 14: // PNG Paeth
nLeft = m_pLineBuffer[nIndex - m_nBytesPerPixel];
nTop = m_pLineBuffer[nIndex];
nTopLeft = arrTopLeftBuf[m_nBytesPerPixel];
nCur = nLeft + nTop - nTopLeft;
if ( ( nLeftDiff = nCur - nLeft ) < 0 )
nLeftDiff = -nLeftDiff;
if ( ( nTopDiff = nCur - nTop ) < 0 )
nTopDiff = -nTopDiff;
if ( ( nTopLeftDiff = nCur - nTopLeft ) < 0 )
nTopLeftDiff = -nTopLeftDiff;
if ( nLeftDiff <= nTopDiff && nLeftDiff <= nTopLeftDiff )
m_pLineBuffer[nIndex] = nLeft + (unsigned char)nChar;
else if ( nTopDiff <= nTopLeftDiff )
m_pLineBuffer[nIndex] = nTop + (unsigned char)nChar;
else
m_pLineBuffer[nIndex] = nTopLeft + (unsigned char)nChar;
break;
case 10: // PNG none
default: // No predictor èëè TIFF predictor
m_pLineBuffer[nIndex] = (unsigned char)nChar;
break;
}
}
// Ïðèìåíÿåì TIFF ôèëüòðàöèþ (predictor)
unsigned long nInTemp, nOutTemp;
if ( m_nPredictor == 2 )
{
if ( m_nBitsPerComponent == 1 )
{
nInTemp = m_pLineBuffer[m_nBytesPerPixel - 1];
for (int nIndex = m_nBytesPerPixel; nIndex < m_nBytesPerLine; nIndex += 8)
{
// 1-bit add is just xor
nInTemp = ( nInTemp << 8) | m_pLineBuffer[nIndex];
m_pLineBuffer[nIndex] ^= nInTemp >> m_nComponentsPerPixel;
}
}
else if ( m_nBitsPerComponent == 8 )
{
for (int nIndex = m_nBytesPerPixel; nIndex < m_nBytesPerLine; ++nIndex)
{
m_pLineBuffer[nIndex] += m_pLineBuffer[nIndex - m_nComponentsPerPixel];
}
}
else
{
memset( arrTopLeftBuf, 0, m_nComponentsPerPixel + 1);
int nBitMask = (1 << m_nBitsPerComponent) - 1;
nInTemp = 0, nOutTemp = 0;
int nInBits = 0, nOutBits = 0;
int nJ = m_nBytesPerPixel, nK = m_nBytesPerPixel;
for (int nIndex = 0; nIndex < m_nWidth; ++nIndex)
{
for (int nKK = 0; nKK < m_nComponentsPerPixel; ++nKK)
{
if ( nInBits < m_nBitsPerComponent )
{
nInTemp = ( nInTemp << 8) | (m_pLineBuffer[nJ++] & 0xff);
nInBits += 8;
}
arrTopLeftBuf[nKK] = (unsigned char)(( arrTopLeftBuf[nKK] + ( nInTemp >> ( nInBits - m_nBitsPerComponent))) & nBitMask);
nInBits -= m_nBitsPerComponent;
nOutTemp = ( nOutTemp << m_nBitsPerComponent) | arrTopLeftBuf[nKK];
nOutBits += m_nBitsPerComponent;
if ( nOutBits >= 8 )
{
m_pLineBuffer[nK++] = (unsigned char)( nOutTemp >> (nOutBits - 8));
nOutBits -= 8;
}
}
}
if ( nOutBits > 0 )
{
m_pLineBuffer[nK++] = (unsigned char)(( nOutTemp << (8 - nOutBits)) + (nInTemp & ((1 << (8 - nOutBits)) - 1)));
}
}
}
m_nLinePos = m_nBytesPerPixel;
return TRUE;
}
//---------------------------------------------------------------------------------------------------------------
// FileStream
//---------------------------------------------------------------------------------------------------------------
FileStream::FileStream(FILE *pFile, unsigned int unStart, BOOL bLimited, unsigned int nLength, Object *pDict):
BaseStream(pDict)
{
m_pFile = pFile;
m_unStart = unStart;
m_bLimited = bLimited;
m_unLength = nLength;
m_pBufferPointer = m_pBufferEnd = m_sBuffer;
m_unBufferPos = m_unStart;
m_nSavePos = 0;
m_bSaved = FALSE;
}
FileStream::~FileStream()
{
Close();
}
Stream *FileStream::MakeSubStream(unsigned int unStart, BOOL bLimited, unsigned int unLength, Object *pDict)
{
return new FileStream( m_pFile, unStart, bLimited, unLength, pDict);
}
void FileStream::Reset()
{
m_nSavePos = (unsigned int)ftell(m_pFile);
fseek( m_pFile, m_unStart, SEEK_SET);
m_bSaved = TRUE;
m_pBufferPointer = m_pBufferEnd = m_sBuffer;
m_unBufferPos = m_unStart;
}
void FileStream::Close()
{
if ( m_bSaved )
{
fseek( m_pFile, m_nSavePos, SEEK_SET);
m_bSaved = FALSE;
}
}
BOOL FileStream::FillBuffer()
{
int nCurBufLen = 0;
m_unBufferPos += m_pBufferEnd - m_sBuffer;
m_pBufferPointer = m_pBufferEnd = m_sBuffer;
if ( m_bLimited && m_unBufferPos >= m_unStart + m_unLength )
return FALSE;
if ( m_bLimited && m_unBufferPos + FileStreamBufferSize > m_unStart + m_unLength )
nCurBufLen = m_unStart + m_unLength - m_unBufferPos;
else
nCurBufLen = FileStreamBufferSize;
nCurBufLen = fread( m_sBuffer, 1, nCurBufLen, m_pFile);
m_pBufferEnd = m_sBuffer + nCurBufLen;
if ( m_pBufferPointer >= m_pBufferEnd )
return FALSE;
return TRUE;
}
void FileStream::SetPos(unsigned int unPos, int nDirection)
{
if ( nDirection >= 0 )
{
fseek( m_pFile, unPos, SEEK_SET);
m_unBufferPos = unPos;
}
else
{
fseek( m_pFile, 0, SEEK_END);
unsigned int unSize = (unsigned int)ftell( m_pFile );
if ( unPos > unSize )
unPos = (unsigned int)unSize;
fseek( m_pFile, -(int)unPos, SEEK_END);
m_unBufferPos = (unsigned int)ftell( m_pFile );
}
m_pBufferPointer = m_pBufferEnd = m_sBuffer;
}
void FileStream::SetStartPos(int nDelta)
{
m_unStart += nDelta;
m_pBufferPointer = m_pBufferEnd = m_sBuffer;
m_unBufferPos = m_unStart;
}
//---------------------------------------------------------------------------------------------------------------
// MemoryStream
//---------------------------------------------------------------------------------------------------------------
MemoryStream::MemoryStream(char *sBuffer, unsigned int unStart, unsigned int unLength, Object *pDict):
BaseStream(pDict)
{
m_sBuffer = sBuffer;
m_unStart = unStart;
m_unLength = unLength;
m_pBufferEnd = m_sBuffer + m_unStart + m_unLength;
m_pBufferPointer = m_sBuffer + m_unStart;
m_bNeedFree = FALSE;
}
MemoryStream::~MemoryStream()
{
if ( m_bNeedFree )
MemUtilsFree(m_sBuffer);
}
Stream *MemoryStream::MakeSubStream(unsigned int unStart, BOOL bLimited, unsigned int unLength, Object *pDict)
{
unsigned int unNewLength = 0;
if ( !bLimited || unStart + unLength > m_unStart + m_unLength )
{
unNewLength = m_unStart + m_unLength - unStart;
}
else
{
unNewLength = unLength;
}
MemoryStream *pSubStream = new MemoryStream( m_sBuffer, unStart, unNewLength, pDict);
return pSubStream;
}
void MemoryStream::Reset()
{
m_pBufferPointer = m_sBuffer + m_unStart;
}
void MemoryStream::Close()
{
}
void MemoryStream::SetPos(unsigned int unPos, int nDirection)
{
unsigned int unCurPos = 0;
if ( nDirection >= 0 )
{
unCurPos = unPos;
}
else
{
unCurPos = m_unStart + m_unLength - unPos;
}
if ( unCurPos < m_unStart )
{
unCurPos = m_unStart;
}
else if ( unCurPos > m_unStart + m_unLength )
{
unCurPos = m_unStart + m_unLength;
}
m_pBufferPointer = m_sBuffer + unCurPos;
}
void MemoryStream::SetStartPos(int nDelta)
{
m_unStart += nDelta;
m_unLength -= nDelta;
m_pBufferPointer = m_sBuffer + m_unStart;
}
//---------------------------------------------------------------------------------------------------------------
// EmbedStream
//---------------------------------------------------------------------------------------------------------------
EmbedStream::EmbedStream(Stream *pStream, Object *pDict, BOOL bLimited, unsigned int unLength):
BaseStream(pDict)
{
m_pStream = pStream;
m_bLimited = bLimited;
m_unLength = unLength;
}
EmbedStream::~EmbedStream()
{
}
Stream *EmbedStream::MakeSubStream(unsigned int unStart, BOOL bLimited, unsigned int unLength, Object *pDict)
{
// TO DO: Error "Internal: called MakeSubStream() on EmbedStream"
return NULL;
}
int EmbedStream::GetChar()
{
if (m_bLimited && !m_unLength)
{
return EOF;
}
--m_unLength;
return m_pStream->GetChar();
}
int EmbedStream::LookChar()
{
if ( m_bLimited && !m_unLength )
{
return EOF;
}
return m_pStream->LookChar();
}
void EmbedStream::SetPos(unsigned int unPos, int nDirection)
{
// TO DO: Error "Internal: called SetPos() on EmbedStream"
}
unsigned int EmbedStream::GetStartPos()
{
// TO DO: Error "Internal: called GetStartPos() on EmbedStream"
return 0;
}
void EmbedStream::SetStartPos(int nDelta)
{
// TO DO: Error "Internal: called SetStartPos() on EmbedStream"
}
//---------------------------------------------------------------------------------------------------------------
// ASCIIHexStream
//---------------------------------------------------------------------------------------------------------------
ASCIIHexStream::ASCIIHexStream(Stream *pStream):
FilterStream(pStream)
{
m_nBuffer = EOF;
m_bEOF = FALSE;
}
ASCIIHexStream::~ASCIIHexStream()
{
delete m_pStream;
}
void ASCIIHexStream::Reset()
{
m_pStream->Reset();
m_nBuffer = EOF;
m_bEOF = FALSE;
}
int ASCIIHexStream::LookChar()
{
int nFirstChar = 0, nSecondChar = 0, nHexValue = 0;
if ( m_nBuffer != EOF )
return m_nBuffer;
if ( m_bEOF )
{
m_nBuffer = EOF;
return EOF;
}
do {
nFirstChar = m_pStream->GetChar();
} while ( isspace(nFirstChar) );
if ( nFirstChar == '>' )
{
m_bEOF = TRUE;
m_nBuffer = EOF;
return m_nBuffer;
}
do {
nSecondChar = m_pStream->GetChar();
} while ( isspace(nSecondChar) );
if ( nSecondChar == '>' )
{
m_bEOF = TRUE;
nSecondChar = '0';
}
if ( nFirstChar >= '0' && nFirstChar <= '9' )
{
nHexValue = ( nFirstChar - '0' ) << 4;
}
else if ( nFirstChar >= 'A' && nFirstChar <= 'F' )
{
nHexValue = ( nFirstChar - 'A' + 10) << 4;
}
else if ( nFirstChar >= 'a' && nFirstChar <= 'f' )
{
nHexValue = ( nFirstChar - 'a' + 10) << 4;
}
else if ( nFirstChar == EOF )
{
m_bEOF = TRUE;
nHexValue = 0;
}
else
{
// TO DO: Error "Illegal character in ASCIIHex stream"
nHexValue = 0;
}
if ( nSecondChar >= '0' && nSecondChar <= '9' )
{
nHexValue += nSecondChar - '0';
}
else if ( nSecondChar >= 'A' && nSecondChar <= 'F' )
{
nHexValue += nSecondChar - 'A' + 10;
}
else if ( nSecondChar >= 'a' && nSecondChar <= 'f' )
{
nHexValue += nSecondChar - 'a' + 10;
}
else if ( nSecondChar == EOF )
{
m_bEOF = TRUE;
nHexValue = 0;
}
else
{
// TO DO: Error "Illegal character in ASCIIHex stream"
}
m_nBuffer = nHexValue & 0xff;
return m_nBuffer;
}
StringExt *ASCIIHexStream::GetPSFilter(int nPSLevel, char *sIndent)
{
StringExt *seResult;
if ( nPSLevel < 2 )
{
return NULL;
}
if (!( seResult = m_pStream->GetPSFilter( nPSLevel, sIndent) ) )
{
return NULL;
}
seResult->Append(sIndent)->Append("/ASCIIHexDecode filter\n");
return seResult;
}
BOOL ASCIIHexStream::IsBinary(BOOL bLast)
{
return m_pStream->IsBinary(FALSE);
}
//---------------------------------------------------------------------------------------------------------------
// ASCII85Stream
//---------------------------------------------------------------------------------------------------------------
ASCII85Stream::ASCII85Stream(Stream *pStream):
FilterStream(pStream)
{
m_nIndex = m_nCount = 0;
m_bEOF = FALSE;
}
ASCII85Stream::~ASCII85Stream()
{
delete m_pStream;
}
void ASCII85Stream::Reset()
{
m_pStream->Reset();
m_nIndex = m_nCount = 0;
m_bEOF = FALSE;
}
int ASCII85Stream::LookChar()
{
int nK = 0;
if ( m_nIndex >= m_nCount )
{
if ( m_bEOF )
return EOF;
m_nIndex = 0;
do {
m_arrC[0] = m_pStream->GetChar();
} while (Lexer::IsSpace(m_arrC[0]));
if (m_arrC[0] == '~' || m_arrC[0] == EOF)
{
m_bEOF = TRUE;
m_nCount = 0;
return EOF;
}
else if (m_arrC[0] == 'z')
{
m_arrB[0] = m_arrB[1] = m_arrB[2] = m_arrB[3] = 0;
m_nCount = 4;
}
else
{
for ( nK = 1; nK < 5; ++ nK )
{
do {
m_arrC[nK] = m_pStream->GetChar();
} while (Lexer::IsSpace(m_arrC[nK]));
if ( m_arrC[nK] == '~' || m_arrC[nK] == EOF )
break;
}
m_nCount = nK - 1;
if ( nK < 5 && ( m_arrC[nK] == '~' || m_arrC[nK] == EOF ) )
{
for (++nK; nK < 5; ++nK)
m_arrC[nK] = 0x21 + 84;
m_bEOF = TRUE;
}
unsigned long unT = 0;
for ( nK = 0; nK < 5; ++nK )
unT = unT * 85 + (m_arrC[nK] - 0x21);
for ( nK = 3; nK >= 0; --nK )
{
m_arrB[nK] = (int)(unT & 0xff);
unT >>= 8;
}
}
}
return m_arrB[m_nIndex];
}
StringExt *ASCII85Stream::GetPSFilter(int nPSLevel, char *sIndent)
{
StringExt *seResult;
if ( nPSLevel < 2 )
{
return NULL;
}
if ( !(seResult = m_pStream->GetPSFilter( nPSLevel, sIndent ) ) )
{
return NULL;
}
seResult->Append(sIndent)->Append("/ASCII85Decode filter\n");
return seResult;
}
BOOL ASCII85Stream::IsBinary(BOOL bLast)
{
return m_pStream->IsBinary(FALSE);
}
//---------------------------------------------------------------------------------------------------------------
// LZWStream
//---------------------------------------------------------------------------------------------------------------
LZWStream::LZWStream(Stream *pStream, int nPredictor, int nColumns, int nColors, int nBitsPerPixel, int nEarlyChange):
FilterStream(pStream)
{
if ( 1 != nPredictor )
{
m_pPredictor = new StreamPredictor(this, nPredictor, nColumns, nColors, nBitsPerPixel);
if ( !m_pPredictor->CheckValidate() )
{
delete m_pPredictor;
m_pPredictor = NULL;
}
}
else
{
m_pPredictor = NULL;
}
m_nEarlyChange = nEarlyChange;
m_bEOF = FALSE;
m_nInputBits = 0;
ClearTable();
}
LZWStream::~LZWStream()
{
if (m_pPredictor)
{
delete m_pPredictor;
}
delete m_pStream;
}
int LZWStream::GetChar()
{
if ( m_pPredictor )
{
return m_pPredictor->GetChar();
}
if ( m_bEOF )
{
return EOF;
}
if ( m_nCurPos >= m_nCurLength )
{
if ( !ProcessNextCode() )
{
return EOF;
}
}
return m_arrCurBuffer[m_nCurPos++];
}
int LZWStream::LookChar()
{
if ( m_pPredictor )
{
return m_pPredictor->LookChar();
}
if ( m_bEOF )
{
return EOF;
}
if ( m_nCurPos >= m_nCurLength )
{
if ( !ProcessNextCode() )
{
return EOF;
}
}
return m_arrCurBuffer[m_nCurPos];
}
int LZWStream::GetRawChar()
{
// Îòëè÷èå îò GetChar â òîì, ÷òî òóò ìû íåèñïîëüçóåì ôèëüòð, óêàçàííûé â m_pPredictor
if ( m_bEOF )
{
return EOF;
}
if ( m_nCurPos >= m_nCurLength )
{
if ( !ProcessNextCode() )
{
return EOF;
}
}
return m_arrCurBuffer[m_nCurPos++];
}
void LZWStream::Reset()
{
m_pStream->Reset();
m_bEOF = FALSE;
m_nInputBits = 0;
ClearTable();
}
BOOL LZWStream::ProcessNextCode()
{
if ( m_bEOF )
{
return FALSE;
}
// Ïðîâåðÿåì êîíåö êîäà(eod) è î÷èùàåì òàáëèöó êîäîâ
start:
int nCode = GetCode();
if ( nCode == EOF || nCode == 257 )
{
m_bEOF = TRUE;
return FALSE;
}
if ( nCode == 256 )
{
ClearTable();
goto start;
}
if ( m_nNextCode >= 4097 )
{
// TO DO: Error "Bad LZW stream - expected clear-table code"
ClearTable();
}
// Process the next code
int nNextLength = m_nCurLength + 1;
if ( nCode < 256 )
{
m_arrCurBuffer[0] = nCode;
m_nCurLength = 1;
}
else if ( nCode < m_nNextCode )
{
m_nCurLength = m_pTable[nCode].nLength;
int nI = 0, nJ = 0;
for (nI = m_nCurLength - 1, nJ = nCode; nI > 0; --nI)
{
m_arrCurBuffer[nI] = m_pTable[nJ].unTail;
nJ = m_pTable[nJ].nHead;
}
m_arrCurBuffer[0] = nJ;
}
else if ( nCode == m_nNextCode )
{
m_arrCurBuffer[m_nCurLength] = m_nNewChar;
++m_nCurLength;
}
else
{
// TO DO : Error "Bad LZW stream - unexpected code"
m_bEOF = TRUE;
return FALSE;
}
m_nNewChar = m_arrCurBuffer[0];
if ( m_bFirst )
{
m_bFirst = FALSE;
}
else
{
m_pTable[m_nNextCode].nLength = nNextLength;
m_pTable[m_nNextCode].nHead = m_nPrevCode;
m_pTable[m_nNextCode].unTail = m_nNewChar;
++m_nNextCode;
if ( m_nNextCode + m_nEarlyChange == 512 )
m_nNextBits = 10;
else if ( m_nNextCode + m_nEarlyChange == 1024 )
m_nNextBits = 11;
else if ( m_nNextCode + m_nEarlyChange == 2048 )
m_nNextBits = 12;
}
m_nPrevCode = nCode;
m_nCurPos = 0;
return TRUE;
}
void LZWStream::ClearTable()
{
m_nNextCode = 258;
m_nNextBits = 9;
m_nCurPos = m_nCurLength = 0;
m_bFirst = TRUE;
}
int LZWStream::GetCode()
{
int nChar = 0;
while ( m_nInputBits < m_nNextBits )
{
if ( ( nChar = m_pStream->GetChar() ) == EOF )
return EOF;
m_nInputBuffer = (m_nInputBuffer << 8) | (nChar & 0xff);
m_nInputBits += 8;
}
int nCode = (m_nInputBuffer >> (m_nInputBits - m_nNextBits)) & ((1 << m_nNextBits) - 1);
m_nInputBits -= m_nNextBits;
return nCode;
}
StringExt *LZWStream::GetPSFilter(int nPSLevel, char *sIndent)
{
StringExt *seResult;
if ( nPSLevel < 2 || m_pPredictor)
{
return NULL;
}
if ( !( seResult = m_pStream->GetPSFilter( nPSLevel, sIndent) ) )
{
return NULL;
}
seResult->Append(sIndent)->Append("<< ");
if ( !m_nEarlyChange )
{
seResult->Append("/EarlyChange 0 ");
}
seResult->Append(">> /LZWDecode filter\n");
return seResult;
}
BOOL LZWStream::IsBinary(BOOL bLast)
{
return m_pStream->IsBinary(TRUE);
}
//---------------------------------------------------------------------------------------------------------------
// RunLengthStream
//---------------------------------------------------------------------------------------------------------------
RunLengthStream::RunLengthStream(Stream *pStream):
FilterStream(pStream)
{
m_pBufferPointer = m_pEndOfBuffer = m_sBuffer;
m_bEOF = FALSE;
}
RunLengthStream::~RunLengthStream()
{
delete m_pStream;
}
void RunLengthStream::Reset()
{
m_pStream->Reset();
m_pBufferPointer = m_pEndOfBuffer = m_sBuffer;
m_bEOF = FALSE;
}
StringExt *RunLengthStream::GetPSFilter(int nPSLevel, char *sIndent)
{
StringExt *seResult;
if ( nPSLevel < 2 )
{
return NULL;
}
if ( !( seResult = m_pStream->GetPSFilter( nPSLevel, sIndent ) ) )
{
return NULL;
}
seResult->Append(sIndent)->Append("/RunLengthDecode filter\n");
return seResult;
}
BOOL RunLengthStream::IsBinary(BOOL bLast)
{
return m_pStream->IsBinary(TRUE);
}
BOOL RunLengthStream::FillBuffer()
{
int nLen = 0;
if ( m_bEOF )
return FALSE;
int nChar = m_pStream->GetChar();
if ( nChar == 0x80 || nChar == EOF )
{
m_bEOF = TRUE;
return FALSE;
}
if ( nChar < 0x80 )
{
nLen = nChar + 1;
for ( int nIndex = 0; nIndex < nLen; ++nIndex )
m_sBuffer[nIndex] = (char)m_pStream->GetChar();
}
else
{
nLen = 0x101 - nChar;
nChar = m_pStream->GetChar();
for ( int nIndex = 0; nIndex < nLen; ++nIndex )
m_sBuffer[nIndex] = (char)nChar;
}
m_pBufferPointer = m_sBuffer;
m_pEndOfBuffer = m_sBuffer + nLen;
return TRUE;
}
//---------------------------------------------------------------------------------------------------------------
// CCITTFaxStream
//---------------------------------------------------------------------------------------------------------------
CCITTFaxStream::CCITTFaxStream(Stream *pStream, int nK, BOOL bEndOfLine, BOOL bByteAlign, int nColumns, int nRows, BOOL bEndOfBlock, BOOL bBlackIs1):
FilterStream(pStream)
{
m_nK = nK;
m_bEndOfLine = bEndOfLine;
m_bByteAlign = bByteAlign;
m_nColumns = nColumns;
if ( m_nColumns < 1 )
m_nColumns = 1;
if ( m_nColumns + 4 <= 0 )
m_nColumns = INT_MAX - 4;
m_nRows = nRows;
m_bEndOfBlock = bEndOfBlock;
m_bBlackIs1 = bBlackIs1;
m_pRefLine = (short *)MemUtilsMallocArray( m_nColumns + 3, sizeof(short));
m_pCodingLine = (short *)MemUtilsMallocArray( m_nColumns + 2, sizeof(short));
m_bEOF = FALSE;
m_mCurRow = 0;
m_bNextLine2D = (m_nK < 0);
m_nInputBits = 0;
m_pCodingLine[0] = 0;
m_pCodingLine[1] = m_pRefLine[2] = m_nColumns;
m_nCurPosCL = 1;
m_nCharBuffer = EOF;
}
CCITTFaxStream::~CCITTFaxStream()
{
delete m_pStream;
MemUtilsFree( m_pRefLine );
MemUtilsFree( m_pCodingLine );
}
void CCITTFaxStream::Reset()
{
short nCode1;
m_pStream->Reset();
m_bEOF = FALSE;
m_mCurRow = 0;
m_bNextLine2D = (m_nK < 0);
m_nInputBits = 0;
m_pCodingLine[0] = 0;
m_pCodingLine[1] = m_nColumns;
m_nCurPosCL = 1;
m_nCharBuffer = EOF;
// Ïðîïóñêàì íà÷àëüíûå íóëåâûå áèòû è ñèìâîëû îêîí÷àíèÿ ñòðîêè, è ñ÷èòûâàåì òýã 2D êîäèðîâêè
while ( ( nCode1 = LookBits(12) ) == 0 )
{
SkipBits(1);
}
if ( nCode1 == 0x001 )
{
SkipBits(12);
}
if ( m_nK > 0 )
{
m_bNextLine2D = !LookBits(1);
SkipBits(1);
}
}
int CCITTFaxStream::LookChar()
{
short nCode1, nCode2, nCode3;
int nIndex = 0;
if ( m_bEOF && m_pCodingLine[m_nCurPosCL] >= m_nColumns )
{
return EOF;
}
// Ñ÷èòûâàåì ñòðîêó
BOOL bError = FALSE;
if ( m_pCodingLine[m_nCurPosCL] >= m_nColumns )
{
// 2D êîäèðîâêà
if ( m_bNextLine2D )
{
// Íà÷àëüíîå ñîñòîÿíèå:
// nNewCLPos = Òåêóùàÿ ïîçèöèÿ â êîäèðîâàííîé ñòðîêå (0 <= nNewCLPos <= m_nColumns)
// m_pCodingLine[m_nCurPosCL] = Ïîñëåäíåå èçìåíåíèå â êîäèðîâàííîé ñòðîêå
// (black-to-white, åñëè m_nCurPosCL ÷åòíî,
// white-to-black, åñëè m_nCurPosCL íå÷åòíî)
// m_pRefLine[m_nCurPosRL] = Ñëåäóþùåå èçìåíåíèå â ññûëî÷íîé ñòðîêå, ïðîòèâîïîëîæíîãî
// öâåòà, öâåòó m_nCurPosCL
// Â ëþáîé ìîìåíò äîëæíî áûòü âåðíî:
// 0 <= m_pCodingLine[m_nCurPosCL] <= nNewCLPos <= m_pRefLine[m_nCurPosRL] <= m_pRefLine[m_nCurPosRL + 1] <= m_nColumns
// 0 <= m_nCurPosCL <= m_nColumns + 1
// m_pRefLine[0] = 0
// m_pRefLine[n] = m_pRefLine[n + 1] = columns -- äëÿ íåêîòîðîãî 1 <= n <= m_nColumns + 1
// Óñëîâèå îêîí÷àíèÿ àëãîðèòìà:
// 0 = m_pCodingLine[0] <= m_pCodingLine[1] < m_pCodingLine[2] < ... < m_pCodingLine[n-1] < m_pCodingLine[n] = m_nColumns,
// ãäå <= n <= m_nColumns + 1
int nNewCLPos = 0;
for (nIndex = 0; m_pCodingLine[nIndex] < m_nColumns; ++nIndex)
{
m_pRefLine[nIndex] = m_pCodingLine[nIndex];
}
m_pRefLine[nIndex] = m_pRefLine[nIndex + 1] = m_nColumns;
m_nCurPosRL = 1;
nNewCLPos = m_pCodingLine[ m_nCurPosCL = 0 ] = 0;
do {
nCode1 = Get2DCode();
switch (nCode1)
{
case Pass_2D:
if ( m_pRefLine[m_nCurPosRL] < m_nColumns )
{
nNewCLPos = m_pRefLine[m_nCurPosRL + 1];
m_nCurPosRL += 2;
}
break;
case Horiz_2D:
if ( ( m_nCurPosCL & 1 ) == 0 )
{
nCode1 = nCode2 = 0;
do {
nCode1 += nCode3 = GetWhiteCode();
} while (nCode3 >= 64);
do {
nCode2 += nCode3 = GetBlackCode();
} while (nCode3 >= 64);
}
else
{
nCode1 = nCode2 = 0;
do {
nCode1 += nCode3 = GetBlackCode();
} while (nCode3 >= 64);
do {
nCode2 += nCode3 = GetWhiteCode();
} while (nCode3 >= 64);
}
if ( nCode1 > 0 || nCode2 > 0 )
{
if ( nNewCLPos + nCode1 <= m_nColumns)
{
m_pCodingLine[m_nCurPosCL + 1] = nNewCLPos + nCode1;
}
else
{
m_pCodingLine[m_nCurPosCL + 1] = m_nColumns;
}
++m_nCurPosCL;
if ( m_pCodingLine[m_nCurPosCL] + nCode2 <= m_nColumns)
{
m_pCodingLine[m_nCurPosCL + 1] = m_pCodingLine[m_nCurPosCL] + nCode2;
}
else
{
m_pCodingLine[m_nCurPosCL + 1] = m_nColumns;
}
++m_nCurPosCL;
nNewCLPos = m_pCodingLine[m_nCurPosCL];
while ( m_pRefLine[m_nCurPosRL] <= nNewCLPos && m_pRefLine[m_nCurPosRL] < m_nColumns)
{
m_nCurPosRL += 2;
}
}
break;
case Vert0_2D:
if ( m_pRefLine[m_nCurPosRL] < m_nColumns)
{
nNewCLPos = m_pCodingLine[++m_nCurPosCL] = m_pRefLine[m_nCurPosRL];
++m_nCurPosRL;
while ( m_pRefLine[m_nCurPosRL] <= nNewCLPos && m_pRefLine[m_nCurPosRL] < m_nColumns)
{
m_nCurPosRL += 2;
}
}
else
{
nNewCLPos = m_pCodingLine[++m_nCurPosCL] = m_nColumns;
}
break;
case VertR1_2D:
if ( m_pRefLine[m_nCurPosRL] + 1 < m_nColumns)
{
nNewCLPos = m_pCodingLine[++m_nCurPosCL] = m_pRefLine[m_nCurPosRL] + 1;
++m_nCurPosRL;
while ( m_pRefLine[m_nCurPosRL] <= nNewCLPos && m_pRefLine[m_nCurPosRL] < m_nColumns)
{
m_nCurPosRL += 2;
}
}
else
{
nNewCLPos = m_pCodingLine[++m_nCurPosCL] = m_nColumns;
}
break;
case VertL1_2D:
if ( m_pRefLine[m_nCurPosRL] - 1 > nNewCLPos || ( m_nCurPosCL == 0 && m_pRefLine[m_nCurPosRL] == 1 ) )
{
nNewCLPos = m_pCodingLine[++m_nCurPosCL] = m_pRefLine[m_nCurPosRL] - 1;
--m_nCurPosRL;
while ( m_pRefLine[m_nCurPosRL] <= nNewCLPos && m_pRefLine[m_nCurPosRL] < m_nColumns)
{
m_nCurPosRL += 2;
}
}
break;
case VertR2_2D:
if ( m_pRefLine[m_nCurPosRL] + 2 < m_nColumns )
{
nNewCLPos = m_pCodingLine[++m_nCurPosCL] = m_pRefLine[m_nCurPosRL] + 2;
++m_nCurPosRL;
while ( m_pRefLine[m_nCurPosRL] <= nNewCLPos && m_pRefLine[m_nCurPosRL] < m_nColumns)
{
m_nCurPosRL += 2;
}
}
else
{
nNewCLPos = m_pCodingLine[++m_nCurPosCL] = m_nColumns;
}
break;
case VertL2_2D:
if ( m_pRefLine[m_nCurPosRL] - 2 > nNewCLPos || ( m_nCurPosCL == 0 && m_pRefLine[m_nCurPosRL] == 2 ) )
{
nNewCLPos = m_pCodingLine[++m_nCurPosCL] = m_pRefLine[m_nCurPosRL] - 2;
--m_nCurPosRL;
while ( m_pRefLine[m_nCurPosRL] <= nNewCLPos && m_pRefLine[m_nCurPosRL] < m_nColumns )
{
m_nCurPosRL += 2;
}
}
break;
case VertR3_2D:
if ( m_pRefLine[m_nCurPosRL] + 3 < m_nColumns )
{
nNewCLPos = m_pCodingLine[++m_nCurPosCL] = m_pRefLine[m_nCurPosRL] + 3;
++m_nCurPosRL;
while ( m_pRefLine[m_nCurPosRL] <= nNewCLPos && m_pRefLine[m_nCurPosRL] < m_nColumns )
{
m_nCurPosRL += 2;
}
}
else
{
nNewCLPos = m_pCodingLine[++m_nCurPosCL] = m_nColumns;
}
break;
case VertL3_2D:
if ( m_pRefLine[m_nCurPosRL] - 3 > nNewCLPos || ( m_nCurPosCL == 0 && m_pRefLine[m_nCurPosRL] == 3 ) )
{
nNewCLPos = m_pCodingLine[++m_nCurPosCL] = m_pRefLine[m_nCurPosRL] - 3;
--m_nCurPosRL;
while ( m_pRefLine[m_nCurPosRL] <= nNewCLPos && m_pRefLine[m_nCurPosRL] < m_nColumns)
{
m_nCurPosRL += 2;
}
}
break;
case EOF:
m_bEOF = TRUE;
m_pCodingLine[m_nCurPosCL = 0] = m_nColumns;
return EOF;
default:
// TO DO: Error "Bad 2D code in CCITTFax stream"
bError = TRUE;
break;
}
} while ( m_pCodingLine[m_nCurPosCL] < m_nColumns);
}
else // 1-D encoding
{
m_pCodingLine[m_nCurPosCL = 0] = 0;
while (1)
{
nCode1 = 0;
do {
nCode1 += nCode3 = GetWhiteCode();
} while ( nCode3 >= 64 );
m_pCodingLine[m_nCurPosCL + 1] = m_pCodingLine[m_nCurPosCL] + nCode1;
++m_nCurPosCL;
if ( m_pCodingLine[m_nCurPosCL] >= m_nColumns)
{
break;
}
nCode2 = 0;
do {
nCode2 += nCode3 = GetBlackCode();
} while (nCode3 >= 64);
m_pCodingLine[m_nCurPosCL + 1] = m_pCodingLine[m_nCurPosCL] + nCode2;
++m_nCurPosCL;
if ( m_pCodingLine[m_nCurPosCL] >= m_nColumns)
{
break;
}
}
}
if ( m_pCodingLine[m_nCurPosCL] != m_nColumns )
{
// TO DO: Error "CCITTFax row is wrong length "
// Âûñòàâëÿåì êîððåêòíóþ äëèíó
while ( m_pCodingLine[m_nCurPosCL] > m_nColumns )
{
--m_nCurPosCL;
}
m_pCodingLine[++m_nCurPosCL] = m_nColumns;
bError = TRUE;
}
if ( m_bByteAlign )
{
m_nInputBits &= ~7;
}
// Ïðîâåðÿåì ñèìâîë êîíöà ñòðîêè, ïðîïóñêà íóëåâûå áèòû
BOOL bEOL = FALSE;
if ( !m_bEndOfBlock && m_mCurRow == m_nRows - 1 )
{
m_bEOF = TRUE;
}
else
{
nCode1 = LookBits(12);
while ( nCode1 == 0 )
{
SkipBits(1);
nCode1 = LookBits(12);
}
if ( nCode1 == 0x001 )
{
SkipBits(12);
bEOL = TRUE;
}
else if ( nCode1 == EOF )
{
m_bEOF = TRUE;
}
}
// Ñ÷èòûâàåì òýã 2D êîäèðîâêè
if ( !m_bEOF && m_nK > 0 )
{
m_bNextLine2D = !LookBits(1);
SkipBits(1);
}
// Ïðîâåðÿåì ñèìâîë êîíöà áëîêà(end-of-block marker)
if ( m_bEndOfBlock && bEOL )
{
nCode1 = LookBits(12);
if ( nCode1 == 0x001 )
{
SkipBits(12);
if ( m_nK > 0 )
{
LookBits(1);
SkipBits(1);
}
if ( m_nK >= 0 )
{
for ( nIndex = 0; nIndex < 4; ++nIndex )
{
nCode1 = LookBits(12);
if ( nCode1 != 0x001 )
{
// TO DO: Error "Bad RTC code in CCITTFax stream"
}
SkipBits(12);
if ( m_nK > 0 )
{
LookBits(1);
SkipBits(1);
}
}
}
m_bEOF = TRUE;
}
}
else if ( bError && m_bEndOfLine )
{
do {
if ( nCode1 == EOF )
{
m_bEOF = TRUE;
return EOF;
}
SkipBits(1);
nCode1 = LookBits(13);
} while ( (nCode1 >> 1) != 0x001 );
SkipBits(12);
if ( m_nK > 0 )
{
SkipBits(1);
m_bNextLine2D = !(nCode1 & 1);
}
}
m_nCurPosCL = 0;
m_nOutputBits = m_pCodingLine[1] - m_pCodingLine[0];
if ( m_nOutputBits == 0 )
{
m_nCurPosCL = 1;
m_nOutputBits = m_pCodingLine[2] - m_pCodingLine[1];
}
++m_mCurRow;
}
// Ñ÷èòûâàåì îäèí áàéò
int nRet = 0;
if ( m_nOutputBits >= 8 )
{
nRet = ((m_nCurPosCL & 1) == 0) ? 0xff : 0x00;
if ( ( m_nOutputBits -= 8 ) == 0 )
{
++m_nCurPosCL;
if ( m_pCodingLine[m_nCurPosCL] < m_nColumns)
{
m_nOutputBits = m_pCodingLine[m_nCurPosCL + 1] - m_pCodingLine[m_nCurPosCL];
}
}
}
else
{
int nBits = 8;
nRet = 0;
do {
if ( m_nOutputBits > nBits )
{
nIndex = nBits;
nBits = 0;
if ((m_nCurPosCL & 1) == 0)
{
nRet |= 0xff >> (8 - nIndex);
}
m_nOutputBits -= nIndex;
}
else
{
nIndex = m_nOutputBits;
nBits -= m_nOutputBits;
if ( (m_nCurPosCL & 1) == 0 )
{
nRet |= (0xff >> (8 - nIndex)) << nBits;
}
m_nOutputBits = 0;
++m_nCurPosCL;
if ( m_pCodingLine[m_nCurPosCL] < m_nColumns )
{
m_nOutputBits = m_pCodingLine[m_nCurPosCL + 1] - m_pCodingLine[m_nCurPosCL];
}
}
} while ( nBits > 0 && m_pCodingLine[m_nCurPosCL] < m_nColumns );
}
m_nCharBuffer = m_bBlackIs1 ? (nRet ^ 0xff) : nRet;
return m_nCharBuffer;
}
short CCITTFaxStream::Get2DCode()
{
CCITTCode *pCCITTCode;
short nCode = 0;
if ( m_bEndOfBlock )
{
nCode = LookBits(7);
pCCITTCode = &c_arrTable2D[nCode];
if ( pCCITTCode->nBitsCount > 0 )
{
SkipBits(pCCITTCode->nBitsCount);
return pCCITTCode->nCode;
}
}
else
{
for ( int nCount = 1; nCount <= 7; ++nCount )
{
nCode = LookBits(nCount);
if ( nCount < 7 )
{
nCode <<= 7 - nCount;
}
pCCITTCode = &c_arrTable2D[nCode];
if ( pCCITTCode->nBitsCount == nCount )
{
SkipBits(nCount);
return pCCITTCode->nCode;
}
}
}
// TO DO: Error "Bad 2D code in CCITTFax stream"
return EOF;
}
short CCITTFaxStream::GetWhiteCode()
{
CCITTCode *pCCITTCode;
short nCode = 0;
if ( m_bEndOfBlock )
{
nCode = LookBits(12);
if ( (nCode >> 5) == 0 )
{
pCCITTCode = &c_arrWhiteTable1[nCode];
}
else
{
pCCITTCode = &c_arrWhiteTable2[nCode >> 3];
}
if ( pCCITTCode->nBitsCount > 0 )
{
SkipBits(pCCITTCode->nBitsCount);
return pCCITTCode->nCode;
}
}
else
{
for ( int nCount = 1; nCount <= 9; ++nCount )
{
nCode = LookBits(nCount);
if ( nCount < 9 )
{
nCode <<= 9 - nCount;
}
pCCITTCode = &c_arrWhiteTable2[nCode];
if ( pCCITTCode->nBitsCount == nCount )
{
SkipBits(nCount);
return pCCITTCode->nCode;
}
}
for ( int nCount = 11; nCount <= 12; ++nCount )
{
nCode = LookBits(nCount);
if ( nCount < 12 )
{
nCode <<= 12 - nCount;
}
pCCITTCode = &c_arrWhiteTable1[nCode];
if ( pCCITTCode->nBitsCount == nCount )
{
SkipBits(nCount);
return pCCITTCode->nCode;
}
}
}
// TO DO: Error "Bad white code in CCITTFax stream"
SkipBits(1);
return 1;
}
short CCITTFaxStream::GetBlackCode()
{
CCITTCode *pCCITTCode;
short nCode = 0;
if ( m_bEndOfBlock )
{
nCode = LookBits(13);
if ( (nCode >> 7) == 0)
{
pCCITTCode = &c_arrBlackTable1[nCode];
}
else if ( (nCode >> 9) == 0)
{
pCCITTCode = &c_arrBlackTable2[(nCode >> 1) - 64];
}
else
{
pCCITTCode = &c_arrBlackTable3[nCode >> 7];
}
if ( pCCITTCode->nBitsCount > 0 )
{
SkipBits(pCCITTCode->nBitsCount);
return pCCITTCode->nCode;
}
}
else
{
for ( int nCount = 2; nCount <= 6; ++nCount )
{
nCode = LookBits(nCount);
if ( nCount < 6 )
{
nCode <<= 6 - nCount;
}
pCCITTCode = &c_arrBlackTable3[nCode];
if ( pCCITTCode->nBitsCount == nCount )
{
SkipBits(nCount);
return pCCITTCode->nCode;
}
}
for ( int nCount = 7; nCount <= 12; ++nCount )
{
nCode = LookBits(nCount);
if ( nCount < 12 )
{
nCode <<= 12 - nCount;
}
if ( nCode >= 64 )
{
pCCITTCode = &c_arrBlackTable2[nCode - 64];
if ( pCCITTCode->nBitsCount == nCount )
{
SkipBits(nCount);
return pCCITTCode->nCode;
}
}
}
for ( int nCount = 10; nCount <= 13; ++nCount )
{
nCode = LookBits(nCount);
if ( nCount < 13 )
{
nCode <<= 13 - nCount;
}
pCCITTCode = &c_arrBlackTable1[nCode];
if ( pCCITTCode->nBitsCount == nCount )
{
SkipBits(nCount);
return pCCITTCode->nCode;
}
}
}
// TO DO: Error "Bad black code in CCITTFax stream"
SkipBits(1);
return 1;
}
short CCITTFaxStream::LookBits(int nCount)
{
while ( m_nInputBits < nCount )
{
int nChar = 0;
if ( ( nChar = m_pStream->GetChar() ) == EOF)
{
if ( m_nInputBits == 0 )
{
return EOF;
}
// Âáëèçè êîíöà ïîòîêà ìîæåò îêàçàòüñÿ, ÷òî çàïðàøèâàåòñÿ áîëüøå áèò, ÷åì
// èõ îñòàëîñü â ïîòîêå. Íóæíî âîçðàòèòü êîððåêòíîå çíà÷åíèå â äàííîì ñëó÷àå.
return ( m_nInputBuffer << (nCount - m_nInputBits)) & (0xffff >> (16 - nCount));
}
m_nInputBuffer = ( m_nInputBuffer << 8) + nChar;
m_nInputBits += 8;
}
return ( m_nInputBuffer >> ( m_nInputBits - nCount)) & (0xffff >> (16 - nCount));
}
StringExt *CCITTFaxStream::GetPSFilter(int nPSLevel, char *sIndent)
{
StringExt *seResult;
char sTemp[50];
if ( nPSLevel < 2 )
{
return NULL;
}
if ( !(seResult = m_pStream->GetPSFilter( nPSLevel, sIndent) ) )
{
return NULL;
}
seResult->Append(sIndent)->Append("<< ");
if ( m_nK != 0 )
{
sprintf( sTemp, "/K %d ", m_nK);
seResult->Append(sTemp);
}
if ( m_bEndOfLine )
{
seResult->Append("/EndOfLine true ");
}
if ( m_bByteAlign )
{
seResult->Append("/EncodedByteAlign true ");
}
sprintf( sTemp, "/Columns %d ", m_nColumns);
seResult->Append(sTemp);
if ( m_nRows != 0 )
{
sprintf( sTemp, "/Rows %d ", m_nRows);
seResult->Append(sTemp);
}
if ( !m_bEndOfBlock )
{
seResult->Append("/EndOfBlock false ");
}
if ( m_bBlackIs1 )
{
seResult->Append("/BlackIs1 true ");
}
seResult->Append(">> /CCITTFaxDecode filter\n");
return seResult;
}
BOOL CCITTFaxStream::IsBinary(BOOL bLast)
{
return m_pStream->IsBinary(TRUE);
}
//---------------------------------------------------------------------------------------------------------------
// DCTStream
//---------------------------------------------------------------------------------------------------------------
// Êîíñòàíòû äëÿ êîñèíóñíîãî ïðåîáðàçîâàíèÿ (20.12 fixed point format)
#define DCT_Cos_1_16 4017 // cos(pi/16)
#define DCT_Sin_1_16 799 // sin(pi/16)
#define DCT_Cos_3_16 3406 // cos(3*pi/16)
#define DCT_Sin_3_16 2276 // sin(3*pi/16)
#define DCT_Cos_6_16 1567 // cos(6*pi/16)
#define DCT_Sin_6_16 3784 // sin(6*pi/16)
#define DCT_Sqrt_2 5793 // sqrt(2)
#define DCT_Sqrt_2__2 2896 // sqrt(2) / 2
// Êîíñòàíòû äëÿ ïðåîáðàçîâàíèÿ öâåòîâ (16.16 fixed point format)
#define DCT_CrToR 91881 // 1.4020
#define DCT_CbToG -22553 // -0.3441363
#define DCT_CrToG -46802 // -0.71413636
#define DCT_CbToB 116130 // 1.772
// clip [-256,511] --> [0,255]
#define DCTClipOffset 256
static unsigned char arrDCTClip[768];
static int nDCTClipInit = 0;
// zig zag
static int arrDCTZigZag[64] =
{
0,
1, 8,
16, 9, 2,
3, 10, 17, 24,
32, 25, 18, 11, 4,
5, 12, 19, 26, 33, 40,
48, 41, 34, 27, 20, 13, 6,
7, 14, 21, 28, 35, 42, 49, 56,
57, 50, 43, 36, 29, 22, 15,
23, 30, 37, 44, 51, 58,
59, 52, 45, 38, 31,
39, 46, 53, 60,
61, 54, 47,
55, 62,
63
};
DCTStream::DCTStream(Stream *pStream, int nColorTransform):
FilterStream(pStream)
{
m_nColorTransform = nColorTransform;
m_bProgressive = m_bInterleaved = FALSE;
m_nWidth = m_nHeight = 0;
m_nMCUWidth = m_nMCUHeight = 0;
m_nComponentsCount = 0;
m_nCurComponent = 0;
m_nX = m_nY = m_nDY = 0;
for (int nComp = 0; nComp < 4; ++nComp )
{
for (int nIndex = 0; nIndex < 32; ++nIndex )
{
m_pppRowBuffer[nComp][nIndex] = NULL;
}
m_ppFrameBuffer[nComp] = NULL;
}
if ( !nDCTClipInit )
{
for (int nIndex = -256; nIndex < 0; ++nIndex)
arrDCTClip[DCTClipOffset + nIndex] = 0;
for (int nIndex = 0; nIndex < 256; ++nIndex)
arrDCTClip[DCTClipOffset + nIndex] = nIndex;
for (int nIndex = 256; nIndex < 512; ++nIndex)
arrDCTClip[DCTClipOffset + nIndex] = 255;
nDCTClipInit = 1;
}
}
DCTStream::~DCTStream()
{
Close();
delete m_pStream;
}
void DCTStream::Reset()
{
m_pStream->Reset();
m_bProgressive = m_bInterleaved = FALSE;
m_nWidth = m_nHeight = 0;
m_nComponentsCount = 0;
m_nQuantTablesCount = 0;
m_nDCHuffTablesCount = 0;
m_nACHuffTablesCount = 0;
m_bJFIFMarker = FALSE;
m_bAdobeMarker = FALSE;
m_nRestartInterval = 0;
if ( !ReadHeader() )
{
m_nY = m_nHeight;
return;
}
// Âû÷èñëèì ðàçìåðû MCU
if ( m_nComponentsCount == 1 )
{
m_arrCompInfo[0].nXResolution = m_arrCompInfo[0].nYResolution = 1;
}
m_nMCUWidth = m_arrCompInfo[0].nXResolution;
m_nMCUHeight = m_arrCompInfo[0].nYResolution;
for ( int nIndex = 1; nIndex < m_nComponentsCount; ++nIndex )
{
if (m_arrCompInfo[nIndex].nXResolution > m_nMCUWidth)
{
m_nMCUWidth = m_arrCompInfo[nIndex].nXResolution;
}
if (m_arrCompInfo[nIndex].nYResolution > m_nMCUHeight)
{
m_nMCUHeight = m_arrCompInfo[nIndex].nYResolution;
}
}
m_nMCUWidth *= 8;
m_nMCUHeight *= 8;
if ( m_nColorTransform == -1 )
{
if ( m_nComponentsCount == 3 )
{
if ( m_bJFIFMarker )
{
m_nColorTransform = 1;
}
else if ( m_arrCompInfo[0].nID == 82 && m_arrCompInfo[1].nID == 71 && m_arrCompInfo[2].nID == 66 ) // ASCII "RGB"
{
m_nColorTransform = 0;
}
else
{
m_nColorTransform = 1;
}
}
else
{
m_nColorTransform = 0;
}
}
if ( m_bProgressive || !m_bInterleaved )
{
// Âûäåëÿåì ïàìÿòü äëÿ âñåé êàðòèíêè
m_nBufferWidth = (( m_nWidth + m_nMCUWidth - 1) / m_nMCUWidth) * m_nMCUWidth;
m_nBufferHeight = (( m_nHeight + m_nMCUHeight - 1) / m_nMCUHeight) * m_nMCUHeight;
for (int nIndex = 0; nIndex < m_nComponentsCount; ++nIndex )
{
m_ppFrameBuffer[nIndex] = (int *)MemUtilsMallocArray(m_nBufferWidth * m_nBufferHeight, sizeof(int));
memset( m_ppFrameBuffer[nIndex], 0, m_nBufferWidth * m_nBufferHeight * sizeof(int));
}
// Ñ÷èòûâàåì äàííûå êàðòèíêè
do {
m_nRestartMarker = 0xd0;
Restart();
ReadScan();
} while (ReadHeader());
// Äåêîäèðóåì
DecodeImage();
// Îáíóëÿåì ñ÷åò÷èêè
m_nCurComponent = 0;
m_nX = 0;
m_nY = 0;
}
else
{
// Âûäåëÿåì ïàìÿòü ïîä îäíó ñòðîêó äëÿ MCU
m_nBufferWidth = (( m_nWidth + m_nMCUWidth - 1) / m_nMCUWidth) * m_nMCUWidth;
for (int nComp = 0; nComp < m_nComponentsCount; ++nComp )
{
for (int nY = 0; nY < m_nMCUHeight; ++nY)
{
m_pppRowBuffer[nComp][nY] = (unsigned char *)MemUtilsMallocArray(m_nBufferWidth, sizeof(unsigned char));
}
}
// Îáíóëÿåì ñ÷åò÷èêè
m_nCurComponent = 0;
m_nX = 0;
m_nY = 0;
m_nDY = m_nMCUHeight;
m_nRestartMarker = 0xd0;
Restart();
}
}
void DCTStream::Close()
{
for (int nComp = 0; nComp < 4; ++nComp )
{
for (int nY = 0; nY < 32; ++nY)
{
MemUtilsFree(m_pppRowBuffer[nComp][nY]);
m_pppRowBuffer[nComp][nY] = NULL;
}
MemUtilsFree(m_ppFrameBuffer[nComp]);
m_ppFrameBuffer[nComp] = NULL;
}
FilterStream::Close();
}
int DCTStream::GetChar()
{
int nChar = 0;
if ( m_nY >= m_nHeight )
{
return EOF;
}
if ( m_bProgressive || !m_bInterleaved )
{
nChar = m_ppFrameBuffer[m_nCurComponent][m_nY * m_nBufferWidth + m_nX];
if (++m_nCurComponent == m_nComponentsCount)
{
m_nCurComponent = 0;
if (++m_nX == m_nWidth)
{
m_nX = 0;
++m_nY;
}
}
}
else
{
if (m_nDY >= m_nMCUHeight)
{
if (!ReadMCURow())
{
m_nY = m_nHeight;
return EOF;
}
m_nCurComponent = 0;
m_nX = 0;
m_nDY = 0;
}
nChar = m_pppRowBuffer[m_nCurComponent][m_nDY][m_nX];
if (++m_nCurComponent == m_nComponentsCount)
{
m_nCurComponent = 0;
if (++m_nX == m_nWidth)
{
m_nX = 0;
++m_nY;
++m_nDY;
if ( m_nY == m_nHeight )
{
ReadTrailer();
}
}
}
}
return nChar;
}
int DCTStream::LookChar()
{
if ( m_nY >= m_nHeight )
{
return EOF;
}
if ( m_bProgressive || !m_bInterleaved )
{
return m_ppFrameBuffer[m_nCurComponent][m_nY * m_nBufferWidth + m_nX];
}
else
{
if (m_nDY >= m_nMCUHeight)
{
if (!ReadMCURow())
{
m_nY = m_nHeight;
return EOF;
}
m_nCurComponent = 0;
m_nX = 0;
m_nDY = 0;
}
return m_pppRowBuffer[m_nCurComponent][m_nDY][m_nX];
}
}
void DCTStream::Restart()
{
m_nInputBits = 0;
m_nRestartCtr = m_nRestartInterval;
for (int nIndex = 0; nIndex < m_nComponentsCount; ++nIndex)
m_arrCompInfo[nIndex].nPrevDC = 0;
m_nEOBRun = 0;
}
// Ñ÷èòûâàåì îäíó ñòðîêó èç MCUs èç ñîîòâåòñòâóþùåãî ïîòîêà JPEG.
BOOL DCTStream::ReadMCURow()
{
int arrRawData[64];
unsigned char arrTransformData[64];
unsigned char *p1, *p2;
int x1, x2, y2, x3, y3, x4, y4, x5, y5, i;
for (x1 = 0; x1 < m_nWidth; x1 += m_nMCUWidth)
{
// Îáðàáàòûâàåì restart marker
if ( m_nRestartInterval > 0 && m_nRestartCtr == 0)
{
int nChar = ReadMarker();
if ( nChar != m_nRestartMarker )
{
// TO DO: Error "Bad DCT data: incorrect restart marker"
return FALSE;
}
if (++m_nRestartMarker == 0xd8)
m_nRestartMarker = 0xd0;
Restart();
}
// Ñ÷èòûâàåì îäèí MCU
for (int nComp = 0; nComp < m_nComponentsCount; ++nComp)
{
int nXRes = m_arrCompInfo[nComp].nXResolution;
int nYRes = m_arrCompInfo[nComp].nYResolution;
int nHoriz = m_nMCUWidth / nXRes;
int nVert = m_nMCUHeight / nYRes;
int nHorizSub = nHoriz / 8;
int nVertSub = nVert / 8;
for (y2 = 0; y2 < m_nMCUHeight; y2 += nVert)
{
for (x2 = 0; x2 < m_nMCUWidth; x2 += nHoriz)
{
if ( !ReadDataUnit( &m_arrDCHuffTables[m_oCurScanInfo.arrDCHuffTable[nComp]], &m_arrACHuffTables[m_oCurScanInfo.arrACHuffTable[nComp]], &m_arrCompInfo[nComp].nPrevDC, arrRawData ) )
return FALSE;
TransformDataUnit( m_arrQuantTables[m_arrCompInfo[nComp].nQuantTableNum], arrRawData, arrTransformData);
if ( nHorizSub == 1 && nVertSub == 1 )
{
for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8)
{
p1 = &m_pppRowBuffer[nComp][y2+y3][x1+x2];
p1[0] = arrTransformData[i + 0];
p1[1] = arrTransformData[i + 1];
p1[2] = arrTransformData[i + 2];
p1[3] = arrTransformData[i + 3];
p1[4] = arrTransformData[i + 4];
p1[5] = arrTransformData[i + 5];
p1[6] = arrTransformData[i + 6];
p1[7] = arrTransformData[i + 7];
}
}
else if ( nHorizSub == 2 && nVertSub == 2 )
{
for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8)
{
p1 = &m_pppRowBuffer[nComp][y2 + y3][x1 + x2];
p2 = &m_pppRowBuffer[nComp][y2 + y3 + 1][x1 + x2];
p1[0] = p1[1] = p2[0] = p2[1] = arrTransformData[i + 0];
p1[2] = p1[3] = p2[2] = p2[3] = arrTransformData[i + 1];
p1[4] = p1[5] = p2[4] = p2[5] = arrTransformData[i + 2];
p1[6] = p1[7] = p2[6] = p2[7] = arrTransformData[i + 3];
p1[8] = p1[9] = p2[8] = p2[9] = arrTransformData[i + 4];
p1[10] = p1[11] = p2[10] = p2[11] = arrTransformData[i + 5];
p1[12] = p1[13] = p2[12] = p2[13] = arrTransformData[i + 6];
p1[14] = p1[15] = p2[14] = p2[15] = arrTransformData[i + 7];
}
}
else
{
i = 0;
for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += nVertSub)
{
for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += nHorizSub )
{
for (y5 = 0; y5 < nVertSub; ++y5)
for (x5 = 0; x5 < nHorizSub; ++x5)
m_pppRowBuffer[nComp][y2 + y4 + y5][x1 + x2 + x4 + x5] = arrTransformData[i];
++i;
}
}
}
}
}
}
--m_nRestartCtr;
// Ïðåîáàçóåì ïðîñòðàíñòâî öâåòîâ
if ( m_nColorTransform )
{
// YCbCr -> RGB
if ( m_nComponentsCount == 3 )
{
for (y2 = 0; y2 < m_nMCUHeight; ++y2)
{
for (x2 = 0; x2 < m_nMCUWidth; ++x2)
{
int nY = m_pppRowBuffer[0][y2][x1 + x2];
int nCb = m_pppRowBuffer[1][y2][x1 + x2] - 128;
int nCr = m_pppRowBuffer[2][y2][x1 + x2] - 128;
int nR = ((nY << 16) + DCT_CrToR * nCr + 32768) >> 16;
m_pppRowBuffer[0][y2][x1 + x2] = arrDCTClip[DCTClipOffset + nR];
int nG = ((nY << 16) + DCT_CbToG * nCb + DCT_CrToG * nCr + 32768) >> 16;
m_pppRowBuffer[1][y2][x1 + x2] = arrDCTClip[DCTClipOffset + nG];
int nB = ((nY << 16) + DCT_CbToB * nCb + 32768) >> 16;
m_pppRowBuffer[2][y2][x1+x2] = arrDCTClip[DCTClipOffset + nB];
}
}
}
else if ( m_nComponentsCount == 4 ) // YCbCrK -> CMYK (K îñòàâëÿåì íåèçìåííåííûì)
{
for (y2 = 0; y2 < m_nMCUHeight; ++y2)
{
for (x2 = 0; x2 < m_nMCUWidth; ++x2)
{
int nY = m_pppRowBuffer[0][y2][x1 + x2];
int nCb = m_pppRowBuffer[1][y2][x1 + x2] - 128;
int nCr = m_pppRowBuffer[2][y2][x1 + x2] - 128;
int nR = ((nY << 16) + DCT_CrToR * nCr + 32768) >> 16;
m_pppRowBuffer[0][y2][x1+x2] = 255 - arrDCTClip[DCTClipOffset + nR];
int nG = ((nY << 16) + DCT_CbToG * nCb + DCT_CrToG * nCr + 32768) >> 16;
m_pppRowBuffer[1][y2][x1+x2] = 255 - arrDCTClip[DCTClipOffset + nG];
int nB = ((nY << 16) + DCT_CbToB * nCb + 32768) >> 16;
m_pppRowBuffer[2][y2][x1+x2] = 255 - arrDCTClip[DCTClipOffset + nB];
}
}
}
}
}
return TRUE;
}
// Òîëüêî äëÿ progressive èëè íå interleaved JPEG.
void DCTStream::ReadScan()
{
int arrData[64];
int x1, y1, dx1, dy1, x2, y2, y3, nComponent = 0, i;
int *pBuffer;
if (m_oCurScanInfo.nComponentsCount == 1)
{
for (nComponent = 0; nComponent < m_nComponentsCount; ++nComponent)
{
if (m_oCurScanInfo.arrbComponent[nComponent])
{
break;
}
}
dx1 = m_nMCUWidth / m_arrCompInfo[nComponent].nXResolution;
dy1 = m_nMCUHeight / m_arrCompInfo[nComponent].nYResolution;
}
else
{
dx1 = m_nMCUWidth;
dy1 = m_nMCUHeight;
}
for (y1 = 0; y1 < m_nHeight; y1 += dy1)
{
for (x1 = 0; x1 < m_nWidth; x1 += dx1)
{
// Îáðàáàòûâàåì restart marker
if ( m_nRestartInterval > 0 && m_nRestartCtr == 0)
{
int nChar = ReadMarker();
if ( nChar != m_nRestartMarker )
{
// TO DO: Error "Bad DCT data: incorrect restart marker"
return;
}
if (++m_nRestartMarker == 0xd8)
{
m_nRestartMarker = 0xd0;
}
Restart();
}
// Ñ÷èòûâàåì îäèí MCU
for (nComponent = 0; nComponent < m_nComponentsCount; ++nComponent)
{
if (!m_oCurScanInfo.arrbComponent[nComponent])
{
continue;
}
int nXRes = m_arrCompInfo[nComponent].nXResolution;
int nYRes = m_arrCompInfo[nComponent].nYResolution;
int nHoriz = m_nMCUWidth / nXRes;
int nVert = m_nMCUHeight / nYRes;
int nVertSub = nVert / 8;
for (y2 = 0; y2 < dy1; y2 += nVert)
{
for (x2 = 0; x2 < dx1; x2 += nHoriz)
{
pBuffer = &m_ppFrameBuffer[nComponent][(y1+y2) * m_nBufferWidth + (x1+x2)];
for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8)
{
arrData[i + 0] = pBuffer[0];
arrData[i + 1] = pBuffer[1];
arrData[i + 2] = pBuffer[2];
arrData[i + 3] = pBuffer[3];
arrData[i + 4] = pBuffer[4];
arrData[i + 5] = pBuffer[5];
arrData[i + 6] = pBuffer[6];
arrData[i + 7] = pBuffer[7];
pBuffer += m_nBufferWidth * nVertSub;
}
if ( m_bProgressive )
{
if ( !ReadProgressiveDataUnit( &m_arrDCHuffTables[m_oCurScanInfo.arrDCHuffTable[nComponent]], &m_arrACHuffTables[m_oCurScanInfo.arrACHuffTable[nComponent]], &m_arrCompInfo[nComponent].nPrevDC, arrData ) )
{
return;
}
}
else
{
if ( !ReadDataUnit( &m_arrDCHuffTables[m_oCurScanInfo.arrDCHuffTable[nComponent]], &m_arrACHuffTables[m_oCurScanInfo.arrACHuffTable[nComponent]], &m_arrCompInfo[nComponent].nPrevDC, arrData ) )
{
return;
}
}
pBuffer = &m_ppFrameBuffer[nComponent][(y1 + y2) * m_nBufferWidth + (x1 + x2)];
for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8)
{
pBuffer[0] = arrData[i + 0];
pBuffer[1] = arrData[i + 1];
pBuffer[2] = arrData[i + 2];
pBuffer[3] = arrData[i + 3];
pBuffer[4] = arrData[i + 4];
pBuffer[5] = arrData[i + 5];
pBuffer[6] = arrData[i + 6];
pBuffer[7] = arrData[i + 7];
pBuffer += m_nBufferWidth * nVertSub;
}
}
}
}
--m_nRestartCtr;
}
}
}
BOOL DCTStream::ReadDataUnit(DCTHuffTable *pDCHuffTable, DCTHuffTable *pACHuffTable, int *pnPrevDC, int arrData[64])
{
int nSize = 0, nAmp = 0;
if ( ( nSize = ReadHuffSymbol(pDCHuffTable) ) == 9999 )
{
return FALSE;
}
if ( nSize > 0 )
{
if ( ( nAmp = ReadAmp(nSize) ) == 9999 )
{
return FALSE;
}
}
else
{
nAmp = 0;
}
arrData[0] = *pnPrevDC += nAmp;
for (int nI = 1; nI < 64; ++nI )
{
arrData[nI] = 0;
}
int nIndex = 1;
while ( nIndex < 64)
{
int nRun = 0;
int nSymbol = 0;
while ( ( nSymbol = ReadHuffSymbol(pACHuffTable) ) == 0xf0 && nRun < 0x30 )
{
nRun += 0x10;
}
if ( nSymbol == 9999 )
{
return FALSE;
}
if ( nSymbol == 0x00 )
{
break;
}
else
{
nRun += (nSymbol >> 4) & 0x0f;
nSize = nSymbol & 0x0f;
nAmp = ReadAmp(nSize);
if ( nAmp == 9999 )
{
return FALSE;
}
nIndex += nRun;
if ( nIndex < 64 )
{
int nNewIndex = arrDCTZigZag[nIndex++];
arrData[nNewIndex] = nAmp;
}
}
}
return TRUE;
}
BOOL DCTStream::ReadProgressiveDataUnit(DCTHuffTable *pDCHuffTable, DCTHuffTable *pACHuffTable, int *pnPrevDC, int arrData[64])
{
int nRun = 0, nSize = 0, nAmp = 0, nBit = 0;
// DC êoýôôèöèåíòû
int nKoef = m_oCurScanInfo.nFirstKoef;
if ( nKoef == 0)
{
if (m_oCurScanInfo.nApproxH == 0)
{
if ( ( nSize = ReadHuffSymbol(pDCHuffTable) ) == 9999 )
{
return FALSE;
}
if ( nSize > 0 )
{
if ( ( nAmp = ReadAmp(nSize) ) == 9999 )
{
return FALSE;
}
}
else
{
nAmp = 0;
}
arrData[0] += (*pnPrevDC += nAmp) << m_oCurScanInfo.nApproxL;
}
else
{
if ( ( nBit = ReadBit() ) == 9999 )
{
return FALSE;
}
arrData[0] += nBit << m_oCurScanInfo.nApproxL;
}
++nKoef;
}
if (m_oCurScanInfo.nLastKoef == 0)
{
return TRUE;
}
// Ïðîâåðÿåì ãðóïïó EOB
if ( m_nEOBRun > 0 )
{
while ( nKoef <= m_oCurScanInfo.nLastKoef)
{
int nNewIndex = arrDCTZigZag[nKoef++];
if ( arrData[nNewIndex] != 0 )
{
if ( ( nBit = ReadBit() ) == EOF )
{
return FALSE;
}
if ( nBit )
{
arrData[nNewIndex] += 1 << m_oCurScanInfo.nApproxL;
}
}
}
--m_nEOBRun;
return TRUE;
}
int nK = 0;
// ñ÷èòûâàåì êîýôôèöèåíòû AC
while ( nKoef <= m_oCurScanInfo.nLastKoef)
{
int nSymbol = 0;
if ( ( nSymbol = ReadHuffSymbol(pACHuffTable) ) == 9999 )
{
return FALSE;
}
// ZRL
if ( nSymbol == 0xf0 )
{
nK = 0;
while ( nK < 16 )
{
int nNewIndex = arrDCTZigZag[nKoef++];
if ( arrData[nNewIndex] == 0 )
{
++nK;
}
else
{
if ( ( nBit = ReadBit() ) == EOF )
{
return FALSE;
}
if ( nBit )
{
arrData[nNewIndex] += 1 << m_oCurScanInfo.nApproxL;
}
}
}
}
else if ( ( nSymbol & 0x0f) == 0x00 ) // EOB run
{
int nTemp = nSymbol >> 4;
m_nEOBRun = 0;
for ( nK = 0; nK < nTemp; ++nK )
{
if ( ( nBit = ReadBit() ) == EOF )
{
return FALSE;
}
m_nEOBRun = ( m_nEOBRun << 1) | nBit;
}
m_nEOBRun += 1 << nTemp;
while ( nKoef <= m_oCurScanInfo.nLastKoef )
{
int nNewIndex = arrDCTZigZag[nKoef++];
if ( arrData[nNewIndex] != 0 )
{
if ( ( nBit = ReadBit() ) == EOF )
{
return FALSE;
}
if ( nBit )
{
arrData[nNewIndex] += 1 << m_oCurScanInfo.nApproxL;
}
}
}
--m_nEOBRun;
break;
}
else
{
nRun = ( nSymbol >> 4) & 0x0f;
nSize = nSymbol & 0x0f;
if ( ( nAmp = ReadAmp(nSize) ) == 9999 )
{
return FALSE;
}
nK = 0;
int nNewIndex = 0;
do {
nNewIndex = arrDCTZigZag[nKoef++];
while ( arrData[nNewIndex] != 0)
{
if ( ( nBit = ReadBit() ) == EOF )
{
return FALSE;
}
if ( nBit )
{
arrData[nNewIndex] += 1 << m_oCurScanInfo.nApproxL;
}
nNewIndex = arrDCTZigZag[nKoef++];
}
++nK;
} while (nK <= nRun);
arrData[nNewIndex] = nAmp << m_oCurScanInfo.nApproxL;
}
}
return TRUE;
}
void DCTStream::DecodeImage()
{
int arrDataIn[64];
unsigned char arrDataOut[64];
unsigned short *pQuantTable;
int x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, i;
int *p0, *p1, *p2;
for (y1 = 0; y1 < m_nBufferHeight; y1 += m_nMCUHeight)
{
for (x1 = 0; x1 < m_nBufferWidth; x1 += m_nMCUWidth)
{
for ( int nComp = 0; nComp < m_nComponentsCount; ++nComp)
{
pQuantTable = m_arrQuantTables[m_arrCompInfo[nComp].nQuantTableNum];
int nXRes = m_arrCompInfo[nComp].nXResolution;
int nYRes = m_arrCompInfo[nComp].nYResolution;
int nHoriz = m_nMCUWidth / nXRes;
int nVert = m_nMCUHeight / nYRes;
int nHorizSub = nHoriz / 8;
int nVertSub = nVert / 8;
for (y2 = 0; y2 < m_nMCUHeight; y2 += nVert)
{
for (x2 = 0; x2 < m_nMCUWidth; x2 += nHoriz)
{
p1 = &m_ppFrameBuffer[nComp][(y1 + y2) * m_nBufferWidth + (x1 + x2)];
for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8)
{
arrDataIn[i + 0] = p1[0];
arrDataIn[i + 1] = p1[1];
arrDataIn[i + 2] = p1[2];
arrDataIn[i + 3] = p1[3];
arrDataIn[i + 4] = p1[4];
arrDataIn[i + 5] = p1[5];
arrDataIn[i + 6] = p1[6];
arrDataIn[i + 7] = p1[7];
p1 += m_nBufferWidth * nVertSub;
}
TransformDataUnit( pQuantTable, arrDataIn, arrDataOut);
p1 = &m_ppFrameBuffer[nComp][(y1+y2) * m_nBufferWidth + (x1+x2)];
if ( nHorizSub == 1 && nVertSub == 1 )
{
for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8)
{
p1[0] = arrDataOut[i + 0] & 0xff;
p1[1] = arrDataOut[i + 1] & 0xff;
p1[2] = arrDataOut[i + 2] & 0xff;
p1[3] = arrDataOut[i + 3] & 0xff;
p1[4] = arrDataOut[i + 4] & 0xff;
p1[5] = arrDataOut[i + 5] & 0xff;
p1[6] = arrDataOut[i + 6] & 0xff;
p1[7] = arrDataOut[i + 7] & 0xff;
p1 += m_nBufferWidth;
}
}
else if ( nHorizSub == 2 && nVertSub == 2)
{
p2 = p1 + m_nBufferWidth;
for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8)
{
p1[0] = p1[1] = p2[0] = p2[1] = arrDataOut[i + 0] & 0xff;
p1[2] = p1[3] = p2[2] = p2[3] = arrDataOut[i + 1] & 0xff;
p1[4] = p1[5] = p2[4] = p2[5] = arrDataOut[i + 2] & 0xff;
p1[6] = p1[7] = p2[6] = p2[7] = arrDataOut[i + 3] & 0xff;
p1[8] = p1[9] = p2[8] = p2[9] = arrDataOut[i + 4] & 0xff;
p1[10] = p1[11] = p2[10] = p2[11] = arrDataOut[i + 5] & 0xff;
p1[12] = p1[13] = p2[12] = p2[13] = arrDataOut[i + 6] & 0xff;
p1[14] = p1[15] = p2[14] = p2[15] = arrDataOut[i + 7] & 0xff;
p1 += m_nBufferWidth * 2;
p2 += m_nBufferWidth * 2;
}
}
else
{
i = 0;
for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += nVertSub)
{
for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += nHorizSub)
{
p2 = p1 + x4;
for (y5 = 0; y5 < nVertSub; ++y5)
{
for (x5 = 0; x5 < nHorizSub; ++x5)
{
p2[x5] = arrDataOut[i] & 0xff;
}
p2 += m_nBufferWidth;
}
++i;
}
p1 += m_nBufferWidth * nVertSub;
}
}
}
}
}
// Ïðåîáðàçîâàíèå ïðîñòðàíñòâà öâåòîâ
if ( m_nColorTransform )
{
// YCbCr -> RGB
if ( m_nComponentsCount == 3 )
{
for ( y2 = 0; y2 < m_nMCUHeight; ++y2 )
{
p0 = &m_ppFrameBuffer[0][(y1+y2) * m_nBufferWidth + x1];
p1 = &m_ppFrameBuffer[1][(y1+y2) * m_nBufferWidth + x1];
p2 = &m_ppFrameBuffer[2][(y1+y2) * m_nBufferWidth + x1];
for (x2 = 0; x2 < m_nMCUWidth; ++x2)
{
int nY = *p0;
int nCb = *p1 - 128;
int nCr = *p2 - 128;
int nR = (( nY << 16 ) + DCT_CrToR * nCr + 32768) >> 16;
*p0++ = arrDCTClip[DCTClipOffset + nR];
int nG = (( nY << 16 ) + DCT_CbToG * nCb + DCT_CrToG * nCr + 32768) >> 16;
*p1++ = arrDCTClip[DCTClipOffset + nG];
int nB = (( nY << 16 ) + DCT_CbToB * nCb + 32768) >> 16;
*p2++ = arrDCTClip[DCTClipOffset + nB];
}
}
}
else if ( m_nComponentsCount == 4 ) // YCbCrK -> CMYK (K îñòàâëÿåì íåèçìåíåííûì)
{
for (y2 = 0; y2 < m_nMCUHeight; ++y2)
{
p0 = &m_ppFrameBuffer[0][(y1+y2) * m_nBufferWidth + x1];
p1 = &m_ppFrameBuffer[1][(y1+y2) * m_nBufferWidth + x1];
p2 = &m_ppFrameBuffer[2][(y1+y2) * m_nBufferWidth + x1];
for (x2 = 0; x2 < m_nMCUWidth; ++x2)
{
int nY = *p0;
int nCb = *p1 - 128;
int nCr = *p2 - 128;
int nR = (( nY << 16 ) + DCT_CrToR * nCr + 32768) >> 16;
*p0++ = 255 - arrDCTClip[DCTClipOffset + nR];
int nG = (( nY << 16) + DCT_CbToG * nCb + DCT_CrToG * nCr + 32768) >> 16;
*p1++ = 255 - arrDCTClip[DCTClipOffset + nG];
int nB = (( nY << 16) + DCT_CbToB * nCb + 32768) >> 16;
*p2++ = 255 - arrDCTClip[DCTClipOffset + nB];
}
}
}
}
}
}
}
void DCTStream::TransformDataUnit(unsigned short *pQuantTable, int arrDataIn[64], unsigned char arrDataOut[64])
{
int arrBuffer[8] = { 0, 0, 0, 0, 0, 0, 0, 0};
int nTemp = 0;
int *pCurLine = NULL;
// Äåêâàíòèçàöèÿ
for (int nIndex = 0; nIndex < 64; ++nIndex )
{
arrDataIn[nIndex] *= pQuantTable[nIndex];
}
// Îáðàòíîå ñèíóñíî-êîñèíóñíîå ïðåîáðàçîâàíèÿ (ïî ñòðîêàì)
for ( int nIndex = 0; nIndex < 64; nIndex += 8)
{
pCurLine = arrDataIn + nIndex;
// Ïðîâåðÿåì ñëó÷àé, êîãäà âñå êîýôôèöèåíòû ðàâíû 0
if ( pCurLine[1] == 0 && pCurLine[2] == 0 && pCurLine[3] == 0 && pCurLine[4] == 0 && pCurLine[5] == 0 && pCurLine[6] == 0 && pCurLine[7] == 0 )
{
nTemp = ( DCT_Sqrt_2 * pCurLine[0] + 512 ) >> 10;
pCurLine[0] = nTemp;
pCurLine[1] = nTemp;
pCurLine[2] = nTemp;
pCurLine[3] = nTemp;
pCurLine[4] = nTemp;
pCurLine[5] = nTemp;
pCurLine[6] = nTemp;
pCurLine[7] = nTemp;
continue;
}
// Øàã 4 (Ñäâèã íà 128)
arrBuffer[0] = (DCT_Sqrt_2 * pCurLine[0] + 128) >> 8;
arrBuffer[1] = (DCT_Sqrt_2 * pCurLine[4] + 128) >> 8;
arrBuffer[2] = pCurLine[2];
arrBuffer[3] = pCurLine[6];
arrBuffer[4] = (DCT_Sqrt_2__2 * (pCurLine[1] - pCurLine[7]) + 128) >> 8;
arrBuffer[7] = (DCT_Sqrt_2__2 * (pCurLine[1] + pCurLine[7]) + 128) >> 8;
arrBuffer[5] = pCurLine[3] << 4;
arrBuffer[6] = pCurLine[5] << 4;
// Øàã 3
nTemp = (arrBuffer[0] - arrBuffer[1]+ 1) >> 1;
arrBuffer[0] = (arrBuffer[0] + arrBuffer[1] + 1) >> 1;
arrBuffer[1] = nTemp;
nTemp = (arrBuffer[2] * DCT_Sin_6_16 + arrBuffer[3] * DCT_Cos_6_16 + 128) >> 8;
arrBuffer[2] = (arrBuffer[2] * DCT_Cos_6_16 - arrBuffer[3] * DCT_Sin_6_16 + 128) >> 8;
arrBuffer[3] = nTemp;
nTemp = (arrBuffer[4] - arrBuffer[6] + 1) >> 1;
arrBuffer[4] = (arrBuffer[4] + arrBuffer[6] + 1) >> 1;
arrBuffer[6] = nTemp;
nTemp = (arrBuffer[7] + arrBuffer[5] + 1) >> 1;
arrBuffer[5] = (arrBuffer[7] - arrBuffer[5] + 1) >> 1;
arrBuffer[7] = nTemp;
// Øàã 2
nTemp = (arrBuffer[0] - arrBuffer[3] + 1) >> 1;
arrBuffer[0] = (arrBuffer[0] + arrBuffer[3] + 1) >> 1;
arrBuffer[3] = nTemp;
nTemp = (arrBuffer[1] - arrBuffer[2] + 1) >> 1;
arrBuffer[1] = (arrBuffer[1] + arrBuffer[2] + 1) >> 1;
arrBuffer[2] = nTemp;
nTemp = (arrBuffer[4] * DCT_Sin_3_16 + arrBuffer[7] * DCT_Cos_3_16 + 2048) >> 12;
arrBuffer[4] = (arrBuffer[4] * DCT_Cos_3_16 - arrBuffer[7] * DCT_Sin_3_16 + 2048) >> 12;
arrBuffer[7] = nTemp;
nTemp = (arrBuffer[5] * DCT_Sin_1_16 + arrBuffer[6] * DCT_Cos_1_16 + 2048) >> 12;
arrBuffer[5] = (arrBuffer[5] * DCT_Cos_1_16 - arrBuffer[6] * DCT_Sin_1_16 + 2048) >> 12;
arrBuffer[6] = nTemp;
// Øàã 1
pCurLine[0] = arrBuffer[0] + arrBuffer[7];
pCurLine[7] = arrBuffer[0] - arrBuffer[7];
pCurLine[1] = arrBuffer[1] + arrBuffer[6];
pCurLine[6] = arrBuffer[1] - arrBuffer[6];
pCurLine[2] = arrBuffer[2] + arrBuffer[5];
pCurLine[5] = arrBuffer[2] - arrBuffer[5];
pCurLine[3] = arrBuffer[3] + arrBuffer[4];
pCurLine[4] = arrBuffer[3] - arrBuffer[4];
}
// Îáðàòíîå ñèíóñíî-êîñèíóñíîå ïðåîáðàçîâàíèÿ (ïî ñòîëáöàì)
for ( int nIndex = 0; nIndex < 8; ++nIndex )
{
pCurLine = arrDataIn + nIndex;
// ïðîâåðÿåì âñå ëè êîýôôèöèåíòû íóëåâûå
if ( pCurLine[ 1 * 8] == 0 && pCurLine[2 * 8] == 0 && pCurLine[3 * 8] == 0 && pCurLine[4 * 8] == 0 && pCurLine[5 * 8] == 0 && pCurLine[6 * 8] == 0 && pCurLine[7 * 8] == 0 )
{
nTemp = (DCT_Sqrt_2 * arrDataIn[nIndex + 0] + 8192) >> 14;
pCurLine[0 * 8] = nTemp;
pCurLine[1 * 8] = nTemp;
pCurLine[2 * 8] = nTemp;
pCurLine[3 * 8] = nTemp;
pCurLine[4 * 8] = nTemp;
pCurLine[5 * 8] = nTemp;
pCurLine[6 * 8] = nTemp;
pCurLine[7 * 8] = nTemp;
continue;
}
// Øàã 4
arrBuffer[0] = (DCT_Sqrt_2 * pCurLine[0 * 8] + 2048) >> 12;
arrBuffer[1] = (DCT_Sqrt_2 * pCurLine[4 * 8] + 2048) >> 12;
arrBuffer[2] = pCurLine[2 * 8];
arrBuffer[3] = pCurLine[6 * 8];
arrBuffer[4] = (DCT_Sqrt_2__2 * (pCurLine[1 * 8] - pCurLine[7 * 8]) + 2048) >> 12;
arrBuffer[7] = (DCT_Sqrt_2__2 * (pCurLine[1 * 8] + pCurLine[7 * 8]) + 2048) >> 12;
arrBuffer[5] = pCurLine[3 * 8];
arrBuffer[6] = pCurLine[5 * 8];
// Øàã 3
nTemp = (arrBuffer[0] - arrBuffer[1] + 1) >> 1;
arrBuffer[0] = (arrBuffer[0] + arrBuffer[1] + 1) >> 1;
arrBuffer[1] = nTemp;
nTemp = (arrBuffer[2] * DCT_Sin_6_16 + arrBuffer[3] * DCT_Cos_6_16 + 2048) >> 12;
arrBuffer[2] = (arrBuffer[2] * DCT_Cos_6_16 - arrBuffer[3] * DCT_Sin_6_16 + 2048) >> 12;
arrBuffer[3] = nTemp;
nTemp = (arrBuffer[4] - arrBuffer[6] + 1) >> 1;
arrBuffer[4] = (arrBuffer[4] + arrBuffer[6] + 1) >> 1;
arrBuffer[6] = nTemp;
nTemp = (arrBuffer[7] + arrBuffer[5] + 1) >> 1;
arrBuffer[5] = (arrBuffer[7] - arrBuffer[5] + 1) >> 1;
arrBuffer[7] = nTemp;
// Øàã 2
nTemp = (arrBuffer[0] - arrBuffer[3] + 1) >> 1;
arrBuffer[0] = (arrBuffer[0] + arrBuffer[3] + 1) >> 1;
arrBuffer[3] = nTemp;
nTemp = (arrBuffer[1] - arrBuffer[2] + 1) >> 1;
arrBuffer[1] = (arrBuffer[1] + arrBuffer[2] + 1) >> 1;
arrBuffer[2] = nTemp;
nTemp = (arrBuffer[4] * DCT_Sin_3_16 + arrBuffer[7] * DCT_Cos_3_16 + 2048) >> 12;
arrBuffer[4] = (arrBuffer[4] * DCT_Cos_3_16 - arrBuffer[7] * DCT_Sin_3_16 + 2048) >> 12;
arrBuffer[7] = nTemp;
nTemp = (arrBuffer[5] * DCT_Sin_1_16 + arrBuffer[6] * DCT_Cos_1_16 + 2048) >> 12;
arrBuffer[5] = (arrBuffer[5] * DCT_Cos_1_16 - arrBuffer[6] * DCT_Sin_1_16 + 2048) >> 12;
arrBuffer[6] = nTemp;
// Øàã 1
pCurLine[0 * 8] = arrBuffer[0] + arrBuffer[7];
pCurLine[7 * 8] = arrBuffer[0] - arrBuffer[7];
pCurLine[1 * 8] = arrBuffer[1] + arrBuffer[6];
pCurLine[6 * 8] = arrBuffer[1] - arrBuffer[6];
pCurLine[2 * 8] = arrBuffer[2] + arrBuffer[5];
pCurLine[5 * 8] = arrBuffer[2] - arrBuffer[5];
pCurLine[3 * 8] = arrBuffer[3] + arrBuffer[4];
pCurLine[4 * 8] = arrBuffer[3] - arrBuffer[4];
}
// convert to 8-bit integers
for ( int nIndex = 0; nIndex < 64; ++nIndex )
{
arrDataOut[nIndex] = arrDCTClip[DCTClipOffset + 128 + ((arrDataIn[nIndex] + 8) >> 4)];
}
}
int DCTStream::ReadHuffSymbol(DCTHuffTable *pTable)
{
unsigned short nCode = 0;
int nCodeBitsCount = 0;
do {
int nBit = 0;
if ( ( nBit = ReadBit() ) == EOF )
return 9999;
nCode = (nCode << 1) + nBit;
++nCodeBitsCount;
if ( nCode - pTable->arrunFirstCode[nCodeBitsCount] < pTable->arrunCodesCount[nCodeBitsCount] )
{
nCode -= pTable->arrunFirstCode[nCodeBitsCount];
return pTable->arrunSymbols[pTable->arrunFirstSymbol[nCodeBitsCount] + nCode];
}
} while ( nCodeBitsCount < 16 );
// TO DO: Error "Bad Huffman code in DCT stream"
return 9999;
}
int DCTStream::ReadAmp(int nSize)
{
int nAmp = 0;
for ( int nBitsCount = 0; nBitsCount < nSize; ++nBitsCount )
{
int nBit = 0;
if ( ( nBit = ReadBit() ) == EOF )
return 9999;
nAmp = (nAmp << 1) + nBit;
}
if ( nAmp < ( 1 << (nSize - 1) ) )
nAmp -= (1 << nSize) - 1;
return nAmp;
}
int DCTStream::ReadBit()
{
if ( m_nInputBits == 0 )
{
int nFirstChar = 0;
if ( ( nFirstChar = m_pStream->GetChar() ) == EOF )
return EOF;
if ( nFirstChar == 0xff )
{
int nSecondChar = 0;
do {
nSecondChar = m_pStream->GetChar();
} while ( nSecondChar == 0xff );
if ( nSecondChar != 0x00 )
{
// TO DO: Error "Bad DCT data: missing 00 after ff"
return EOF;
}
}
m_nInputBuffer = nFirstChar;
m_nInputBits = 8;
}
int nBit = (m_nInputBuffer >> (m_nInputBits - 1)) & 1;
--m_nInputBits;
return nBit;
}
BOOL DCTStream::ReadHeader()
{
// ×èòàåì çàãîëîâîê
BOOL bDoScan = FALSE;
while ( !bDoScan )
{
int nChar = ReadMarker();
switch ( nChar )
{
case 0xc0: // SOF0 (sequential)
case 0xc1: // SOF1 (extended sequential)
if ( !ReadBaselineSOF() )
{
return FALSE;
}
break;
case 0xc2: // SOF2 (progressive)
if ( !ReadProgressiveSOF() )
{
return FALSE;
}
break;
case 0xc4: // DHT
if ( !ReadHuffmanTables() )
{
return FALSE;
}
break;
case 0xd8: // SOI
break;
case 0xd9: // EOI
return FALSE;
case 0xda: // SOS
if ( !ReadScanInfo() )
{
return FALSE;
}
bDoScan = TRUE;
break;
case 0xdb: // DQT
if ( !ReadQuantTables() )
{
return FALSE;
}
break;
case 0xdd: // DRI
if ( !ReadRestartInterval() )
{
return FALSE;
}
break;
case 0xe0: // APP0
if ( !ReadJFIFMarker() )
{
return FALSE;
}
break;
case 0xee: // APP14
if ( !ReadAdobeMarker() )
{
return FALSE;
}
break;
case EOF:
// TO DO : Error "Bad DCT header"
return FALSE;
default:
// Ïðîïóñêàì ìàðêåðû òèïà: APPn, COM è ò.ä.
if ( nChar >= 0xe0 )
{
int nCount = Read16() - 2;
for (int nIndex = 0; nIndex < nCount; ++nIndex )
{
m_pStream->GetChar();
}
}
else
{
// TO DO: Error "Unknown DCT marker"
return FALSE;
}
break;
}
}
return TRUE;
}
BOOL DCTStream::ReadBaselineSOF()
{
int nLength = Read16();
int nPrecision = m_pStream->GetChar();
m_nHeight = Read16();
m_nWidth = Read16();
m_nComponentsCount = m_pStream->GetChar();
if ( m_nComponentsCount <= 0 || m_nComponentsCount > 4 )
{
// TO DO: Error "Bad number of components in DCT stream"
m_nComponentsCount = 0;
return FALSE;
}
if ( nPrecision != 8 )
{
// TO DO: Error "Bad DCT precision"
return FALSE;
}
for ( int nIndex = 0; nIndex < m_nComponentsCount; ++nIndex )
{
m_arrCompInfo[nIndex].nID = m_pStream->GetChar();
int nChar = m_pStream->GetChar();
m_arrCompInfo[nIndex].nXResolution = (nChar >> 4) & 0x0f;
m_arrCompInfo[nIndex].nYResolution = nChar & 0x0f;
m_arrCompInfo[nIndex].nQuantTableNum = m_pStream->GetChar();
}
m_bProgressive = FALSE;
return TRUE;
}
BOOL DCTStream::ReadProgressiveSOF()
{
int nLength = Read16();
int ReadProgressiveSOF = m_pStream->GetChar();
m_nHeight = Read16();
m_nWidth = Read16();
m_nComponentsCount = m_pStream->GetChar();
if ( m_nComponentsCount <= 0 || m_nComponentsCount > 4 )
{
// TO DO: Error "Bad number of components in DCT stream"
m_nComponentsCount = 0;
return FALSE;
}
if ( ReadProgressiveSOF != 8 )
{
// TO DO: Error "Bad DCT precision"
return FALSE;
}
for ( int nIndex = 0; nIndex < m_nComponentsCount; ++nIndex)
{
m_arrCompInfo[nIndex].nID = m_pStream->GetChar();
int nChar = m_pStream->GetChar();
m_arrCompInfo[nIndex].nXResolution = (nChar >> 4) & 0x0f;
m_arrCompInfo[nIndex].nYResolution = nChar & 0x0f;
m_arrCompInfo[nIndex].nQuantTableNum = m_pStream->GetChar();
}
m_bProgressive = TRUE;
return TRUE;
}
BOOL DCTStream::ReadScanInfo()
{
int nComp = 0;
int nLength = Read16() - 2;
m_oCurScanInfo.nComponentsCount = m_pStream->GetChar();
if ( m_oCurScanInfo.nComponentsCount <= 0 || m_oCurScanInfo.nComponentsCount > 4 )
{
// TO DO: Error "Bad number of components in DCT stream"
m_oCurScanInfo.nComponentsCount = 0;
return FALSE;
}
--nLength;
if ( nLength != 2 * m_oCurScanInfo.nComponentsCount + 3 )
{
// TO DO: Error "Bad DCT scan info block"
return FALSE;
}
m_bInterleaved = m_oCurScanInfo.nComponentsCount == m_nComponentsCount;
for ( nComp = 0; nComp < m_nComponentsCount; ++nComp )
{
m_oCurScanInfo.arrbComponent[nComp] = FALSE;
}
for ( int nIndex = 0; nIndex < m_oCurScanInfo.nComponentsCount; ++nIndex )
{
int nID = m_pStream->GetChar();
// íåêîòîðûå(íåêîððåêòíûå) DCT ïîòîêè èñïîëüçóþò ñâîè ID ÷èñëà ìíîãî ðàç, íî êàê ìèíèìóì
// â ïîòîêå êîìïîíåíòû èäóò ïî ïîðÿäêó, ïîýòîìó ìû ñíà÷àëà ïðîâåðÿåì m_arrCompInfo[i], ÷òîáû
// ðåøèòü äàííóþ ïðîáåìó
if ( nID == m_arrCompInfo[nIndex].nID )
{
nComp = nIndex;
}
else
{
for ( nComp = 0; nComp < m_nComponentsCount; ++nComp )
{
if ( nID == m_arrCompInfo[nComp].nID )
{
break;
}
}
if ( nComp == m_nComponentsCount )
{
// TO DO: Error "Bad DCT component ID in scan info block"
return FALSE;
}
}
m_oCurScanInfo.arrbComponent[nComp] = TRUE;
int nChar = m_pStream->GetChar();
m_oCurScanInfo.arrDCHuffTable[nComp] = (nChar >> 4) & 0x0f;
m_oCurScanInfo.arrACHuffTable[nComp] = nChar & 0x0f;
}
m_oCurScanInfo.nFirstKoef = m_pStream->GetChar();
m_oCurScanInfo.nLastKoef = m_pStream->GetChar();
int nChar = m_pStream->GetChar();
m_oCurScanInfo.nApproxH = (nChar >> 4) & 0x0f;
m_oCurScanInfo.nApproxL = nChar & 0x0f;
return TRUE;
}
BOOL DCTStream::ReadQuantTables()
{
int nLength = Read16() - 2;
while ( nLength > 0 )
{
int nTableIndex = m_pStream->GetChar();
int nPrecision = (nTableIndex >> 4) & 0x0f;
nTableIndex &= 0x0f;
if ( nPrecision > 1 || nTableIndex >= 4 )
{
// TO DO: Error "Bad DCT quantization table"
return FALSE;
}
if ( nTableIndex == m_nQuantTablesCount )
{
m_nQuantTablesCount = nTableIndex + 1;
}
for (int nIndex = 0; nIndex < 64; ++nIndex )
{
if ( nPrecision )
{
m_arrQuantTables[nTableIndex][arrDCTZigZag[nIndex]] = Read16();
}
else
{
m_arrQuantTables[nTableIndex][arrDCTZigZag[nIndex]] = m_pStream->GetChar();
}
}
if ( nPrecision )
{
nLength -= 129;
}
else
{
nLength -= 65;
}
}
return TRUE;
}
BOOL DCTStream::ReadHuffmanTables()
{
int nLength = Read16() - 2;
while ( nLength > 0 )
{
int nTableIndex = m_pStream->GetChar();
--nLength;
if ( (nTableIndex & 0x0f) >= 4 )
{
// TO DO: Error "Bad DCT Huffman table"
return FALSE;
}
DCTHuffTable *pTable = NULL;
if ( nTableIndex & 0x10 )
{
nTableIndex &= 0x0f;
if ( nTableIndex >= m_nACHuffTablesCount )
m_nACHuffTablesCount = nTableIndex + 1;
pTable = &m_arrACHuffTables[nTableIndex];
}
else
{
nTableIndex &= 0x0f;
if ( nTableIndex >= m_nDCHuffTablesCount )
m_nDCHuffTablesCount = nTableIndex + 1;
pTable = &m_arrDCHuffTables[nTableIndex];
}
unsigned char nSymbol = 0;
unsigned short nCode = 0;
for ( int nIndex = 1; nIndex <= 16; ++nIndex )
{
int nChar = m_pStream->GetChar();
pTable->arrunFirstSymbol[nIndex] = nSymbol;
pTable->arrunFirstCode[nIndex] = nCode;
pTable->arrunCodesCount[nIndex] = nChar;
nSymbol += nChar;
nCode = (nCode + nChar) << 1;
}
nLength -= 16;
for ( int nIndex = 0; nIndex < nSymbol; ++nIndex )
pTable->arrunSymbols[nIndex] = m_pStream->GetChar();
nLength -= nSymbol;
}
return TRUE;
}
BOOL DCTStream::ReadRestartInterval()
{
int nLength = Read16();
if ( nLength != 4 )
{
// TO DO: Error "Bad DCT restart interval"
return FALSE;
}
m_nRestartInterval = Read16();
return TRUE;
}
BOOL DCTStream::ReadJFIFMarker()
{
char sBuffer[5];
int nLength = Read16();
nLength -= 2;
if ( nLength >= 5 )
{
for ( int nIndex = 0; nIndex < 5; ++nIndex )
{
int nChar = 0;
if ( ( nChar = m_pStream->GetChar() ) == EOF )
{
// TO DO: Error "Bad DCT APP0 marker"
return FALSE;
}
sBuffer[nIndex] = nChar;
}
nLength -= 5;
if ( !memcmp( sBuffer, "JFIF\0", 5) )
{
m_bJFIFMarker = TRUE;
}
}
while ( nLength > 0 )
{
if ( m_pStream->GetChar() == EOF )
{
// TO DO: Error "Bad DCT APP0 marker"
return FALSE;
}
--nLength;
}
return TRUE;
}
BOOL DCTStream::ReadAdobeMarker()
{
char sBuffer[12];
int nLength = Read16();
if ( nLength < 14 )
{
// TO DO: Error "Bad DCT Adobe APP14 marker"
return FALSE;
}
for ( int nIndex = 0; nIndex < 12; ++nIndex )
{
int nChar = 0;
if ( ( nChar = m_pStream->GetChar() ) == EOF)
{
// TO DO: Error "Bad DCT Adobe APP14 marker"
return FALSE;
}
sBuffer[nIndex] = nChar;
}
if ( strncmp( sBuffer, "Adobe", 5 ) )
{
// TO DO: Error "Bad DCT Adobe APP14 marker"
return FALSE;
}
m_nColorTransform = sBuffer[11];
m_bAdobeMarker = TRUE;
for ( int nIndex = 14; nIndex < nLength; ++nIndex )
{
if ( m_pStream->GetChar() == EOF )
{
// TO DO: Error "Bad DCT Adobe APP14 marker"
return FALSE;
}
}
return TRUE;
}
BOOL DCTStream::ReadTrailer()
{
int nChar = ReadMarker();
if ( nChar != 0xd9 ) // EOI
{
// TO DO: Error "Bad DCT trailer"
return FALSE;
}
return TRUE;
}
int DCTStream::ReadMarker()
{
int nChar = 0;
do {
do {
nChar = m_pStream->GetChar();
} while ( nChar != 0xff && nChar != EOF );
do {
nChar = m_pStream->GetChar();
} while ( nChar == 0xff );
} while ( nChar == 0x00 );
return nChar;
}
int DCTStream::Read16()
{
int nFirstChar = 0, nSecondChar = 0;
if ( ( nFirstChar = m_pStream->GetChar() ) == EOF )
return EOF;
if ( ( nSecondChar = m_pStream->GetChar() ) == EOF )
return EOF;
return (nFirstChar << 8) + nSecondChar;
}
StringExt *DCTStream::GetPSFilter(int nPSLevel, char *sIndent)
{
StringExt *seResult;
if ( nPSLevel < 2 )
{
return NULL;
}
if ( !( seResult = m_pStream->GetPSFilter( nPSLevel, sIndent) ) )
{
return NULL;
}
seResult->Append(sIndent)->Append("<< >> /DCTDecode filter\n");
return seResult;
}
BOOL DCTStream::IsBinary(BOOL bLast)
{
return m_pStream->IsBinary(TRUE);
}
//---------------------------------------------------------------------------------------------------------------
// FlateZlibStream
//---------------------------------------------------------------------------------------------------------------
FlateZlibStream::FlateZlibStream(Stream *pStream, int nPredictor, int nWidth, int nComponents, int nBitsPerComponent):
FilterStream(pStream)
{
if ( 1 != nPredictor )
{
m_pPredictor = new StreamPredictor( this, nPredictor, nWidth, nComponents, nBitsPerComponent);
if ( !m_pPredictor->CheckValidate() )
{
delete m_pPredictor;
m_pPredictor = NULL;
}
}
else
{
m_pPredictor = NULL;
}
memset( m_arrInBuffer, 0, flateZlibWindow );
memset( m_arrBuffer, 0, flateZlibWindow);
m_oZStream.zalloc = Z_NULL;
m_oZStream.zfree = Z_NULL;
m_oZStream.opaque = Z_NULL;
inflateInit( &m_oZStream );
}
FlateZlibStream::~FlateZlibStream()
{
if ( m_pPredictor )
{
delete m_pPredictor;
}
delete m_pStream;
inflateEnd( &m_oZStream );
}
void FlateZlibStream::Reset()
{
m_nBufferCurPos = 0;
m_nRemain = 0;
m_bEndOfBlock = TRUE;
m_bEOF = TRUE;
inflateEnd( &m_oZStream );
m_oZStream.zalloc = Z_NULL;
m_oZStream.zfree = Z_NULL;
m_oZStream.opaque = Z_NULL;
inflateInit( &m_oZStream );
m_pStream->Reset();
m_bEOF = FALSE;
}
int FlateZlibStream::GetChar()
{
if ( m_pPredictor )
{
return m_pPredictor->GetChar();
}
while ( m_nRemain == 0 )
{
if ( m_bEndOfBlock && m_bEOF )
return EOF;
ReadSome();
}
int nChar = m_arrBuffer[m_nBufferCurPos];
m_nBufferCurPos = (m_nBufferCurPos + 1) & flateZlibMask;
--m_nRemain;
return nChar;
}
int FlateZlibStream::LookChar()
{
if ( m_pPredictor )
{
return m_pPredictor->LookChar();
}
while ( m_nRemain == 0 )
{
if ( m_bEndOfBlock && m_bEOF )
return EOF;
ReadSome();
}
int nChar = m_arrBuffer[m_nBufferCurPos];
return nChar;
}
int FlateZlibStream::GetRawChar()
{
while ( m_nRemain == 0 )
{
if (m_bEndOfBlock && m_bEOF)
return EOF;
ReadSome();
}
int nChar = m_arrBuffer[m_nBufferCurPos];
m_nBufferCurPos = (m_nBufferCurPos + 1) & flateZlibMask;
--m_nRemain;
return nChar;
}
StringExt *FlateZlibStream::GetPSFilter(int nPSLevel, char *sIndent)
{
StringExt *seResult;
if ( nPSLevel < 3 || m_pPredictor )
{
return NULL;
}
if ( !( seResult = m_pStream->GetPSFilter( nPSLevel, sIndent) ) )
{
return NULL;
}
seResult->Append(sIndent)->Append("<< >> /FlateDecode filter\n");
return seResult;
}
BOOL FlateZlibStream::IsBinary(BOOL bLast)
{
return m_pStream->IsBinary(TRUE);
}
void FlateZlibStream::ReadSome()
{
unsigned int unInSize = flateZlibWindow;
if ( m_bEndOfBlock )
{
memset( m_arrInBuffer, 0, flateZlibWindow );
int nChar = 0;
for ( unsigned int unIndex = 0; unIndex < flateZlibWindow; unIndex++ )
{
nChar = m_pStream->GetChar();
if ( EOF == nChar )
{
unInSize = unIndex;
if ( 0 == unInSize )
{
m_nRemain = 0;
m_bEndOfBlock = m_bEOF = TRUE;
return;
}
break;
}
m_arrInBuffer[unIndex] = nChar;
}
m_oZStream.avail_in = unInSize;
m_oZStream.next_in = (Bytef *)m_arrInBuffer;
m_bEndOfBlock = FALSE;
}
m_oZStream.avail_out = flateZlibWindow;
m_oZStream.next_out = (Bytef *)m_arrBuffer;
int nRet = inflate( &m_oZStream, Z_NO_FLUSH );
if ( nRet == Z_DATA_ERROR || nRet == Z_MEM_ERROR )
{
m_nRemain = 0;
m_bEOF = m_bEndOfBlock = TRUE;
return;
}
m_nRemain = flateZlibWindow - m_oZStream.avail_out;
if ( m_oZStream.avail_out != 0 )
m_bEndOfBlock = TRUE;
return;
}
//---------------------------------------------------------------------------------------------------------------
// FlateStream
//---------------------------------------------------------------------------------------------------------------
int FlateStream::m_arrCodeLenCodeMap[flateMaxCodeLenCodes] =
{
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
};
FlateDecode FlateStream::m_arrLengthDecode[flateMaxLitCodes - 257] =
{
{0, 3},
{0, 4},
{0, 5},
{0, 6},
{0, 7},
{0, 8},
{0, 9},
{0, 10},
{1, 11},
{1, 13},
{1, 15},
{1, 17},
{2, 19},
{2, 23},
{2, 27},
{2, 31},
{3, 35},
{3, 43},
{3, 51},
{3, 59},
{4, 67},
{4, 83},
{4, 99},
{4, 115},
{5, 131},
{5, 163},
{5, 195},
{5, 227},
{0, 258},
{0, 258},
{0, 258}
};
FlateDecode FlateStream::m_arrDistanceDecode[flateMaxDistCodes] =
{
{ 0, 1},
{ 0, 2},
{ 0, 3},
{ 0, 4},
{ 1, 5},
{ 1, 7},
{ 2, 9},
{ 2, 13},
{ 3, 17},
{ 3, 25},
{ 4, 33},
{ 4, 49},
{ 5, 65},
{ 5, 97},
{ 6, 129},
{ 6, 193},
{ 7, 257},
{ 7, 385},
{ 8, 513},
{ 8, 769},
{ 9, 1025},
{ 9, 1537},
{10, 2049},
{10, 3073},
{11, 4097},
{11, 6145},
{12, 8193},
{12, 12289},
{13, 16385},
{13, 24577}
};
static FlateHuffmanCode c_arrFlateFixedLiteralCodeTableCodes[512] =
{
{7, 0x0100},
{8, 0x0050},
{8, 0x0010},
{8, 0x0118},
{7, 0x0110},
{8, 0x0070},
{8, 0x0030},
{9, 0x00c0},
{7, 0x0108},
{8, 0x0060},
{8, 0x0020},
{9, 0x00a0},
{8, 0x0000},
{8, 0x0080},
{8, 0x0040},
{9, 0x00e0},
{7, 0x0104},
{8, 0x0058},
{8, 0x0018},
{9, 0x0090},
{7, 0x0114},
{8, 0x0078},
{8, 0x0038},
{9, 0x00d0},
{7, 0x010c},
{8, 0x0068},
{8, 0x0028},
{9, 0x00b0},
{8, 0x0008},
{8, 0x0088},
{8, 0x0048},
{9, 0x00f0},
{7, 0x0102},
{8, 0x0054},
{8, 0x0014},
{8, 0x011c},
{7, 0x0112},
{8, 0x0074},
{8, 0x0034},
{9, 0x00c8},
{7, 0x010a},
{8, 0x0064},
{8, 0x0024},
{9, 0x00a8},
{8, 0x0004},
{8, 0x0084},
{8, 0x0044},
{9, 0x00e8},
{7, 0x0106},
{8, 0x005c},
{8, 0x001c},
{9, 0x0098},
{7, 0x0116},
{8, 0x007c},
{8, 0x003c},
{9, 0x00d8},
{7, 0x010e},
{8, 0x006c},
{8, 0x002c},
{9, 0x00b8},
{8, 0x000c},
{8, 0x008c},
{8, 0x004c},
{9, 0x00f8},
{7, 0x0101},
{8, 0x0052},
{8, 0x0012},
{8, 0x011a},
{7, 0x0111},
{8, 0x0072},
{8, 0x0032},
{9, 0x00c4},
{7, 0x0109},
{8, 0x0062},
{8, 0x0022},
{9, 0x00a4},
{8, 0x0002},
{8, 0x0082},
{8, 0x0042},
{9, 0x00e4},
{7, 0x0105},
{8, 0x005a},
{8, 0x001a},
{9, 0x0094},
{7, 0x0115},
{8, 0x007a},
{8, 0x003a},
{9, 0x00d4},
{7, 0x010d},
{8, 0x006a},
{8, 0x002a},
{9, 0x00b4},
{8, 0x000a},
{8, 0x008a},
{8, 0x004a},
{9, 0x00f4},
{7, 0x0103},
{8, 0x0056},
{8, 0x0016},
{8, 0x011e},
{7, 0x0113},
{8, 0x0076},
{8, 0x0036},
{9, 0x00cc},
{7, 0x010b},
{8, 0x0066},
{8, 0x0026},
{9, 0x00ac},
{8, 0x0006},
{8, 0x0086},
{8, 0x0046},
{9, 0x00ec},
{7, 0x0107},
{8, 0x005e},
{8, 0x001e},
{9, 0x009c},
{7, 0x0117},
{8, 0x007e},
{8, 0x003e},
{9, 0x00dc},
{7, 0x010f},
{8, 0x006e},
{8, 0x002e},
{9, 0x00bc},
{8, 0x000e},
{8, 0x008e},
{8, 0x004e},
{9, 0x00fc},
{7, 0x0100},
{8, 0x0051},
{8, 0x0011},
{8, 0x0119},
{7, 0x0110},
{8, 0x0071},
{8, 0x0031},
{9, 0x00c2},
{7, 0x0108},
{8, 0x0061},
{8, 0x0021},
{9, 0x00a2},
{8, 0x0001},
{8, 0x0081},
{8, 0x0041},
{9, 0x00e2},
{7, 0x0104},
{8, 0x0059},
{8, 0x0019},
{9, 0x0092},
{7, 0x0114},
{8, 0x0079},
{8, 0x0039},
{9, 0x00d2},
{7, 0x010c},
{8, 0x0069},
{8, 0x0029},
{9, 0x00b2},
{8, 0x0009},
{8, 0x0089},
{8, 0x0049},
{9, 0x00f2},
{7, 0x0102},
{8, 0x0055},
{8, 0x0015},
{8, 0x011d},
{7, 0x0112},
{8, 0x0075},
{8, 0x0035},
{9, 0x00ca},
{7, 0x010a},
{8, 0x0065},
{8, 0x0025},
{9, 0x00aa},
{8, 0x0005},
{8, 0x0085},
{8, 0x0045},
{9, 0x00ea},
{7, 0x0106},
{8, 0x005d},
{8, 0x001d},
{9, 0x009a},
{7, 0x0116},
{8, 0x007d},
{8, 0x003d},
{9, 0x00da},
{7, 0x010e},
{8, 0x006d},
{8, 0x002d},
{9, 0x00ba},
{8, 0x000d},
{8, 0x008d},
{8, 0x004d},
{9, 0x00fa},
{7, 0x0101},
{8, 0x0053},
{8, 0x0013},
{8, 0x011b},
{7, 0x0111},
{8, 0x0073},
{8, 0x0033},
{9, 0x00c6},
{7, 0x0109},
{8, 0x0063},
{8, 0x0023},
{9, 0x00a6},
{8, 0x0003},
{8, 0x0083},
{8, 0x0043},
{9, 0x00e6},
{7, 0x0105},
{8, 0x005b},
{8, 0x001b},
{9, 0x0096},
{7, 0x0115},
{8, 0x007b},
{8, 0x003b},
{9, 0x00d6},
{7, 0x010d},
{8, 0x006b},
{8, 0x002b},
{9, 0x00b6},
{8, 0x000b},
{8, 0x008b},
{8, 0x004b},
{9, 0x00f6},
{7, 0x0103},
{8, 0x0057},
{8, 0x0017},
{8, 0x011f},
{7, 0x0113},
{8, 0x0077},
{8, 0x0037},
{9, 0x00ce},
{7, 0x010b},
{8, 0x0067},
{8, 0x0027},
{9, 0x00ae},
{8, 0x0007},
{8, 0x0087},
{8, 0x0047},
{9, 0x00ee},
{7, 0x0107},
{8, 0x005f},
{8, 0x001f},
{9, 0x009e},
{7, 0x0117},
{8, 0x007f},
{8, 0x003f},
{9, 0x00de},
{7, 0x010f},
{8, 0x006f},
{8, 0x002f},
{9, 0x00be},
{8, 0x000f},
{8, 0x008f},
{8, 0x004f},
{9, 0x00fe},
{7, 0x0100},
{8, 0x0050},
{8, 0x0010},
{8, 0x0118},
{7, 0x0110},
{8, 0x0070},
{8, 0x0030},
{9, 0x00c1},
{7, 0x0108},
{8, 0x0060},
{8, 0x0020},
{9, 0x00a1},
{8, 0x0000},
{8, 0x0080},
{8, 0x0040},
{9, 0x00e1},
{7, 0x0104},
{8, 0x0058},
{8, 0x0018},
{9, 0x0091},
{7, 0x0114},
{8, 0x0078},
{8, 0x0038},
{9, 0x00d1},
{7, 0x010c},
{8, 0x0068},
{8, 0x0028},
{9, 0x00b1},
{8, 0x0008},
{8, 0x0088},
{8, 0x0048},
{9, 0x00f1},
{7, 0x0102},
{8, 0x0054},
{8, 0x0014},
{8, 0x011c},
{7, 0x0112},
{8, 0x0074},
{8, 0x0034},
{9, 0x00c9},
{7, 0x010a},
{8, 0x0064},
{8, 0x0024},
{9, 0x00a9},
{8, 0x0004},
{8, 0x0084},
{8, 0x0044},
{9, 0x00e9},
{7, 0x0106},
{8, 0x005c},
{8, 0x001c},
{9, 0x0099},
{7, 0x0116},
{8, 0x007c},
{8, 0x003c},
{9, 0x00d9},
{7, 0x010e},
{8, 0x006c},
{8, 0x002c},
{9, 0x00b9},
{8, 0x000c},
{8, 0x008c},
{8, 0x004c},
{9, 0x00f9},
{7, 0x0101},
{8, 0x0052},
{8, 0x0012},
{8, 0x011a},
{7, 0x0111},
{8, 0x0072},
{8, 0x0032},
{9, 0x00c5},
{7, 0x0109},
{8, 0x0062},
{8, 0x0022},
{9, 0x00a5},
{8, 0x0002},
{8, 0x0082},
{8, 0x0042},
{9, 0x00e5},
{7, 0x0105},
{8, 0x005a},
{8, 0x001a},
{9, 0x0095},
{7, 0x0115},
{8, 0x007a},
{8, 0x003a},
{9, 0x00d5},
{7, 0x010d},
{8, 0x006a},
{8, 0x002a},
{9, 0x00b5},
{8, 0x000a},
{8, 0x008a},
{8, 0x004a},
{9, 0x00f5},
{7, 0x0103},
{8, 0x0056},
{8, 0x0016},
{8, 0x011e},
{7, 0x0113},
{8, 0x0076},
{8, 0x0036},
{9, 0x00cd},
{7, 0x010b},
{8, 0x0066},
{8, 0x0026},
{9, 0x00ad},
{8, 0x0006},
{8, 0x0086},
{8, 0x0046},
{9, 0x00ed},
{7, 0x0107},
{8, 0x005e},
{8, 0x001e},
{9, 0x009d},
{7, 0x0117},
{8, 0x007e},
{8, 0x003e},
{9, 0x00dd},
{7, 0x010f},
{8, 0x006e},
{8, 0x002e},
{9, 0x00bd},
{8, 0x000e},
{8, 0x008e},
{8, 0x004e},
{9, 0x00fd},
{7, 0x0100},
{8, 0x0051},
{8, 0x0011},
{8, 0x0119},
{7, 0x0110},
{8, 0x0071},
{8, 0x0031},
{9, 0x00c3},
{7, 0x0108},
{8, 0x0061},
{8, 0x0021},
{9, 0x00a3},
{8, 0x0001},
{8, 0x0081},
{8, 0x0041},
{9, 0x00e3},
{7, 0x0104},
{8, 0x0059},
{8, 0x0019},
{9, 0x0093},
{7, 0x0114},
{8, 0x0079},
{8, 0x0039},
{9, 0x00d3},
{7, 0x010c},
{8, 0x0069},
{8, 0x0029},
{9, 0x00b3},
{8, 0x0009},
{8, 0x0089},
{8, 0x0049},
{9, 0x00f3},
{7, 0x0102},
{8, 0x0055},
{8, 0x0015},
{8, 0x011d},
{7, 0x0112},
{8, 0x0075},
{8, 0x0035},
{9, 0x00cb},
{7, 0x010a},
{8, 0x0065},
{8, 0x0025},
{9, 0x00ab},
{8, 0x0005},
{8, 0x0085},
{8, 0x0045},
{9, 0x00eb},
{7, 0x0106},
{8, 0x005d},
{8, 0x001d},
{9, 0x009b},
{7, 0x0116},
{8, 0x007d},
{8, 0x003d},
{9, 0x00db},
{7, 0x010e},
{8, 0x006d},
{8, 0x002d},
{9, 0x00bb},
{8, 0x000d},
{8, 0x008d},
{8, 0x004d},
{9, 0x00fb},
{7, 0x0101},
{8, 0x0053},
{8, 0x0013},
{8, 0x011b},
{7, 0x0111},
{8, 0x0073},
{8, 0x0033},
{9, 0x00c7},
{7, 0x0109},
{8, 0x0063},
{8, 0x0023},
{9, 0x00a7},
{8, 0x0003},
{8, 0x0083},
{8, 0x0043},
{9, 0x00e7},
{7, 0x0105},
{8, 0x005b},
{8, 0x001b},
{9, 0x0097},
{7, 0x0115},
{8, 0x007b},
{8, 0x003b},
{9, 0x00d7},
{7, 0x010d},
{8, 0x006b},
{8, 0x002b},
{9, 0x00b7},
{8, 0x000b},
{8, 0x008b},
{8, 0x004b},
{9, 0x00f7},
{7, 0x0103},
{8, 0x0057},
{8, 0x0017},
{8, 0x011f},
{7, 0x0113},
{8, 0x0077},
{8, 0x0037},
{9, 0x00cf},
{7, 0x010b},
{8, 0x0067},
{8, 0x0027},
{9, 0x00af},
{8, 0x0007},
{8, 0x0087},
{8, 0x0047},
{9, 0x00ef},
{7, 0x0107},
{8, 0x005f},
{8, 0x001f},
{9, 0x009f},
{7, 0x0117},
{8, 0x007f},
{8, 0x003f},
{9, 0x00df},
{7, 0x010f},
{8, 0x006f},
{8, 0x002f},
{9, 0x00bf},
{8, 0x000f},
{8, 0x008f},
{8, 0x004f},
{9, 0x00ff}
};
FlateHuffmanTable FlateStream::m_oFixedLiteralCodeTable =
{
c_arrFlateFixedLiteralCodeTableCodes, 9
};
static FlateHuffmanCode c_arrFlateFixedDistanceCodeTableCodes[32] =
{
{5, 0x0000},
{5, 0x0010},
{5, 0x0008},
{5, 0x0018},
{5, 0x0004},
{5, 0x0014},
{5, 0x000c},
{5, 0x001c},
{5, 0x0002},
{5, 0x0012},
{5, 0x000a},
{5, 0x001a},
{5, 0x0006},
{5, 0x0016},
{5, 0x000e},
{0, 0x0000},
{5, 0x0001},
{5, 0x0011},
{5, 0x0009},
{5, 0x0019},
{5, 0x0005},
{5, 0x0015},
{5, 0x000d},
{5, 0x001d},
{5, 0x0003},
{5, 0x0013},
{5, 0x000b},
{5, 0x001b},
{5, 0x0007},
{5, 0x0017},
{5, 0x000f},
{0, 0x0000}
};
FlateHuffmanTable FlateStream::m_oFixedDistanceCodeTable =
{
c_arrFlateFixedDistanceCodeTableCodes, 5
};
FlateStream::FlateStream(Stream *pStream, int nPredictor, int nWidth, int nComponents, int nBitsPerComponent):
FilterStream(pStream)
{
if ( 1 != nPredictor )
{
m_pPredictor = new StreamPredictor( this, nPredictor, nWidth, nComponents, nBitsPerComponent);
if ( !m_pPredictor->CheckValidate() )
{
delete m_pPredictor;
m_pPredictor = NULL;
}
}
else
{
m_pPredictor = NULL;
}
m_oLiteratCodeTable.pCodes = NULL;
m_oDistanceCodeTable.pCodes = NULL;
memset( m_arrBuffer, 0, flateWindow);
}
FlateStream::~FlateStream()
{
if ( m_oLiteratCodeTable.pCodes != m_oFixedLiteralCodeTable.pCodes )
{
MemUtilsFree( m_oLiteratCodeTable.pCodes );
}
if ( m_oDistanceCodeTable.pCodes != m_oFixedDistanceCodeTable.pCodes )
{
MemUtilsFree( m_oDistanceCodeTable.pCodes );
}
if ( m_pPredictor )
{
delete m_pPredictor;
}
delete m_pStream;
}
void FlateStream::Reset()
{
m_nBufferCurPos = 0;
m_nRemain = 0;
m_nCodeBuffer = 0;
m_nCodeSize = 0;
m_bCompressedBlock = FALSE;
m_bEndOfBlock = TRUE;
m_bEOF = TRUE;
m_pStream->Reset();
m_bEndOfBlock = m_bEOF = TRUE;
//÷èòàåì çàãîëîâîê
int nCmf = m_pStream->GetChar();
int nFlag = m_pStream->GetChar();
if ( nCmf == EOF || nFlag == EOF )
return;
if ( ( nCmf & 0x0f ) != 0x08 )
{
//TO DO: Error "Unknown compression method in flate stream"
return;
}
if ((( (nCmf << 8) + nFlag ) % 31) != 0)
{
// TO DO: Error "Bad FCHECK in flate stream"
return;
}
if ( nFlag & 0x20 )
{
//TO DO: Error "FDICT bit set in flate stream"
return;
}
m_bEOF = FALSE;
}
int FlateStream::GetChar()
{
if ( m_pPredictor )
{
return m_pPredictor->GetChar();
}
while ( m_nRemain == 0 )
{
if ( m_bEndOfBlock && m_bEOF )
return EOF;
ReadSome();
}
int nChar = m_arrBuffer[m_nBufferCurPos];
m_nBufferCurPos = (m_nBufferCurPos + 1) & flateMask;
--m_nRemain;
return nChar;
}
int FlateStream::LookChar()
{
if ( m_pPredictor )
{
return m_pPredictor->LookChar();
}
while ( m_nRemain == 0 )
{
if ( m_bEndOfBlock && m_bEOF )
return EOF;
ReadSome();
}
int nChar = m_arrBuffer[m_nBufferCurPos];
return nChar;
}
int FlateStream::GetRawChar()
{
while ( m_nRemain == 0 )
{
if (m_bEndOfBlock && m_bEOF)
return EOF;
ReadSome();
}
int nChar = m_arrBuffer[m_nBufferCurPos];
m_nBufferCurPos = (m_nBufferCurPos + 1) & flateMask;
--m_nRemain;
return nChar;
}
StringExt *FlateStream::GetPSFilter(int nPSLevel, char *sIndent)
{
StringExt *seResult;
if ( nPSLevel < 3 || m_pPredictor )
{
return NULL;
}
if ( !( seResult = m_pStream->GetPSFilter( nPSLevel, sIndent) ) )
{
return NULL;
}
seResult->Append(sIndent)->Append("<< >> /FlateDecode filter\n");
return seResult;
}
BOOL FlateStream::IsBinary(BOOL bLast)
{
return m_pStream->IsBinary(TRUE);
}
void FlateStream::ReadSome()
{
int nFirst = 0, nSecond = 0;
if ( m_bEndOfBlock )
{
if ( !StartBlock() )
return;
}
if ( m_bCompressedBlock )
{
int nHuffCode = 0;
if ( ( nHuffCode = GetHuffmanCodeWord(&m_oLiteratCodeTable) ) == EOF )
{
// TO DO: Error "Unexpected end of file in flate stream"
m_bEndOfBlock = m_bEOF = TRUE;
m_nRemain = 0;
}
if ( nHuffCode < 256 )
{
m_arrBuffer[m_nBufferCurPos] = nHuffCode;
m_nRemain = 1;
}
else if ( nHuffCode == 256 )
{
m_bEndOfBlock = TRUE;
m_nRemain = 0;
}
else
{
nHuffCode -= 257;
int nExtraCode = m_arrLengthDecode[nHuffCode].nExtraBitsCount;
if ( nExtraCode > 0 && ( nExtraCode = GetCodeWord(nExtraCode) ) == EOF )
{
// TO DO: Error "Unexpected end of file in flate stream"
m_bEndOfBlock = m_bEOF = TRUE;
m_nRemain = 0;
}
int nLen = m_arrLengthDecode[nHuffCode].nFirst + nExtraCode;
if ( ( nHuffCode = GetHuffmanCodeWord(&m_oDistanceCodeTable) ) == EOF )
{
// TO DO: Error "Unexpected end of file in flate stream"
m_bEndOfBlock = m_bEOF = TRUE;
m_nRemain = 0;
}
nExtraCode = m_arrDistanceDecode[nHuffCode].nExtraBitsCount;
if ( nExtraCode > 0 && ( nExtraCode = GetCodeWord(nExtraCode) ) == EOF )
{
// TO DO: Error "Unexpected end of file in flate stream"
m_bEndOfBlock = m_bEOF = TRUE;
m_nRemain = 0;
}
int nDistance = m_arrDistanceDecode[nHuffCode].nFirst + nExtraCode;
nFirst = m_nBufferCurPos;
nSecond = (m_nBufferCurPos - nDistance) & flateMask;
for ( int nK = 0; nK < nLen; ++nK)
{
m_arrBuffer[nFirst] = m_arrBuffer[nSecond];
nFirst = (nFirst + 1) & flateMask;
nSecond = (nSecond + 1) & flateMask;
}
m_nRemain = nLen;
}
}
else
{
int nLen = (m_nUncompBlockLen < flateWindow) ? m_nUncompBlockLen : flateWindow;
for ( nFirst = 0, nSecond = m_nBufferCurPos; nFirst < nLen; ++nFirst, nSecond = (nSecond + 1) & flateMask)
{
int nChar = 0;
if ( (nChar = m_pStream->GetChar()) == EOF )
{
m_bEndOfBlock = m_bEOF = TRUE;
break;
}
m_arrBuffer[nSecond] = nChar & 0xff;
}
m_nRemain = nFirst;
m_nUncompBlockLen -= nLen;
if ( m_nUncompBlockLen == 0 )
m_bEndOfBlock = TRUE;
}
return;
}
BOOL FlateStream::StartBlock()
{
// Îñâîáîæäàåì òàáëèöû êîäîâ èç ïðåäûäóùåãî áëîêà
if ( m_oLiteratCodeTable.pCodes != m_oFixedLiteralCodeTable.pCodes )
{
MemUtilsFree( m_oLiteratCodeTable.pCodes );
}
m_oLiteratCodeTable.pCodes = NULL;
if ( m_oDistanceCodeTable.pCodes != m_oFixedDistanceCodeTable.pCodes )
{
MemUtilsFree( m_oDistanceCodeTable.pCodes );
}
m_oDistanceCodeTable.pCodes = NULL;
// Ñ÷èòûâàåì çàãîëîâîê áëîêà
int nBlockHeader = GetCodeWord(3);
if ( nBlockHeader & 1)
m_bEOF = TRUE;
nBlockHeader >>= 1;
if ( nBlockHeader == 0 ) // uncompressed block
{
m_bCompressedBlock = FALSE;
int nChar = 0;
if ( ( nChar = m_pStream->GetChar() ) == EOF )
{
// TO DO: Error "Bad block header in flate stream"
m_bEndOfBlock = m_bEOF = TRUE;
return FALSE;
}
m_nUncompBlockLen = nChar & 0xff;
if ( ( nChar = m_pStream->GetChar() ) == EOF )
{
// TO DO: Error "Bad block header in flate stream"
m_bEndOfBlock = m_bEOF = TRUE;
return FALSE;
}
m_nUncompBlockLen |= (nChar & 0xff) << 8;
if ( ( nChar = m_pStream->GetChar() ) == EOF )
{
// TO DO: Error "Bad block header in flate stream"
m_bEndOfBlock = m_bEOF = TRUE;
return FALSE;
}
int nCheck = nChar & 0xff;
if ( ( nChar = m_pStream->GetChar() ) == EOF )
{
// TO DO: Error "Bad block header in flate stream"
m_bEndOfBlock = m_bEOF = TRUE;
return FALSE;
}
nCheck |= (nChar & 0xff) << 8;
if ( nCheck != (~m_nUncompBlockLen & 0xffff) )
{
// TO DO: Error "Bad uncompressed block length in flate stream"
}
m_nCodeBuffer = 0;
m_nCodeSize = 0;
}
else if ( nBlockHeader == 1 ) // compressed block with fixed codes
{
m_bCompressedBlock = TRUE;
LoadFixedCodes();
}
else if ( nBlockHeader == 2 ) // compressed block with dynamic codes
{
m_bCompressedBlock = TRUE;
if ( !ReadDynamicCodes() )
{
// TO DO: Error "Bad block header in flate stream"
m_bEndOfBlock = m_bEOF = TRUE;
return FALSE;
}
}
else // unknown block type
{
// TO DO: Error "Bad block header in flate stream"
m_bEndOfBlock = m_bEOF = TRUE;
return FALSE;
}
m_bEndOfBlock = FALSE;
return TRUE;
}
void FlateStream::LoadFixedCodes()
{
m_oLiteratCodeTable.pCodes = m_oFixedLiteralCodeTable.pCodes;
m_oLiteratCodeTable.nMaxLen = m_oFixedLiteralCodeTable.nMaxLen;
m_oDistanceCodeTable.pCodes = m_oFixedDistanceCodeTable.pCodes;
m_oDistanceCodeTable.nMaxLen = m_oFixedDistanceCodeTable.nMaxLen;
}
BOOL FlateStream::ReadDynamicCodes()
{
int arrCodeLenCodeLengths[flateMaxCodeLenCodes];
FlateHuffmanTable oCodeLenCodeTable;
oCodeLenCodeTable.pCodes = NULL;
// Lengths
int nNumLiteralCodes = 0;
if ( ( nNumLiteralCodes = GetCodeWord(5) ) == EOF )
{
// TO DO: Error "Bad dynamic code table in flate stream"
MemUtilsFree( oCodeLenCodeTable.pCodes);
return FALSE;
}
nNumLiteralCodes += 257;
int nNumDistanceCodes = 0;
if ( ( nNumDistanceCodes = GetCodeWord(5) ) == EOF )
{
// TO DO: Error "Bad dynamic code table in flate stream"
MemUtilsFree( oCodeLenCodeTable.pCodes);
return FALSE;
}
nNumDistanceCodes += 1;
int nNumCodeLenCodes = 0;
if ( ( nNumCodeLenCodes = GetCodeWord(4) ) == EOF )
{
// TO DO: Error "Bad dynamic code table in flate stream"
MemUtilsFree( oCodeLenCodeTable.pCodes);
return FALSE;
}
nNumCodeLenCodes += 4;
if ( nNumLiteralCodes > flateMaxLitCodes || nNumDistanceCodes > flateMaxDistCodes || nNumCodeLenCodes > flateMaxCodeLenCodes )
{
// TO DO: Error "Bad dynamic code table in flate stream"
MemUtilsFree( oCodeLenCodeTable.pCodes);
return FALSE;
}
// code length code table
for ( int nI = 0; nI < flateMaxCodeLenCodes; ++nI )
{
arrCodeLenCodeLengths[nI] = 0;
}
for ( int nI = 0; nI < nNumCodeLenCodes; ++nI )
{
if ( ( arrCodeLenCodeLengths[m_arrCodeLenCodeMap[nI]] = GetCodeWord(3) ) == -1 )
{
// TO DO: Error "Bad dynamic code table in flate stream"
MemUtilsFree( oCodeLenCodeTable.pCodes);
return FALSE;
}
}
ConvertHuffmanCodes( arrCodeLenCodeLengths, flateMaxCodeLenCodes, &oCodeLenCodeTable);
// Literal, distance code tables
int nLen = 0;
int nRepeat = 0;
int nIndex = 0;
int nCurCode = 0;
while ( nIndex < nNumLiteralCodes + nNumDistanceCodes )
{
if ( ( nCurCode = GetHuffmanCodeWord(&oCodeLenCodeTable) ) == EOF )
{
// TO DO: Error "Bad dynamic code table in flate stream"
MemUtilsFree( oCodeLenCodeTable.pCodes);
return FALSE;
}
if ( nCurCode == 16 )
{
if ( ( nRepeat = GetCodeWord(2) ) == EOF )
{
// TO DO: Error "Bad dynamic code table in flate stream"
MemUtilsFree( oCodeLenCodeTable.pCodes);
return FALSE;
}
nRepeat += 3;
if ( nIndex + nRepeat > nNumLiteralCodes + nNumDistanceCodes )
{
// TO DO: Error "Bad dynamic code table in flate stream"
MemUtilsFree( oCodeLenCodeTable.pCodes);
return FALSE;
}
for (; nRepeat > 0; --nRepeat)
{
m_arrCodeLengths[nIndex++] = nLen;
}
}
else if ( nCurCode == 17 )
{
if ( ( nRepeat = GetCodeWord(3) ) == EOF )
{
// TO DO: Error "Bad dynamic code table in flate stream"
MemUtilsFree( oCodeLenCodeTable.pCodes);
return FALSE;
}
nRepeat += 3;
if ( nIndex + nRepeat > nNumLiteralCodes + nNumDistanceCodes )
{
// TO DO: Error "Bad dynamic code table in flate stream"
MemUtilsFree( oCodeLenCodeTable.pCodes);
return FALSE;
}
nLen = 0;
for (; nRepeat > 0; --nRepeat)
{
m_arrCodeLengths[nIndex++] = 0;
}
}
else if ( nCurCode == 18 )
{
if ( ( nRepeat = GetCodeWord(7) ) == EOF )
{
// TO DO: Error "Bad dynamic code table in flate stream"
MemUtilsFree( oCodeLenCodeTable.pCodes);
return FALSE;
}
nRepeat += 11;
if ( nIndex + nRepeat > nNumLiteralCodes + nNumDistanceCodes )
{
// TO DO: Error "Bad dynamic code table in flate stream"
MemUtilsFree( oCodeLenCodeTable.pCodes);
return FALSE;
}
nLen = 0;
for (; nRepeat > 0; --nRepeat)
{
m_arrCodeLengths[nIndex++] = 0;
}
}
else
{
m_arrCodeLengths[nIndex++] = nLen = nCurCode;
}
}
ConvertHuffmanCodes( m_arrCodeLengths, nNumLiteralCodes, &m_oLiteratCodeTable);
ConvertHuffmanCodes( m_arrCodeLengths + nNumLiteralCodes, nNumDistanceCodes, &m_oDistanceCodeTable);
MemUtilsFree( oCodeLenCodeTable.pCodes);
return TRUE;
}
// Êîíâåðòèðóåì ìàññèâ <pLengths>, â òàáëèöó Õàôôìàíà(ñîðòèðóÿ ïî çíà÷åíèÿì)
void FlateStream::ConvertHuffmanCodes(int *pLengths, int nCount, FlateHuffmanTable *pTable)
{
// Èùåì ìàêèìàëüíûé ýëåìåíò
pTable->nMaxLen = 0;
for ( int nValue = 0; nValue < nCount; ++nValue)
{
if ( pLengths[nValue] > pTable->nMaxLen)
{
pTable->nMaxLen = pLengths[nValue];
}
}
// Âûäåëÿåì ìåñòî äëÿ òàáëèöû
int nTableSize = 1 << pTable->nMaxLen;
pTable->pCodes = (FlateHuffmanCode *)MemUtilsMallocArray( nTableSize, sizeof(FlateHuffmanCode));
// Î÷èùàåì òàáëèöó
for ( int nIndex = 0; nIndex < nTableSize; ++nIndex)
{
pTable->pCodes[nIndex].nLength = 0;
pTable->pCodes[nIndex].nValue = 0;
}
// Çàïîëíÿåì òàáëèöó
int nLen = 0, nSkip = 0, nCode = 0;
for (nLen = 1, nCode = 0, nSkip = 2; nLen <= pTable->nMaxLen; ++nLen, nCode <<= 1, nSkip <<= 1)
{
for (int nValue = 0; nValue < nCount; ++nValue )
{
if ( pLengths[nValue] == nLen )
{
// bit-reverse code
int nReverseCode = 0;
int nTemp = nCode;
for ( int nIndex = 0; nIndex < nLen; ++nIndex)
{
nReverseCode = (nReverseCode << 1) | (nTemp & 1);
nTemp >>= 1;
}
for ( int nIndex = nReverseCode; nIndex < nTableSize; nIndex += nSkip)
{
pTable->pCodes[nIndex].nLength = (unsigned short)nLen;
pTable->pCodes[nIndex].nValue = (unsigned short)nValue;
}
++nCode;
}
}
}
}
int FlateStream::GetHuffmanCodeWord(FlateHuffmanTable *pTable)
{
while ( m_nCodeSize < pTable->nMaxLen )
{
int nChar = 0;
if ( ( nChar = m_pStream->GetChar() ) == EOF )
{
break;
}
m_nCodeBuffer |= (nChar & 0xff) << m_nCodeSize;
m_nCodeSize += 8;
}
FlateHuffmanCode *pHuffCode = &pTable->pCodes[m_nCodeBuffer & ((1 << pTable->nMaxLen) - 1)];
if ( m_nCodeSize == 0 || m_nCodeSize < pHuffCode->nLength || pHuffCode->nLength == 0 )
{
return EOF;
}
m_nCodeBuffer >>= pHuffCode->nLength;
m_nCodeSize -= pHuffCode->nLength;
return (int)pHuffCode->nValue;
}
int FlateStream::GetCodeWord(int nBits)
{
int nChar = 0;
while ( m_nCodeSize < nBits )
{
if ( ( nChar = m_pStream->GetChar() ) == EOF )
return EOF;
m_nCodeBuffer |= (nChar & 0xff) << m_nCodeSize;
m_nCodeSize += 8;
}
nChar = m_nCodeBuffer & ((1 << nBits) - 1);
m_nCodeBuffer >>= nBits;
m_nCodeSize -= nBits;
return nChar;
}
//---------------------------------------------------------------------------------------------------------------
// EOFStream
//---------------------------------------------------------------------------------------------------------------
EOFStream::EOFStream(Stream *pStream):
FilterStream(pStream)
{
}
EOFStream::~EOFStream()
{
delete m_pStream;
}
//---------------------------------------------------------------------------------------------------------------
// FixedLengthEncoder
//---------------------------------------------------------------------------------------------------------------
FixedLengthEncoder::FixedLengthEncoder(Stream *pStream, int nLength):
FilterStream(pStream)
{
m_nLength = nLength;
m_nCount = 0;
}
FixedLengthEncoder::~FixedLengthEncoder()
{
if ( m_pStream->IsEncoder() )
delete m_pStream;
}
void FixedLengthEncoder::Reset()
{
m_pStream->Reset();
m_nCount = 0;
}
int FixedLengthEncoder::GetChar()
{
if ( m_nLength >= 0 && m_nCount >= m_nLength )
return EOF;
++m_nCount;
return m_pStream->GetChar();
}
int FixedLengthEncoder::LookChar()
{
if ( m_nLength >= 0 && m_nCount >= m_nLength )
return EOF;
return m_pStream->GetChar();
}
BOOL FixedLengthEncoder::IsBinary(BOOL bLast)
{
return m_pStream->IsBinary(TRUE);
}
//---------------------------------------------------------------------------------------------------------------
// ASCIIHexEncoder
//---------------------------------------------------------------------------------------------------------------
ASCIIHexEncoder::ASCIIHexEncoder(Stream *pStream):
FilterStream(pStream)
{
m_pBufferPointer = m_pBufferEnd = m_sBuffer;
m_nLineLength = 0;
m_bEOF = FALSE;
}
ASCIIHexEncoder::~ASCIIHexEncoder()
{
if ( m_pStream->IsEncoder() )
delete m_pStream;
}
void ASCIIHexEncoder::Reset()
{
m_pStream->Reset();
m_pBufferPointer = m_pBufferEnd = m_sBuffer;
m_nLineLength = 0;
m_bEOF = FALSE;
}
BOOL ASCIIHexEncoder::FillBuffer()
{
static char *c_sHex = "0123456789abcdef";
if ( m_bEOF )
{
return FALSE;
}
m_pBufferPointer = m_pBufferEnd = m_sBuffer;
int nChar = 0;
if ( ( nChar = m_pStream->GetChar() ) == EOF )
{
*m_pBufferEnd++ = '>';
m_bEOF = TRUE;
}
else
{
if ( m_nLineLength >= 64 )
{
*m_pBufferEnd++ = '\n';
m_nLineLength = 0;
}
*m_pBufferEnd++ = c_sHex[(nChar >> 4) & 0x0f];
*m_pBufferEnd++ = c_sHex[nChar & 0x0f];
m_nLineLength += 2;
}
return TRUE;
}
//---------------------------------------------------------------------------------------------------------------
// ASCII85Encoder
//---------------------------------------------------------------------------------------------------------------
ASCII85Encoder::ASCII85Encoder(Stream *pStream):
FilterStream(pStream)
{
m_pBufferPointer = m_pBufferEnd = m_sBuffer;
m_nLineLength = 0;
m_bEOF = FALSE;
}
ASCII85Encoder::~ASCII85Encoder()
{
if ( m_pStream->IsEncoder() )
delete m_pStream;
}
void ASCII85Encoder::Reset()
{
m_pStream->Reset();
m_pBufferPointer = m_pBufferEnd = m_sBuffer;
m_nLineLength = 0;
m_bEOF = FALSE;
}
BOOL ASCII85Encoder::FillBuffer()
{
unsigned long unTemp = 0;
char arrB[5];
int arrC[4] = { 0, 0, 0, 0};
int nLen = 0;
if ( m_bEOF )
{
return FALSE;
}
arrC[0] = m_pStream->GetChar();
arrC[1] = m_pStream->GetChar();
arrC[2] = m_pStream->GetChar();
arrC[3] = m_pStream->GetChar();
m_pBufferPointer = m_pBufferEnd = m_sBuffer;
if ( arrC[3] == EOF )
{
if ( arrC[0] == EOF )
{
nLen = 0;
unTemp = 0;
}
else
{
if ( arrC[1] == EOF )
{
nLen = 1;
unTemp = arrC[0] << 24;
}
else if ( arrC[2] == EOF )
{
nLen = 2;
unTemp = ( arrC[0] << 24 ) | ( arrC[1] << 16 );
}
else
{
nLen = 3;
unTemp = ( arrC[0] << 24 ) | ( arrC[1] << 16 ) | ( arrC[2] << 8 );
}
for ( int nIndex = 4; nIndex >= 0; --nIndex )
{
arrB[nIndex] = (char)(unTemp % 85 + 0x21);
unTemp /= 85;
}
for ( int nIndex = 0; nIndex <= nLen; ++nIndex )
{
*m_pBufferEnd++ = arrB[nIndex];
if (++m_nLineLength == 65)
{
*m_pBufferEnd++ = '\n';
m_nLineLength = 0;
}
}
}
*m_pBufferEnd++ = '~';
*m_pBufferEnd++ = '>';
m_bEOF = TRUE;
}
else
{
unTemp = ( arrC[0] << 24 ) | ( arrC[1] << 16 ) | ( arrC[2] << 8 ) | arrC[3];
if ( unTemp == 0 )
{
*m_pBufferEnd++ = 'z';
if ( ++m_nLineLength == 65 )
{
*m_pBufferEnd++ = '\n';
m_nLineLength = 0;
}
}
else
{
for ( int nIndex = 4; nIndex >= 0; --nIndex)
{
arrB[nIndex] = (char)(unTemp % 85 + 0x21);
unTemp /= 85;
}
for ( int nIndex = 0; nIndex <= 4; ++nIndex)
{
*m_pBufferEnd++ = arrB[nIndex];
if (++m_nLineLength == 65)
{
*m_pBufferEnd++ = '\n';
m_nLineLength = 0;
}
}
}
}
return TRUE;
}
//---------------------------------------------------------------------------------------------------------------
// RunLengthEncoder
//---------------------------------------------------------------------------------------------------------------
RunLengthEncoder::RunLengthEncoder(Stream *pStream):
FilterStream(pStream)
{
m_pBufferPointer = m_pBufferEnd = m_pNextEnd = m_sBuffer;
m_bEOF = FALSE;
}
RunLengthEncoder::~RunLengthEncoder()
{
if ( m_pStream->IsEncoder() )
delete m_pStream;
}
void RunLengthEncoder::Reset()
{
m_pStream->Reset();
m_pBufferPointer = m_pBufferEnd = m_pNextEnd = m_sBuffer;
m_bEOF = FALSE;
}
//
// Ïîñëå âûïîëíåíèÿ ôóíêöèè FillBuffer, m_sBuffer[] âûãëÿäèò ñëåäóþùèì îáðàçîì:
// +-----+--------------+-----------------+--
// + tag | ... data ... | next 0, 1, or 2 |
// +-----+--------------+-----------------+--
// ^ ^ ^
// m_pBufferPointer m_pBufferEnd m_pNextEnd
//
BOOL RunLengthEncoder::FillBuffer()
{
if ( m_bEOF )
return FALSE;
// ñ÷èòûâàåì äâà áàéòà
int nChar1 = 0, nChar2 = 0;
if ( m_pNextEnd < m_pBufferEnd + 1 )
{
if ( ( nChar1 = m_pStream->GetChar() ) == EOF )
{
m_bEOF = TRUE;
return FALSE;
}
}
else
{
nChar1 = m_pBufferEnd[0] & 0xff;
}
if ( m_pNextEnd < m_pBufferEnd + 2 )
{
if ( ( nChar2 = m_pStream->GetChar() ) == EOF )
{
m_bEOF = TRUE;
m_sBuffer[0] = 0;
m_sBuffer[1] = nChar1;
m_pBufferPointer = m_sBuffer;
m_pBufferEnd = &m_sBuffer[2];
return TRUE;
}
}
else
{
nChar2 = m_pBufferEnd[1] & 0xff;
}
int nChar = 0;
if ( nChar1 == nChar2 )
{
int nLen = 2;
while ( nLen < 128 && (nChar = m_pStream->GetChar()) == nChar1 )
++nLen;
m_sBuffer[0] = (char)(257 - nLen);
m_sBuffer[1] = nChar1;
m_pBufferEnd = &m_sBuffer[2];
if ( nChar == EOF )
{
m_bEOF = TRUE;
}
else if ( nLen < 128 )
{
m_sBuffer[2] = nChar;
m_pNextEnd = &m_sBuffer[3];
}
else
{
m_pNextEnd = m_pBufferEnd;
}
}
else
{
m_sBuffer[1] = nChar1;
m_sBuffer[2] = nChar2;
int nLen = 2;
while ( nLen < 128 )
{
if ( ( nChar = m_pStream->GetChar() ) == EOF )
{
m_bEOF = TRUE;
break;
}
++nLen;
m_sBuffer[nLen] = nChar;
if ( m_sBuffer[nLen] == m_sBuffer[nLen - 1] )
break;
}
if ( m_sBuffer[nLen] == m_sBuffer[nLen - 1] )
{
m_sBuffer[0] = (char)(nLen - 2 - 1);
m_pBufferEnd = &m_sBuffer[nLen - 1];
m_pNextEnd = &m_sBuffer[nLen + 1];
}
else
{
m_sBuffer[0] = (char)(nLen - 1);
m_pBufferEnd = m_pNextEnd = &m_sBuffer[nLen + 1];
}
}
m_pBufferPointer = m_sBuffer;
return TRUE;
}