File indexing completed on 2025-01-05 03:56:36

0001 /*
0002  * The Progressive Graphics File; http://www.libpgf.org
0003  *
0004  * $Date: 2006-06-04 22:05:59 +0200 (So, 04 Jun 2006) $
0005  * $Revision: 229 $
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 Decoder.cpp
0026 /// @brief PGF decoder class implementation
0027 /// @author C. Stamm, R. Spuler
0028 
0029 #include "Decoder.h"
0030 #ifdef TRACE
0031     #include <stdio.h>
0032 #endif
0033 
0034 #if defined(__GNUC__)
0035 #pragma GCC diagnostic push
0036 #pragma GCC diagnostic ignored "-Wextra"
0037 #endif
0038 
0039 #if defined(__APPLE__)
0040 #pragma clang diagnostic push
0041 #pragma clang diagnostic ignored "-Wextra"
0042 #endif
0043 
0044 //////////////////////////////////////////////////////
0045 // PGF: file structure
0046 //
0047 // PGFPreHeader PGFHeader [PGFPostHeader] LevelLengths Level_n-1 Level_n-2 ... Level_0
0048 // PGFPostHeader ::= [ColorTable] [UserData]
0049 // LevelLengths  ::= UINT32[nLevels]
0050 
0051 //////////////////////////////////////////////////////
0052 // Decoding scheme
0053 // input:  binary file
0054 // output: wavelet coefficients stored in subbands
0055 //
0056 //                    file      (for each buffer: packedLength (16 bit), packed bits)
0057 //                      |
0058 //                m_codeBuffer  (for each plane: RLcodeLength (16 bit), RLcoded sigBits + m_sign, refBits)
0059 //                |     |     |
0060 //           m_sign  sigBits  refBits   [BufferLen, BufferLen, BufferLen]
0061 //                |     |     |
0062 //                   m_value    [BufferSize]
0063 //                      |
0064 //                   subband
0065 //
0066 
0067 // Constants
0068 #define CodeBufferBitLen        (CodeBufferLen*WordWidth)   ///< max number of bits in m_codeBuffer
0069 #define MaxCodeLen              ((1 << RLblockSizeLen) - 1) ///< max length of RL encoded block
0070 
0071 /////////////////////////////////////////////////////////////////////
0072 /// Constructor
0073 /// Read pre-header, header, and levelLength
0074 /// It might throw an IOException.
0075 /// @param stream A PGF stream
0076 /// @param preHeader [out] A PGF pre-header
0077 /// @param header [out] A PGF header
0078 /// @param postHeader [out] A PGF post-header
0079 /// @param levelLength The location of the levelLength array. The array is allocated in this method. The caller has to delete this array.
0080 /// @param userDataPos The stream position of the user data (metadata)
0081 /// @param useOMP If true, then the decoder will use multi-threading based on openMP
0082 /// @param userDataPolicy Policy of user data (meta-data) handling while reading PGF headers.
0083 CDecoder::CDecoder(CPGFStream* stream, PGFPreHeader& preHeader, PGFHeader& header,
0084                    PGFPostHeader& postHeader, UINT32*& levelLength, UINT64& userDataPos,
0085                    bool useOMP, UINT32 userDataPolicy)
0086 : m_stream(stream)
0087 , m_startPos(0)
0088 , m_streamSizeEstimation(0)
0089 , m_encodedHeaderLength(0)
0090 , m_currentBlockIndex(0)
0091 , m_macroBlocksAvailable(0)
0092 #ifdef __PGFROISUPPORT__
0093 , m_roi(false)
0094 #endif
0095 {
0096     ASSERT(m_stream);
0097 
0098     int count, expected;
0099 
0100     // store current stream position
0101     m_startPos = m_stream->GetPos();
0102 
0103     // read magic and version
0104     count = expected = MagicVersionSize;
0105     m_stream->Read(&count, &preHeader);
0106     if (count != expected) ReturnWithError(MissingData);
0107 
0108     // read header size
0109     if (preHeader.version & Version6) {
0110         // 32 bit header size since version 6
0111         count = expected = 4;
0112     } else {
0113         count = expected = 2;
0114     }
0115     m_stream->Read(&count, ((UINT8*)&preHeader) + MagicVersionSize);
0116     if (count != expected) ReturnWithError(MissingData);
0117 
0118     // make sure the values are correct read
0119     preHeader.hSize = __VAL(preHeader.hSize);
0120 
0121     // check magic number
0122     if (memcmp(preHeader.magic, PGFMagic, 3) != 0) {
0123         // error condition: wrong Magic number
0124         ReturnWithError(FormatCannotRead);
0125     }
0126 
0127     // read file header
0128     count = expected = (preHeader.hSize < HeaderSize) ? preHeader.hSize : HeaderSize;
0129     m_stream->Read(&count, &header);
0130     if (count != expected) ReturnWithError(MissingData);
0131 
0132     // make sure the values are correct read
0133     header.height = __VAL(UINT32(header.height));
0134     header.width = __VAL(UINT32(header.width));
0135 
0136     // be ready to read all versions including version 0
0137     if (preHeader.version > 0) {
0138 #ifndef __PGFROISUPPORT__
0139         // check ROI usage
0140         if (preHeader.version & PGFROI) ReturnWithError(FormatCannotRead);
0141 #endif
0142 
0143         UINT32 size = preHeader.hSize;
0144 
0145         if (size > HeaderSize) {
0146             size -= HeaderSize;
0147             count = 0;
0148 
0149             // read post-header
0150             if (header.mode == ImageModeIndexedColor) {
0151                 if (size < ColorTableSize) ReturnWithError(FormatCannotRead);
0152                 // read color table
0153                 count = expected = ColorTableSize;
0154                 m_stream->Read(&count, postHeader.clut);
0155                 if (count != expected) ReturnWithError(MissingData);
0156             }
0157 
0158             if (size > (UINT32)count) {
0159                 size -= count;
0160 
0161                 // read/skip user data
0162                 UserdataPolicy policy = (UserdataPolicy)((userDataPolicy <= MaxUserDataSize) ? UP_CachePrefix : 0xFFFFFFFF - userDataPolicy);
0163                 userDataPos = m_stream->GetPos();
0164                 postHeader.userDataLen = size;
0165 
0166                 if (policy == UP_Skip) {
0167                     postHeader.cachedUserDataLen = 0;
0168                     postHeader.userData = nullptr;
0169                     Skip(size);
0170                 } else {
0171                     postHeader.cachedUserDataLen = (policy == UP_CachePrefix) ? __min(size, userDataPolicy) : size;
0172 
0173                     // create user data memory block
0174                     postHeader.userData = new(std::nothrow) UINT8[postHeader.cachedUserDataLen];
0175                     if (!postHeader.userData) ReturnWithError(InsufficientMemory);
0176 
0177                     // read user data
0178                     count = expected = postHeader.cachedUserDataLen;
0179                     m_stream->Read(&count, postHeader.userData);
0180                     if (count != expected) ReturnWithError(MissingData);
0181 
0182                     // skip remaining user data
0183                     if (postHeader.cachedUserDataLen < size) Skip(size - postHeader.cachedUserDataLen);
0184                 }
0185             }
0186         }
0187 
0188         // create levelLength
0189         levelLength = new(std::nothrow) UINT32[header.nLevels];
0190         if (!levelLength) ReturnWithError(InsufficientMemory);
0191 
0192         // read levelLength
0193         count = expected = header.nLevels*WordBytes;
0194         m_stream->Read(&count, levelLength);
0195         if (count != expected) ReturnWithError(MissingData);
0196 
0197 #ifdef PGF_USE_BIG_ENDIAN
0198         // make sure the values are correct read
0199         for (int i=0; i < header.nLevels; i++) {
0200             levelLength[i] = __VAL(levelLength[i]);
0201         }
0202 #endif
0203 
0204         // compute the total size in bytes; keep attention: level length information is optional
0205         for (int i=0; i < header.nLevels; i++) {
0206             m_streamSizeEstimation += levelLength[i];
0207         }
0208 
0209     }
0210 
0211     // store current stream position
0212     m_encodedHeaderLength = UINT32(m_stream->GetPos() - m_startPos);
0213 
0214     // set number of threads
0215 #ifdef LIBPGF_USE_OPENMP
0216     m_macroBlockLen = omp_get_num_procs();
0217 #else
0218     m_macroBlockLen = 1;
0219 #endif
0220 
0221     if (useOMP && m_macroBlockLen > 1) {
0222 #ifdef LIBPGF_USE_OPENMP
0223         omp_set_num_threads(m_macroBlockLen);
0224 #endif
0225 
0226         // create macro block array
0227         m_macroBlocks = new(std::nothrow) CMacroBlock*[m_macroBlockLen];
0228         if (!m_macroBlocks) ReturnWithError(InsufficientMemory);
0229         for (int i = 0; i < m_macroBlockLen; i++) m_macroBlocks[i] = new CMacroBlock();
0230         m_currentBlock = m_macroBlocks[m_currentBlockIndex];
0231     } else {
0232         m_macroBlocks = 0;
0233         m_macroBlockLen = 1; // there is only one macro block
0234         m_currentBlock = new(std::nothrow) CMacroBlock();
0235         if (!m_currentBlock) ReturnWithError(InsufficientMemory);
0236     }
0237 }
0238 
0239 /////////////////////////////////////////////////////////////////////
0240 // Destructor
0241 CDecoder::~CDecoder() {
0242     if (m_macroBlocks) {
0243         for (int i=0; i < m_macroBlockLen; i++) delete m_macroBlocks[i];
0244         delete[] m_macroBlocks;
0245     } else {
0246         delete m_currentBlock;
0247     }
0248 }
0249 
0250 //////////////////////////////////////////////////////////////////////
0251 /// Copies data from the open stream to a target buffer.
0252 /// It might throw an IOException.
0253 /// @param target The target buffer
0254 /// @param len The number of bytes to read
0255 /// @return The number of bytes copied to the target buffer
0256 UINT32 CDecoder::ReadEncodedData(UINT8* target, UINT32 len) const {
0257     ASSERT(m_stream);
0258 
0259     int count = len;
0260     m_stream->Read(&count, target);
0261 
0262     return count;
0263 }
0264 
0265 /////////////////////////////////////////////////////////////////////
0266 /// Unpartitions a rectangular region of a given subband.
0267 /// Partitioning scheme: The plane is partitioned in squares of side length LinBlockSize.
0268 /// Read wavelet coefficients from the output buffer of a macro block.
0269 /// It might throw an IOException.
0270 /// @param band A subband
0271 /// @param quantParam Dequantization value
0272 /// @param width The width of the rectangle
0273 /// @param height The height of the rectangle
0274 /// @param startPos The relative subband position of the top left corner of the rectangular region
0275 /// @param pitch The number of bytes in row of the subband
0276 void CDecoder::Partition(CSubband* band, int quantParam, int width, int height, int startPos, int pitch) {
0277     ASSERT(band);
0278 
0279     const div_t ww = div(width, LinBlockSize);
0280     const div_t hh = div(height, LinBlockSize);
0281     const int ws = pitch - LinBlockSize;
0282     const int wr = pitch - ww.rem;
0283     int pos, base = startPos, base2;
0284 
0285     // main height
0286     for (int i=0; i < hh.quot; i++) {
0287         // main width
0288         base2 = base;
0289         for (int j=0; j < ww.quot; j++) {
0290             pos = base2;
0291             for (int y=0; y < LinBlockSize; y++) {
0292                 for (int x=0; x < LinBlockSize; x++) {
0293                     DequantizeValue(band, pos, quantParam);
0294                     pos++;
0295                 }
0296                 pos += ws;
0297             }
0298             base2 += LinBlockSize;
0299         }
0300         // rest of width
0301         pos = base2;
0302         for (int y=0; y < LinBlockSize; y++) {
0303             for (int x=0; x < ww.rem; x++) {
0304                 DequantizeValue(band, pos, quantParam);
0305                 pos++;
0306             }
0307             pos += wr;
0308             base += pitch;
0309         }
0310     }
0311     // main width
0312     base2 = base;
0313     for (int j=0; j < ww.quot; j++) {
0314         // rest of height
0315         pos = base2;
0316         for (int y=0; y < hh.rem; y++) {
0317             for (int x=0; x < LinBlockSize; x++) {
0318                 DequantizeValue(band, pos, quantParam);
0319                 pos++;
0320             }
0321             pos += ws;
0322         }
0323         base2 += LinBlockSize;
0324     }
0325     // rest of height
0326     pos = base2;
0327     for (int y=0; y < hh.rem; y++) {
0328         // rest of width
0329         for (int x=0; x < ww.rem; x++) {
0330             DequantizeValue(band, pos, quantParam);
0331             pos++;
0332         }
0333         pos += wr;
0334     }
0335 }
0336 
0337 ////////////////////////////////////////////////////////////////////
0338 // Decodes and dequantizes HL, and LH band of one level
0339 // LH and HH are interleaved in the codestream and must be split
0340 // Deccoding and dequantization of HL and LH Band (interleaved) using partitioning scheme
0341 // partitions the plane in squares of side length InterBlockSize
0342 // It might throw an IOException.
0343 void CDecoder::DecodeInterleaved(CWaveletTransform* wtChannel, int level, int quantParam) {
0344     CSubband* hlBand = wtChannel->GetSubband(level, HL);
0345     CSubband* lhBand = wtChannel->GetSubband(level, LH);
0346     const div_t lhH = div(lhBand->GetHeight(), InterBlockSize);
0347     const div_t hlW = div(hlBand->GetWidth(), InterBlockSize);
0348     const int hlws = hlBand->GetWidth() - InterBlockSize;
0349     const int hlwr = hlBand->GetWidth() - hlW.rem;
0350     const int lhws = lhBand->GetWidth() - InterBlockSize;
0351     const int lhwr = lhBand->GetWidth() - hlW.rem;
0352     int hlPos, lhPos;
0353     int hlBase = 0, lhBase = 0, hlBase2, lhBase2;
0354 
0355     ASSERT(lhBand->GetWidth() >= hlBand->GetWidth());
0356     ASSERT(hlBand->GetHeight() >= lhBand->GetHeight());
0357 
0358     if (!hlBand->AllocMemory()) ReturnWithError(InsufficientMemory);
0359     if (!lhBand->AllocMemory()) ReturnWithError(InsufficientMemory);
0360 
0361     // correct quantParam with normalization factor
0362     quantParam -= level;
0363     if (quantParam < 0) quantParam = 0;
0364 
0365     // main height
0366     for (int i=0; i < lhH.quot; i++) {
0367         // main width
0368         hlBase2 = hlBase;
0369         lhBase2 = lhBase;
0370         for (int j=0; j < hlW.quot; j++) {
0371             hlPos = hlBase2;
0372             lhPos = lhBase2;
0373             for (int y=0; y < InterBlockSize; y++) {
0374                 for (int x=0; x < InterBlockSize; x++) {
0375                     DequantizeValue(hlBand, hlPos, quantParam);
0376                     DequantizeValue(lhBand, lhPos, quantParam);
0377                     hlPos++;
0378                     lhPos++;
0379                 }
0380                 hlPos += hlws;
0381                 lhPos += lhws;
0382             }
0383             hlBase2 += InterBlockSize;
0384             lhBase2 += InterBlockSize;
0385         }
0386         // rest of width
0387         hlPos = hlBase2;
0388         lhPos = lhBase2;
0389         for (int y=0; y < InterBlockSize; y++) {
0390             for (int x=0; x < hlW.rem; x++) {
0391                 DequantizeValue(hlBand, hlPos, quantParam);
0392                 DequantizeValue(lhBand, lhPos, quantParam);
0393                 hlPos++;
0394                 lhPos++;
0395             }
0396             // width difference between HL and LH
0397             if (lhBand->GetWidth() > hlBand->GetWidth()) {
0398                 DequantizeValue(lhBand, lhPos, quantParam);
0399             }
0400             hlPos += hlwr;
0401             lhPos += lhwr;
0402             hlBase += hlBand->GetWidth();
0403             lhBase += lhBand->GetWidth();
0404         }
0405     }
0406     // main width
0407     hlBase2 = hlBase;
0408     lhBase2 = lhBase;
0409     for (int j=0; j < hlW.quot; j++) {
0410         // rest of height
0411         hlPos = hlBase2;
0412         lhPos = lhBase2;
0413         for (int y=0; y < lhH.rem; y++) {
0414             for (int x=0; x < InterBlockSize; x++) {
0415                 DequantizeValue(hlBand, hlPos, quantParam);
0416                 DequantizeValue(lhBand, lhPos, quantParam);
0417                 hlPos++;
0418                 lhPos++;
0419             }
0420             hlPos += hlws;
0421             lhPos += lhws;
0422         }
0423         hlBase2 += InterBlockSize;
0424         lhBase2 += InterBlockSize;
0425     }
0426     // rest of height
0427     hlPos = hlBase2;
0428     lhPos = lhBase2;
0429     for (int y=0; y < lhH.rem; y++) {
0430         // rest of width
0431         for (int x=0; x < hlW.rem; x++) {
0432             DequantizeValue(hlBand, hlPos, quantParam);
0433             DequantizeValue(lhBand, lhPos, quantParam);
0434             hlPos++;
0435             lhPos++;
0436         }
0437         // width difference between HL and LH
0438         if (lhBand->GetWidth() > hlBand->GetWidth()) {
0439             DequantizeValue(lhBand, lhPos, quantParam);
0440         }
0441         hlPos += hlwr;
0442         lhPos += lhwr;
0443         hlBase += hlBand->GetWidth();
0444     }
0445     // height difference between HL and LH
0446     if (hlBand->GetHeight() > lhBand->GetHeight()) {
0447         // total width
0448         hlPos = hlBase;
0449         for (int j=0; j < hlBand->GetWidth(); j++) {
0450             DequantizeValue(hlBand, hlPos, quantParam);
0451             hlPos++;
0452         }
0453     }
0454 }
0455 
0456 ////////////////////////////////////////////////////////////////////
0457 /// Skips a given number of bytes in the open stream.
0458 /// It might throw an IOException.
0459 void CDecoder::Skip(UINT64 offset) {
0460     m_stream->SetPos(FSFromCurrent, offset);
0461 }
0462 
0463 //////////////////////////////////////////////////////////////////////
0464 /// Dequantization of a single value at given position in subband.
0465 /// If encoded data is available, then stores dequantized band value into
0466 /// buffer m_value at position m_valuePos.
0467 /// Otherwise reads encoded data block and decodes it.
0468 /// It might throw an IOException.
0469 /// @param band A subband
0470 /// @param bandPos A valid position in subband band
0471 /// @param quantParam The quantization parameter
0472 void CDecoder::DequantizeValue(CSubband* band, UINT32 bandPos, int quantParam) {
0473     ASSERT(m_currentBlock);
0474 
0475     if (m_currentBlock->IsCompletelyRead()) {
0476         // all data of current macro block has been read --> prepare next macro block
0477         GetNextMacroBlock();
0478     }
0479 
0480     band->SetData(bandPos, m_currentBlock->m_value[m_currentBlock->m_valuePos] << quantParam);
0481     m_currentBlock->m_valuePos++;
0482 }
0483 
0484 //////////////////////////////////////////////////////////////////////
0485 // Gets next macro block
0486 // It might throw an IOException.
0487 void CDecoder::GetNextMacroBlock() {
0488     // current block has been read --> prepare next current block
0489     m_macroBlocksAvailable--;
0490 
0491     if (m_macroBlocksAvailable > 0) {
0492         m_currentBlock = m_macroBlocks[++m_currentBlockIndex];
0493     } else {
0494         DecodeBuffer();
0495     }
0496     ASSERT(m_currentBlock);
0497 }
0498 
0499 //////////////////////////////////////////////////////////////////////
0500 // Reads next block(s) from stream and decodes them
0501 // Decoding scheme: <wordLen>(16 bits) [ ROI ] data
0502 //      ROI   ::= <bufferSize>(15 bits) <eofTile>(1 bit)
0503 // It might throw an IOException.
0504 void CDecoder::DecodeBuffer() {
0505     ASSERT(m_macroBlocksAvailable <= 0);
0506 
0507     // macro block management
0508     if (m_macroBlockLen == 1) {
0509         ASSERT(m_currentBlock);
0510         ReadMacroBlock(m_currentBlock);
0511         m_currentBlock->BitplaneDecode();
0512         m_macroBlocksAvailable = 1;
0513     } else {
0514         m_macroBlocksAvailable = 0;
0515         for (int i=0; i < m_macroBlockLen; i++) {
0516             // read sequentially several blocks
0517             try {
0518                 ReadMacroBlock(m_macroBlocks[i]);
0519                 m_macroBlocksAvailable++;
0520             } catch(IOException& ex) {
0521                 if (ex.error == MissingData || ex.error == FormatCannotRead) {
0522                     break; // no further data available or the data isn't valid PGF data (might occur in streaming or PPPExt)
0523                 } else {
0524                     throw;
0525                 }
0526             }
0527         }
0528 #ifdef LIBPGF_USE_OPENMP
0529         // decode in parallel
0530         #pragma omp parallel for default(shared) //no declared exceptions in next block
0531 #endif
0532         for (int i=0; i < m_macroBlocksAvailable; i++) {
0533             m_macroBlocks[i]->BitplaneDecode();
0534         }
0535 
0536         // prepare current macro block
0537         m_currentBlockIndex = 0;
0538         m_currentBlock = m_macroBlocks[m_currentBlockIndex];
0539     }
0540 }
0541 
0542 //////////////////////////////////////////////////////////////////////
0543 // Reads next block from stream and stores it in the given macro block
0544 // It might throw an IOException.
0545 void CDecoder::ReadMacroBlock(CMacroBlock* block) {
0546     ASSERT(block);
0547 
0548     UINT16 wordLen;
0549     ROIBlockHeader h(BufferSize);
0550     int count, expected;
0551 
0552 #ifdef TRACE
0553     //UINT32 filePos = (UINT32)m_stream->GetPos();
0554     //printf("DecodeBuffer: %d\n", filePos);
0555 #endif
0556 
0557     // read wordLen
0558     count = expected = sizeof(UINT16);
0559     m_stream->Read(&count, &wordLen);
0560     if (count != expected) ReturnWithError(MissingData);
0561     wordLen = __VAL(wordLen); // convert wordLen
0562     if (wordLen > BufferSize) ReturnWithError(FormatCannotRead);
0563 
0564 #ifdef __PGFROISUPPORT__
0565     // read ROIBlockHeader
0566     if (m_roi) {
0567         count = expected = sizeof(ROIBlockHeader);
0568         m_stream->Read(&count, &h.val);
0569         if (count != expected) ReturnWithError(MissingData);
0570         h.val = __VAL(h.val); // convert ROIBlockHeader
0571     }
0572 #endif
0573     // save header
0574     block->m_header = h;
0575 
0576     // read data
0577     count = expected = wordLen*WordBytes;
0578     m_stream->Read(&count, block->m_codeBuffer);
0579     if (count != expected) ReturnWithError(MissingData);
0580 
0581 #ifdef PGF_USE_BIG_ENDIAN
0582     // convert data
0583     count /= WordBytes;
0584     for (int i=0; i < count; i++) {
0585         block->m_codeBuffer[i] = __VAL(block->m_codeBuffer[i]);
0586     }
0587 #endif
0588 
0589 #ifdef __PGFROISUPPORT__
0590     ASSERT(m_roi && h.rbh.bufferSize <= BufferSize || h.rbh.bufferSize == BufferSize);
0591 #else
0592     ASSERT(h.rbh.bufferSize == BufferSize);
0593 #endif
0594 }
0595 
0596 #ifdef __PGFROISUPPORT__
0597 //////////////////////////////////////////////////////////////////////
0598 // Resets stream position to next tile.
0599 // Used with ROI encoding scheme only.
0600 // Reads several next blocks from stream but doesn't decode them into macro blocks
0601 // Encoding scheme: <wordLen>(16 bits) ROI data
0602 //      ROI   ::= <bufferSize>(15 bits) <eofTile>(1 bit)
0603 // It might throw an IOException.
0604 void CDecoder::SkipTileBuffer() {
0605     ASSERT(m_roi);
0606 
0607     // current macro block belongs to the last tile, so go to the next macro block
0608     m_macroBlocksAvailable--;
0609     m_currentBlockIndex++;
0610 
0611     // check if pre-decoded data is available
0612     while (m_macroBlocksAvailable > 0 && !m_macroBlocks[m_currentBlockIndex]->m_header.rbh.tileEnd) {
0613         m_macroBlocksAvailable--;
0614         m_currentBlockIndex++;
0615     }
0616     if (m_macroBlocksAvailable > 0) {
0617         // set new current macro block
0618         m_currentBlock = m_macroBlocks[m_currentBlockIndex];
0619         ASSERT(m_currentBlock->m_header.rbh.tileEnd);
0620         return;
0621     }
0622 
0623     ASSERT(m_macroBlocksAvailable <= 0);
0624     m_macroBlocksAvailable = 0;
0625     UINT16 wordLen;
0626     ROIBlockHeader h(0);
0627     int count, expected;
0628 
0629     // skips all blocks until tile end
0630     do {
0631         // read wordLen
0632         count = expected = sizeof(wordLen);
0633         m_stream->Read(&count, &wordLen);
0634         if (count != expected) ReturnWithError(MissingData);
0635         wordLen = __VAL(wordLen); // convert wordLen
0636         if (wordLen > BufferSize) ReturnWithError(FormatCannotRead);
0637 
0638         // read ROIBlockHeader
0639         count = expected = sizeof(ROIBlockHeader);
0640         m_stream->Read(&count, &h.val);
0641         if (count != expected) ReturnWithError(MissingData);
0642         h.val = __VAL(h.val); // convert ROIBlockHeader
0643 
0644         // skip data
0645         m_stream->SetPos(FSFromCurrent, wordLen*WordBytes);
0646     } while (!h.rbh.tileEnd);
0647 }
0648 #endif
0649 
0650 //////////////////////////////////////////////////////////////////////
0651 // Decodes macro block into buffer of given size using bit plane coding.
0652 // A buffer contains bufferLen UINT32 values, thus, bufferSize bits per bit plane.
0653 // Following coding scheme is used:
0654 //      Buffer      ::= <nPlanes>(5 bits) Q_FOREACH (plane i): Plane[i]
0655 //      Plane[i]    ::= [ Sig1 | Sig2 ] [DWORD alignment] refBits
0656 //      Sig1        ::= 1 <codeLen>(15 bits) codedSigAndSignBits
0657 //      Sig2        ::= 0 <sigLen>(15 bits) [Sign1 | Sign2 ] [DWORD alignment] sigBits
0658 //      Sign1       ::= 1 <codeLen>(15 bits) codedSignBits
0659 //      Sign2       ::= 0 <signLen>(15 bits) [DWORD alignment] signBits
0660 void CDecoder::CMacroBlock::BitplaneDecode() {
0661     UINT32 bufferSize = m_header.rbh.bufferSize; ASSERT(bufferSize <= BufferSize);
0662 
0663     // clear significance vector
0664     for (UINT32 k=0; k < bufferSize; k++) {
0665         m_sigFlagVector[k] = false;
0666     }
0667     m_sigFlagVector[bufferSize] = true; // sentinel
0668 
0669     // clear output buffer
0670     for (UINT32 k=0; k < BufferSize; k++) {
0671         m_value[k] = 0;
0672     }
0673 
0674     // read number of bit planes
0675     // <nPlanes>
0676     UINT32 nPlanes = GetValueBlock(m_codeBuffer, 0, MaxBitPlanesLog);
0677     UINT32 codePos = MaxBitPlanesLog;
0678 
0679     // loop through all bit planes
0680     if (nPlanes == 0) nPlanes = MaxBitPlanes + 1;
0681     ASSERT(0 < nPlanes && nPlanes <= MaxBitPlanes + 1);
0682     DataT planeMask = 1 << (nPlanes - 1);
0683 
0684     for (int plane = nPlanes - 1; plane >= 0; plane--) {
0685         UINT32 sigLen = 0;
0686 
0687         // read RL code
0688         if (GetBit(m_codeBuffer, codePos)) {
0689             // RL coding of sigBits is used
0690             // <1><codeLen><codedSigAndSignBits>_<refBits>
0691             codePos++;
0692 
0693             // read codeLen
0694             UINT32 codeLen = GetValueBlock(m_codeBuffer, codePos, RLblockSizeLen); ASSERT(codeLen <= MaxCodeLen);
0695 
0696             // position of encoded sigBits and signBits
0697             UINT32 sigPos = codePos + RLblockSizeLen; ASSERT(sigPos < CodeBufferBitLen);
0698 
0699             // refinement bits
0700             codePos = AlignWordPos(sigPos + codeLen); ASSERT(codePos < CodeBufferBitLen);
0701 
0702             // run-length decode significant bits and signs from m_codeBuffer and
0703             // read refinement bits from m_codeBuffer and compose bit plane
0704             sigLen = ComposeBitplaneRLD(bufferSize, planeMask, sigPos, &m_codeBuffer[codePos >> WordWidthLog]);
0705 
0706         } else {
0707             // no RL coding is used for sigBits and signBits together
0708             // <0><sigLen>
0709             codePos++;
0710 
0711             // read sigLen
0712             sigLen = GetValueBlock(m_codeBuffer, codePos, RLblockSizeLen); ASSERT(sigLen <= MaxCodeLen);
0713             codePos += RLblockSizeLen; ASSERT(codePos < CodeBufferBitLen);
0714 
0715             // read RL code for signBits
0716             if (GetBit(m_codeBuffer, codePos)) {
0717                 // RL coding is used just for signBits
0718                 // <1><codeLen><codedSignBits>_<sigBits>_<refBits>
0719                 codePos++;
0720 
0721                 // read codeLen
0722                 UINT32 codeLen = GetValueBlock(m_codeBuffer, codePos, RLblockSizeLen); ASSERT(codeLen <= MaxCodeLen);
0723 
0724                 // sign bits
0725                 UINT32 signPos = codePos + RLblockSizeLen; ASSERT(signPos < CodeBufferBitLen);
0726 
0727                 // significant bits
0728                 UINT32 sigPos = AlignWordPos(signPos + codeLen); ASSERT(sigPos < CodeBufferBitLen);
0729 
0730                 // refinement bits
0731                 codePos = AlignWordPos(sigPos + sigLen); ASSERT(codePos < CodeBufferBitLen);
0732 
0733                 // read significant and refinement bitset from m_codeBuffer
0734                 sigLen = ComposeBitplaneRLD(bufferSize, planeMask, &m_codeBuffer[sigPos >> WordWidthLog], &m_codeBuffer[codePos >> WordWidthLog], signPos);
0735 
0736             } else {
0737                 // RL coding of signBits was not efficient and therefore not used
0738                 // <0><signLen>_<signBits>_<sigBits>_<refBits>
0739                 codePos++;
0740 
0741                 // read signLen
0742                 UINT32 signLen = GetValueBlock(m_codeBuffer, codePos, RLblockSizeLen); ASSERT(signLen <= MaxCodeLen);
0743 
0744                 // sign bits
0745                 UINT32 signPos = AlignWordPos(codePos + RLblockSizeLen); ASSERT(signPos < CodeBufferBitLen);
0746 
0747                 // significant bits
0748                 UINT32 sigPos = AlignWordPos(signPos + signLen); ASSERT(sigPos < CodeBufferBitLen);
0749 
0750                 // refinement bits
0751                 codePos = AlignWordPos(sigPos + sigLen); ASSERT(codePos < CodeBufferBitLen);
0752 
0753                 // read significant and refinement bitset from m_codeBuffer
0754                 sigLen = ComposeBitplane(bufferSize, planeMask, &m_codeBuffer[sigPos >> WordWidthLog], &m_codeBuffer[codePos >> WordWidthLog], &m_codeBuffer[signPos >> WordWidthLog]);
0755             }
0756         }
0757 
0758         // start of next chunk
0759         codePos = AlignWordPos(codePos + bufferSize - sigLen); ASSERT(codePos < CodeBufferBitLen);
0760 
0761         // next plane
0762         planeMask >>= 1;
0763     }
0764 
0765     m_valuePos = 0;
0766 }
0767 
0768 ////////////////////////////////////////////////////////////////////
0769 // Reconstructs bitplane from significant bitset and refinement bitset
0770 // returns length [bits] of sigBits
0771 // input:  sigBits, refBits, signBits
0772 // output: m_value
0773 UINT32 CDecoder::CMacroBlock::ComposeBitplane(UINT32 bufferSize, DataT planeMask, UINT32* sigBits, UINT32* refBits, UINT32* signBits) {
0774     ASSERT(sigBits);
0775     ASSERT(refBits);
0776     ASSERT(signBits);
0777 
0778     UINT32 valPos = 0, signPos = 0, refPos = 0, sigPos = 0;
0779 
0780     while (valPos < bufferSize) {
0781         // search next 1 in m_sigFlagVector using searching with sentinel
0782         UINT32 sigEnd = valPos;
0783         while(!m_sigFlagVector[sigEnd]) { sigEnd++; }
0784         sigEnd -= valPos;
0785         sigEnd += sigPos;
0786 
0787         // search 1's in sigBits[sigPos..sigEnd)
0788         // these 1's are significant bits
0789         while (sigPos < sigEnd) {
0790             // search 0's
0791             UINT32 zerocnt = SeekBitRange(sigBits, sigPos, sigEnd - sigPos);
0792             sigPos += zerocnt;
0793             valPos += zerocnt;
0794             if (sigPos < sigEnd) {
0795                 // write bit to m_value
0796                 SetBitAtPos(valPos, planeMask);
0797 
0798                 // copy sign bit
0799                 SetSign(valPos, GetBit(signBits, signPos++));
0800 
0801                 // update significance flag vector
0802                 m_sigFlagVector[valPos++] = true;
0803                 sigPos++;
0804             }
0805         }
0806         // refinement bit
0807         if (valPos < bufferSize) {
0808             // write one refinement bit
0809             if (GetBit(refBits, refPos)) {
0810                 SetBitAtPos(valPos, planeMask);
0811             }
0812             refPos++;
0813             valPos++;
0814         }
0815     }
0816     ASSERT(sigPos <= bufferSize);
0817     ASSERT(refPos <= bufferSize);
0818     ASSERT(signPos <= bufferSize);
0819     ASSERT(valPos == bufferSize);
0820 
0821     return sigPos;
0822 }
0823 
0824 ////////////////////////////////////////////////////////////////////
0825 // Reconstructs bitplane from significant bitset and refinement bitset
0826 // returns length [bits] of decoded significant bits
0827 // input:  RL encoded sigBits and signBits in m_codeBuffer, refBits
0828 // output: m_value
0829 // RLE:
0830 // - Decode run of 2^k zeros by a single 0.
0831 // - Decode run of count 0's followed by a 1 with codeword: 1<count>x
0832 // - x is 0: if a positive sign has been stored, otherwise 1
0833 // - Read each bit from m_codeBuffer[codePos] and increment codePos.
0834 UINT32 CDecoder::CMacroBlock::ComposeBitplaneRLD(UINT32 bufferSize, DataT planeMask, UINT32 codePos, UINT32* refBits) {
0835     ASSERT(refBits);
0836 
0837     UINT32 valPos = 0, refPos = 0;
0838     UINT32 sigPos = 0, sigEnd;
0839     UINT32 k = 3;
0840     UINT32 runlen = 1 << k; // = 2^k
0841     UINT32 count = 0, rest = 0;
0842     bool set1 = false;
0843 
0844     while (valPos < bufferSize) {
0845         // search next 1 in m_sigFlagVector using searching with sentinel
0846         sigEnd = valPos;
0847         while(!m_sigFlagVector[sigEnd]) { sigEnd++; }
0848         sigEnd -= valPos;
0849         sigEnd += sigPos;
0850 
0851         while (sigPos < sigEnd) {
0852             if (rest || set1) {
0853                 // rest of last run
0854                 sigPos += rest;
0855                 valPos += rest;
0856                 rest = 0;
0857             } else {
0858                 // decode significant bits
0859                 if (GetBit(m_codeBuffer, codePos++)) {
0860                     // extract counter and generate zero run of length count
0861                     if (k > 0) {
0862                         // extract counter
0863                         count = GetValueBlock(m_codeBuffer, codePos, k);
0864                         codePos += k;
0865                         if (count > 0) {
0866                             sigPos += count;
0867                             valPos += count;
0868                         }
0869 
0870                         // adapt k (half run-length interval)
0871                         k--;
0872                         runlen >>= 1;
0873                     }
0874 
0875                     set1 = true;
0876 
0877                 } else {
0878                     // generate zero run of length 2^k
0879                     sigPos += runlen;
0880                     valPos += runlen;
0881 
0882                     // adapt k (double run-length interval)
0883                     if (k < WordWidth) {
0884                         k++;
0885                         runlen <<= 1;
0886                     }
0887                 }
0888             }
0889 
0890             if (sigPos < sigEnd) {
0891                 if (set1) {
0892                     set1 = false;
0893 
0894                     // write 1 bit
0895                     SetBitAtPos(valPos, planeMask);
0896 
0897                     // set sign bit
0898                     SetSign(valPos, GetBit(m_codeBuffer, codePos++));
0899 
0900                     // update significance flag vector
0901                     m_sigFlagVector[valPos++] = true;
0902                     sigPos++;
0903                 }
0904             } else {
0905                 rest = sigPos - sigEnd;
0906                 sigPos = sigEnd;
0907                 valPos -= rest;
0908             }
0909 
0910         }
0911 
0912         // refinement bit
0913         if (valPos < bufferSize) {
0914             // write one refinement bit
0915             if (GetBit(refBits, refPos)) {
0916                 SetBitAtPos(valPos, planeMask);
0917             }
0918             refPos++;
0919             valPos++;
0920         }
0921     }
0922     ASSERT(sigPos <= bufferSize);
0923     ASSERT(refPos <= bufferSize);
0924     ASSERT(valPos == bufferSize);
0925 
0926     return sigPos;
0927 }
0928 
0929 ////////////////////////////////////////////////////////////////////
0930 // Reconstructs bitplane from significant bitset, refinement bitset, and RL encoded sign bits
0931 // returns length [bits] of sigBits
0932 // input:  sigBits, refBits, RL encoded signBits
0933 // output: m_value
0934 // RLE:
0935 // decode run of 2^k 1's by a single 1
0936 // decode run of count 1's followed by a 0 with codeword: 0<count>
0937 UINT32 CDecoder::CMacroBlock::ComposeBitplaneRLD(UINT32 bufferSize, DataT planeMask, UINT32* sigBits, UINT32* refBits, UINT32 signPos) {
0938     ASSERT(sigBits);
0939     ASSERT(refBits);
0940 
0941     UINT32 valPos = 0, refPos = 0;
0942     UINT32 sigPos = 0, sigEnd;
0943     UINT32 zerocnt, count = 0;
0944     UINT32 k = 0;
0945     UINT32 runlen = 1 << k; // = 2^k
0946     bool signBit = false;
0947     bool zeroAfterRun = false;
0948 
0949     while (valPos < bufferSize) {
0950         // search next 1 in m_sigFlagVector using searching with sentinel
0951         sigEnd = valPos;
0952         while(!m_sigFlagVector[sigEnd]) { sigEnd++; }
0953         sigEnd -= valPos;
0954         sigEnd += sigPos;
0955 
0956         // search 1's in sigBits[sigPos..sigEnd)
0957         // these 1's are significant bits
0958         while (sigPos < sigEnd) {
0959             // search 0's
0960             zerocnt = SeekBitRange(sigBits, sigPos, sigEnd - sigPos);
0961             sigPos += zerocnt;
0962             valPos += zerocnt;
0963             if (sigPos < sigEnd) {
0964                 // write bit to m_value
0965                 SetBitAtPos(valPos, planeMask);
0966 
0967                 // check sign bit
0968                 if (count == 0) {
0969                     // all 1's have been set
0970                     if (zeroAfterRun) {
0971                         // finish the run with a 0
0972                         signBit = false;
0973                         zeroAfterRun = false;
0974                     } else {
0975                         // decode next sign bit
0976                         if (GetBit(m_codeBuffer, signPos++)) {
0977                             // generate 1's run of length 2^k
0978                             count = runlen - 1;
0979                             signBit = true;
0980 
0981                             // adapt k (double run-length interval)
0982                             if (k < WordWidth) {
0983                                 k++;
0984                                 runlen <<= 1;
0985                             }
0986                         } else {
0987                             // extract counter and generate 1's run of length count
0988                             if (k > 0) {
0989                                 // extract counter
0990                                 count = GetValueBlock(m_codeBuffer, signPos, k);
0991                                 signPos += k;
0992 
0993                                 // adapt k (half run-length interval)
0994                                 k--;
0995                                 runlen >>= 1;
0996                             }
0997                             if (count > 0) {
0998                                 count--;
0999                                 signBit = true;
1000                                 zeroAfterRun = true;
1001                             } else {
1002                                 signBit = false;
1003                             }
1004                         }
1005                     }
1006                 } else {
1007                     ASSERT(count > 0);
1008                     ASSERT(signBit);
1009                     count--;
1010                 }
1011 
1012                 // copy sign bit
1013                 SetSign(valPos, signBit);
1014 
1015                 // update significance flag vector
1016                 m_sigFlagVector[valPos++] = true;
1017                 sigPos++;
1018             }
1019         }
1020 
1021         // refinement bit
1022         if (valPos < bufferSize) {
1023             // write one refinement bit
1024             if (GetBit(refBits, refPos)) {
1025                 SetBitAtPos(valPos, planeMask);
1026             }
1027             refPos++;
1028             valPos++;
1029         }
1030     }
1031     ASSERT(sigPos <= bufferSize);
1032     ASSERT(refPos <= bufferSize);
1033     ASSERT(valPos == bufferSize);
1034 
1035     return sigPos;
1036 }
1037 
1038 ////////////////////////////////////////////////////////////////////
1039 #ifdef TRACE
1040 void CDecoder::DumpBuffer() {
1041     //printf("\nDump\n");
1042     //for (int i=0; i < BufferSize; i++) {
1043     //  printf("%d", m_value[i]);
1044     //}
1045 }
1046 #endif //TRACE
1047 
1048 #if defined(__GNUC__)
1049 #pragma GCC diagnostic pop
1050 #endif
1051 
1052 #if defined(__APPLE__)
1053 #pragma clang diagnostic pop
1054 #endif