|
libpgf
6.14.12
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; m_lastMacroBlock = 0; m_levelLength = NULL; // 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_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 147 of file Encoder.cpp.
{
if (m_macroBlocks) {
for (int i=0; i < m_macroBlockLen; i++) delete m_macroBlocks[i];
delete[] m_macroBlocks;
} else {
delete m_currentBlock;
}
}
| INT64 CEncoder::ComputeBufferLength | ( | ) | const [inline] |
Compute stream length of encoded buffer.
Definition at line 179 of file Encoder.h.
{ return m_stream->GetPos() - m_bufferStartPos; }
| INT64 CEncoder::ComputeHeaderLength | ( | ) | const [inline] |
Compute stream length of header.
Definition at line 174 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 184 of file Encoder.h.
{ return m_stream->GetPos() - m_levelLengthPos; }
| void CEncoder::EncodeBuffer | ( | ROIBlockHeader | h | ) | [private] |
Definition at line 341 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;
#ifdef LIBPGF_USE_OPENMP
#pragma omp parallel for ordered default(shared)
#endif
for (int i=0; i < m_lastMacroBlock; i++) {
if (error == NoError) {
m_macroBlocks[i]->BitplaneEncode();
#ifdef LIBPGF_USE_OPENMP
#pragma omp ordered
#endif
{
try {
WriteMacroBlock(m_macroBlocks[i]);
} catch (IOException& e) {
error = e.error;
}
delete m_macroBlocks[i]; m_macroBlocks[i] = 0;
}
}
}
if (error != NoError) ReturnWithError(error);
*/
#ifdef LIBPGF_USE_OPENMP
#pragma omp parallel for default(shared) //no declared exceptions in next block
#endif
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 121 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 310 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 246 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 188 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 162 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 202 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 160 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 177 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 406 of file Encoder.cpp.
{
ASSERT(block);
#ifdef __PGFROISUPPORT__
ROIBlockHeader h = block->m_header;
#endif
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 326 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] |