libpgf  6.11.42
PGF - Progressive Graphics File
Encoder.cpp
Go to the documentation of this 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 
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines