/*
 * class Wavelet
 *
 * $Date$
 * $Revision$
 *
 */

#ifndef WAVELET_HH__
#define WAVELET_HH__

#include "WImage/ReferenceVector.hh"
#include "Wave/VectorPosition.hh"
#include "Wave/Filter.hh"

/** 
 * @addtogroup Wave 
 * @{ */

/** 
 * A Wavelet. The Wavelet transform is one-dimensional, it
 * thus works on vectors.
 */
class 
Wavelet
{
public:
  /** Calculate the level for the transform and execute some 
   * consistency checks. 
   * @exception invalid_argument
   * vector size is not a power of two or the two vectors don't have
   * the same size
   * @param dest
   * the destination vector
   * @param src
   * the source vector
   * @param steps
   * the number of steps for the transform */
  int level (ReferenceVector &dest, ReferenceVector &src, int steps);

  /** Constructor. Sets the the filter. */
  Wavelet (FilterSet &fset);
  /** Destructor. Releases allocated objects. */
  virtual ~Wavelet (void);

  /** Decompose a vector. The result is written to a second vector. 
   * @exception invalid_argument
   * low pass subband signal too small (decrease the number of transform
   * steps or increase signal size)
   * @param src
   * A vector of {\em coeff} containing the original data
   * @param dest
   * A vector of {\em coeff} to get the transformed data
   * @param steps
   * The last col the decomposition step will be performed to
   */
  void analysis (ReferenceVector &dest, ReferenceVector &src, int steps);


  /** Reconstruct a vector. The result is written to a second vector. 
   * @param src
   * A vector of {\em coeff} containing the analysisd data
   * @param dest
   * A vector of {\em coeff} to get the synthesised data
   * @param steps
   * The number of coefficient pairs to synthesis.
   * @param prevSteps 
   * if greater than 0, the number of previous decomposition steps
   * to assume. This is necessary to reconstruct images that are
   * not square and have side lengths which are not powers of two. */
  void synthesis (ReferenceVector &dest, ReferenceVector &src, 
                  int steps, int prevSteps = 0);
  
  /** A decomposition step on a vector. The result is written to a 
   * second vector. Only the result coefficients are being written,
   * the rest may have to be done manually.
   * @param dest
   * A vector of {\em coeff} to get the transformed data
   * @param src
   * A vector of {\em coeff} containing the original data
   * @param size
   * The number of values in {\em src} to perform the decomposition step on */
  virtual void 
  anastep (ReferenceVector &dest, ReferenceVector &src, int size);
  /** A reconstruction step on a vector. The result is written to a 
   * second vector. Only the result coefficients are being written,
   * the rest may have to be done manually.
   * @param dest
   * A vector of {\em coeff} to get the transformed data
   * @param src
   * A vector of {\em coeff} containing the original data
   * @param size
   * The number of values in {\em src} to perform the synthesis step on */
  virtual void 
  synstep (ReferenceVector &dest, ReferenceVector &src, int size);

#ifdef INCLUDE_DEPRECATED_API
  inline void analysis (ReferenceVector *dest, ReferenceVector *src, 
                        int steps) { analysis (*dest, *src, steps); }
  inline void synthesis (ReferenceVector *dest, ReferenceVector *src, 
                    int steps) { synthesis (*dest, *src, steps); } 
#endif
  
protected:
  /** Initialize the filter set to be used. The filters in the set will 
   * be duplicated.
   * @param pfset
   * a reference to the filter set */
  void init (FilterSet *pfset = NULL);
  /** The low pass analysis filter. */
  Filter *m_analow;       // H and G
  /** The high pass analysis filter. */
  Filter *m_anahigh;    
  /** The low pass synthesis filter. */
  Filter *m_synlow;       // H~ and G~
  /** The high pass synthesis filter. */
  Filter *m_synhigh;
  /** The padding object for the analysis. */
  VectorPosition *m_apad;
  /** The padding object for the synthesis low pass part. */
  VectorPosition *m_slpad;
  /** The padding object for the synthesis high pass part. */
  VectorPosition *m_shpad;
  /**  {\em true} if filter set is symmetric. */
  bool m_symmetric;       
  /** The number of padding coefficients needed. */
  int m_npad;
  /** Padding positions for analysis. */
  int *m_apositions; 
  /** Size of padding positions array for analysis. */
  int m_apsize;
  /** Padding positions for lowband synthesis. */
  int *m_slpositions; 
  /** Size of padding positions array for lowband synthesis . */
  int m_slpsize;
  /** Padding positions for highband synthesis. */
  int *m_shpositions; 
  /** Padding signs for highband synthesis. */
  int *m_shsigns; 
  /** Size of padding positions array for highband synthesis . */
  int m_shpsize;

}; /* class Wavelet */

/** @} */

#endif /* WAVELET_HH__ */


