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