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>

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 More...
 

Private Attributes

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

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.

76 : m_stream(stream)
77 , m_startPos(0)
82 #ifdef __PGFROISUPPORT__
83 , m_roi(false)
84 #endif
85 {
86  ASSERT(m_stream);
87 
88  int count, expected;
89 
90  // set number of threads
91 #ifdef LIBPGF_USE_OPENMP
92  m_macroBlockLen = omp_get_num_procs();
93 #else
94  m_macroBlockLen = 1;
95 #endif
96 
97  if (useOMP && m_macroBlockLen > 1) {
98 #ifdef LIBPGF_USE_OPENMP
99  omp_set_num_threads(m_macroBlockLen);
100 #endif
101 
102  // create macro block array
103  m_macroBlocks = new(std::nothrow) CMacroBlock*[m_macroBlockLen];
104  if (!m_macroBlocks) ReturnWithError(InsufficientMemory);
105  for (int i=0; i < m_macroBlockLen; i++) m_macroBlocks[i] = new CMacroBlock(this);
107  } else {
108  m_macroBlocks = 0;
109  m_macroBlockLen = 1; // there is only one macro block
110  m_currentBlock = new CMacroBlock(this);
111  }
112 
113  // store current stream position
115 
116  // read magic and version
117  count = expected = MagicVersionSize;
118  m_stream->Read(&count, &preHeader);
119  if (count != expected) ReturnWithError(MissingData);
120 
121  // read header size
122  if (preHeader.version & Version6) {
123  // 32 bit header size since version 6
124  count = expected = 4;
125  } else {
126  count = expected = 2;
127  }
128  m_stream->Read(&count, ((UINT8*)&preHeader) + MagicVersionSize);
129  if (count != expected) ReturnWithError(MissingData);
130 
131  // make sure the values are correct read
132  preHeader.hSize = __VAL(preHeader.hSize);
133 
134  // check magic number
135  if (memcmp(preHeader.magic, Magic, 3) != 0) {
136  // error condition: wrong Magic number
137  ReturnWithError(FormatCannotRead);
138  }
139 
140  // read file header
141  count = expected = (preHeader.hSize < HeaderSize) ? preHeader.hSize : HeaderSize;
142  m_stream->Read(&count, &header);
143  if (count != expected) ReturnWithError(MissingData);
144 
145  // make sure the values are correct read
146  header.height = __VAL(UINT32(header.height));
147  header.width = __VAL(UINT32(header.width));
148 
149  // be ready to read all versions including version 0
150  if (preHeader.version > 0) {
151 #ifndef __PGFROISUPPORT__
152  // check ROI usage
153  if (preHeader.version & PGFROI) ReturnWithError(FormatCannotRead);
154 #endif
155 
156  int size = preHeader.hSize - HeaderSize;
157 
158  if (size > 0) {
159  // read post-header
160  if (header.mode == ImageModeIndexedColor) {
161  ASSERT((size_t)size >= ColorTableSize);
162  // read color table
163  count = expected = ColorTableSize;
164  m_stream->Read(&count, postHeader.clut);
165  if (count != expected) ReturnWithError(MissingData);
166  size -= count;
167  }
168 
169  if (size > 0) {
170  userDataPos = m_stream->GetPos();
171  postHeader.userDataLen = size;
172  if (skipUserData) {
173  Skip(size);
174  } else {
175  // create user data memory block
176  postHeader.userData = new(std::nothrow) UINT8[postHeader.userDataLen];
177  if (!postHeader.userData) ReturnWithError(InsufficientMemory);
178 
179  // read user data
180  count = expected = postHeader.userDataLen;
181  m_stream->Read(&count, postHeader.userData);
182  if (count != expected) ReturnWithError(MissingData);
183  }
184  }
185  }
186 
187  // create levelLength
188  levelLength = new(std::nothrow) UINT32[header.nLevels];
189  if (!levelLength) ReturnWithError(InsufficientMemory);
190 
191  // read levelLength
192  count = expected = header.nLevels*WordBytes;
193  m_stream->Read(&count, levelLength);
194  if (count != expected) ReturnWithError(MissingData);
195 
196 #ifdef PGF_USE_BIG_ENDIAN
197  // make sure the values are correct read
198  for (int i=0; i < header.nLevels; i++) {
199  levelLength[i] = __VAL(levelLength[i]);
200  }
201 #endif
202 
203  // compute the total size in bytes; keep attention: level length information is optional
204  for (int i=0; i < header.nLevels; i++) {
205  m_streamSizeEstimation += levelLength[i];
206  }
207 
208  }
209 
210  // store current stream position
212 }
CDecoder::~CDecoder ( )

Destructor

Definition at line 216 of file Decoder.cpp.

216  {
217  if (m_macroBlocks) {
218  for (int i=0; i < m_macroBlockLen; i++) delete m_macroBlocks[i];
219  delete[] m_macroBlocks;
220  } else {
221  delete m_currentBlock;
222  }
223 }

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.

479  {
480  ASSERT(m_macroBlocksAvailable <= 0);
481 
482  // macro block management
483  if (m_macroBlockLen == 1) {
484  ASSERT(m_currentBlock);
488  } else {
490  for (int i=0; i < m_macroBlockLen; i++) {
491  // read sequentially several blocks
492  try {
495  } catch(IOException& ex) {
496  if (ex.error == MissingData) {
497  break; // no further data available
498  } else {
499  throw ex;
500  }
501  }
502  }
503 
504  // decode in parallel
505  #pragma omp parallel for default(shared) //no declared exceptions in next block
506  for (int i=0; i < m_macroBlocksAvailable; i++) {
508  }
509 
510  // prepare current macro block
513  }
514 }
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.

318  {
319  CSubband* hlBand = wtChannel->GetSubband(level, HL);
320  CSubband* lhBand = wtChannel->GetSubband(level, LH);
321  const div_t lhH = div(lhBand->GetHeight(), InterBlockSize);
322  const div_t hlW = div(hlBand->GetWidth(), InterBlockSize);
323  const int hlws = hlBand->GetWidth() - InterBlockSize;
324  const int hlwr = hlBand->GetWidth() - hlW.rem;
325  const int lhws = lhBand->GetWidth() - InterBlockSize;
326  const int lhwr = lhBand->GetWidth() - hlW.rem;
327  int hlPos, lhPos;
328  int hlBase = 0, lhBase = 0, hlBase2, lhBase2;
329 
330  ASSERT(lhBand->GetWidth() >= hlBand->GetWidth());
331  ASSERT(hlBand->GetHeight() >= lhBand->GetHeight());
332 
333  if (!hlBand->AllocMemory()) ReturnWithError(InsufficientMemory);
334  if (!lhBand->AllocMemory()) ReturnWithError(InsufficientMemory);
335 
336  // correct quantParam with normalization factor
337  quantParam -= level;
338  if (quantParam < 0) quantParam = 0;
339 
340  // main height
341  for (int i=0; i < lhH.quot; i++) {
342  // main width
343  hlBase2 = hlBase;
344  lhBase2 = lhBase;
345  for (int j=0; j < hlW.quot; j++) {
346  hlPos = hlBase2;
347  lhPos = lhBase2;
348  for (int y=0; y < InterBlockSize; y++) {
349  for (int x=0; x < InterBlockSize; x++) {
350  DequantizeValue(hlBand, hlPos, quantParam);
351  DequantizeValue(lhBand, lhPos, quantParam);
352  hlPos++;
353  lhPos++;
354  }
355  hlPos += hlws;
356  lhPos += lhws;
357  }
358  hlBase2 += InterBlockSize;
359  lhBase2 += InterBlockSize;
360  }
361  // rest of width
362  hlPos = hlBase2;
363  lhPos = lhBase2;
364  for (int y=0; y < InterBlockSize; y++) {
365  for (int x=0; x < hlW.rem; x++) {
366  DequantizeValue(hlBand, hlPos, quantParam);
367  DequantizeValue(lhBand, lhPos, quantParam);
368  hlPos++;
369  lhPos++;
370  }
371  // width difference between HL and LH
372  if (lhBand->GetWidth() > hlBand->GetWidth()) {
373  DequantizeValue(lhBand, lhPos, quantParam);
374  }
375  hlPos += hlwr;
376  lhPos += lhwr;
377  hlBase += hlBand->GetWidth();
378  lhBase += lhBand->GetWidth();
379  }
380  }
381  // main width
382  hlBase2 = hlBase;
383  lhBase2 = lhBase;
384  for (int j=0; j < hlW.quot; j++) {
385  // rest of height
386  hlPos = hlBase2;
387  lhPos = lhBase2;
388  for (int y=0; y < lhH.rem; y++) {
389  for (int x=0; x < InterBlockSize; x++) {
390  DequantizeValue(hlBand, hlPos, quantParam);
391  DequantizeValue(lhBand, lhPos, quantParam);
392  hlPos++;
393  lhPos++;
394  }
395  hlPos += hlws;
396  lhPos += lhws;
397  }
398  hlBase2 += InterBlockSize;
399  lhBase2 += InterBlockSize;
400  }
401  // rest of height
402  hlPos = hlBase2;
403  lhPos = lhBase2;
404  for (int y=0; y < lhH.rem; y++) {
405  // rest of width
406  for (int x=0; x < hlW.rem; x++) {
407  DequantizeValue(hlBand, hlPos, quantParam);
408  DequantizeValue(lhBand, lhPos, quantParam);
409  hlPos++;
410  lhPos++;
411  }
412  // width difference between HL and LH
413  if (lhBand->GetWidth() > hlBand->GetWidth()) {
414  DequantizeValue(lhBand, lhPos, quantParam);
415  }
416  hlPos += hlwr;
417  lhPos += lhwr;
418  hlBase += hlBand->GetWidth();
419  }
420  // height difference between HL and LH
421  if (hlBand->GetHeight() > lhBand->GetHeight()) {
422  // total width
423  hlPos = hlBase;
424  for (int j=0; j < hlBand->GetWidth(); j++) {
425  DequantizeValue(hlBand, hlPos, quantParam);
426  hlPos++;
427  }
428  }
429 }
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.

447  {
448  ASSERT(m_currentBlock);
449 
451  // all data of current macro block has been read --> prepare next macro block
452  DecodeTileBuffer();
453  }
454 
455  band->SetData(bandPos, m_currentBlock->m_value[m_currentBlock->m_valuePos] << quantParam);
457 }
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.

136 { return m_encodedHeaderLength; }
CPGFStream* CDecoder::GetStream ( )
inline
Returns
Stream

Definition at line 174 of file Decoder.h.

174 { 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.

178 { 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.

251  {
252  ASSERT(band);
253 
254  const div_t ww = div(width, LinBlockSize);
255  const div_t hh = div(height, LinBlockSize);
256  const int ws = pitch - LinBlockSize;
257  const int wr = pitch - ww.rem;
258  int pos, base = startPos, base2;
259 
260  // main height
261  for (int i=0; i < hh.quot; i++) {
262  // main width
263  base2 = base;
264  for (int j=0; j < ww.quot; j++) {
265  pos = base2;
266  for (int y=0; y < LinBlockSize; y++) {
267  for (int x=0; x < LinBlockSize; x++) {
268  DequantizeValue(band, pos, quantParam);
269  pos++;
270  }
271  pos += ws;
272  }
273  base2 += LinBlockSize;
274  }
275  // rest of width
276  pos = base2;
277  for (int y=0; y < LinBlockSize; y++) {
278  for (int x=0; x < ww.rem; x++) {
279  DequantizeValue(band, pos, quantParam);
280  pos++;
281  }
282  pos += wr;
283  base += pitch;
284  }
285  }
286  // main width
287  base2 = base;
288  for (int j=0; j < ww.quot; j++) {
289  // rest of height
290  pos = base2;
291  for (int y=0; y < hh.rem; y++) {
292  for (int x=0; x < LinBlockSize; x++) {
293  DequantizeValue(band, pos, quantParam);
294  pos++;
295  }
296  pos += ws;
297  }
298  base2 += LinBlockSize;
299  }
300  // rest of height
301  pos = base2;
302  for (int y=0; y < hh.rem; y++) {
303  // rest of width
304  for (int x=0; x < ww.rem; x++) {
305  DequantizeValue(band, pos, quantParam);
306  pos++;
307  }
308  pos += wr;
309  }
310 }
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.

231  {
232  ASSERT(m_stream);
233 
234  int count = len;
235  m_stream->Read(&count, target);
236 
237  return count;
238 }
void CDecoder::ReadMacroBlock ( CMacroBlock block)
private

throws IOException

Definition at line 519 of file Decoder.cpp.

519  {
520  ASSERT(block);
521 
522  UINT16 wordLen;
524  int count, expected;
525 
526 #ifdef TRACE
527  //UINT32 filePos = (UINT32)m_stream->GetPos();
528  //printf("DecodeBuffer: %d\n", filePos);
529 #endif
530 
531  // read wordLen
532  count = expected = sizeof(UINT16);
533  m_stream->Read(&count, &wordLen);
534  if (count != expected) ReturnWithError(MissingData);
535  wordLen = __VAL(wordLen);
536  if (wordLen > BufferSize)
537  ReturnWithError(FormatCannotRead);
538 
539 #ifdef __PGFROISUPPORT__
540  // read ROIBlockHeader
541  if (m_roi) {
542  m_stream->Read(&count, &h.val);
543  if (count != expected) ReturnWithError(MissingData);
544 
545  // convert ROIBlockHeader
546  h.val = __VAL(h.val);
547  }
548 #endif
549  // save header
550  block->m_header = h;
551 
552  // read data
553  count = expected = wordLen*WordBytes;
554  m_stream->Read(&count, block->m_codeBuffer);
555  if (count != expected) ReturnWithError(MissingData);
556 
557 #ifdef PGF_USE_BIG_ENDIAN
558  // convert data
559  count /= WordBytes;
560  for (int i=0; i < count; i++) {
561  block->m_codeBuffer[i] = __VAL(block->m_codeBuffer[i]);
562  }
563 #endif
564 
565 #ifdef __PGFROISUPPORT__
566  ASSERT(m_roi && h.rbh.bufferSize <= BufferSize || h.rbh.bufferSize == BufferSize);
567 #else
568  ASSERT(h.rbh.bufferSize == BufferSize);
569 #endif
570 }
void CDecoder::SetStreamPosToData ( )
inline

Reset stream position to beginning of data block

Definition at line 144 of file Decoder.h.

144 { 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 140 of file Decoder.h.

140 { 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.

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

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: