/******************************************************************************

   This file is a part of the

             COMPLEX PSEUDO-RAW SAR IMAGE PROCESSING TOOLBOX

   Copyright (C) 2017 Rémy Abergel (Remy.Abergel AT parisdescartes.fr), Loïc
   Denis (Loic.Denis AT univ-st-etienne.fr), Saïd Ladjal (Said.Ladjal AT
   telecom-paristech.fr) and Florence Tupin (Florence.Tupin AT
   telecom-paristech.fr).

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.

******************************************************************************/

/*

   Compilation (using gcc):
   ========================

   gcc -O3 tiffadd.c tiffread.c tiffwrite.c -lfftw3 -lm -ltiff -o tiffadd


   Description:
   ============

   pointwise addition of two TIFF images.

 */

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include "fftw3.h"

#define ASSERT_ALLOC(cmd) if(NULL == (cmd)) { printf("Not enough memory\n"); exit(EXIT_FAILURE); }

extern int load_2pages_tiff_into_fftw_complex(fftw_complex**,int*,int*,char*,char); // see source file 'tiffread.c'
extern int save_2pages_striped_tiff_float_from_fftw_complex(char*,fftw_complex*,int,int,char); // see source file 'tiffwrite.c'


static void display_usage()
{
  printf("\nPointwise addition of two TIFF images: out = in1 + in2.\n\n");
  printf("Usage: tiffadd in1 int2 out\n\n");
  printf("   in1  : input complex image, (stack of 2 TIFF images)\n");
  printf("   in2  : input complex image, (stack of 2 TIFF images)\n");
  printf("   out  : output complex image (stack of 2 TIFF images)\n\n");
  printf("Description of the 2-pages TIFF I/O format :\n\n");
  printf("   The input and outputs are complex-valued images, stored as a stack of two\n");
  printf("   images into a single TIFF file, such as the first (respectively the second)\n");
  printf("   image of the stack represents the real (respectively the imaginary) part of\n");
  printf("   the image.\n\n");

}


int main(int argc, char **argv)
{
  char *filenamein1 = NULL,*filenamein2 = NULL,*filenameout = NULL,vflag;
  fftw_complex *u1,*u2,*v;
  int adr,i,nx1,ny1,nx2,ny2;
  vflag = 0;

  /******************************************/
  /*            arguments parser            */
  /******************************************/

  /* main parser */
  for(i=1;i<argc;i++) {
    if (NULL == filenamein1) filenamein1 = argv[i];
    else if (NULL == filenamein2) filenamein2 = argv[i];
    else if (NULL == filenameout) filenameout = argv[i];
    else { display_usage(); printf("Error: could not retrieve properly input arguments.\n"); return EXIT_FAILURE; }
  }

  /* check consistency */
  if ((NULL == filenamein1) || (NULL == filenamein2) || (NULL==filenameout)) {
    display_usage();
    if (NULL == filenamein1) printf("Error: input 'in1' is missing\n\n");
    else if (NULL == filenamein2) printf("Error: input 'in2' is missing\n\n");
    else printf("Error: output 'out' is missing\n\n");
    return EXIT_FAILURE;
  }

  /*******************/
  /* Open TIFF Image */
  /*******************/

  if(EXIT_FAILURE == load_2pages_tiff_into_fftw_complex(&u1,&nx1,&ny1,filenamein1,vflag)) {
    printf("Error: could not open input '%s'\n",filenamein1);
   return EXIT_FAILURE;
  }
  if(EXIT_FAILURE == load_2pages_tiff_into_fftw_complex(&u2,&nx2,&ny2,filenamein2,vflag)) {
    printf("Error: could not open input '%s'\n",filenamein2);
    fftw_free(u1);
   return EXIT_FAILURE;
  }
  if((nx1 != nx2)||(ny1 != ny2)){
    printf("Error: the two input images do not have the same dimensions\n");
    fftw_free(u1); fftw_free(u2);
   return EXIT_FAILURE;
  }

  /*********************/
  /* Memory allocation */
  /*********************/
  ASSERT_ALLOC(v = (fftw_complex*) fftw_malloc (nx1*ny1 * sizeof(fftw_complex)));

  /**********/
  /* KERNEL */
  /**********/
  for(adr=0;adr<nx1*ny1;adr++) {
    v[adr][0] = u1[adr][0] + u2[adr][0];
    v[adr][1] = u1[adr][1] + u2[adr][1];
  }

  /*********************************************/
  /*               END OF KERNEL               */
  /*********************************************/

  /********************************/
  /* Write output as a TIFF Image */
  /********************************/
  if(EXIT_FAILURE == save_2pages_striped_tiff_float_from_fftw_complex(filenameout,v,nx1,ny1,vflag)) {
    printf("Error: could not save output '%s'\n",filenameout);
    fftw_free(u1); fftw_free(u2);
    return EXIT_FAILURE;
  }

  /* free memory */
  fftw_free(u1);
  fftw_free(u2);
  fftw_free(v);

  return EXIT_SUCCESS;
}
