libpgf
6.11.42
PGF - Progressive Graphics File
|
PGF encoder. More...
#include <Encoder.h>
Classes | |
class | CMacroBlock |
A macro block is an encoding unit of fixed size (uncoded) More... | |
Public Member Functions | |
CEncoder (CPGFStream *stream, PGFPreHeader preHeader, PGFHeader header, const PGFPostHeader &postHeader, UINT32 *&levelLength, bool useOMP=true) THROW_ | |
~CEncoder () | |
void | FavorSpeedOverSize () |
void | Flush () THROW_ |
UINT32 | WriteLevelLength () THROW_ |
void | Partition (CSubband *band, int width, int height, int startPos, int pitch) THROW_ |
void | SetEncodedLevel (int currentLevel) |
void | WriteValue (CSubband *band, int bandPos) THROW_ |
UINT32 | ComputeHeaderLength () const |
UINT32 | ComputeBufferLength () const |
void | SetBufferStartPos () |
Private Member Functions | |
void | EncodeBuffer (ROIBlockHeader h) THROW_ |
void | WriteMacroBlock (CMacroBlock *block) THROW_ |
Private Attributes | |
CPGFStream * | m_stream |
UINT64 | m_startPosition |
file position of PGF start (PreHeader) | |
UINT64 | m_levelLengthPos |
file position of Metadata | |
UINT64 | m_bufferStartPos |
file 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 |
CEncoder::CEncoder | ( | CPGFStream * | stream, |
PGFPreHeader | preHeader, | ||
PGFHeader | header, | ||
const PGFPostHeader & | postHeader, | ||
UINT32 *& | levelLength, | ||
bool | useOMP = true |
||
) |
Write pre-header, header, postHeader, and levelLength. It might throw an IOException.
stream | A PGF stream |
preHeader | A already filled in PGF pre header |
header | An already filled in PGF header |
postHeader | [in] A already filled in PGF post header (containing color table, user data, ...) |
levelLength | A reference to an integer array, large enough to save the relative file positions of all PGF levels |
useOMP | If true, then the encoder will use multi-threading based on openMP |
Definition at line 66 of file Encoder.cpp.
: m_stream(stream) , m_startPosition(0) , m_currLevelIndex(0) , m_nLevels(header.nLevels) , m_favorSpeed(false) , m_forceWriting(false) #ifdef __PGFROISUPPORT__ , m_roi(false) #endif { ASSERT(m_stream); int count; // 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_lastMacroBlock = 0; m_currentBlock = m_macroBlocks[m_lastMacroBlock++]; } else { m_macroBlocks = 0; m_macroBlockLen = 1; m_currentBlock = new CMacroBlock(this); } // save file position m_startPosition = m_stream->GetPos(); // write preHeader preHeader.hSize = __VAL(preHeader.hSize); count = PreHeaderSize; m_stream->Write(&count, &preHeader); // write file header header.height = __VAL(header.height); header.width = __VAL(header.width); count = HeaderSize; m_stream->Write(&count, &header); // write postHeader if (header.mode == ImageModeIndexedColor) { // write color table count = ColorTableSize; m_stream->Write(&count, (void *)postHeader.clut); } if (postHeader.userData && postHeader.userDataLen) { // write user data count = postHeader.userDataLen; m_stream->Write(&count, postHeader.userData); } // renew levelLength delete[] levelLength; levelLength = new UINT32[m_nLevels]; for (UINT8 l = 0; l < m_nLevels; l++) levelLength[l] = 0; m_levelLength = levelLength; // write dummy levelLength m_levelLengthPos = m_stream->GetPos(); count = m_nLevels*WordBytes; m_stream->Write(&count, m_levelLength); // save current file position SetBufferStartPos(); }
Destructor
Definition at line 146 of file Encoder.cpp.
{ delete m_currentBlock; delete[] m_macroBlocks; }
UINT32 CEncoder::ComputeBufferLength | ( | ) | const [inline] |
Compute stream length of encoded buffer.
Definition at line 161 of file Encoder.h.
{ return UINT32(m_stream->GetPos() - m_bufferStartPos); }
UINT32 CEncoder::ComputeHeaderLength | ( | ) | const [inline] |
Compute stream length of header.
Definition at line 156 of file Encoder.h.
{ return UINT32(m_bufferStartPos - m_startPosition); }
void CEncoder::EncodeBuffer | ( | ROIBlockHeader | h | ) | [private] |
Definition at line 287 of file Encoder.cpp.
{ ASSERT(m_currentBlock); #ifdef __PGFROISUPPORT__ ASSERT(m_roi && h.rbh.bufferSize <= BufferSize || h.rbh.bufferSize == BufferSize); #else ASSERT(h.rbh.bufferSize == BufferSize); #endif m_currentBlock->m_header = h; // macro block management if (m_macroBlockLen == 1) { m_currentBlock->BitplaneEncode(); WriteMacroBlock(m_currentBlock); } else { // save last level index int lastLevelIndex = m_currentBlock->m_lastLevelIndex; if (m_forceWriting || m_lastMacroBlock == m_macroBlockLen) { // encode macro blocks /* volatile OSError error = NoError; #pragma omp parallel for ordered default(shared) for (int i=0; i < m_lastMacroBlock; i++) { if (error == NoError) { m_macroBlocks[i]->BitplaneEncode(); #pragma omp ordered { try { WriteMacroBlock(m_macroBlocks[i]); } catch (IOException& e) { error = e.error; } delete m_macroBlocks[i]; m_macroBlocks[i] = 0; } } } if (error != NoError) ReturnWithError(error); */ #pragma omp parallel for default(shared) //no declared exceptions in next block for (int i=0; i < m_lastMacroBlock; i++) { m_macroBlocks[i]->BitplaneEncode(); } for (int i=0; i < m_lastMacroBlock; i++) { WriteMacroBlock(m_macroBlocks[i]); } // prepare for next round m_forceWriting = false; m_lastMacroBlock = 0; } // re-initialize macro block m_currentBlock = m_macroBlocks[m_lastMacroBlock++]; m_currentBlock->Init(lastLevelIndex); } }
void CEncoder::FavorSpeedOverSize | ( | ) | [inline] |
Encoder favors speed over compression size
Definition at line 116 of file Encoder.h.
{ m_favorSpeed = true; }
void CEncoder::Flush | ( | ) |
Pad buffer with zeros and encode buffer. It might throw an IOException.
Definition at line 225 of file Encoder.cpp.
{ // pad buffer with zeros memset(&(m_currentBlock->m_value[m_currentBlock->m_valuePos]), 0, (BufferSize - m_currentBlock->m_valuePos)*DataTSize); m_currentBlock->m_valuePos = BufferSize; // encode buffer m_forceWriting = true; // makes sure that the following EncodeBuffer is really written into the stream EncodeBuffer(ROIBlockHeader(m_currentBlock->m_valuePos, true)); }
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 into buffer. It might throw an IOException.
band | A subband |
width | The width of the rectangle |
height | The height of the rectangle |
startPos | The buffer position of the top left corner of the rectangular region |
pitch | The number of bytes in row of the subband |
Definition at line 161 of file Encoder.cpp.
{ ASSERT(band); const div_t hh = div(height, LinBlockSize); const div_t ww = div(width, 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++) { WriteValue(band, pos); 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++) { WriteValue(band, pos); 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++) { WriteValue(band, pos); 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++) { WriteValue(band, pos); pos++; } pos += wr; } }
void CEncoder::SetBufferStartPos | ( | ) | [inline] |
Save current stream position as beginning of current level.
Definition at line 165 of file Encoder.h.
{ m_bufferStartPos = m_stream->GetPos(); }
void CEncoder::SetEncodedLevel | ( | int | currentLevel | ) | [inline] |
Informs the encoder about the encoded level.
currentLevel | encoded level [0, nLevels) |
Definition at line 144 of file Encoder.h.
{ ASSERT(currentLevel >= 0); m_currentBlock->m_lastLevelIndex = m_nLevels - currentLevel - 1; m_forceWriting = true; }
UINT32 CEncoder::WriteLevelLength | ( | ) |
Write levelLength into header.
Definition at line 239 of file Encoder.cpp.
{ UINT64 curPos = m_stream->GetPos(); UINT32 retValue = UINT32(curPos - m_startPosition); if (m_levelLength) { // append levelLength to file, directly after post-header // set file pos to levelLength m_stream->SetPos(FSFromStart, m_levelLengthPos); #ifdef PGF_USE_BIG_ENDIAN UINT32 levelLength; int count = WordBytes; for (int i=0; i < m_currLevelIndex; i++) { levelLength = __VAL(UINT32(m_levelLength[i])); m_stream->Write(&count, &levelLength); } #else int count = m_currLevelIndex*WordBytes; m_stream->Write(&count, m_levelLength); #endif //PGF_USE_BIG_ENDIAN // restore file position m_stream->SetPos(FSFromStart, curPos); } return retValue; }
void CEncoder::WriteMacroBlock | ( | CMacroBlock * | block | ) | [private] |
Definition at line 346 of file Encoder.cpp.
{ ASSERT(block); ROIBlockHeader h = block->m_header; UINT16 wordLen = UINT16(NumberOfWords(block->m_codePos)); ASSERT(wordLen <= BufferSize); int count = sizeof(UINT16); #ifdef TRACE //UINT32 filePos = (UINT32)m_stream->GetPos(); //printf("EncodeBuffer: %d\n", filePos); #endif #ifdef PGF_USE_BIG_ENDIAN // write wordLen UINT16 wl = __VAL(wordLen); m_stream->Write(&count, &wl); ASSERT(count == sizeof(UINT16)); #ifdef __PGFROISUPPORT__ // write ROIBlockHeader if (m_roi) { h.val = __VAL(h.val); m_stream->Write(&count, &h.val); ASSERT(count == sizeof(UINT16)); } #endif // __PGFROISUPPORT__ // convert data for (int i=0; i < wordLen; i++) { block->m_codeBuffer[i] = __VAL(block->m_codeBuffer[i]); } #else // write wordLen m_stream->Write(&count, &wordLen); ASSERT(count == sizeof(UINT16)); #ifdef __PGFROISUPPORT__ // write ROIBlockHeader if (m_roi) { m_stream->Write(&count, &h.val); ASSERT(count == sizeof(UINT16)); } #endif // __PGFROISUPPORT__ #endif // PGF_USE_BIG_ENDIAN // write encoded data into stream count = wordLen*WordBytes; m_stream->Write(&count, block->m_codeBuffer); // store levelLength if (m_levelLength) { // store level length // EncodeBuffer has been called after m_lastLevelIndex has been updated m_levelLength[m_currLevelIndex] += ComputeBufferLength(); m_currLevelIndex = block->m_lastLevelIndex + 1; } // prepare for next buffer SetBufferStartPos(); // reset values block->m_valuePos = 0; block->m_maxAbsValue = 0; }
void CEncoder::WriteValue | ( | CSubband * | band, |
int | bandPos | ||
) |
Write a single value into subband at given position. It might throw an IOException.
band | A subband |
bandPos | A valid position in subband band |
Definition at line 272 of file Encoder.cpp.
{ if (m_currentBlock->m_valuePos == BufferSize) { EncodeBuffer(ROIBlockHeader(BufferSize, false)); } DataT val = m_currentBlock->m_value[m_currentBlock->m_valuePos++] = band->GetData(bandPos); UINT32 v = abs(val); if (v > m_currentBlock->m_maxAbsValue) m_currentBlock->m_maxAbsValue = v; }
UINT64 CEncoder::m_bufferStartPos [private] |
CMacroBlock* CEncoder::m_currentBlock [private] |
int CEncoder::m_currLevelIndex [private] |
bool CEncoder::m_favorSpeed [private] |
bool CEncoder::m_forceWriting [private] |
int CEncoder::m_lastMacroBlock [private] |
UINT32* CEncoder::m_levelLength [private] |
UINT64 CEncoder::m_levelLengthPos [private] |
int CEncoder::m_macroBlockLen [private] |
CMacroBlock** CEncoder::m_macroBlocks [private] |
UINT8 CEncoder::m_nLevels [private] |
UINT64 CEncoder::m_startPosition [private] |
CPGFStream* CEncoder::m_stream [private] |