File indexing completed on 2025-01-19 03:56:09
0001 /* 0002 * The Progressive Graphics File; http://www.libpgf.org 0003 * 0004 * $Date: 2007-02-03 13:04:21 +0100 (Sa, 03 Feb 2007) $ 0005 * $Revision: 280 $ 0006 * 0007 * This file Copyright (C) 2006 xeraina GmbH, Switzerland 0008 * 0009 * This program is free software; you can redistribute it and/or 0010 * modify it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE 0011 * as published by the Free Software Foundation; either version 2.1 0012 * of the License, or (at your option) any later version. 0013 * 0014 * This program is distributed in the hope that it will be useful, 0015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0017 * GNU General Public License for more details. 0018 * 0019 * You should have received a copy of the GNU General Public License 0020 * along with this program; if not, write to the Free Software 0021 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 0022 */ 0023 0024 ////////////////////////////////////////////////////////////////////// 0025 /// @file Encoder.cpp 0026 /// @brief PGF encoder class implementation 0027 /// @author C. Stamm, R. Spuler 0028 0029 #include "Encoder.h" 0030 #ifdef TRACE 0031 #include <stdio.h> 0032 #endif 0033 0034 ////////////////////////////////////////////////////// 0035 // PGF: file structure 0036 // 0037 // PGFPreHeader PGFHeader [PGFPostHeader] LevelLengths Level_n-1 Level_n-2 ... Level_0 0038 // PGFPostHeader ::= [ColorTable] [UserData] 0039 // LevelLengths ::= UINT32[nLevels] 0040 0041 ////////////////////////////////////////////////////// 0042 // Encoding scheme 0043 // input: wavelet coefficients stored in subbands 0044 // output: binary file 0045 // 0046 // subband 0047 // | 0048 // m_value [BufferSize] 0049 // | | | 0050 // m_sign sigBits refBits [BufferSize, BufferLen, BufferLen] 0051 // | | | 0052 // m_codeBuffer (for each plane: RLcodeLength (16 bit), RLcoded sigBits + m_sign, refBits) 0053 // | 0054 // file (for each buffer: packedLength (16 bit), packed bits) 0055 // 0056 0057 // Constants 0058 #define CodeBufferBitLen (CodeBufferLen*WordWidth) ///< max number of bits in m_codeBuffer 0059 #define MaxCodeLen ((1 << RLblockSizeLen) - 1) ///< max length of RL encoded block 0060 0061 ////////////////////////////////////////////////////// 0062 /// Write pre-header, header, postHeader, and levelLength. 0063 /// It might throw an IOException. 0064 /// @param stream A PGF stream 0065 /// @param preHeader A already filled in PGF pre-header 0066 /// @param header An already filled in PGF header 0067 /// @param postHeader [in] An already filled in PGF post-header (containing color table, user data, ...) 0068 /// @param userDataPos [out] File position of user data 0069 /// @param useOMP If true, then the encoder will use multi-threading based on openMP 0070 CEncoder::CEncoder(CPGFStream* stream, PGFPreHeader preHeader, PGFHeader header, const PGFPostHeader& postHeader, UINT64& userDataPos, bool useOMP) 0071 : m_stream(stream) 0072 , m_bufferStartPos(0) 0073 , m_currLevelIndex(0) 0074 , m_nLevels(header.nLevels) 0075 , m_favorSpeed(false) 0076 , m_forceWriting(false) 0077 #ifdef __PGFROISUPPORT__ 0078 , m_roi(false) 0079 #endif 0080 { 0081 ASSERT(m_stream); 0082 0083 int count; 0084 m_lastMacroBlock = 0; 0085 m_levelLength = nullptr; 0086 0087 // set number of threads 0088 #ifdef LIBPGF_USE_OPENMP 0089 m_macroBlockLen = omp_get_num_procs(); 0090 #else 0091 m_macroBlockLen = 1; 0092 #endif 0093 0094 if (useOMP && m_macroBlockLen > 1) { 0095 #ifdef LIBPGF_USE_OPENMP 0096 omp_set_num_threads(m_macroBlockLen); 0097 #endif 0098 // create macro block array 0099 m_macroBlocks = new(std::nothrow) CMacroBlock*[m_macroBlockLen]; 0100 if (!m_macroBlocks) ReturnWithError(InsufficientMemory); 0101 for (int i=0; i < m_macroBlockLen; i++) m_macroBlocks[i] = new CMacroBlock(this); 0102 m_currentBlock = m_macroBlocks[m_lastMacroBlock++]; 0103 } else { 0104 m_macroBlocks = 0; 0105 m_macroBlockLen = 1; 0106 m_currentBlock = new CMacroBlock(this); 0107 } 0108 0109 // save file position 0110 m_startPosition = m_stream->GetPos(); 0111 0112 // write preHeader 0113 preHeader.hSize = __VAL(preHeader.hSize); 0114 count = PreHeaderSize; 0115 m_stream->Write(&count, &preHeader); 0116 0117 // write file header 0118 header.height = __VAL(header.height); 0119 header.width = __VAL(header.width); 0120 count = HeaderSize; 0121 m_stream->Write(&count, &header); 0122 0123 // write postHeader 0124 if (header.mode == ImageModeIndexedColor) { 0125 // write color table 0126 count = ColorTableSize; 0127 m_stream->Write(&count, (void *)postHeader.clut); 0128 } 0129 // save user data file position 0130 userDataPos = m_stream->GetPos(); 0131 if (postHeader.userDataLen) { 0132 if (postHeader.userData) { 0133 // write user data 0134 count = postHeader.userDataLen; 0135 m_stream->Write(&count, postHeader.userData); 0136 } else { 0137 m_stream->SetPos(FSFromCurrent, count); 0138 } 0139 } 0140 0141 // save level length file position 0142 m_levelLengthPos = m_stream->GetPos(); 0143 } 0144 0145 ////////////////////////////////////////////////////// 0146 // Destructor 0147 CEncoder::~CEncoder() { 0148 if (m_macroBlocks) { 0149 for (int i=0; i < m_macroBlockLen; i++) delete m_macroBlocks[i]; 0150 delete[] m_macroBlocks; 0151 } else { 0152 delete m_currentBlock; 0153 } 0154 } 0155 0156 ///////////////////////////////////////////////////////////////////// 0157 /// Increase post-header size and write new size into stream. 0158 /// @param preHeader An already filled in PGF pre-header 0159 /// It might throw an IOException. 0160 void CEncoder::UpdatePostHeaderSize(PGFPreHeader preHeader) { 0161 UINT64 curPos = m_stream->GetPos(); // end of user data 0162 int count = PreHeaderSize; 0163 0164 // write preHeader 0165 SetStreamPosToStart(); 0166 preHeader.hSize = __VAL(preHeader.hSize); 0167 m_stream->Write(&count, &preHeader); 0168 0169 m_stream->SetPos(FSFromStart, curPos); 0170 } 0171 0172 ///////////////////////////////////////////////////////////////////// 0173 /// Create level length data structure and write a place holder into stream. 0174 /// It might throw an IOException. 0175 /// @param levelLength A reference to an integer array, large enough to save the relative file positions of all PGF levels 0176 /// @return number of bytes written into stream 0177 UINT32 CEncoder::WriteLevelLength(UINT32*& levelLength) { 0178 // renew levelLength 0179 delete[] levelLength; 0180 levelLength = new(std::nothrow) UINT32[m_nLevels]; 0181 if (!levelLength) ReturnWithError(InsufficientMemory); 0182 for (UINT8 l = 0; l < m_nLevels; l++) levelLength[l] = 0; 0183 m_levelLength = levelLength; 0184 0185 // save level length file position 0186 m_levelLengthPos = m_stream->GetPos(); 0187 0188 // write dummy levelLength 0189 int count = m_nLevels*WordBytes; 0190 m_stream->Write(&count, m_levelLength); 0191 0192 // save current file position 0193 SetBufferStartPos(); 0194 0195 return count; 0196 } 0197 0198 ////////////////////////////////////////////////////// 0199 /// Write new levelLength into stream. 0200 /// It might throw an IOException. 0201 /// @return Written image bytes. 0202 UINT32 CEncoder::UpdateLevelLength() { 0203 UINT64 curPos = m_stream->GetPos(); // end of image 0204 0205 // set file pos to levelLength 0206 m_stream->SetPos(FSFromStart, m_levelLengthPos); 0207 0208 if (m_levelLength) { 0209 #ifdef PGF_USE_BIG_ENDIAN 0210 UINT32 levelLength; 0211 int count = WordBytes; 0212 0213 for (int i=0; i < m_currLevelIndex; i++) { 0214 levelLength = __VAL(UINT32(m_levelLength[i])); 0215 m_stream->Write(&count, &levelLength); 0216 } 0217 #else 0218 int count = m_currLevelIndex*WordBytes; 0219 0220 m_stream->Write(&count, m_levelLength); 0221 #endif //PGF_USE_BIG_ENDIAN 0222 } else { 0223 int count = m_currLevelIndex*WordBytes; 0224 m_stream->SetPos(FSFromCurrent, count); 0225 } 0226 0227 // begin of image 0228 UINT32 retValue = UINT32(curPos - m_stream->GetPos()); 0229 0230 // restore file position 0231 m_stream->SetPos(FSFromStart, curPos); 0232 0233 return retValue; 0234 } 0235 0236 ///////////////////////////////////////////////////////////////////// 0237 /// Partitions a rectangular region of a given subband. 0238 /// Partitioning scheme: The plane is partitioned in squares of side length LinBlockSize. 0239 /// Write wavelet coefficients from subband into the input buffer of a macro block. 0240 /// It might throw an IOException. 0241 /// @param band A subband 0242 /// @param width The width of the rectangle 0243 /// @param height The height of the rectangle 0244 /// @param startPos The absolute subband position of the top left corner of the rectangular region 0245 /// @param pitch The number of bytes in row of the subband 0246 void CEncoder::Partition(CSubband* band, int width, int height, int startPos, int pitch) { 0247 ASSERT(band); 0248 0249 const div_t hh = div(height, LinBlockSize); 0250 const div_t ww = div(width, LinBlockSize); 0251 const int ws = pitch - LinBlockSize; 0252 const int wr = pitch - ww.rem; 0253 int pos, base = startPos, base2; 0254 0255 // main height 0256 for (int i=0; i < hh.quot; i++) { 0257 // main width 0258 base2 = base; 0259 for (int j=0; j < ww.quot; j++) { 0260 pos = base2; 0261 for (int y=0; y < LinBlockSize; y++) { 0262 for (int x=0; x < LinBlockSize; x++) { 0263 WriteValue(band, pos); 0264 pos++; 0265 } 0266 pos += ws; 0267 } 0268 base2 += LinBlockSize; 0269 } 0270 // rest of width 0271 pos = base2; 0272 for (int y=0; y < LinBlockSize; y++) { 0273 for (int x=0; x < ww.rem; x++) { 0274 WriteValue(band, pos); 0275 pos++; 0276 } 0277 pos += wr; 0278 base += pitch; 0279 } 0280 } 0281 // main width 0282 base2 = base; 0283 for (int j=0; j < ww.quot; j++) { 0284 // rest of height 0285 pos = base2; 0286 for (int y=0; y < hh.rem; y++) { 0287 for (int x=0; x < LinBlockSize; x++) { 0288 WriteValue(band, pos); 0289 pos++; 0290 } 0291 pos += ws; 0292 } 0293 base2 += LinBlockSize; 0294 } 0295 // rest of height 0296 pos = base2; 0297 for (int y=0; y < hh.rem; y++) { 0298 // rest of width 0299 for (int x=0; x < ww.rem; x++) { 0300 WriteValue(band, pos); 0301 pos++; 0302 } 0303 pos += wr; 0304 } 0305 } 0306 0307 ////////////////////////////////////////////////////// 0308 /// Pad buffer with zeros and encode buffer. 0309 /// It might throw an IOException. 0310 void CEncoder::Flush() { 0311 if (m_currentBlock->m_valuePos > 0) { 0312 // pad buffer with zeros 0313 memset(&(m_currentBlock->m_value[m_currentBlock->m_valuePos]), 0, (BufferSize - m_currentBlock->m_valuePos)*DataTSize); 0314 m_currentBlock->m_valuePos = BufferSize; 0315 0316 // encode buffer 0317 m_forceWriting = true; // makes sure that the following EncodeBuffer is really written into the stream 0318 EncodeBuffer(ROIBlockHeader(m_currentBlock->m_valuePos, true)); 0319 } 0320 } 0321 0322 ///////////////////////////////////////////////////////////////////// 0323 // Stores band value from given position bandPos into buffer m_value at position m_valuePos 0324 // If buffer is full encode it to file 0325 // It might throw an IOException. 0326 void CEncoder::WriteValue(CSubband* band, int bandPos) { 0327 if (m_currentBlock->m_valuePos == BufferSize) { 0328 EncodeBuffer(ROIBlockHeader(BufferSize, false)); 0329 } 0330 DataT val = m_currentBlock->m_value[m_currentBlock->m_valuePos++] = band->GetData(bandPos); 0331 UINT32 v = abs(val); 0332 if (v > m_currentBlock->m_maxAbsValue) m_currentBlock->m_maxAbsValue = v; 0333 } 0334 0335 ///////////////////////////////////////////////////////////////////// 0336 // Encode buffer and write data into stream. 0337 // h contains buffer size and flag indicating end of tile. 0338 // Encoding scheme: <wordLen>(16 bits) [ ROI ] data 0339 // ROI ::= <bufferSize>(15 bits) <eofTile>(1 bit) 0340 // It might throw an IOException. 0341 void CEncoder::EncodeBuffer(ROIBlockHeader h) { 0342 ASSERT(m_currentBlock); 0343 #ifdef __PGFROISUPPORT__ 0344 ASSERT(m_roi && h.rbh.bufferSize <= BufferSize || h.rbh.bufferSize == BufferSize); 0345 #else 0346 ASSERT(h.rbh.bufferSize == BufferSize); 0347 #endif 0348 m_currentBlock->m_header = h; 0349 0350 // macro block management 0351 if (m_macroBlockLen == 1) { 0352 m_currentBlock->BitplaneEncode(); 0353 WriteMacroBlock(m_currentBlock); 0354 } else { 0355 // save last level index 0356 int lastLevelIndex = m_currentBlock->m_lastLevelIndex; 0357 0358 if (m_forceWriting || m_lastMacroBlock == m_macroBlockLen) { 0359 // encode macro blocks 0360 /* 0361 volatile OSError error = NoError; 0362 #ifdef LIBPGF_USE_OPENMP 0363 #pragma omp parallel for ordered default(shared) 0364 #endif 0365 for (int i=0; i < m_lastMacroBlock; i++) { 0366 if (error == NoError) { 0367 m_macroBlocks[i]->BitplaneEncode(); 0368 #ifdef LIBPGF_USE_OPENMP 0369 #pragma omp ordered 0370 #endif 0371 { 0372 try { 0373 WriteMacroBlock(m_macroBlocks[i]); 0374 } catch (IOException& e) { 0375 error = e.error; 0376 } 0377 delete m_macroBlocks[i]; m_macroBlocks[i] = 0; 0378 } 0379 } 0380 } 0381 if (error != NoError) ReturnWithError(error); 0382 */ 0383 #ifdef LIBPGF_USE_OPENMP 0384 #pragma omp parallel for default(shared) //no declared exceptions in next block 0385 #endif 0386 for (int i=0; i < m_lastMacroBlock; i++) { 0387 m_macroBlocks[i]->BitplaneEncode(); 0388 } 0389 for (int i=0; i < m_lastMacroBlock; i++) { 0390 WriteMacroBlock(m_macroBlocks[i]); 0391 } 0392 0393 // prepare for next round 0394 m_forceWriting = false; 0395 m_lastMacroBlock = 0; 0396 } 0397 // re-initialize macro block 0398 m_currentBlock = m_macroBlocks[m_lastMacroBlock++]; 0399 m_currentBlock->Init(lastLevelIndex); 0400 } 0401 } 0402 0403 ///////////////////////////////////////////////////////////////////// 0404 // Write encoded macro block into stream. 0405 // It might throw an IOException. 0406 void CEncoder::WriteMacroBlock(CMacroBlock* block) { 0407 ASSERT(block); 0408 #ifdef __PGFROISUPPORT__ 0409 ROIBlockHeader h = block->m_header; 0410 #endif 0411 UINT16 wordLen = UINT16(NumberOfWords(block->m_codePos)); ASSERT(wordLen <= CodeBufferLen); 0412 int count = sizeof(UINT16); 0413 0414 #ifdef TRACE 0415 //UINT32 filePos = (UINT32)m_stream->GetPos(); 0416 //printf("EncodeBuffer: %d\n", filePos); 0417 #endif 0418 0419 #ifdef PGF_USE_BIG_ENDIAN 0420 // write wordLen 0421 UINT16 wl = __VAL(wordLen); 0422 m_stream->Write(&count, &wl); ASSERT(count == sizeof(UINT16)); 0423 0424 #ifdef __PGFROISUPPORT__ 0425 // write ROIBlockHeader 0426 if (m_roi) { 0427 count = sizeof(ROIBlockHeader); 0428 h.val = __VAL(h.val); 0429 m_stream->Write(&count, &h.val); ASSERT(count == sizeof(ROIBlockHeader)); 0430 } 0431 #endif // __PGFROISUPPORT__ 0432 0433 // convert data 0434 for (int i=0; i < wordLen; i++) { 0435 block->m_codeBuffer[i] = __VAL(block->m_codeBuffer[i]); 0436 } 0437 #else 0438 // write wordLen 0439 m_stream->Write(&count, &wordLen); ASSERT(count == sizeof(UINT16)); 0440 0441 #ifdef __PGFROISUPPORT__ 0442 // write ROIBlockHeader 0443 if (m_roi) { 0444 count = sizeof(ROIBlockHeader); 0445 m_stream->Write(&count, &h.val); ASSERT(count == sizeof(ROIBlockHeader)); 0446 } 0447 #endif // __PGFROISUPPORT__ 0448 #endif // PGF_USE_BIG_ENDIAN 0449 0450 // write encoded data into stream 0451 count = wordLen*WordBytes; 0452 m_stream->Write(&count, block->m_codeBuffer); 0453 0454 // store levelLength 0455 if (m_levelLength) { 0456 // store level length 0457 // EncodeBuffer has been called after m_lastLevelIndex has been updated 0458 ASSERT(m_currLevelIndex < m_nLevels); 0459 m_levelLength[m_currLevelIndex] += (UINT32)ComputeBufferLength(); 0460 m_currLevelIndex = block->m_lastLevelIndex + 1; 0461 0462 } 0463 0464 // prepare for next buffer 0465 SetBufferStartPos(); 0466 0467 // reset values 0468 block->m_valuePos = 0; 0469 block->m_maxAbsValue = 0; 0470 } 0471 0472 //////////////////////////////////////////////////////// 0473 // Encode buffer of given size using bit plane coding. 0474 // A buffer contains bufferLen UINT32 values, thus, bufferSize bits per bit plane. 0475 // Following coding scheme is used: 0476 // Buffer ::= <nPlanes>(5 bits) Q_FOREACH (plane i): Plane[i] 0477 // Plane[i] ::= [ Sig1 | Sig2 ] [DWORD alignment] refBits 0478 // Sig1 ::= 1 <codeLen>(15 bits) codedSigAndSignBits 0479 // Sig2 ::= 0 <sigLen>(15 bits) [Sign1 | Sign2 ] [DWORD alignment] sigBits 0480 // Sign1 ::= 1 <codeLen>(15 bits) codedSignBits 0481 // Sign2 ::= 0 <signLen>(15 bits) [DWORD alignment] signBits 0482 void CEncoder::CMacroBlock::BitplaneEncode() { 0483 UINT8 nPlanes; 0484 UINT32 sigLen, codeLen = 0, wordPos, refLen, signLen; 0485 UINT32 sigBits[BufferLen] = { 0 }; 0486 UINT32 refBits[BufferLen] = { 0 }; 0487 UINT32 signBits[BufferLen] = { 0 }; 0488 UINT32 planeMask; 0489 UINT32 bufferSize = m_header.rbh.bufferSize; ASSERT(bufferSize <= BufferSize); 0490 bool useRL; 0491 0492 #ifdef TRACE 0493 //printf("which thread: %d\n", omp_get_thread_num()); 0494 #endif 0495 0496 // clear significance vector 0497 for (UINT32 k=0; k < bufferSize; k++) { 0498 m_sigFlagVector[k] = false; 0499 } 0500 m_sigFlagVector[bufferSize] = true; // sentinel 0501 0502 // clear output buffer 0503 for (UINT32 k=0; k < bufferSize; k++) { 0504 m_codeBuffer[k] = 0; 0505 } 0506 m_codePos = 0; 0507 0508 // compute number of bit planes and split buffer into separate bit planes 0509 nPlanes = NumberOfBitplanes(); 0510 0511 // write number of bit planes to m_codeBuffer 0512 // <nPlanes> 0513 SetValueBlock(m_codeBuffer, 0, nPlanes, MaxBitPlanesLog); 0514 m_codePos += MaxBitPlanesLog; 0515 0516 // loop through all bit planes 0517 if (nPlanes == 0) nPlanes = MaxBitPlanes + 1; 0518 planeMask = 1 << (nPlanes - 1); 0519 0520 for (int plane = nPlanes - 1; plane >= 0; plane--) { 0521 // clear significant bitset 0522 for (UINT32 k=0; k < BufferLen; k++) { 0523 sigBits[k] = 0; 0524 } 0525 0526 // split bitplane in significant bitset and refinement bitset 0527 sigLen = DecomposeBitplane(bufferSize, planeMask, m_codePos + RLblockSizeLen + 1, sigBits, refBits, signBits, signLen, codeLen); 0528 0529 if (sigLen > 0 && codeLen <= MaxCodeLen && codeLen < AlignWordPos(sigLen) + AlignWordPos(signLen) + 2*RLblockSizeLen) { 0530 // set RL code bit 0531 // <1><codeLen> 0532 SetBit(m_codeBuffer, m_codePos++); 0533 0534 // write length codeLen to m_codeBuffer 0535 SetValueBlock(m_codeBuffer, m_codePos, codeLen, RLblockSizeLen); 0536 m_codePos += RLblockSizeLen + codeLen; 0537 } else { 0538 #ifdef TRACE 0539 //printf("new\n"); 0540 //for (UINT32 i=0; i < bufferSize; i++) { 0541 // printf("%s", (GetBit(sigBits, i)) ? "1" : "_"); 0542 // if (i%120 == 119) printf("\n"); 0543 //} 0544 //printf("\n"); 0545 #endif // TRACE 0546 0547 // run-length coding wasn't efficient enough 0548 // we don't use RL coding for sigBits 0549 // <0><sigLen> 0550 ClearBit(m_codeBuffer, m_codePos++); 0551 0552 // write length sigLen to m_codeBuffer 0553 ASSERT(sigLen <= MaxCodeLen); 0554 SetValueBlock(m_codeBuffer, m_codePos, sigLen, RLblockSizeLen); 0555 m_codePos += RLblockSizeLen; 0556 0557 if (m_encoder->m_favorSpeed || signLen == 0) { 0558 useRL = false; 0559 } else { 0560 // overwrite m_codeBuffer 0561 useRL = true; 0562 // run-length encode m_sign and append them to the m_codeBuffer 0563 codeLen = RLESigns(m_codePos + RLblockSizeLen + 1, signBits, signLen); 0564 } 0565 0566 if (useRL && codeLen <= MaxCodeLen && codeLen < signLen) { 0567 // RL encoding of m_sign was efficient 0568 // <1><codeLen><codedSignBits>_ 0569 // write RL code bit 0570 SetBit(m_codeBuffer, m_codePos++); 0571 0572 // write codeLen to m_codeBuffer 0573 SetValueBlock(m_codeBuffer, m_codePos, codeLen, RLblockSizeLen); 0574 0575 // compute position of sigBits 0576 wordPos = NumberOfWords(m_codePos + RLblockSizeLen + codeLen); 0577 ASSERT(0 <= wordPos && wordPos < CodeBufferLen); 0578 } else { 0579 // RL encoding of signBits wasn't efficient 0580 // <0><signLen>_<signBits>_ 0581 // clear RL code bit 0582 ClearBit(m_codeBuffer, m_codePos++); 0583 0584 // write signLen to m_codeBuffer 0585 ASSERT(signLen <= MaxCodeLen); 0586 SetValueBlock(m_codeBuffer, m_codePos, signLen, RLblockSizeLen); 0587 0588 // write signBits to m_codeBuffer 0589 wordPos = NumberOfWords(m_codePos + RLblockSizeLen); 0590 ASSERT(0 <= wordPos && wordPos < CodeBufferLen); 0591 codeLen = NumberOfWords(signLen); 0592 0593 for (UINT32 k=0; k < codeLen; k++) { 0594 m_codeBuffer[wordPos++] = signBits[k]; 0595 } 0596 } 0597 0598 // write sigBits 0599 // <sigBits>_ 0600 ASSERT(0 <= wordPos && wordPos < CodeBufferLen); 0601 refLen = NumberOfWords(sigLen); 0602 0603 for (UINT32 k=0; k < refLen; k++) { 0604 m_codeBuffer[wordPos++] = sigBits[k]; 0605 } 0606 m_codePos = wordPos << WordWidthLog; 0607 } 0608 0609 // append refinement bitset (aligned to word boundary) 0610 // _<refBits> 0611 wordPos = NumberOfWords(m_codePos); 0612 ASSERT(0 <= wordPos && wordPos < CodeBufferLen); 0613 refLen = NumberOfWords(bufferSize - sigLen); 0614 0615 for (UINT32 k=0; k < refLen; k++) { 0616 m_codeBuffer[wordPos++] = refBits[k]; 0617 } 0618 m_codePos = wordPos << WordWidthLog; 0619 planeMask >>= 1; 0620 } 0621 ASSERT(0 <= m_codePos && m_codePos <= CodeBufferBitLen); 0622 } 0623 0624 ////////////////////////////////////////////////////////// 0625 // Split bitplane of length bufferSize into significant and refinement bitset 0626 // returns length [bits] of significant bits 0627 // input: bufferSize, planeMask, codePos 0628 // output: sigBits, refBits, signBits, signLen [bits], codeLen [bits] 0629 // RLE 0630 // - Encode run of 2^k zeros by a single 0. 0631 // - Encode run of count 0's followed by a 1 with codeword: 1<count>x 0632 // - x is 0: if a positive sign is stored, otherwise 1 0633 // - Store each bit in m_codeBuffer[codePos] and increment codePos. 0634 UINT32 CEncoder::CMacroBlock::DecomposeBitplane(UINT32 bufferSize, UINT32 planeMask, UINT32 codePos, UINT32* sigBits, UINT32* refBits, UINT32* signBits, UINT32& signLen, UINT32& codeLen) { 0635 ASSERT(sigBits); 0636 ASSERT(refBits); 0637 ASSERT(signBits); 0638 ASSERT(codePos < CodeBufferBitLen); 0639 0640 UINT32 sigPos = 0; 0641 UINT32 valuePos = 0, valueEnd; 0642 UINT32 refPos = 0; 0643 0644 // set output value 0645 signLen = 0; 0646 0647 // prepare RLE of Sigs and Signs 0648 const UINT32 outStartPos = codePos; 0649 UINT32 k = 3; 0650 UINT32 runlen = 1 << k; // = 2^k 0651 UINT32 count = 0; 0652 0653 while (valuePos < bufferSize) { 0654 // search next 1 in m_sigFlagVector using searching with sentinel 0655 valueEnd = valuePos; 0656 while(!m_sigFlagVector[valueEnd]) { valueEnd++; } 0657 0658 // search 1's in m_value[plane][valuePos..valueEnd) 0659 // these 1's are significant bits 0660 while (valuePos < valueEnd) { 0661 if (GetBitAtPos(valuePos, planeMask)) { 0662 // RLE encoding 0663 // encode run of count 0's followed by a 1 0664 // with codeword: 1<count>(signBits[signPos]) 0665 SetBit(m_codeBuffer, codePos++); 0666 if (k > 0) { 0667 SetValueBlock(m_codeBuffer, codePos, count, k); 0668 codePos += k; 0669 0670 // adapt k (half the zero run-length) 0671 k--; 0672 runlen >>= 1; 0673 } 0674 0675 // copy and write sign bit 0676 if (m_value[valuePos] < 0) { 0677 SetBit(signBits, signLen++); 0678 SetBit(m_codeBuffer, codePos++); 0679 } else { 0680 ClearBit(signBits, signLen++); 0681 ClearBit(m_codeBuffer, codePos++); 0682 } 0683 0684 // write a 1 to sigBits 0685 SetBit(sigBits, sigPos++); 0686 0687 // update m_sigFlagVector 0688 m_sigFlagVector[valuePos] = true; 0689 0690 // prepare for next run 0691 count = 0; 0692 } else { 0693 // RLE encoding 0694 count++; 0695 if (count == runlen) { 0696 // encode run of 2^k zeros by a single 0 0697 ClearBit(m_codeBuffer, codePos++); 0698 // adapt k (double the zero run-length) 0699 if (k < WordWidth) { 0700 k++; 0701 runlen <<= 1; 0702 } 0703 0704 // prepare for next run 0705 count = 0; 0706 } 0707 0708 // write 0 to sigBits 0709 sigPos++; 0710 } 0711 valuePos++; 0712 } 0713 // refinement bit 0714 if (valuePos < bufferSize) { 0715 // write one refinement bit 0716 if (GetBitAtPos(valuePos++, planeMask)) { 0717 SetBit(refBits, refPos); 0718 } else { 0719 ClearBit(refBits, refPos); 0720 } 0721 refPos++; 0722 } 0723 } 0724 // RLE encoding of the rest of the plane 0725 // encode run of count 0's followed by a 1 0726 // with codeword: 1<count>(signBits[signPos]) 0727 SetBit(m_codeBuffer, codePos++); 0728 if (k > 0) { 0729 SetValueBlock(m_codeBuffer, codePos, count, k); 0730 codePos += k; 0731 } 0732 // write dmmy sign bit 0733 SetBit(m_codeBuffer, codePos++); 0734 0735 // write word filler zeros 0736 0737 ASSERT(sigPos <= bufferSize); 0738 ASSERT(refPos <= bufferSize); 0739 ASSERT(signLen <= bufferSize); 0740 ASSERT(valuePos == bufferSize); 0741 ASSERT(codePos >= outStartPos && codePos < CodeBufferBitLen); 0742 codeLen = codePos - outStartPos; 0743 0744 return sigPos; 0745 } 0746 0747 0748 /////////////////////////////////////////////////////// 0749 // Compute number of bit planes needed 0750 UINT8 CEncoder::CMacroBlock::NumberOfBitplanes() { 0751 UINT8 cnt = 0; 0752 0753 // determine number of bitplanes for max value 0754 if (m_maxAbsValue > 0) { 0755 while (m_maxAbsValue > 0) { 0756 m_maxAbsValue >>= 1; cnt++; 0757 } 0758 if (cnt == MaxBitPlanes + 1) cnt = 0; 0759 // end cs 0760 ASSERT(cnt <= MaxBitPlanes); 0761 ASSERT((cnt >> MaxBitPlanesLog) == 0); 0762 return cnt; 0763 } else { 0764 return 1; 0765 } 0766 } 0767 0768 ////////////////////////////////////////////////////// 0769 // Adaptive Run-Length encoder for long sequences of ones. 0770 // Returns length of output in bits. 0771 // - Encode run of 2^k ones by a single 1. 0772 // - Encode run of count 1's followed by a 0 with codeword: 0<count>. 0773 // - Store each bit in m_codeBuffer[codePos] and increment codePos. 0774 UINT32 CEncoder::CMacroBlock::RLESigns(UINT32 codePos, UINT32* signBits, UINT32 signLen) { 0775 ASSERT(signBits); 0776 ASSERT(0 <= codePos && codePos < CodeBufferBitLen); 0777 ASSERT(0 < signLen && signLen <= BufferSize); 0778 0779 const UINT32 outStartPos = codePos; 0780 UINT32 k = 0; 0781 UINT32 runlen = 1 << k; // = 2^k 0782 UINT32 count = 0; 0783 UINT32 signPos = 0; 0784 0785 while (signPos < signLen) { 0786 // search next 0 in signBits starting at position signPos 0787 count = SeekBit1Range(signBits, signPos, __min(runlen, signLen - signPos)); 0788 // count 1's found 0789 if (count == runlen) { 0790 // encode run of 2^k ones by a single 1 0791 signPos += count; 0792 SetBit(m_codeBuffer, codePos++); 0793 // adapt k (double the 1's run-length) 0794 if (k < WordWidth) { 0795 k++; 0796 runlen <<= 1; 0797 } 0798 } else { 0799 // encode run of count 1's followed by a 0 0800 // with codeword: 0(count) 0801 signPos += count + 1; 0802 ClearBit(m_codeBuffer, codePos++); 0803 if (k > 0) { 0804 SetValueBlock(m_codeBuffer, codePos, count, k); 0805 codePos += k; 0806 } 0807 // adapt k (half the 1's run-length) 0808 if (k > 0) { 0809 k--; 0810 runlen >>= 1; 0811 } 0812 } 0813 } 0814 ASSERT(signPos == signLen || signPos == signLen + 1); 0815 ASSERT(codePos >= outStartPos && codePos < CodeBufferBitLen); 0816 return codePos - outStartPos; 0817 } 0818 0819 ////////////////////////////////////////////////////// 0820 #ifdef TRACE 0821 void CEncoder::DumpBuffer() const { 0822 //printf("\nDump\n"); 0823 //for (UINT32 i=0; i < BufferSize; i++) { 0824 // printf("%d", m_value[i]); 0825 //} 0826 //printf("\n"); 0827 } 0828 #endif //TRACE 0829 0830