/* -*- c-basic-offset: 3 -*-
 * @(#)fst.cpp              PANDORE    2005-05-09
 *
 * 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:
 * Regis.Clouard@greyc.ensicaen.fr
 * http://www.greyc.ensicaen.fr/~regis
 */

/**
 * (R)Glinel Christophe - 20-07-2005
 * (R)Ouédraogo Nael - 07-11-2005
 * (R)Rémy Yannick - 07-11-2005
 */
 
/**
 * Generic fast synthesis transform function in the specified
 * dictionary. This operator calls the inverse transform  of 
 * the transform specified in the dictionary. The input 
 * depends on the type of the transform. It simplifies the 
 * applications.
 */
 
/**
 * Cet opérateur permet de choisir la transformée inverse
 * de celle contenue dans le dictionnaire. L'entrée dépend 
 * de la transformée. Cet opérateur simplifie l'écriture 
 * des applications.
 */
 
#include "wutils.cpp" 
#include "dctutils.cpp"

#ifdef MAIN
#undef MAIN

namespace Dwt{
#include "dwt.cpp"
#include "idwt.cpp"
}
namespace Udwt{
#include "udwt.cpp"
#include "iudwt.cpp"
}
namespace Isoudwt{
#include "isoudwt.cpp"
#include "isoiudwt.cpp"
}
namespace Dct{
#include "dct.cpp"
#include "idct.cpp"
#include "ldct.cpp"
#include "ildct.cpp"
}
namespace Dst{
#include "dst.cpp"
#include "idst.cpp"
#include "ldst.cpp"
#include "ildst.cpp"
}
namespace Dctiv{
#include "dctiv.cpp"
#include "ldctiv.cpp"
#include "ildctiv.cpp"
}

namespace Fct{
#include "fct.cpp"
#include "fict.cpp"
}
#define MAIN
#endif


/**
 * This function is for the applications.
 * Inputs :
 *	col  : The input collection containing the image (Imx3dsf) or the collection.
 *	dict : The dictionary.
 *	imd  : The output image.
 */
Errc FST(Collection * &col,Dictionary & dict,Img2dsf &imd){
   Errc result;
   Qmf q(dict);
   Char * name = dict.GetNameofTransform();

   //If the collection contains an image
   if(!col->Exists("Collection")){
      Imx3dsf *ims = (Imx3dsf*)col->GETPOBJECT("Image", Imx3dsf);
		   
      if(!strcmp(name,"UDWT"))
	 result = Udwt::IUDWT(*(dynamic_cast<Img3dsf *> (ims)), q, imd, (int)dict.GetPar1()); 
      else if(!strcmp(name,"ISOUDWT"))
	 result = Isoudwt::ISOIUDWT(*(dynamic_cast<Img3dsf *> (ims)), imd, (int)dict.GetPar1());
      else if(!strcmp(name,"DWT"))
	 result = Dwt::IDWT(*(dynamic_cast<Img2dsf *> (ims)),q,imd,(int)dict.GetPar1());
      else if(!strcmp(name,"DCT"))
	 result = Dct::IDCT(*(dynamic_cast<Img2dsf *> (ims)), imd);
      else if(!strcmp(name,"DST"))
	 result = Dst::IDST(*(dynamic_cast<Img2dsf *> (ims)), imd);
      else if(!strcmp(name,"LDCT"))
	 result = Dct::ILDCT(*(dynamic_cast<Img2dsf *> (ims)), imd, (int)dict.GetPar1());
      else if(!strcmp(name,"LDST"))
	 result = Dst::ILDST(*(dynamic_cast<Img2dsf *> (ims)), imd, (int)dict.GetPar1());
      else if(!strcmp(name,"LDCTIV"))
	 result = Dctiv::ILDCTIV(*(dynamic_cast<Img2dsf *> (ims)), imd, (int)dict.GetPar1(),dict.GetPar2()[0]);
      else if(!strcmp(name,"DCTIV"))
	 result = Dctiv::DCTIV(*(dynamic_cast<Img2dsf *> (ims)), imd);
      else{
	 std::cerr<<"FST: "<<name<<" specified in the dictionary is not implemented."<<std::endl;
	 Exit(FAILURE);
      }
   }
   else{ //the collection col contains a collection
      Collection *cols = (Collection*)col->GETPOBJECT("Collection", Collection);
      if(!strcmp(name,"FCT")){
	 result = Fct::FICT(*cols, imd);
      }
      else{
	 std::cerr<<"FST: "<<name<<" specified in the dictionary is not implemented."<<std::endl;
	 Exit(FAILURE);
      }
   }
   return result;
}

/**
 * This function is for the main. It allows to control that the format of the input image (Img2dsf 
 * or Img3dsf) is correct for the transform.
 * Inputs :
 *	col  : The input collection containing an image (img2dsf or Img3dsf) or a collection 
 *	dict : The dictionary.
 *	imd  : The output image.
 */
Errc FST(Collection &col,Dictionary & dict,Img2dsf &imd){
   Errc result;
   Qmf q(dict);
   Char * name = dict.GetNameofTransform();

   //If the collection contains an image
   if(!col.Exists("Collection")){
      //Test sur le type de l'image contenue dans la collection
      Pobject *po = col.GETPOBJECT("Image", Imx3dsf);
      
      //Si Img2dsf
      if(po->Type()==Po_Img2dsf){ 
	 Img2dsf *ims = (Img2dsf*)col.GETPOBJECT("Image", Img2dsf);
	
	 if(!strcmp(name,"DWT"))
	    result = Dwt::IDWT(*ims,q,imd,(int)dict.GetPar1());
	 else if(!strcmp(name,"DCT"))
	    result = Dct::IDCT(*ims, imd);
	 else if(!strcmp(name,"DST"))
	    result = Dst::IDST(*ims, imd);
	 else if(!strcmp(name,"LDCT"))
	    result = Dct::ILDCT(*ims, imd, (int)dict.GetPar1());
	 else if(!strcmp(name,"LDST"))
	    result = Dst::ILDST(*ims, imd, (int)dict.GetPar1());
	 else if(!strcmp(name,"LDCTIV"))
	    result = Dctiv::ILDCTIV(*ims, imd, (int)dict.GetPar1(),dict.GetPar2()[0]);
	 else if(!strcmp(name,"DCTIV"))
	    result = Dctiv::DCTIV(*ims, imd);
	 else{
	    std::cerr<<"FST: "<<name<<" specified in the dictionary is not implemented or the format of the input image is not correct for this transform."<<std::endl;
	    result = FAILURE;
	 }
      }
      //Si Img3dsf
      else if(po->Type()==Po_Img3dsf){ 
	 Img3dsf *ims = (Img3dsf*)col.GETPOBJECT("Image", Img3dsf);
	   
	 if(!strcmp(name,"UDWT"))
	    result = Udwt::IUDWT(*ims, q, imd, (int)dict.GetPar1()); 
	 else if(!strcmp(name,"ISOUDWT"))
	    result = Isoudwt::ISOIUDWT(*ims, imd, (int)dict.GetPar1());
	 else{
	    std::cerr<<"FST: "<<name<<" specified in the dictionary is not implemented or the format of the input image is not correct for this transform."<<std::endl;
	    result = FAILURE;
	 }  
      }
      else{
	 std::cerr<<"FST: "<<name<<" specified in the dictionary is not implemented or the format of the input image is not correct for this transform."<<std::endl;
	 result = FAILURE;
      }
   }
   //If the collection contains a collection
   else{
      Collection *cols = (Collection*)col.GETPOBJECT("Collection", Collection);

      if(!strcmp(name,"FCT")){
	 result = Fct::FICT(*cols, imd);
      }
      else{
	 std::cerr<<"FST: "<<name<<" specified in the dictionary is not implemented."<<std::endl;
	 Exit(FAILURE);
      }
   }
   return result;
}


#ifdef MAIN
#define USAGE	"USAGE : %s  num [dico_in|-] [col_in|-] [im_out|-]"
#define PARC	1
#define FINC	2
#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_Collection  && objs[1]->Type() == Po_Collection){
	 Collection * const colin = (Collection*)objs[0];//dictionnaire
	 Collection * col = (Collection*)objs[1]; //collection contenant l'image ou la collection 
	 Dictionary dict(*colin);

	 if(!col->Exists("Collection")){//la collection contient une image
	    Imx3dsf *const ims = (Imx3dsf*)col->GETPOBJECT("Image", Imx3dsf);
	    Check(*ims);	 
	    objd[0] = new Img2dsf(ims->Height(),ims->Width());
	 }
	 else // allocation de objd[0]
	    if(!strcmp(dict[atoi(parv[0])].GetNameofTransform(), "FCT")){
	       Collection * colFCT=(Collection *)col->GETPOBJECT("Collection", Collection);
	       objd[0] = new Img2dsf(colFCT->GETVALUE("height",Long),colFCT->GETVALUE("width",Long));
	    }

	 Img2dsf * const imd = (Img2dsf*)objd[0];
	 result = FST(*col,dict[atoi(parv[0])],*imd);
	 goto end;
      }

      else
	 {
	    PrintErrorFormat(objin,FINC);
	    result = FAILURE;
	 }	

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