/*===========================================================================
  Copyright (C) 1993-2009 European Southern Observatory (ESO)
 
  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 2 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, write to the Free 
  Software Foundation, Inc., 675 Massachusetts Ave, Cambridge, 
  MA 02139, USA.
 
  Correspondence concerning ESO-MIDAS should be addressed as follows:
	Internet e-mail: midas@eso.org
	Postal address: European Southern Observatory
			Data Management Division 
			Karl-Schwarzschild-Strasse 2
			D 85748 Garching bei Muenchen 
			GERMANY
===========================================================================*/

/******************************************************************************
**
**    UNIT
**
**    Version: 19.1
**
**    Author: Jean-Luc Starck
**
**    Date:  03/02/25
**    
**    File:  reconstr.c
**
.VERSION
 090804		last modif

*******************************************************************************
**
**    DESCRIPTION  reconstruction routines
**    -----------
**
******************************************************************************
**
** wavelet_reconstruct_file (File_Name_Imag, 
**                           File_Name_Transform, Build_Direct_Ok)
** char *File_Name_Imag, *File_Name_Transform;
** Build_Direct_Ok;
**
** Reconstructs an image from its the wavelet transform of file name 
** File_Name_Transform and write the result in the file File_Name_Imag
**
** File_Name_Imag = File name of the output image
** File_Name_Transform = File name of the input wavelet transform
** Build_Direct_Ok = input paramater (TRUE=1 or FALSE=0)
**    if the wavelet transform algorithm used the FFT and is pyramidal
**        (Type_Wave_Transform =  TO_PYR_FFT_DIFF_RESOL
**                             or TO_PYR_FFT_DIFF_SQUARE_RESOL)
**        then if Build_Direct_Ok = 1 (TRUE) then
**                       the reconstruction is done by addition
**                       of the wavelet coefficient in the Fourier space
**             else (Build_Direct_Ok = 0 (FALSE))  
**                       the reconstruction is done from a least mean square
**                       estimation
**
******************************************************************************
**
** wavelet_reconstruct_data (Wavelet, Imag, Build_Direct_Ok)
** float *Imag;
** wave_transf_des *Wavelet;
** int Build_Direct_Ok;
**
** Reconstructs an image from its the wavelet transform 
**
** Imag = OUTPUT:image
** Wavelet = INPUT:wavelet
** Build_Direct_Ok = input paramater (TRUE=1 or FALSE=0)
**    if Wavelet->Type_Wave_Transform =  TO_PYR_FFT_DIFF_RESOL
**                                    or TO_PYR_FFT_DIFF_SQUARE_RESOL
**        then if Build_Direct_Ok = 1 (TRUE) then
**                       the reconstruction is done by addition
**                       of the wavelet coefficient in the Fourier space
**             else (Build_Direct_Ok = 0 (FALSE))  
**                       the reconstruction is done from a least mean square
**                       estimation

******************************************************************************
**
** int W_Pyr_Rec_Iter_Number = 1; 
**
** Global variable used to define the number of iterations in
** Van Ciitert's iterative reconstruction. This parameter is used if
**  Wavelet->Type_Wave_Transform = TO_PYR_BSPLINE
**                              or TO_PYR_LINEAR
** 
** This parameter can be modified by an external program by:
**
** extern int W_Pyr_Rec_Iter_Number;
** W_Pyr_Rec_Iter_Number = Value;
**
******************************************************************************/


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

#include "Def_Math.h"
#include "Def_Mem.h"
#include "Def_Wavelet.h"

extern void wave_io_read(), wave_io_free();
extern void io_write_pict_f_to_file();
extern void pave_2d_build(), pave_2d_cf_build();
extern void pyr_2d_build_pict_from_pyr(), pyr_2d_build_iter_pict_from_pyr();
extern void pyr_2d_cf_build_pict_from_pyr(), mallat_2d_reconstruct();

void wavelet_reconstruct_data();


/* Global variable used to define the number of iterations in
   Van Ciitert's iterative reconstruction */
int W_Pyr_Rec_Iter_Number = 1; 

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

void wavelet_reconstruct_file (File_Name_Imag, File_Name_Transform, Build_Direct_Ok)
char *File_Name_Imag, *File_Name_Transform;
int Build_Direct_Ok;
{
    float *Imag;
    wave_transf_des Wavelet;
    int Nl, Nc;

    /* read the wavelet file */
    wave_io_read (File_Name_Transform, &Wavelet);
    
    Nl =  Wavelet.Nbr_Ligne;
    Nc = Wavelet.Nbr_Col;
    Imag = f_vector_alloc (Nl*Nc);
    wavelet_reconstruct_data (&Wavelet, Imag, Build_Direct_Ok);

    /* write the result */
    io_write_pict_f_to_file (File_Name_Imag, Imag, Nl, Nc);

    wave_io_free (&Wavelet);
    free ((void *) Imag);
}

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

void wavelet_reconstruct_data (Wavelet, Imag, Build_Direct_Ok)
float *Imag;
wave_transf_des *Wavelet;
int Build_Direct_Ok;
{
    float *Pyr, *Pave;
    int Nl, Nc, Nbr_Plan;
    float Fc;
    
    Nl = Wavelet->Nbr_Ligne;
    Nc = Wavelet->Nbr_Col;
    Nbr_Plan = Wavelet->Nbr_Plan;
    switch (Wavelet->Type_Wave_Transform)
    {
        case TO_PAVE_LINEAR:
        case TO_PAVE_BSPLINE:
                   Pave = Wavelet->Pave.Data;
                   pave_2d_build (Pave, Imag, Nl, Nc, Nbr_Plan);
                   break;
        case TO_PAVE_BSPLINE_FFT:
                   Fc = Wavelet->Pave.Freq_Coup;
                   Pave = Wavelet->Pave.Data;
                   pave_2d_cf_build (Pave, Imag, Nl, Nc, Nbr_Plan);
                   break;
        case TO_PYR_LINEAR:
        case TO_PYR_BSPLINE:
                   Pyr = Wavelet->Pyramid.Data;
                   if (W_Pyr_Rec_Iter_Number == 1)
                        pyr_2d_build_pict_from_pyr (Pyr,
                                   Imag, 
                                   Wavelet->Pyramid.Tab_Nl, 
                                   Wavelet->Pyramid.Tab_Col, 
                                   Wavelet->Pyramid.Tab_Pos, 
                                   Nbr_Plan - 1);
                   else
                        pyr_2d_build_iter_pict_from_pyr (Pyr, 
                                                  Imag, 
                                                  Wavelet->Pyramid.Tab_Nl, 
                                                  Wavelet->Pyramid.Tab_Col, 
                                                  Wavelet->Pyramid.Tab_Pos, 
                                                  Nbr_Plan - 1,
                                                  W_Pyr_Rec_Iter_Number,
                                                  Wavelet->Type_Wave_Transform);
                   break;
        case TO_PYR_FFT_DIFF_RESOL:
                   Fc = Wavelet->Pyramid.Freq_Coup;
                   Pyr = Wavelet->Pyramid.Data;
                   pyr_2d_cf_build_pict_from_pyr (Pyr, 
                                                  Imag, 
                                                  Wavelet->Pyramid.Tab_Nl, 
                                                  Wavelet->Pyramid.Tab_Col, 
                                                  Wavelet->Pyramid.Tab_Pos, 
                                                  Nbr_Plan, 
                                                  Wavelet->Type_Wave_Transform,
                                                  Fc,
                                                  Build_Direct_Ok);
                   break;
        case TO_PYR_FFT_DIFF_SQUARE_RESOL:
                   Fc = Wavelet->Pyramid.Freq_Coup;
                   Pyr = Wavelet->Pyramid.Data;
                   pyr_2d_cf_build_pict_from_pyr (Pyr, 
                                                  Imag, 
                                                  Wavelet->Pyramid.Tab_Nl, 
                                                  Wavelet->Pyramid.Tab_Col, 
                                                  Wavelet->Pyramid.Tab_Pos, 
                                                  Nbr_Plan, 
                                                  Wavelet->Type_Wave_Transform,
                                                  Fc,
                                                  Build_Direct_Ok);
                   break;
        case TO_MALLAT_BARLAUD:
                   mallat_2d_reconstruct (Imag, &(Wavelet->Mallat), 
                                                  Nl, Nc, Nbr_Plan);
                   break;
        default:
                   fprintf (stderr, "Unknow transform\n");
                    break;
    }   
}

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