/*---------------------------------------------------------------------------*/
/**
 * @file geraCampo.cpp
 * Este programa gera uma deformação radial em uma imagem, savlando a imagem deformada
 * e salvando o campo de vetores gerado
 * @author Lenardo (lmartins@tecgraf.puc-rio.br)
 * @date 15/10/2008
 */
/*---------------------------------------------------------------------------*/

#include "CImg.h"
using namespace cimg_library;

int main(int argc, char *argv[])
{
    
    if (argc < 3)
    {
       printf("Uso: %s <input img> <output format (png, pgm, jpg,etc.)>\n",argv[0]);
       system("pause");
       exit(0);
    }
        
    CImg<>image1(argv[1]);//imagem 1    
    const CImg<>origImage(argv[1]);//imagem 1 (copia) 
    
    CImg<>vector_image(image1.dimx(),image1.dimy());//imagem com o campo de vetores
    CImg<>field(image1.dimx(), image1.dimy(),1,2,3); //campo de vetores correto    
       
    float dx, dy, sx, sy;
    float mx = image1.dimx()/2.0; //metade da dimensao x
    float my = image1.dimy()/2.0;//metade da dimensao y
    const float white = 255;//cor branca
    int idx, idy; //valores inteiros de deslocamento
    double valor; //valor da imagem reamostrada
    
    float max = 2.0;//valor maximo de cada componente
    
    if (argc >3)
     max = atof(argv[3]);//atribui um valor maximo para as componentes vetoriais
     
    //abre arquivo para gravação do campo correto 
    char str[512];    
    sprintf(str,"%s.field",argv[1]);    
    FILE * fieldValues = fopen(str,"w");
    sprintf(str,"%s.def.%s",argv[1],argv[2]);
    fprintf(fieldValues,"%s %s\n",argv[1], str);//grava nome das imagens
    fprintf(fieldValues,"%d %d\n",image1.dimx(),image1.dimy());//grava dimesão das imagens
    
    //int l1, l2;    
    double sigma = 1E-8;
    int incremento;
      
    for (int lin = 0; lin < image1.dimy(); lin++)
    {
        for (int col = 0; col < image1.dimx(); col++)
        {
            
            dx = 0.0;
            dy = 0.0;
            
            if (col != mx && (mx-col) <0)
            {
             dx = -(max*exp(-sigma*(col-mx)*(col-mx)));
             dx *= (mx/col)*(mx/col);
            }
            if (lin != my && (my-lin) <0)
            {
             dy = -(max*exp(-sigma*(lin-my)*(lin-my)));
             dy *= (my/lin)*(my/lin);             
            }
            if (col != mx && (mx-col) >0)
            {
             dx = (max*exp(-sigma*(col-mx)*(col-mx)));
             dx *= (col/mx)*(col/mx);
            }
            if (lin != my && (my-lin) >0)
            {
             dy = (max*exp(-sigma*(lin-my)*(lin-my)));
             dy *= (lin/my)*(lin/my);
            }
            
            idx = (int)floor(dx);
            idy = (int)floor(dy);
            sx = dx - idx;
            sy = dy - idy;
            incremento = -1;
             
             //realiza a interpolação bilinear para achar o valor na imagem reamostrada
             if (col < image1.dimx()-max-1 && col >max+1 && lin < image1.dimy()-max-1 && lin >max+1 )
             {
              valor = (1-sx)*(1-sy)*origImage(col-idx, lin-idy)+ sx*(1-sy)*origImage(col-idx+incremento, lin-idy) + (1-sx)*sy*origImage(col-idx, lin-idy+incremento) + sx*sy*origImage(col-idx+incremento, lin-idy+incremento);
             }
            //se estiver dentro do círculo, aplica distorção
            if ((col - mx)*(col - mx) + (lin - my)*(lin - my) <= 50000/*80000*/)
            {
             image1(col, lin) = valor;//origImage(col-dx,lin-dy);
             fprintf(fieldValues,"%d %d %.10f %.10f\n",lin, col, dx,dy);
             field(col, lin,0) = dx;
             field(col, lin,1) = dy;
             }
             else 
             {
               fprintf(fieldValues,"%d %d 0.0000 0.0000\n",lin, col);             
               field(col, lin,0) = 0.0;
               field(col, lin,1) = 0.0;
             }                         
        }
    }
    fclose(fieldValues);
    image1.save(str);//salva a imagem deformada    
    vector_image.draw_quiver(field,&white,8,-14,0,0.7f).save("correctField.pgm");//salva o campo correto
    vector_image.draw_quiver(field,&white,8,-14,0,0.7f).display(0);//exibe o campo correto
    return 0;
}
