Subversion Repositories Scribus

Rev

Rev 16771 | Rev 19721 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 * The Progressive Graphics File; http://www.libpgf.org
 *
 * $Date: 2006-06-04 22:05:59 +0200 (So, 04 Jun 2006) $
 * $Revision: 229 $
 *
 * This file Copyright (C) 2006 xeraina GmbH, Switzerland
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
 * as published by the Free Software Foundation; either version 2.1
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */


//////////////////////////////////////////////////////////////////////
/// @file Encoder.h
/// @brief PGF encoder class
/// @author C. Stamm, R. Spuler

#ifndef PGF_ENCODER_H
#define PGF_ENCODER_H

#include "PGFstream.h"
#include "BitStream.h"
#include "Subband.h"
#include "WaveletTransform.h"

/////////////////////////////////////////////////////////////////////
// Constants
#define BufferLen                       (BufferSize/WordWidth)  // number of words per buffer

/////////////////////////////////////////////////////////////////////
/// PGF encoder class.
/// @author C. Stamm
/// @brief PGF encoder
class CEncoder {
        //////////////////////////////////////////////////////////////////////
        /// PGF encoder macro block class.
        /// @author C. Stamm, I. Bauersachs
        /// @brief A macro block is an encoding unit of fixed size (uncoded)
        class CMacroBlock {
        public:
                CMacroBlock(CEncoder *encoder)
                : m_header(0)
        , m_encoder(encoder)
                {
                        ASSERT(m_encoder);
                        Init(-1);
                }

                DataT   m_value[BufferSize];                            // input buffer of values with index m_valuePos
                UINT32  m_codeBuffer[BufferSize];                       // output buffer for encoded bitstream

                ROIBlockHeader m_header;                                        // block header
                UINT32  m_valuePos;                                                     // current buffer position
                UINT32  m_maxAbsValue;                                          // maximum absolute coefficient in each buffer
                UINT32  m_codePos;                                                      // current position in encoded bitstream
                int             m_lastLevelIndex;                                       // index of last encoded level: [0, nLevels); used because a level-end can occur before a buffer is full

                void Init(int lastLevelIndex) {                         // initialize for reusage
                        m_valuePos = 0;
                        m_maxAbsValue = 0;
                        m_codePos = 0;
                        m_lastLevelIndex = lastLevelIndex;
                }
                void BitplaneEncode();                                          // several macro blocks can be encoded in parallel
        private:
                UINT32 RLESigns(UINT32 codePos, UINT32* signBits, UINT32 signLen);
                UINT32 DecomposeBitplane(UINT32 bufferSize, UINT32 planeMask, UINT32 codePos, UINT32* sigBits, UINT32* refBits, UINT32* signBits, UINT32& signLen, UINT32& codeLen);
                UINT8  NumberOfBitplanes();
                bool   GetBitAtPos(UINT32 pos, UINT32 planeMask) const  { return (abs(m_value[pos]) & planeMask) > 0; }

                CEncoder *m_encoder;                                            // encoder instance
                bool    m_sigFlagVector[BufferSize+1];          // see paper from Malvar, Fast Progressive Wavelet Coder
        };

public:
        /////////////////////////////////////////////////////////////////////
        /// Write pre-header, header, postHeader, and levelLength.
        /// It might throw an IOException.
        /// @param stream A PGF stream
        /// @param preHeader A already filled in PGF pre header
        /// @param header An already filled in PGF header
        /// @param postHeader [in] A already filled in PGF post header (containing color table, user data, ...)
        /// @param levelLength A reference to an integer array, large enough to save the relative file positions of all PGF levels
        /// @param useOMP If true, then the encoder will use multi-threading based on openMP
        CEncoder(CPGFStream* stream, PGFPreHeader preHeader, PGFHeader header, const PGFPostHeader& postHeader, UINT32*& levelLength, bool useOMP = true) THROW_; // throws IOException

        /////////////////////////////////////////////////////////////////////
        /// Destructor
        ~CEncoder();

        /////////////////////////////////////////////////////////////////////
        /// Encoder favors speed over compression size
        void FavorSpeedOverSize() { m_favorSpeed = true; }

        /////////////////////////////////////////////////////////////////////
        /// Pad buffer with zeros and encode buffer.
        /// It might throw an IOException.
        void Flush() THROW_;

        /////////////////////////////////////////////////////////////////////
        /// Write levelLength into header.
        /// @return number of bytes written into stream
        /// It might throw an IOException.
        UINT32 WriteLevelLength() THROW_;

        /////////////////////////////////////////////////////////////////////
        /// Partitions a rectangular region of a given subband.
        /// Partitioning scheme: The plane is partitioned in squares of side length LinBlockSize.
        /// Write wavelet coefficients into buffer.
        /// It might throw an IOException.
        /// @param band A subband
        /// @param width The width of the rectangle
        /// @param height The height of the rectangle
        /// @param startPos The buffer position of the top left corner of the rectangular region
        /// @param pitch The number of bytes in row of the subband
        void Partition(CSubband* band, int width, int height, int startPos, int pitch) THROW_;

        /////////////////////////////////////////////////////////////////////
        /// Informs the encoder about the encoded level.
        /// @param currentLevel encoded level [0, nLevels)
        void SetEncodedLevel(int currentLevel) { ASSERT(currentLevel >= 0); m_currentBlock->m_lastLevelIndex = m_nLevels - currentLevel - 1; m_forceWriting = true; }

        /////////////////////////////////////////////////////////////////////
        /// Write a single value into subband at given position.
        /// It might throw an IOException.
        /// @param band A subband
        /// @param bandPos A valid position in subband band
        void WriteValue(CSubband* band, int bandPos) THROW_;

        /////////////////////////////////////////////////////////////////////
        /// Compute stream length of header.
        /// @return header length
        UINT32 ComputeHeaderLength() const { return UINT32(m_bufferStartPos - m_startPosition); }

        /////////////////////////////////////////////////////////////////////
        /// Compute stream length of encoded buffer.
        /// @return encoded buffer length
        UINT32 ComputeBufferLength() const { return UINT32(m_stream->GetPos() - m_bufferStartPos); }

        /////////////////////////////////////////////////////////////////////
        /// Save current stream position as beginning of current level.
        void SetBufferStartPos() { m_bufferStartPos = m_stream->GetPos(); }

#ifdef __PGFROISUPPORT__
        /////////////////////////////////////////////////////////////////////
        /// Encodes tile buffer and writes it into stream
        /// It might throw an IOException.
        void EncodeTileBuffer() THROW_  { ASSERT(m_currentBlock && m_currentBlock->m_valuePos >= 0 && m_currentBlock->m_valuePos <= BufferSize); EncodeBuffer(ROIBlockHeader(m_currentBlock->m_valuePos, true)); }

        /////////////////////////////////////////////////////////////////////
        /// Enables region of interest (ROI) status.
        void SetROI()                                   { m_roi = true; }
#endif

#ifdef TRACE
        void DumpBuffer() const;
#endif

private:
        void EncodeBuffer(ROIBlockHeader h) THROW_; // throws IOException
        void WriteMacroBlock(CMacroBlock* block) THROW_; // throws IOException

        CPGFStream *m_stream;
        UINT64  m_startPosition;                                        // file position of PGF start (PreHeader)
        UINT64  m_levelLengthPos;                                       // file position of Metadata
        UINT64  m_bufferStartPos;                                       // file position of encoded buffer

        CMacroBlock **m_macroBlocks;                            // array of macroblocks
        int             m_macroBlockLen;                                        // array length
        int             m_lastMacroBlock;                                       // array index of the last created macro block
        CMacroBlock *m_currentBlock;                            // current macro block (used by main thread)

        UINT32* m_levelLength;                                          // temporary saves the level index
        int     m_currLevelIndex;                                       // counts where (=index) to save next value
        UINT8   m_nLevels;                                                      // number of levels
        bool    m_favorSpeed;                                           // favor speed over size
        bool    m_forceWriting;                                         // all macro blocks have to be written into the stream
#ifdef __PGFROISUPPORT__
        bool    m_roi;                                                          // true: ensures region of interest (ROI) encoding
#endif
};

#endif //PGF_ENCODER