/* -*- 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 Hoock Jean-Baptiste - 2005-07-28 
 */

/**
 * @file quartdetour.cpp
 */

#include <pandore.h>
#include <math.h>

#undef MAIN
#include <visualisation/plotfunction.cc>

#include "utils.cc"

//Fonction utilisee par le quicksort pour un tri decroissant
int compare(const void *x, const void *y){
   return (*(Float*)x-*(Float*)y)<0?1:-1;
}

/**
 * Fonction qui calcule le seuil correspondant a un pourcentage P de coefficients les 
 * plus importants a garder.
 * Apres avoir trie les coefficients par ordre decroissant, le seuil cherche est la valeur du
 * coefficient dont la position represente la proportion P par rapport au nombre total de
 * coefficients.
 * 
 * @param tabCoeffs le tableau contenant tous les coefficients (numerote a partir de 0)
 *        nbCoeffs le nombre de coefficients (taille du tableau)
 *        P (en %)le pourcentage de coefficients que l'on veut conserver (les plus importants)
 *
 * tabCoeffs n'est pas modifie.
 */
Float calculSeuil(Float const *tabCoeffs, Long nbCoeffs, Float P){
   Float *tabCoeffsTrie=new Float[nbCoeffs];
   for(Long i=0; i<nbCoeffs; i++) {
     tabCoeffsTrie[i]=fabs(tabCoeffs[i]);
   }
   qsort((void*)tabCoeffsTrie,nbCoeffs,sizeof(Float),(int (*)(const void*,const void*))compare);

   int nbCoeffsGardes=(int)floor((P/100)*nbCoeffs);
   //   std::cout<<"nbCoeff= " << nbCoeffs<<" nbCoeffsGardes= "<<nbCoeffsGardes<<std::endl;
   Float seuil=tabCoeffsTrie[nbCoeffsGardes-1];   
   
   delete[] tabCoeffsTrie;
   return seuil;
}

/**
 * Fonction qui calcule le pourcentage de coefficients conserves pour un pas de quantification
 * Apres avoir trie les coefficients par ordre decroissant, on cherche le premier coefficient
 * inferieur ou egal au pas ; son indice permet de calcule le pourcentage
 * 
 * @param tabCoeffs le tableau contenant tous les coefficients (numerote a partir de 0)
 *        nbCoeffs le nombre de coefficients (taille du tableau)
 *        P le pas de quantification
 *
 * tabCoeffs n'est pas modifie.
 */
Float calculPrct(Float const *tabCoeffs, Long nbCoeffs, Float P){
   Float *tabCoeffsTrie=new Float[nbCoeffs];
   for(Long i=0; i<nbCoeffs; i++) {
     tabCoeffsTrie[i]=fabs(tabCoeffs[i]);
   }
   qsort((void*)tabCoeffsTrie,nbCoeffs,sizeof(Float),(int (*)(const void*,const void*))compare);
   for(Long i=0; i<nbCoeffs; i++) {
     if (tabCoeffsTrie[i]<P) return (Float)((Float)i/(Float)nbCoeffs) * 100.0;
   }
   return 100;
   
   delete[] tabCoeffsTrie;
}

/**
 * Fonction qui realise la quantification uniforme des coefficients 
 * contenus dans un tableau tabCoeffs
 * 
 * Quantification : Q(x)=0 si |x|<pasQuantif
 *                  Q(x)=sign(x)*(E(|x|/pasQuantif)+0.5)*pasQuantif  
 *
 * @param tabCoeffs le tableau contenant tous les coefficients (numerote a partir de 0)
 *        nbCoeffs le nombre de coefficients (taille du tableau)
 *        pasQuantif le pas de quantification utilise pour la quantification uniforme
 *
 * tabCoeffs sera modifie et contiendra en sortie les coefficients quantifies obtenus 
 * (dans le meme ordre que celui initial). 
 */
void quantificationUniforme(Float *tabCoeffs, int nbCoeffs, Float  pasQuantif){
  if (pasQuantif == 0) return;
  for(int i=0; i<nbCoeffs; i++)
    if(fabs(tabCoeffs[i])< pasQuantif)
      tabCoeffs[i]=0;
    else
      tabCoeffs[i]=sign(tabCoeffs[i])*(floor(fabs(tabCoeffs[i])/pasQuantif)+0.5)* pasQuantif; 
}

/*
#define USAGE   "USAGE : %s itermax gamma expdecrease stop [dict_in|-] [im_in|-] [im_out|-]"
#define PARC    4
#define FINC    2
#define FOUTC   1
#define MASK    0

int main(int argc, char* argv[]) {
   Errc result;              // The result code of the execution.
 
   Float tab[50];
   std::cout<<"Coefficients avant quantification :"<<std::endl;
   for(int i=0; i<50; i++){
      std::cout<<i<<" ";
      tab[i]=50.0/sqrt(i+1);//i;
   }
   std::cout<<std::endl;

   //Tests plotfunction : avant quantif
   Img1dsf *imf0=new Img1dsf(50,tab);
   Imc2duc *imp0=new Imc2duc(256,256);
   PlotFunction(*imf0,*imp0,0,60,-2);
   imp0->SaveFile("im1.pan");
   imf0->Delete();
   imp0->Delete();


   Float seuil=calculSeuil(tab, 50, 30);
   //   quantificationUniforme(tab, 50, seuil);
   int pasQuantif=3;
   quantificationUniforme(tab, 50, pasQuantif);
  
   std::cout<<"Coefficients apres quantification :"<<std::endl;
   for(int i=0; i<50; i++){
      std::cout<<tab[i]<<" ";
   }
   std::cout<<std::endl;


   //Tests plotfunction : apres quantif
   Img1dsf *imf=new Img1dsf(50,tab);
   Imc2duc *imp=new Imc2duc(256,256);
   PlotFunction(*imf,*imp,0,60,-2);
   imp->SaveFile("im2.pan");
   imf->Delete();
   imp->Delete();

   return 0;
}
*/
