SINFONI Pipeline Reference Manual  2.5.2
sinfo_image_ops.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  * M.P.E. - SPIFFI project
21  *
22  *
23  *
24  * who when what
25  * -------- -------- ----------------------------------------------
26  * rabuter 2004-12-03 support one dimensional image in sinfo_shiftImage
27  * schreib 23/05/00 created
28  */
29 
30 /************************************************************************
31  * NAME
32  * sinfo_image_ops.c -
33  * image arithmetic routines
34  *
35  * SYNOPSIS
36  * #include "sinfo_image_ops.h"
37  *
38  * 1) Vector * sinfo_new_mean_of_columns( cpl_image *im )
39  * 2) Vector * sinfo_new_clean_mean_of_columns( cpl_image *im,
40  * double lo_reject,
41  * double hi_reject)
42  * 3) cpl_image * sinfo_new_div_image_by_row( cpl_image *im, Vector *row )
43  * 4) cpl_image * sinfo_new_mult_row_to_image( cpl_image *im, Vector *row )
44  * 5) cpl_image * sinfo_new_col_tilt ( cpl_image * image, float sigmaFactor )
45  * 6) cpl_image * sinfo_new_median_image( cpl_image * im, float fmedian )
46  * 7) cpl_image * sinfo_new_compare_images( cpl_image * im1,
47  cpl_image * im2,
48  cpl_image * origim )
49  * 8) cpl_image * sinfo_new_thresh_image ( cpl_image * im,
50  float lo_cut, float hi_cut )
51  * 9) pixel_map * sinfo_new_promote_image_to_pixelmap ( cpl_image * im )
52  * 10) cpl_image * sinfo_new_promote_image_to_mask ( cpl_image * im,
53  int * n_badpixels )
54  * 11) cpl_image * sinfo_new_mult_image_by_mask ( cpl_image * im,
55  cpl_image * mask )
56  * 12) cpl_image * sinfo_new_interpol_image ( cpl_image * im,
57  * cpl_image * mask,
58  * int max_radius,
59  * int n_pixels )
60  * 13) cpl_image * sinfo_interpol_source_image ( cpl_image * im,
61  * cpl_image * mask,
62  * int max_rad,
63  * float ** slit_edges )
64  * 14) cpl_image * sinfo_new_stack_row_to_image ( Vector * row, int ly )
65  * 15) Stats * sinfo_new_image_stats_on_rectangle ( cpl_image * im,
66  * float loReject,
67  * float hiReject,
68  * int llx,
69  * int lly,
70  * int urx,
71  * int ury )
72  * 16) cpl_image * sinfo_new_normalize_to_central_pixel ( cpl_image * image )
73  * 17) cpl_image *
74  * sinfo_new_shift_image(
75  * cpl_image * image_in,
76  * double shift_x,
77  * double shift_y,
78  * double * interp_kernel)
79  * 18) cpl_image * sinfo_new_combine_masks ( cpl_image * firstMask,
80  cpl_image * secondMask )
81  * 19) cpl_image * sinfo_new_slice_cube (cpl_imagelist * cube, int x, int y )
82  * 20) cpl_image * sinfo_new_div_images_robust ( cpl_image * im1,
83  cpl_image * im2 )
84  *
85  *
86  * DESCRIPTION
87  * 1) takes the average of each image column
88  * 2) takes the average of each image column by sorting the
89  * column values and rejecting the given percentage of
90  * the highest and lowest values [0...1]
91  * 3) divides each image column by a row value
92  * 4) multiplies each image column with a row value
93  * 5) first calculates statistics for each column of an image.
94  * sinfo_median value and standard deviation of columns are de-
95  * termined, blank values are excluded. Fits a straight
96  * line through the pixel values of each column and subtracts
97  * the fit in order to remove the tilt of each column.
98  * Only those pixels are used for the fit that are within
99  * a defined factor of sigma noise limit. The noise is
100  * calculated from pixels between the 10percentil and
101  * 90percentil points.
102  * if the straight line could not be determined, the sinfo_median
103  * of the column is subtracted from the column
104  * 6) sinfo_median filter, calculates the sinfo_median for an image
105  * by using the 8 closest pixels to each pixel.
106  * The values in the output image are determined according
107  * to the values of the input parameter.
108  * If fmedian = 0: always replace by sinfo_median
109  * if fmedian < 0: replace by sinfo_median if |pixel - sinfo_median| >
110  * -fmedian
111  * if fmedian > 0: replace by sinfo_median (fmedian as a factor of
112  * the square root of the sinfo_median itself)
113  * if |pixel - median| >= fmedian * sqrt ( median )
114  * This can be used to consider photon noise.
115  * This considers a dependence of the differences on the
116  * pixel values themselves.
117  * 7) if a pixel value of one image (im1) equals
118  * the pixel value of the other image keep the
119  * pixel value of the original image otherwise replace
120  * it with ZEROs
121  * 8) simple search for static bad pixels for a flat field
122  * or sinfo_dark frame, values below and above the threshold
123  * values are set to ZERO.
124  * 9) changes an image with ZERO indicated bad pixels to
125  * a bad pixel map.
126  * 10) changes an image with ZERO indicated bad pixels to
127  * a bad pixel mask image, that means the returned
128  * image has values 1 at positions of good pixels and
129  * ZEROs at positions of bad pixels.
130  * 11) changes an image to an image that has ZERO indicated
131  * static bad pixels
132  * 12) interpolates all bad pixels indicated by the bad pixel mask.
133  * Therefore, the mean of at least 2 valid values of
134  * the nearest 8 neighbors is taken. If too much
135  * neighbors are also bad pixels
136  * the neighbor radius is increased to a maximum of
137  * max_radius until n_pixels valid pixels are found.
138  * The valid neighbors are searched by going through
139  * the columns and rows around the central square that
140  * was already searched.
141  * The bad pixel is interpolated by the mean of these
142  * valid pixels (less than 9) or by the sinfo_median of them
143  * (more than 8).
144  * 13) interpolates all bad pixels indicated by the bad pixel mask.
145  * Therefore, the mean of the nearest 4 neighbors is taken,
146  * two in spectral direction and 2 in spatial direction.
147  * The routine cares about the image and slitlet edges.
148  * If there are no good pixel found within the nearest neighbors,
149  * the next 4 nearest neighbors in spatial and spectral direction
150  * are searched for valid pixels until a limit of max_rad.
151  * A maximum of 4 valid pixels are used for interpolation by their mean.
152  * 14) stack a given image row to build a whole image
153  * 15) computes the mean and standard deviation of
154  * a given rectangle on an image by leaving the extreme
155  * intensity values.
156  * 16) normalizes a raw flatfield image by dividing by the median of the
157  central spectral pixels to produce a master flatfield
158  * 17) This function is a conversion to CPL of the ECLIPSE function
159  shift_image()
160  * but slightly changed. If a blank (ZERO) pixel appears the blank pixel
161  * is shifted but preserved as blank.
162  * If a blank (ZERO) pixel appears within the
163  * interpolation kernel the blank pixel is set to 0.
164  *
165  * This function shifts an image by a non-integer offset, using
166  * interpolation. You can either generate an interpolation kernel once and
167  * pass it to this function, or let it generate a default kernel. In the
168  * former case, use sinfo_generate_interpolation_kernel() to generate an
169  * appropriate kernel. In the latter case, pass NULL as last argument. A
170  * default interpolation kernel is then generated then discarded
171  before this function returns.
172  *
173  * The returned image is a newly allocated object, it must be deallocated
174  * using cpl_image_delete().
175  * 18) combines two bad pixel mask to one using an or relation
176  * 19) slices a data cube in x or y direction
177  * 20) divides two images by considering blanks and
178  * calculating first 1/im2 by
179  * cutting the very high values and setting to 1,
180  * then multiplying im1 * 1/im2.
181  *
182  * FILES
183  *
184  * ENVIRONMENT
185  *
186  * RETURN VALUES
187  *
188  * CAUTIONS
189  *
190  * EXAMPLES
191  *
192  * SEE ALSO
193  *
194  * BUGS
195  *
196  *------------------------------------------------------------------------
197  */
198 
199 #ifdef HAVE_CONFIG_H
200 # include <config.h>
201 #endif
202 #include "sinfo_vltPort.h"
203 
204 /*
205  * System Headers
206  */
207 #include <errno.h>
208 /*
209  * Local Headers
210  */
211 
212 #include "sinfo_image_ops.h"
213 #include "sinfo_error.h"
214 #include "sinfo_resampling.h"
215 #include "sinfo_local_types.h"
216 #include "sinfo_utils_wrappers.h"
225 static cpl_image *
226 sinfo_gen_lowpass(const int xs,
227  const int ys,
228  const double sigma_x,
229  const double sigma_y);
230 
231 
232 static void quicksort_int(int* data, int left, int right);
235 /*----------------------------------------------------------------------------
236  * Function codes
237  *--------------------------------------------------------------------------*/
238 
239 
240 
252 cpl_error_code
253 sinfo_image_line_corr(const int width,
254  const int filt_rad,
255  const int kappa,
256  cpl_image* ima_in,
257  cpl_image** ima_out)
258 {
259 
260  cpl_image* mask=NULL;
261 
262  cpl_image* ima_backpix=NULL;
263  cpl_image* ima_backpos=NULL;
264  cpl_image* ima_ybackpix=NULL;
265  cpl_image* ima_diffbackpix=NULL;
266  cpl_image* ima_filt=NULL;
267  cpl_image* ima = NULL;
268 
269  cpl_matrix* filter=NULL;
270  //cpl_mask* bpm_good=NULL; //Is this really useful?
271  cpl_mask* bpm_bad=NULL;
272 
273  int sx=0;
274  int sy=0;
275  int i=0;
276  int j=0;
277  int k=0;
278  double med_back=0;
279  double sigma_back=0;
280  double medvalue=0;
281 
282  float* pima=NULL;
283  float* ppix=NULL;
284  float* pmsk=NULL;
285  int* ppos=NULL;
286  int* pbackpix=NULL;
287  cpl_binary* pbin=NULL;
288  double tot=0;
289  double mean=0;
290  int* ybad=NULL;
291 
292  int nrow=0;
293  int nbad=0;
294  int yval=0;
295  int yprev=0;
296 
297 
298  check_nomsg(sx=cpl_image_get_size_x(ima_in));
299  check_nomsg(sy=cpl_image_get_size_y(ima_in));
300  check_nomsg(*ima_out=cpl_image_duplicate(ima_in));
301 
302  check_nomsg(mask=cpl_image_new(sx,sy,CPL_TYPE_FLOAT));
303  check_nomsg(pmsk=cpl_image_get_data_float(mask));
304 
305  for(i=0;i<width;i++) {
306  for(j=width;j<sy-width;j++) {
307  pmsk[j*sx+i]=1;
308  }
309  }
310 
311  for(i=sx-width;i<sx;i++) {
312  for(j=width;j<sy-width;j++) {
313  pmsk[j*sx+i]=1;
314  }
315  }
316  sinfo_free_image(&mask); //is mask needed?
317 
318 
319  nrow=2*width*(sy-2*width);
320  check_nomsg(ima_backpix=cpl_image_new(nrow,1,CPL_TYPE_FLOAT));
321  check_nomsg(ima_backpos=cpl_image_new(nrow,1,CPL_TYPE_INT));
322 
323  check_nomsg(pima=cpl_image_get_data_float(ima_in));
324  check_nomsg(ppix=cpl_image_get_data_float(ima_backpix));
325  check_nomsg(ppos=cpl_image_get_data_int(ima_backpos));
326 
327  k=0;
328  for(i=0;i<width;i++) {
329  for(j=width;j<sy-width;j++) {
330  ppix[k]=pima[j*sx+i];
331  ppos[k]=j*sx+i;
332  k++;
333  }
334  }
335 
336  for(i=sx-width;i<sx;i++) {
337  for(j=width;j<sy-width;j++) {
338  ppix[k]=pima[j*sx+i];
339  ppos[k]=j*sx+i;
340  k++;
341  }
342  }
343 
344  check_nomsg(ima_ybackpix=cpl_image_duplicate(ima_backpos));
345  sinfo_free_image(&ima_backpos);
346 
347  check_nomsg(pbackpix=cpl_image_get_data_int(ima_ybackpix));
348 
349  check_nomsg(cpl_image_divide_scalar(ima_ybackpix,sx));
350  check_nomsg(pbackpix=cpl_image_get_data_int(ima_ybackpix));
351 
352 
353  check_nomsg(med_back=cpl_image_get_median(ima_backpix));
354  check_nomsg(ima_diffbackpix=cpl_image_duplicate(ima_backpix));
355  //sinfo_msg("med_back=%g",med_back);
356  check_nomsg(cpl_image_subtract_scalar(ima_diffbackpix,med_back));
357  //check_nomsg(cpl_image_save(ima_diffbackpix,"ima_diff.fits",
358  // CPL_BPP_IEEE_FLOAT,NULL,CPL_IO_DEFAULT));
359 
360  check_nomsg(filter=cpl_matrix_new(1,filt_rad));
361  check_nomsg(cpl_matrix_fill(filter,1.));
362  check_nomsg(ima_filt=sinfo_image_filter_median(ima_diffbackpix,filter));
363  sinfoni_free_matrix(&filter);
364  //check_nomsg(cpl_image_save(ima_filt,"ima_filt.fits",CPL_BPP_IEEE_FLOAT,
365  // NULL,CPL_IO_DEFAULT));
366 
367 
368  check_nomsg(sigma_back=cpl_image_get_stdev(ima_filt));
369  sinfo_free_image(&ima_filt);
370 
371  check_nomsg(ima=cpl_image_duplicate(ima_diffbackpix));
372  sinfo_free_image(&ima_diffbackpix);
373 
374  check_nomsg(cpl_image_abs(ima));
375  //sinfo_msg("sigma_back=%g",sigma_back);
376 
377  //find good pixels
378  check_nomsg(bpm_bad=cpl_mask_threshold_image_create(ima,kappa*sigma_back,
379  SINFO_DBL_MAX));
380  /*check_nomsg(bpm_good=cpl_mask_threshold_image_create(ima,SINFO_DBL_MIN,
381  kappa*sigma_back));
382  sinfo_free_mask(&bpm_good);
383  */
384  check_nomsg(cpl_image_reject_from_mask(ima_backpix,bpm_bad));
385  check_nomsg(medvalue=cpl_image_get_median(ima_backpix));
386  //sinfo_msg("medvalue=%g",sigma_back);
387  check_nomsg(nbad=cpl_mask_count(bpm_bad));
388  //sinfo_msg("nbad=%d",nbad);
389  check_nomsg(cpl_image_reject_from_mask(ima_backpix,bpm_bad));
390  sinfo_free_image(&ima_backpix);
391 
392  yprev=-1;
393 
394  check_nomsg(pbin=cpl_mask_get_data(bpm_bad));
395  check_nomsg(pbackpix=cpl_image_get_data_int(ima_ybackpix));
396  cpl_msg_debug(cpl_func, "%d lines detected", nbad);
397  if(nbad)
398  {
399 
400  ybad = cpl_calloc(nbad,sizeof(int));
401  k=0;
402 
403  for(i=0;i<nrow;i++) {
404  if(pbin[i] == CPL_BINARY_1) {
405  ybad[k]=pbackpix[i] + 1;
406  k++;
407  }
408  }
409  sinfo_free_mask(&bpm_bad);
410  sinfo_free_image(&ima_ybackpix);
411 
412  quicksort_int(&(ybad[0]), 0, nbad-1);
413  yprev=-1;
414  for(k=0;k<nbad;k++) {
415  yval=ybad[k];
416  if(yval == yprev) {
417  sinfo_msg_debug("skyp %d",yval);
418  }
419  else {
420  yprev=yval;
421  sinfo_msg_debug("correct raw %d",yval);
422  check_nomsg(tot=cpl_image_get_flux_window(ima_in,1,yval,width,yval));
423  check_nomsg(tot+=cpl_image_get_flux_window(ima_in,sx-width+1,
424  yval,sx,yval));
425  mean=tot/(2. * width);
426  check_nomsg(pima=cpl_image_get_data_float(*ima_out));
427  for(i=width;i<sx-width;i++) {
428  pima[i+(yval-1)*sx]+=(float)(mean-medvalue);
429  }
430 
431  }
432  }
433  }
434 
435 
436  cleanup:
437 
438  sinfo_free_image(&mask); //is mask needed?
439  sinfo_free_image(&ima_backpos);
440  sinfoni_free_matrix(&filter);
441  sinfo_free_image(&ima_filt);
442  sinfo_free_image(&ima_diffbackpix);
443  // sinfo_free_mask(&bpm_good);
444  sinfo_free_image(&ima_backpix);
445  sinfo_free_mask(&bpm_bad);
446  sinfo_free_image(&ima_ybackpix);
447  cpl_image_delete(ima);
448  cpl_free(ybad);
449  return cpl_error_get_code();
450 
451 }
452 
453 
462 double sinfo_new_my_median_image(cpl_image* im)
463 {
464  double m=0;
465  register int i=0;
466  int n=0;
467  pixelvalue* pv=0;
468  int ilx=0;
469  int ily=0;
470  float* pidata=NULL;
471 
472 
473  if(im==NULL) sinfo_msg_error("Null Image");
474  ilx=cpl_image_get_size_x(im);
475  ily=cpl_image_get_size_y(im);
476  pidata=cpl_image_get_data_float(im);
477 
478  for ( i = 0 ; i < (int) ilx*ily ; i++ )
479  {
480  if ( isnan(pidata[i]) )
481  {
482 
483  } else {
484  n++;
485  }
486  }
487  pv = cpl_calloc(n,sizeof(pixelvalue));
488  n=0;
489  for ( i = 0 ; i < (int) ilx*ily ; i++ )
490  {
491  if ( isnan(pidata[i]) )
492  {
493 
494  } else {
495  pv[n]=pidata[i];
496  n++;
497  }
498  }
499  if(pv == NULL || n == 0) {
500  m=0;
501  } else {
502  m=sinfo_new_median(pv,n);
503  }
504  cpl_free(pv);
505  if(isnan(m)){
506  m=0;
507  }
508  return m;
509 }
510 
519 Vector * sinfo_new_mean_of_columns( cpl_image *im )
520 {
521  Vector * row=NULL ;
522  int i=0;
523  int j=0;
524  int ilx=0;
525  int ily=0;
526  float* pidata=NULL;
527 
528  if ( im == NULL )
529  {
530  sinfo_msg_error ("null image") ;
531  return NullVector ;
532  }
533  ilx=cpl_image_get_size_x(im);
534  ily=cpl_image_get_size_y(im);
535  pidata=cpl_image_get_data_float(im);
536 
537  /* allocate memory for a row with the length of the image x-axis */
538  if ( NULL == (row = sinfo_new_vector (ilx)) )
539  {
540  sinfo_msg_error ("not able to allocate a sinfo_vector" ) ;
541  return NullVector ;
542  }
543 
544  for ( i = 0 ; i < ilx ; i++ )
545  {
546  for ( j = 0 ; j < ily ; j++ )
547  {
548  if (!isnan(pidata[i+j*ilx]))
549  {
550  row->data[i] += pidata[i + j*(ilx)] ;
551  }
552  }
553 
554  row->data[i] /= ily ;
555  }
556  return row ;
557 }
569 cpl_image * sinfo_new_clean_mean_of_columns( cpl_image *im,
570  float lo_reject,
571  float hi_reject)
572 {
573  cpl_image * row=NULL ;
574  pixelvalue* buffer=NULL ;
575  int i=0;
576  int j=0;
577  int k=0;
578  int nv=0;
579  int lo_n=0;
580  int hi_n=0;
581  int ilx=0;
582  int ily=0;
583  float* pidata=NULL;
584  float* podata=NULL;
585 
586  if ( im == NULL )
587  {
588  sinfo_msg_error ("null image") ;
589  return NULL ;
590  }
591  ilx=cpl_image_get_size_x(im);
592  ily=cpl_image_get_size_y(im);
593  pidata=cpl_image_get_data_float(im);
594 
595  if ((lo_reject + hi_reject) > 0.9)
596  {
597  sinfo_msg_error("illegal rejection thresholds: [%f] and [%f]",
598  lo_reject, hi_reject) ;
599  sinfo_msg_error("threshold sum should not be over "
600  "0.90 aborting average") ;
601  return NULL ;
602  }
603 
604  lo_n = (int) (ily * lo_reject + 0.5) ;
605  hi_n = (int) (ily * hi_reject + 0.5) ;
606  if (lo_n + hi_n >= ily)
607  {
608  sinfo_msg_error ("everything would be rejected") ;
609  return NULL ;
610  }
611 
612  /* allocate memory for a row with the length of the image x-axis */
613  if ( NULL == (row = cpl_image_new (ilx, 1,CPL_TYPE_FLOAT)) )
614  {
615  sinfo_msg_error ("cannot allocate new image") ;
616  return NULL ;
617  }
618  podata=cpl_image_get_data_float(row);
619 
620  buffer=(pixelvalue*) cpl_calloc(ily,sizeof(pixelvalue)) ;
621 
622  for ( i = 0 ; i < ilx ; i++ )
623  {
624  for ( j = 0 ; j < ily ; j++ )
625  {
626  buffer[j] = pidata[i + j*(ilx)] ;
627  }
628  sinfo_pixel_qsort (buffer, ily) ;
629 
630  nv = 0 ;
631  for (k = lo_n ; k < ily - hi_n ; k ++)
632  {
633  if ( !isnan(buffer[k]) )
634  {
635  podata[i] += buffer[k] ;
636  nv ++ ;
637  }
638  }
639  podata[i] /= nv ;
640 
641  }
642  cpl_free(buffer);
643  return row ;
644 }
645 
646 
656 cpl_image * sinfo_new_div_image_by_row( cpl_image *im, Vector *row )
657 {
658  cpl_image *image=NULL ;
659  int i=0;
660  int j=0;
661  int ilx=0;
662  int ily=0;
663  float* pidata=NULL;
664  float* podata=NULL;
665 
666  if ( im == NULL || row == NULL )
667  {
668  sinfo_msg_error ("null image or null row") ;
669  return NULL ;
670  }
671  ilx=cpl_image_get_size_x(im);
672  ily=cpl_image_get_size_y(im);
673  pidata=cpl_image_get_data_float(im);
674 
675  if ( ilx != row -> n_elements )
676  {
677  sinfo_msg_error("image and row size not compatible") ;
678  return NULL ;
679  }
680 
681  if ( NULL == (image = cpl_image_duplicate (im)) )
682  {
683  sinfo_msg_error ("cannot copy image") ;
684  return NULL ;
685  }
686  podata=cpl_image_get_data_float(image);
687 
688  for (i = 0 ; i < ilx ; i++ )
689  {
690  for (j = 0 ; j < ily ; j++)
691  {
692  if ( !isnan(pidata[i + j*(ilx)]) )
693  {
694  podata[i + j*(ilx)] = pidata[i + j*(ilx)] / row -> data[i] ;
695  }
696  }
697  }
698  return image ;
699 }
700 
701 
711 cpl_image * sinfo_new_mult_row_to_image( cpl_image *im, Vector *row )
712 {
713  cpl_image *image=NULL;
714  int i=0;
715  int j=0;
716  int ilx=0;
717  int ily=0;
718  float* pidata=NULL;
719  float* podata=NULL;
720 
721 
722 
723 
724  if ( im == NULL || row == NULL )
725  {
726  sinfo_msg_error ("null image or null row") ;
727  return NULL ;
728  }
729  ilx=cpl_image_get_size_x(im);
730  ily=cpl_image_get_size_y(im);
731  pidata=cpl_image_get_data_float(im);
732 
733  if ( ilx != row -> n_elements )
734  {
735  sinfo_msg_error("image and row size not compatible") ;
736  return NULL ;
737  }
738 
739  if ( NULL == (image = cpl_image_duplicate (im)) )
740  {
741  sinfo_msg_error ("cannot copy image") ;
742  return NULL ;
743  }
744  podata=cpl_image_get_data_float(image);
745 
746  for (i = 0 ; i < ilx ; i++ )
747  {
748  for (j = 0 ; j < ily ; j++)
749  {
750  if ( !isnan(pidata[i + j*(ilx)]) )
751  {
752  podata[i + j*(ilx)] = pidata[i + j*(ilx)] * row -> data[i] ;
753  }
754  }
755  }
756  return image ;
757 }
758 
759 
760 
761 
762 
763 
787 cpl_image * sinfo_new_col_tilt ( cpl_image * image, float sigmaFactor )
788 {
789  cpl_image * im=NULL;
790  float * column=NULL ;
791  double sum=0;
792  double sum2=0;
793  double mean=0;
794  float sinfo_median=0;
795  float noise=0 ;
796  float * sig=NULL;
797  float * dat=NULL;
798  float a=0;
799  float b=0;
800  float siga=0;
801  float sigb=0;
802  float chi2=0;
803  float q=0;
804  int i=0;
805  int j=0;
806  int colnum=0;
807  int npix=0;
808  int mwt=0 ;
809  int lx=0;
810  int ly=0;
811  float* p_in_data=NULL;
812  float* p_ou_data=NULL;
813 
814 
815  if ( image == NULL )
816  {
817  sinfo_msg_error ("no image given" ) ;
818  return NULL ;
819  }
820 
821  if ( sigmaFactor <= 0. )
822  {
823  sinfo_msg_error ("no or negative sigma factor") ;
824  return NULL ;
825  }
826  lx = cpl_image_get_size_x(image);
827  ly = cpl_image_get_size_y(image);
828 
829 
830  /* allocate memory */
831  if ( NULL == (im = cpl_image_new (lx,ly,CPL_TYPE_FLOAT )) )
832  {
833  sinfo_msg_error ("cannot allocate new image" ) ;
834  return NULL ;
835  }
836 
837  /* go through the columns */
838  p_in_data = cpl_image_get_data_float(image);
839  p_ou_data = cpl_image_get_data_float(im);
840  for ( i = 0 ; i < lx ; i ++ )
841  {
842  /* initialize the buffer variables for each column */
843  colnum = 0 ;
844  column = (float *) cpl_calloc ( ly , sizeof (float *) ) ;
845  sig = (float *) cpl_calloc ( ly , sizeof (float *) ) ;
846  dat = (float *) cpl_calloc ( ly , sizeof (float *) ) ;
847 
848  /*select only non-ZERO values of one column*/
849  for ( j = 0 ; j < ly ; j++ )
850  {
851  if ( !isnan(p_in_data[i + j*lx]) )
852  {
853  column[j] = p_in_data[i + j*lx] ;
854  colnum ++ ;
855  }
856  }
857  if ( colnum < 10 )
858  {
859  /*sinfo_msg_warning ("sinfo_new_col_tilt:",
860  "column %d has almost only blank pixels and is set to blank", i+1) ;*/
861  for ( j = 0 ; j < ly ; j++ )
862  {
863  p_ou_data[i + j*lx] = ZERO;
864  }
865  /*
866  cpl_free (column) ;
867  cpl_free (sig);
868  cpl_free (dat) ;
869  continue ;
870  */
871  }
872 
873  /*-------------------------------------------------------------------
874  * sort the data, clip off the extremes, determine the noise
875  * and get the range for the valid data. It is assumed here
876  * that most pixels are o.k.
877  */
878 
879  sinfo_pixel_qsort (column, colnum) ;
880 
881  sum = 0. ;
882  sum2 = 0. ;
883  npix = 0 ;
884 
885  for ( j = 0.1*colnum + 1 ; j <= 0.9*colnum ; j++ )
886  {
887  sum += column[j] ;
888  sum2 += column[j] * column[j] ;
889  npix ++ ;
890  }
891 
892  if (npix <= 1)
893  {
894  noise = sigmaFactor * 1000.;
895  }
896  else
897  {
898  mean = sum/(float)npix ;
899  noise = sqrt( (sum2 - sum*mean)/(double)(npix -1) ) ;
900  noise *= sigmaFactor ;
901  }
902 
903  /* -------------------------------------------------------------
904  * determine sinfo_median if colnum is odd, sinfo_median will be the
905  colnum/2 th value, otherwise
906  * sinfo_median is the mean of colnum/2-1 th and colnum/2 th value.
907  */
908 
909  if ( colnum % 2 == 1 )
910  {
911  sinfo_median = column[colnum/2] ;
912  }
913  else
914  {
915  sinfo_median = (column[colnum/2 - 1] + column[colnum/2])/2. ;
916  }
917 
918  /* now select the pixels for the tilt calculation */
919 
920  colnum = 0 ;
921  for ( j = 0; j < ly ; j ++ )
922  {
923  if ( !isnan(p_in_data[i+j*lx]) &&
924  fabs ( (p_in_data[i+j*lx]) - sinfo_median) <= noise )
925  {
926  column[colnum] = p_in_data[i+j*lx] ;
927  dat[colnum] = (float) j ;
928  sig[colnum] = 1. ;
929  colnum ++ ;
930  }
931  }
932 
933  if ( colnum == 0 )
934  {
935  /*for ( j = 0; j < ly; j++ )
936  {
937  p_ou_data[i+j*lx] -= sinfo_median ;
938  }
939  cpl_free (column) ;
940  cpl_free (sig) ;
941  cpl_free (dat) ;
942  continue ;*/
943  a=0./0.;
944  b=0./0.;
945  }
946  else
947  {
948  mwt = 0 ;
949  sinfo_my_fit ( dat, column, colnum, sig, mwt, &a,
950  &b, &siga, &sigb, &chi2, &q ) ;
951  }
952  if ( fabs(b) >= SLOPE || fabs(a) >= SATURATION ||
953  isnan(b) || isnan(a))
954  {
955  sinfo_msg_warning ("linear fit: slope is greater than limit: %f"
956  " saturation level is reached: %f in column"
957  " number %d ", b, a , i+1) ;
958  }
959 
960  /* subtract fit or sinfo_median from data */
961  for ( j = 0; j < ly; j++ )
962  {
963  if ( !isnan(p_in_data[i+j*lx]) &&
964  fabs(b) < SLOPE && fabs(a) < SATURATION )
965  {
966  p_ou_data[i+j*lx] = p_in_data[i+j*lx] - (a + b * (float)j) ;
967  }
968  else if ( isnan(p_in_data[i+j*lx]) )
969  {
970  p_ou_data[i+j*lx] = ZERO ;
971  }
972  else if ( (fabs(b) >= SLOPE ||
973  fabs(a) >= SATURATION || isnan(a) || isnan(b)) &&
974  !isnan(p_in_data[i+j*lx]) )
975  {
976  p_ou_data[i+j*lx] -= sinfo_median ;
977  }
978  else
979  {
980  sinfo_msg_error (" case is not possible! %f %f", b,a) ;
981  /*cpl_free (column) ;
982  cpl_free (sig) ;
983  cpl_free (dat) ;
984  cpl_image_delete(im) ;
985  return NULL ;*/
986  }
987  }
988  cpl_free (column) ;
989  cpl_free (sig) ;
990  cpl_free (dat) ;
991  }
992 
993  return im ;
994 }
995 
996 
997 
998 
999 
1023 cpl_image * sinfo_new_median_image( cpl_image * im, float fmedian )
1024 {
1025  cpl_image * image=NULL ;
1026  pixelvalue * value=NULL ;
1027  pixelvalue sinfo_median=0 ;
1028  int * position=NULL ;
1029  int nposition=0 ;
1030  int n=0;
1031  int i=0;
1032  int j=0;
1033  int lx=0;
1034  int ly=0;
1035  float* p_in_data=NULL;
1036  float* p_ou_data=NULL;
1037  int im_size=0;
1038  if ( im == NULL )
1039  {
1040  sinfo_msg_error ("no image input") ;
1041  return NULL ;
1042  }
1043 
1044  image = cpl_image_duplicate ( im ) ;
1045  lx=cpl_image_get_size_x(im);
1046  ly=cpl_image_get_size_y(im);
1047  im_size=lx*ly;
1048  p_in_data=cpl_image_get_data_float(im);
1049  p_ou_data=cpl_image_get_data_float(image);
1050 
1051  /*----------------------------------------------------------------------
1052  * go through all pixels
1053  */
1054 
1055  for ( i = 0 ; i < im_size ; i++ )
1056  {
1057  /* blank pixels are not replaced */
1058  if ( isnan(p_in_data[i]) )
1059  {
1060  continue ;
1061  }
1062 
1063  /* initialize the buffer variables for the 8 nearest neighbors */
1064  value = (pixelvalue * )cpl_calloc ( 8, sizeof ( pixelvalue * ) ) ;
1065  position = ( int * ) cpl_calloc ( 8, sizeof ( int * ) ) ;
1066 
1067  /*--------------------------------------------------------------------
1068  * determine the pixel position of the 8 nearest neighbors
1069  */
1070 
1071  position[0] = i + lx - 1 ; /* upper left */
1072  position[1] = i + lx ; /* upper */
1073  position[2] = i + lx + 1 ; /* upper right */
1074  position[3] = i + 1 ; /* right */
1075  position[4] = i - lx + 1 ; /* lower right */
1076  position[5] = i - lx ; /* lower */
1077  position[6] = i - lx - 1 ; /* lower left */
1078  position[7] = i - 1 ; /* left */
1079 
1080  /*-------------------------------------------------------------------
1081  * determine the positions of the image margins, top positions are
1082  changed to low positions and vice versa. Right positions are
1083  changed to left positions and vice versa.
1084  */
1085 
1086  if ( i >= 0 && i < lx ) /* bottom line */
1087  {
1088  position[4] += 2 * lx ;
1089  position[5] += 2 * lx ;
1090  position[6] += 2 * lx ;
1091  }
1092  else if ( i >= ((int) lx*ly - lx ) && i < (int) lx*ly ) /* top line */
1093  {
1094  position[0] -= 2 * lx ;
1095  position[1] -= 2 * lx ;
1096  position[2] -= 2 * lx ;
1097  }
1098  else if ( i % lx == 0 ) /* left side */
1099  {
1100  position[0] += 2 ;
1101  position[6] += 2 ;
1102  position[7] += 2 ;
1103  }
1104  else if ( i % lx == lx - 1 ) /* right side */
1105  {
1106  position[2] -= 2 ;
1107  position[3] -= 2 ;
1108  position[4] -= 2 ;
1109  }
1110 
1111  /* --------------------------------------------------------------------
1112  * read the pixel values of the neighboring pixels,
1113  * blanks are not considered
1114  */
1115 
1116  nposition = 8 ;
1117  n = 0 ;
1118  for ( j = 0 ; j < nposition ; j ++ )
1119  {
1120  if((position[j] >-1 ) && (position[j]<im_size)) {
1121  if ( !isnan(p_in_data[position[j]]) )
1122  {
1123  value[n] = p_in_data[position[j]] ;
1124  n ++ ;
1125  }
1126  }
1127  }
1128  nposition = n ;
1129 
1130  if ( nposition <= 1 ) /* almost all neighbors are blank */
1131  {
1132  p_ou_data[i] = ZERO ;
1133  cpl_free(value) ;
1134  cpl_free(position) ;
1135  continue ;
1136  }
1137 
1138  /* sort the values and determine the sinfo_median */
1139 
1140  sinfo_pixel_qsort ( value, nposition ) ;
1141  if ( nposition % 2 == 1 )
1142  {
1143  sinfo_median = value [ nposition/2 ] ;
1144  }
1145  else
1146  {
1147  sinfo_median = ( value [nposition/2 - 1] +
1148  value [nposition/2] ) / 2. ;
1149  }
1150 
1151  /* -----------------------------------------------------------------
1152  * replace the pixel value by the sinfo_median on conditions:
1153  * fmedian = 0: always replace with sinfo_median.
1154  * fmedian < 0: interpret as absolute condition:
1155  * if |pixel - sinfo_median| > -fmedian
1156  * replace with sinfo_median.
1157  * fmedian > 0: replace by sinfo_median (fmedian as a factor of
1158  * the square root of the sinfo_median itself)
1159  * if |pixel - sinfo_median| >= fmedian *
1160  sqrt ( sinfo_median )
1161  * considers a dependence on the pixel value.
1162  * This can be used to consider photon noise.
1163  */
1164 
1165  if ( fmedian == 0 )
1166  {
1167  p_ou_data[i] = sinfo_median ;
1168  }
1169  else if ( fmedian < 0 &&
1170  fabs ( sinfo_median - p_in_data[i] ) >= -fmedian )
1171  {
1172  p_ou_data[i] = sinfo_median ;
1173  }
1174  else if ( fmedian > 0 &&
1175  fabs ( sinfo_median - p_in_data[i] ) >= fmedian *
1176  sqrt(fabs(sinfo_median)) )
1177  {
1178  p_ou_data[i] = sinfo_median ;
1179  }
1180  else
1181  {
1182  cpl_free (value) ;
1183  cpl_free (position) ;
1184  continue ;
1185  }
1186 
1187  cpl_free (value) ;
1188  cpl_free (position) ;
1189  }
1190  return image ;
1191 }
1192 
1193 
1194 
1195 
1206 cpl_image *
1207 sinfo_new_compare_images(cpl_image * im1,cpl_image * im2,cpl_image * origim )
1208 {
1209  cpl_image * image=NULL ;
1210  int i=0 ;
1211  int lx1=0;
1212  int ly1=0;
1213  int lx2=0;
1214  int ly2=0;
1215  float* p_in1_data=NULL;
1216  float* p_in2_data=NULL;
1217  float* p_ou_data=NULL;
1218  float* p_org_data=NULL;
1219 
1220 
1221  if ( im1 == NULL || im2 == NULL || origim == NULL )
1222  {
1223  sinfo_msg_error ("Null images as input" ) ;
1224  return NULL ;
1225  }
1226  lx1=cpl_image_get_size_x(im1);
1227  ly1=cpl_image_get_size_y(im1);
1228 
1229  lx2=cpl_image_get_size_x(im2);
1230  ly2=cpl_image_get_size_y(im2);
1231 
1232  p_in1_data=cpl_image_get_data_float(im1);
1233  p_in2_data=cpl_image_get_data_float(im2);
1234  p_org_data=cpl_image_get_data_float(origim);
1235  if ( lx1 != lx2 || ly1 != ly2 )
1236  {
1237  sinfo_msg_error ("incompatible image sizes" ) ;
1238  return NULL ;
1239  }
1240 
1241  /* allocate memory */
1242  if ( NULL == (image = cpl_image_new ( lx1, ly1, CPL_TYPE_FLOAT )) )
1243  {
1244  sinfo_msg_error ("cannot allocate new image" ) ;
1245  return NULL ;
1246  }
1247  p_ou_data=cpl_image_get_data_float(image);
1248  for ( i = 0 ; i < (int) lx1*ly1 ; i ++ )
1249  {
1250  if ( isnan(p_in1_data[i]) && isnan(p_in2_data[i]) )
1251  {
1252  p_ou_data[i] = ZERO ;
1253  }
1254  else
1255  {
1256  if ( p_in1_data[i] == p_in2_data[i] )
1257  {
1258  p_ou_data[i] = p_org_data[i] ;
1259  }
1260  else
1261  {
1262  p_ou_data[i] = ZERO ;
1263  }
1264  }
1265  }
1266  return image ;
1267 }
1268 
1269 
1270 
1282 cpl_image *
1283 sinfo_new_promote_image_to_mask (cpl_image * im, int * n_badpixels )
1284 {
1285  cpl_image * reImage=NULL ;
1286  int i=0 ;
1287  int lx=0;
1288  int ly=0;
1289  float* p_in_data=NULL;
1290  float* p_ou_data=NULL;
1291 
1292  if ( NULL == im )
1293  {
1294  sinfo_msg_error("no input image given!") ;
1295  return NULL ;
1296  }
1297  lx=cpl_image_get_size_x(im);
1298  ly=cpl_image_get_size_y(im);
1299  p_in_data=cpl_image_get_data_float(im);
1300 
1301  /* allocate memory for the returned image */
1302  if ( NULL == (reImage = cpl_image_new (lx,ly,CPL_TYPE_FLOAT )) )
1303  {
1304  sinfo_msg_error ("cannot allocate new image!") ;
1305  return NULL ;
1306  }
1307  p_ou_data=cpl_image_get_data_float(reImage);
1308 
1309  *n_badpixels = 0 ;
1310  for ( i = 0 ; i < (int) lx*ly ; i ++ )
1311  {
1312  if ( isnan(p_in_data[i]) )
1313  {
1314  p_ou_data[i] = 0. ;
1315  (*n_badpixels)++ ;
1316  }
1317  else
1318  {
1319  p_ou_data[i] = 1. ;
1320  }
1321  }
1322  return reImage ;
1323 }
1324 
1325 
1336 cpl_image * sinfo_new_mult_image_by_mask (cpl_image * im,cpl_image * mask )
1337 {
1338  cpl_image * reImage=NULL ;
1339  int i=0 ;
1340  int ix=0;
1341  int iy=0;
1342  int mx=0;
1343  int my=0;
1344 
1345 
1346  float* pmdata=NULL;
1347  float* podata=NULL;
1348 
1349  if ( NULL == im )
1350  {
1351  sinfo_msg_error("no input image given!") ;
1352  return NULL ;
1353  }
1354  if ( NULL == mask )
1355  {
1356  sinfo_msg_error("no mask image given!") ;
1357  return NULL ;
1358  }
1359  ix=cpl_image_get_size_x(im);
1360  iy=cpl_image_get_size_y(im);
1361  mx=cpl_image_get_size_x(mask);
1362  my=cpl_image_get_size_y(mask);
1363 
1364  if ( ix != mx || iy != my)
1365  {
1366  sinfo_msg_error("image sizes are not correspondent!") ;
1367  return NULL ;
1368  }
1369 
1370  reImage = cpl_image_duplicate( im ) ;
1371  podata=cpl_image_get_data_float(reImage);
1372  pmdata=cpl_image_get_data_float(mask);
1373 
1374  for ( i = 0 ; i < (int) ix*iy ; i ++ )
1375  {
1376  if ( pmdata[i] == 0. )
1377  {
1378  podata[i] = ZERO ;
1379  }
1380  }
1381 
1382  return reImage ;
1383 }
1384 
1385 
1386 
1396 cpl_image *
1397 sinfo_new_thresh_image (cpl_image * im, float lo_cut, float hi_cut )
1398 {
1399  cpl_image * image=NULL ;
1400  float* p_inp_data=NULL;
1401  float* p_out_data=NULL;
1402  int lx=0;
1403  int ly=0;
1404 
1405  int i=0 ;
1406 
1407  if (im == NULL)
1408  {
1409  sinfo_msg_error ("null image given") ;
1410  return NULL ;
1411  }
1412  lx=cpl_image_get_size_x(im);
1413  ly=cpl_image_get_size_y(im);
1414 
1415  image = cpl_image_duplicate(im) ;
1416  p_inp_data=cpl_image_get_data(im);
1417  p_out_data=cpl_image_get_data(image);
1418  for ( i = 0 ; i < (int) lx*ly ; i ++ )
1419  {
1420  if ( p_inp_data[i] > (pixelvalue) hi_cut ||
1421  p_inp_data[i] < (pixelvalue) lo_cut )
1422  {
1423  p_out_data[i] = ZERO ;
1424  }
1425  }
1426  return image ;
1427 }
1428 
1429 
1430 
1431 
1456 cpl_image * sinfo_new_interpol_image ( cpl_image * im,
1457  cpl_image * mask,
1458  int max_radius,
1459  int n_pixels )
1460 {
1461  cpl_image * returnImage=NULL ;
1462  float* neighbors=NULL ;
1463  float sum=0;
1464  float mean=0;
1465  int i=0;
1466  int j=0;
1467  int k=0;
1468  int row=0;
1469  int col=0;
1470  int n_valid=0;
1471  int agreed=0;
1472 
1473  int ilx=0;
1474  int ily=0;
1475  int mlx=0;
1476  int mly=0;
1477  float* pidata=NULL;
1478  float* podata=NULL;
1479  float* pmdata=NULL;
1480 
1481  if ( NULL == im )
1482  {
1483  sinfo_msg_error("sorry, no input image given!") ;
1484  return NULL ;
1485  }
1486  ilx=cpl_image_get_size_x(im);
1487  ily=cpl_image_get_size_y(im);
1488  pidata=cpl_image_get_data_float(im);
1489 
1490  if ( NULL == mask )
1491  {
1492  sinfo_msg_error("sorry, no mask image given!") ;
1493  return NULL ;
1494  }
1495 
1496  mlx=cpl_image_get_size_x(mask);
1497  mly=cpl_image_get_size_y(mask);
1498  pmdata=cpl_image_get_data_float(mask);
1499 
1500  if ( mlx != ilx || mly != ily )
1501  {
1502  sinfo_msg_error("images not compatible !") ;
1503  return NULL ;
1504  }
1505 
1506  if ( max_radius <= 0 )
1507  {
1508  sinfo_msg_error("wrong number of pixels for maximal "
1509  "search radius given!") ;
1510  return NULL ;
1511  }
1512 
1513  if ( n_pixels <= 2 )
1514  {
1515  sinfo_msg_error("wrong number of pixels used "
1516  "for interpolation given!") ;
1517  return NULL ;
1518  }
1519 
1520  returnImage = cpl_image_duplicate ( im ) ;
1521  podata=cpl_image_get_data_float(returnImage);
1522 
1523  /* go through the columns and rows of the input and mask image */
1524  neighbors=cpl_calloc(4*max_radius*max_radius,sizeof(float)) ;
1525 
1526  for ( col = 0 ; col < ilx ; col++ )
1527  {
1528  for ( row = 0 ; row < ily ; row++ )
1529  {
1530  /* look for the ZEROS that means the detected bad pixels */
1531  if ( isnan(pmdata[col+row*ilx]) || pmdata[col+row*ilx] == 0. )
1532  {
1533  /* now the neighbors must be considered */
1534  n_valid = 0 ;
1535  agreed = 0 ;
1536  for ( j = 1 ; j <= max_radius ; j++ )
1537  {
1538 
1539  /* go through the left column */
1540  for ( k = -j ; k < j ; k++ )
1541  {
1542  if ( col-j >= 0 && row+k < ily && row+k >= 0 )
1543  {
1544  if ( !isnan(pmdata[col-j+(row+k)*mlx]) ||
1545  pmdata[col-j+(row+k)*mlx] != 0 )
1546  {
1547  neighbors[n_valid]=pidata[col-j+(row+k)*ilx] ;
1548  n_valid++ ;
1549  }
1550  }
1551  }
1552 
1553  /* go through the upper row */
1554  for ( k = -j ; k < j ; k++ )
1555  {
1556  if ( col+k < ilx && col+k >= 0 && row+j < ily )
1557  {
1558  if ( !isnan(pmdata[col+k+(row+j)*mlx]) ||
1559  pmdata[col+k+(row+j)*mlx] != 0. )
1560  {
1561  neighbors[n_valid]=pidata[col+k+(row+j)*ilx] ;
1562  n_valid++ ;
1563  }
1564  }
1565  }
1566 
1567  /* go through the right column */
1568  for ( k = -j ; k < j ; k++ )
1569  {
1570  if ( col+j < ilx && row-k >= 0 && row-k < ily )
1571  {
1572  if ( !isnan(pmdata[col+j+(row-k)*mlx]) ||
1573  pmdata[col+j+(row-k)*mlx] != 0. )
1574  {
1575  neighbors[n_valid]=pidata[col+j+(row-k)*ilx] ;
1576  n_valid++ ;
1577  }
1578  }
1579  }
1580 
1581  /* go through the lower row */
1582  for ( k = -j ; k < j ; k++ )
1583  {
1584  if ( col-k >= 0 && col-k < ilx && row-j < ily )
1585  {
1586  if ( !isnan(pmdata[col-k+(row-j)*mlx]) ||
1587  pmdata[col-k+(row-j)*mlx] != 0. )
1588  {
1589  neighbors[n_valid]=pidata[col-k+(row-j)*ilx] ;
1590  n_valid++ ;
1591  }
1592  }
1593  }
1594 
1595  /* control if the breaking criteria is fullfilled */
1596  if ( n_valid >= n_pixels )
1597  {
1598  agreed = 1 ;
1599  break ;
1600  }
1601  /* do a break if more than 2 nearest neighbors are found */
1602  if ( j == 1 && n_valid >= 2 )
1603  {
1604  agreed = 1 ;
1605  break ;
1606  }
1607  }
1608  if ( n_valid < n_pixels && agreed == 0 )
1609  {
1610  sinfo_msg_error("not enough valid neighbors found to "
1611  "interpolate bad pixel in col: "
1612  "%d, row: %d", col, row ) ;
1613  return NULL ;
1614  }
1615  else
1616  {
1617  /* ------------------------------------------------------
1618  * take the mean of the valid neighboring pixels if less
1619  * than 9 valid pixels are available else take the
1620  sinfo_median.
1621  */
1622  if ( n_valid <= 8 )
1623  {
1624  sum = 0. ;
1625 
1626  for ( i = 0 ; i < n_valid ; i++ )
1627  {
1628  sum += neighbors[i] ;
1629  }
1630  mean = sum / n_valid ;
1631 
1632  podata[col+row*ilx] = mean ;
1633  }
1634  else
1635  {
1636  podata[col+row*ilx]=sinfo_new_median(neighbors,n_valid);
1637  }
1638  }
1639  }
1640  }
1641  }
1642  cpl_free(neighbors);
1643  return returnImage ;
1644 }
1645 
1646 
1669 cpl_image * sinfo_interpol_source_image ( cpl_image * im,
1670  cpl_image * mask,
1671  int max_rad,
1672  float ** slit_edges )
1673 {
1674  cpl_image * returnImage=NULL ;
1675  float validpixel[6] ;
1676  float sum=0 ;
1677  int n=0;
1678  int row=0;
1679  int col=0;
1680  int i=0;
1681  int k=0;
1682  int slitlet=0;
1683  int n_slitlets=0;
1684  int ilx=0;
1685  int ily=0;
1686  int mlx=0;
1687  int mly=0;
1688 
1689  float* pidata=NULL;
1690  float* podata=NULL;
1691  float* pmdata=NULL;
1692 
1693 
1694  if ( NULL == im )
1695  {
1696  sinfo_msg_error("sorry, no input image given!") ;
1697  return NULL ;
1698  }
1699  ilx=cpl_image_get_size_x(im);
1700  ily=cpl_image_get_size_y(im);
1701  pidata=cpl_image_get_data_float(im);
1702 
1703  if ( NULL == mask )
1704  {
1705  sinfo_msg_error("sorry, no bad pixel mask image given!") ;
1706  return NULL ;
1707  }
1708  mlx=cpl_image_get_size_x(mask);
1709  mly=cpl_image_get_size_y(mask);
1710  pmdata=cpl_image_get_data_float(mask);
1711 
1712  if ( mlx != ilx || mly != ily )
1713  {
1714  sinfo_msg_error("images not compatible in size!") ;
1715  return NULL ;
1716  }
1717 
1718  if ( max_rad < 1 )
1719  {
1720  sinfo_msg_error("sorry, wrong maximum distance given!") ;
1721  return NULL ;
1722  }
1723 
1724  if ( slit_edges == NULL )
1725  {
1726  sinfo_msg_error("sorry, array slit_edges is empty!") ;
1727  return NULL ;
1728  }
1729 
1730  /* determine the number of slitlets */
1731  n_slitlets = N_SLITLETS ;
1732 
1733  /* copy the original image in the image that will be returned */
1734  returnImage = cpl_image_duplicate( im ) ;
1735  podata=cpl_image_get_data_float(returnImage);
1736 
1737  /* go through the rows and columns of the image and search for
1738  the bad pixels */
1739  for ( row = 0 ; row < ily ; row++ )
1740  {
1741  for ( col = 0 ; col < ilx ; col++ )
1742  {
1743  n = 0 ;
1744  if ( isnan(pmdata[col + row*mlx]) ||
1745  pmdata[col + row*mlx] == 0. ||
1746  isnan(pidata[col + row*mlx]) )
1747  {
1748  /* look for the slitlet where the bad pixel is found */
1749  slitlet = -1000 ;
1750  for ( k = 0 ; k < n_slitlets ; k++ )
1751  {
1752  if ( sinfo_new_nint(slit_edges[k][0]) <= col &&
1753  sinfo_new_nint(slit_edges[k][1]) >= col )
1754  {
1755  slitlet = k ;
1756  }
1757  /* The following else statement is wrong, because in the
1758  end slitlet will always be -1000
1759  else
1760  {
1761  slitlet = -1000 ;
1762  }
1763  */
1764  }
1765  for ( i = 0 ; i < 6 ; i++ )
1766  {
1767  validpixel[i] = 0. ;
1768  }
1769  /* look for the valid nearest neighbors
1770  and collect them but only a maximum of 4 */
1771  for ( i = 1 ; i <= max_rad ; i++ )
1772  {
1773  if ( row + i < ily)
1774  {
1775  if ( !isnan(pmdata[col + (row+i) * mlx])
1776  && pmdata[col + (row+i) * mlx] != 0. &&
1777  !isnan(pidata[col + (row+i) * ilx]) )
1778  {
1779  validpixel[n] = pidata[col + (row+i) * ilx] ;
1780  n++ ;
1781  }
1782  }
1783  if ( row - i >= 0 )
1784  {
1785  if ( !isnan(pmdata[col + (row-i) * mlx])
1786  && pmdata[col + (row-i) * mlx] != 0. &&
1787  !isnan(pidata[col + (row-i) * ilx]) )
1788  {
1789  validpixel[n] = pidata[col + (row-i) * ilx] ;
1790  n++ ;
1791  }
1792  }
1793 
1794  /* be aware of the slitlet edges in the
1795  spatial direction */
1796  if ( col + i < ilx )
1797  {
1798  if ( slitlet != -1000 )
1799  {
1800  if (col+i <= sinfo_new_nint(slit_edges[slitlet][1]) &&
1801  !isnan(pmdata[col + i + row * mlx]) &&
1802  pmdata[col + i + row * mlx] != 0. &&
1803  !isnan(pidata[col + i + row * ilx]) )
1804  {
1805  validpixel[n] = pidata[col + i + row * ilx] ;
1806  n++ ;
1807  }
1808  }
1809  }
1810  if ( col - i >= 0 )
1811  {
1812  if ( slitlet != -1000 )
1813  {
1814  if (col-i >= sinfo_new_nint(slit_edges[slitlet][0]) &&
1815  !isnan(pmdata[col - i + row * mlx]) &&
1816  pmdata[col - i + row * mlx] != 0. &&
1817  !isnan(pidata[col - i + row * ilx]) )
1818  {
1819  validpixel[n] = pidata[col - i + row * ilx] ;
1820  n++ ;
1821  }
1822  }
1823  }
1824 
1825  if ( i == 1 && n > 1 )
1826  {
1827  break ;
1828  }
1829  if ( n > 2 )
1830  {
1831  break ;
1832  }
1833  }
1834 
1835  if ( n == 0 )
1836  {
1837  podata[col + row*ilx] = ZERO ;
1838  /*sinfo_msg_warning("sinfo_interpolSourceImage:",
1839  "bad pixel in column: %d and row: %d"
1840  " could not be interpolated!",col,row);
1841  */
1842  }
1843  else
1844  {
1845  /* now compute the mean and replace
1846  the bad pixel value by the mean */
1847  sum = 0. ;
1848  for ( i = 0 ; i < n ; i++ )
1849  {
1850  sum += validpixel[i] ;
1851  }
1852  podata[col + row*ilx] = sum/n ;
1853  }
1854  }
1855  }
1856  }
1857 
1858  return returnImage ;
1859 }
1860 
1870 cpl_image * sinfo_new_stack_row_to_image ( Vector * row, int ly )
1871 {
1872  cpl_image * image=NULL;
1873  int col=0;
1874  int ro=0;
1875  float* podata=NULL;
1876 
1877  if ( row == NullVector )
1878  {
1879  sinfo_msg_error ("Null sinfo_vector as input" ) ;
1880  return NULL ;
1881  }
1882  if ( ly <= 1 )
1883  {
1884  sinfo_msg_error ("wrong image length given" ) ;
1885  return NULL ;
1886  }
1887 
1888  /* allocate memory */
1889  if (NULL == (image = cpl_image_new(row->n_elements ,ly,CPL_TYPE_FLOAT )) )
1890  {
1891  sinfo_msg_error ("cannot allocate new image" ) ;
1892  return NULL ;
1893  }
1894  podata=cpl_image_get_data_float(image);
1895 
1896  for ( col = 0 ; col < row -> n_elements ; col++ )
1897  {
1898  for ( ro = 0 ; ro < ly ; ro++ )
1899  {
1900  podata[col + ro*ly] = row -> data[col] ;
1901  }
1902  }
1903  return image ;
1904 }
1905 
1921 Stats * sinfo_new_image_stats_on_rectangle ( cpl_image * im,
1922  float loReject,
1923  float hiReject,
1924  int llx,
1925  int lly,
1926  int urx,
1927  int ury )
1928 {
1929  Stats * retstats=NULL;
1930  int i=0 ;
1931  int row=0;
1932  int col=0;
1933  int n=0;
1934  int npix=0;
1935  int lo_n=0;
1936  int hi_n=0;
1937  double pix_sum=0;
1938  double sqr_sum=0;
1939  float * pix_array=NULL;
1940  int im_lx=0;
1941  int im_ly=0;
1942  float* pim=NULL;
1943 
1944  if ( NULL == im )
1945  {
1946  sinfo_msg_error("sorry, no input image given!") ;
1947  return NULL ;
1948  }
1949  if ( loReject+hiReject >= 100. )
1950  {
1951  sinfo_msg_error("sorry, too much pixels rejected!") ;
1952  return NULL ;
1953  }
1954  if ( loReject < 0. || loReject >= 100. ||
1955  hiReject < 0. || hiReject >= 100. )
1956  {
1957  sinfo_msg_error("sorry, negative reject values!") ;
1958  return NULL ;
1959  }
1960 
1961  im_lx=cpl_image_get_size_x(im);
1962  im_ly=cpl_image_get_size_y(im);
1963 
1964  if ( llx < 0 || lly < 0 || urx < 0 || ury < 0 ||
1965  llx >= im_lx || lly >= im_ly || urx >= im_lx ||
1966  ury >= im_ly || ury <= lly || urx <= llx )
1967  {
1968  sinfo_msg_error("sorry, wrong pixel coordinates of rectangle!") ;
1969  return NULL ;
1970  }
1971 
1972  /* allocate memory */
1973  retstats = (Stats*) cpl_calloc(1, sizeof(Stats)) ;
1974  npix = (urx - llx + 1) * (ury - lly + 1) ;
1975  pix_array = (float*) cpl_calloc ( npix, sizeof(float) ) ;
1976 
1977  /*-------------------------------------------------------------------------
1978  * go through the rectangle and copy the pixel values into an array.
1979  */
1980  n = 0 ;
1981  pim = cpl_image_get_data_float(im);
1982  for ( row = lly ; row <= ury ; row++ )
1983  {
1984  for ( col = llx ; col <= urx ; col++ )
1985  {
1986  if ( !isnan(pim[col + row*im_lx]) )
1987  {
1988  pix_array[n] = pim[col + row*im_lx] ;
1989  n++ ;
1990  }
1991  }
1992  }
1993 
1994  npix = n;
1995  /*if (n != npix)
1996  {
1997  sinfo_msg_error("the computed number of pixel equals "
1998  "not the counted number, impossible!") ;
1999  cpl_free(retstats) ;
2000  cpl_free(pix_array) ;
2001  return NULL ;
2002  }*/
2003 
2004  /* determining the clean mean is already done in the recipes */
2005  if ( FLT_MAX == (retstats->cleanmean = sinfo_new_clean_mean(pix_array,
2006  npix, loReject, hiReject)) )
2007  {
2008  sinfo_msg_error("sinfo_new_clean_mean() did not work!") ;
2009  cpl_free(retstats) ;
2010  cpl_free(pix_array) ;
2011  return NULL ;
2012  }
2013 
2014  /* now the clean standard deviation must be calculated */
2015  /* initialize sums */
2016  lo_n = (int) (loReject / 100. * (float)npix) ;
2017  hi_n = (int) (hiReject / 100. * (float)npix) ;
2018  pix_sum = 0. ;
2019  sqr_sum = 0. ;
2020  n = 0 ;
2021  for ( i = lo_n ; i <= npix - hi_n ; i++ )
2022  {
2023  pix_sum += (double)pix_array[i] ;
2024  sqr_sum += ((double)pix_array[i] * (double)pix_array[i]) ;
2025  n++ ;
2026  }
2027 
2028  if ( n == 0 )
2029  {
2030  sinfo_msg_error("number of clean pixels is zero!") ;
2031  cpl_free(retstats) ;
2032  cpl_free(pix_array) ;
2033  return NULL ;
2034  }
2035  retstats -> npix = n ;
2036  pix_sum /= (double) n ;
2037  sqr_sum /= (double) n ;
2038  retstats -> cleanstdev = (float)sqrt(sqr_sum - pix_sum * pix_sum) ;
2039  cpl_free (pix_array) ;
2040  return retstats ;
2041 }
2042 
2043 
2044 
2053 cpl_image * sinfo_new_normalize_to_central_pixel ( cpl_image * image )
2054 {
2055  int col=0;
2056  int row=0;
2057  int i=0;
2058  int n=0;
2059  float* array=NULL ;
2060  float divisor=0;
2061  cpl_image * retImage=NULL;
2062  int ilx=0;
2063  int ily=0;
2064  float* pidata=NULL;
2065  float* podata=NULL;
2066 
2067  if ( image == NULL )
2068  {
2069  sinfo_msg_error("no image given!") ;
2070  return NULL ;
2071  }
2072  ilx=cpl_image_get_size_x(image);
2073  ily=cpl_image_get_size_y(image);
2074  pidata=cpl_image_get_data_float(image);
2075 
2076  retImage = cpl_image_duplicate(image) ;
2077  podata=cpl_image_get_data_float(retImage);
2078 
2079  n = 0 ;
2080  /* go through the central two image rows and store
2081  the values in an array */
2082  array=cpl_calloc(2*ilx,sizeof(float)) ;
2083 
2084  for ( row = ily/2 ; row < ily/2+1 ; row++ )
2085  {
2086  for ( col = 0 ; col < ilx ; col++ )
2087  {
2088  if ( !isnan(pidata[col+ilx*row]) )
2089  {
2090  array[n] = pidata[col+ilx*row] ;
2091  n++ ;
2092  }
2093  }
2094  }
2095  /* compute the sinfo_median of the central 2 spectral
2096  values of all spatial pixels*/
2097  if ( isnan(divisor = sinfo_new_median(array, n) ) )
2098  {
2099  sinfo_msg_error("no sinfo_median possible!") ;
2100  return NULL ;
2101  }
2102  if ( 0 == divisor )
2103  {
2104  sinfo_msg_error("cannot divide by 0") ;
2105  return NULL ;
2106  }
2107 
2108  for ( i = 0 ; i < (int) ilx*ily ; i++ )
2109  {
2110  if ( isnan(pidata[i]) )
2111  {
2112  podata[i] = ZERO ;
2113  }
2114  else
2115  {
2116  podata[i] = pidata[i]/divisor ;
2117  }
2118  }
2119  cpl_free(array);
2120  return retImage ;
2121 }
2122 
2123 /*-------------------------------------------------------------------------*/
2152 /*--------------------------------------------------------------------------*/
2153 
2154 cpl_image *
2155 sinfo_new_mpe_shift_image(
2156  cpl_image * image_in,
2157  double shift_x,
2158  double shift_y,
2159  double * interp_kernel)
2160 {
2161  cpl_image * shifted=NULL ;
2162  pixelvalue * first_pass=NULL ;
2163  pixelvalue * second_pass=NULL ;
2164  int samples = KERNEL_SAMPLES ;
2165  int i=0, j=0 ;
2166  double fx=0, fy=0 ;
2167  double rx=0, ry=0 ;
2168  int px=0, py=0 ;
2169  int tabx=0, taby=0 ;
2170  double value=0 ;
2171  size_t pos ;
2172  register pixelvalue * pix ;
2173  register pixelvalue * pixint ;
2174  int mid=0;
2175  double norm=0 ;
2176  double * ker=NULL ;
2177  int freeKernel = 1 ;
2178 
2179  int ilx=0;
2180  int ily=0;
2181  float* pidata=NULL;
2182  float* psdata=NULL;
2183 
2184 
2185  /* error handling: test entries */
2186  if (image_in==NULL) return NULL ;
2187 
2188  /* Shifting by a zero offset returns a copy of the input image */
2189  if ((fabs(shift_x)<1e-2) && (fabs(shift_y)<1e-2))
2190  return cpl_image_duplicate(image_in) ;
2191  ilx=cpl_image_get_size_x(image_in);
2192  ily=cpl_image_get_size_y(image_in);
2193  pidata=cpl_image_get_data_float(image_in);
2194 
2195 
2196  /* See if a kernel needs to be generated */
2197  if (interp_kernel == NULL) {
2198  ker = sinfo_generate_interpolation_kernel("default") ;
2199  if (ker == NULL) {
2200  sinfo_msg_error("kernel generation failure:aborting resampling") ;
2201  return NULL ;
2202  }
2203  } else {
2204  ker = interp_kernel ;
2205  freeKernel = 0 ;
2206  }
2207 
2208  mid = (int)samples/(int)2 ;
2209  first_pass = cpl_calloc(ilx, ily*sizeof(pixelvalue)) ;
2210  shifted = cpl_image_new(ilx, ily,CPL_TYPE_FLOAT) ;
2211  psdata=cpl_image_get_data_float(shifted);
2212 
2213  second_pass = psdata ;
2214 
2215  pix = pidata ;
2216  if ( ilx != 1 )
2217  {
2218  for (j=0 ; j<ily ; j++)
2219  {
2220  for (i=0 ; i<ilx ; i++) {
2221  fx = (double)i-shift_x ;
2222  px = (int)fx ;
2223  rx = fx - (double)px ;
2224  pos = px + j * ilx ;
2225 
2226  if ((px>1) && (px<(ilx-2)))
2227  {
2228  tabx = (int)(fabs((double)mid * rx)) ;
2229  /* exclude blank (ZERO) pixels from interpolation */
2230  if (isnan(pix[pos]))
2231  {
2232  value = ZERO ;
2233  }
2234  else
2235  {
2236  if (isnan(pix[pos-1]))
2237  {
2238  pix[pos-1] = 0. ;
2239  }
2240  if (isnan(pix[pos+1]))
2241  {
2242  pix[pos+1] = 0. ;
2243  }
2244  if (isnan(pix[pos+2]))
2245  {
2246  pix[pos+2] = 0. ;
2247  }
2248 
2249  /*
2250  * Sum up over 4 closest pixel values,
2251  * weighted by interpolation kernel values
2252  */
2253  value = (double)pix[pos-1] * ker[mid+tabx] +
2254  (double)pix[pos] * ker[tabx] +
2255  (double)pix[pos+1] * ker[mid-tabx] +
2256  (double)pix[pos+2] * ker[samples-tabx-1] ;
2257  /*
2258  * Also sum up interpolation kernel coefficients
2259  * for further normalization
2260  */
2261  norm = (double)ker[mid+tabx] +
2262  (double)ker[tabx] +
2263  (double)ker[mid-tabx] +
2264  (double)ker[samples-tabx-1] ;
2265  if (fabs(norm) > 1e-4) {
2266  value /= norm ;
2267  }
2268  }
2269  } else {
2270  value = ZERO ;
2271  }
2272  /*
2273  * There may be a problem of rounding here if pixelvalue
2274  * has not enough bits to sustain the accuracy.
2275  */
2276  if ( isnan(value) )
2277  {
2278  first_pass[i+j*ilx] = ZERO ;
2279  }
2280  else
2281  {
2282  first_pass[i+j*ilx] = (pixelvalue)value ;
2283  }
2284  }
2285  }
2286  }
2287  else
2288  {
2289  memcpy(first_pass,pix,ily*sizeof(pixelvalue));
2290  }
2291 
2292  pixint = first_pass ;
2293  for (i=0 ; i<ilx ; i++) {
2294  for (j=0 ; j<ily ; j++) {
2295  fy = (double)j - shift_y ;
2296  py = (int)fy ;
2297  ry = fy - (double)py ;
2298  pos = i + py * ilx ;
2299 
2300  taby = (int)(fabs((double)mid * ry)) ;
2301 
2302  if ((py>(int)1) && (py<(ily-2))) {
2303  /* exclude blank (ZERO) pixels from interpolation */
2304  if (isnan(pixint[pos]) && ilx != 1 )
2305  {
2306  value = ZERO ;
2307  }
2308  else
2309  {
2310  if (isnan(pixint[pos-ilx]))
2311  {
2312  pixint[pos-ilx] = 0. ;
2313  }
2314  if (isnan(pixint[pos+ilx]))
2315  {
2316  pixint[pos+ilx] = 0. ;
2317  }
2318  if (isnan(pixint[pos+2*ilx]))
2319  {
2320  pixint[pos+2*ilx] = 0. ;
2321  }
2322  /*
2323  * Sum up over 4 closest pixel values,
2324  * weighted by interpolation kernel values
2325  */
2326  value = (double)pixint[pos-ilx] * ker[mid+taby] +
2327  (double)pixint[pos] * ker[taby] +
2328  (double)pixint[pos+ilx] * ker[mid-taby] +
2329  (double)pixint[pos+2*ilx]*ker[samples-taby-1];
2330  /*
2331  * Also sum up interpolation kernel coefficients
2332  * for further normalization
2333  */
2334  norm = (double)ker[mid+taby] +
2335  (double)ker[taby] +
2336  (double)ker[mid-taby] +
2337  (double)ker[samples-taby-1] ;
2338 
2339  if (fabs(norm) > 1e-4) {
2340  value /= norm ;
2341  }
2342  }
2343  } else {
2344  value = ZERO ;
2345  }
2346  if (isnan(value))
2347  {
2348  second_pass[i+j*ilx] = ZERO ;
2349  }
2350  else
2351  {
2352  second_pass[i+j*ilx] = (pixelvalue)value ;
2353  }
2354  }
2355  }
2356 
2357  cpl_free(first_pass) ;
2358  if (freeKernel)
2359  cpl_free(ker) ;
2360  return shifted ;
2361 }
2362 
2363 
2364 /*-------------------------------------------------------------------------*/
2395 /*--------------------------------------------------------------------------*/
2396 
2397 void
2398 sinfo_new_shift_image_in_cube(
2399  cpl_image * image_in,
2400  double shift_x,
2401  double shift_y,
2402  double * interp_kernel,
2403  cpl_image * shifted,
2404  pixelvalue * first_pass)
2405 {
2406  pixelvalue * second_pass=NULL ;
2407  int samples = KERNEL_SAMPLES ;
2408  int i=0, j=0 ;
2409  double fx=0, fy=0 ;
2410  double rx=0, ry=0 ;
2411  int px=0, py=0 ;
2412  int tabx=0, taby=0 ;
2413  double value=0 ;
2414  size_t pos ;
2415  register pixelvalue * pix ;
2416  register pixelvalue * pixint ;
2417  int mid=0;
2418  double norm=0 ;
2419  double * ker=NULL ;
2420  int freeKernel = 1 ;
2421 
2422  int ilx=0;
2423  int ily=0;
2424  int slx=0;
2425  int sly=0;
2426  float* pidata=NULL;
2427  float* psdata=NULL;
2428 
2429  /* error handling: test entries */
2430  if (image_in==NULL) shifted = NULL ;
2431  pidata=cpl_image_get_data_float(image_in);
2432  ilx=cpl_image_get_size_x(image_in);
2433  ily=cpl_image_get_size_y(image_in);
2434 
2435  shifted=cpl_image_new(ilx,ily,CPL_TYPE_FLOAT);
2436  slx=ilx;
2437  sly=ily;
2438 
2439  psdata=cpl_image_get_data_float(shifted);
2440 
2441  /* Shifting by a zero offset returns a copy of the input image */
2442  if ((fabs(shift_x)<1e-2) && (fabs(shift_y)<1e-2))
2443  memcpy(psdata,pidata, (size_t) slx*sly * sizeof(pixelvalue)) ;
2444 
2445  /* See if a kernel needs to be generated */
2446  if (interp_kernel == NULL) {
2447  ker = sinfo_generate_interpolation_kernel("default") ;
2448  if (ker == NULL) {
2449  sinfo_msg_error("kernel generation failure:aborting resampling") ;
2450  shifted = NULL ;
2451  }
2452  } else {
2453  ker = interp_kernel ;
2454  freeKernel = 0 ;
2455  }
2456 
2457  mid = (int)samples/(int)2 ;
2458  second_pass = psdata ;
2459 
2460  pix = pidata ;
2461  for (j=0 ; j<ily ; j++) {
2462  for (i=1 ; i<ilx-2 ; i++) {
2463  fx = (double)i-shift_x ;
2464  px = (int)fx ;
2465  rx = fx - (double)px ;
2466 
2467  pos = px + j * ilx ;
2468 
2469  if ((px>1) && (px<(ilx-2))) {
2470  tabx = (int)(fabs((double)mid * rx)) ;
2471  /* exclude blank (ZERO) pixels from interpolation */
2472  if (isnan(pix[pos]))
2473  {
2474  value = ZERO ;
2475  }
2476  else
2477  {
2478  if (isnan(pix[pos-1]))
2479  {
2480  pix[pos-1] = 0. ;
2481  }
2482  if (isnan(pix[pos+1]))
2483  {
2484  pix[pos+1] = 0. ;
2485  }
2486  if (isnan(pix[pos+2]))
2487  {
2488  pix[pos+2] = 0. ;
2489  }
2490 
2491  /*
2492  * Sum up over 4 closest pixel values,
2493  * weighted by interpolation kernel values
2494  */
2495  value = (double)pix[pos-1] * ker[mid+tabx] +
2496  (double)pix[pos] * ker[tabx] +
2497  (double)pix[pos+1] * ker[mid-tabx] +
2498  (double)pix[pos+2] * ker[samples-tabx-1] ;
2499  /*
2500  * Also sum up interpolation kernel coefficients
2501  * for further normalization
2502  */
2503  norm = (double)ker[mid+tabx] +
2504  (double)ker[tabx] +
2505  (double)ker[mid-tabx] +
2506  (double)ker[samples-tabx-1] ;
2507  if (fabs(norm) > 1e-4) {
2508  value /= norm ;
2509  }
2510  }
2511  } else {
2512  value = 0.0 ;
2513  }
2514  /*
2515  * There may be a problem of rounding here if pixelvalue
2516  * has not enough bits to sustain the accuracy.
2517  */
2518  if ( isnan(value) )
2519  {
2520  first_pass[i+j*ilx] = ZERO ;
2521  }
2522  else
2523  {
2524  first_pass[i+j*ilx] = (pixelvalue)value ;
2525  }
2526  }
2527  }
2528  pixint = first_pass ;
2529  for (i=0 ; i< ilx ; i++) {
2530  for (j=1 ; j< ily-2 ; j++) {
2531  fy = (double)j - shift_y ;
2532  py = (int)fy ;
2533  ry = fy - (double)py ;
2534  pos = i + py * ilx ;
2535 
2536  taby = (int)(fabs((double)mid * ry)) ;
2537 
2538  if ((py>(int)1) && (py<(ily-2))) {
2539  /* exclude blank (ZERO) pixels from interpolation */
2540  if (isnan(pixint[pos]))
2541  {
2542  value = ZERO ;
2543  }
2544  else
2545  {
2546  if (isnan(pixint[pos-ilx]))
2547  {
2548  pixint[pos-ilx] = 0. ;
2549  }
2550  if (isnan(pixint[pos+ilx]))
2551  {
2552  pixint[pos+ilx] = 0. ;
2553  }
2554  if (isnan(pixint[pos+2*ilx]))
2555  {
2556  pixint[pos+2*ilx] = 0. ;
2557  }
2558  /*
2559  * Sum up over 4 closest pixel values,
2560  * weighted by interpolation kernel values
2561  */
2562  value = (double)pixint[pos-ilx] * ker[mid+taby] +
2563  (double)pixint[pos] * ker[taby] +
2564  (double)pixint[pos+ilx] * ker[mid-taby] +
2565  (double)pixint[pos+2*ilx]*ker[samples-taby-1];
2566  /*
2567  * Also sum up interpolation kernel coefficients
2568  * for further normalization
2569  */
2570  norm = (double)ker[mid+taby] +
2571  (double)ker[taby] +
2572  (double)ker[mid-taby] +
2573  (double)ker[samples-taby-1] ;
2574 
2575  if (fabs(norm) > 1e-4) {
2576  value /= norm ;
2577  }
2578  }
2579  } else {
2580  /* value = 0.0 ; AMo: This affect slitlet #1 */
2581  }
2582  if (isnan(value))
2583  {
2584  second_pass[i+j*ilx] = ZERO ;
2585  }
2586  else
2587  {
2588  second_pass[i+j*ilx] = (pixelvalue)value ;
2589  }
2590  }
2591  }
2592 
2593  if (freeKernel)
2594  cpl_free(ker) ;
2595 }
2596 
2597 /* function to delete the image statistics within python */
2598 void sinfo_new_del_Stats( Stats * st)
2599 {
2600  cpl_free (st) ;
2601 }
2602 
2609 cpl_image *
2610 sinfo_new_combine_masks ( cpl_image * firstMask, cpl_image * secondMask )
2611 {
2612  cpl_image * retMask=NULL ;
2613  int n=0 ;
2614  int olx=0;
2615  int oly=0;
2616  float* podata=NULL;
2617  //float* pm1data=NULL;
2618  float* pm2data=NULL;
2619 
2620  if ( firstMask == NULL || secondMask == NULL )
2621  {
2622  sinfo_msg_error ("no input mask image given!") ;
2623  return NULL ;
2624  }
2625  retMask = cpl_image_duplicate (firstMask) ;
2626  podata = cpl_image_get_data_float(retMask);
2627  //pm1data = cpl_image_get_data_float(firstMask);
2628  pm2data = cpl_image_get_data_float(secondMask);
2629  olx=cpl_image_get_size_x(retMask);
2630  oly=cpl_image_get_size_y(retMask);
2631 
2632  for ( n = 0 ; n < (int) olx*oly ; n++ )
2633  {
2634  if ( podata[n] == 0. || pm2data[n] == 0. )
2635  {
2636  podata[n] = 0. ;
2637  }
2638  else
2639  {
2640  podata[n] = 1. ;
2641  }
2642  }
2643  return retMask ;
2644 }
2645 
2654 cpl_image * sinfo_new_slice_cube (cpl_imagelist * cube, int x, int y )
2655 {
2656  cpl_image * retImage=NULL ;
2657  int col=0, row=0, z=0 ;
2658  int inp=0;
2659  int ilx=0;
2660  int ily=0;
2661  cpl_image* img=NULL;
2662  float* podata=NULL;
2663  float* pidata=NULL;
2664 
2665  if ( cube == NULL )
2666  {
2667  sinfo_msg_error("no cube given!") ;
2668  return NULL ;
2669  }
2670  if ( x > 31 || y > 31 )
2671  {
2672  sinfo_msg_warning("wrong x or y values!") ;
2673  }
2674 
2675  img=cpl_imagelist_get(cube,0);
2676  ilx=cpl_image_get_size_x(img);
2677  ily=cpl_image_get_size_y(img);
2678  inp=cpl_imagelist_get_size(cube);
2679  if ( x < 0 )
2680  {
2681  /* allocate memory */
2682  if ( NULL == (retImage = cpl_image_new(ilx, inp, CPL_TYPE_FLOAT)) )
2683  {
2684  sinfo_msg_error("could not allocate memory!") ;
2685  return NULL ;
2686  }
2687  podata=cpl_image_get_data_float(retImage);
2688  for ( z = 0 ; z < inp ; z++ )
2689  {
2690 
2691  pidata=cpl_image_get_data_float(cpl_imagelist_get(cube,z));
2692  for ( col = 0 ; col < ilx ; col++ )
2693  {
2694  podata[col+z*ilx] = pidata[col+y*ilx] ;
2695  }
2696  }
2697  }
2698  else if ( y < 0 )
2699  {
2700  /* allocate memory */
2701  if ( NULL == (retImage = cpl_image_new(ily, inp,CPL_TYPE_FLOAT)) )
2702  {
2703  sinfo_msg_error("could not allocate memory!") ;
2704  return NULL ;
2705  }
2706  podata=cpl_image_get_data_float(retImage);
2707 
2708  for ( z = 0 ; z < inp ; z++ )
2709  {
2710  pidata=cpl_image_get_data_float(cpl_imagelist_get(cube,z));
2711  for ( row = 0 ; row < ily ; row++ )
2712  {
2713  podata[row+z*ily] = pidata[x+row*ily] ;
2714  }
2715  }
2716  }
2717  else
2718  {
2719  sinfo_msg_error("wrong input!") ;
2720  return NULL ;
2721  }
2722  return retImage ;
2723 }
2724 
2736 cpl_image * sinfo_new_div_images_robust ( cpl_image * im1, cpl_image * im2 )
2737 {
2738  cpl_image * retIm=NULL ;
2739  float help=0 ;
2740  int i=0 ;
2741  int lx1=0;
2742  int ly1=0;
2743  int lx2=0;
2744  int ly2=0;
2745 
2746  float* p1data=NULL;
2747  float* p2data=NULL;
2748  float* podata=NULL;
2749 
2750  if ( im1 == NULL || im2 == NULL )
2751  {
2752  sinfo_msg_error("no input images given!") ;
2753  return NULL ;
2754  }
2755  lx1=cpl_image_get_size_x(im1);
2756  ly1=cpl_image_get_size_y(im1);
2757  lx2=cpl_image_get_size_x(im2);
2758  ly2=cpl_image_get_size_y(im2);
2759  p1data=cpl_image_get_data_float(im1);
2760  p2data=cpl_image_get_data_float(im2);
2761 
2762  if ( lx1 != lx2 || ly1 != ly2 )
2763  {
2764  sinfo_msg_error("images not compatible!") ;
2765  return NULL ;
2766  }
2767  if ( NULL == (retIm = cpl_image_new(lx1, ly1, CPL_TYPE_FLOAT)) )
2768  {
2769  sinfo_msg_error("could not allocate memory!") ;
2770  return NULL ;
2771  }
2772  podata=cpl_image_get_data_float(retIm);
2773 
2774  for ( i = 0 ; i < (int) lx2*ly2 ; i++ )
2775  {
2776  if ( !isnan(p2data[i]) )
2777  {
2778  help = 1./p2data[i] ;
2779  if (fabs( help )> THRESH )
2780  {
2781  help = 1. ;
2782  }
2783  }
2784  else
2785  {
2786  help = ZERO ;
2787  }
2788  if ( isnan(help) || isnan(p1data[i]) )
2789  {
2790  podata[i] = ZERO ;
2791  }
2792  else
2793  {
2794  podata[i] = p1data[i] * help ;
2795  }
2796  }
2797  return retIm ;
2798 }
2799 
2800 cpl_image * sinfo_new_null_edges ( cpl_image * image)
2801 {
2802  cpl_image * new=NULL ;
2803  int i=0,j=0 ;
2804  /*
2805  int ilx=0;
2806  int ily=0;
2807  */
2808  int olx=0;
2809  int oly=0;
2810 
2811  //float* pidata=NULL;
2812  float* podata=NULL;
2813 
2814  if ( image == NULL )
2815  {
2816  sinfo_msg_error ("no input image given!\n") ;
2817  return NULL ;
2818  }
2819 
2820 
2821  new = cpl_image_duplicate (image) ;
2822  /*
2823  ilx=cpl_image_get_size_x(image);
2824  ily=cpl_image_get_size_y(image);
2825  */
2826  olx=cpl_image_get_size_x(new);
2827  oly=cpl_image_get_size_y(new);
2828  //pidata=cpl_image_get_data_float(image);
2829  podata=cpl_image_get_data_float(new);
2830 
2831  for ( i = 0 ; i < olx ; i++ )
2832  {
2833  for ( j = 0 ; j < 4 ; j++)
2834  {
2835  podata[i+j*olx]=0;
2836  podata[i+(oly-j-1)*olx]=0;
2837  }
2838  }
2839  for ( i = 0 ; i < oly ; i++ )
2840  {
2841  for ( j = 0 ; j < 4 ; j++)
2842  {
2843  podata[j+i*olx]=0;
2844  podata[(olx-j-1)+i*olx]=0;
2845  }
2846  }
2847  return new ;
2848 }
2849 
2850 
2851 void sinfo_new_used_cor_map( cpl_image *im, cpl_image *map)
2852 {
2853  int i=0,j=0,loc_index=0;
2854  float temp_array[2048];
2855  int lx=cpl_image_get_size_x(im);
2856  int ly=cpl_image_get_size_y(im);
2857  float* pidata=cpl_image_get_data_float(im);
2858  float* pmdata=cpl_image_get_data_float(map);
2859 
2860  for( j=0; j<ly; j++)
2861  {
2862  for( i=0;i<lx;i++)
2863  {
2864  loc_index = (int)pmdata[i+j*lx];
2865  temp_array[i] = pidata[loc_index+j*lx];
2866  }
2867  for( i=0;i<lx;i++)
2868  {
2869  pidata[i+j*lx]= temp_array[i];
2870  }
2871  }
2872 }
2873 
2874 
2875 
2876 
2877 /*-------------------------------------------------------------------------*/
2900 /*--------------------------------------------------------------------------*/
2901 
2902 cpl_image *
2903 sinfo_new_shift_image(
2904  cpl_image * image_in,
2905  double shift_x,
2906  double shift_y,
2907  double * interp_kernel)
2908 {
2909  cpl_image * shifted=NULL ;
2910  float * first_pass=NULL ;
2911  float * second_pass=NULL ;
2912  int samples = KERNEL_SAMPLES ;
2913  int i=0, j=0 ;
2914  double fx=0, fy=0 ;
2915  double rx=0, ry=0 ;
2916  int px=0, py=0 ;
2917  int tabx=0, taby=0 ;
2918  double value=0 ;
2919  size_t pos ;
2920  register float * pix=NULL ;
2921  register float * pixint=NULL ;
2922  int mid=0;
2923  double norm=0 ;
2924  double * ker=NULL ;
2925  int freeKernel = 1 ;
2926  int ilx=0;
2927  int ily=0;
2928 
2929  /* error handling: test entries */
2930  if (image_in==NULL) return NULL ;
2931 
2932  /* Shifting by a zero offset returns a copy of the input image */
2933  if ((fabs(shift_x)<1e-2) && (fabs(shift_y)<1e-2))
2934  return cpl_image_duplicate(image_in) ;
2935 
2936  /* See if a kernel needs to be generated */
2937  if (interp_kernel == NULL) {
2938  ker = sinfo_generate_interpolation_kernel("default") ;
2939  if (ker == NULL) {
2940  sinfo_msg_error("kernel generation failure: aborting resampling") ;
2941  return NULL ;
2942  }
2943  } else {
2944  ker = interp_kernel ;
2945  freeKernel = 0 ;
2946  }
2947 
2948  ilx=cpl_image_get_size_x(image_in);
2949  ily=cpl_image_get_size_y(image_in);
2950 
2951 
2952  pix = cpl_image_get_data_float(image_in);
2953  if (pix)
2954  {
2955  mid = (int)samples/(int)2 ;
2956  first_pass = cpl_calloc(ilx, ily*sizeof(float)) ;
2957  shifted = cpl_image_new(ilx, ily,CPL_TYPE_FLOAT) ;
2958  second_pass = cpl_image_get_data_float(shifted);
2959  for (j=0 ; j<ily ; j++) {
2960  for (i=1 ; i<ilx-2 ; i++) {
2961  fx = (double)i-shift_x ;
2962  px = (int)fx ;
2963  rx = fx - (double)px ;
2964 
2965  pos = px + j * ilx ;
2966 
2967  if ((px>1) && (px<(ilx-3))) {
2968  tabx = (int)(fabs((double)mid * rx)) ;
2969  /*
2970  * Sum up over 4 closest pixel values,
2971  * weighted by interpolation kernel values
2972  */
2973  value = (double)pix[pos-1] * ker[mid+tabx] +
2974  (double)pix[pos] * ker[tabx] +
2975  (double)pix[pos+1] * ker[mid-tabx] +
2976  (double)pix[pos+2] * ker[samples-tabx-1] ;
2977  /*
2978  * Also sum up interpolation kernel coefficients
2979  * for further normalization
2980  */
2981  norm = (double)ker[mid+tabx] +
2982  (double)ker[tabx] +
2983  (double)ker[mid-tabx] +
2984  (double)ker[samples-tabx-1] ;
2985  if (fabs(norm) > 1e-4) {
2986  value /= norm ;
2987  }
2988  } else {
2989  value = 0.0 ;
2990  }
2991  /*
2992  * There may be a problem of rounding here if pixelvalue
2993  * has not enough bits to sustain the accuracy.
2994  */
2995  first_pass[i+j*ilx] = (float)value ;
2996  }
2997  }
2998  pixint = first_pass ;
2999  for (i=0 ; i<ilx ; i++) {
3000  for (j=1 ; j<ily-3 ; j++) {
3001  fy = (double)j - shift_y ;
3002  py = (int)fy ;
3003  ry = fy - (double)py ;
3004  pos = i + py * ilx ;
3005 
3006  taby = (int)(fabs((double)mid * ry)) ;
3007 
3008  if ((py>(int)1) && (py<(ily-2))) {
3009  /*
3010  * Sum up over 4 closest pixel values,
3011  * weighted by interpolation kernel values
3012  */
3013  value = (double)pixint[pos-ilx] * ker[mid+taby] +
3014  (double)pixint[pos] * ker[taby] +
3015  (double)pixint[pos+ilx] * ker[mid-taby] +
3016  (double)pixint[pos+2*ilx]*ker[samples-taby-1];
3017  /*
3018  * Also sum up interpolation kernel coefficients
3019  * for further normalization
3020  */
3021  norm = (double)ker[mid+taby] +
3022  (double)ker[taby] +
3023  (double)ker[mid-taby] +
3024  (double)ker[samples-taby-1] ;
3025 
3026  if (fabs(norm) > 1e-4) {
3027  value /= norm ;
3028  }
3029  } else {
3030  value = 0.0 ;
3031  }
3032  second_pass[i+j*ilx] = (float)value ;
3033  }
3034  }
3035  }
3036  else
3037  {
3038  cpl_msg_warning(cpl_func, "cannot get a data from an image");
3039  }
3040  cpl_free(first_pass) ;
3041  if (freeKernel)
3042  cpl_free(ker) ;
3043  return shifted ;
3044 }
3045 
3046 
3047 /*-------------------------------------------------------------------------*/
3061 /*--------------------------------------------------------------------------*/
3062 
3063 cpl_image *
3064 sinfo_image_hermite_interpol(cpl_image * inp)
3065 {
3066 
3067  /*
3068  @param xp x-value to interpolate
3069  @param x x-values
3070  @param y y-values
3071  @param n array length
3072  @param istart (input/output) initial row (set to 0 to search all row)
3073 
3074  sinfo_spline_hermite( double xp, const double *x,
3075  const double *y, int n, int *istart );
3076 
3077  */
3078  float* pinp=NULL;
3079  float* pout=NULL;
3080  int sx=0;
3081  int sy=0;
3082  int i=0;
3083  int j=0;
3084  int r=5;
3085  int k=0;
3086 
3087  cpl_image* out=NULL;
3088 
3089  cknull(inp,"Null in put image, exit");
3090  check_nomsg(out=cpl_image_duplicate(inp));
3091  check_nomsg(sx=cpl_image_get_size_x(inp));
3092  check_nomsg(sy=cpl_image_get_size_y(inp));
3093  check_nomsg(pinp=cpl_image_get_data_float(inp));
3094  check_nomsg(pout=cpl_image_get_data_float(out));
3095  for(j=r;j<sy-r;j++) {
3096  for(i=0;i<sx;i++) {
3097  for(k=-r;k<r;k++) {
3098  pout[j*sx+i]+=pinp[(j+k)*sx+i];
3099  }
3100  pout[j*sx+i]/=2*r;
3101  }
3102  }
3103 
3104  cleanup:
3105 
3106  if(cpl_error_get_code() != CPL_ERROR_NONE) {
3107  return NULL;
3108  } else {
3109  return out;
3110 
3111  }
3112 
3113 }
3114 
3115 
3116 
3117 /*-------------------------------------------------------------------------*/
3131 /*--------------------------------------------------------------------------*/
3132 
3133 cpl_image *
3134 sinfo_image_smooth_y(cpl_image * inp, const int r)
3135 {
3136 
3137  /*
3138  @param xp x-value to interpolate
3139  @param x x-values
3140  @param y y-values
3141  @param n array length
3142  @param istart (input/output) initial row (set to 0 to search all row)
3143 
3144  */
3145  float* pinp=NULL;
3146  float* pout=NULL;
3147  int sx=0;
3148  int sy=0;
3149  int i=0;
3150  int j=0;
3151  int k=0;
3152 
3153  cpl_image* out=NULL;
3154 
3155  cknull(inp,"Null in put image, exit");
3156  check_nomsg(out=cpl_image_duplicate(inp));
3157  check_nomsg(sx=cpl_image_get_size_x(inp));
3158  check_nomsg(sy=cpl_image_get_size_y(inp));
3159  check_nomsg(pinp=cpl_image_get_data_float(inp));
3160  check_nomsg(pout=cpl_image_get_data_float(out));
3161  for(j=r;j<sy-r;j++) {
3162  for(i=0;i<sx;i++) {
3163  for(k=-r;k<r;k++) {
3164  pout[j*sx+i]+=pinp[(j+k)*sx+i];
3165  }
3166  pout[j*sx+i]/=2*r;
3167  }
3168  }
3169 
3170  cleanup:
3171 
3172  if(cpl_error_get_code() != CPL_ERROR_NONE) {
3173  return NULL;
3174  } else {
3175  return out;
3176 
3177  }
3178 
3179 }
3180 
3181 
3182 /*-------------------------------------------------------------------------*/
3196 /*--------------------------------------------------------------------------*/
3197 
3198 cpl_image *
3199 sinfo_image_smooth_mean_y(cpl_image * inp, const int r)
3200 {
3201 
3202  /*
3203  @param xp x-value to interpolate
3204  @param x x-values
3205  @param y y-values
3206  @param n array length
3207  @param istart (input/output) initial row (set to 0 to search all row)
3208 
3209  */
3210  float* pinp=NULL;
3211  float* pout=NULL;
3212  int sx=0;
3213  int sy=0;
3214  int i=0;
3215  int j=0;
3216  int k=0;
3217 
3218  cpl_image* out=NULL;
3219 
3220  cknull(inp,"Null in put image, exit");
3221  check_nomsg(out=cpl_image_duplicate(inp));
3222  check_nomsg(sx=cpl_image_get_size_x(inp));
3223  check_nomsg(sy=cpl_image_get_size_y(inp));
3224  check_nomsg(pinp=cpl_image_get_data_float(inp));
3225  check_nomsg(pout=cpl_image_get_data_float(out));
3226  for(j=r;j<sy-r;j++) {
3227  for(i=0;i<sx;i++) {
3228  for(k=-r;k<r;k++) {
3229  pout[j*sx+i]+=pinp[(j+k)*sx+i];
3230  }
3231  pout[j*sx+i]/=2*r;
3232  }
3233  }
3234 
3235  cleanup:
3236 
3237  if(cpl_error_get_code() != CPL_ERROR_NONE) {
3238  return NULL;
3239  } else {
3240  return out;
3241 
3242  }
3243 
3244 }
3245 
3246 
3247 /*-------------------------------------------------------------------------*/
3261 /*--------------------------------------------------------------------------*/
3262 
3263 cpl_image *
3264 sinfo_image_smooth_median_y(cpl_image * inp, const int r)
3265 {
3266 
3267  /*
3268  @param xp x-value to interpolate
3269  @param x x-values
3270  @param y y-values
3271  @param n array length
3272  @param istart (input/output) initial row (set to 0 to search all row)
3273 
3274  */
3275  float* pout=NULL;
3276  int sx=0;
3277  int sy=0;
3278  int i=0;
3279  int j=0;
3280 
3281  cpl_image* out=NULL;
3282 
3283 
3284  cknull(inp,"Null in put image, exit");
3285  check_nomsg(out=cpl_image_duplicate(inp));
3286  check_nomsg(sx=cpl_image_get_size_x(inp));
3287  check_nomsg(sy=cpl_image_get_size_y(inp));
3288  check_nomsg(pout=cpl_image_get_data_float(out));
3289 
3290  for(j=r+1;j<sy-r;j++) {
3291  for(i=1;i<sx;i++) {
3292  pout[j*sx+i]=(float)cpl_image_get_median_window(inp,i,j,i,j+r);
3293  }
3294  }
3295 
3296  cleanup:
3297 
3298  if(cpl_error_get_code() != CPL_ERROR_NONE) {
3299  return NULL;
3300  } else {
3301  return out;
3302 
3303  }
3304 
3305 }
3306 
3307 /*-------------------------------------------------------------------------*/
3320 /*--------------------------------------------------------------------------*/
3321 
3322 cpl_image *
3323 sinfo_image_smooth_fft(cpl_image * inp, const int fy)
3324 {
3325 
3326  int sx=0;
3327  int sy=0;
3328 
3329  cpl_image* out=NULL;
3330  cpl_image* im_re=NULL;
3331  cpl_image* im_im=NULL;
3332  cpl_image* ifft_re=NULL;
3333  cpl_image* ifft_im=NULL;
3334  cpl_image* filter=NULL;
3335 
3336  int sigma_x=0;
3337  int sigma_y=fy;
3338 
3339  cknull(inp,"Null in put image, exit");
3340  check_nomsg(im_re = cpl_image_cast(inp, CPL_TYPE_DOUBLE));
3341  check_nomsg(im_im = cpl_image_cast(inp, CPL_TYPE_DOUBLE));
3342 
3343  // Compute FFT
3344  check_nomsg(cpl_image_fft(im_re,im_im,CPL_FFT_DEFAULT));
3345 
3346  check_nomsg(sx=cpl_image_get_size_x(inp));
3347  check_nomsg(sy=cpl_image_get_size_y(inp));
3348  sigma_x=sx;
3349 
3350  //Generates filter image
3351  check_nomsg(filter = sinfo_gen_lowpass(sx,sy,sigma_x,sigma_y));
3352 
3353  //Apply filter
3354  cpl_image_multiply(im_re,filter);
3355  cpl_image_multiply(im_im,filter);
3356 
3357  sinfo_free_image(&filter);
3358 
3359  check_nomsg(ifft_re = cpl_image_duplicate(im_re));
3360  check_nomsg(ifft_im = cpl_image_duplicate(im_im));
3361 
3362  sinfo_free_image(&im_re);
3363  sinfo_free_image(&im_im);
3364 
3365  //Computes FFT-INVERSE
3366  check_nomsg(cpl_image_fft(ifft_re,ifft_im,CPL_FFT_INVERSE));
3367  check_nomsg(out = cpl_image_cast(ifft_re, CPL_TYPE_FLOAT));
3368 
3369  cleanup:
3370 
3371  sinfo_free_image(&ifft_re);
3372  sinfo_free_image(&ifft_im);
3373  sinfo_free_image(&filter);
3374  sinfo_free_image(&im_re);
3375  sinfo_free_image(&im_im);
3376 
3377  if(cpl_error_get_code() != CPL_ERROR_NONE) {
3378  return NULL;
3379  } else {
3380  return out;
3381  }
3382 
3383 }
3384 
3385 
3386 
3387 /*-------------------------------------------------------------------------*/
3403 /*--------------------------------------------------------------------------*/
3404 static cpl_image *
3405 sinfo_gen_lowpass(const int xs,
3406  const int ys,
3407  const double sigma_x,
3408  const double sigma_y)
3409 {
3410 
3411  int i= 0.0;
3412  int j= 0.0;
3413  int hlx= 0.0;
3414  int hly = 0.0;
3415  double x= 0.0;
3416  double y= 0.0;
3417  double gaussval= 0.0;
3418  double inv_sigma_x=1./sigma_x;
3419  double inv_sigma_y=1./sigma_y;
3420 
3421  float *data;
3422 
3423  cpl_image *lowpass_image=NULL;
3424 
3425 
3426  lowpass_image = cpl_image_new (xs, ys, CPL_TYPE_FLOAT);
3427  if (lowpass_image == NULL) {
3428  sinfo_msg_error("Cannot generate lowpass filter <%s>",
3429  cpl_error_get_message());
3430  return NULL;
3431  }
3432 
3433  hlx = xs/2;
3434  hly = ys/2;
3435 
3436  data = cpl_image_get_data_float(lowpass_image);
3437 
3438  /* Given an image with pixels 0<=i<N, 0<=j<M then the convolution image
3439  has the following properties:
3440 
3441  ima[0][0] = 1
3442  ima[i][0] = ima[N-i][0] = exp (-0.5 * (i/sig_i)^2) 1<=i<N/2
3443  ima[0][j] = ima[0][M-j] = exp (-0.5 * (j/sig_j)^2) 1<=j<M/2
3444  ima[i][j] = ima[N-i][j] = ima[i][M-j] = ima[N-i][M-j]
3445  = exp (-0.5 * ((i/sig_i)^2 + (j/sig_j)^2))
3446  */
3447 
3448  data[0] = 1.0;
3449 
3450  /* first row */
3451  for (i=1 ; i<=hlx ; i++) {
3452  x = i * inv_sigma_x;
3453  gaussval = exp(-0.5*x*x);
3454  data[i] = gaussval;
3455  data[xs-i] = gaussval;
3456  }
3457 
3458  for (j=1; j<=hly ; j++) {
3459  y = j * inv_sigma_y;
3460  /* first column */
3461  data[j*xs] = exp(-0.5*y*y);
3462  data[(ys-j)*xs] = exp(-0.5*y*y);
3463 
3464  for (i=1 ; i<=hlx ; i++) {
3465  /* Use internal symetries */
3466  x = i * inv_sigma_x;
3467  gaussval = exp (-0.5*(x*x+y*y));
3468  data[j*xs+i] = gaussval;
3469  data[(j+1)*xs-i] = gaussval;
3470  data[(ys-j)*xs+i] = gaussval;
3471  data[(ys+1-j)*xs-i] = gaussval;
3472 
3473  }
3474  }
3475 
3476  /* FIXME: for the moment, reset errno which is coming from exp()
3477  in first for-loop at i=348. This is causing cfitsio to
3478  fail when loading an extension image (bug in cfitsio too).
3479  */
3480  if(errno != 0)
3481  errno = 0;
3482 
3483  return lowpass_image;
3484 }
3485 
3486 static void quicksort_int(int* data, int left, int right)
3487 {
3488  int i = left;
3489  int j = right;
3490  int pivot = (i + j) / 2;
3491  double index_value = data[pivot];
3492  do
3493  {
3494  while(data[i] < index_value) i++;
3495  while(data[j] > index_value) j--;
3496  if (i <= j)
3497  {
3498  if(i < j)
3499  {
3500  int tmp = data[i];
3501  data[i]=data[j];
3502  data[j]=tmp;
3503  }
3504  i++;
3505  j--;
3506  }
3507  } while (i <= j);
3508 
3509  if (i < right)
3510  {
3511  quicksort_int(data, i, right);
3512  }
3513  if (left < j)
3514  {
3515  quicksort_int(data, left, j);
3516  }
3517 }
3518 
3519 /*--------------------------------------------------------------------------*/