/* -*- mode: c++; c-basic-offset: 3 -*-
 *
 * PANDORE (PANTHEON Project)
 *
 * GREYC IMAGE
 * 6 Boulevard Maréchal Juin
 * F-14050 Caen Cedex France
 *
 * This file is free software. You can use it, distribute it
 * and/or modify it. However, the entire risk to the quality
 * and performance of this program is with you.
 *
 * Please email any bugs, comments, and/or additions to this file to:
 * pandore@greyc.ensicaen.fr
 * http://www.greyc.ensicaen.fr/EquipeImage/Pandore/
 */

/**
 * @author Jalal Fadili - 02-02-2005
 * @author Christophe Glinel - 20-07-2005
 */

/**
 * @file isoiudwt.cpp
 *
 * 2D Isotropic Inverse Undecimated Wavelet Transform (ISOIUDWT).
 * This uses the fact that all bands (including the approximation)
 * of the ISOUDWT sum up to the original image.
 *
 * La IUDWT implémentée ici ne traite que le cas des images
 * 2D  de niveaux de gris. Nous sommons toutes les bandes (avec l'approximation)
 * de l'image d'entrée. 
 */

#include <pandore.h>
using namespace pandore;
#include "wutils.cpp"

#ifdef MAIN
Float NORMC[21] = {2.734375e-01F,1.085883e-01F,5.145657e-02F,2.600124e-02F,1.349663e-02F,
	7.089505e-03F,3.743773e-03F,1.981668e-03F,1.050050e-03F,5.566641e-04F,
	2.951664e-04F,1.565240e-04F,8.300666e-05F,4.402028e-05F,2.334513e-05F,
	1.238059e-05F,6.565790e-06F,3.482034e-06F,1.846627e-06F,9.793216e-07F,5.193637e-07F};
Float NORMD[21] = {8.907963e-01F,1.996878e-01F,8.559235e-02F,4.272887e-02F,2.229211e-02F,
	1.176224e-02F,6.226405e-03F,3.299607e-03F,1.749331e-03F,9.275954e-04F,
	4.919020e-04F,2.608634e-04F,1.383421e-04F,7.336658e-05F,3.890842e-05F,
	2.063428e-05F,1.094298e-05F,5.803388e-06F,3.077711e-06F,1.632203e-06F,8.656061e-07F};
#endif



/*      
 * Inverse Undecimated Discret Wavelet Transform
 * Integer 2D gray image. (Img3dsf)
 * Images MUST have their dimensions all powers of 2 -> reshape.
 * The dimensions of the input and output must be the same.
 * Inputs :
 *	ims : The input image.
 *	imd : The output image.
 *	scale : The scale of the transform.
 */
Errc ISOIUDWT(Img3dsf & ims, Img2dsf & imd, int scale){
	
   int n = ims.Width();
   int m = ims.Height();
   int i, j, d;
	
   if(ims.Depth() != (scale+1)){
      std::cerr<<"ERROR: Output image do not have the proper depth\n";
      Exit(FAILURE);
   }
   if(scale>=nextpow2(MIN(m,n))){
      std::cerr<<"Incorrect scale : scale >= nexpow2(N)"<<std::endl;
      Exit(FAILURE);
   }
	
   // Reconstruction
   for(i = 0; i < m; i++)
      for(j = 0; j < n; j++)
	 for(d = 0,imd[i][j] = 0; d <= scale; d++)
	    imd[i][j] += ims[d][i][j]*(!d ? NORMC[scale-1]:NORMD[d-1]);
	
   return SUCCESS;
}
#ifdef MAIN
#define USAGE   "USAGE : %s  scale [im_in|-] [im_out|-]"
#define PARC    1
#define FINC    1
#define FOUTC   1
#define MASK    0
int main( int argc, char *argv[] ) {
   Errc result;              // The result code of the execution.
   Pobject* mask;            // The region map.
   Pobject* objin[FINC+1];   // The input objects;
   Pobject* objs[FINC+1];    // The source objects masked.
   Pobject* objout[FOUTC+1]; // The output object.
   Pobject* objd[FOUTC+1];   // The result object of the execution.
   char* parv[PARC+1];       // The input parameters.

   ReadArgs(argc,argv,PARC,FINC,FOUTC,&mask,objin,objs,objout,objd,parv,USAGE,MASK);
if(objs[0]->Type()== Po_Img3dsf){

   Img3dsf* const ims = (Img3dsf*)objs[0];	
   Check(*ims);
   objd[0] = new Img2dsf( ims->Height(),ims->Width());
   Img2dsf* const imd = (Img2dsf*)objd[0];
   result = ISOIUDWT(*ims, *imd, atoi(parv[0]));
   goto end;
}
else 
  {
     PrintErrorFormat(objin,FINC);
     result = FAILURE;
  }	

end:
  if (result)
	WriteArgs(argc,argv,PARC,FINC,FOUTC,&mask,objin,objs,objout,objd,MASK);
  Exit(result);
  return 0;
}
#endif
