CEncoder(3)

NAME
CEncoder - PGF encoder.

SYNOPSIS

#include <Encoder.h>

  Classes
class CMacroBlock
A macro block is an encoding unit of fixed size (uncoded).

  Public Member Functions
CEncoder (CPGFStream *stream, PGFPreHeader preHeader, PGFHeader header, const PGFPostHeader &postHeader, UINT64 &userDataPos, bool useOMP)
~CEncoder ()
Destructor.
void FavorSpeedOverSize ()
Encoder favors speed over compression size.
void Flush ()
void UpdatePostHeaderSize (PGFPreHeader preHeader)
UINT32 WriteLevelLength (UINT32 *&levelLength)
UINT32 UpdateLevelLength ()
void Partition (CSubband *band, int width, int height, int startPos, int pitch)
void SetEncodedLevel (int currentLevel)
void WriteValue (CSubband *band, int bandPos)
INT64 ComputeHeaderLength () const
INT64 ComputeBufferLength () const
INT64 ComputeOffset () const
void SetStreamPosToStart ()
Resets stream position to beginning of PGF pre-header.
void SetBufferStartPos ()
Save current stream position as beginning of current level.

  Private Member Functions
void EncodeBuffer (ROIBlockHeader h)
void WriteMacroBlock (CMacroBlock *block)

  Private Attributes
CPGFStream * m_stream
output PMF stream
UINT64 m_startPosition
stream position of PGF start (PreHeader)
UINT64 m_levelLengthPos
stream position of Metadata
UINT64 m_bufferStartPos
stream position of encoded buffer
CMacroBlock ** m_macroBlocks
array of macroblocks
int m_macroBlockLen
array length
int m_lastMacroBlock
array index of the last created macro block
CMacroBlock * m_currentBlock
current macro block (used by main thread)
UINT32 * m_levelLength
temporary saves the level index
int m_currLevelIndex
counts where (=index) to save next value
UINT8 m_nLevels
number of levels
bool m_favorSpeed
favor speed over size
bool m_forceWriting
all macro blocks have to be written into the stream

Detailed Description

PGF encoder. PGF encoder class.

Author
    C. Stamm

Definition at line 46 of file Encoder.h.

Constructor & Destructor Documentation

  CEncoder::CEncoder (CPGFStream * stream, PGFPreHeader preHeader, PGFHeader header, const PGFPostHeader & postHeader, UINT64 & userDataPos, bool useOMP)
Write pre-header, header, post-Header, and levelLength. It might throw an IOException.

Parameters
    stream A PGF stream
    preHeader A already filled in PGF pre-header
    header An already filled in PGF header
    postHeader [in] An already filled in PGF post-header (containing color table, user data, ...)
    userDataPos [out] File position of user data
    useOMP If true, then the encoder will use multi-threading based on openMP

Write pre-header, header, postHeader, and levelLength. It might throw an IOException.

Parameters
    stream A PGF stream
    preHeader A already filled in PGF pre-header
    header An already filled in PGF header
    postHeader [in] An already filled in PGF post-header (containing color table, user data, ...)
    userDataPos [out] File position of user data
    useOMP If true, then the encoder will use multi-threading based on openMP

Definition at line 70 of file Encoder.cpp.
71 : m_stream(stream)
72 , m_bufferStartPos(0)
73 , m_currLevelIndex(0)
74 , m_nLevels(header.nLevels)
75 , m_favorSpeed(false)
76 , m_forceWriting(false)
77 #ifdef __PGFROISUPPORT__
78 , m_roi(false)
79 #endif
80 {
81         ASSERT(m_stream);
82
83         int count;
84         m_lastMacroBlock = 0;
85         m_levelLength = nullptr;
86
87         // set number of threads
88 #ifdef LIBPGF_USE_OPENMP
89         m_macroBlockLen = omp_get_num_procs();
90 #else
91         m_macroBlockLen = 1;
92 #endif
93
94         if (useOMP && m_macroBlockLen > 1) {
95 #ifdef LIBPGF_USE_OPENMP
96                 omp_set_num_threads(m_macroBlockLen);
97 #endif
98                 // create macro block array
99                 m_macroBlocks = new(std::nothrow) CMacroBlock*[m_macroBlockLen];
100                 if (!m_macroBlocks) ReturnWithError(InsufficientMemory);
101                 for (int i=0; i < m_macroBlockLen; i++) m_macroBlocks[i] = new CMacroBlock(this);
102                 m_currentBlock = m_macroBlocks[m_lastMacroBlock++];
103         } else {
104                 m_macroBlocks = 0;
105                 m_macroBlockLen = 1;
106                 m_currentBlock = new CMacroBlock(this);
107         }
108
109         // save file position
110         m_startPosition = m_stream->GetPos();
111
112         // write preHeader
113         preHeader.hSize = __VAL(preHeader.hSize);
114         count = PreHeaderSize;
115         m_stream->Write(&count, &preHeader);
116
117         // write file header
118         header.height = __VAL(header.height);
119         header.width = __VAL(header.width);
120         count = HeaderSize;
121         m_stream->Write(&count, &header);
122
123         // write postHeader
124         if (header.mode == ImageModeIndexedColor) {
125                 // write color table
126                 count = ColorTableSize;
127                 m_stream->Write(&count, (void *)postHeader.clut);
128         }
129         // save user data file position
130         userDataPos = m_stream->GetPos();
131         if (postHeader.userDataLen) {
132                 if (postHeader.userData) {
133                         // write user data
134                         count = postHeader.userDataLen;
135                         m_stream->Write(&count, postHeader.userData);
136                 } else {
137                         m_stream->SetPos(FSFromCurrent, count);
138                 }
139         }
140
141         // save level length file position
142         m_levelLengthPos = m_stream->GetPos();
143 }

  CEncoder::~CEncoder ()

Destructor.

Definition at line 147 of file Encoder.cpp.
147                     {
148         if (m_macroBlocks) {
149                 for (int i=0; i < m_macroBlockLen; i++) delete m_macroBlocks[i];
150                 delete[] m_macroBlocks;
151         } else {
152                 delete m_currentBlock;
153         }
154 }

Member Function Documentation

  INT64 CEncoder::ComputeBufferLength () const [inline]
Compute stream length of encoded buffer.

Returns
    encoded buffer length

Definition at line 179 of file Encoder.h.
179 { return m_stream->GetPos() - m_bufferStartPos; }

  INT64 CEncoder::ComputeHeaderLength () const [inline]
Compute stream length of header.

Returns
    header length

Definition at line 174 of file Encoder.h.
174 { return m_levelLengthPos - m_startPosition; }

  INT64 CEncoder::ComputeOffset () const [inline]
Compute file offset between real and expected levelLength position.

Returns
    file offset

Definition at line 184 of file Encoder.h.
184 { return m_stream->GetPos() - m_levelLengthPos; }

  void CEncoder::EncodeBuffer (ROIBlockHeader h) [private]

Definition at line 341 of file Encoder.cpp.
341                                             {
342         ASSERT(m_currentBlock);
343 #ifdef __PGFROISUPPORT__
344         ASSERT(m_roi && h.rbh.bufferSize <= BufferSize || h.rbh.bufferSize == BufferSize);
345 #else
346         ASSERT(h.rbh.bufferSize == BufferSize);
347 #endif
348         m_currentBlock->m_header = h;
349
350         // macro block management
351         if (m_macroBlockLen == 1) {
352                 m_currentBlock->BitplaneEncode();
353                 WriteMacroBlock(m_currentBlock);
354         } else {
355                 // save last level index
356                 int lastLevelIndex = m_currentBlock->m_lastLevelIndex;
357
358                 if (m_forceWriting || m_lastMacroBlock == m_macroBlockLen) {
359                         // encode macro blocks
360                         /*
361                         volatile OSError error = NoError;
362                         #ifdef LIBPGF_USE_OPENMP
363                         #pragma omp parallel for ordered default(shared)
364                         #endif
365                         for (int i=0; i < m_lastMacroBlock; i++) {
366                                 if (error == NoError) {
367                                         m_macroBlocks[i]->BitplaneEncode();
368                                         #ifdef LIBPGF_USE_OPENMP
369                                         #pragma omp ordered
370                                         #endif
371                                         {
372                                                 try {
373                                                         WriteMacroBlock(m_macroBlocks[i]);
374                                                 } catch (IOException& e) {
375                                                         error = e.error;
376                                                 }
377                                                 delete m_macroBlocks[i]; m_macroBlocks[i] = 0;
378                                         }
379                                 }
380                         }
381                         if (error != NoError) ReturnWithError(error);
382                         */
383 #ifdef LIBPGF_USE_OPENMP
384                         #pragma omp parallel for default(shared) //no declared exceptions in next block
385 #endif
386                         for (int i=0; i < m_lastMacroBlock; i++) {
387                                 m_macroBlocks[i]->BitplaneEncode();
388                         }
389                         for (int i=0; i < m_lastMacroBlock; i++) {
390                                 WriteMacroBlock(m_macroBlocks[i]);
391                         }
392
393                         // prepare for next round
394                         m_forceWriting = false;
395                         m_lastMacroBlock = 0;
396                 }
397                 // re-initialize macro block
398                 m_currentBlock = m_macroBlocks[m_lastMacroBlock++];
399                 m_currentBlock->Init(lastLevelIndex);
400         }
401 }

  void CEncoder::FavorSpeedOverSize () [inline]

Encoder favors speed over compression size.

Definition at line 121 of file Encoder.h.
121 { m_favorSpeed = true; }

  void CEncoder::Flush ()
Pad buffer with zeros and encode buffer. It might throw an IOException.

Definition at line 310 of file Encoder.cpp.
310                      {
311         if (m_currentBlock->m_valuePos > 0) {
312                 // pad buffer with zeros
313                 memset(&(m_currentBlock->m_value[m_currentBlock->m_valuePos]), 0, (BufferSize - m_currentBlock->m_valuePos)*DataTSize);
314                 m_currentBlock->m_valuePos = BufferSize;
315
316                 // encode buffer
317                 m_forceWriting = true;  // makes sure that the following EncodeBuffer is really written into the stream
318                 EncodeBuffer(ROIBlockHeader(m_currentBlock->m_valuePos, true));
319         }
320 }

  void CEncoder::Partition (CSubband * band, int width, int height, int startPos, int pitch)
Partitions a rectangular region of a given subband. Partitioning scheme: The plane is partitioned in squares of side length LinBlockSize. Write wavelet coefficients from subband into the input buffer of a macro block. It might throw an IOException.

Parameters
    band A subband
    width The width of the rectangle
    height The height of the rectangle
    startPos The absolute subband position of the top left corner of the rectangular region
    pitch The number of bytes in row of the subband

Definition at line 246 of file Encoder.cpp.
246                                                                                        {
247         ASSERT(band);
248
249         const div_t hh = div(height, LinBlockSize);
250         const div_t ww = div(width, LinBlockSize);
251         const int ws = pitch - LinBlockSize;
252         const int wr = pitch - ww.rem;
253         int pos, base = startPos, base2;
254
255         // main height
256         for (int i=0; i < hh.quot; i++) {
257                 // main width
258                 base2 = base;
259                 for (int j=0; j < ww.quot; j++) {
260                         pos = base2;
261                         for (int y=0; y < LinBlockSize; y++) {
262                                 for (int x=0; x < LinBlockSize; x++) {
263                                         WriteValue(band, pos);
264                                         pos++;
265                                 }
266                                 pos += ws;
267                         }
268                         base2 += LinBlockSize;
269                 }
270                 // rest of width
271                 pos = base2;
272                 for (int y=0; y < LinBlockSize; y++) {
273                         for (int x=0; x < ww.rem; x++) {
274                                 WriteValue(band, pos);
275                                 pos++;
276                         }
277                         pos += wr;
278                         base += pitch;
279                 }
280         }
281         // main width
282         base2 = base;
283         for (int j=0; j < ww.quot; j++) {
284                 // rest of height
285                 pos = base2;
286                 for (int y=0; y < hh.rem; y++) {
287                         for (int x=0; x < LinBlockSize; x++) {
288                                 WriteValue(band, pos);
289                                 pos++;
290                         }
291                         pos += ws;
292                 }
293                 base2 += LinBlockSize;
294         }
295         // rest of height
296         pos = base2;
297         for (int y=0; y < hh.rem; y++) {
298                 // rest of width
299                 for (int x=0; x < ww.rem; x++) {
300                         WriteValue(band, pos);
301                         pos++;
302                 }
303                 pos += wr;
304         }
305 }

  void CEncoder::SetBufferStartPos () [inline]

Save current stream position as beginning of current level.

Definition at line 192 of file Encoder.h.
192 { m_bufferStartPos = m_stream->GetPos(); }

  void CEncoder::SetEncodedLevel (int currentLevel) [inline]
Informs the encoder about the encoded level.

Parameters
    currentLevel encoded level [0, nLevels)

Definition at line 162 of file Encoder.h.
162 { ASSERT(currentLevel >= 0); m_currentBlock->m_lastLevelIndex = m_nLevels - currentLevel - 1; m_forceWriting = true; }

  void CEncoder::SetStreamPosToStart () [inline]

Resets stream position to beginning of PGF pre-header.

Definition at line 188 of file Encoder.h.
188 { ASSERT(m_stream); m_stream->SetPos(FSFromStart, m_startPosition); }

  UINT32 CEncoder::UpdateLevelLength ()
Write new levelLength into stream. It might throw an IOException.

Returns
    Written image bytes.

Definition at line 202 of file Encoder.cpp.
202                                    {
203         UINT64 curPos = m_stream->GetPos(); // end of image
204
205         // set file pos to levelLength
206         m_stream->SetPos(FSFromStart, m_levelLengthPos);
207
208         if (m_levelLength) {
209         #ifdef PGF_USE_BIG_ENDIAN
210                 UINT32 levelLength;
211                 int count = WordBytes;
212
213                 for (int i=0; i < m_currLevelIndex; i++) {
214                         levelLength = __VAL(UINT32(m_levelLength[i]));
215                         m_stream->Write(&count, &levelLength);
216                 }
217         #else
218                 int count = m_currLevelIndex*WordBytes;
219
220                 m_stream->Write(&count, m_levelLength);
221         #endif //PGF_USE_BIG_ENDIAN
222         } else {
223                 int count = m_currLevelIndex*WordBytes;
224                 m_stream->SetPos(FSFromCurrent, count);
225         }
226
227         // begin of image
228         UINT32 retValue = UINT32(curPos - m_stream->GetPos());
229
230         // restore file position
231         m_stream->SetPos(FSFromStart, curPos);
232
233         return retValue;
234 }

  void CEncoder::UpdatePostHeaderSize (PGFPreHeader preHeader)
Increase post-header size and write new size into stream.

Parameters
    preHeader An already filled in PGF pre-header It might throw an IOException.

Definition at line 160 of file Encoder.cpp.
160                                                           {
161         UINT64 curPos = m_stream->GetPos(); // end of user data
162         int count = PreHeaderSize;
163
164         // write preHeader
165         SetStreamPosToStart();
166         preHeader.hSize = __VAL(preHeader.hSize);
167         m_stream->Write(&count, &preHeader);
168
169         m_stream->SetPos(FSFromStart, curPos);
170 }

  UINT32 CEncoder::WriteLevelLength (UINT32 *& levelLength)
Create level length data structure and write a place holder into stream. It might throw an IOException.

Parameters
    levelLength A reference to an integer array, large enough to save the relative file positions of all PGF levels

Returns
    number of bytes written into stream

Definition at line 177 of file Encoder.cpp.
177                                                       {
178         // renew levelLength
179         delete[] levelLength;
180         levelLength = new(std::nothrow) UINT32[m_nLevels];
181         if (!levelLength) ReturnWithError(InsufficientMemory);
182         for (UINT8 l = 0; l < m_nLevels; l++) levelLength[l] = 0;
183         m_levelLength = levelLength;
184
185         // save level length file position
186         m_levelLengthPos = m_stream->GetPos();
187
188         // write dummy levelLength
189         int count = m_nLevels*WordBytes;
190         m_stream->Write(&count, m_levelLength);
191
192         // save current file position
193         SetBufferStartPos();
194
195         return count;
196 }

  void CEncoder::WriteMacroBlock (CMacroBlock * block) [private]

Definition at line 406 of file Encoder.cpp.
406                                                  {
407         ASSERT(block);
408 #ifdef __PGFROISUPPORT__
409         ROIBlockHeader h = block->m_header;
410 #endif
411         UINT16 wordLen = UINT16(NumberOfWords(block->m_codePos)); ASSERT(wordLen <= CodeBufferLen);
412         int count = sizeof(UINT16);
413
414 #ifdef TRACE
415         //UINT32 filePos = (UINT32)m_stream->GetPos();
416         //printf("EncodeBuffer: %d\n", filePos);
417 #endif
418
419 #ifdef PGF_USE_BIG_ENDIAN
420         // write wordLen
421         UINT16 wl = __VAL(wordLen);
422         m_stream->Write(&count, &wl); ASSERT(count == sizeof(UINT16));
423
424 #ifdef __PGFROISUPPORT__
425         // write ROIBlockHeader
426         if (m_roi) {
427                 count = sizeof(ROIBlockHeader);
428                 h.val = __VAL(h.val);
429                 m_stream->Write(&count, &h.val); ASSERT(count == sizeof(ROIBlockHeader));
430         }
431 #endif // __PGFROISUPPORT__
432
433         // convert data
434         for (int i=0; i < wordLen; i++) {
435                 block->m_codeBuffer[i] = __VAL(block->m_codeBuffer[i]);
436         }
437 #else
438         // write wordLen
439         m_stream->Write(&count, &wordLen); ASSERT(count == sizeof(UINT16));
440
441 #ifdef __PGFROISUPPORT__
442         // write ROIBlockHeader
443         if (m_roi) {
444                 count = sizeof(ROIBlockHeader);
445                 m_stream->Write(&count, &h.val); ASSERT(count == sizeof(ROIBlockHeader));
446         }
447 #endif // __PGFROISUPPORT__
448 #endif // PGF_USE_BIG_ENDIAN
449
450         // write encoded data into stream
451         count = wordLen*WordBytes;
452         m_stream->Write(&count, block->m_codeBuffer);
453
454         // store levelLength
455         if (m_levelLength) {
456                 // store level length
457                 // EncodeBuffer has been called after m_lastLevelIndex has been updated
458                 ASSERT(m_currLevelIndex < m_nLevels);
459                 m_levelLength[m_currLevelIndex] += (UINT32)ComputeBufferLength();
460                 m_currLevelIndex = block->m_lastLevelIndex + 1;
461
462         }
463
464         // prepare for next buffer
465         SetBufferStartPos();
466
467         // reset values
468         block->m_valuePos = 0;
469         block->m_maxAbsValue = 0;
470 }

  void CEncoder::WriteValue (CSubband * band, int bandPos)
Write a single value into subband at given position. It might throw an IOException.

Parameters
    band A subband
    bandPos A valid position in subband band

Definition at line 326 of file Encoder.cpp.
326                                                      {
327         if (m_currentBlock->m_valuePos == BufferSize) {
328                 EncodeBuffer(ROIBlockHeader(BufferSize, false));
329         }
330         DataT val = m_currentBlock->m_value[m_currentBlock->m_valuePos++] = band->GetData(bandPos);
331         UINT32 v = abs(val);
332         if (v > m_currentBlock->m_maxAbsValue) m_currentBlock->m_maxAbsValue = v;
333 }

Member Data Documentation

  UINT64 CEncoder::m_bufferStartPos [private]

stream position of encoded buffer

Definition at line 216 of file Encoder.h.

  CMacroBlock* CEncoder::m_currentBlock [private]

current macro block (used by main thread)

Definition at line 221 of file Encoder.h.

  int CEncoder::m_currLevelIndex [private]

counts where (=index) to save next value

Definition at line 224 of file Encoder.h.

  bool CEncoder::m_favorSpeed [private]

favor speed over size

Definition at line 226 of file Encoder.h.

  bool CEncoder::m_forceWriting [private]

all macro blocks have to be written into the stream

Definition at line 227 of file Encoder.h.

  int CEncoder::m_lastMacroBlock [private]

array index of the last created macro block

Definition at line 220 of file Encoder.h.

  UINT32* CEncoder::m_levelLength [private]

temporary saves the level index

Definition at line 223 of file Encoder.h.

  UINT64 CEncoder::m_levelLengthPos [private]

stream position of Metadata

Definition at line 215 of file Encoder.h.

  int CEncoder::m_macroBlockLen [private]

array length

Definition at line 219 of file Encoder.h.

  CMacroBlock** CEncoder::m_macroBlocks [private]

array of macroblocks

Definition at line 218 of file Encoder.h.

  UINT8 CEncoder::m_nLevels [private]

number of levels

Definition at line 225 of file Encoder.h.

  UINT64 CEncoder::m_startPosition [private]

stream position of PGF start (PreHeader)

Definition at line 214 of file Encoder.h.

  CPGFStream* CEncoder::m_stream [private]

output PMF stream

Definition at line 213 of file Encoder.h.

Author

Generated automatically by Doxygen for libpgf from the source code.