libpgf
6.12.24
PGF - Progressive Graphics File
|
00001 /* 00002 * The Progressive Graphics File; http://www.libpgf.org 00003 * 00004 * $Date: 2006-06-04 22:05:59 +0200 (So, 04 Jun 2006) $ 00005 * $Revision: 229 $ 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 "Decoder.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 // Decoding scheme 00043 // input: binary file 00044 // output: wavelet coefficients stored in subbands 00045 // 00046 // file (for each buffer: packedLength (16 bit), packed bits) 00047 // | 00048 // m_codeBuffer (for each plane: RLcodeLength (16 bit), RLcoded sigBits + m_sign, refBits) 00049 // | | | 00050 // m_sign sigBits refBits [BufferLen, BufferLen, BufferLen] 00051 // | | | 00052 // m_value [BufferSize] 00053 // | 00054 // subband 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 00073 CDecoder::CDecoder(CPGFStream* stream, PGFPreHeader& preHeader, PGFHeader& header, 00074 PGFPostHeader& postHeader, UINT32*& levelLength, UINT64& userDataPos, 00075 bool useOMP, bool skipUserData) THROW_ 00076 : m_stream(stream) 00077 , m_startPos(0) 00078 , m_streamSizeEstimation(0) 00079 , m_encodedHeaderLength(0) 00080 , m_currentBlockIndex(0) 00081 , m_macroBlocksAvailable(0) 00082 #ifdef __PGFROISUPPORT__ 00083 , m_roi(false) 00084 #endif 00085 { 00086 ASSERT(m_stream); 00087 00088 int count, expected; 00089 00090 // set number of threads 00091 #ifdef LIBPGF_USE_OPENMP 00092 m_macroBlockLen = omp_get_num_procs(); 00093 #else 00094 m_macroBlockLen = 1; 00095 #endif 00096 00097 if (useOMP && m_macroBlockLen > 1) { 00098 #ifdef LIBPGF_USE_OPENMP 00099 omp_set_num_threads(m_macroBlockLen); 00100 #endif 00101 00102 // create macro block array 00103 m_macroBlocks = new(std::nothrow) CMacroBlock*[m_macroBlockLen]; 00104 if (!m_macroBlocks) ReturnWithError(InsufficientMemory); 00105 for (int i=0; i < m_macroBlockLen; i++) m_macroBlocks[i] = new CMacroBlock(this); 00106 m_currentBlock = m_macroBlocks[m_currentBlockIndex]; 00107 } else { 00108 m_macroBlocks = 0; 00109 m_macroBlockLen = 1; // there is only one macro block 00110 m_currentBlock = new CMacroBlock(this); 00111 } 00112 00113 // store current stream position 00114 m_startPos = m_stream->GetPos(); 00115 00116 // read magic and version 00117 count = expected = MagicVersionSize; 00118 m_stream->Read(&count, &preHeader); 00119 if (count != expected) ReturnWithError(MissingData); 00120 00121 // read header size 00122 if (preHeader.version & Version6) { 00123 // 32 bit header size since version 6 00124 count = expected = 4; 00125 } else { 00126 count = expected = 2; 00127 } 00128 m_stream->Read(&count, ((UINT8*)&preHeader) + MagicVersionSize); 00129 if (count != expected) ReturnWithError(MissingData); 00130 00131 // make sure the values are correct read 00132 preHeader.hSize = __VAL(preHeader.hSize); 00133 00134 // check magic number 00135 if (memcmp(preHeader.magic, Magic, 3) != 0) { 00136 // error condition: wrong Magic number 00137 ReturnWithError(FormatCannotRead); 00138 } 00139 00140 // read file header 00141 count = expected = (preHeader.hSize < HeaderSize) ? preHeader.hSize : HeaderSize; 00142 m_stream->Read(&count, &header); 00143 if (count != expected) ReturnWithError(MissingData); 00144 00145 // make sure the values are correct read 00146 header.height = __VAL(UINT32(header.height)); 00147 header.width = __VAL(UINT32(header.width)); 00148 00149 // be ready to read all versions including version 0 00150 if (preHeader.version > 0) { 00151 #ifndef __PGFROISUPPORT__ 00152 // check ROI usage 00153 if (preHeader.version & PGFROI) ReturnWithError(FormatCannotRead); 00154 #endif 00155 00156 int size = preHeader.hSize - HeaderSize; 00157 00158 if (size > 0) { 00159 // read post-header 00160 if (header.mode == ImageModeIndexedColor) { 00161 ASSERT((size_t)size >= ColorTableSize); 00162 // read color table 00163 count = expected = ColorTableSize; 00164 m_stream->Read(&count, postHeader.clut); 00165 if (count != expected) ReturnWithError(MissingData); 00166 size -= count; 00167 } 00168 00169 if (size > 0) { 00170 userDataPos = m_stream->GetPos(); 00171 postHeader.userDataLen = size; 00172 if (skipUserData) { 00173 Skip(size); 00174 } else { 00175 // create user data memory block 00176 postHeader.userData = new(std::nothrow) UINT8[postHeader.userDataLen]; 00177 if (!postHeader.userData) ReturnWithError(InsufficientMemory); 00178 00179 // read user data 00180 count = expected = postHeader.userDataLen; 00181 m_stream->Read(&count, postHeader.userData); 00182 if (count != expected) ReturnWithError(MissingData); 00183 } 00184 } 00185 } 00186 00187 // create levelLength 00188 levelLength = new(std::nothrow) UINT32[header.nLevels]; 00189 if (!levelLength) ReturnWithError(InsufficientMemory); 00190 00191 // read levelLength 00192 count = expected = header.nLevels*WordBytes; 00193 m_stream->Read(&count, levelLength); 00194 if (count != expected) ReturnWithError(MissingData); 00195 00196 #ifdef PGF_USE_BIG_ENDIAN 00197 // make sure the values are correct read 00198 for (int i=0; i < header.nLevels; i++) { 00199 levelLength[i] = __VAL(levelLength[i]); 00200 } 00201 #endif 00202 00203 // compute the total size in bytes; keep attention: level length information is optional 00204 for (int i=0; i < header.nLevels; i++) { 00205 m_streamSizeEstimation += levelLength[i]; 00206 } 00207 00208 } 00209 00210 // store current stream position 00211 m_encodedHeaderLength = UINT32(m_stream->GetPos() - m_startPos); 00212 } 00213 00215 // Destructor 00216 CDecoder::~CDecoder() { 00217 if (m_macroBlocks) { 00218 for (int i=0; i < m_macroBlockLen; i++) delete m_macroBlocks[i]; 00219 delete[] m_macroBlocks; 00220 } else { 00221 delete m_currentBlock; 00222 } 00223 } 00224 00231 UINT32 CDecoder::ReadEncodedData(UINT8* target, UINT32 len) const THROW_ { 00232 ASSERT(m_stream); 00233 00234 int count = len; 00235 m_stream->Read(&count, target); 00236 00237 return count; 00238 } 00239 00251 void CDecoder::Partition(CSubband* band, int quantParam, int width, int height, int startPos, int pitch) THROW_ { 00252 ASSERT(band); 00253 00254 const div_t ww = div(width, LinBlockSize); 00255 const div_t hh = div(height, LinBlockSize); 00256 const int ws = pitch - LinBlockSize; 00257 const int wr = pitch - ww.rem; 00258 int pos, base = startPos, base2; 00259 00260 // main height 00261 for (int i=0; i < hh.quot; i++) { 00262 // main width 00263 base2 = base; 00264 for (int j=0; j < ww.quot; j++) { 00265 pos = base2; 00266 for (int y=0; y < LinBlockSize; y++) { 00267 for (int x=0; x < LinBlockSize; x++) { 00268 DequantizeValue(band, pos, quantParam); 00269 pos++; 00270 } 00271 pos += ws; 00272 } 00273 base2 += LinBlockSize; 00274 } 00275 // rest of width 00276 pos = base2; 00277 for (int y=0; y < LinBlockSize; y++) { 00278 for (int x=0; x < ww.rem; x++) { 00279 DequantizeValue(band, pos, quantParam); 00280 pos++; 00281 } 00282 pos += wr; 00283 base += pitch; 00284 } 00285 } 00286 // main width 00287 base2 = base; 00288 for (int j=0; j < ww.quot; j++) { 00289 // rest of height 00290 pos = base2; 00291 for (int y=0; y < hh.rem; y++) { 00292 for (int x=0; x < LinBlockSize; x++) { 00293 DequantizeValue(band, pos, quantParam); 00294 pos++; 00295 } 00296 pos += ws; 00297 } 00298 base2 += LinBlockSize; 00299 } 00300 // rest of height 00301 pos = base2; 00302 for (int y=0; y < hh.rem; y++) { 00303 // rest of width 00304 for (int x=0; x < ww.rem; x++) { 00305 DequantizeValue(band, pos, quantParam); 00306 pos++; 00307 } 00308 pos += wr; 00309 } 00310 } 00311 00313 // Decode and dequantize HL, and LH band of one level 00314 // LH and HH are interleaved in the codestream and must be split 00315 // Deccoding and dequantization of HL and LH Band (interleaved) using partitioning scheme 00316 // partitions the plane in squares of side length InterBlockSize 00317 // It might throw an IOException. 00318 void CDecoder::DecodeInterleaved(CWaveletTransform* wtChannel, int level, int quantParam) THROW_ { 00319 CSubband* hlBand = wtChannel->GetSubband(level, HL); 00320 CSubband* lhBand = wtChannel->GetSubband(level, LH); 00321 const div_t lhH = div(lhBand->GetHeight(), InterBlockSize); 00322 const div_t hlW = div(hlBand->GetWidth(), InterBlockSize); 00323 const int hlws = hlBand->GetWidth() - InterBlockSize; 00324 const int hlwr = hlBand->GetWidth() - hlW.rem; 00325 const int lhws = lhBand->GetWidth() - InterBlockSize; 00326 const int lhwr = lhBand->GetWidth() - hlW.rem; 00327 int hlPos, lhPos; 00328 int hlBase = 0, lhBase = 0, hlBase2, lhBase2; 00329 00330 ASSERT(lhBand->GetWidth() >= hlBand->GetWidth()); 00331 ASSERT(hlBand->GetHeight() >= lhBand->GetHeight()); 00332 00333 if (!hlBand->AllocMemory()) ReturnWithError(InsufficientMemory); 00334 if (!lhBand->AllocMemory()) ReturnWithError(InsufficientMemory); 00335 00336 // correct quantParam with normalization factor 00337 quantParam -= level; 00338 if (quantParam < 0) quantParam = 0; 00339 00340 // main height 00341 for (int i=0; i < lhH.quot; i++) { 00342 // main width 00343 hlBase2 = hlBase; 00344 lhBase2 = lhBase; 00345 for (int j=0; j < hlW.quot; j++) { 00346 hlPos = hlBase2; 00347 lhPos = lhBase2; 00348 for (int y=0; y < InterBlockSize; y++) { 00349 for (int x=0; x < InterBlockSize; x++) { 00350 DequantizeValue(hlBand, hlPos, quantParam); 00351 DequantizeValue(lhBand, lhPos, quantParam); 00352 hlPos++; 00353 lhPos++; 00354 } 00355 hlPos += hlws; 00356 lhPos += lhws; 00357 } 00358 hlBase2 += InterBlockSize; 00359 lhBase2 += InterBlockSize; 00360 } 00361 // rest of width 00362 hlPos = hlBase2; 00363 lhPos = lhBase2; 00364 for (int y=0; y < InterBlockSize; y++) { 00365 for (int x=0; x < hlW.rem; x++) { 00366 DequantizeValue(hlBand, hlPos, quantParam); 00367 DequantizeValue(lhBand, lhPos, quantParam); 00368 hlPos++; 00369 lhPos++; 00370 } 00371 // width difference between HL and LH 00372 if (lhBand->GetWidth() > hlBand->GetWidth()) { 00373 DequantizeValue(lhBand, lhPos, quantParam); 00374 } 00375 hlPos += hlwr; 00376 lhPos += lhwr; 00377 hlBase += hlBand->GetWidth(); 00378 lhBase += lhBand->GetWidth(); 00379 } 00380 } 00381 // main width 00382 hlBase2 = hlBase; 00383 lhBase2 = lhBase; 00384 for (int j=0; j < hlW.quot; j++) { 00385 // rest of height 00386 hlPos = hlBase2; 00387 lhPos = lhBase2; 00388 for (int y=0; y < lhH.rem; y++) { 00389 for (int x=0; x < InterBlockSize; x++) { 00390 DequantizeValue(hlBand, hlPos, quantParam); 00391 DequantizeValue(lhBand, lhPos, quantParam); 00392 hlPos++; 00393 lhPos++; 00394 } 00395 hlPos += hlws; 00396 lhPos += lhws; 00397 } 00398 hlBase2 += InterBlockSize; 00399 lhBase2 += InterBlockSize; 00400 } 00401 // rest of height 00402 hlPos = hlBase2; 00403 lhPos = lhBase2; 00404 for (int y=0; y < lhH.rem; y++) { 00405 // rest of width 00406 for (int x=0; x < hlW.rem; x++) { 00407 DequantizeValue(hlBand, hlPos, quantParam); 00408 DequantizeValue(lhBand, lhPos, quantParam); 00409 hlPos++; 00410 lhPos++; 00411 } 00412 // width difference between HL and LH 00413 if (lhBand->GetWidth() > hlBand->GetWidth()) { 00414 DequantizeValue(lhBand, lhPos, quantParam); 00415 } 00416 hlPos += hlwr; 00417 lhPos += lhwr; 00418 hlBase += hlBand->GetWidth(); 00419 } 00420 // height difference between HL and LH 00421 if (hlBand->GetHeight() > lhBand->GetHeight()) { 00422 // total width 00423 hlPos = hlBase; 00424 for (int j=0; j < hlBand->GetWidth(); j++) { 00425 DequantizeValue(hlBand, hlPos, quantParam); 00426 hlPos++; 00427 } 00428 } 00429 } 00430 00434 void CDecoder::Skip(UINT64 offset) THROW_ { 00435 m_stream->SetPos(FSFromCurrent, offset); 00436 } 00437 00447 void CDecoder::DequantizeValue(CSubband* band, UINT32 bandPos, int quantParam) THROW_ { 00448 ASSERT(m_currentBlock); 00449 00450 if (m_currentBlock->IsCompletelyRead()) { 00451 // all data of current macro block has been read --> prepare next macro block 00452 DecodeTileBuffer(); 00453 } 00454 00455 band->SetData(bandPos, m_currentBlock->m_value[m_currentBlock->m_valuePos] << quantParam); 00456 m_currentBlock->m_valuePos++; 00457 } 00458 00460 // Read next group of blocks from stream and decodes them into macro blocks 00461 // It might throw an IOException. 00462 void CDecoder::DecodeTileBuffer() THROW_ { 00463 // current block has been read --> prepare next current block 00464 m_macroBlocksAvailable--; 00465 00466 if (m_macroBlocksAvailable > 0) { 00467 m_currentBlock = m_macroBlocks[++m_currentBlockIndex]; 00468 } else { 00469 DecodeBuffer(); 00470 } 00471 ASSERT(m_currentBlock); 00472 } 00473 00475 // Read next block from stream and decode into macro block 00476 // Decoding scheme: <wordLen>(16 bits) [ ROI ] data 00477 // ROI ::= <bufferSize>(15 bits) <eofTile>(1 bit) 00478 // It might throw an IOException. 00479 void CDecoder::DecodeBuffer() THROW_ { 00480 ASSERT(m_macroBlocksAvailable <= 0); 00481 00482 // macro block management 00483 if (m_macroBlockLen == 1) { 00484 ASSERT(m_currentBlock); 00485 ReadMacroBlock(m_currentBlock); 00486 m_currentBlock->BitplaneDecode(); 00487 m_macroBlocksAvailable = 1; 00488 } else { 00489 m_macroBlocksAvailable = 0; 00490 for (int i=0; i < m_macroBlockLen; i++) { 00491 // read sequentially several blocks 00492 try { 00493 ReadMacroBlock(m_macroBlocks[i]); 00494 m_macroBlocksAvailable++; 00495 } catch(IOException& ex) { 00496 if (ex.error == MissingData) { 00497 break; // no further data available 00498 } else { 00499 throw ex; 00500 } 00501 } 00502 } 00503 00504 // decode in parallel 00505 #pragma omp parallel for default(shared) //no declared exceptions in next block 00506 for (int i=0; i < m_macroBlocksAvailable; i++) { 00507 m_macroBlocks[i]->BitplaneDecode(); 00508 } 00509 00510 // prepare current macro block 00511 m_currentBlockIndex = 0; 00512 m_currentBlock = m_macroBlocks[m_currentBlockIndex]; 00513 } 00514 } 00515 00517 // Read next block from stream and store it in the given block 00518 // It might throw an IOException. 00519 void CDecoder::ReadMacroBlock(CMacroBlock* block) THROW_ { 00520 ASSERT(block); 00521 00522 UINT16 wordLen; 00523 ROIBlockHeader h(BufferSize); 00524 int count, expected; 00525 00526 #ifdef TRACE 00527 //UINT32 filePos = (UINT32)m_stream->GetPos(); 00528 //printf("DecodeBuffer: %d\n", filePos); 00529 #endif 00530 00531 // read wordLen 00532 count = expected = sizeof(UINT16); 00533 m_stream->Read(&count, &wordLen); 00534 if (count != expected) ReturnWithError(MissingData); 00535 wordLen = __VAL(wordLen); 00536 if (wordLen > BufferSize) 00537 ReturnWithError(FormatCannotRead); 00538 00539 #ifdef __PGFROISUPPORT__ 00540 // read ROIBlockHeader 00541 if (m_roi) { 00542 m_stream->Read(&count, &h.val); 00543 if (count != expected) ReturnWithError(MissingData); 00544 00545 // convert ROIBlockHeader 00546 h.val = __VAL(h.val); 00547 } 00548 #endif 00549 // save header 00550 block->m_header = h; 00551 00552 // read data 00553 count = expected = wordLen*WordBytes; 00554 m_stream->Read(&count, block->m_codeBuffer); 00555 if (count != expected) ReturnWithError(MissingData); 00556 00557 #ifdef PGF_USE_BIG_ENDIAN 00558 // convert data 00559 count /= WordBytes; 00560 for (int i=0; i < count; i++) { 00561 block->m_codeBuffer[i] = __VAL(block->m_codeBuffer[i]); 00562 } 00563 #endif 00564 00565 #ifdef __PGFROISUPPORT__ 00566 ASSERT(m_roi && h.rbh.bufferSize <= BufferSize || h.rbh.bufferSize == BufferSize); 00567 #else 00568 ASSERT(h.rbh.bufferSize == BufferSize); 00569 #endif 00570 } 00571 00573 // Read next block from stream but don't decode into macro block 00574 // Encoding scheme: <wordLen>(16 bits) [ ROI ] data 00575 // ROI ::= <bufferSize>(15 bits) <eofTile>(1 bit) 00576 // It might throw an IOException. 00577 void CDecoder::SkipTileBuffer() THROW_ { 00578 // current block is not used 00579 m_macroBlocksAvailable--; 00580 00581 // check if pre-decoded data is available 00582 if (m_macroBlocksAvailable > 0) { 00583 m_currentBlock = m_macroBlocks[++m_currentBlockIndex]; 00584 return; 00585 } 00586 00587 UINT16 wordLen; 00588 int count, expected; 00589 00590 // read wordLen 00591 count = expected = sizeof(wordLen); 00592 m_stream->Read(&count, &wordLen); 00593 if (count != expected) ReturnWithError(MissingData); 00594 wordLen = __VAL(wordLen); 00595 ASSERT(wordLen <= BufferSize); 00596 00597 #ifdef __PGFROISUPPORT__ 00598 if (m_roi) { 00599 // skip ROIBlockHeader 00600 m_stream->SetPos(FSFromCurrent, sizeof(ROIBlockHeader)); 00601 } 00602 #endif 00603 00604 // skip data 00605 m_stream->SetPos(FSFromCurrent, wordLen*WordBytes); 00606 } 00607 00609 // Decode block into buffer of given size using bit plane coding. 00610 // A buffer contains bufferLen UINT32 values, thus, bufferSize bits per bit plane. 00611 // Following coding scheme is used: 00612 // Buffer ::= <nPlanes>(5 bits) foreach(plane i): Plane[i] 00613 // Plane[i] ::= [ Sig1 | Sig2 ] [DWORD alignment] refBits 00614 // Sig1 ::= 1 <codeLen>(15 bits) codedSigAndSignBits 00615 // Sig2 ::= 0 <sigLen>(15 bits) [Sign1 | Sign2 ] [DWORD alignment] sigBits 00616 // Sign1 ::= 1 <codeLen>(15 bits) codedSignBits 00617 // Sign2 ::= 0 <signLen>(15 bits) [DWORD alignment] signBits 00618 void CDecoder::CMacroBlock::BitplaneDecode() { 00619 UINT32 bufferSize = m_header.rbh.bufferSize; ASSERT(bufferSize <= BufferSize); 00620 00621 UINT32 nPlanes; 00622 UINT32 codePos = 0, codeLen, sigLen, sigPos, signLen, signPos; 00623 DataT planeMask; 00624 00625 // clear significance vector 00626 for (UINT32 k=0; k < bufferSize; k++) { 00627 m_sigFlagVector[k] = false; 00628 } 00629 m_sigFlagVector[bufferSize] = true; // sentinel 00630 00631 // clear output buffer 00632 for (UINT32 k=0; k < BufferSize; k++) { 00633 m_value[k] = 0; 00634 } 00635 00636 // read number of bit planes 00637 // <nPlanes> 00638 nPlanes = GetValueBlock(m_codeBuffer, 0, MaxBitPlanesLog); 00639 codePos += MaxBitPlanesLog; 00640 00641 // loop through all bit planes 00642 if (nPlanes == 0) nPlanes = MaxBitPlanes + 1; 00643 ASSERT(0 < nPlanes && nPlanes <= MaxBitPlanes + 1); 00644 planeMask = 1 << (nPlanes - 1); 00645 00646 for (int plane = nPlanes - 1; plane >= 0; plane--) { 00647 // read RL code 00648 if (GetBit(m_codeBuffer, codePos)) { 00649 // RL coding of sigBits is used 00650 // <1><codeLen><codedSigAndSignBits>_<refBits> 00651 codePos++; 00652 00653 // read codeLen 00654 codeLen = GetValueBlock(m_codeBuffer, codePos, RLblockSizeLen); ASSERT(codeLen <= MaxCodeLen); 00655 00656 // position of encoded sigBits and signBits 00657 sigPos = codePos + RLblockSizeLen; ASSERT(sigPos < CodeBufferBitLen); 00658 00659 // refinement bits 00660 codePos = AlignWordPos(sigPos + codeLen); ASSERT(codePos < CodeBufferBitLen); 00661 00662 // run-length decode significant bits and signs from m_codeBuffer and 00663 // read refinement bits from m_codeBuffer and compose bit plane 00664 sigLen = ComposeBitplaneRLD(bufferSize, planeMask, sigPos, &m_codeBuffer[codePos >> WordWidthLog]); 00665 00666 } else { 00667 // no RL coding is used for sigBits and signBits together 00668 // <0><sigLen> 00669 codePos++; 00670 00671 // read sigLen 00672 sigLen = GetValueBlock(m_codeBuffer, codePos, RLblockSizeLen); ASSERT(sigLen <= MaxCodeLen); 00673 codePos += RLblockSizeLen; ASSERT(codePos < CodeBufferBitLen); 00674 00675 // read RL code for signBits 00676 if (GetBit(m_codeBuffer, codePos)) { 00677 // RL coding is used just for signBits 00678 // <1><codeLen><codedSignBits>_<sigBits>_<refBits> 00679 codePos++; 00680 00681 // read codeLen 00682 codeLen = GetValueBlock(m_codeBuffer, codePos, RLblockSizeLen); ASSERT(codeLen <= MaxCodeLen); 00683 00684 // sign bits 00685 signPos = codePos + RLblockSizeLen; ASSERT(signPos < CodeBufferBitLen); 00686 00687 // significant bits 00688 sigPos = AlignWordPos(signPos + codeLen); ASSERT(sigPos < CodeBufferBitLen); 00689 00690 // refinement bits 00691 codePos = AlignWordPos(sigPos + sigLen); ASSERT(codePos < CodeBufferBitLen); 00692 00693 // read significant and refinement bitset from m_codeBuffer 00694 sigLen = ComposeBitplaneRLD(bufferSize, planeMask, &m_codeBuffer[sigPos >> WordWidthLog], &m_codeBuffer[codePos >> WordWidthLog], signPos); 00695 00696 } else { 00697 // RL coding of signBits was not efficient and therefore not used 00698 // <0><signLen>_<signBits>_<sigBits>_<refBits> 00699 codePos++; 00700 00701 // read signLen 00702 signLen = GetValueBlock(m_codeBuffer, codePos, RLblockSizeLen); ASSERT(signLen <= MaxCodeLen); 00703 00704 // sign bits 00705 signPos = AlignWordPos(codePos + RLblockSizeLen); ASSERT(signPos < CodeBufferBitLen); 00706 00707 // significant bits 00708 sigPos = AlignWordPos(signPos + signLen); ASSERT(sigPos < CodeBufferBitLen); 00709 00710 // refinement bits 00711 codePos = AlignWordPos(sigPos + sigLen); ASSERT(codePos < CodeBufferBitLen); 00712 00713 // read significant and refinement bitset from m_codeBuffer 00714 sigLen = ComposeBitplane(bufferSize, planeMask, &m_codeBuffer[sigPos >> WordWidthLog], &m_codeBuffer[codePos >> WordWidthLog], &m_codeBuffer[signPos >> WordWidthLog]); 00715 } 00716 } 00717 00718 // start of next chunk 00719 codePos = AlignWordPos(codePos + bufferSize - sigLen); ASSERT(codePos < CodeBufferBitLen); 00720 00721 // next plane 00722 planeMask >>= 1; 00723 } 00724 00725 m_valuePos = 0; 00726 } 00727 00729 // Reconstruct bitplane from significant bitset and refinement bitset 00730 // returns length [bits] of sigBits 00731 // input: sigBits, refBits, signBits 00732 // output: m_value 00733 UINT32 CDecoder::CMacroBlock::ComposeBitplane(UINT32 bufferSize, DataT planeMask, UINT32* sigBits, UINT32* refBits, UINT32* signBits) { 00734 ASSERT(sigBits); 00735 ASSERT(refBits); 00736 ASSERT(signBits); 00737 00738 UINT32 valPos = 0, signPos = 0, refPos = 0; 00739 UINT32 sigPos = 0, sigEnd; 00740 UINT32 zerocnt; 00741 00742 while (valPos < bufferSize) { 00743 // search next 1 in m_sigFlagVector using searching with sentinel 00744 sigEnd = valPos; 00745 while(!m_sigFlagVector[sigEnd]) { sigEnd++; } 00746 sigEnd -= valPos; 00747 sigEnd += sigPos; 00748 00749 // search 1's in sigBits[sigPos..sigEnd) 00750 // these 1's are significant bits 00751 while (sigPos < sigEnd) { 00752 // search 0's 00753 zerocnt = SeekBitRange(sigBits, sigPos, sigEnd - sigPos); 00754 sigPos += zerocnt; 00755 valPos += zerocnt; 00756 if (sigPos < sigEnd) { 00757 // write bit to m_value 00758 SetBitAtPos(valPos, planeMask); 00759 00760 // copy sign bit 00761 SetSign(valPos, GetBit(signBits, signPos++)); 00762 00763 // update significance flag vector 00764 m_sigFlagVector[valPos++] = true; 00765 sigPos++; 00766 } 00767 } 00768 // refinement bit 00769 if (valPos < bufferSize) { 00770 // write one refinement bit 00771 if (GetBit(refBits, refPos)) { 00772 SetBitAtPos(valPos, planeMask); 00773 } 00774 refPos++; 00775 valPos++; 00776 } 00777 } 00778 ASSERT(sigPos <= bufferSize); 00779 ASSERT(refPos <= bufferSize); 00780 ASSERT(signPos <= bufferSize); 00781 ASSERT(valPos == bufferSize); 00782 00783 return sigPos; 00784 } 00785 00787 // Reconstruct bitplane from significant bitset and refinement bitset 00788 // returns length [bits] of decoded significant bits 00789 // input: RL encoded sigBits and signBits in m_codeBuffer, refBits 00790 // output: m_value 00791 // RLE: 00792 // - Decode run of 2^k zeros by a single 0. 00793 // - Decode run of count 0's followed by a 1 with codeword: 1<count>x 00794 // - x is 0: if a positive sign has been stored, otherwise 1 00795 // - Read each bit from m_codeBuffer[codePos] and increment codePos. 00796 UINT32 CDecoder::CMacroBlock::ComposeBitplaneRLD(UINT32 bufferSize, DataT planeMask, UINT32 codePos, UINT32* refBits) { 00797 ASSERT(refBits); 00798 00799 UINT32 valPos = 0, refPos = 0; 00800 UINT32 sigPos = 0, sigEnd; 00801 UINT32 k = 3; 00802 UINT32 runlen = 1 << k; // = 2^k 00803 UINT32 count = 0, rest = 0; 00804 bool set1 = false; 00805 00806 while (valPos < bufferSize) { 00807 // search next 1 in m_sigFlagVector using searching with sentinel 00808 sigEnd = valPos; 00809 while(!m_sigFlagVector[sigEnd]) { sigEnd++; } 00810 sigEnd -= valPos; 00811 sigEnd += sigPos; 00812 00813 while (sigPos < sigEnd) { 00814 if (rest || set1) { 00815 // rest of last run 00816 sigPos += rest; 00817 valPos += rest; 00818 rest = 0; 00819 } else { 00820 // decode significant bits 00821 if (GetBit(m_codeBuffer, codePos++)) { 00822 // extract counter and generate zero run of length count 00823 if (k > 0) { 00824 // extract counter 00825 count = GetValueBlock(m_codeBuffer, codePos, k); 00826 codePos += k; 00827 if (count > 0) { 00828 sigPos += count; 00829 valPos += count; 00830 } 00831 00832 // adapt k (half run-length interval) 00833 k--; 00834 runlen >>= 1; 00835 } 00836 00837 set1 = true; 00838 00839 } else { 00840 // generate zero run of length 2^k 00841 sigPos += runlen; 00842 valPos += runlen; 00843 00844 // adapt k (double run-length interval) 00845 if (k < WordWidth) { 00846 k++; 00847 runlen <<= 1; 00848 } 00849 } 00850 } 00851 00852 if (sigPos < sigEnd) { 00853 if (set1) { 00854 set1 = false; 00855 00856 // write 1 bit 00857 SetBitAtPos(valPos, planeMask); 00858 00859 // set sign bit 00860 SetSign(valPos, GetBit(m_codeBuffer, codePos++)); 00861 00862 // update significance flag vector 00863 m_sigFlagVector[valPos++] = true; 00864 sigPos++; 00865 } 00866 } else { 00867 rest = sigPos - sigEnd; 00868 sigPos = sigEnd; 00869 valPos -= rest; 00870 } 00871 00872 } 00873 00874 // refinement bit 00875 if (valPos < bufferSize) { 00876 // write one refinement bit 00877 if (GetBit(refBits, refPos)) { 00878 SetBitAtPos(valPos, planeMask); 00879 } 00880 refPos++; 00881 valPos++; 00882 } 00883 } 00884 ASSERT(sigPos <= bufferSize); 00885 ASSERT(refPos <= bufferSize); 00886 ASSERT(valPos == bufferSize); 00887 00888 return sigPos; 00889 } 00890 00892 // Reconstruct bitplane from significant bitset, refinement bitset, and RL encoded sign bits 00893 // returns length [bits] of sigBits 00894 // input: sigBits, refBits, RL encoded signBits 00895 // output: m_value 00896 // RLE: 00897 // decode run of 2^k 1's by a single 1 00898 // decode run of count 1's followed by a 0 with codeword: 0<count> 00899 UINT32 CDecoder::CMacroBlock::ComposeBitplaneRLD(UINT32 bufferSize, DataT planeMask, UINT32* sigBits, UINT32* refBits, UINT32 signPos) { 00900 ASSERT(sigBits); 00901 ASSERT(refBits); 00902 00903 UINT32 valPos = 0, refPos = 0; 00904 UINT32 sigPos = 0, sigEnd; 00905 UINT32 zerocnt, count = 0; 00906 UINT32 k = 0; 00907 UINT32 runlen = 1 << k; // = 2^k 00908 bool signBit = false; 00909 bool zeroAfterRun = false; 00910 00911 while (valPos < bufferSize) { 00912 // search next 1 in m_sigFlagVector using searching with sentinel 00913 sigEnd = valPos; 00914 while(!m_sigFlagVector[sigEnd]) { sigEnd++; } 00915 sigEnd -= valPos; 00916 sigEnd += sigPos; 00917 00918 // search 1's in sigBits[sigPos..sigEnd) 00919 // these 1's are significant bits 00920 while (sigPos < sigEnd) { 00921 // search 0's 00922 zerocnt = SeekBitRange(sigBits, sigPos, sigEnd - sigPos); 00923 sigPos += zerocnt; 00924 valPos += zerocnt; 00925 if (sigPos < sigEnd) { 00926 // write bit to m_value 00927 SetBitAtPos(valPos, planeMask); 00928 00929 // check sign bit 00930 if (count == 0) { 00931 // all 1's have been set 00932 if (zeroAfterRun) { 00933 // finish the run with a 0 00934 signBit = false; 00935 zeroAfterRun = false; 00936 } else { 00937 // decode next sign bit 00938 if (GetBit(m_codeBuffer, signPos++)) { 00939 // generate 1's run of length 2^k 00940 count = runlen - 1; 00941 signBit = true; 00942 00943 // adapt k (double run-length interval) 00944 if (k < WordWidth) { 00945 k++; 00946 runlen <<= 1; 00947 } 00948 } else { 00949 // extract counter and generate 1's run of length count 00950 if (k > 0) { 00951 // extract counter 00952 count = GetValueBlock(m_codeBuffer, signPos, k); 00953 signPos += k; 00954 00955 // adapt k (half run-length interval) 00956 k--; 00957 runlen >>= 1; 00958 } 00959 if (count > 0) { 00960 count--; 00961 signBit = true; 00962 zeroAfterRun = true; 00963 } else { 00964 signBit = false; 00965 } 00966 } 00967 } 00968 } else { 00969 ASSERT(count > 0); 00970 ASSERT(signBit); 00971 count--; 00972 } 00973 00974 // copy sign bit 00975 SetSign(valPos, signBit); 00976 00977 // update significance flag vector 00978 m_sigFlagVector[valPos++] = true; 00979 sigPos++; 00980 } 00981 } 00982 00983 // refinement bit 00984 if (valPos < bufferSize) { 00985 // write one refinement bit 00986 if (GetBit(refBits, refPos)) { 00987 SetBitAtPos(valPos, planeMask); 00988 } 00989 refPos++; 00990 valPos++; 00991 } 00992 } 00993 ASSERT(sigPos <= bufferSize); 00994 ASSERT(refPos <= bufferSize); 00995 ASSERT(valPos == bufferSize); 00996 00997 return sigPos; 00998 } 00999 01001 #ifdef TRACE 01002 void CDecoder::DumpBuffer() { 01003 //printf("\nDump\n"); 01004 //for (int i=0; i < BufferSize; i++) { 01005 // printf("%d", m_value[i]); 01006 //} 01007 } 01008 #endif //TRACE