libpgf
6.12.24
PGF - Progressive Graphics File
|
00001 /* 00002 * The Progressive Graphics File; http://www.libpgf.org 00003 * 00004 * $Date: 2007-02-03 13:04:21 +0100 (Sa, 03 Feb 2007) $ 00005 * $Revision: 280 $ 00006 * 00007 * This file Copyright (C) 2006 xeraina GmbH, Switzerland 00008 * 00009 * This program is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE 00011 * as published by the Free Software Foundation; either version 2.1 00012 * of the License, or (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this program; if not, write to the Free Software 00021 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00022 */ 00023 00028 00029 #include "Encoder.h" 00030 #ifdef TRACE 00031 #include <stdio.h> 00032 #endif 00033 00035 // PGF: file structure 00036 // 00037 // PGFPreHeader PGFHeader PGFPostHeader LevelLengths Level_n-1 Level_n-2 ... Level_0 00038 // PGFPostHeader ::= [ColorTable] [UserData] 00039 // LevelLengths ::= UINT32[nLevels] 00040 00042 // Encoding scheme 00043 // input: wavelet coefficients stored in subbands 00044 // output: binary file 00045 // 00046 // subband 00047 // | 00048 // m_value [BufferSize] 00049 // | | | 00050 // m_sign sigBits refBits [BufferSize, BufferLen, BufferLen] 00051 // | | | 00052 // m_codeBuffer (for each plane: RLcodeLength (16 bit), RLcoded sigBits + m_sign, refBits) 00053 // | 00054 // file (for each buffer: packedLength (16 bit), packed bits) 00055 // 00056 00057 // Constants 00058 #define CodeBufferBitLen (CodeBufferLen*WordWidth) ///< max number of bits in m_codeBuffer 00059 #define MaxCodeLen ((1 << RLblockSizeLen) - 1) ///< max length of RL encoded block 00060 00070 CEncoder::CEncoder(CPGFStream* stream, PGFPreHeader preHeader, PGFHeader header, const PGFPostHeader& postHeader, UINT64& userDataPos, bool useOMP) THROW_ 00071 : m_stream(stream) 00072 , m_bufferStartPos(0) 00073 , m_currLevelIndex(0) 00074 , m_nLevels(header.nLevels) 00075 , m_favorSpeed(false) 00076 , m_forceWriting(false) 00077 #ifdef __PGFROISUPPORT__ 00078 , m_roi(false) 00079 #endif 00080 { 00081 ASSERT(m_stream); 00082 00083 int count; 00084 00085 // set number of threads 00086 #ifdef LIBPGF_USE_OPENMP 00087 m_macroBlockLen = omp_get_num_procs(); 00088 #else 00089 m_macroBlockLen = 1; 00090 #endif 00091 00092 if (useOMP && m_macroBlockLen > 1) { 00093 #ifdef LIBPGF_USE_OPENMP 00094 omp_set_num_threads(m_macroBlockLen); 00095 #endif 00096 // create macro block array 00097 m_macroBlocks = new(std::nothrow) CMacroBlock*[m_macroBlockLen]; 00098 if (!m_macroBlocks) ReturnWithError(InsufficientMemory); 00099 for (int i=0; i < m_macroBlockLen; i++) m_macroBlocks[i] = new CMacroBlock(this); 00100 m_lastMacroBlock = 0; 00101 m_currentBlock = m_macroBlocks[m_lastMacroBlock++]; 00102 } else { 00103 m_macroBlocks = 0; 00104 m_macroBlockLen = 1; 00105 m_currentBlock = new CMacroBlock(this); 00106 } 00107 00108 // save file position 00109 m_startPosition = m_stream->GetPos(); 00110 00111 // write preHeader 00112 preHeader.hSize = __VAL(preHeader.hSize); 00113 count = PreHeaderSize; 00114 m_stream->Write(&count, &preHeader); 00115 00116 // write file header 00117 header.height = __VAL(header.height); 00118 header.width = __VAL(header.width); 00119 count = HeaderSize; 00120 m_stream->Write(&count, &header); 00121 00122 // write postHeader 00123 if (header.mode == ImageModeIndexedColor) { 00124 // write color table 00125 count = ColorTableSize; 00126 m_stream->Write(&count, (void *)postHeader.clut); 00127 } 00128 // save user data file position 00129 userDataPos = m_stream->GetPos(); 00130 if (postHeader.userDataLen) { 00131 if (postHeader.userData) { 00132 // write user data 00133 count = postHeader.userDataLen; 00134 m_stream->Write(&count, postHeader.userData); 00135 } else { 00136 m_stream->SetPos(FSFromCurrent, count); 00137 } 00138 } 00139 00140 // save level length file position 00141 m_levelLengthPos = m_stream->GetPos(); 00142 } 00143 00145 // Destructor 00146 CEncoder::~CEncoder() { 00147 delete m_currentBlock; 00148 delete[] m_macroBlocks; 00149 } 00150 00155 void CEncoder::UpdatePostHeaderSize(PGFPreHeader preHeader) THROW_ { 00156 UINT64 curPos = m_stream->GetPos(); // end of user data 00157 int count = PreHeaderSize; 00158 00159 // write preHeader 00160 m_stream->SetPos(FSFromStart, m_startPosition); 00161 preHeader.hSize = __VAL(preHeader.hSize); 00162 m_stream->Write(&count, &preHeader); 00163 00164 m_stream->SetPos(FSFromStart, curPos); 00165 } 00166 00172 UINT32 CEncoder::WriteLevelLength(UINT32*& levelLength) THROW_ { 00173 // renew levelLength 00174 delete[] levelLength; 00175 levelLength = new(std::nothrow) UINT32[m_nLevels]; 00176 if (!levelLength) ReturnWithError(InsufficientMemory); 00177 for (UINT8 l = 0; l < m_nLevels; l++) levelLength[l] = 0; 00178 m_levelLength = levelLength; 00179 00180 // save level length file position 00181 m_levelLengthPos = m_stream->GetPos(); 00182 00183 // write dummy levelLength 00184 int count = m_nLevels*WordBytes; 00185 m_stream->Write(&count, m_levelLength); 00186 00187 // save current file position 00188 SetBufferStartPos(); 00189 00190 return count; 00191 } 00192 00197 UINT32 CEncoder::UpdateLevelLength() THROW_ { 00198 UINT64 curPos = m_stream->GetPos(); // end of image 00199 00200 // set file pos to levelLength 00201 m_stream->SetPos(FSFromStart, m_levelLengthPos); 00202 00203 if (m_levelLength) { 00204 #ifdef PGF_USE_BIG_ENDIAN 00205 UINT32 levelLength; 00206 int count = WordBytes; 00207 00208 for (int i=0; i < m_currLevelIndex; i++) { 00209 levelLength = __VAL(UINT32(m_levelLength[i])); 00210 m_stream->Write(&count, &levelLength); 00211 } 00212 #else 00213 int count = m_currLevelIndex*WordBytes; 00214 00215 m_stream->Write(&count, m_levelLength); 00216 #endif //PGF_USE_BIG_ENDIAN 00217 } else { 00218 int count = m_currLevelIndex*WordBytes; 00219 m_stream->SetPos(FSFromCurrent, count); 00220 } 00221 00222 // begin of image 00223 UINT32 retValue = UINT32(curPos - m_stream->GetPos()); 00224 00225 // restore file position 00226 m_stream->SetPos(FSFromStart, curPos); 00227 00228 return retValue; 00229 } 00230 00241 void CEncoder::Partition(CSubband* band, int width, int height, int startPos, int pitch) THROW_ { 00242 ASSERT(band); 00243 00244 const div_t hh = div(height, LinBlockSize); 00245 const div_t ww = div(width, LinBlockSize); 00246 const int ws = pitch - LinBlockSize; 00247 const int wr = pitch - ww.rem; 00248 int pos, base = startPos, base2; 00249 00250 // main height 00251 for (int i=0; i < hh.quot; i++) { 00252 // main width 00253 base2 = base; 00254 for (int j=0; j < ww.quot; j++) { 00255 pos = base2; 00256 for (int y=0; y < LinBlockSize; y++) { 00257 for (int x=0; x < LinBlockSize; x++) { 00258 WriteValue(band, pos); 00259 pos++; 00260 } 00261 pos += ws; 00262 } 00263 base2 += LinBlockSize; 00264 } 00265 // rest of width 00266 pos = base2; 00267 for (int y=0; y < LinBlockSize; y++) { 00268 for (int x=0; x < ww.rem; x++) { 00269 WriteValue(band, pos); 00270 pos++; 00271 } 00272 pos += wr; 00273 base += pitch; 00274 } 00275 } 00276 // main width 00277 base2 = base; 00278 for (int j=0; j < ww.quot; j++) { 00279 // rest of height 00280 pos = base2; 00281 for (int y=0; y < hh.rem; y++) { 00282 for (int x=0; x < LinBlockSize; x++) { 00283 WriteValue(band, pos); 00284 pos++; 00285 } 00286 pos += ws; 00287 } 00288 base2 += LinBlockSize; 00289 } 00290 // rest of height 00291 pos = base2; 00292 for (int y=0; y < hh.rem; y++) { 00293 // rest of width 00294 for (int x=0; x < ww.rem; x++) { 00295 WriteValue(band, pos); 00296 pos++; 00297 } 00298 pos += wr; 00299 } 00300 } 00301 00305 void CEncoder::Flush() THROW_ { 00306 if (m_currentBlock->m_valuePos > 0) { 00307 // pad buffer with zeros 00308 memset(&(m_currentBlock->m_value[m_currentBlock->m_valuePos]), 0, (BufferSize - m_currentBlock->m_valuePos)*DataTSize); 00309 m_currentBlock->m_valuePos = BufferSize; 00310 00311 // encode buffer 00312 m_forceWriting = true; // makes sure that the following EncodeBuffer is really written into the stream 00313 EncodeBuffer(ROIBlockHeader(m_currentBlock->m_valuePos, true)); 00314 } 00315 } 00316 00318 // Stores band value from given position bandPos into buffer m_value at position m_valuePos 00319 // If buffer is full encode it to file 00320 // It might throw an IOException. 00321 void CEncoder::WriteValue(CSubband* band, int bandPos) THROW_ { 00322 if (m_currentBlock->m_valuePos == BufferSize) { 00323 EncodeBuffer(ROIBlockHeader(BufferSize, false)); 00324 } 00325 DataT val = m_currentBlock->m_value[m_currentBlock->m_valuePos++] = band->GetData(bandPos); 00326 UINT32 v = abs(val); 00327 if (v > m_currentBlock->m_maxAbsValue) m_currentBlock->m_maxAbsValue = v; 00328 } 00329 00331 // Encode buffer and write data into stream. 00332 // h contains buffer size and flag indicating end of tile. 00333 // Encoding scheme: <wordLen>(16 bits) [ ROI ] data 00334 // ROI ::= <bufferSize>(15 bits) <eofTile>(1 bit) 00335 // It might throw an IOException. 00336 void CEncoder::EncodeBuffer(ROIBlockHeader h) THROW_ { 00337 ASSERT(m_currentBlock); 00338 #ifdef __PGFROISUPPORT__ 00339 ASSERT(m_roi && h.rbh.bufferSize <= BufferSize || h.rbh.bufferSize == BufferSize); 00340 #else 00341 ASSERT(h.rbh.bufferSize == BufferSize); 00342 #endif 00343 m_currentBlock->m_header = h; 00344 00345 // macro block management 00346 if (m_macroBlockLen == 1) { 00347 m_currentBlock->BitplaneEncode(); 00348 WriteMacroBlock(m_currentBlock); 00349 } else { 00350 // save last level index 00351 int lastLevelIndex = m_currentBlock->m_lastLevelIndex; 00352 00353 if (m_forceWriting || m_lastMacroBlock == m_macroBlockLen) { 00354 // encode macro blocks 00355 /* 00356 volatile OSError error = NoError; 00357 #pragma omp parallel for ordered default(shared) 00358 for (int i=0; i < m_lastMacroBlock; i++) { 00359 if (error == NoError) { 00360 m_macroBlocks[i]->BitplaneEncode(); 00361 #pragma omp ordered 00362 { 00363 try { 00364 WriteMacroBlock(m_macroBlocks[i]); 00365 } catch (IOException& e) { 00366 error = e.error; 00367 } 00368 delete m_macroBlocks[i]; m_macroBlocks[i] = 0; 00369 } 00370 } 00371 } 00372 if (error != NoError) ReturnWithError(error); 00373 */ 00374 #pragma omp parallel for default(shared) //no declared exceptions in next block 00375 for (int i=0; i < m_lastMacroBlock; i++) { 00376 m_macroBlocks[i]->BitplaneEncode(); 00377 } 00378 for (int i=0; i < m_lastMacroBlock; i++) { 00379 WriteMacroBlock(m_macroBlocks[i]); 00380 } 00381 00382 // prepare for next round 00383 m_forceWriting = false; 00384 m_lastMacroBlock = 0; 00385 } 00386 // re-initialize macro block 00387 m_currentBlock = m_macroBlocks[m_lastMacroBlock++]; 00388 m_currentBlock->Init(lastLevelIndex); 00389 } 00390 } 00391 00393 // Write encoded macro block into stream. 00394 // It might throw an IOException. 00395 void CEncoder::WriteMacroBlock(CMacroBlock* block) THROW_ { 00396 ASSERT(block); 00397 00398 ROIBlockHeader h = block->m_header; 00399 UINT16 wordLen = UINT16(NumberOfWords(block->m_codePos)); ASSERT(wordLen <= CodeBufferLen); 00400 int count = sizeof(UINT16); 00401 00402 #ifdef TRACE 00403 //UINT32 filePos = (UINT32)m_stream->GetPos(); 00404 //printf("EncodeBuffer: %d\n", filePos); 00405 #endif 00406 00407 #ifdef PGF_USE_BIG_ENDIAN 00408 // write wordLen 00409 UINT16 wl = __VAL(wordLen); 00410 m_stream->Write(&count, &wl); ASSERT(count == sizeof(UINT16)); 00411 00412 #ifdef __PGFROISUPPORT__ 00413 // write ROIBlockHeader 00414 if (m_roi) { 00415 h.val = __VAL(h.val); 00416 m_stream->Write(&count, &h.val); ASSERT(count == sizeof(UINT16)); 00417 } 00418 #endif // __PGFROISUPPORT__ 00419 00420 // convert data 00421 for (int i=0; i < wordLen; i++) { 00422 block->m_codeBuffer[i] = __VAL(block->m_codeBuffer[i]); 00423 } 00424 #else 00425 // write wordLen 00426 m_stream->Write(&count, &wordLen); ASSERT(count == sizeof(UINT16)); 00427 00428 #ifdef __PGFROISUPPORT__ 00429 // write ROIBlockHeader 00430 if (m_roi) { 00431 m_stream->Write(&count, &h.val); ASSERT(count == sizeof(UINT16)); 00432 } 00433 #endif // __PGFROISUPPORT__ 00434 #endif // PGF_USE_BIG_ENDIAN 00435 00436 // write encoded data into stream 00437 count = wordLen*WordBytes; 00438 m_stream->Write(&count, block->m_codeBuffer); 00439 00440 // store levelLength 00441 if (m_levelLength) { 00442 // store level length 00443 // EncodeBuffer has been called after m_lastLevelIndex has been updated 00444 ASSERT(m_currLevelIndex < m_nLevels); 00445 m_levelLength[m_currLevelIndex] += (UINT32)ComputeBufferLength(); 00446 m_currLevelIndex = block->m_lastLevelIndex + 1; 00447 00448 } 00449 00450 // prepare for next buffer 00451 SetBufferStartPos(); 00452 00453 // reset values 00454 block->m_valuePos = 0; 00455 block->m_maxAbsValue = 0; 00456 } 00457 00459 // Encode buffer of given size using bit plane coding. 00460 // A buffer contains bufferLen UINT32 values, thus, bufferSize bits per bit plane. 00461 // Following coding scheme is used: 00462 // Buffer ::= <nPlanes>(5 bits) foreach(plane i): Plane[i] 00463 // Plane[i] ::= [ Sig1 | Sig2 ] [DWORD alignment] refBits 00464 // Sig1 ::= 1 <codeLen>(15 bits) codedSigAndSignBits 00465 // Sig2 ::= 0 <sigLen>(15 bits) [Sign1 | Sign2 ] [DWORD alignment] sigBits 00466 // Sign1 ::= 1 <codeLen>(15 bits) codedSignBits 00467 // Sign2 ::= 0 <signLen>(15 bits) [DWORD alignment] signBits 00468 void CEncoder::CMacroBlock::BitplaneEncode() { 00469 UINT8 nPlanes; 00470 UINT32 sigLen, codeLen = 0, wordPos, refLen, signLen; 00471 UINT32 sigBits[BufferLen] = { 0 }; 00472 UINT32 refBits[BufferLen] = { 0 }; 00473 UINT32 signBits[BufferLen] = { 0 }; 00474 UINT32 planeMask; 00475 UINT32 bufferSize = m_header.rbh.bufferSize; ASSERT(bufferSize <= BufferSize); 00476 bool useRL; 00477 00478 #ifdef TRACE 00479 //printf("which thread: %d\n", omp_get_thread_num()); 00480 #endif 00481 00482 // clear significance vector 00483 for (UINT32 k=0; k < bufferSize; k++) { 00484 m_sigFlagVector[k] = false; 00485 } 00486 m_sigFlagVector[bufferSize] = true; // sentinel 00487 00488 // clear output buffer 00489 for (UINT32 k=0; k < bufferSize; k++) { 00490 m_codeBuffer[k] = 0; 00491 } 00492 m_codePos = 0; 00493 00494 // compute number of bit planes and split buffer into separate bit planes 00495 nPlanes = NumberOfBitplanes(); 00496 00497 // write number of bit planes to m_codeBuffer 00498 // <nPlanes> 00499 SetValueBlock(m_codeBuffer, 0, nPlanes, MaxBitPlanesLog); 00500 m_codePos += MaxBitPlanesLog; 00501 00502 // loop through all bit planes 00503 if (nPlanes == 0) nPlanes = MaxBitPlanes + 1; 00504 planeMask = 1 << (nPlanes - 1); 00505 00506 for (int plane = nPlanes - 1; plane >= 0; plane--) { 00507 // clear significant bitset 00508 for (UINT32 k=0; k < BufferLen; k++) { 00509 sigBits[k] = 0; 00510 } 00511 00512 // split bitplane in significant bitset and refinement bitset 00513 sigLen = DecomposeBitplane(bufferSize, planeMask, m_codePos + RLblockSizeLen + 1, sigBits, refBits, signBits, signLen, codeLen); 00514 00515 if (sigLen > 0 && codeLen <= MaxCodeLen && codeLen < AlignWordPos(sigLen) + AlignWordPos(signLen) + 2*RLblockSizeLen) { 00516 // set RL code bit 00517 // <1><codeLen> 00518 SetBit(m_codeBuffer, m_codePos++); 00519 00520 // write length codeLen to m_codeBuffer 00521 SetValueBlock(m_codeBuffer, m_codePos, codeLen, RLblockSizeLen); 00522 m_codePos += RLblockSizeLen + codeLen; 00523 } else { 00524 #ifdef TRACE 00525 //printf("new\n"); 00526 //for (UINT32 i=0; i < bufferSize; i++) { 00527 // printf("%s", (GetBit(sigBits, i)) ? "1" : "_"); 00528 // if (i%120 == 119) printf("\n"); 00529 //} 00530 //printf("\n"); 00531 #endif // TRACE 00532 00533 // run-length coding wasn't efficient enough 00534 // we don't use RL coding for sigBits 00535 // <0><sigLen> 00536 ClearBit(m_codeBuffer, m_codePos++); 00537 00538 // write length sigLen to m_codeBuffer 00539 ASSERT(sigLen <= MaxCodeLen); 00540 SetValueBlock(m_codeBuffer, m_codePos, sigLen, RLblockSizeLen); 00541 m_codePos += RLblockSizeLen; 00542 00543 if (m_encoder->m_favorSpeed || signLen == 0) { 00544 useRL = false; 00545 } else { 00546 // overwrite m_codeBuffer 00547 useRL = true; 00548 // run-length encode m_sign and append them to the m_codeBuffer 00549 codeLen = RLESigns(m_codePos + RLblockSizeLen + 1, signBits, signLen); 00550 } 00551 00552 if (useRL && codeLen <= MaxCodeLen && codeLen < signLen) { 00553 // RL encoding of m_sign was efficient 00554 // <1><codeLen><codedSignBits>_ 00555 // write RL code bit 00556 SetBit(m_codeBuffer, m_codePos++); 00557 00558 // write codeLen to m_codeBuffer 00559 SetValueBlock(m_codeBuffer, m_codePos, codeLen, RLblockSizeLen); 00560 00561 // compute position of sigBits 00562 wordPos = NumberOfWords(m_codePos + RLblockSizeLen + codeLen); 00563 ASSERT(0 <= wordPos && wordPos < CodeBufferLen); 00564 } else { 00565 // RL encoding of signBits wasn't efficient 00566 // <0><signLen>_<signBits>_ 00567 // clear RL code bit 00568 ClearBit(m_codeBuffer, m_codePos++); 00569 00570 // write signLen to m_codeBuffer 00571 ASSERT(signLen <= MaxCodeLen); 00572 SetValueBlock(m_codeBuffer, m_codePos, signLen, RLblockSizeLen); 00573 00574 // write signBits to m_codeBuffer 00575 wordPos = NumberOfWords(m_codePos + RLblockSizeLen); 00576 ASSERT(0 <= wordPos && wordPos < CodeBufferLen); 00577 codeLen = NumberOfWords(signLen); 00578 00579 for (UINT32 k=0; k < codeLen; k++) { 00580 m_codeBuffer[wordPos++] = signBits[k]; 00581 } 00582 } 00583 00584 // write sigBits 00585 // <sigBits>_ 00586 ASSERT(0 <= wordPos && wordPos < CodeBufferLen); 00587 refLen = NumberOfWords(sigLen); 00588 00589 for (UINT32 k=0; k < refLen; k++) { 00590 m_codeBuffer[wordPos++] = sigBits[k]; 00591 } 00592 m_codePos = wordPos << WordWidthLog; 00593 } 00594 00595 // append refinement bitset (aligned to word boundary) 00596 // _<refBits> 00597 wordPos = NumberOfWords(m_codePos); 00598 ASSERT(0 <= wordPos && wordPos < CodeBufferLen); 00599 refLen = NumberOfWords(bufferSize - sigLen); 00600 00601 for (UINT32 k=0; k < refLen; k++) { 00602 m_codeBuffer[wordPos++] = refBits[k]; 00603 } 00604 m_codePos = wordPos << WordWidthLog; 00605 planeMask >>= 1; 00606 } 00607 ASSERT(0 <= m_codePos && m_codePos <= CodeBufferBitLen); 00608 } 00609 00611 // Split bitplane of length bufferSize into significant and refinement bitset 00612 // returns length [bits] of significant bits 00613 // input: bufferSize, planeMask, codePos 00614 // output: sigBits, refBits, signBits, signLen [bits], codeLen [bits] 00615 // RLE 00616 // - Encode run of 2^k zeros by a single 0. 00617 // - Encode run of count 0's followed by a 1 with codeword: 1<count>x 00618 // - x is 0: if a positive sign is stored, otherwise 1 00619 // - Store each bit in m_codeBuffer[codePos] and increment codePos. 00620 UINT32 CEncoder::CMacroBlock::DecomposeBitplane(UINT32 bufferSize, UINT32 planeMask, UINT32 codePos, UINT32* sigBits, UINT32* refBits, UINT32* signBits, UINT32& signLen, UINT32& codeLen) { 00621 ASSERT(sigBits); 00622 ASSERT(refBits); 00623 ASSERT(signBits); 00624 ASSERT(codePos < CodeBufferBitLen); 00625 00626 UINT32 sigPos = 0; 00627 UINT32 valuePos = 0, valueEnd; 00628 UINT32 refPos = 0; 00629 00630 // set output value 00631 signLen = 0; 00632 00633 // prepare RLE of Sigs and Signs 00634 const UINT32 outStartPos = codePos; 00635 UINT32 k = 3; 00636 UINT32 runlen = 1 << k; // = 2^k 00637 UINT32 count = 0; 00638 00639 while (valuePos < bufferSize) { 00640 // search next 1 in m_sigFlagVector using searching with sentinel 00641 valueEnd = valuePos; 00642 while(!m_sigFlagVector[valueEnd]) { valueEnd++; } 00643 00644 // search 1's in m_value[plane][valuePos..valueEnd) 00645 // these 1's are significant bits 00646 while (valuePos < valueEnd) { 00647 if (GetBitAtPos(valuePos, planeMask)) { 00648 // RLE encoding 00649 // encode run of count 0's followed by a 1 00650 // with codeword: 1<count>(signBits[signPos]) 00651 SetBit(m_codeBuffer, codePos++); 00652 if (k > 0) { 00653 SetValueBlock(m_codeBuffer, codePos, count, k); 00654 codePos += k; 00655 00656 // adapt k (half the zero run-length) 00657 k--; 00658 runlen >>= 1; 00659 } 00660 00661 // copy and write sign bit 00662 if (m_value[valuePos] < 0) { 00663 SetBit(signBits, signLen++); 00664 SetBit(m_codeBuffer, codePos++); 00665 } else { 00666 ClearBit(signBits, signLen++); 00667 ClearBit(m_codeBuffer, codePos++); 00668 } 00669 00670 // write a 1 to sigBits 00671 SetBit(sigBits, sigPos++); 00672 00673 // update m_sigFlagVector 00674 m_sigFlagVector[valuePos] = true; 00675 00676 // prepare for next run 00677 count = 0; 00678 } else { 00679 // RLE encoding 00680 count++; 00681 if (count == runlen) { 00682 // encode run of 2^k zeros by a single 0 00683 ClearBit(m_codeBuffer, codePos++); 00684 // adapt k (double the zero run-length) 00685 if (k < WordWidth) { 00686 k++; 00687 runlen <<= 1; 00688 } 00689 00690 // prepare for next run 00691 count = 0; 00692 } 00693 00694 // write 0 to sigBits 00695 sigPos++; 00696 } 00697 valuePos++; 00698 } 00699 // refinement bit 00700 if (valuePos < bufferSize) { 00701 // write one refinement bit 00702 if (GetBitAtPos(valuePos++, planeMask)) { 00703 SetBit(refBits, refPos); 00704 } else { 00705 ClearBit(refBits, refPos); 00706 } 00707 refPos++; 00708 } 00709 } 00710 // RLE encoding of the rest of the plane 00711 // encode run of count 0's followed by a 1 00712 // with codeword: 1<count>(signBits[signPos]) 00713 SetBit(m_codeBuffer, codePos++); 00714 if (k > 0) { 00715 SetValueBlock(m_codeBuffer, codePos, count, k); 00716 codePos += k; 00717 } 00718 // write dmmy sign bit 00719 SetBit(m_codeBuffer, codePos++); 00720 00721 // write word filler zeros 00722 00723 ASSERT(sigPos <= bufferSize); 00724 ASSERT(refPos <= bufferSize); 00725 ASSERT(signLen <= bufferSize); 00726 ASSERT(valuePos == bufferSize); 00727 ASSERT(codePos >= outStartPos && codePos < CodeBufferBitLen); 00728 codeLen = codePos - outStartPos; 00729 00730 return sigPos; 00731 } 00732 00733 00735 // Compute number of bit planes needed 00736 UINT8 CEncoder::CMacroBlock::NumberOfBitplanes() { 00737 UINT8 cnt = 0; 00738 00739 // determine number of bitplanes for max value 00740 if (m_maxAbsValue > 0) { 00741 while (m_maxAbsValue > 0) { 00742 m_maxAbsValue >>= 1; cnt++; 00743 } 00744 if (cnt == MaxBitPlanes + 1) cnt = 0; 00745 // end cs 00746 ASSERT(cnt <= MaxBitPlanes); 00747 ASSERT((cnt >> MaxBitPlanesLog) == 0); 00748 return cnt; 00749 } else { 00750 return 1; 00751 } 00752 } 00753 00755 // Adaptive Run-Length encoder for long sequences of ones. 00756 // Returns length of output in bits. 00757 // - Encode run of 2^k ones by a single 1. 00758 // - Encode run of count 1's followed by a 0 with codeword: 0<count>. 00759 // - Store each bit in m_codeBuffer[codePos] and increment codePos. 00760 UINT32 CEncoder::CMacroBlock::RLESigns(UINT32 codePos, UINT32* signBits, UINT32 signLen) { 00761 ASSERT(signBits); 00762 ASSERT(0 <= codePos && codePos < CodeBufferBitLen); 00763 ASSERT(0 < signLen && signLen <= BufferSize); 00764 00765 const UINT32 outStartPos = codePos; 00766 UINT32 k = 0; 00767 UINT32 runlen = 1 << k; // = 2^k 00768 UINT32 count = 0; 00769 UINT32 signPos = 0; 00770 00771 while (signPos < signLen) { 00772 // search next 0 in signBits starting at position signPos 00773 count = SeekBit1Range(signBits, signPos, __min(runlen, signLen - signPos)); 00774 // count 1's found 00775 if (count == runlen) { 00776 // encode run of 2^k ones by a single 1 00777 signPos += count; 00778 SetBit(m_codeBuffer, codePos++); 00779 // adapt k (double the 1's run-length) 00780 if (k < WordWidth) { 00781 k++; 00782 runlen <<= 1; 00783 } 00784 } else { 00785 // encode run of count 1's followed by a 0 00786 // with codeword: 0(count) 00787 signPos += count + 1; 00788 ClearBit(m_codeBuffer, codePos++); 00789 if (k > 0) { 00790 SetValueBlock(m_codeBuffer, codePos, count, k); 00791 codePos += k; 00792 } 00793 // adapt k (half the 1's run-length) 00794 if (k > 0) { 00795 k--; 00796 runlen >>= 1; 00797 } 00798 } 00799 } 00800 ASSERT(signPos == signLen || signPos == signLen + 1); 00801 ASSERT(codePos >= outStartPos && codePos < CodeBufferBitLen); 00802 return codePos - outStartPos; 00803 } 00804 00806 #ifdef TRACE 00807 void CEncoder::DumpBuffer() const { 00808 //printf("\nDump\n"); 00809 //for (UINT32 i=0; i < BufferSize; i++) { 00810 // printf("%d", m_value[i]); 00811 //} 00812 //printf("\n"); 00813 } 00814 #endif //TRACE 00815 00816