/* $Id: resampling.c,v 1.1.1.1 2001/08/27 11:27:25 rpalsa Exp $ * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ * COPYRIGHT (c) 2001 European Southern Observatory * LICENSE: GNU General Public License version 2 or later * * PROJECT: VLT Data Flow System * AUTHOR: Ralf Palsa -- ESO/DMD/DPG * SUBSYSTEM: Instrument pipelines * * PURPOSE: * DESCRIPTION: * The contents of this file has been extracted from the eclipse library * and modified. * * The original file was resampling.c (Revision 1.19, 2001/07/20) by * N. Devillard. * * $Name: fsmosaic-1_0 $ * $Revision: 1.1.1.1 $ * ---------------------------------------------------------------------------- */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include "e_error.h" #include "resampling.h" #define hk_gen(x,s) (((tanh(s*(x+0.5))+1)/2)*((tanh(s*(-x+0.5))+1)/2)) /** * @memo * Cardinal sine. * * @return 1 double. * * @param x double value. * * @doc * Compute the value of the function sinc(x)=sin(pi*x)/(pi*x) at the * requested x. * * @author N. Devillard */ double sinc(double x) { if (fabs(x) < 1e-4) return (double)1.00; else return ((sin(x * (double)PI_NUMB)) / (x * (double)PI_NUMB)); } #define KERNEL_SW(a,b) tempr=(a);(a)=(b);(b)=tempr /** * @memo * Bring a hyperbolic tangent kernel from Fourier to normal space. * * @return void * * @param data Kernel samples in Fourier space. * @param nn Number of samples in the input kernel. * * @doc * Bring back a hyperbolic tangent kernel from Fourier to normal space. Do * not try to understand the implementation and DO NOT MODIFY THIS FUNCTION. * * @author N. Devillard */ static void reverse_tanh_kernel(double * data, int nn) { unsigned long n, mmax, m, i, j, istep; double wtemp, wr, wpr, wpi, wi, theta; double tempr, tempi; n = (unsigned long)nn << 1; j = 1; for (i = 1; i < n; i += 2) { if (j > i) { KERNEL_SW(data[j-1],data[i-1]); KERNEL_SW(data[j],data[i]); } m = n >> 1; while (m >= 2 && j > m) { j -= m; m >>= 1; } j += m; } mmax = 2; while (n > mmax) { istep = mmax << 1; theta = 2 * PI_NUMB / mmax; wtemp = sin(0.5 * theta); wpr = -2.0 * wtemp * wtemp; wpi = sin(theta); wr = 1.0; wi = 0.0; for (m = 1; m < mmax; m += 2) { for (i = m; i <= n; i += istep) { j = i + mmax; tempr = wr * data[j-1] - wi * data[j]; tempi = wr * data[j] + wi * data[j-1]; data[j-1] = data[i-1] - tempr; data[j] = data[i] - tempi; data[i-1] += tempr; data[i] += tempi; } wr = (wtemp = wr) * wpr - wi * wpi + wr; wi = wi * wpr + wtemp * wpi + wi; } mmax = istep; } } #undef KERNEL_SW /** * @memo * Generate a hyperbolic tangent kernel. * * @return 1 pointer to a newly allocated array of doubles. * * @param steep Steepness of the hyperbolic tangent parts. * * @doc * The following function builds up a good approximation of a box filter. * It is built from a product of hyperbolic tangents. It has the following * properties: * \begin{itemize} * \item It converges very quickly towards +/- 1. * \item The converging transition is very sharp. * \item It is infinitely differentiable everywhere (i.e. smooth). * \item The transition sharpness is scalable. * \end{itemize} * * The returned array must be deallocated using free(). * * @author N. Devillard */ double * generate_tanh_kernel(double steep) { double *kernel; double *x; double width; double inv_np; double ind; int i; int np; int samples; width = (double)TABSPERPIX / 2.0; samples = KERNEL_SAMPLES; np = 32768; /* Hardcoded: should never be changed */ inv_np = 1.00 / (double)np; /* * Generate the kernel expression in Fourier space * with a correct frequency ordering to allow standard FT */ x = malloc((2*np+1)*sizeof(double)); for (i=0 ; ihsize; int ly_out = image_out->vsize; double cur; double *invert_transform; double neighbors[16]; double rsc[8], sumrs; double x, y; double *kernel; assert(image_in != NULL); assert(param != NULL); invert_transform = invert_linear_transform(param); if (invert_transform == NULL) { e_error("cannot compute invert transform: aborting warping"); return NULL; } /* * Generate default interpolation kernel */ kernel = generate_interpolation_kernel(kernel_type); if (kernel == NULL) { e_error("cannot generate kernel: aborting resampling"); return NULL; } /* Pre compute leaps for 16 closest neighbors positions */ leaps[0] = -1 - image_in->hsize; leaps[1] = - image_in->hsize; leaps[2] = 1 - image_in->hsize; leaps[3] = 2 - image_in->hsize; leaps[4] = -1; leaps[5] = 0; leaps[6] = 1; leaps[7] = 2; leaps[8] = -1 + image_in->hsize; leaps[9] = image_in->hsize; leaps[10]= 1 + image_in->hsize; leaps[11]= 2 + image_in->hsize; leaps[12]= -1 + 2*image_in->hsize; leaps[13]= 2*image_in->hsize; leaps[14]= 1 + 2*image_in->hsize; leaps[15]= 2 + 2*image_in->hsize; /* Double loop on the output image */ for (j=0 ; j < ly_out ; j++) { for (i=0 ; i< lx_out ; i++) { /* Compute the original source for this pixel */ x = invert_transform[0] * (double)i + invert_transform[1] * (double)j + invert_transform[2]; y = invert_transform[3] * (double)i + invert_transform[4] * (double)j + invert_transform[5]; /* Which is the closest integer positioned neighbor? */ px = (int)x; py = (int)y; if ((px < 1) || (px > (image_in->hsize-3)) || (py < 1) || (py > (image_in->vsize-3))) image_out->data[i+j*lx_out] = (pixel_t)0.0; else { /* Now feed the positions for the closest 16 neighbors */ pos = px + py * image_in->hsize; for (k=0 ; k<16 ; k++) neighbors[k] = (double)(image_in->data[(int)(pos + leaps[k])]); /* Which tabulated value index shall we use? */ tabx = (int)((x - (double)px) * (double)(TABSPERPIX)); taby = (int)((y - (double)py) * (double)(TABSPERPIX)); /* Compute resampling coefficients */ /* rsc[0..3] in x, rsc[4..7] in y */ rsc[0] = kernel[TABSPERPIX + tabx]; rsc[1] = kernel[tabx]; rsc[2] = kernel[TABSPERPIX - tabx]; rsc[3] = kernel[2 * TABSPERPIX - tabx]; rsc[4] = kernel[TABSPERPIX + taby]; rsc[5] = kernel[taby]; rsc[6] = kernel[TABSPERPIX - taby]; rsc[7] = kernel[2 * TABSPERPIX - taby]; sumrs = (rsc[0] + rsc[1] + rsc[2] + rsc[3]) * (rsc[4] + rsc[5] + rsc[6] + rsc[7]); /* Compute interpolated pixel now */ cur = rsc[4] * (rsc[0]*neighbors[0] + rsc[1]*neighbors[1] + rsc[2]*neighbors[2] + rsc[3]*neighbors[3]) + rsc[5] * (rsc[0]*neighbors[4] + rsc[1]*neighbors[5] + rsc[2]*neighbors[6] + rsc[3]*neighbors[7]) + rsc[6] * (rsc[0]*neighbors[8] + rsc[1]*neighbors[9] + rsc[2]*neighbors[10] + rsc[3]*neighbors[11]) + rsc[7] * (rsc[0]*neighbors[12] + rsc[1]*neighbors[13] + rsc[2]*neighbors[14] + rsc[3]*neighbors[15]); /* Affect the value to the output image */ image_out->data[i+j*lx_out] = (pixel_t)(cur/sumrs); /* done ! */ } } } free(kernel); free(invert_transform); return image_out; }