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