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.h
0026 /// @brief PGF decoder class
0027 /// @author C. Stamm, R. Spuler
0028 
0029 #ifndef PGF_DECODER_H
0030 #define PGF_DECODER_H
0031 
0032 #include "PGFstream.h"
0033 #include "BitStream.h"
0034 #include "Subband.h"
0035 #include "WaveletTransform.h"
0036 
0037 #include "digikam_export.h"
0038 
0039 /////////////////////////////////////////////////////////////////////
0040 // Constants
0041 #define BufferLen           (BufferSize/WordWidth)  ///< number of words per buffer
0042 #define CodeBufferLen       BufferSize              ///< number of words in code buffer (CodeBufferLen > BufferLen)
0043 
0044 /////////////////////////////////////////////////////////////////////
0045 /// PGF decoder class.
0046 /// @author C. Stamm, R. Spuler
0047 /// @brief PGF decoder
0048 class DIGIKAM_EXPORT CDecoder {
0049     //////////////////////////////////////////////////////////////////////
0050     /// PGF decoder macro block class.
0051     /// @author C. Stamm, I. Bauersachs
0052     /// @brief A macro block is a decoding unit of fixed size (uncoded)
0053     class CMacroBlock {
0054     public:
0055         //////////////////////////////////////////////////////////////////////
0056         /// Constructor: Initializes new macro block.
0057         CMacroBlock()
0058         : m_header(0)                               // makes sure that IsCompletelyRead() returns true for an empty macro block
0059 #ifdef _MSC_VER
0060 #pragma warning( suppress : 4351 )
0061 #endif
0062         , m_value()
0063         , m_codeBuffer()
0064         , m_valuePos(0)
0065         , m_sigFlagVector()
0066         {
0067         }
0068 
0069         //////////////////////////////////////////////////////////////////////
0070         /// Returns true if this macro block has been completely read.
0071         /// @return true if current value position is at block end
0072         bool IsCompletelyRead() const   { return m_valuePos >= m_header.rbh.bufferSize; }
0073 
0074         //////////////////////////////////////////////////////////////////////
0075         /// Decodes already read input data into this macro block.
0076         /// Several macro blocks can be decoded in parallel.
0077         /// Call CDecoder::ReadMacroBlock before this method.
0078         void BitplaneDecode();
0079 
0080         ROIBlockHeader m_header;                    ///< block header
0081         DataT  m_value[BufferSize];                 ///< output buffer of values with index m_valuePos
0082         UINT32 m_codeBuffer[CodeBufferLen];         ///< input buffer for encoded bitstream
0083         UINT32 m_valuePos;                          ///< current position in m_value
0084 
0085     private:
0086         UINT32 ComposeBitplane(UINT32 bufferSize, DataT planeMask, UINT32* sigBits, UINT32* refBits, UINT32* signBits);
0087         UINT32 ComposeBitplaneRLD(UINT32 bufferSize, DataT planeMask, UINT32 sigPos, UINT32* refBits);
0088         UINT32 ComposeBitplaneRLD(UINT32 bufferSize, DataT planeMask, UINT32* sigBits, UINT32* refBits, UINT32 signPos);
0089         void  SetBitAtPos(UINT32 pos, DataT planeMask)          { (m_value[pos] >= 0) ? m_value[pos] |= planeMask : m_value[pos] -= planeMask; }
0090         void  SetSign(UINT32 pos, bool sign)                    { m_value[pos] = -m_value[pos]*sign + m_value[pos]*(!sign); }
0091 
0092         bool m_sigFlagVector[BufferSize+1];         // see paper from Malvar, Fast Progressive Wavelet Coder
0093     };
0094 
0095 public:
0096     /////////////////////////////////////////////////////////////////////
0097     /// Constructor: Read pre-header, header, and levelLength at current stream position.
0098     /// It might throw an IOException.
0099     /// @param stream A PGF stream
0100     /// @param preHeader [out] A PGF pre-header
0101     /// @param header [out] A PGF header
0102     /// @param postHeader [out] A PGF post-header
0103     /// @param levelLength The location of the levelLength array. The array is allocated in this method. The caller has to delete this array.
0104     /// @param userDataPos The stream position of the user data (metadata)
0105     /// @param useOMP If true, then the decoder will use multi-threading based on openMP
0106     /// @param userDataPolicy Policy of user data (meta-data) handling while reading PGF headers.
0107     CDecoder(CPGFStream* stream, PGFPreHeader& preHeader, PGFHeader& header,
0108              PGFPostHeader& postHeader, UINT32*& levelLength, UINT64& userDataPos,
0109              bool useOMP, UINT32 userDataPolicy); // throws IOException
0110 
0111     /////////////////////////////////////////////////////////////////////
0112     /// Destructor
0113     ~CDecoder();
0114 
0115     /////////////////////////////////////////////////////////////////////
0116     /// Unpartitions a rectangular region of a given subband.
0117     /// Partitioning scheme: The plane is partitioned in squares of side length LinBlockSize.
0118     /// Read wavelet coefficients from the output buffer of a macro block.
0119     /// It might throw an IOException.
0120     /// @param band A subband
0121     /// @param quantParam Dequantization value
0122     /// @param width The width of the rectangle
0123     /// @param height The height of the rectangle
0124     /// @param startPos The relative subband position of the top left corner of the rectangular region
0125     /// @param pitch The number of bytes in row of the subband
0126     void Partition(CSubband* band, int quantParam, int width, int height, int startPos, int pitch);
0127 
0128     /////////////////////////////////////////////////////////////////////
0129     /// Deccoding and dequantization of HL and LH subband (interleaved) using partitioning scheme.
0130     /// Partitioning scheme: The plane is partitioned in squares of side length InterBlockSize.
0131     /// It might throw an IOException.
0132     /// @param wtChannel A wavelet transform channel containing the HL and HL band
0133     /// @param level Wavelet transform level
0134     /// @param quantParam Dequantization value
0135     void DecodeInterleaved(CWaveletTransform* wtChannel, int level, int quantParam);
0136 
0137     //////////////////////////////////////////////////////////////////////
0138     /// Returns the length of all encoded headers in bytes.
0139     /// @return The length of all encoded headers in bytes
0140     UINT32 GetEncodedHeaderLength() const           { return m_encodedHeaderLength; }
0141 
0142     ////////////////////////////////////////////////////////////////////
0143     /// Resets stream position to beginning of PGF pre-header
0144     void SetStreamPosToStart()              { ASSERT(m_stream); m_stream->SetPos(FSFromStart, m_startPos); }
0145 
0146     ////////////////////////////////////////////////////////////////////
0147     /// Resets stream position to beginning of data block
0148     void SetStreamPosToData()               { ASSERT(m_stream); m_stream->SetPos(FSFromStart, m_startPos + m_encodedHeaderLength); }
0149 
0150     ////////////////////////////////////////////////////////////////////
0151     /// Skips a given number of bytes in the open stream.
0152     /// It might throw an IOException.
0153     void Skip(UINT64 offset);
0154 
0155     /////////////////////////////////////////////////////////////////////
0156     /// Dequantization of a single value at given position in subband.
0157     /// It might throw an IOException.
0158     /// @param band A subband
0159     /// @param bandPos A valid position in subband band
0160     /// @param quantParam The quantization parameter
0161     void DequantizeValue(CSubband* band, UINT32 bandPos, int quantParam);
0162 
0163     //////////////////////////////////////////////////////////////////////
0164     /// Copies data from the open stream to a target buffer.
0165     /// It might throw an IOException.
0166     /// @param target The target buffer
0167     /// @param len The number of bytes to read
0168     /// @return The number of bytes copied to the target buffer
0169     UINT32 ReadEncodedData(UINT8* target, UINT32 len) const;
0170 
0171     /////////////////////////////////////////////////////////////////////
0172     /// Reads next block(s) from stream and decodes them
0173     /// It might throw an IOException.
0174     void DecodeBuffer();
0175 
0176     /////////////////////////////////////////////////////////////////////
0177     /// @return Stream
0178     CPGFStream* GetStream()                         { return m_stream; }
0179 
0180     /////////////////////////////////////////////////////////////////////
0181     /// Gets next macro block
0182     /// It might throw an IOException.
0183     void GetNextMacroBlock();
0184 
0185 #ifdef __PGFROISUPPORT__
0186     /////////////////////////////////////////////////////////////////////
0187     /// Resets stream position to next tile.
0188     /// Used with ROI encoding scheme only.
0189     /// It might throw an IOException.
0190     void SkipTileBuffer();
0191 
0192     /////////////////////////////////////////////////////////////////////
0193     /// Enables region of interest (ROI) status.
0194     void SetROI()                   { m_roi = true; }
0195 #endif
0196 
0197 #ifdef TRACE
0198     void DumpBuffer();
0199 #endif
0200 
0201 private:
0202     void ReadMacroBlock(CMacroBlock* block); ///< throws IOException
0203 
0204     CPGFStream *m_stream;                       ///< input PGF stream
0205     UINT64 m_startPos;                          ///< stream position at the beginning of the PGF pre-header
0206     UINT64 m_streamSizeEstimation;              ///< estimation of stream size
0207     UINT32 m_encodedHeaderLength;               ///< stream offset from startPos to the beginning of the data part (highest level)
0208 
0209     CMacroBlock **m_macroBlocks;                ///< array of macroblocks
0210     int m_currentBlockIndex;                    ///< index of current macro block
0211     int m_macroBlockLen;                        ///< array length
0212     int m_macroBlocksAvailable;                 ///< number of decoded macro blocks (including currently used macro block)
0213     CMacroBlock *m_currentBlock;                ///< current macro block (used by main thread)
0214 
0215 #ifdef __PGFROISUPPORT__
0216     bool   m_roi;                               ///< true: ensures region of interest (ROI) decoding
0217 #endif
0218 };
0219 
0220 #endif //PGF_DECODER_H