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