
#include "global.h"


/******************************************************************************/
/* CALCUL DES NIVEAUX DE GRIS DE L'IMAGE A AFFICHER                           */
/*                                                                            */
/* Fonction qui affecte a chaque point de l'image un niveau de gris afin qu'en*/
/* zoomant la zone de l'image agrandie conserve sa couleur. Lors de la gene-  */
/* ration de l'image, on fixe le maximum des niveaux de l'image a 255 et son  */
/* minimum a 0. Puis on s'arrange pour que les extremums des niveaux de gris  */
/* de la zone a zoomer dans une image soient conserves apres un zoom.         */
/*                                                                            */
/* ENTREES :                                                                  */
/*   -> Qr           : matrice de texture                                     */
/*   -> minNG, maxNG : extremum des niveaux de gris d'une image (action 2)    */
/*   -> NG           : matrice des niveaux de gris (action 3)                 */
/*   -> cadre        : cadre du zoom (action 3)                               */
/* SORTIES :                                                                  */
/*   -> NG           : matrice des niveaux de gris (actions 1 et 2)           */
/*   -> minNG, maxNG : extremum des niveaux de gris d'une image (action 3)    */
/*                                                                            */
/* action 1 : repartion des niveaux de gris entre 0 et 255                    */
/* action 2 : repartion des niveaux de gris pour des extrema donnes           */
/* action 3 : recherche des extrema des niveaux de gris d'une zone de l'image */
/******************************************************************************/

void mexFunction(int nb_sorties,      mxArray *sorties[],
                 int nb_entrees,const mxArray *entrees[]) {

  /* variables locales */

  unsigned char action,minNG,maxNG,*NG;
  long m,n,mNG,L,l,x_min,y_min,delta_x,delta_y,i,j;
  double *Qr,*min,*max,minQr,maxQr,conversion;


  /* lecture des entrees */

  if      (nb_entrees==1 && nb_sorties==1) action=1;
  else if (nb_entrees==3 && nb_sorties==1) action=2;
  else if (nb_entrees==3 && nb_sorties==2) action=3;
  else    mexErrMsgTxt("Mauvais nombre d'arguments");
  Qr=mxGetPr(entrees[0]);
  m=mxGetM(entrees[0]);
  n=mxGetN(entrees[0]);
  if (action==2) {        /* repartion des niveaux de gris pour des extrema  */
                          /* donnes                                          */

    minNG=(unsigned char)*mxGetPr(entrees[1]);
    maxNG=(unsigned char)*mxGetPr(entrees[2]);

  } else if (action==3) { /* recherche des extrema des niveaux de gris d'une */
                          /* zone de l'image                                 */

    NG=(unsigned char *)mxGetData(entrees[1]);
    mNG=mxGetM(entrees[1]);
    L=MAX(mxGetM(entrees[2]),mxGetN(entrees[2]));
    l=MIN(mxGetM(entrees[2]),mxGetN(entrees[2]));
    if (l==1 && L==4) {
      x_min  =(long)*(mxGetPr(entrees[2])  );
      y_min  =(long)*(mxGetPr(entrees[2])+1);
      delta_x=(long)*(mxGetPr(entrees[2])+2);
      delta_y=(long)*(mxGetPr(entrees[2])+3);
    } else mexErrMsgTxt("Le cadre du zoom doit avoir quatre parametres !");

  }


  /* allocation memoire pour les sorties */

  if (action==1 || action==2) {
    sorties[0]=mxCreateNumericMatrix(m,n,mxUINT8_CLASS,mxREAL);
    NG=(unsigned char *)mxGetData(sorties[0]);
  } else {                /* repartion des niveaux de gris entre 0 et 255    */
    sorties[0]=mxCreateDoubleMatrix(1,1,mxREAL);
    sorties[1]=mxCreateDoubleMatrix(1,1,mxREAL);
    min=mxGetPr(sorties[0]);
    max=mxGetPr(sorties[1]);
  }


  /* action a effectuer */

  if (action==1) {        /* repartion des niveaux de gris entre 0 et 255    */

    minQr=maxQr=Qr[0];
    for (i=1;i<m*n;i++) {
      if      (Qr[i]>maxQr) maxQr=Qr[i];
      else if (Qr[i]<minQr) minQr=Qr[i];
    }
    conversion=255/(maxQr-minQr);
    minNG=0;

  } else if (action==2) { /* repartion des niveaux de gris pour des extrema  */
                          /* donnes                                          */

    minQr=maxQr=Qr[0];
    for (i=1;i<m*n;i++) {
      if (Qr[i]<minQr) minQr=Qr[i];
      if (Qr[i]>maxQr) maxQr=Qr[i];
    }
    conversion=(maxNG-minNG)/(maxQr-minQr);

  } else {                /* recherche des extrema des niveaux de gris d'une */
                          /* zone de l'image                                 */

    *max=*min=NG[y_min+x_min*mNG];
    for (i=y_min;i<y_min+delta_y;i++) {
      for (j=x_min;j<x_min+delta_x;j++) {
        if (NG[i+j*mNG]<*min) *min=NG[i+j*mNG];
        if (NG[i+j*mNG]>*max) *max=NG[i+j*mNG];
      }
    }

  }


  /* mise à l'echelle */

  if (action==1 || action==2)
    for (i=0;i<m*n;i++) NG[i]=(unsigned char)(minNG+(Qr[i]-minQr)*conversion);
}

