libpgf  6.11.42
PGF - Progressive Graphics File
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, 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_

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 45 of file Decoder.h.


Constructor & Destructor Documentation

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.

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.
useOMPIf true, then the decoder will use multi-threading based on openMP

Definition at line 65 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);
}

Destructor

Definition at line 199 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;
        }
}

Member Function Documentation

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

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

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

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

Returns:
The length of all encoded headers in bytes

Definition at line 131 of file Decoder.h.

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.

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

Definition at line 234 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 214 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 502 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::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]

Reset stream position to beginning of PGF pre header

Definition at line 135 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 417 of file Decoder.cpp.

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

Member Data Documentation

current macro block (used by main thread)

Definition at line 199 of file Decoder.h.

index of current macro block

Definition at line 196 of file Decoder.h.

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

Definition at line 193 of file Decoder.h.

array length

Definition at line 197 of file Decoder.h.

array of macroblocks

Definition at line 195 of file Decoder.h.

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

Definition at line 198 of file Decoder.h.

UINT64 CDecoder::m_startPos [private]

stream position at the beginning of the PGF pre header

Definition at line 191 of file Decoder.h.

input pgf stream

Definition at line 190 of file Decoder.h.

estimation of stream size

Definition at line 192 of file Decoder.h.


The documentation for this class was generated from the following files:
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines