|
libpgf
6.11.32
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 () |
| void | EncodeTileBuffer () THROW_ |
| void | SetROI () |
Private Member Functions | |
| void | EncodeBuffer (ROIBlockHeader h) THROW_ |
| void | WriteMacroBlock (CMacroBlock *block) THROW_ |
Private Attributes | |
| CPGFStream * | m_stream |
| UINT64 | m_startPosition |
| UINT64 | m_levelLengthPos |
| UINT64 | m_bufferStartPos |
| CMacroBlock ** | m_macroBlocks |
| int | m_macroBlockLen |
| int | m_lastMacroBlock |
| CMacroBlock * | m_currentBlock |
| UINT32 * | m_levelLength |
| int | m_currLevelIndex |
| UINT8 | m_nLevels |
| bool | m_favorSpeed |
| bool | m_forceWriting |
| bool | m_roi |
PGF encoder.
PGF encoder class.
| 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(); }
| CEncoder::~CEncoder | ( | ) |
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::EncodeTileBuffer | ( | ) | [inline] |
Encodes tile buffer and writes it into stream It might throw an IOException.
Definition at line 171 of file Encoder.h.
{ ASSERT(m_currentBlock && m_currentBlock->m_valuePos >= 0 && m_currentBlock->m_valuePos <= BufferSize); EncodeBuffer(ROIBlockHeader(m_currentBlock->m_valuePos, true)); }
| 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; }
| void CEncoder::SetROI | ( | ) | [inline] |
| 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] |
bool CEncoder::m_roi [private] |
UINT64 CEncoder::m_startPosition [private] |
CPGFStream* CEncoder::m_stream [private] |