/* -*- 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 Christophe Glinel - 20-07-2005
 */

/**
 * @file fat.cpp
 *
 * Generic fast analysis transform function in the specified dictionary.
 * This operator calls the good transform specified in the dictionary.
 * The output depends on the type of the transform.
 * It simplifies the applications.
 *
 * Cet opérateur permet de choisir la bonne transformée 
 * contenue dans le dictionnaire. La sortie 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 "frequency/pidwt.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

/**
 * Inputs :
 *	ims  : The input image.
 *	dict : The dictionary.
 *	col  : The output collection.
 *             It contains one field depending on the transform :
 *             - Collection : The result of a transform which returns a collection (e.g. FCT)
 *             - Image : The result of a transform which returns an image (e.g. DCT)
 */

Errc FAT(Img2duc & ims, Dictionary & dict, Collection & col ) {	
   Errc result;
   Qmf q(dict);
   Char * name = dict.GetNameofTransform();
   Collection * collec = 0;
   Imx3dsf * imd = 0;
   if(!strcmp(name,"UDWT")){
      imd = new Img3dsf(3*(int)dict.GetPar1()+1,ims.Height(),ims.Width());
      result = Udwt::UDWT(ims, q, *(dynamic_cast<Img3dsf*> (imd)), (int)dict.GetPar1());
   }
   else if(!strcmp(name,"ISOUDWT")){
      imd = new Img3dsf((int)dict.GetPar1()+1,ims.Height(),ims.Width());
      result = Isoudwt::ISOUDWT(ims, *(dynamic_cast<Img3dsf*> (imd)), (int)dict.GetPar1());
   }
   else if(!strcmp(name,"DWT")){
      imd = new Img2dsf(ims.Height(),ims.Width());
      result = Dwt::DWT(ims,q,*(dynamic_cast<Img2dsf*> (imd)),(int)dict.GetPar1());
   }
   else if(!strcmp(name,"DCT")){
      imd = new Img2dsf(ims.Height(),ims.Width());
      result = Dct::DCT(ims, *(dynamic_cast<Img2dsf*> (imd)));
   }
   else if(!strcmp(name,"DST")){
      imd = new Img2dsf(ims.Height(),ims.Width());
      result = Dst::DST(ims, *(dynamic_cast<Img2dsf*> (imd)));
   }
   else if(!strcmp(name,"LDCT")){
      imd = new Img2dsf(ims.Height(),ims.Width());
      result = Dct::LDCT(ims, *(dynamic_cast<Img2dsf*> (imd)), (int)dict.GetPar1());
   }
   else if(!strcmp(name,"LDST")){ 
      imd = new Img2dsf(ims.Height(),ims.Width());
      result = Dst::LDST(ims, *(dynamic_cast<Img2dsf*> (imd)), (int)dict.GetPar1());
   }
   else if(!strcmp(name,"LDCTIV")){
      imd = new Img2dsf(ims.Height(),ims.Width());
      result = Dctiv::LDCTIV(ims, *(dynamic_cast<Img2dsf*> (imd)), (int)dict.GetPar1());
   }
   else if(!strcmp(name,"DCTIV")){
      imd = new Img2dsf(ims.Height(),ims.Width());
      result = Dctiv::DCTIV(ims, *(dynamic_cast<Img2dsf*> (imd)));
   }
   else if(!strcmp(name,"FCT")){
      Img2dsf* ims2=(Img2dsf*)&ims;
      collec = new Collection;
      //std::cout << (Long)dict.GetPar2()[0]<<std::endl;
      result= Fct::FCT(*ims2, *collec, (Long)dict.GetPar1(), (Long)dict.GetPar2()[0]);
   }
   else{
      std::cerr<<"FAT: "<<name<<" specified in the dictionary is not implemented."<<std::endl;
      Exit(FAILURE);
   }
   if(!strcmp(name,"UDWT") || !strcmp(name,"ISOUDWT")) {
      col.SETPOBJECT("Image",Img3dsf,imd);
   }
   else if(!strcmp(name,"FCT")) {
      col.SETPOBJECT("Collection",Collection,collec);
   }
   else {
      col.SETPOBJECT("Image",Img2dsf,imd);
   }
   return result;
}

Errc FAT(Img2dsl & ims, Dictionary & dict, Collection & col ) {	
   Errc result;
   Qmf q(dict);
   Char * name = dict.GetNameofTransform();
   Collection * collec = 0;
   Imx3dsf * imd = 0;
   if(!strcmp(name,"UDWT")){
      imd = new Img3dsf(3*(int)dict.GetPar1()+1,ims.Height(),ims.Width());
      result = Udwt::UDWT(ims, q, *(dynamic_cast<Img3dsf*> (imd)), (int)dict.GetPar1());
   }
   else if(!strcmp(name,"ISOUDWT")){
      imd = new Img3dsf((int)dict.GetPar1()+1,ims.Height(),ims.Width());
      result = Isoudwt::ISOUDWT(ims, *(dynamic_cast<Img3dsf*> (imd)), (int)dict.GetPar1());
   }
   else if(!strcmp(name,"DWT")){
      imd = new Img2dsf(ims.Height(),ims.Width());
      result = Dwt::DWT(ims,q,*(dynamic_cast<Img2dsf*> (imd)),(int)dict.GetPar1());
   }
   else if(!strcmp(name,"DCT")){
      imd = new Img2dsf(ims.Height(),ims.Width());
      result = Dct::DCT(ims, *(dynamic_cast<Img2dsf*> (imd)));
   }
   else if(!strcmp(name,"DST")){
      imd = new Img2dsf(ims.Height(),ims.Width());
      result = Dst::DST(ims, *(dynamic_cast<Img2dsf*> (imd)));
   }
   else if(!strcmp(name,"LDCT")){
      imd = new Img2dsf(ims.Height(),ims.Width());
      result = Dct::LDCT(ims, *(dynamic_cast<Img2dsf*> (imd)), (int)dict.GetPar1());
   }
   else if(!strcmp(name,"LDST")){ 
      imd = new Img2dsf(ims.Height(),ims.Width());
      result = Dst::LDST(ims, *(dynamic_cast<Img2dsf*> (imd)), (int)dict.GetPar1());
   }
   else if(!strcmp(name,"LDCTIV")){
      imd = new Img2dsf(ims.Height(),ims.Width());
      result = Dctiv::LDCTIV(ims, *(dynamic_cast<Img2dsf*> (imd)), (int)dict.GetPar1());
   }
   else if(!strcmp(name,"DCTIV")){
      imd = new Img2dsf(ims.Height(),ims.Width());
      result = Dctiv::DCTIV(ims, *(dynamic_cast<Img2dsf*> (imd)));
   }
   else if(!strcmp(name,"FCT")){
      Img2dsf* ims2=(Img2dsf*)&ims;
      collec = new Collection;
      //std::cout << (Long)dict.GetPar2()[0]<<std::endl;
      result= Fct::FCT(*ims2, *collec, (Long)dict.GetPar1(), (Long)dict.GetPar2()[0]);
   }
   else{
      std::cerr<<"FAT: "<<name<<" specified in the dictionary is not implemented."<<std::endl;
      Exit(FAILURE);
   }
   if(!strcmp(name,"UDWT") || !strcmp(name,"ISOUDWT")) {
      col.SETPOBJECT("Image",Img3dsf,imd);
   }
   else if(!strcmp(name,"FCT")) {
      col.SETPOBJECT("Collection",Collection,collec);
   }
   else {
      col.SETPOBJECT("Image",Img2dsf,imd);
   }
   return result;
}

Errc FAT(Img2dsf & ims, Dictionary & dict, Collection & col ) {	
   Errc result;
   Qmf q(dict);
   Char * name = dict.GetNameofTransform();
   Collection * collec = 0;
   Imx3dsf * imd = 0;
   if(!strcmp(name,"UDWT")){
      imd = new Img3dsf(3*(int)dict.GetPar1()+1,ims.Height(),ims.Width());
      result = Udwt::UDWT(ims, q, *(dynamic_cast<Img3dsf*> (imd)), (int)dict.GetPar1());
   }
   else if(!strcmp(name,"ISOUDWT")){
      imd = new Img3dsf((int)dict.GetPar1()+1,ims.Height(),ims.Width());
      result = Isoudwt::ISOUDWT(ims, *(dynamic_cast<Img3dsf*> (imd)), (int)dict.GetPar1());
   }
   else if(!strcmp(name,"DWT")){
      imd = new Img2dsf(ims.Height(),ims.Width());
      result = Dwt::DWT(ims,q,*(dynamic_cast<Img2dsf*> (imd)),(int)dict.GetPar1());
   }
   else if(!strcmp(name,"DCT")){
      imd = new Img2dsf(ims.Height(),ims.Width());
      result = Dct::DCT(ims, *(dynamic_cast<Img2dsf*> (imd)));
   }
   else if(!strcmp(name,"DST")){
      imd = new Img2dsf(ims.Height(),ims.Width());
      result = Dst::DST(ims, *(dynamic_cast<Img2dsf*> (imd)));
   }
   else if(!strcmp(name,"LDCT")){
      imd = new Img2dsf(ims.Height(),ims.Width());
      result = Dct::LDCT(ims, *(dynamic_cast<Img2dsf*> (imd)), (int)dict.GetPar1());
   }
   else if(!strcmp(name,"LDST")){ 
      imd = new Img2dsf(ims.Height(),ims.Width());
      result = Dst::LDST(ims, *(dynamic_cast<Img2dsf*> (imd)), (int)dict.GetPar1());
   }
   else if(!strcmp(name,"LDCTIV")){
      imd = new Img2dsf(ims.Height(),ims.Width());
      result = Dctiv::LDCTIV(ims, *(dynamic_cast<Img2dsf*> (imd)), (int)dict.GetPar1());
   }
   else if(!strcmp(name,"DCTIV")){
      imd = new Img2dsf(ims.Height(),ims.Width());
      result = Dctiv::DCTIV(ims, *(dynamic_cast<Img2dsf*> (imd)));
   }
   else if(!strcmp(name,"FCT")){
      Img2dsf* ims2=(Img2dsf*)&ims;
      collec = new Collection;
      //std::cout << (Long)dict.GetPar2()[0]<<std::endl;
      result= Fct::FCT(*ims2, *collec, (Long)dict.GetPar1(), (Long)dict.GetPar2()[0]);
   }
   else{
      std::cerr<<"FAT: "<<name<<" specified in the dictionary is not implemented."<<std::endl;
      Exit(FAILURE);
   }
   if(!strcmp(name,"UDWT") || !strcmp(name,"ISOUDWT")) {
      col.SETPOBJECT("Image",Img3dsf,imd);
   }
   else if(!strcmp(name,"FCT")) {
      col.SETPOBJECT("Collection",Collection,collec);
   }
   else {
      col.SETPOBJECT("Image",Img2dsf,imd);
   }
   return result;
}


#ifdef MAIN
#define USAGE	"USAGE : %s  num [col_in|-] [im_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_Img2duc) {	
	 Collection * const colin = (Collection*)objs[0];
	 Img2duc * const ims = (Img2duc*)objs[1];
	 Check(*ims);
	 Collection * const coltemp = new Collection;
	 Dictionary dict(*colin);
	 result = FAT(*ims,dict[(int)parv[0]],*coltemp);
	 objd[0] = coltemp;
	 goto end;
      }
      else
      if (objs[0]->Type() == Po_Collection  && objs[1]->Type() == Po_Img2dsl) {	
	 Collection * const colin = (Collection*)objs[0];
	 Img2dsl * const ims = (Img2dsl*)objs[1];
	 Check(*ims);
	 Collection * const coltemp = new Collection;
	 Dictionary dict(*colin);
	 result = FAT(*ims,dict[(int)parv[0]],*coltemp);
	 objd[0] = coltemp;
	 goto end;
      }
      else
      if (objs[0]->Type() == Po_Collection  && objs[1]->Type() == Po_Img2dsf) {	
	 Collection * const colin = (Collection*)objs[0];
	 Img2dsf * const ims = (Img2dsf*)objs[1];
	 Check(*ims);
	 Collection * const coltemp = new Collection;
	 Dictionary dict(*colin);
	 result = FAT(*ims,dict[atoi(parv[0])],*coltemp);
	 objd[0] = coltemp;
	 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
