CDecoder - Man Page
PGF decoder.
Synopsis
#include <Decoder.h>
Classes
class CMacroBlock
A macro block is a decoding unit of fixed size (uncoded)
Public Member Functions
CDecoder (CPGFStream *stream, PGFPreHeader &preHeader, PGFHeader &header, PGFPostHeader &postHeader, UINT32 *&levelLength, UINT64 &userDataPos, bool useOMP, bool skipUserData) THROW_
~CDecoder ()
Destructor.
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_
Reset stream position to beginning of PGF pre-header.
void SetStreamPosToData () THROW_
Reset stream position to beginning of data block.
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_
CPGFStream * GetStream ()
bool MacroBlocksAvailable () const
Private Member Functions
void ReadMacroBlock (CMacroBlock *block) THROW_
throws IOException
Private Attributes
CPGFStream * m_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)
CMacroBlock * m_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
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.
userDataPos The stream position of the user data (metadata)
useOMP If true, then the decoder will use multi-threading based on openMP
skipUserData If 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
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.
userDataPos The stream position of the user data (metadata)
useOMP If true, then the decoder will use multi-threading based on openMP
skipUserData If 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..PP
76 : m_stream(stream) 77 , m_startPos(0) 78 , m_streamSizeEstimation(0) 79 , m_encodedHeaderLength(0) 80 , m_currentBlockIndex(0) 81 , m_macroBlocksAvailable(0) 82 #ifdef __PGFROISUPPORT__ 83 , m_roi(false) 84 #endif 85 { 86 ASSERT(m_stream); 87 88 int count, expected; 89 90 // store current stream position 91 m_startPos = m_stream->GetPos(); 92 93 // read magic and version 94 count = expected = MagicVersionSize; 95 m_stream->Read(&count, &preHeader); 96 if (count != expected) ReturnWithError(MissingData); 97 98 // read header size 99 if (preHeader.version & Version6) { 100 // 32 bit header size since version 6 101 count = expected = 4; 102 } else { 103 count = expected = 2; 104 } 105 m_stream->Read(&count, ((UINT8*)&preHeader) + MagicVersionSize); 106 if (count != expected) ReturnWithError(MissingData); 107 108 // make sure the values are correct read 109 preHeader.hSize = __VAL(preHeader.hSize); 110 111 // check magic number 112 if (memcmp(preHeader.magic, PGFMagic, 3) != 0) { 113 // error condition: wrong Magic number 114 ReturnWithError(FormatCannotRead); 115 } 116 117 // read file header 118 count = expected = (preHeader.hSize < HeaderSize) ? preHeader.hSize : HeaderSize; 119 m_stream->Read(&count, &header); 120 if (count != expected) ReturnWithError(MissingData); 121 122 // make sure the values are correct read 123 header.height = __VAL(UINT32(header.height)); 124 header.width = __VAL(UINT32(header.width)); 125 126 // be ready to read all versions including version 0 127 if (preHeader.version > 0) { 128 #ifndef __PGFROISUPPORT__ 129 // check ROI usage 130 if (preHeader.version & PGFROI) ReturnWithError(FormatCannotRead); 131 #endif 132 133 int size = preHeader.hSize - HeaderSize; 134 135 if (size > 0) { 136 // read post-header 137 if (header.mode == ImageModeIndexedColor) { 138 if (size < ColorTableSize) ReturnWithError(FormatCannotRead); 139 // read color table 140 count = expected = ColorTableSize; 141 m_stream->Read(&count, postHeader.clut); 142 if (count != expected) ReturnWithError(MissingData); 143 size -= count; 144 } 145 146 if (size > 0) { 147 userDataPos = m_stream->GetPos(); 148 postHeader.userDataLen = size; 149 if (skipUserData) { 150 Skip(size); 151 } else { 152 // create user data memory block 153 postHeader.userData = new(std::nothrow) UINT8[postHeader.userDataLen]; 154 if (!postHeader.userData) ReturnWithError(InsufficientMemory); 155 156 // read user data 157 count = expected = postHeader.userDataLen; 158 m_stream->Read(&count, postHeader.userData); 159 if (count != expected) ReturnWithError(MissingData); 160 } 161 } 162 } 163 164 // create levelLength 165 levelLength = new(std::nothrow) UINT32[header.nLevels]; 166 if (!levelLength) ReturnWithError(InsufficientMemory); 167 168 // read levelLength 169 count = expected = header.nLevels*WordBytes; 170 m_stream->Read(&count, levelLength); 171 if (count != expected) ReturnWithError(MissingData); 172 173 #ifdef PGF_USE_BIG_ENDIAN 174 // make sure the values are correct read 175 for (int i=0; i < header.nLevels; i++) { 176 levelLength[i] = __VAL(levelLength[i]); 177 } 178 #endif 179 180 // compute the total size in bytes; keep attention: level length information is optional 181 for (int i=0; i < header.nLevels; i++) { 182 m_streamSizeEstimation += levelLength[i]; 183 } 184 185 } 186 187 // store current stream position 188 m_encodedHeaderLength = UINT32(m_stream->GetPos() - m_startPos); 189 190 // set number of threads 191 #ifdef LIBPGF_USE_OPENMP 192 m_macroBlockLen = omp_get_num_procs(); 193 #else 194 m_macroBlockLen = 1; 195 #endif 196 197 if (useOMP && m_macroBlockLen > 1) { 198 #ifdef LIBPGF_USE_OPENMP 199 omp_set_num_threads(m_macroBlockLen); 200 #endif 201 202 // create macro block array 203 m_macroBlocks = new(std::nothrow) CMacroBlock*[m_macroBlockLen]; 204 if (!m_macroBlocks) ReturnWithError(InsufficientMemory); 205 for (int i = 0; i < m_macroBlockLen; i++) m_macroBlocks[i] = new CMacroBlock(); 206 m_currentBlock = m_macroBlocks[m_currentBlockIndex]; 207 } else { 208 m_macroBlocks = 0; 209 m_macroBlockLen = 1; // there is only one macro block 210 m_currentBlock = new(std::nothrow) CMacroBlock(); 211 if (!m_currentBlock) ReturnWithError(InsufficientMemory); 212 } 213 }
CDecoder::~CDecoder ()
Destructor.
Definition at line 217 of file Decoder.cpp..PP
217 { 218 if (m_macroBlocks) { 219 for (int i=0; i < m_macroBlockLen; i++) delete m_macroBlocks[i]; 220 delete[] m_macroBlocks; 221 } else { 222 delete m_currentBlock; 223 } 224 }
Member Function Documentation
void CDecoder::DecodeBuffer ()
Reads stream and decodes tile buffer It might throw an IOException.
Definition at line 480 of file Decoder.cpp..PP
480 { 481 ASSERT(m_macroBlocksAvailable <= 0); 482 483 // macro block management 484 if (m_macroBlockLen == 1) { 485 ASSERT(m_currentBlock); 486 ReadMacroBlock(m_currentBlock); 487 m_currentBlock->BitplaneDecode(); 488 m_macroBlocksAvailable = 1; 489 } else { 490 m_macroBlocksAvailable = 0; 491 for (int i=0; i < m_macroBlockLen; i++) { 492 // read sequentially several blocks 493 try { 494 ReadMacroBlock(m_macroBlocks[i]); 495 m_macroBlocksAvailable++; 496 } catch(IOException& ex) { 497 if (ex.error == MissingData) { 498 break; // no further data available 499 } else { 500 throw; 501 } 502 } 503 } 504 #ifdef LIBPGF_USE_OPENMP 505 // decode in parallel 506 #pragma omp parallel for default(shared) //no declared exceptions in next block 507 #endif 508 for (int i=0; i < m_macroBlocksAvailable; i++) { 509 m_macroBlocks[i]->BitplaneDecode(); 510 } 511 512 // prepare current macro block 513 m_currentBlockIndex = 0; 514 m_currentBlock = m_macroBlocks[m_currentBlockIndex]; 515 } 516 }
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
wtChannel A wavelet transform channel containing the HL and HL band
level Wavelet transform level
quantParam Dequantization value
Definition at line 319 of file Decoder.cpp..PP
319 { 320 CSubband* hlBand = wtChannel->GetSubband(level, HL); 321 CSubband* lhBand = wtChannel->GetSubband(level, LH); 322 const div_t lhH = div(lhBand->GetHeight(), InterBlockSize); 323 const div_t hlW = div(hlBand->GetWidth(), InterBlockSize); 324 const int hlws = hlBand->GetWidth() - InterBlockSize; 325 const int hlwr = hlBand->GetWidth() - hlW.rem; 326 const int lhws = lhBand->GetWidth() - InterBlockSize; 327 const int lhwr = lhBand->GetWidth() - hlW.rem; 328 int hlPos, lhPos; 329 int hlBase = 0, lhBase = 0, hlBase2, lhBase2; 330 331 ASSERT(lhBand->GetWidth() >= hlBand->GetWidth()); 332 ASSERT(hlBand->GetHeight() >= lhBand->GetHeight()); 333 334 if (!hlBand->AllocMemory()) ReturnWithError(InsufficientMemory); 335 if (!lhBand->AllocMemory()) ReturnWithError(InsufficientMemory); 336 337 // correct quantParam with normalization factor 338 quantParam -= level; 339 if (quantParam < 0) quantParam = 0; 340 341 // main height 342 for (int i=0; i < lhH.quot; i++) { 343 // main width 344 hlBase2 = hlBase; 345 lhBase2 = lhBase; 346 for (int j=0; j < hlW.quot; j++) { 347 hlPos = hlBase2; 348 lhPos = lhBase2; 349 for (int y=0; y < InterBlockSize; y++) { 350 for (int x=0; x < InterBlockSize; x++) { 351 DequantizeValue(hlBand, hlPos, quantParam); 352 DequantizeValue(lhBand, lhPos, quantParam); 353 hlPos++; 354 lhPos++; 355 } 356 hlPos += hlws; 357 lhPos += lhws; 358 } 359 hlBase2 += InterBlockSize; 360 lhBase2 += InterBlockSize; 361 } 362 // rest of width 363 hlPos = hlBase2; 364 lhPos = lhBase2; 365 for (int y=0; y < InterBlockSize; y++) { 366 for (int x=0; x < hlW.rem; x++) { 367 DequantizeValue(hlBand, hlPos, quantParam); 368 DequantizeValue(lhBand, lhPos, quantParam); 369 hlPos++; 370 lhPos++; 371 } 372 // width difference between HL and LH 373 if (lhBand->GetWidth() > hlBand->GetWidth()) { 374 DequantizeValue(lhBand, lhPos, quantParam); 375 } 376 hlPos += hlwr; 377 lhPos += lhwr; 378 hlBase += hlBand->GetWidth(); 379 lhBase += lhBand->GetWidth(); 380 } 381 } 382 // main width 383 hlBase2 = hlBase; 384 lhBase2 = lhBase; 385 for (int j=0; j < hlW.quot; j++) { 386 // rest of height 387 hlPos = hlBase2; 388 lhPos = lhBase2; 389 for (int y=0; y < lhH.rem; y++) { 390 for (int x=0; x < InterBlockSize; x++) { 391 DequantizeValue(hlBand, hlPos, quantParam); 392 DequantizeValue(lhBand, lhPos, quantParam); 393 hlPos++; 394 lhPos++; 395 } 396 hlPos += hlws; 397 lhPos += lhws; 398 } 399 hlBase2 += InterBlockSize; 400 lhBase2 += InterBlockSize; 401 } 402 // rest of height 403 hlPos = hlBase2; 404 lhPos = lhBase2; 405 for (int y=0; y < lhH.rem; y++) { 406 // rest of width 407 for (int x=0; x < hlW.rem; x++) { 408 DequantizeValue(hlBand, hlPos, quantParam); 409 DequantizeValue(lhBand, lhPos, quantParam); 410 hlPos++; 411 lhPos++; 412 } 413 // width difference between HL and LH 414 if (lhBand->GetWidth() > hlBand->GetWidth()) { 415 DequantizeValue(lhBand, lhPos, quantParam); 416 } 417 hlPos += hlwr; 418 lhPos += lhwr; 419 hlBase += hlBand->GetWidth(); 420 } 421 // height difference between HL and LH 422 if (hlBand->GetHeight() > lhBand->GetHeight()) { 423 // total width 424 hlPos = hlBase; 425 for (int j=0; j < hlBand->GetWidth(); j++) { 426 DequantizeValue(hlBand, hlPos, quantParam); 427 hlPos++; 428 } 429 } 430 }
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
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.
- Parameters
band A subband
bandPos A valid position in subband band
quantParam The quantization parameter
Definition at line 448 of file Decoder.cpp..PP
448 { 449 ASSERT(m_currentBlock); 450 451 if (m_currentBlock->IsCompletelyRead()) { 452 // all data of current macro block has been read --> prepare next macro block 453 DecodeTileBuffer(); 454 } 455 456 band->SetData(bandPos, m_currentBlock->m_value[m_currentBlock->m_valuePos] << quantParam); 457 m_currentBlock->m_valuePos++; 458 }
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 137 of file Decoder.h..PP
137 { return m_encodedHeaderLength; }
CPGFStream * CDecoder::GetStream () [inline]
- Returns
Stream
Definition at line 175 of file Decoder.h..PP
175 { return m_stream; }
bool CDecoder::MacroBlocksAvailable () const [inline]
- Returns
True if decoded macro blocks are available for processing
Definition at line 179 of file Decoder.h..PP
179 { 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
band A subband
quantParam Dequantization value
width The width of the rectangle
height The height of the rectangle
startPos The relative subband position of the top left corner of the rectangular region
pitch The number of bytes in row of the subband
Definition at line 252 of file Decoder.cpp..PP
252 { 253 ASSERT(band); 254 255 const div_t ww = div(width, LinBlockSize); 256 const div_t hh = div(height, LinBlockSize); 257 const int ws = pitch - LinBlockSize; 258 const int wr = pitch - ww.rem; 259 int pos, base = startPos, base2; 260 261 // main height 262 for (int i=0; i < hh.quot; i++) { 263 // main width 264 base2 = base; 265 for (int j=0; j < ww.quot; j++) { 266 pos = base2; 267 for (int y=0; y < LinBlockSize; y++) { 268 for (int x=0; x < LinBlockSize; x++) { 269 DequantizeValue(band, pos, quantParam); 270 pos++; 271 } 272 pos += ws; 273 } 274 base2 += LinBlockSize; 275 } 276 // rest of width 277 pos = base2; 278 for (int y=0; y < LinBlockSize; y++) { 279 for (int x=0; x < ww.rem; x++) { 280 DequantizeValue(band, pos, quantParam); 281 pos++; 282 } 283 pos += wr; 284 base += pitch; 285 } 286 } 287 // main width 288 base2 = base; 289 for (int j=0; j < ww.quot; j++) { 290 // rest of height 291 pos = base2; 292 for (int y=0; y < hh.rem; y++) { 293 for (int x=0; x < LinBlockSize; x++) { 294 DequantizeValue(band, pos, quantParam); 295 pos++; 296 } 297 pos += ws; 298 } 299 base2 += LinBlockSize; 300 } 301 // rest of height 302 pos = base2; 303 for (int y=0; y < hh.rem; y++) { 304 // rest of width 305 for (int x=0; x < ww.rem; x++) { 306 DequantizeValue(band, pos, quantParam); 307 pos++; 308 } 309 pos += wr; 310 } 311 }
UINT32 CDecoder::ReadEncodedData (UINT8 * target, UINT32 len) const
Copies data from the open stream to a target buffer. It might throw an IOException.
- Parameters
target The target buffer
len The number of bytes to read- Returns
The number of bytes copied to the target buffer
Definition at line 232 of file Decoder.cpp..PP
232 { 233 ASSERT(m_stream); 234 235 int count = len; 236 m_stream->Read(&count, target); 237 238 return count; 239 }
void CDecoder::ReadMacroBlock (CMacroBlock * block) [private]
throws IOException
Definition at line 521 of file Decoder.cpp..PP
521 { 522 ASSERT(block); 523 524 UINT16 wordLen; 525 ROIBlockHeader h(BufferSize); 526 int count, expected; 527 528 #ifdef TRACE 529 //UINT32 filePos = (UINT32)m_stream->GetPos(); 530 //printf("DecodeBuffer: %d\n", filePos); 531 #endif 532 533 // read wordLen 534 count = expected = sizeof(UINT16); 535 m_stream->Read(&count, &wordLen); 536 if (count != expected) ReturnWithError(MissingData); 537 wordLen = __VAL(wordLen); 538 if (wordLen > BufferSize) 539 ReturnWithError(FormatCannotRead); 540 541 #ifdef __PGFROISUPPORT__ 542 // read ROIBlockHeader 543 if (m_roi) { 544 m_stream->Read(&count, &h.val); 545 if (count != expected) ReturnWithError(MissingData); 546 547 // convert ROIBlockHeader 548 h.val = __VAL(h.val); 549 } 550 #endif 551 // save header 552 block->m_header = h; 553 554 // read data 555 count = expected = wordLen*WordBytes; 556 m_stream->Read(&count, block->m_codeBuffer); 557 if (count != expected) ReturnWithError(MissingData); 558 559 #ifdef PGF_USE_BIG_ENDIAN 560 // convert data 561 count /= WordBytes; 562 for (int i=0; i < count; i++) { 563 block->m_codeBuffer[i] = __VAL(block->m_codeBuffer[i]); 564 } 565 #endif 566 567 #ifdef __PGFROISUPPORT__ 568 ASSERT(m_roi && h.rbh.bufferSize <= BufferSize || h.rbh.bufferSize == BufferSize); 569 #else 570 ASSERT(h.rbh.bufferSize == BufferSize); 571 #endif 572 }
void CDecoder::SetStreamPosToData () [inline]
Reset stream position to beginning of data block.
Definition at line 145 of file Decoder.h..PP
145 { 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 141 of file Decoder.h..PP
141 { 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 435 of file Decoder.cpp..PP
435 { 436 m_stream->SetPos(FSFromCurrent, offset); 437 }
Member Data Documentation
CMacroBlock* CDecoder::m_currentBlock [private]
current macro block (used by main thread)
Definition at line 213 of file Decoder.h.
int CDecoder::m_currentBlockIndex [private]
index of current macro block
Definition at line 210 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 207 of file Decoder.h.
int CDecoder::m_macroBlockLen [private]
array length
Definition at line 211 of file Decoder.h.
CMacroBlock** CDecoder::m_macroBlocks [private]
array of macroblocks
Definition at line 209 of file Decoder.h.
int CDecoder::m_macroBlocksAvailable [private]
number of decoded macro blocks (including currently used macro block)
Definition at line 212 of file Decoder.h.
UINT64 CDecoder::m_startPos [private]
stream position at the beginning of the PGF pre-header
Definition at line 205 of file Decoder.h.
CPGFStream* CDecoder::m_stream [private]
input PGF stream
Definition at line 204 of file Decoder.h.
UINT64 CDecoder::m_streamSizeEstimation [private]
estimation of stream size
Definition at line 206 of file Decoder.h.
Author
Generated automatically by Doxygen for libpgf from the source code.