File indexing completed on 2025-01-19 03:56:09

0001 /*
0002  * The Progressive Graphics File; http://www.libpgf.org
0003  *
0004  * $Date: 2007-02-03 13:04:21 +0100 (Sa, 03 Feb 2007) $
0005  * $Revision: 280 $
0006  *
0007  * This file Copyright (C) 2006 xeraina GmbH, Switzerland
0008  *
0009  * This program is free software; you can redistribute it and/or
0010  * modify it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
0011  * as published by the Free Software Foundation; either version 2.1
0012  * of the License, or (at your option) any later version.
0013  *
0014  * This program is distributed in the hope that it will be useful,
0015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0017  * GNU General Public License for more details.
0018  *
0019  * You should have received a copy of the GNU General Public License
0020  * along with this program; if not, write to the Free Software
0021  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
0022  */
0023 
0024 //////////////////////////////////////////////////////////////////////
0025 /// @file Encoder.cpp
0026 /// @brief PGF encoder class implementation
0027 /// @author C. Stamm, R. Spuler
0028 
0029 #include "Encoder.h"
0030 #ifdef TRACE
0031     #include <stdio.h>
0032 #endif
0033 
0034 //////////////////////////////////////////////////////
0035 // PGF: file structure
0036 //
0037 // PGFPreHeader PGFHeader [PGFPostHeader] LevelLengths Level_n-1 Level_n-2 ... Level_0
0038 // PGFPostHeader ::= [ColorTable] [UserData]
0039 // LevelLengths  ::= UINT32[nLevels]
0040 
0041 //////////////////////////////////////////////////////
0042 // Encoding scheme
0043 // input: wavelet coefficients stored in subbands
0044 // output: binary file
0045 //
0046 //                   subband
0047 //                      |
0048 //                   m_value    [BufferSize]
0049 //                |     |     |
0050 //           m_sign  sigBits  refBits   [BufferSize, BufferLen, BufferLen]
0051 //                |     |     |
0052 //                m_codeBuffer  (for each plane: RLcodeLength (16 bit), RLcoded sigBits + m_sign, refBits)
0053 //                      |
0054 //                    file      (for each buffer: packedLength (16 bit), packed bits)
0055 //
0056 
0057 // Constants
0058 #define CodeBufferBitLen        (CodeBufferLen*WordWidth)   ///< max number of bits in m_codeBuffer
0059 #define MaxCodeLen              ((1 << RLblockSizeLen) - 1) ///< max length of RL encoded block
0060 
0061 //////////////////////////////////////////////////////
0062 /// Write pre-header, header, postHeader, and levelLength.
0063 /// It might throw an IOException.
0064 /// @param stream A PGF stream
0065 /// @param preHeader A already filled in PGF pre-header
0066 /// @param header An already filled in PGF header
0067 /// @param postHeader [in] An already filled in PGF post-header (containing color table, user data, ...)
0068 /// @param userDataPos [out] File position of user data
0069 /// @param useOMP If true, then the encoder will use multi-threading based on openMP
0070 CEncoder::CEncoder(CPGFStream* stream, PGFPreHeader preHeader, PGFHeader header, const PGFPostHeader& postHeader, UINT64& userDataPos, bool useOMP)
0071 : m_stream(stream)
0072 , m_bufferStartPos(0)
0073 , m_currLevelIndex(0)
0074 , m_nLevels(header.nLevels)
0075 , m_favorSpeed(false)
0076 , m_forceWriting(false)
0077 #ifdef __PGFROISUPPORT__
0078 , m_roi(false)
0079 #endif
0080 {
0081     ASSERT(m_stream);
0082 
0083     int count;
0084     m_lastMacroBlock = 0;
0085     m_levelLength = nullptr;
0086 
0087     // set number of threads
0088 #ifdef LIBPGF_USE_OPENMP
0089     m_macroBlockLen = omp_get_num_procs();
0090 #else
0091     m_macroBlockLen = 1;
0092 #endif
0093 
0094     if (useOMP && m_macroBlockLen > 1) {
0095 #ifdef LIBPGF_USE_OPENMP
0096         omp_set_num_threads(m_macroBlockLen);
0097 #endif
0098         // create macro block array
0099         m_macroBlocks = new(std::nothrow) CMacroBlock*[m_macroBlockLen];
0100         if (!m_macroBlocks) ReturnWithError(InsufficientMemory);
0101         for (int i=0; i < m_macroBlockLen; i++) m_macroBlocks[i] = new CMacroBlock(this);
0102         m_currentBlock = m_macroBlocks[m_lastMacroBlock++];
0103     } else {
0104         m_macroBlocks = 0;
0105         m_macroBlockLen = 1;
0106         m_currentBlock = new CMacroBlock(this);
0107     }
0108 
0109     // save file position
0110     m_startPosition = m_stream->GetPos();
0111 
0112     // write preHeader
0113     preHeader.hSize = __VAL(preHeader.hSize);
0114     count = PreHeaderSize;
0115     m_stream->Write(&count, &preHeader);
0116 
0117     // write file header
0118     header.height = __VAL(header.height);
0119     header.width = __VAL(header.width);
0120     count = HeaderSize;
0121     m_stream->Write(&count, &header);
0122 
0123     // write postHeader
0124     if (header.mode == ImageModeIndexedColor) {
0125         // write color table
0126         count = ColorTableSize;
0127         m_stream->Write(&count, (void *)postHeader.clut);
0128     }
0129     // save user data file position
0130     userDataPos = m_stream->GetPos();
0131     if (postHeader.userDataLen) {
0132         if (postHeader.userData) {
0133             // write user data
0134             count = postHeader.userDataLen;
0135             m_stream->Write(&count, postHeader.userData);
0136         } else {
0137             m_stream->SetPos(FSFromCurrent, count);
0138         }
0139     }
0140 
0141     // save level length file position
0142     m_levelLengthPos = m_stream->GetPos();
0143 }
0144 
0145 //////////////////////////////////////////////////////
0146 // Destructor
0147 CEncoder::~CEncoder() {
0148     if (m_macroBlocks) {
0149         for (int i=0; i < m_macroBlockLen; i++) delete m_macroBlocks[i];
0150         delete[] m_macroBlocks;
0151     } else {
0152         delete m_currentBlock;
0153     }
0154 }
0155 
0156 /////////////////////////////////////////////////////////////////////
0157 /// Increase post-header size and write new size into stream.
0158 /// @param preHeader An already filled in PGF pre-header
0159 /// It might throw an IOException.
0160 void CEncoder::UpdatePostHeaderSize(PGFPreHeader preHeader) {
0161     UINT64 curPos = m_stream->GetPos(); // end of user data
0162     int count = PreHeaderSize;
0163 
0164     // write preHeader
0165     SetStreamPosToStart();
0166     preHeader.hSize = __VAL(preHeader.hSize);
0167     m_stream->Write(&count, &preHeader);
0168 
0169     m_stream->SetPos(FSFromStart, curPos);
0170 }
0171 
0172 /////////////////////////////////////////////////////////////////////
0173 /// Create level length data structure and write a place holder into stream.
0174 /// It might throw an IOException.
0175 /// @param levelLength A reference to an integer array, large enough to save the relative file positions of all PGF levels
0176 /// @return number of bytes written into stream
0177 UINT32 CEncoder::WriteLevelLength(UINT32*& levelLength) {
0178     // renew levelLength
0179     delete[] levelLength;
0180     levelLength = new(std::nothrow) UINT32[m_nLevels];
0181     if (!levelLength) ReturnWithError(InsufficientMemory);
0182     for (UINT8 l = 0; l < m_nLevels; l++) levelLength[l] = 0;
0183     m_levelLength = levelLength;
0184 
0185     // save level length file position
0186     m_levelLengthPos = m_stream->GetPos();
0187 
0188     // write dummy levelLength
0189     int count = m_nLevels*WordBytes;
0190     m_stream->Write(&count, m_levelLength);
0191 
0192     // save current file position
0193     SetBufferStartPos();
0194 
0195     return count;
0196 }
0197 
0198 //////////////////////////////////////////////////////
0199 /// Write new levelLength into stream.
0200 /// It might throw an IOException.
0201 /// @return Written image bytes.
0202 UINT32 CEncoder::UpdateLevelLength() {
0203     UINT64 curPos = m_stream->GetPos(); // end of image
0204 
0205     // set file pos to levelLength
0206     m_stream->SetPos(FSFromStart, m_levelLengthPos);
0207 
0208     if (m_levelLength) {
0209     #ifdef PGF_USE_BIG_ENDIAN
0210         UINT32 levelLength;
0211         int count = WordBytes;
0212 
0213         for (int i=0; i < m_currLevelIndex; i++) {
0214             levelLength = __VAL(UINT32(m_levelLength[i]));
0215             m_stream->Write(&count, &levelLength);
0216         }
0217     #else
0218         int count = m_currLevelIndex*WordBytes;
0219 
0220         m_stream->Write(&count, m_levelLength);
0221     #endif //PGF_USE_BIG_ENDIAN
0222     } else {
0223         int count = m_currLevelIndex*WordBytes;
0224         m_stream->SetPos(FSFromCurrent, count);
0225     }
0226 
0227     // begin of image
0228     UINT32 retValue = UINT32(curPos - m_stream->GetPos());
0229 
0230     // restore file position
0231     m_stream->SetPos(FSFromStart, curPos);
0232 
0233     return retValue;
0234 }
0235 
0236 /////////////////////////////////////////////////////////////////////
0237 /// Partitions a rectangular region of a given subband.
0238 /// Partitioning scheme: The plane is partitioned in squares of side length LinBlockSize.
0239 /// Write wavelet coefficients from subband into the input buffer of a macro block.
0240 /// It might throw an IOException.
0241 /// @param band A subband
0242 /// @param width The width of the rectangle
0243 /// @param height The height of the rectangle
0244 /// @param startPos The absolute subband position of the top left corner of the rectangular region
0245 /// @param pitch The number of bytes in row of the subband
0246 void CEncoder::Partition(CSubband* band, int width, int height, int startPos, int pitch) {
0247     ASSERT(band);
0248 
0249     const div_t hh = div(height, LinBlockSize);
0250     const div_t ww = div(width, LinBlockSize);
0251     const int ws = pitch - LinBlockSize;
0252     const int wr = pitch - ww.rem;
0253     int pos, base = startPos, base2;
0254 
0255     // main height
0256     for (int i=0; i < hh.quot; i++) {
0257         // main width
0258         base2 = base;
0259         for (int j=0; j < ww.quot; j++) {
0260             pos = base2;
0261             for (int y=0; y < LinBlockSize; y++) {
0262                 for (int x=0; x < LinBlockSize; x++) {
0263                     WriteValue(band, pos);
0264                     pos++;
0265                 }
0266                 pos += ws;
0267             }
0268             base2 += LinBlockSize;
0269         }
0270         // rest of width
0271         pos = base2;
0272         for (int y=0; y < LinBlockSize; y++) {
0273             for (int x=0; x < ww.rem; x++) {
0274                 WriteValue(band, pos);
0275                 pos++;
0276             }
0277             pos += wr;
0278             base += pitch;
0279         }
0280     }
0281     // main width
0282     base2 = base;
0283     for (int j=0; j < ww.quot; j++) {
0284         // rest of height
0285         pos = base2;
0286         for (int y=0; y < hh.rem; y++) {
0287             for (int x=0; x < LinBlockSize; x++) {
0288                 WriteValue(band, pos);
0289                 pos++;
0290             }
0291             pos += ws;
0292         }
0293         base2 += LinBlockSize;
0294     }
0295     // rest of height
0296     pos = base2;
0297     for (int y=0; y < hh.rem; y++) {
0298         // rest of width
0299         for (int x=0; x < ww.rem; x++) {
0300             WriteValue(band, pos);
0301             pos++;
0302         }
0303         pos += wr;
0304     }
0305 }
0306 
0307 //////////////////////////////////////////////////////
0308 /// Pad buffer with zeros and encode buffer.
0309 /// It might throw an IOException.
0310 void CEncoder::Flush() {
0311     if (m_currentBlock->m_valuePos > 0) {
0312         // pad buffer with zeros
0313         memset(&(m_currentBlock->m_value[m_currentBlock->m_valuePos]), 0, (BufferSize - m_currentBlock->m_valuePos)*DataTSize);
0314         m_currentBlock->m_valuePos = BufferSize;
0315 
0316         // encode buffer
0317         m_forceWriting = true;  // makes sure that the following EncodeBuffer is really written into the stream
0318         EncodeBuffer(ROIBlockHeader(m_currentBlock->m_valuePos, true));
0319     }
0320 }
0321 
0322 /////////////////////////////////////////////////////////////////////
0323 // Stores band value from given position bandPos into buffer m_value at position m_valuePos
0324 // If buffer is full encode it to file
0325 // It might throw an IOException.
0326 void CEncoder::WriteValue(CSubband* band, int bandPos) {
0327     if (m_currentBlock->m_valuePos == BufferSize) {
0328         EncodeBuffer(ROIBlockHeader(BufferSize, false));
0329     }
0330     DataT val = m_currentBlock->m_value[m_currentBlock->m_valuePos++] = band->GetData(bandPos);
0331     UINT32 v = abs(val);
0332     if (v > m_currentBlock->m_maxAbsValue) m_currentBlock->m_maxAbsValue = v;
0333 }
0334 
0335 /////////////////////////////////////////////////////////////////////
0336 // Encode buffer and write data into stream.
0337 // h contains buffer size and flag indicating end of tile.
0338 // Encoding scheme: <wordLen>(16 bits) [ ROI ] data
0339 //      ROI   ::= <bufferSize>(15 bits) <eofTile>(1 bit)
0340 // It might throw an IOException.
0341 void CEncoder::EncodeBuffer(ROIBlockHeader h) {
0342     ASSERT(m_currentBlock);
0343 #ifdef __PGFROISUPPORT__
0344     ASSERT(m_roi && h.rbh.bufferSize <= BufferSize || h.rbh.bufferSize == BufferSize);
0345 #else
0346     ASSERT(h.rbh.bufferSize == BufferSize);
0347 #endif
0348     m_currentBlock->m_header = h;
0349 
0350     // macro block management
0351     if (m_macroBlockLen == 1) {
0352         m_currentBlock->BitplaneEncode();
0353         WriteMacroBlock(m_currentBlock);
0354     } else {
0355         // save last level index
0356         int lastLevelIndex = m_currentBlock->m_lastLevelIndex;
0357 
0358         if (m_forceWriting || m_lastMacroBlock == m_macroBlockLen) {
0359             // encode macro blocks
0360             /*
0361             volatile OSError error = NoError;
0362             #ifdef LIBPGF_USE_OPENMP
0363             #pragma omp parallel for ordered default(shared)
0364             #endif
0365             for (int i=0; i < m_lastMacroBlock; i++) {
0366                 if (error == NoError) {
0367                     m_macroBlocks[i]->BitplaneEncode();
0368                     #ifdef LIBPGF_USE_OPENMP
0369                     #pragma omp ordered
0370                     #endif
0371                     {
0372                         try {
0373                             WriteMacroBlock(m_macroBlocks[i]);
0374                         } catch (IOException& e) {
0375                             error = e.error;
0376                         }
0377                         delete m_macroBlocks[i]; m_macroBlocks[i] = 0;
0378                     }
0379                 }
0380             }
0381             if (error != NoError) ReturnWithError(error);
0382             */
0383 #ifdef LIBPGF_USE_OPENMP
0384             #pragma omp parallel for default(shared) //no declared exceptions in next block
0385 #endif
0386             for (int i=0; i < m_lastMacroBlock; i++) {
0387                 m_macroBlocks[i]->BitplaneEncode();
0388             }
0389             for (int i=0; i < m_lastMacroBlock; i++) {
0390                 WriteMacroBlock(m_macroBlocks[i]);
0391             }
0392 
0393             // prepare for next round
0394             m_forceWriting = false;
0395             m_lastMacroBlock = 0;
0396         }
0397         // re-initialize macro block
0398         m_currentBlock = m_macroBlocks[m_lastMacroBlock++];
0399         m_currentBlock->Init(lastLevelIndex);
0400     }
0401 }
0402 
0403 /////////////////////////////////////////////////////////////////////
0404 // Write encoded macro block into stream.
0405 // It might throw an IOException.
0406 void CEncoder::WriteMacroBlock(CMacroBlock* block) {
0407     ASSERT(block);
0408 #ifdef __PGFROISUPPORT__
0409     ROIBlockHeader h = block->m_header;
0410 #endif
0411     UINT16 wordLen = UINT16(NumberOfWords(block->m_codePos)); ASSERT(wordLen <= CodeBufferLen);
0412     int count = sizeof(UINT16);
0413 
0414 #ifdef TRACE
0415     //UINT32 filePos = (UINT32)m_stream->GetPos();
0416     //printf("EncodeBuffer: %d\n", filePos);
0417 #endif
0418 
0419 #ifdef PGF_USE_BIG_ENDIAN
0420     // write wordLen
0421     UINT16 wl = __VAL(wordLen);
0422     m_stream->Write(&count, &wl); ASSERT(count == sizeof(UINT16));
0423 
0424 #ifdef __PGFROISUPPORT__
0425     // write ROIBlockHeader
0426     if (m_roi) {
0427         count = sizeof(ROIBlockHeader);
0428         h.val = __VAL(h.val);
0429         m_stream->Write(&count, &h.val); ASSERT(count == sizeof(ROIBlockHeader));
0430     }
0431 #endif // __PGFROISUPPORT__
0432 
0433     // convert data
0434     for (int i=0; i < wordLen; i++) {
0435         block->m_codeBuffer[i] = __VAL(block->m_codeBuffer[i]);
0436     }
0437 #else
0438     // write wordLen
0439     m_stream->Write(&count, &wordLen); ASSERT(count == sizeof(UINT16));
0440 
0441 #ifdef __PGFROISUPPORT__
0442     // write ROIBlockHeader
0443     if (m_roi) {
0444         count = sizeof(ROIBlockHeader);
0445         m_stream->Write(&count, &h.val); ASSERT(count == sizeof(ROIBlockHeader));
0446     }
0447 #endif // __PGFROISUPPORT__
0448 #endif // PGF_USE_BIG_ENDIAN
0449 
0450     // write encoded data into stream
0451     count = wordLen*WordBytes;
0452     m_stream->Write(&count, block->m_codeBuffer);
0453 
0454     // store levelLength
0455     if (m_levelLength) {
0456         // store level length
0457         // EncodeBuffer has been called after m_lastLevelIndex has been updated
0458         ASSERT(m_currLevelIndex < m_nLevels);
0459         m_levelLength[m_currLevelIndex] += (UINT32)ComputeBufferLength();
0460         m_currLevelIndex = block->m_lastLevelIndex + 1;
0461 
0462     }
0463 
0464     // prepare for next buffer
0465     SetBufferStartPos();
0466 
0467     // reset values
0468     block->m_valuePos = 0;
0469     block->m_maxAbsValue = 0;
0470 }
0471 
0472 ////////////////////////////////////////////////////////
0473 // Encode buffer of given size using bit plane coding.
0474 // A buffer contains bufferLen UINT32 values, thus, bufferSize bits per bit plane.
0475 // Following coding scheme is used:
0476 //      Buffer      ::= <nPlanes>(5 bits) Q_FOREACH (plane i): Plane[i]
0477 //      Plane[i]    ::= [ Sig1 | Sig2 ] [DWORD alignment] refBits
0478 //      Sig1        ::= 1 <codeLen>(15 bits) codedSigAndSignBits
0479 //      Sig2        ::= 0 <sigLen>(15 bits) [Sign1 | Sign2 ] [DWORD alignment] sigBits
0480 //      Sign1       ::= 1 <codeLen>(15 bits) codedSignBits
0481 //      Sign2       ::= 0 <signLen>(15 bits) [DWORD alignment] signBits
0482 void CEncoder::CMacroBlock::BitplaneEncode() {
0483     UINT8   nPlanes;
0484     UINT32  sigLen, codeLen = 0, wordPos, refLen, signLen;
0485     UINT32  sigBits[BufferLen] = { 0 };
0486     UINT32  refBits[BufferLen] = { 0 };
0487     UINT32  signBits[BufferLen] = { 0 };
0488     UINT32  planeMask;
0489     UINT32  bufferSize = m_header.rbh.bufferSize; ASSERT(bufferSize <= BufferSize);
0490     bool    useRL;
0491 
0492 #ifdef TRACE
0493     //printf("which thread: %d\n", omp_get_thread_num());
0494 #endif
0495 
0496     // clear significance vector
0497     for (UINT32 k=0; k < bufferSize; k++) {
0498         m_sigFlagVector[k] = false;
0499     }
0500     m_sigFlagVector[bufferSize] = true; // sentinel
0501 
0502     // clear output buffer
0503     for (UINT32 k=0; k < bufferSize; k++) {
0504         m_codeBuffer[k] = 0;
0505     }
0506     m_codePos = 0;
0507 
0508     // compute number of bit planes and split buffer into separate bit planes
0509     nPlanes = NumberOfBitplanes();
0510 
0511     // write number of bit planes to m_codeBuffer
0512     // <nPlanes>
0513     SetValueBlock(m_codeBuffer, 0, nPlanes, MaxBitPlanesLog);
0514     m_codePos += MaxBitPlanesLog;
0515 
0516     // loop through all bit planes
0517     if (nPlanes == 0) nPlanes = MaxBitPlanes + 1;
0518     planeMask = 1 << (nPlanes - 1);
0519 
0520     for (int plane = nPlanes - 1; plane >= 0; plane--) {
0521         // clear significant bitset
0522         for (UINT32 k=0; k < BufferLen; k++) {
0523             sigBits[k] = 0;
0524         }
0525 
0526         // split bitplane in significant bitset and refinement bitset
0527         sigLen = DecomposeBitplane(bufferSize, planeMask, m_codePos + RLblockSizeLen + 1, sigBits, refBits, signBits, signLen, codeLen);
0528 
0529         if (sigLen > 0 && codeLen <= MaxCodeLen && codeLen < AlignWordPos(sigLen) + AlignWordPos(signLen) + 2*RLblockSizeLen) {
0530             // set RL code bit
0531             // <1><codeLen>
0532             SetBit(m_codeBuffer, m_codePos++);
0533 
0534             // write length codeLen to m_codeBuffer
0535             SetValueBlock(m_codeBuffer, m_codePos, codeLen, RLblockSizeLen);
0536             m_codePos += RLblockSizeLen + codeLen;
0537         } else {
0538         #ifdef TRACE
0539             //printf("new\n");
0540             //for (UINT32 i=0; i < bufferSize; i++) {
0541             //  printf("%s", (GetBit(sigBits, i)) ? "1" : "_");
0542             //  if (i%120 == 119) printf("\n");
0543             //}
0544             //printf("\n");
0545         #endif // TRACE
0546 
0547             // run-length coding wasn't efficient enough
0548             // we don't use RL coding for sigBits
0549             // <0><sigLen>
0550             ClearBit(m_codeBuffer, m_codePos++);
0551 
0552             // write length sigLen to m_codeBuffer
0553             ASSERT(sigLen <= MaxCodeLen);
0554             SetValueBlock(m_codeBuffer, m_codePos, sigLen, RLblockSizeLen);
0555             m_codePos += RLblockSizeLen;
0556 
0557             if (m_encoder->m_favorSpeed || signLen == 0) {
0558                 useRL = false;
0559             } else {
0560                 // overwrite m_codeBuffer
0561                 useRL = true;
0562                 // run-length encode m_sign and append them to the m_codeBuffer
0563                 codeLen = RLESigns(m_codePos + RLblockSizeLen + 1, signBits, signLen);
0564             }
0565 
0566             if (useRL && codeLen <= MaxCodeLen && codeLen < signLen) {
0567                 // RL encoding of m_sign was efficient
0568                 // <1><codeLen><codedSignBits>_
0569                 // write RL code bit
0570                 SetBit(m_codeBuffer, m_codePos++);
0571 
0572                 // write codeLen to m_codeBuffer
0573                 SetValueBlock(m_codeBuffer, m_codePos, codeLen, RLblockSizeLen);
0574 
0575                 // compute position of sigBits
0576                 wordPos = NumberOfWords(m_codePos + RLblockSizeLen + codeLen);
0577                 ASSERT(0 <= wordPos && wordPos < CodeBufferLen);
0578             } else {
0579                 // RL encoding of signBits wasn't efficient
0580                 // <0><signLen>_<signBits>_
0581                 // clear RL code bit
0582                 ClearBit(m_codeBuffer, m_codePos++);
0583 
0584                 // write signLen to m_codeBuffer
0585                 ASSERT(signLen <= MaxCodeLen);
0586                 SetValueBlock(m_codeBuffer, m_codePos, signLen, RLblockSizeLen);
0587 
0588                 // write signBits to m_codeBuffer
0589                 wordPos = NumberOfWords(m_codePos + RLblockSizeLen);
0590                 ASSERT(0 <= wordPos && wordPos < CodeBufferLen);
0591                 codeLen = NumberOfWords(signLen);
0592 
0593                 for (UINT32 k=0; k < codeLen; k++) {
0594                     m_codeBuffer[wordPos++] = signBits[k];
0595                 }
0596             }
0597 
0598             // write sigBits
0599             // <sigBits>_
0600             ASSERT(0 <= wordPos && wordPos < CodeBufferLen);
0601             refLen = NumberOfWords(sigLen);
0602 
0603             for (UINT32 k=0; k < refLen; k++) {
0604                 m_codeBuffer[wordPos++] = sigBits[k];
0605             }
0606             m_codePos = wordPos << WordWidthLog;
0607         }
0608 
0609         // append refinement bitset (aligned to word boundary)
0610         // _<refBits>
0611         wordPos = NumberOfWords(m_codePos);
0612         ASSERT(0 <= wordPos && wordPos < CodeBufferLen);
0613         refLen = NumberOfWords(bufferSize - sigLen);
0614 
0615         for (UINT32 k=0; k < refLen; k++) {
0616             m_codeBuffer[wordPos++] = refBits[k];
0617         }
0618         m_codePos = wordPos << WordWidthLog;
0619         planeMask >>= 1;
0620     }
0621     ASSERT(0 <= m_codePos && m_codePos <= CodeBufferBitLen);
0622 }
0623 
0624 //////////////////////////////////////////////////////////
0625 // Split bitplane of length bufferSize into significant and refinement bitset
0626 // returns length [bits] of significant bits
0627 // input:  bufferSize, planeMask, codePos
0628 // output: sigBits, refBits, signBits, signLen [bits], codeLen [bits]
0629 // RLE
0630 // - Encode run of 2^k zeros by a single 0.
0631 // - Encode run of count 0's followed by a 1 with codeword: 1<count>x
0632 // - x is 0: if a positive sign is stored, otherwise 1
0633 // - Store each bit in m_codeBuffer[codePos] and increment codePos.
0634 UINT32 CEncoder::CMacroBlock::DecomposeBitplane(UINT32 bufferSize, UINT32 planeMask, UINT32 codePos, UINT32* sigBits, UINT32* refBits, UINT32* signBits, UINT32& signLen, UINT32& codeLen) {
0635     ASSERT(sigBits);
0636     ASSERT(refBits);
0637     ASSERT(signBits);
0638     ASSERT(codePos < CodeBufferBitLen);
0639 
0640     UINT32 sigPos = 0;
0641     UINT32 valuePos = 0, valueEnd;
0642     UINT32 refPos = 0;
0643 
0644     // set output value
0645     signLen = 0;
0646 
0647     // prepare RLE of Sigs and Signs
0648     const UINT32 outStartPos = codePos;
0649     UINT32 k = 3;
0650     UINT32 runlen = 1 << k; // = 2^k
0651     UINT32 count = 0;
0652 
0653     while (valuePos < bufferSize) {
0654         // search next 1 in m_sigFlagVector using searching with sentinel
0655         valueEnd = valuePos;
0656         while(!m_sigFlagVector[valueEnd]) { valueEnd++; }
0657 
0658         // search 1's in m_value[plane][valuePos..valueEnd)
0659         // these 1's are significant bits
0660         while (valuePos < valueEnd) {
0661             if (GetBitAtPos(valuePos, planeMask)) {
0662                 // RLE encoding
0663                 // encode run of count 0's followed by a 1
0664                 // with codeword: 1<count>(signBits[signPos])
0665                 SetBit(m_codeBuffer, codePos++);
0666                 if (k > 0) {
0667                     SetValueBlock(m_codeBuffer, codePos, count, k);
0668                     codePos += k;
0669 
0670                     // adapt k (half the zero run-length)
0671                     k--;
0672                     runlen >>= 1;
0673                 }
0674 
0675                 // copy and write sign bit
0676                 if (m_value[valuePos] < 0) {
0677                     SetBit(signBits, signLen++);
0678                     SetBit(m_codeBuffer, codePos++);
0679                 } else {
0680                     ClearBit(signBits, signLen++);
0681                     ClearBit(m_codeBuffer, codePos++);
0682                 }
0683 
0684                 // write a 1 to sigBits
0685                 SetBit(sigBits, sigPos++);
0686 
0687                 // update m_sigFlagVector
0688                 m_sigFlagVector[valuePos] = true;
0689 
0690                 // prepare for next run
0691                 count = 0;
0692             } else {
0693                 // RLE encoding
0694                 count++;
0695                 if (count == runlen) {
0696                     // encode run of 2^k zeros by a single 0
0697                     ClearBit(m_codeBuffer, codePos++);
0698                     // adapt k (double the zero run-length)
0699                     if (k < WordWidth) {
0700                         k++;
0701                         runlen <<= 1;
0702                     }
0703 
0704                     // prepare for next run
0705                     count = 0;
0706                 }
0707 
0708                 // write 0 to sigBits
0709                 sigPos++;
0710             }
0711             valuePos++;
0712         }
0713         // refinement bit
0714         if (valuePos < bufferSize) {
0715             // write one refinement bit
0716             if (GetBitAtPos(valuePos++, planeMask)) {
0717                 SetBit(refBits, refPos);
0718             } else {
0719                 ClearBit(refBits, refPos);
0720             }
0721             refPos++;
0722         }
0723     }
0724     // RLE encoding of the rest of the plane
0725     // encode run of count 0's followed by a 1
0726     // with codeword: 1<count>(signBits[signPos])
0727     SetBit(m_codeBuffer, codePos++);
0728     if (k > 0) {
0729         SetValueBlock(m_codeBuffer, codePos, count, k);
0730         codePos += k;
0731     }
0732     // write dmmy sign bit
0733     SetBit(m_codeBuffer, codePos++);
0734 
0735     // write word filler zeros
0736 
0737     ASSERT(sigPos <= bufferSize);
0738     ASSERT(refPos <= bufferSize);
0739     ASSERT(signLen <= bufferSize);
0740     ASSERT(valuePos == bufferSize);
0741     ASSERT(codePos >= outStartPos && codePos < CodeBufferBitLen);
0742     codeLen = codePos - outStartPos;
0743 
0744     return sigPos;
0745 }
0746 
0747 
0748 ///////////////////////////////////////////////////////
0749 // Compute number of bit planes needed
0750 UINT8 CEncoder::CMacroBlock::NumberOfBitplanes() {
0751     UINT8 cnt = 0;
0752 
0753     // determine number of bitplanes for max value
0754     if (m_maxAbsValue > 0) {
0755         while (m_maxAbsValue > 0) {
0756             m_maxAbsValue >>= 1; cnt++;
0757         }
0758         if (cnt == MaxBitPlanes + 1) cnt = 0;
0759         // end cs
0760         ASSERT(cnt <= MaxBitPlanes);
0761         ASSERT((cnt >> MaxBitPlanesLog) == 0);
0762         return cnt;
0763     } else {
0764         return 1;
0765     }
0766 }
0767 
0768 //////////////////////////////////////////////////////
0769 // Adaptive Run-Length encoder for long sequences of ones.
0770 // Returns length of output in bits.
0771 // - Encode run of 2^k ones by a single 1.
0772 // - Encode run of count 1's followed by a 0 with codeword: 0<count>.
0773 // - Store each bit in m_codeBuffer[codePos] and increment codePos.
0774 UINT32 CEncoder::CMacroBlock::RLESigns(UINT32 codePos, UINT32* signBits, UINT32 signLen) {
0775     ASSERT(signBits);
0776     ASSERT(0 <= codePos && codePos < CodeBufferBitLen);
0777     ASSERT(0 < signLen && signLen <= BufferSize);
0778 
0779     const UINT32  outStartPos = codePos;
0780     UINT32 k = 0;
0781     UINT32 runlen = 1 << k; // = 2^k
0782     UINT32 count = 0;
0783     UINT32 signPos = 0;
0784 
0785     while (signPos < signLen) {
0786         // search next 0 in signBits starting at position signPos
0787         count = SeekBit1Range(signBits, signPos, __min(runlen, signLen - signPos));
0788         // count 1's found
0789         if (count == runlen) {
0790             // encode run of 2^k ones by a single 1
0791             signPos += count;
0792             SetBit(m_codeBuffer, codePos++);
0793             // adapt k (double the 1's run-length)
0794             if (k < WordWidth) {
0795                 k++;
0796                 runlen <<= 1;
0797             }
0798         } else {
0799             // encode run of count 1's followed by a 0
0800             // with codeword: 0(count)
0801             signPos += count + 1;
0802             ClearBit(m_codeBuffer, codePos++);
0803             if (k > 0) {
0804                 SetValueBlock(m_codeBuffer, codePos, count, k);
0805                 codePos += k;
0806             }
0807             // adapt k (half the 1's run-length)
0808             if (k > 0) {
0809                 k--;
0810                 runlen >>= 1;
0811             }
0812         }
0813     }
0814     ASSERT(signPos == signLen || signPos == signLen + 1);
0815     ASSERT(codePos >= outStartPos && codePos < CodeBufferBitLen);
0816     return codePos - outStartPos;
0817 }
0818 
0819 //////////////////////////////////////////////////////
0820 #ifdef TRACE
0821 void CEncoder::DumpBuffer() const {
0822     //printf("\nDump\n");
0823     //for (UINT32 i=0; i < BufferSize; i++) {
0824     //  printf("%d", m_value[i]);
0825     //}
0826     //printf("\n");
0827 }
0828 #endif //TRACE
0829 
0830