/* -*- 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 Régis Clouard - 2002-11-22
 * @author Régis Clouard - 2005-10-24 (fix bug on fft())
 */

#include <pandore.h>
using namespace pandore;

/**
 * @file pfftshift.cpp
 * Fait une permutation des 4 sous-images. (1<-> 4, 2<-> 3)
 */

Errc PFFTShift( const Img2dsf &imsr, const Img2dsf &imsi, Img2dsf &imdr, Img2dsf &imdi ) {
   int midx = imsr.Width() >> 1;
   int midy = imsr.Height() >> 1;
   int finx, finy;
   int y;

   // Cas impair -> +1
   finx= (imsr.Width() % 2 == 1)?  midx+1 : midx;
   finy= (imsr.Height() % 2 == 1)?  midy+1 : midy;

   // Cadre 1 -> Cadre 4.
   for (y=0; y < finy; y++)
      for (int x=0; x < finx; x++) {
	 imdr[y][x] = imsr[y+midy][x+midx];
	 imdi[y][x] = imsi[y+midy][x+midx];
      }
   
   // Cadre 2 -> Cadre 4.
   for (y=0; y < finy; y++)
      for (int x=finx; x < imsr.Width(); x++) {
	 imdr[y][x] = imsr[y+midy][x-finx];
	 imdi[y][x] = imsi[y+midy][x-finx];
      }

   
   // Cadre 3 -> cadre 2.
   for (y=finy ; y< imsr.Height(); y++)
      for (int x=0; x < finx; x++) {
	 imdr[y][x] = imsr[y-finy][x+midx];
	 imdi[y][x] = imsi[y-finy][x+midx];
      }

   // Cadre 4 -> Cadre 1.
   for (y=finy; y < imsr.Height(); y++)
      for (int x=finx; x < imsr.Width(); x++) {
	 imdr[y][x] = imsr[y-finy][x-finx];
	 imdi[y][x] = imsi[y-finy][x-finx];
      }
   
   return SUCCESS;
}

/*
 * Modify only the following constants, and the function call.
 */
#ifdef MAIN
#define	USAGE	"usage: %s [-m mask] [imr_in|-] [imi_in|-] [imr_out|-] [imi_out|-]"
#define	PARC	0
#define	FINC	2
#define	FOUTC	2
#define	MASK	1


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_Img2dsf) {
      Img2dsf* const ims_reel=(Img2dsf*)objs[0];
      Img2dsf* const ims_imag=(Img2dsf*)objs[1];
      objd[0]=new Img2dsf(ims_reel->Size());
      Img2dsf* const imd_reel=(Img2dsf*)objd[0];
      objd[1]=new Img2dsf(ims_imag->Size());
      Img2dsf* const imd_imag=(Img2dsf*)objd[1];
      
      result=PFFTShift(*ims_reel,*ims_imag,*imd_reel,*imd_imag);
      
      goto end;
   }
   {
      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
