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