SINFONI Pipeline Reference Manual  2.5.2
sinfo_new_resampling.c
1 /*
2  * This file is part of the ESO SINFONI Pipeline
3  * Copyright (C) 2004,2005 European Southern Observatory
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA
18  */
19 
20 /*----------------------------------------------------------------------------
21 
22  File name : sinfo_new_resampling.c
23  Author : Nicolas Devillard
24  Created on : Jan 04, 1996
25  Description : resampling routines
26 
27  ---------------------------------------------------------------------------*/
28 
29 /*
30  $Id: sinfo_new_resampling.c,v 1.10 2012-03-03 09:50:08 amodigli Exp $
31  $Author: amodigli $
32  $Date: 2012-03-03 09:50:08 $
33  $Revision: 1.10 $
34  */
35 
36 #ifdef HAVE_CONFIG_H
37 # include <config.h>
38 #endif
39 /*---------------------------------------------------------------------------
40  Includes
41  ---------------------------------------------------------------------------*/
42 #include <math.h>
43 #include "sinfo_new_resampling.h"
44 #include "sinfo_pixel_handling.h"
45 #include "sinfo_globals.h"
46 /* #include "my_pi.h" */
47 #include "sinfo_resampling.h"
48 /*---------------------------------------------------------------------------
49  Private functions
50  ---------------------------------------------------------------------------*/
51 
52 static void new_reverse_tanh_kernel(double * data, int nn) ;
53 static double sinfo_new_sinc(double x);
54 
55 /*---------------------------------------------------------------------------
56  Function codes
57  ---------------------------------------------------------------------------*/
58 
66 /*-------------------------------------------------------------------------*/
90 /*--------------------------------------------------------------------------*/
91 
92 double *
93 sinfo_new_generate_interpolation_kernel(const char * kernel_type)
94 {
95  double * tab ;
96  int i ;
97  double x ;
98  double alpha ;
99  double inv_norm ;
100  int samples = KERNEL_SAMPLES ;
101 
102  if (kernel_type==NULL) {
103  tab = sinfo_new_generate_interpolation_kernel("tanh") ;
104  } else if (!strcmp(kernel_type, "default")) {
105  tab = sinfo_new_generate_interpolation_kernel("tanh") ;
106  } else if (!strcmp(kernel_type, "sinfo_new_sinc")) {
107  tab = cpl_malloc(samples * sizeof(double)) ;
108  tab[0] = 1.0 ;
109  tab[samples-1] = 0.0 ;
110  for (i=1 ; i<samples ; i++) {
111  x = (double)KERNEL_WIDTH * (double)i/(double)(samples-1) ;
112  tab[i] = sinfo_new_sinc(x) ;
113  }
114  } else if (!strcmp(kernel_type, "sinc2")) {
115  tab = cpl_malloc(samples * sizeof(double)) ;
116  tab[0] = 1.0 ;
117  tab[samples-1] = 0.0 ;
118  for (i=1 ; i<samples ; i++) {
119  x = 2.0 * (double)i/(double)(samples-1) ;
120  tab[i] = sinfo_new_sinc(x) ;
121  tab[i] *= tab[i] ;
122  }
123  } else if (!strcmp(kernel_type, "lanczos")) {
124  tab = cpl_malloc(samples * sizeof(double)) ;
125  for (i=0 ; i<samples ; i++) {
126  x = (double)KERNEL_WIDTH * (double)i/(double)(samples-1) ;
127  if (fabs(x)<2) {
128  tab[i] = sinfo_new_sinc(x) * sinfo_new_sinc(x/2) ;
129  } else {
130  tab[i] = 0.00 ;
131  }
132  }
133  } else if (!strcmp(kernel_type, "hamming")) {
134  tab = cpl_malloc(samples * sizeof(double)) ;
135  alpha = 0.54 ;
136  inv_norm = 1.00 / (double)(samples - 1) ;
137  for (i=0 ; i<samples ; i++) {
138  x = (double)i ;
139  if (i<(samples-1)/2) {
140  tab[i] = alpha + (1-alpha) * cos(2.0*PI_NUMB*x*inv_norm) ;
141  } else {
142  tab[i] = 0.0 ;
143  }
144  }
145  } else if (!strcmp(kernel_type, "hann")) {
146  tab = cpl_malloc(samples * sizeof(double)) ;
147  alpha = 0.50 ;
148  inv_norm = 1.00 / (double)(samples - 1) ;
149  for (i=0 ; i<samples ; i++) {
150  x = (double)i ;
151  if (i<(samples-1)/2) {
152  tab[i] = alpha + (1-alpha) * cos(2.0*PI_NUMB*x*inv_norm) ;
153  } else {
154  tab[i] = 0.0 ;
155  }
156  }
157  } else if (!strcmp(kernel_type, "tanh")) {
158  tab = sinfo_new_generate_tanh_kernel(TANH_STEEPNESS) ;
159  } else {
160  sinfo_msg_error("unrecognized kernel type [%s]: aborting generation",
161  kernel_type) ;
162  return NULL ;
163  }
164 
165  return tab ;
166 }
167 
168 /*-------------------------------------------------------------------------*/
179 /*--------------------------------------------------------------------------*/
180 
181 double
182 sinfo_new_sinc(double x)
183 {
184  if (fabs(x)<1e-4)
185  return (double)1.00 ;
186  else
187  return ((sin(x * (double)PI_NUMB)) / (x * (double)PI_NUMB)) ;
188 }
189 
190 
191 
192 /*-------------------------------------------------------------------------*/
228 /*--------------------------------------------------------------------------*/
229 
230 cpl_image *
231 sinfo_new_warp_image_generic(
232  cpl_image * image_in,
233  char * kernel_type,
234  cpl_polynomial * poly_u,
235  cpl_polynomial * poly_v
236 )
237 {
238  cpl_image * image_out ;
239  int i, j, k ;
240  int lx_out, ly_out ;
241  double cur ;
242  double neighbors[16] ;
243  double rsc[8],
244  sumrs ;
245  double x, y ;
246  int px, py ;
247  int pos ;
248  int tabx, taby ;
249  double * kernel ;
250  int leaps[16] ;
251  int ilx=0;
252  int ily=0;
253  float* pidata=NULL;
254  float* podata=NULL;
255  cpl_vector* vx=NULL;
256  if (image_in == NULL) return NULL ;
257 
258 
259  /* Generate default interpolation kernel */
260  kernel = sinfo_new_generate_interpolation_kernel(kernel_type) ;
261  if (kernel == NULL) {
262  sinfo_msg_error("cannot generate kernel: aborting resampling") ;
263  return NULL ;
264  }
265  ilx=cpl_image_get_size_x(image_in);
266  ily=cpl_image_get_size_y(image_in);
267  pidata=cpl_image_get_data_float(image_in);
268 
269  /* Compute new image size */
270  lx_out = (int)ilx ;
271  ly_out = (int)ily ;
272 
273  image_out = cpl_image_new(lx_out, ly_out,CPL_TYPE_FLOAT) ;
274  podata=cpl_image_get_data_float(image_out);
275 
276  /* Pre compute leaps for 16 closest neighbors positions */
277 
278  leaps[0] = -1 - ilx ;
279  leaps[1] = - ilx ;
280  leaps[2] = 1 - ilx ;
281  leaps[3] = 2 - ilx ;
282 
283  leaps[4] = -1 ;
284  leaps[5] = 0 ;
285  leaps[6] = 1 ;
286  leaps[7] = 2 ;
287 
288  leaps[8] = -1 + ilx ;
289  leaps[9] = ilx ;
290  leaps[10]= 1 + ilx ;
291  leaps[11]= 2 + ilx ;
292 
293  leaps[12]= -1 + 2*ilx ;
294  leaps[13]= 2*ilx ;
295  leaps[14]= 1 + 2*ilx ;
296  leaps[15]= 2 + 2*ilx ;
297 
298  vx=cpl_vector_new(2); /* vector of size 2 = polynomial dimension */
299  /* Double loop on the output image */
300  for (j=0 ; j < ly_out ; j++) {
301  for (i=0 ; i< lx_out ; i++) {
302  /* Compute the original source for this pixel */
303  cpl_vector_set(vx,0,(double)i);
304  cpl_vector_set(vx,1,(double)j);
305  x = cpl_polynomial_eval(poly_u, vx);
306  y = cpl_polynomial_eval(poly_v, vx);
307 
308  /* Which is the closest integer positioned neighbor? */
309  px = (int)x ;
310  py = (int)y ;
311 
312  if ((px < 1) ||
313  (px > (ilx-3)) ||
314  (py < 1) ||
315  (py > (ily-3)))
316  podata[i+j*lx_out] = (pixelvalue)0.0/0.0 ;
317  else {
318  /* Now feed the positions for the closest 16 neighbors */
319  pos = px + py * ilx ;
320  for (k=0 ; k<16 ; k++)
321  neighbors[k] = (double)(pidata[(int)(pos+leaps[k])]) ;
322 
323  /* Which tabulated value index shall we use? */
324  tabx = (x - (double)px) * (double)(TABSPERPIX) ;
325  taby = (y - (double)py) * (double)(TABSPERPIX) ;
326 
327  /* Compute resampling coefficients */
328  /* rsc[0..3] in x, rsc[4..7] in y */
329 
330  rsc[0] = kernel[TABSPERPIX + tabx] ;
331  rsc[1] = kernel[tabx] ;
332  rsc[2] = kernel[TABSPERPIX - tabx] ;
333  rsc[3] = kernel[2 * TABSPERPIX - tabx] ;
334  rsc[4] = kernel[TABSPERPIX + taby] ;
335  rsc[5] = kernel[taby] ;
336  rsc[6] = kernel[TABSPERPIX - taby] ;
337  rsc[7] = kernel[2 * TABSPERPIX - taby] ;
338 
339  sumrs = (rsc[0]+rsc[1]+rsc[2]+rsc[3]) *
340  (rsc[4]+rsc[5]+rsc[6]+rsc[7]) ;
341 
342  /* Compute interpolated pixel now */
343  cur = rsc[4] * ( rsc[0]*neighbors[0] +
344  rsc[1]*neighbors[1] +
345  rsc[2]*neighbors[2] +
346  rsc[3]*neighbors[3] ) +
347  rsc[5] * ( rsc[0]*neighbors[4] +
348  rsc[1]*neighbors[5] +
349  rsc[2]*neighbors[6] +
350  rsc[3]*neighbors[7] ) +
351  rsc[6] * ( rsc[0]*neighbors[8] +
352  rsc[1]*neighbors[9] +
353  rsc[2]*neighbors[10] +
354  rsc[3]*neighbors[11] ) +
355  rsc[7] * ( rsc[0]*neighbors[12] +
356  rsc[1]*neighbors[13] +
357  rsc[2]*neighbors[14] +
358  rsc[3]*neighbors[15] ) ;
359 
360  /* Affect the value to the output image */
361  podata[i+j*lx_out] = (pixelvalue)(cur/sumrs) ;
362  /* done ! */
363  }
364  }
365  }
366  cpl_vector_delete(vx);
367  cpl_free(kernel) ;
368  return image_out ;
369 }
370 
371 
372 /*-------------------------------------------------------------------------*/
393 /*--------------------------------------------------------------------------*/
394 
395 #define hk_gen(x,s) (((tanh(s*(x+0.5))+1)/2)*((tanh(s*(-x+0.5))+1)/2))
396 
397 double * sinfo_new_generate_tanh_kernel(double steep)
398 {
399  double * kernel ;
400  double * x ;
401  double width ;
402  double inv_np ;
403  double ind ;
404  int i ;
405  int np ;
406  int samples ;
407 
408  width = (double)TABSPERPIX / 2.0 ;
409  samples = KERNEL_SAMPLES ;
410  np = 32768 ; /* Hardcoded: should never be changed */
411  inv_np = 1.00 / (double)np ;
412 
413  /*
414  * Generate the kernel expression in Fourier space
415  * with a correct frequency ordering to allow standard FT
416  */
417  x = cpl_malloc((2*np+1)*sizeof(double)) ;
418  for (i=0 ; i<np/2 ; i++) {
419  ind = (double)i * 2.0 * width * inv_np ;
420  x[2*i] = hk_gen(ind, steep) ;
421  x[2*i+1] = 0.00 ;
422  }
423  for (i=np/2 ; i<np ; i++) {
424  ind = (double)(i-np) * 2.0 * width * inv_np ;
425  x[2*i] = hk_gen(ind, steep) ;
426  x[2*i+1] = 0.00 ;
427  }
428 
429  /*
430  * Reverse Fourier to come back to image space
431  */
432  new_reverse_tanh_kernel(x, np) ;
433 
434  /*
435  * Allocate and fill in returned array
436  */
437  kernel = cpl_malloc(samples * sizeof(double)) ;
438  for (i=0 ; i<samples ; i++) {
439  kernel[i] = 2.0 * width * x[2*i] * inv_np ;
440  }
441  cpl_free(x) ;
442  return kernel ;
443 }
444 
445 
446 /*-------------------------------------------------------------------------*/
458 /*--------------------------------------------------------------------------*/
459 
460 #define KERNEL_SW(a,b) tempr=(a);(a)=(b);(b)=tempr
461 static void new_reverse_tanh_kernel(double * data, int nn)
462 {
463  unsigned long n,
464  mmax,
465  m,
466  i, j,
467  istep ;
468  double wtemp,
469  wr,
470  wpr,
471  wpi,
472  wi,
473  theta;
474  double tempr,
475  tempi;
476 
477  n = (unsigned long)nn << 1;
478  j = 1;
479  for (i=1 ; i<n ; i+=2) {
480  if (j > i) {
481  KERNEL_SW(data[j-1],data[i-1]);
482  KERNEL_SW(data[j],data[i]);
483  }
484  m = n >> 1;
485  while (m>=2 && j>m) {
486  j -= m;
487  m >>= 1;
488  }
489  j += m;
490  }
491  mmax = 2;
492  while (n > mmax) {
493  istep = mmax << 1;
494  theta = 2 * PI_NUMB / mmax;
495  wtemp = sin(0.5 * theta);
496  wpr = -2.0 * wtemp * wtemp;
497  wpi = sin(theta);
498  wr = 1.0;
499  wi = 0.0;
500  for (m=1 ; m<mmax ; m+=2) {
501  for (i=m ; i<=n ; i+=istep) {
502  j = i + mmax;
503  tempr = wr * data[j-1] - wi * data[j];
504  tempi = wr * data[j] + wi * data[j-1];
505  data[j-1] = data[i-1] - tempr;
506  data[j] = data[i] - tempi;
507  data[i-1] += tempr;
508  data[i] += tempi;
509  }
510  wr = (wtemp = wr) * wpr - wi * wpi + wr;
511  wi = wi * wpr + wtemp * wpi + wi;
512  }
513  mmax = istep;
514  }
515 }
516 #undef KERNEL_SW
517 
518 
519 
520 /*-------------------------------------------------------------------------*/
533 /*--------------------------------------------------------------------------*/
534 
535 void sinfo_new_show_interpolation_kernel(char * kernel_name)
536 {
537  double * ker ;
538  int i ;
539  double x ;
540 
541 
542  ker = sinfo_new_generate_interpolation_kernel(kernel_name) ;
543  if (ker == NULL)
544  return ;
545 
546  (void)fprintf(stdout, "# Kernel is %s\n", kernel_name) ;
547  x = 0.00 ;
548  for (i=0 ; i<KERNEL_SAMPLES ; i++) {
549  (void)fprintf(stdout, "%g %g\n", x, ker[i]) ;
550  x += 1.00 / (double)TABSPERPIX ;
551  }
552  cpl_free(ker) ;
553  return ;
554 }