libpgf  6.12.24
PGF - Progressive Graphics File
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
CDecoder Class Reference

PGF decoder. More...

#include <Decoder.h>

List of all members.

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, UINT64 &userDataPos, bool useOMP, bool skipUserData) 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_
CPGFStreamGetStream ()
bool MacroBlocksAvailable () const

Private Member Functions

void ReadMacroBlock (CMacroBlock *block) THROW_
 throws IOException

Private Attributes

CPGFStreamm_stream
 input PGF stream
UINT64 m_startPos
 stream position at the beginning of the PGF pre-header
UINT64 m_streamSizeEstimation
 estimation of stream size
UINT32 m_encodedHeaderLength
 stream offset from startPos to the beginning of the data part (highest level)
CMacroBlock ** m_macroBlocks
 array of macroblocks
int m_currentBlockIndex
 index of current macro block
int m_macroBlockLen
 array length
int m_macroBlocksAvailable
 number of decoded macro blocks (including currently used macro block)
CMacroBlockm_currentBlock
 current macro block (used by main thread)

Detailed Description

PGF decoder.

PGF decoder class.

Author:
C. Stamm, R. Spuler

Definition at line 46 of file Decoder.h.


Constructor & Destructor Documentation

CDecoder::CDecoder ( CPGFStream stream,
PGFPreHeader preHeader,
PGFHeader header,
PGFPostHeader postHeader,
UINT32 *&  levelLength,
UINT64 &  userDataPos,
bool  useOMP,
bool  skipUserData 
)

Constructor: Read pre-header, header, and levelLength at current stream position. It might throw an IOException.

Parameters:
streamA PGF stream
preHeader[out] A PGF pre-header
header[out] A PGF header
postHeader[out] A PGF post-header
levelLengthThe location of the levelLength array. The array is allocated in this method. The caller has to delete this array.
userDataPosThe stream position of the user data (metadata)
useOMPIf true, then the decoder will use multi-threading based on openMP
skipUserDataIf true, then user data is not read. In case of available user data, the file position is still returned in userDataPos.

Constructor Read pre-header, header, and levelLength It might throw an IOException.

Parameters:
streamA PGF stream
preHeader[out] A PGF pre-header
header[out] A PGF header
postHeader[out] A PGF post-header
levelLengthThe location of the levelLength array. The array is allocated in this method. The caller has to delete this array.
userDataPosThe stream position of the user data (metadata)
useOMPIf true, then the decoder will use multi-threading based on openMP
skipUserDataIf true, then user data is not read. In case of available user data, the file position is still returned in userDataPos.

Definition at line 73 of file Decoder.cpp.

: m_stream(stream)
#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
#endif
if (useOMP && m_macroBlockLen > 1) {
#ifdef LIBPGF_USE_OPENMP
omp_set_num_threads(m_macroBlockLen);
#endif
// create macro block array
m_macroBlocks = new(std::nothrow) CMacroBlock*[m_macroBlockLen];
if (!m_macroBlocks) ReturnWithError(InsufficientMemory);
for (int i=0; i < m_macroBlockLen; i++) m_macroBlocks[i] = new CMacroBlock(this);
} else {
m_macroBlockLen = 1; // there is only one macro block
m_currentBlock = new CMacroBlock(this);
}
// store current stream position
// 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) {
userDataPos = m_stream->GetPos();
postHeader.userDataLen = size;
if (skipUserData) {
Skip(size);
} else {
// create user data memory block
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(std::nothrow) UINT32[header.nLevels];
if (!levelLength) ReturnWithError(InsufficientMemory);
// 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
}
CDecoder::~CDecoder ( )

Destructor

Definition at line 216 of file Decoder.cpp.

{
for (int i=0; i < m_macroBlockLen; i++) delete m_macroBlocks[i];
delete[] m_macroBlocks;
} else {
}
}

Member Function Documentation

void CDecoder::DecodeBuffer ( )

Reads stream and decodes tile buffer It might throw an IOException.

Definition at line 479 of file Decoder.cpp.

{
ASSERT(m_macroBlocksAvailable <= 0);
// macro block management
if (m_macroBlockLen == 1) {
ASSERT(m_currentBlock);
} else {
for (int i=0; i < m_macroBlockLen; i++) {
// read sequentially several blocks
try {
} 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++) {
}
// prepare current macro block
}
}
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.

Parameters:
wtChannelA wavelet transform channel containing the HL and HL band
levelWavelet transform level
quantParamDequantization value

Definition at line 318 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::DequantizeValue ( CSubband band,
UINT32  bandPos,
int  quantParam 
)

Dequantization of a single value at given position in subband. It might throw an IOException.

Parameters:
bandA subband
bandPosA valid position in subband band
quantParamThe 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.

Parameters:
bandA subband
bandPosA valid position in subband band
quantParamThe quantization parameter

Definition at line 447 of file Decoder.cpp.

{
ASSERT(m_currentBlock);
// 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);
}
UINT32 CDecoder::GetEncodedHeaderLength ( ) const
inline

Return the length of all encoded headers in bytes.

Returns:
The length of all encoded headers in bytes

Definition at line 136 of file Decoder.h.

CPGFStream* CDecoder::GetStream ( )
inline
Returns:
Stream

Definition at line 174 of file Decoder.h.

{ return m_stream; }
bool CDecoder::MacroBlocksAvailable ( ) const
inline
Returns:
True if decoded macro blocks are available for processing

Definition at line 178 of file Decoder.h.

{ return m_macroBlocksAvailable > 1; }
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. Read wavelet coefficients from the output buffer of a macro block. It might throw an IOException.

Parameters:
bandA subband
quantParamDequantization value
widthThe width of the rectangle
heightThe height of the rectangle
startPosThe relative subband position of the top left corner of the rectangular region
pitchThe number of bytes in row of the subband

Definition at line 251 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.

Parameters:
targetThe target buffer
lenThe number of bytes to read
Returns:
The number of bytes copied to the target buffer

Definition at line 231 of file Decoder.cpp.

{
ASSERT(m_stream);
int count = len;
m_stream->Read(&count, target);
return count;
}
void CDecoder::ReadMacroBlock ( CMacroBlock block)
private

throws IOException

Definition at line 519 of file Decoder.cpp.

{
ASSERT(block);
UINT16 wordLen;
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::SetStreamPosToData ( )
inline

Reset stream position to beginning of data block

Definition at line 144 of file Decoder.h.

void CDecoder::SetStreamPosToStart ( )
inline

Reset stream position to beginning of PGF pre-header

Definition at line 140 of file Decoder.h.

{ ASSERT(m_stream); m_stream->SetPos(FSFromStart, m_startPos); }
void CDecoder::Skip ( UINT64  offset)

Skip a given number of bytes in the open stream. It might throw an IOException.

Definition at line 434 of file Decoder.cpp.

{
m_stream->SetPos(FSFromCurrent, offset);
}

Member Data Documentation

CMacroBlock* CDecoder::m_currentBlock
private

current macro block (used by main thread)

Definition at line 212 of file Decoder.h.

int CDecoder::m_currentBlockIndex
private

index of current macro block

Definition at line 209 of file Decoder.h.

UINT32 CDecoder::m_encodedHeaderLength
private

stream offset from startPos to the beginning of the data part (highest level)

Definition at line 206 of file Decoder.h.

int CDecoder::m_macroBlockLen
private

array length

Definition at line 210 of file Decoder.h.

CMacroBlock** CDecoder::m_macroBlocks
private

array of macroblocks

Definition at line 208 of file Decoder.h.

int CDecoder::m_macroBlocksAvailable
private

number of decoded macro blocks (including currently used macro block)

Definition at line 211 of file Decoder.h.

UINT64 CDecoder::m_startPos
private

stream position at the beginning of the PGF pre-header

Definition at line 204 of file Decoder.h.

CPGFStream* CDecoder::m_stream
private

input PGF stream

Definition at line 203 of file Decoder.h.

UINT64 CDecoder::m_streamSizeEstimation
private

estimation of stream size

Definition at line 205 of file Decoder.h.


The documentation for this class was generated from the following files: