|
libpgf
6.11.32
PGF - Progressive Graphics File
|
PGF decoder. More...
#include <Decoder.h>
Classes | |
| class | CMacroBlock |
| A macro block is a decoding unit of fixed size (uncoded) More... | |
Public Member Functions | |
| CDecoder (CPGFStream *stream, PGFPreHeader &preHeader, PGFHeader &header, PGFPostHeader &postHeader, UINT32 *&levelLength, bool useOMP=true) THROW_ | |
| ~CDecoder () | |
| void | Partition (CSubband *band, int quantParam, int width, int height, int startPos, int pitch) THROW_ |
| void | DecodeInterleaved (CWaveletTransform *wtChannel, int level, int quantParam) THROW_ |
| UINT32 | GetEncodedHeaderLength () const |
| void | SetStreamPosToStart () THROW_ |
| void | SetStreamPosToData () THROW_ |
| void | Skip (UINT64 offset) THROW_ |
| void | DequantizeValue (CSubband *band, UINT32 bandPos, int quantParam) THROW_ |
| UINT32 | ReadEncodedData (UINT8 *target, UINT32 len) const THROW_ |
| void | DecodeBuffer () THROW_ |
| void | DecodeTileBuffer () THROW_ |
| void | SkipTileBuffer () THROW_ |
| void | SetROI () |
Private Member Functions | |
| void | ReadMacroBlock (CMacroBlock *block) THROW_ |
Private Attributes | |
| CPGFStream * | m_stream |
| UINT64 | m_startPos |
| UINT64 | m_streamSizeEstimation |
| UINT32 | m_encodedHeaderLength |
| CMacroBlock ** | m_macroBlocks |
| int | m_currentBlockIndex |
| int | m_macroBlockLen |
| int | m_macroBlocksAvailable |
| CMacroBlock * | m_currentBlock |
| bool | m_roi |
PGF decoder.
PGF decoder class.
| CDecoder::CDecoder | ( | CPGFStream * | stream, |
| PGFPreHeader & | preHeader, | ||
| PGFHeader & | header, | ||
| PGFPostHeader & | postHeader, | ||
| UINT32 *& | levelLength, | ||
| bool | useOMP = true |
||
| ) |
Constructor: Read pre-header, header, and levelLength at current stream position. It might throw an IOException.
| stream | A PGF stream |
| preHeader | [out] A PGF pre-header |
| header | [out] A PGF header |
| postHeader | [out] A PGF post-header |
| levelLength | The location of the levelLength array. The array is allocated in this method. The caller has to delete this array. |
| useOMP | If true, then the decoder will use multi-threading based on openMP |
Definition at line 64 of file Decoder.cpp.
: m_stream(stream) , m_startPos(0) , m_streamSizeEstimation(0) , m_encodedHeaderLength(0) , m_currentBlockIndex(0) , m_macroBlocksAvailable(0) #ifdef __PGFROISUPPORT__ , m_roi(false) #endif { ASSERT(m_stream); int count, expected; // set number of threads #ifdef LIBPGF_USE_OPENMP m_macroBlockLen = omp_get_num_procs(); #else m_macroBlockLen = 1; #endif if (useOMP && m_macroBlockLen > 1) { #ifdef LIBPGF_USE_OPENMP omp_set_num_threads(m_macroBlockLen); #endif // create macro block array m_macroBlocks = new CMacroBlock*[m_macroBlockLen]; for (int i=0; i < m_macroBlockLen; i++) m_macroBlocks[i] = new CMacroBlock(this); m_currentBlock = m_macroBlocks[m_currentBlockIndex]; } else { m_macroBlocks = 0; m_macroBlockLen = 1; // there is only one macro block m_currentBlock = new CMacroBlock(this); } // store current stream position m_startPos = m_stream->GetPos(); // read magic and version count = expected = MagicVersionSize; m_stream->Read(&count, &preHeader); if (count != expected) ReturnWithError(MissingData); // read header size if (preHeader.version & Version6) { // 32 bit header size since version 6 count = expected = 4; } else { count = expected = 2; } m_stream->Read(&count, ((UINT8*)&preHeader) + MagicVersionSize); if (count != expected) ReturnWithError(MissingData); // make sure the values are correct read preHeader.hSize = __VAL(preHeader.hSize); // check magic number if (memcmp(preHeader.magic, Magic, 3) != 0) { // error condition: wrong Magic number ReturnWithError(FormatCannotRead); } // read file header count = expected = (preHeader.hSize < HeaderSize) ? preHeader.hSize : HeaderSize; m_stream->Read(&count, &header); if (count != expected) ReturnWithError(MissingData); // make sure the values are correct read header.height = __VAL(UINT32(header.height)); header.width = __VAL(UINT32(header.width)); // be ready to read all versions including version 0 if (preHeader.version > 0) { #ifndef __PGFROISUPPORT__ // check ROI usage if (preHeader.version & PGFROI) ReturnWithError(FormatCannotRead); #endif int size = preHeader.hSize - HeaderSize; if (size > 0) { // read post header if (header.mode == ImageModeIndexedColor) { ASSERT((size_t)size >= ColorTableSize); // read color table count = expected = ColorTableSize; m_stream->Read(&count, postHeader.clut); if (count != expected) ReturnWithError(MissingData); size -= count; } if (size > 0) { // create user data memory block postHeader.userDataLen = size; postHeader.userData = new(std::nothrow) UINT8[postHeader.userDataLen]; if (!postHeader.userData) ReturnWithError(InsufficientMemory); // read user data count = expected = postHeader.userDataLen; m_stream->Read(&count, postHeader.userData); if (count != expected) ReturnWithError(MissingData); } } // create levelLength levelLength = new UINT32[header.nLevels]; // read levelLength count = expected = header.nLevels*WordBytes; m_stream->Read(&count, levelLength); if (count != expected) ReturnWithError(MissingData); #ifdef PGF_USE_BIG_ENDIAN // make sure the values are correct read for (int i=0; i < header.nLevels; i++) { levelLength[i] = __VAL(levelLength[i]); } #endif // compute the total size in bytes; keep attention: level length information is optional for (int i=0; i < header.nLevels; i++) { m_streamSizeEstimation += levelLength[i]; } } // store current stream position m_encodedHeaderLength = UINT32(m_stream->GetPos() - m_startPos); }
| CDecoder::~CDecoder | ( | ) |
Destructor
Definition at line 198 of file Decoder.cpp.
{
if (m_macroBlocks) {
for (int i=0; i < m_macroBlockLen; i++) delete m_macroBlocks[i];
delete[] m_macroBlocks;
} else {
delete m_currentBlock;
}
}
| void CDecoder::DecodeBuffer | ( | ) |
Reads stream and decodes tile buffer It might throw an IOException.
Definition at line 461 of file Decoder.cpp.
{
ASSERT(m_macroBlocksAvailable <= 0);
// macro block management
if (m_macroBlockLen == 1) {
ASSERT(m_currentBlock);
ReadMacroBlock(m_currentBlock);
m_currentBlock->BitplaneDecode();
m_macroBlocksAvailable = 1;
} else {
m_macroBlocksAvailable = 0;
for (int i=0; i < m_macroBlockLen; i++) {
// read sequentially several blocks
try {
ReadMacroBlock(m_macroBlocks[i]);
m_macroBlocksAvailable++;
} catch(IOException& ex) {
if (ex.error == MissingData) {
break; // no further data available
} else {
throw ex;
}
}
}
// decode in parallel
#pragma omp parallel for default(shared) //no declared exceptions in next block
for (int i=0; i < m_macroBlocksAvailable; i++) {
m_macroBlocks[i]->BitplaneDecode();
}
// prepare current macro block
m_currentBlockIndex = 0;
m_currentBlock = m_macroBlocks[m_currentBlockIndex];
}
}
| void CDecoder::DecodeInterleaved | ( | CWaveletTransform * | wtChannel, |
| int | level, | ||
| int | quantParam | ||
| ) |
Deccoding and dequantization of HL and LH subband (interleaved) using partitioning scheme. Partitioning scheme: The plane is partitioned in squares of side length InterBlockSize. It might throw an IOException.
| wtChannel | A wavelet transform channel containing the HL and HL band |
| level | Wavelet transform level |
| quantParam | Dequantization value |
Definition at line 300 of file Decoder.cpp.
{
CSubband* hlBand = wtChannel->GetSubband(level, HL);
CSubband* lhBand = wtChannel->GetSubband(level, LH);
const div_t lhH = div(lhBand->GetHeight(), InterBlockSize);
const div_t hlW = div(hlBand->GetWidth(), InterBlockSize);
const int hlws = hlBand->GetWidth() - InterBlockSize;
const int hlwr = hlBand->GetWidth() - hlW.rem;
const int lhws = lhBand->GetWidth() - InterBlockSize;
const int lhwr = lhBand->GetWidth() - hlW.rem;
int hlPos, lhPos;
int hlBase = 0, lhBase = 0, hlBase2, lhBase2;
ASSERT(lhBand->GetWidth() >= hlBand->GetWidth());
ASSERT(hlBand->GetHeight() >= lhBand->GetHeight());
if (!hlBand->AllocMemory()) ReturnWithError(InsufficientMemory);
if (!lhBand->AllocMemory()) ReturnWithError(InsufficientMemory);
// correct quantParam with normalization factor
quantParam -= level;
if (quantParam < 0) quantParam = 0;
// main height
for (int i=0; i < lhH.quot; i++) {
// main width
hlBase2 = hlBase;
lhBase2 = lhBase;
for (int j=0; j < hlW.quot; j++) {
hlPos = hlBase2;
lhPos = lhBase2;
for (int y=0; y < InterBlockSize; y++) {
for (int x=0; x < InterBlockSize; x++) {
DequantizeValue(hlBand, hlPos, quantParam);
DequantizeValue(lhBand, lhPos, quantParam);
hlPos++;
lhPos++;
}
hlPos += hlws;
lhPos += lhws;
}
hlBase2 += InterBlockSize;
lhBase2 += InterBlockSize;
}
// rest of width
hlPos = hlBase2;
lhPos = lhBase2;
for (int y=0; y < InterBlockSize; y++) {
for (int x=0; x < hlW.rem; x++) {
DequantizeValue(hlBand, hlPos, quantParam);
DequantizeValue(lhBand, lhPos, quantParam);
hlPos++;
lhPos++;
}
// width difference between HL and LH
if (lhBand->GetWidth() > hlBand->GetWidth()) {
DequantizeValue(lhBand, lhPos, quantParam);
}
hlPos += hlwr;
lhPos += lhwr;
hlBase += hlBand->GetWidth();
lhBase += lhBand->GetWidth();
}
}
// main width
hlBase2 = hlBase;
lhBase2 = lhBase;
for (int j=0; j < hlW.quot; j++) {
// rest of height
hlPos = hlBase2;
lhPos = lhBase2;
for (int y=0; y < lhH.rem; y++) {
for (int x=0; x < InterBlockSize; x++) {
DequantizeValue(hlBand, hlPos, quantParam);
DequantizeValue(lhBand, lhPos, quantParam);
hlPos++;
lhPos++;
}
hlPos += hlws;
lhPos += lhws;
}
hlBase2 += InterBlockSize;
lhBase2 += InterBlockSize;
}
// rest of height
hlPos = hlBase2;
lhPos = lhBase2;
for (int y=0; y < lhH.rem; y++) {
// rest of width
for (int x=0; x < hlW.rem; x++) {
DequantizeValue(hlBand, hlPos, quantParam);
DequantizeValue(lhBand, lhPos, quantParam);
hlPos++;
lhPos++;
}
// width difference between HL and LH
if (lhBand->GetWidth() > hlBand->GetWidth()) {
DequantizeValue(lhBand, lhPos, quantParam);
}
hlPos += hlwr;
lhPos += lhwr;
hlBase += hlBand->GetWidth();
}
// height difference between HL and LH
if (hlBand->GetHeight() > lhBand->GetHeight()) {
// total width
hlPos = hlBase;
for (int j=0; j < hlBand->GetWidth(); j++) {
DequantizeValue(hlBand, hlPos, quantParam);
hlPos++;
}
}
}
| void CDecoder::DecodeTileBuffer | ( | ) |
Reads stream and decodes tile buffer It might throw an IOException.
Definition at line 444 of file Decoder.cpp.
{
// current block has been read --> prepare next current block
m_macroBlocksAvailable--;
if (m_macroBlocksAvailable > 0) {
m_currentBlock = m_macroBlocks[++m_currentBlockIndex];
} else {
DecodeBuffer();
}
ASSERT(m_currentBlock);
}
| void CDecoder::DequantizeValue | ( | CSubband * | band, |
| UINT32 | bandPos, | ||
| int | quantParam | ||
| ) |
Dequantization of a single value at given position in subband. It might throw an IOException.
| band | A subband |
| bandPos | A valid position in subband band |
| quantParam | The quantization parameter |
Dequantization of a single value at given position in subband. If encoded data is available, then stores dequantized band value into buffer m_value at position m_valuePos. Otherwise reads encoded data block and decodes it. It might throw an IOException.
| band | A subband |
| bandPos | A valid position in subband band |
| quantParam | The quantization parameter |
Definition at line 429 of file Decoder.cpp.
{
ASSERT(m_currentBlock);
if (m_currentBlock->IsCompletelyRead()) {
// all data of current macro block has been read --> prepare next macro block
DecodeTileBuffer();
}
band->SetData(bandPos, m_currentBlock->m_value[m_currentBlock->m_valuePos] << quantParam);
m_currentBlock->m_valuePos++;
}
| UINT32 CDecoder::GetEncodedHeaderLength | ( | ) | const [inline] |
Return the length of all encoded headers in bytes.
Definition at line 131 of file Decoder.h.
{ return m_encodedHeaderLength; }
| void CDecoder::Partition | ( | CSubband * | band, |
| int | quantParam, | ||
| int | width, | ||
| int | height, | ||
| int | startPos, | ||
| int | pitch | ||
| ) |
Unpartitions a rectangular region of a given subband. Partitioning scheme: The plane is partitioned in squares of side length LinBlockSize. Write wavelet coefficients into buffer. It might throw an IOException.
| band | A subband |
| quantParam | Dequantization value |
| width | The width of the rectangle |
| height | The height of the rectangle |
| startPos | The buffer position of the top left corner of the rectangular region |
| pitch | The number of bytes in row of the subband |
Definition at line 233 of file Decoder.cpp.
{
ASSERT(band);
const div_t ww = div(width, LinBlockSize);
const div_t hh = div(height, LinBlockSize);
const int ws = pitch - LinBlockSize;
const int wr = pitch - ww.rem;
int pos, base = startPos, base2;
// main height
for (int i=0; i < hh.quot; i++) {
// main width
base2 = base;
for (int j=0; j < ww.quot; j++) {
pos = base2;
for (int y=0; y < LinBlockSize; y++) {
for (int x=0; x < LinBlockSize; x++) {
DequantizeValue(band, pos, quantParam);
pos++;
}
pos += ws;
}
base2 += LinBlockSize;
}
// rest of width
pos = base2;
for (int y=0; y < LinBlockSize; y++) {
for (int x=0; x < ww.rem; x++) {
DequantizeValue(band, pos, quantParam);
pos++;
}
pos += wr;
base += pitch;
}
}
// main width
base2 = base;
for (int j=0; j < ww.quot; j++) {
// rest of height
pos = base2;
for (int y=0; y < hh.rem; y++) {
for (int x=0; x < LinBlockSize; x++) {
DequantizeValue(band, pos, quantParam);
pos++;
}
pos += ws;
}
base2 += LinBlockSize;
}
// rest of height
pos = base2;
for (int y=0; y < hh.rem; y++) {
// rest of width
for (int x=0; x < ww.rem; x++) {
DequantizeValue(band, pos, quantParam);
pos++;
}
pos += wr;
}
}
| UINT32 CDecoder::ReadEncodedData | ( | UINT8 * | target, |
| UINT32 | len | ||
| ) | const |
Copies data from the open stream to a target buffer. It might throw an IOException.
| target | The target buffer |
| len | The number of bytes to read |
Definition at line 213 of file Decoder.cpp.
| void CDecoder::ReadMacroBlock | ( | CMacroBlock * | block | ) | [private] |
Definition at line 501 of file Decoder.cpp.
{
ASSERT(block);
UINT16 wordLen;
ROIBlockHeader h(BufferSize);
int count, expected;
#ifdef TRACE
//UINT32 filePos = (UINT32)m_stream->GetPos();
//printf("DecodeBuffer: %d\n", filePos);
#endif
// read wordLen
count = expected = sizeof(UINT16);
m_stream->Read(&count, &wordLen);
if (count != expected) ReturnWithError(MissingData);
wordLen = __VAL(wordLen);
if (wordLen > BufferSize)
ReturnWithError(FormatCannotRead);
#ifdef __PGFROISUPPORT__
// read ROIBlockHeader
if (m_roi) {
m_stream->Read(&count, &h.val);
if (count != expected) ReturnWithError(MissingData);
// convert ROIBlockHeader
h.val = __VAL(h.val);
}
#endif
// save header
block->m_header = h;
// read data
count = expected = wordLen*WordBytes;
m_stream->Read(&count, block->m_codeBuffer);
if (count != expected) ReturnWithError(MissingData);
#ifdef PGF_USE_BIG_ENDIAN
// convert data
count /= WordBytes;
for (int i=0; i < count; i++) {
block->m_codeBuffer[i] = __VAL(block->m_codeBuffer[i]);
}
#endif
#ifdef __PGFROISUPPORT__
ASSERT(m_roi && h.rbh.bufferSize <= BufferSize || h.rbh.bufferSize == BufferSize);
#else
ASSERT(h.rbh.bufferSize == BufferSize);
#endif
}
| void CDecoder::SetROI | ( | ) | [inline] |
| void CDecoder::SetStreamPosToData | ( | ) | [inline] |
Reset stream position to beginning of data block
Definition at line 139 of file Decoder.h.
{ ASSERT(m_stream); m_stream->SetPos(FSFromStart, m_startPos + m_encodedHeaderLength); }
| void CDecoder::SetStreamPosToStart | ( | ) | [inline] |
| void CDecoder::Skip | ( | UINT64 | offset | ) |
Skip a given number of bytes in the open stream. It might throw an IOException.
Definition at line 416 of file Decoder.cpp.
| void CDecoder::SkipTileBuffer | ( | ) |
Resets stream position to next tile. It might throw an IOException.
Definition at line 559 of file Decoder.cpp.
{
// current block is not used
m_macroBlocksAvailable--;
// check if pre-decoded data is available
if (m_macroBlocksAvailable > 0) {
m_currentBlock = m_macroBlocks[++m_currentBlockIndex];
return;
}
UINT16 wordLen;
int count, expected;
// read wordLen
count = expected = sizeof(wordLen);
m_stream->Read(&count, &wordLen);
if (count != expected) ReturnWithError(MissingData);
wordLen = __VAL(wordLen);
ASSERT(wordLen <= BufferSize);
#ifdef __PGFROISUPPORT__
if (m_roi) {
// skip ROIBlockHeader
m_stream->SetPos(FSFromCurrent, sizeof(ROIBlockHeader));
}
#endif
// skip data
m_stream->SetPos(FSFromCurrent, wordLen*WordBytes);
}
CMacroBlock* CDecoder::m_currentBlock [private] |
int CDecoder::m_currentBlockIndex [private] |
UINT32 CDecoder::m_encodedHeaderLength [private] |
int CDecoder::m_macroBlockLen [private] |
CMacroBlock** CDecoder::m_macroBlocks [private] |
int CDecoder::m_macroBlocksAvailable [private] |
bool CDecoder::m_roi [private] |
UINT64 CDecoder::m_startPos [private] |
CPGFStream* CDecoder::m_stream [private] |
UINT64 CDecoder::m_streamSizeEstimation [private] |