00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #ifdef HAVE_CONFIG_H
00036 # include <config.h>
00037 #endif
00038
00039
00040
00041 #include <string.h>
00042 #include "sinfo_resampling.h"
00043 #include <math.h>
00044 #include "sinfo_globals.h"
00045
00046
00047
00048 static void reverse_tanh_kernel(double * data, int nn) ;
00049 static double * sinfo_generate_tanh_kernel(double steep);
00050
00060
00061
00062
00063
00088 double *
00089 sinfo_generate_interpolation_kernel(const char * kernel_type)
00090 {
00091 double * tab ;
00092 int i ;
00093 double x ;
00094 double alpha ;
00095 double inv_norm ;
00096 int samples = KERNEL_SAMPLES ;
00097
00098 if (kernel_type==NULL) {
00099 tab = sinfo_generate_interpolation_kernel("tanh") ;
00100 } else if (!strcmp(kernel_type, "default")) {
00101 tab = sinfo_generate_interpolation_kernel("tanh") ;
00102 } else if (!strcmp(kernel_type, "sinc")) {
00103 tab = cpl_malloc(samples * sizeof(double)) ;
00104 tab[0] = 1.0 ;
00105 tab[samples-1] = 0.0 ;
00106 for (i=1 ; i<samples ; i++) {
00107 x = (double)KERNEL_WIDTH * (double)i/(double)(samples-1) ;
00108 tab[i] = sinfo_sinc(x) ;
00109 }
00110 } else if (!strcmp(kernel_type, "sinc2")) {
00111 tab = cpl_malloc(samples * sizeof(double)) ;
00112 tab[0] = 1.0 ;
00113 tab[samples-1] = 0.0 ;
00114 for (i=1 ; i<samples ; i++) {
00115 x = 2.0 * (double)i/(double)(samples-1) ;
00116 tab[i] = sinfo_sinc(x) ;
00117 tab[i] *= tab[i] ;
00118 }
00119 } else if (!strcmp(kernel_type, "lanczos")) {
00120 tab = cpl_malloc(samples * sizeof(double)) ;
00121 for (i=0 ; i<samples ; i++) {
00122 x = (double)KERNEL_WIDTH * (double)i/(double)(samples-1) ;
00123 if (fabs(x)<2) {
00124 tab[i] = sinfo_sinc(x) * sinfo_sinc(x/2) ;
00125 } else {
00126 tab[i] = 0.00 ;
00127 }
00128 }
00129 } else if (!strcmp(kernel_type, "hamming")) {
00130 tab = cpl_malloc(samples * sizeof(double)) ;
00131 alpha = 0.54 ;
00132 inv_norm = 1.00 / (double)(samples - 1) ;
00133 for (i=0 ; i<samples ; i++) {
00134 x = (double)i ;
00135 if (i<(samples-1)/2) {
00136 tab[i] = alpha + (1-alpha) * cos(2.0*PI_NUMB*x*inv_norm) ;
00137 } else {
00138 tab[i] = 0.0 ;
00139 }
00140 }
00141 } else if (!strcmp(kernel_type, "hann")) {
00142 tab = cpl_malloc(samples * sizeof(double)) ;
00143 alpha = 0.50 ;
00144 inv_norm = 1.00 / (double)(samples - 1) ;
00145 for (i=0 ; i<samples ; i++) {
00146 x = (double)i ;
00147 if (i<(samples-1)/2) {
00148 tab[i] = alpha + (1-alpha) * cos(2.0*PI_NUMB*x*inv_norm) ;
00149 } else {
00150 tab[i] = 0.0 ;
00151 }
00152 }
00153 } else if (!strcmp(kernel_type, "tanh")) {
00154 tab = sinfo_generate_tanh_kernel(TANH_STEEPNESS) ;
00155 } else {
00156 sinfo_msg_error("unrecognized kernel type [%s]: aborting generation",
00157 kernel_type) ;
00158 return NULL ;
00159 }
00160
00161 return tab ;
00162 }
00163
00175 double
00176 sinfo_sinc(double x)
00177 {
00178 if (fabs(x)<1e-4)
00179 return (double)1.00 ;
00180 else
00181 return ((sin(x * (double)PI_NUMB)) / (x * (double)PI_NUMB)) ;
00182 }
00183
00205 #define hk_gen(x,s) (((tanh(s*(x+0.5))+1)/2)*((tanh(s*(-x+0.5))+1)/2))
00206
00207 static double *
00208 sinfo_generate_tanh_kernel(double steep)
00209 {
00210 double * kernel ;
00211 double * x ;
00212 double width ;
00213 double inv_np ;
00214 double ind ;
00215 int i ;
00216 int np ;
00217 int samples ;
00218
00219 width = (double)TABSPERPIX / 2.0 ;
00220 samples = KERNEL_SAMPLES ;
00221 np = 32768 ;
00222 inv_np = 1.00 / (double)np ;
00223
00224
00225
00226
00227
00228 x = cpl_malloc((2*np+1)*sizeof(double)) ;
00229 for (i=0 ; i<np/2 ; i++) {
00230 ind = (double)i * 2.0 * width * inv_np ;
00231 x[2*i] = hk_gen(ind, steep) ;
00232 x[2*i+1] = 0.00 ;
00233 }
00234 for (i=np/2 ; i<np ; i++) {
00235 ind = (double)(i-np) * 2.0 * width * inv_np ;
00236 x[2*i] = hk_gen(ind, steep) ;
00237 x[2*i+1] = 0.00 ;
00238 }
00239
00240
00241
00242
00243 reverse_tanh_kernel(x, np) ;
00244
00245
00246
00247
00248 kernel = cpl_malloc(samples * sizeof(double)) ;
00249 for (i=0 ; i<samples ; i++) {
00250 kernel[i] = 2.0 * width * x[2*i] * inv_np ;
00251 }
00252 cpl_free(x) ;
00253 return kernel ;
00254 }
00255
00268 #define KERNEL_SW(a,b) tempr=(a);(a)=(b);(b)=tempr
00269 static void
00270 reverse_tanh_kernel(double * data, int nn)
00271 {
00272 unsigned long n,
00273 mmax,
00274 m,
00275 i, j,
00276 istep ;
00277 double wtemp,
00278 wr,
00279 wpr,
00280 wpi,
00281 wi,
00282 theta;
00283 double tempr,
00284 tempi;
00285
00286 n = (unsigned long)nn << 1;
00287 j = 1;
00288 for (i=1 ; i<n ; i+=2) {
00289 if (j > i) {
00290 KERNEL_SW(data[j-1],data[i-1]);
00291 KERNEL_SW(data[j],data[i]);
00292 }
00293 m = n >> 1;
00294 while (m>=2 && j>m) {
00295 j -= m;
00296 m >>= 1;
00297 }
00298 j += m;
00299 }
00300 mmax = 2;
00301 while (n > mmax) {
00302 istep = mmax << 1;
00303 theta = 2 * PI_NUMB / mmax;
00304 wtemp = sin(0.5 * theta);
00305 wpr = -2.0 * wtemp * wtemp;
00306 wpi = sin(theta);
00307 wr = 1.0;
00308 wi = 0.0;
00309 for (m=1 ; m<mmax ; m+=2) {
00310 for (i=m ; i<=n ; i+=istep) {
00311 j = i + mmax;
00312 tempr = wr * data[j-1] - wi * data[j];
00313 tempi = wr * data[j] + wi * data[j-1];
00314 data[j-1] = data[i-1] - tempr;
00315 data[j] = data[i] - tempi;
00316 data[i-1] += tempr;
00317 data[i] += tempi;
00318 }
00319 wr = (wtemp = wr) * wpr - wi * wpi + wr;
00320 wi = wi * wpr + wtemp * wpi + wi;
00321 }
00322 mmax = istep;
00323 }
00324 }
00325 #undef KERNEL_SW
00326
00364 double *
00365 sinfo_invert_linear_transform(double *trans)
00366 {
00367 double * i_trans ;
00368 double det ;
00369
00370 if (trans==NULL) return NULL ;
00371 det = (trans[0] * trans[4]) - (trans[1] * trans[3]) ;
00372 if (fabs(det) < 1e-6) {
00373 sinfo_msg_error("NULL determinant: cannot sinfo_invert transform") ;
00374 return NULL ;
00375 }
00376
00377 i_trans = cpl_calloc(6, sizeof(double)) ;
00378
00379 i_trans[0] = trans[4] / det ;
00380 i_trans[1] = -trans[1] / det ;
00381 i_trans[2] = ((trans[1] * trans[5]) - (trans[2] * trans[4])) / det ;
00382 i_trans[3] = -trans[3] / det ;
00383 i_trans[4] = trans[0] / det ;
00384 i_trans[5] = ((trans[2] * trans[3]) - (trans[0] * trans[5])) / det ;
00385
00386 return i_trans ;
00387 }