/* -*- 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 - 2006-04-5
 */

/**
 * @file fcatom.ccpp
 *
 * Description:
 *
 * Separate orthogonally oriented linear structures in two by two quadrants (1-4 and 2-3)
 *      -------------
 *      |  1  |  2  |
 *      -------------
 *      |  3  |  4  |
 *      -------------
 * Can also filter out the horizontal and vertical linear structures.
 * 
 */

#undef MAIN
#include "fispex_protect.h"
#include "wutils.cpp"
#include "dctutils.cpp"
#include "dictionary_ifp.h"

namespace Arithm{
#include "arithmetic/padd.cpp"
#include "arithmetic/psub.cpp"
#include "utility/pinsertsubimage.cpp"
#include "utility/pextractsubimage.cpp"
}

namespace Fct{
#include "fftshift2.cpp"
#include "fct.cpp"
#include "fict.cpp"
}

#define MAIN

#define NB_ANGLES_COARSE 16 // For FCT

/**
 * Desallocate a FCT collection
 * @param collect the collection
 * @return SUCCESS or FAILURE
 */
Errc desalocFCTCollec(Collection & collec) {
   Collection ** img = collec.GETPARRAY("curvelets",Collection);
   Img2dsl ** curv_size = collec.GETPARRAY("curv_size",Img2dsl);
   Long nbs = collec.GETVALUE("nbscales",Long);
   Img1dsl * nbangles = (Img1dsl *)collec.GETPOBJECT("nbangles",Img1dsl);
   Img2dsf** curvdata_tmp=NULL;
   
   for(int it = 0; it < nbs; it++) {
      curvdata_tmp=img[it]->GETPARRAY("curvangles",Img2dsf);
      for(int j=0; j < (*nbangles)[it]; j++) curvdata_tmp[j]->Delete();
      delete[] curvdata_tmp;
      curv_size[it]->Delete();
   }	      			   
   delete[] img;
   delete[] curv_size;
   nbangles->Delete();
   collec.Delete();   
   return SUCCESS;
}

/** 
 * Get FCT atom in spatial domain. 
 * @param scale	Coarsest decomposition scale of FCT.
 * @param wedge	Angular wedge index.
 * @param imd	The output image.
 * @return SUCCESS or FAILURE
 */
Errc FctAtom( Long scale, Long wedge, Img2dsf & imd) {
   Collection *res = new Collection();
   Collection ** les_curvelets;
   Img2dsl ** curv_size;
   Img2dsf ** curvdata_tmp=NULL;
   Img1dsl* nbangles;
   Long n = imd.Width();
   Long J=nextpow2(n);
	
	
   // Check scale consistency.
   if(scale > J){
      std::cerr<<"Scale must be less than "<<J<<" "<<std::endl;
      exit(FAILURE);
   }
	
   // Compute the FCT.
   imd = 0;
   Fct::FCT(imd, *res, scale, NB_ANGLES_COARSE);
   les_curvelets = res->GETPARRAY("curvelets",Collection);
   curv_size = res->GETPARRAY("curv_size", Img2dsl);
   nbangles = (Img1dsl*)(res->GETPOBJECT("nbangles",Img1dsl));
	
   curvdata_tmp=les_curvelets[0]->GETPARRAY("curvangles",Img2dsf);
	
   //std::cout<<"Number of wedges at this scale:"<<(*nbangles)[0]<<" "<<std::endl;
   // Check wedge index consistency.
   if(wedge > (*nbangles)[0]){
      std::cerr<<"Wedge index must be less than "<<(*nbangles)[0]<<" "<<std::endl;
      exit(FAILURE);
   }
	
   (*(curvdata_tmp[wedge-1]))[(*curv_size[0])[wedge-1][0]/2][(*curv_size[0])[wedge-1][1]/2] = 1;
	
   Fct::FICT(*res, imd);
   desalocFCTCollec(*res);
   
   return SUCCESS;
}

#ifdef MAIN
#define USAGE   "USAGE : %s size scale wedge [im_out|-]"
#define PARC    3
#define FINC    0
#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 (atoi(parv[0])>0) {
      objd[0] = new Img2dsf(atol(parv[0]),atol(parv[0]));
      Img2dsf* const imd = (Img2dsf*)objd[0];	
      result = FctAtom(atol(parv[1]), atol(parv[2]), *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
