File indexing completed on 2025-01-19 03:56:09
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 Encoder.h 0026 /// @brief PGF encoder class 0027 /// @author C. Stamm, R. Spuler 0028 0029 #ifndef PGF_ENCODER_H 0030 #define PGF_ENCODER_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 encoder class. 0046 /// @author C. Stamm 0047 /// @brief PGF encoder 0048 class DIGIKAM_EXPORT CEncoder { 0049 ////////////////////////////////////////////////////////////////////// 0050 /// PGF encoder macro block class. 0051 /// @author C. Stamm, I. Bauersachs 0052 /// @brief A macro block is an encoding unit of fixed size (uncoded) 0053 class CMacroBlock { 0054 public: 0055 ////////////////////////////////////////////////////////////////////// 0056 /// Constructor: Initializes new macro block. 0057 /// @param encoder Pointer to outer class. 0058 CMacroBlock(CEncoder *encoder) 0059 #ifdef _MSC_VER 0060 #pragma warning( suppress : 4351 ) 0061 #endif 0062 : m_value() 0063 , m_codeBuffer() 0064 , m_header(0) 0065 , m_encoder(encoder) 0066 , m_sigFlagVector() 0067 { 0068 ASSERT(m_encoder); 0069 Init(-1); 0070 } 0071 0072 ////////////////////////////////////////////////////////////////////// 0073 /// Reinitialzes this macro block (allows reusage). 0074 /// @param lastLevelIndex Level length directory index of last encoded level: [0, nLevels) 0075 void Init(int lastLevelIndex) { // initialize for reusage 0076 m_valuePos = 0; 0077 m_maxAbsValue = 0; 0078 m_codePos = 0; 0079 m_lastLevelIndex = lastLevelIndex; 0080 } 0081 0082 ////////////////////////////////////////////////////////////////////// 0083 /// Encodes this macro block into internal code buffer. 0084 /// Several macro blocks can be encoded in parallel. 0085 /// Call CEncoder::WriteMacroBlock after this method. 0086 void BitplaneEncode(); 0087 0088 DataT m_value[BufferSize]; ///< input buffer of values with index m_valuePos 0089 UINT32 m_codeBuffer[CodeBufferLen]; ///< output buffer for encoded bitstream 0090 ROIBlockHeader m_header; ///< block header 0091 UINT32 m_valuePos; ///< current buffer position 0092 UINT32 m_maxAbsValue; ///< maximum absolute coefficient in each buffer 0093 UINT32 m_codePos; ///< current position in encoded bitstream 0094 int m_lastLevelIndex; ///< index of last encoded level: [0, nLevels); used because a level-end can occur before a buffer is full 0095 0096 private: 0097 UINT32 RLESigns(UINT32 codePos, UINT32* signBits, UINT32 signLen); 0098 UINT32 DecomposeBitplane(UINT32 bufferSize, UINT32 planeMask, UINT32 codePos, UINT32* sigBits, UINT32* refBits, UINT32* signBits, UINT32& signLen, UINT32& codeLen); 0099 UINT8 NumberOfBitplanes(); 0100 bool GetBitAtPos(UINT32 pos, UINT32 planeMask) const { return (abs(m_value[pos]) & planeMask) > 0; } 0101 0102 CEncoder *m_encoder; // encoder instance 0103 bool m_sigFlagVector[BufferSize+1]; // see paper from Malvar, Fast Progressive Wavelet Coder 0104 }; 0105 0106 public: 0107 ///////////////////////////////////////////////////////////////////// 0108 /// Write pre-header, header, post-Header, and levelLength. 0109 /// It might throw an IOException. 0110 /// @param stream A PGF stream 0111 /// @param preHeader A already filled in PGF pre-header 0112 /// @param header An already filled in PGF header 0113 /// @param postHeader [in] An already filled in PGF post-header (containing color table, user data, ...) 0114 /// @param userDataPos [out] File position of user data 0115 /// @param useOMP If true, then the encoder will use multi-threading based on openMP 0116 CEncoder(CPGFStream* stream, PGFPreHeader preHeader, PGFHeader header, const PGFPostHeader& postHeader, 0117 UINT64& userDataPos, bool useOMP); // throws IOException 0118 0119 ///////////////////////////////////////////////////////////////////// 0120 /// Destructor 0121 ~CEncoder(); 0122 0123 ///////////////////////////////////////////////////////////////////// 0124 /// Encoder favors speed over compression size 0125 void FavorSpeedOverSize() { m_favorSpeed = true; } 0126 0127 ///////////////////////////////////////////////////////////////////// 0128 /// Pad buffer with zeros and encode buffer. 0129 /// It might throw an IOException. 0130 void Flush(); 0131 0132 ///////////////////////////////////////////////////////////////////// 0133 /// Increase post-header size and write new size into stream. 0134 /// @param preHeader An already filled in PGF pre-header 0135 /// It might throw an IOException. 0136 void UpdatePostHeaderSize(PGFPreHeader preHeader); 0137 0138 ///////////////////////////////////////////////////////////////////// 0139 /// Create level length data structure and write a place holder into stream. 0140 /// It might throw an IOException. 0141 /// @param levelLength A reference to an integer array, large enough to save the relative file positions of all PGF levels 0142 /// @return number of bytes written into stream 0143 UINT32 WriteLevelLength(UINT32*& levelLength); 0144 0145 ///////////////////////////////////////////////////////////////////// 0146 /// Write new levelLength into stream. 0147 /// It might throw an IOException. 0148 /// @return Written image bytes. 0149 UINT32 UpdateLevelLength(); 0150 0151 ///////////////////////////////////////////////////////////////////// 0152 /// Partitions a rectangular region of a given subband. 0153 /// Partitioning scheme: The plane is partitioned in squares of side length LinBlockSize. 0154 /// Write wavelet coefficients from subband into the input buffer of a macro block. 0155 /// It might throw an IOException. 0156 /// @param band A subband 0157 /// @param width The width of the rectangle 0158 /// @param height The height of the rectangle 0159 /// @param startPos The absolute subband position of the top left corner of the rectangular region 0160 /// @param pitch The number of bytes in row of the subband 0161 void Partition(CSubband* band, int width, int height, int startPos, int pitch); 0162 0163 ///////////////////////////////////////////////////////////////////// 0164 /// Informs the encoder about the encoded level. 0165 /// @param currentLevel encoded level [0, nLevels) 0166 void SetEncodedLevel(int currentLevel) { ASSERT(currentLevel >= 0); m_currentBlock->m_lastLevelIndex = m_nLevels - currentLevel - 1; m_forceWriting = true; } 0167 0168 ///////////////////////////////////////////////////////////////////// 0169 /// Write a single value into subband at given position. 0170 /// It might throw an IOException. 0171 /// @param band A subband 0172 /// @param bandPos A valid position in subband band 0173 void WriteValue(CSubband* band, int bandPos); 0174 0175 ///////////////////////////////////////////////////////////////////// 0176 /// Compute stream length of header. 0177 /// @return header length 0178 INT64 ComputeHeaderLength() const { return m_levelLengthPos - m_startPosition; } 0179 0180 ///////////////////////////////////////////////////////////////////// 0181 /// Compute stream length of encoded buffer. 0182 /// @return encoded buffer length 0183 INT64 ComputeBufferLength() const { return m_stream->GetPos() - m_bufferStartPos; } 0184 0185 ///////////////////////////////////////////////////////////////////// 0186 /// Compute file offset between real and expected levelLength position. 0187 /// @return file offset 0188 INT64 ComputeOffset() const { return m_stream->GetPos() - m_levelLengthPos; } 0189 0190 //////////////////////////////////////////////////////////////////// 0191 /// Resets stream position to beginning of PGF pre-header 0192 void SetStreamPosToStart() { ASSERT(m_stream); m_stream->SetPos(FSFromStart, m_startPosition); } 0193 0194 ///////////////////////////////////////////////////////////////////// 0195 /// Save current stream position as beginning of current level. 0196 void SetBufferStartPos() { m_bufferStartPos = m_stream->GetPos(); } 0197 0198 #ifdef __PGFROISUPPORT__ 0199 ///////////////////////////////////////////////////////////////////// 0200 /// Encodes tile buffer and writes it into stream 0201 /// It might throw an IOException. 0202 void EncodeTileBuffer() { ASSERT(m_currentBlock && m_currentBlock->m_valuePos >= 0 && m_currentBlock->m_valuePos <= BufferSize); EncodeBuffer(ROIBlockHeader(m_currentBlock->m_valuePos, true)); } 0203 0204 ///////////////////////////////////////////////////////////////////// 0205 /// Enables region of interest (ROI) status. 0206 void SetROI() { m_roi = true; } 0207 #endif 0208 0209 #ifdef TRACE 0210 void DumpBuffer() const; 0211 #endif 0212 0213 private: 0214 void EncodeBuffer(ROIBlockHeader h); // throws IOException 0215 void WriteMacroBlock(CMacroBlock* block); // throws IOException 0216 0217 CPGFStream *m_stream; ///< output PMF stream 0218 UINT64 m_startPosition; ///< stream position of PGF start (PreHeader) 0219 UINT64 m_levelLengthPos; ///< stream position of Metadata 0220 UINT64 m_bufferStartPos; ///< stream position of encoded buffer 0221 0222 CMacroBlock **m_macroBlocks; ///< array of macroblocks 0223 int m_macroBlockLen; ///< array length 0224 int m_lastMacroBlock; ///< array index of the last created macro block 0225 CMacroBlock *m_currentBlock; ///< current macro block (used by main thread) 0226 0227 UINT32* m_levelLength; ///< temporary saves the level index 0228 int m_currLevelIndex; ///< counts where (=index) to save next value 0229 UINT8 m_nLevels; ///< number of levels 0230 bool m_favorSpeed; ///< favor speed over size 0231 bool m_forceWriting; ///< all macro blocks have to be written into the stream 0232 #ifdef __PGFROISUPPORT__ 0233 bool m_roi; ///< true: ensures region of interest (ROI) encoding 0234 #endif 0235 }; 0236 0237 #endif //PGF_ENCODER