/*
 * Implementation of class PyramidTransform
 *
 * $Date$
 * $Revision$
 *
 */
#include "Wave/PyramidTransform.hh"
#include "WImage/ColumnVector.hh"
#include "WImage/RowVector.hh"
#include "WImage/debug.h"
#include "WImage/tools.h"
#include <cassert>
#include <stdexcept>
#ifndef _WIN32_WCE
#include <iostream>
#else
#include "WImage/miscdefs.h"
#endif

#if !(defined __WATCOMC__ && __WATCOMC__ < 1230)
using namespace std;
#endif

void
PyramidTransform::doanalysis (int steps)
{
  RowVector &rv1 = m_image->row (0);
  RowVector &rv2 = m_buffer->row (0);
  ColumnVector &cv1 = m_image->col (0);
  ColumnVector &cv2 = m_buffer->col (0);

  int hSize = m_image->cols ();
  int vSize = m_image->rows ();

  int dummy;
  if (tools_powerOfTwo (rv1.size (), dummy))
    {
      int level = m_wavelet->level (rv1, rv2, steps);

      if (steps <= 0 || steps > level)
        {
          steps = level;
        }
    }

  m_image->anasteps (steps);

  /*
   * Do the decomposition...
   */
  for (; steps > 0; steps--)
    {
      DPRINTF (("vSize: %d\n", vSize));
      for (int row = 0; row < vSize; row++)
        {
          rv1.go (row);
          rv2.go (row);
          m_wavelet->anastep (rv2, rv1, hSize);
        }
      DPRINTF (("hSize: %d\n", hSize));
      for (int col = 0; col < hSize; col++)
        {
          cv1.go (col);
          cv2.go (col);
          m_wavelet->anastep (cv1, cv2, vSize);
        }

      vSize = (int)DIV2 (vSize + 1);
      hSize = (int)DIV2 (hSize + 1);
    }
}

void
PyramidTransform::dosynthesis (int steps, int prevSteps)
{
  RowVector &rv1 = m_image->row (0);
  RowVector &rv2 = m_buffer->row (0);
  ColumnVector &cv1 = m_image->col (0);
  ColumnVector &cv2 = m_buffer->col (0);

  int *hSize = NEW (int [steps]);
  int *vSize = NEW (int [steps]);

  hSize[0] = m_image->cols ();
  vSize[0] = m_image->rows ();

  if (prevSteps > 0)
    {
      for (int i = 0; i < prevSteps - steps; i++)
        {
          hSize[1] = DIV2 (hSize[0] + 1);
          vSize[1] = DIV2 (vSize[0] + 1);
          hSize[0] = hSize[1];
          vSize[0] = vSize[1];
        }
    }

  for (int i = 1; i < steps; i++)
    {
      hSize[i] = DIV2 (hSize[i-1] + 1);
      vSize[i] = DIV2 (vSize[i-1] + 1);
    }

  m_image->synsteps (steps);

  for (; steps > 0; steps--)
    {
      for (int col = 0; col < hSize[steps - 1]; col++)
        {
          cv1.go (col);
          cv2.go (col);
          m_wavelet->synstep (cv2, cv1, vSize[steps - 1]);
        }
      for (int row = 0; row < vSize[steps - 1]; row++)
        {
          rv1.go (row);
          rv2.go (row);
          m_wavelet->synstep (rv1, rv2, hSize[steps - 1]);
        }
    }
  DELETEAR (vSize);
  DELETEAR (hSize);
}
