libpgf
6.12.24
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, UINT64 &userDataPos, bool useOMP) THROW_ | |
~CEncoder () | |
void | FavorSpeedOverSize () |
void | Flush () THROW_ |
void | UpdatePostHeaderSize (PGFPreHeader preHeader) THROW_ |
UINT32 | WriteLevelLength (UINT32 *&levelLength) THROW_ |
UINT32 | UpdateLevelLength () 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_ |
INT64 | ComputeHeaderLength () const |
INT64 | ComputeBufferLength () const |
INT64 | ComputeOffset () const |
void | SetBufferStartPos () |
Private Member Functions | |
void | EncodeBuffer (ROIBlockHeader h) THROW_ |
void | WriteMacroBlock (CMacroBlock *block) THROW_ |
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 |
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.
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.
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.
: m_stream(stream) , m_bufferStartPos(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(std::nothrow) CMacroBlock*[m_macroBlockLen]; if (!m_macroBlocks) ReturnWithError(InsufficientMemory); 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); } // save user data file position userDataPos = m_stream->GetPos(); if (postHeader.userDataLen) { if (postHeader.userData) { // write user data count = postHeader.userDataLen; m_stream->Write(&count, postHeader.userData); } else { m_stream->SetPos(FSFromCurrent, count); } } // save level length file position m_levelLengthPos = m_stream->GetPos(); }
Destructor
Definition at line 146 of file Encoder.cpp.
{ delete m_currentBlock; delete[] m_macroBlocks; }
INT64 CEncoder::ComputeBufferLength | ( | ) | const [inline] |
Compute stream length of encoded buffer.
Definition at line 175 of file Encoder.h.
{ return m_stream->GetPos() - m_bufferStartPos; }
INT64 CEncoder::ComputeHeaderLength | ( | ) | const [inline] |
Compute stream length of header.
Definition at line 170 of file Encoder.h.
{ return m_levelLengthPos - m_startPosition; }
INT64 CEncoder::ComputeOffset | ( | ) | const [inline] |
Compute file offset between real and expected levelLength position.
Definition at line 180 of file Encoder.h.
{ return m_stream->GetPos() - m_levelLengthPos; }
void CEncoder::EncodeBuffer | ( | ROIBlockHeader | h | ) | [private] |
Definition at line 336 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 117 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 305 of file Encoder.cpp.
{ if (m_currentBlock->m_valuePos > 0) { // 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 from subband into the input buffer of a macro block. It might throw an IOException.
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 241 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 184 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 158 of file Encoder.h.
{ ASSERT(currentLevel >= 0); m_currentBlock->m_lastLevelIndex = m_nLevels - currentLevel - 1; m_forceWriting = true; }
UINT32 CEncoder::UpdateLevelLength | ( | ) |
Write new levelLength into stream. It might throw an IOException.
Definition at line 197 of file Encoder.cpp.
{ UINT64 curPos = m_stream->GetPos(); // end of image // set file pos to levelLength m_stream->SetPos(FSFromStart, m_levelLengthPos); if (m_levelLength) { #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 } else { int count = m_currLevelIndex*WordBytes; m_stream->SetPos(FSFromCurrent, count); } // begin of image UINT32 retValue = UINT32(curPos - m_stream->GetPos()); // restore file position m_stream->SetPos(FSFromStart, curPos); return retValue; }
void CEncoder::UpdatePostHeaderSize | ( | PGFPreHeader | preHeader | ) |
Increase post-header size and write new size into stream.
preHeader | An already filled in PGF pre-header It might throw an IOException. |
Definition at line 155 of file Encoder.cpp.
UINT32 CEncoder::WriteLevelLength | ( | UINT32 *& | levelLength | ) |
Create level length data structure and write a place holder into stream. It might throw an IOException.
levelLength | A reference to an integer array, large enough to save the relative file positions of all PGF levels |
Definition at line 172 of file Encoder.cpp.
{ // renew levelLength delete[] levelLength; levelLength = new(std::nothrow) UINT32[m_nLevels]; if (!levelLength) ReturnWithError(InsufficientMemory); for (UINT8 l = 0; l < m_nLevels; l++) levelLength[l] = 0; m_levelLength = levelLength; // save level length file position m_levelLengthPos = m_stream->GetPos(); // write dummy levelLength int count = m_nLevels*WordBytes; m_stream->Write(&count, m_levelLength); // save current file position SetBufferStartPos(); return count; }
void CEncoder::WriteMacroBlock | ( | CMacroBlock * | block | ) | [private] |
Definition at line 395 of file Encoder.cpp.
{ ASSERT(block); ROIBlockHeader h = block->m_header; UINT16 wordLen = UINT16(NumberOfWords(block->m_codePos)); ASSERT(wordLen <= CodeBufferLen); 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 ASSERT(m_currLevelIndex < m_nLevels); m_levelLength[m_currLevelIndex] += (UINT32)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 321 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] |