SINFONI Pipeline Reference Manual  2.6.0
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  *
34  *------------------------------------------------------------------------
35  */
36 
37 #ifdef HAVE_CONFIG_H
38 # include <config.h>
39 #endif
40 #include "sinfo_vltPort.h"
41 
42 /*
43  * System Headers
44  */
45 #include <errno.h>
46 /*
47  * Local Headers
48  */
49 
50 #include "sinfo_image_ops.h"
51 #include "sinfo_error.h"
52 #include "sinfo_resampling.h"
53 #include "sinfo_local_types.h"
54 #include "sinfo_utils_wrappers.h"
63 static cpl_image *
64 sinfo_gen_lowpass(const int xs,
65  const int ys,
66  const double sigma_x,
67  const double sigma_y);
68 
69 
70 static void quicksort_int(int* data, int left, int right);
73 /*----------------------------------------------------------------------------
74  * Function codes
75  *--------------------------------------------------------------------------*/
76 
77 
78 
90 cpl_error_code
91 sinfo_image_line_corr(const int width,
92  const int filt_rad,
93  const int kappa,
94  cpl_image* ima_in,
95  cpl_image** ima_out)
96 {
97 
98  cpl_image* mask=NULL;
99 
100  cpl_image* ima_backpix=NULL;
101  cpl_image* ima_backpos=NULL;
102  cpl_image* ima_ybackpix=NULL;
103  cpl_image* ima_diffbackpix=NULL;
104  cpl_image* ima_filt=NULL;
105  cpl_image* ima = NULL;
106 
107  cpl_matrix* filter=NULL;
108  //cpl_mask* bpm_good=NULL; //Is this really useful?
109  cpl_mask* bpm_bad=NULL;
110 
111  int sx=0;
112  int sy=0;
113  int i=0;
114  int j=0;
115  int k=0;
116  double med_back=0;
117  double sigma_back=0;
118  double medvalue=0;
119 
120  float* pima=NULL;
121  float* ppix=NULL;
122  float* pmsk=NULL;
123  int* ppos=NULL;
124  int* pbackpix=NULL;
125  cpl_binary* pbin=NULL;
126  double tot=0;
127  double mean=0;
128  int* ybad=NULL;
129 
130  int nrow=0;
131  int nbad=0;
132  int yval=0;
133  int yprev=0;
134 
135 
136  check_nomsg(sx=cpl_image_get_size_x(ima_in));
137  check_nomsg(sy=cpl_image_get_size_y(ima_in));
138  check_nomsg(*ima_out=cpl_image_duplicate(ima_in));
139 
140  check_nomsg(mask=cpl_image_new(sx,sy,CPL_TYPE_FLOAT));
141  check_nomsg(pmsk=cpl_image_get_data_float(mask));
142 
143  for(i=0;i<width;i++) {
144  for(j=width;j<sy-width;j++) {
145  pmsk[j*sx+i]=1;
146  }
147  }
148 
149  for(i=sx-width;i<sx;i++) {
150  for(j=width;j<sy-width;j++) {
151  pmsk[j*sx+i]=1;
152  }
153  }
154  sinfo_free_image(&mask); //is mask needed?
155 
156 
157  nrow=2*width*(sy-2*width);
158  check_nomsg(ima_backpix=cpl_image_new(nrow,1,CPL_TYPE_FLOAT));
159  check_nomsg(ima_backpos=cpl_image_new(nrow,1,CPL_TYPE_INT));
160 
161  check_nomsg(pima=cpl_image_get_data_float(ima_in));
162  check_nomsg(ppix=cpl_image_get_data_float(ima_backpix));
163  check_nomsg(ppos=cpl_image_get_data_int(ima_backpos));
164 
165  k=0;
166  for(i=0;i<width;i++) {
167  for(j=width;j<sy-width;j++) {
168  ppix[k]=pima[j*sx+i];
169  ppos[k]=j*sx+i;
170  k++;
171  }
172  }
173 
174  for(i=sx-width;i<sx;i++) {
175  for(j=width;j<sy-width;j++) {
176  ppix[k]=pima[j*sx+i];
177  ppos[k]=j*sx+i;
178  k++;
179  }
180  }
181 
182  check_nomsg(ima_ybackpix=cpl_image_duplicate(ima_backpos));
183  sinfo_free_image(&ima_backpos);
184 
185  check_nomsg(pbackpix=cpl_image_get_data_int(ima_ybackpix));
186 
187  check_nomsg(cpl_image_divide_scalar(ima_ybackpix,sx));
188  check_nomsg(pbackpix=cpl_image_get_data_int(ima_ybackpix));
189 
190 
191  check_nomsg(med_back=cpl_image_get_median(ima_backpix));
192  check_nomsg(ima_diffbackpix=cpl_image_duplicate(ima_backpix));
193  //sinfo_msg("med_back=%g",med_back);
194  check_nomsg(cpl_image_subtract_scalar(ima_diffbackpix,med_back));
195  //check_nomsg(cpl_image_save(ima_diffbackpix,"ima_diff.fits",
196  // CPL_BPP_IEEE_FLOAT,NULL,CPL_IO_DEFAULT));
197 
198  check_nomsg(filter=cpl_matrix_new(1,filt_rad));
199  check_nomsg(cpl_matrix_fill(filter,1.));
200  check_nomsg(ima_filt=sinfo_image_filter_median(ima_diffbackpix,filter));
201  sinfoni_free_matrix(&filter);
202  //check_nomsg(cpl_image_save(ima_filt,"ima_filt.fits",CPL_BPP_IEEE_FLOAT,
203  // NULL,CPL_IO_DEFAULT));
204 
205 
206  check_nomsg(sigma_back=cpl_image_get_stdev(ima_filt));
207  sinfo_free_image(&ima_filt);
208 
209  check_nomsg(ima=cpl_image_duplicate(ima_diffbackpix));
210  sinfo_free_image(&ima_diffbackpix);
211 
212  check_nomsg(cpl_image_abs(ima));
213  //sinfo_msg("sigma_back=%g",sigma_back);
214 
215  //find good pixels
216  check_nomsg(bpm_bad=cpl_mask_threshold_image_create(ima,kappa*sigma_back,
217  SINFO_DBL_MAX));
218  /*check_nomsg(bpm_good=cpl_mask_threshold_image_create(ima,SINFO_DBL_MIN,
219  kappa*sigma_back));
220  sinfo_free_mask(&bpm_good);
221  */
222  check_nomsg(cpl_image_reject_from_mask(ima_backpix,bpm_bad));
223  check_nomsg(medvalue=cpl_image_get_median(ima_backpix));
224  //sinfo_msg("medvalue=%g",sigma_back);
225  check_nomsg(nbad=cpl_mask_count(bpm_bad));
226  //sinfo_msg("nbad=%d",nbad);
227  check_nomsg(cpl_image_reject_from_mask(ima_backpix,bpm_bad));
228  sinfo_free_image(&ima_backpix);
229 
230  yprev=-1;
231 
232  check_nomsg(pbin=cpl_mask_get_data(bpm_bad));
233  check_nomsg(pbackpix=cpl_image_get_data_int(ima_ybackpix));
234  cpl_msg_debug(cpl_func, "%d lines detected", nbad);
235  if(nbad)
236  {
237 
238  ybad = cpl_calloc(nbad,sizeof(int));
239  k=0;
240 
241  for(i=0;i<nrow;i++) {
242  if(pbin[i] == CPL_BINARY_1) {
243  ybad[k]=pbackpix[i] + 1;
244  k++;
245  }
246  }
247  sinfo_free_mask(&bpm_bad);
248  sinfo_free_image(&ima_ybackpix);
249 
250  quicksort_int(&(ybad[0]), 0, nbad-1);
251  yprev=-1;
252  for(k=0;k<nbad;k++) {
253  yval=ybad[k];
254  if(yval == yprev) {
255  sinfo_msg_debug("skyp %d",yval);
256  }
257  else {
258  yprev=yval;
259  sinfo_msg_debug("correct raw %d",yval);
260  check_nomsg(tot=cpl_image_get_flux_window(ima_in,1,yval,width,yval));
261  check_nomsg(tot+=cpl_image_get_flux_window(ima_in,sx-width+1,
262  yval,sx,yval));
263  mean=tot/(2. * width);
264  check_nomsg(pima=cpl_image_get_data_float(*ima_out));
265  for(i=width;i<sx-width;i++) {
266  pima[i+(yval-1)*sx]+=(float)(mean-medvalue);
267  }
268 
269  }
270  }
271  }
272 
273 
274  cleanup:
275 
276  sinfo_free_image(&mask); //is mask needed?
277  sinfo_free_image(&ima_backpos);
278  sinfoni_free_matrix(&filter);
279  sinfo_free_image(&ima_filt);
280  sinfo_free_image(&ima_diffbackpix);
281  // sinfo_free_mask(&bpm_good);
282  sinfo_free_image(&ima_backpix);
283  sinfo_free_mask(&bpm_bad);
284  sinfo_free_image(&ima_ybackpix);
285  cpl_image_delete(ima);
286  cpl_free(ybad);
287  return cpl_error_get_code();
288 
289 }
290 
291 
300 double sinfo_new_my_median_image(cpl_image* im)
301 {
302  double m=0;
303  register int i=0;
304  int n=0;
305  pixelvalue* pv=0;
306  int ilx=0;
307  int ily=0;
308  float* pidata=NULL;
309 
310 
311  if(im==NULL) sinfo_msg_error("Null Image");
312  ilx=cpl_image_get_size_x(im);
313  ily=cpl_image_get_size_y(im);
314  pidata=cpl_image_get_data_float(im);
315 
316  for ( i = 0 ; i < (int) ilx*ily ; i++ )
317  {
318  if ( isnan(pidata[i]) )
319  {
320 
321  } else {
322  n++;
323  }
324  }
325  pv = cpl_calloc(n,sizeof(pixelvalue));
326  n=0;
327  for ( i = 0 ; i < (int) ilx*ily ; i++ )
328  {
329  if ( isnan(pidata[i]) )
330  {
331 
332  } else {
333  pv[n]=pidata[i];
334  n++;
335  }
336  }
337  if(pv == NULL || n == 0) {
338  m=0;
339  } else {
340  m=sinfo_new_median(pv,n);
341  }
342  cpl_free(pv);
343  if(isnan(m)){
344  m=0;
345  }
346  return m;
347 }
348 
358 Vector * sinfo_new_mean_of_columns( cpl_image *im )
359 {
360  Vector * row=NULL ;
361  int i=0;
362  int j=0;
363  int ilx=0;
364  int ily=0;
365  float* pidata=NULL;
366 
367  if ( im == NULL )
368  {
369  sinfo_msg_error ("null image") ;
370  return NullVector ;
371  }
372  ilx=cpl_image_get_size_x(im);
373  ily=cpl_image_get_size_y(im);
374  pidata=cpl_image_get_data_float(im);
375 
376  /* allocate memory for a row with the length of the image x-axis */
377  if ( NULL == (row = sinfo_new_vector (ilx)) )
378  {
379  sinfo_msg_error ("not able to allocate a sinfo_vector" ) ;
380  return NullVector ;
381  }
382 
383  for ( i = 0 ; i < ilx ; i++ )
384  {
385  for ( j = 0 ; j < ily ; j++ )
386  {
387  if (!isnan(pidata[i+j*ilx]))
388  {
389  row->data[i] += pidata[i + j*(ilx)] ;
390  }
391  }
392 
393  row->data[i] /= ily ;
394  }
395  return row ;
396 }
409 cpl_image * sinfo_new_clean_mean_of_columns( cpl_image *im,
410  float lo_reject,
411  float hi_reject)
412 {
413  cpl_image * row=NULL ;
414  pixelvalue* buffer=NULL ;
415  int i=0;
416  int j=0;
417  int k=0;
418 
419  int lo_n=0;
420  int hi_n=0;
421  int ilx=0;
422  int ily=0;
423  float* pidata=NULL;
424  float* podata=NULL;
425 
426  if ( im == NULL )
427  {
428  sinfo_msg_error ("null image") ;
429  return NULL ;
430  }
431  ilx=cpl_image_get_size_x(im);
432  ily=cpl_image_get_size_y(im);
433  pidata=cpl_image_get_data_float(im);
434 
435  if ((lo_reject + hi_reject) > 0.9)
436  {
437  sinfo_msg_error("illegal rejection thresholds: [%f] and [%f]",
438  lo_reject, hi_reject) ;
439  sinfo_msg_error("threshold sum should not be over "
440  "0.90 aborting average") ;
441  return NULL ;
442  }
443 
444  lo_n = (int) (ily * lo_reject + 0.5) ;
445  hi_n = (int) (ily * hi_reject + 0.5) ;
446  if (lo_n + hi_n >= ily)
447  {
448  sinfo_msg_error ("everything would be rejected") ;
449  return NULL ;
450  }
451 
452  /* allocate memory for a row with the length of the image x-axis */
453  if ( NULL == (row = cpl_image_new (ilx, 1,CPL_TYPE_FLOAT)) )
454  {
455  sinfo_msg_error ("cannot allocate new image") ;
456  return NULL ;
457  }
458  podata=cpl_image_get_data_float(row);
459 
460  buffer=(pixelvalue*) cpl_calloc(ily,sizeof(pixelvalue)) ;
461 
462  for ( i = 0 ; i < ilx ; i++ )
463  {
464  for ( j = 0 ; j < ily ; j++ )
465  {
466  buffer[j] = pidata[i + j*(ilx)] ;
467  }
468  sinfo_pixel_qsort (buffer, ily) ;
469 
470  int nv = 0 ;
471  for (k = lo_n ; k < ily - hi_n ; k ++)
472  {
473  if ( !isnan(buffer[k]) )
474  {
475  podata[i] += buffer[k] ;
476  nv ++ ;
477  }
478  }
479  podata[i] /= nv ;
480 
481  }
482  cpl_free(buffer);
483  return row ;
484 }
485 
486 
497 cpl_image * sinfo_new_div_image_by_row( cpl_image *im, Vector *row )
498 {
499  cpl_image *image=NULL ;
500  int i=0;
501  int j=0;
502  int ilx=0;
503  int ily=0;
504  float* pidata=NULL;
505  float* podata=NULL;
506 
507  if ( im == NULL || row == NULL )
508  {
509  sinfo_msg_error ("null image or null row") ;
510  return NULL ;
511  }
512  ilx=cpl_image_get_size_x(im);
513  ily=cpl_image_get_size_y(im);
514  pidata=cpl_image_get_data_float(im);
515 
516  if ( ilx != row -> n_elements )
517  {
518  sinfo_msg_error("image and row size not compatible") ;
519  return NULL ;
520  }
521 
522  if ( NULL == (image = cpl_image_duplicate (im)) )
523  {
524  sinfo_msg_error ("cannot copy image") ;
525  return NULL ;
526  }
527  podata=cpl_image_get_data_float(image);
528 
529  for (i = 0 ; i < ilx ; i++ )
530  {
531  for (j = 0 ; j < ily ; j++)
532  {
533  if ( !isnan(pidata[i + j*(ilx)]) )
534  {
535  podata[i + j*(ilx)] = pidata[i + j*(ilx)] / row -> data[i] ;
536  }
537  }
538  }
539  return image ;
540 }
541 
542 
553 cpl_image * sinfo_new_mult_row_to_image( cpl_image *im, Vector *row )
554 {
555  cpl_image *image=NULL;
556  int i=0;
557  int j=0;
558  int ilx=0;
559  int ily=0;
560  float* pidata=NULL;
561  float* podata=NULL;
562 
563 
564 
565 
566  if ( im == NULL || row == NULL )
567  {
568  sinfo_msg_error ("null image or null row") ;
569  return NULL ;
570  }
571  ilx=cpl_image_get_size_x(im);
572  ily=cpl_image_get_size_y(im);
573  pidata=cpl_image_get_data_float(im);
574 
575  if ( ilx != row -> n_elements )
576  {
577  sinfo_msg_error("image and row size not compatible") ;
578  return NULL ;
579  }
580 
581  if ( NULL == (image = cpl_image_duplicate (im)) )
582  {
583  sinfo_msg_error ("cannot copy image") ;
584  return NULL ;
585  }
586  podata=cpl_image_get_data_float(image);
587 
588  for (i = 0 ; i < ilx ; i++ )
589  {
590  for (j = 0 ; j < ily ; j++)
591  {
592  if ( !isnan(pidata[i + j*(ilx)]) )
593  {
594  podata[i + j*(ilx)] = pidata[i + j*(ilx)] * row -> data[i] ;
595  }
596  }
597  }
598  return image ;
599 }
600 
601 
602 
603 
604 
605 
631 cpl_image * sinfo_new_col_tilt ( cpl_image * image, float sigmaFactor )
632 {
633  cpl_image * im=NULL;
634  float * column=NULL ;
635 
636 
637  double mean=0;
638  float sinfo_median=0;
639  float noise=0 ;
640 
641 
642  float a=0;
643  float b=0;
644  float siga=0;
645  float sigb=0;
646  float chi2=0;
647  float q=0;
648  int i=0;
649  int j=0;
650 
651 
652  int mwt=0 ;
653  int lx=0;
654  int ly=0;
655  float* p_in_data=NULL;
656  float* p_ou_data=NULL;
657 
658 
659  if ( image == NULL )
660  {
661  sinfo_msg_error ("no image given" ) ;
662  return NULL ;
663  }
664 
665  if ( sigmaFactor <= 0. )
666  {
667  sinfo_msg_error ("no or negative sigma factor") ;
668  return NULL ;
669  }
670  lx = cpl_image_get_size_x(image);
671  ly = cpl_image_get_size_y(image);
672 
673 
674  /* allocate memory */
675  if ( NULL == (im = cpl_image_new (lx,ly,CPL_TYPE_FLOAT )) )
676  {
677  sinfo_msg_error ("cannot allocate new image" ) ;
678  return NULL ;
679  }
680 
681  /* go through the columns */
682  p_in_data = cpl_image_get_data_float(image);
683  p_ou_data = cpl_image_get_data_float(im);
684  for ( i = 0 ; i < lx ; i ++ )
685  {
686  /* initialize the buffer variables for each column */
687  int colnum = 0 ;
688  column = (float *) cpl_calloc ( ly , sizeof (float *) ) ;
689  float* sig = (float *) cpl_calloc ( ly , sizeof (float *) ) ;
690  float* dat = (float *) cpl_calloc ( ly , sizeof (float *) ) ;
691 
692  /*select only non-ZERO values of one column*/
693  for ( j = 0 ; j < ly ; j++ )
694  {
695  if ( !isnan(p_in_data[i + j*lx]) )
696  {
697  column[j] = p_in_data[i + j*lx] ;
698  colnum ++ ;
699  }
700  }
701  if ( colnum < 10 )
702  {
703  /*sinfo_msg_warning ("sinfo_new_col_tilt:",
704  "column %d has almost only blank pixels and is set to blank", i+1) ;*/
705  for ( j = 0 ; j < ly ; j++ )
706  {
707  p_ou_data[i + j*lx] = ZERO;
708  }
709  /*
710  cpl_free (column) ;
711  cpl_free (sig);
712  cpl_free (dat) ;
713  continue ;
714  */
715  }
716 
717  /*-------------------------------------------------------------------
718  * sort the data, clip off the extremes, determine the noise
719  * and get the range for the valid data. It is assumed here
720  * that most pixels are o.k.
721  */
722 
723  sinfo_pixel_qsort (column, colnum) ;
724 
725  double sum = 0. ;
726  double sum2 = 0. ;
727  int npix = 0 ;
728 
729  for ( j = 0.1*colnum + 1 ; j <= 0.9*colnum ; j++ )
730  {
731  sum += column[j] ;
732  sum2 += column[j] * column[j] ;
733  npix ++ ;
734  }
735 
736  if (npix <= 1)
737  {
738  noise = sigmaFactor * 1000.;
739  }
740  else
741  {
742  mean = sum/(float)npix ;
743  noise = sqrt( (sum2 - sum*mean)/(double)(npix -1) ) ;
744  noise *= sigmaFactor ;
745  }
746 
747  /* -------------------------------------------------------------
748  * determine sinfo_median if colnum is odd, sinfo_median will be the
749  colnum/2 th value, otherwise
750  * sinfo_median is the mean of colnum/2-1 th and colnum/2 th value.
751  */
752 
753  if ( colnum % 2 == 1 )
754  {
755  sinfo_median = column[colnum/2] ;
756  }
757  else
758  {
759  sinfo_median = (column[colnum/2 - 1] + column[colnum/2])/2. ;
760  }
761 
762  /* now select the pixels for the tilt calculation */
763 
764  colnum = 0 ;
765  for ( j = 0; j < ly ; j ++ )
766  {
767  if ( !isnan(p_in_data[i+j*lx]) &&
768  fabs ( (p_in_data[i+j*lx]) - sinfo_median) <= noise )
769  {
770  column[colnum] = p_in_data[i+j*lx] ;
771  dat[colnum] = (float) j ;
772  sig[colnum] = 1. ;
773  colnum ++ ;
774  }
775  }
776 
777  if ( colnum == 0 )
778  {
779  /*for ( j = 0; j < ly; j++ )
780  {
781  p_ou_data[i+j*lx] -= sinfo_median ;
782  }
783  cpl_free (column) ;
784  cpl_free (sig) ;
785  cpl_free (dat) ;
786  continue ;*/
787  a=0./0.;
788  b=0./0.;
789  }
790  else
791  {
792  mwt = 0 ;
793  sinfo_my_fit ( dat, column, colnum, sig, mwt, &a,
794  &b, &siga, &sigb, &chi2, &q ) ;
795  }
796  if ( fabs(b) >= SLOPE || fabs(a) >= SATURATION ||
797  isnan(b) || isnan(a))
798  {
799  sinfo_msg_warning ("linear fit: slope is greater than limit: %f"
800  " saturation level is reached: %f in column"
801  " number %d ", b, a , i+1) ;
802  }
803 
804  /* subtract fit or sinfo_median from data */
805  for ( j = 0; j < ly; j++ )
806  {
807  if ( !isnan(p_in_data[i+j*lx]) &&
808  fabs(b) < SLOPE && fabs(a) < SATURATION )
809  {
810  p_ou_data[i+j*lx] = p_in_data[i+j*lx] - (a + b * (float)j) ;
811  }
812  else if ( isnan(p_in_data[i+j*lx]) )
813  {
814  p_ou_data[i+j*lx] = ZERO ;
815  }
816  else if ( (fabs(b) >= SLOPE ||
817  fabs(a) >= SATURATION || isnan(a) || isnan(b)) &&
818  !isnan(p_in_data[i+j*lx]) )
819  {
820  p_ou_data[i+j*lx] -= sinfo_median ;
821  }
822  else
823  {
824  sinfo_msg_error (" case is not possible! %f %f", b,a) ;
825  /*cpl_free (column) ;
826  cpl_free (sig) ;
827  cpl_free (dat) ;
828  cpl_image_delete(im) ;
829  return NULL ;*/
830  }
831  }
832  cpl_free (column) ;
833  cpl_free (sig) ;
834  cpl_free (dat) ;
835  }
836 
837  return im ;
838 }
839 
840 
841 
842 
843 
868 cpl_image * sinfo_new_median_image( cpl_image * im, float fmedian )
869 {
870  cpl_image * image=NULL ;
871  pixelvalue * value=NULL ;
872  pixelvalue sinfo_median=0 ;
873  int * position=NULL ;
874  int nposition=0 ;
875  int n=0;
876  int i=0;
877  int j=0;
878  int lx=0;
879  int ly=0;
880  float* p_in_data=NULL;
881  float* p_ou_data=NULL;
882  int im_size=0;
883  if ( im == NULL )
884  {
885  sinfo_msg_error ("no image input") ;
886  return NULL ;
887  }
888 
889  image = cpl_image_duplicate ( im ) ;
890  lx=cpl_image_get_size_x(im);
891  ly=cpl_image_get_size_y(im);
892  im_size=lx*ly;
893  p_in_data=cpl_image_get_data_float(im);
894  p_ou_data=cpl_image_get_data_float(image);
895 
896  /*----------------------------------------------------------------------
897  * go through all pixels
898  */
899 
900  for ( i = 0 ; i < im_size ; i++ )
901  {
902  /* blank pixels are not replaced */
903  if ( isnan(p_in_data[i]) )
904  {
905  continue ;
906  }
907 
908  /* initialize the buffer variables for the 8 nearest neighbors */
909  value = (pixelvalue * )cpl_calloc ( 8, sizeof ( pixelvalue * ) ) ;
910  position = ( int * ) cpl_calloc ( 8, sizeof ( int * ) ) ;
911 
912  /*--------------------------------------------------------------------
913  * determine the pixel position of the 8 nearest neighbors
914  */
915 
916  position[0] = i + lx - 1 ; /* upper left */
917  position[1] = i + lx ; /* upper */
918  position[2] = i + lx + 1 ; /* upper right */
919  position[3] = i + 1 ; /* right */
920  position[4] = i - lx + 1 ; /* lower right */
921  position[5] = i - lx ; /* lower */
922  position[6] = i - lx - 1 ; /* lower left */
923  position[7] = i - 1 ; /* left */
924 
925  /*-------------------------------------------------------------------
926  * determine the positions of the image margins, top positions are
927  changed to low positions and vice versa. Right positions are
928  changed to left positions and vice versa.
929  */
930 
931  if ( i >= 0 && i < lx ) /* bottom line */
932  {
933  position[4] += 2 * lx ;
934  position[5] += 2 * lx ;
935  position[6] += 2 * lx ;
936  }
937  else if ( i >= ((int) lx*ly - lx ) && i < (int) lx*ly ) /* top line */
938  {
939  position[0] -= 2 * lx ;
940  position[1] -= 2 * lx ;
941  position[2] -= 2 * lx ;
942  }
943  else if ( i % lx == 0 ) /* left side */
944  {
945  position[0] += 2 ;
946  position[6] += 2 ;
947  position[7] += 2 ;
948  }
949  else if ( i % lx == lx - 1 ) /* right side */
950  {
951  position[2] -= 2 ;
952  position[3] -= 2 ;
953  position[4] -= 2 ;
954  }
955 
956  /* --------------------------------------------------------------------
957  * read the pixel values of the neighboring pixels,
958  * blanks are not considered
959  */
960 
961  nposition = 8 ;
962  n = 0 ;
963  for ( j = 0 ; j < nposition ; j ++ )
964  {
965  if((position[j] >-1 ) && (position[j]<im_size)) {
966  if ( !isnan(p_in_data[position[j]]) )
967  {
968  value[n] = p_in_data[position[j]] ;
969  n ++ ;
970  }
971  }
972  }
973  nposition = n ;
974 
975  if ( nposition <= 1 ) /* almost all neighbors are blank */
976  {
977  p_ou_data[i] = ZERO ;
978  cpl_free(value) ;
979  cpl_free(position) ;
980  continue ;
981  }
982 
983  /* sort the values and determine the sinfo_median */
984 
985  sinfo_pixel_qsort ( value, nposition ) ;
986  if ( nposition % 2 == 1 )
987  {
988  sinfo_median = value [ nposition/2 ] ;
989  }
990  else
991  {
992  sinfo_median = ( value [nposition/2 - 1] +
993  value [nposition/2] ) / 2. ;
994  }
995 
996  /* -----------------------------------------------------------------
997  * replace the pixel value by the sinfo_median on conditions:
998  * fmedian = 0: always replace with sinfo_median.
999  * fmedian < 0: interpret as absolute condition:
1000  * if |pixel - sinfo_median| > -fmedian
1001  * replace with sinfo_median.
1002  * fmedian > 0: replace by sinfo_median (fmedian as a factor of
1003  * the square root of the sinfo_median itself)
1004  * if |pixel - sinfo_median| >= fmedian *
1005  sqrt ( sinfo_median )
1006  * considers a dependence on the pixel value.
1007  * This can be used to consider photon noise.
1008  */
1009 
1010  if ( fmedian == 0 )
1011  {
1012  p_ou_data[i] = sinfo_median ;
1013  }
1014  else if ( fmedian < 0 &&
1015  fabs ( sinfo_median - p_in_data[i] ) >= -fmedian )
1016  {
1017  p_ou_data[i] = sinfo_median ;
1018  }
1019  else if ( fmedian > 0 &&
1020  fabs ( sinfo_median - p_in_data[i] ) >= fmedian *
1021  sqrt(fabs(sinfo_median)) )
1022  {
1023  p_ou_data[i] = sinfo_median ;
1024  }
1025  else
1026  {
1027  cpl_free (value) ;
1028  cpl_free (position) ;
1029  continue ;
1030  }
1031 
1032  cpl_free (value) ;
1033  cpl_free (position) ;
1034  }
1035  return image ;
1036 }
1037 
1038 
1039 
1040 
1052 cpl_image *
1053 sinfo_new_compare_images(cpl_image * im1,cpl_image * im2,cpl_image * origim )
1054 {
1055  cpl_image * image=NULL ;
1056  int i=0 ;
1057  int lx1=0;
1058  int ly1=0;
1059  int lx2=0;
1060  int ly2=0;
1061  float* p_in1_data=NULL;
1062  float* p_in2_data=NULL;
1063  float* p_ou_data=NULL;
1064  float* p_org_data=NULL;
1065 
1066 
1067  if ( im1 == NULL || im2 == NULL || origim == NULL )
1068  {
1069  sinfo_msg_error ("Null images as input" ) ;
1070  return NULL ;
1071  }
1072  lx1=cpl_image_get_size_x(im1);
1073  ly1=cpl_image_get_size_y(im1);
1074 
1075  lx2=cpl_image_get_size_x(im2);
1076  ly2=cpl_image_get_size_y(im2);
1077 
1078  p_in1_data=cpl_image_get_data_float(im1);
1079  p_in2_data=cpl_image_get_data_float(im2);
1080  p_org_data=cpl_image_get_data_float(origim);
1081  if ( lx1 != lx2 || ly1 != ly2 )
1082  {
1083  sinfo_msg_error ("incompatible image sizes" ) ;
1084  return NULL ;
1085  }
1086 
1087  /* allocate memory */
1088  if ( NULL == (image = cpl_image_new ( lx1, ly1, CPL_TYPE_FLOAT )) )
1089  {
1090  sinfo_msg_error ("cannot allocate new image" ) ;
1091  return NULL ;
1092  }
1093  p_ou_data=cpl_image_get_data_float(image);
1094  for ( i = 0 ; i < (int) lx1*ly1 ; i ++ )
1095  {
1096  if ( isnan(p_in1_data[i]) && isnan(p_in2_data[i]) )
1097  {
1098  p_ou_data[i] = ZERO ;
1099  }
1100  else
1101  {
1102  if ( p_in1_data[i] == p_in2_data[i] )
1103  {
1104  p_ou_data[i] = p_org_data[i] ;
1105  }
1106  else
1107  {
1108  p_ou_data[i] = ZERO ;
1109  }
1110  }
1111  }
1112  return image ;
1113 }
1114 
1115 
1116 
1129 cpl_image *
1130 sinfo_new_promote_image_to_mask (cpl_image * im, int * n_badpixels )
1131 {
1132  cpl_image * reImage=NULL ;
1133  int i=0 ;
1134  int lx=0;
1135  int ly=0;
1136  float* p_in_data=NULL;
1137  float* p_ou_data=NULL;
1138 
1139  if ( NULL == im )
1140  {
1141  sinfo_msg_error("no input image given!") ;
1142  return NULL ;
1143  }
1144  lx=cpl_image_get_size_x(im);
1145  ly=cpl_image_get_size_y(im);
1146  p_in_data=cpl_image_get_data_float(im);
1147 
1148  /* allocate memory for the returned image */
1149  if ( NULL == (reImage = cpl_image_new (lx,ly,CPL_TYPE_FLOAT )) )
1150  {
1151  sinfo_msg_error ("cannot allocate new image!") ;
1152  return NULL ;
1153  }
1154  p_ou_data=cpl_image_get_data_float(reImage);
1155 
1156  *n_badpixels = 0 ;
1157  for ( i = 0 ; i < (int) lx*ly ; i ++ )
1158  {
1159  if ( isnan(p_in_data[i]) )
1160  {
1161  p_ou_data[i] = 0. ;
1162  (*n_badpixels)++ ;
1163  }
1164  else
1165  {
1166  p_ou_data[i] = 1. ;
1167  }
1168  }
1169  return reImage ;
1170 }
1171 
1172 
1184 cpl_image * sinfo_new_mult_image_by_mask (cpl_image * im,cpl_image * mask )
1185 {
1186  cpl_image * reImage=NULL ;
1187  int i=0 ;
1188  int ix=0;
1189  int iy=0;
1190  int mx=0;
1191  int my=0;
1192 
1193 
1194  float* pmdata=NULL;
1195  float* podata=NULL;
1196 
1197  if ( NULL == im )
1198  {
1199  sinfo_msg_error("no input image given!") ;
1200  return NULL ;
1201  }
1202  if ( NULL == mask )
1203  {
1204  sinfo_msg_error("no mask image given!") ;
1205  return NULL ;
1206  }
1207  ix=cpl_image_get_size_x(im);
1208  iy=cpl_image_get_size_y(im);
1209  mx=cpl_image_get_size_x(mask);
1210  my=cpl_image_get_size_y(mask);
1211 
1212  if ( ix != mx || iy != my)
1213  {
1214  sinfo_msg_error("image sizes are not correspondent!") ;
1215  return NULL ;
1216  }
1217 
1218  reImage = cpl_image_duplicate( im ) ;
1219  podata=cpl_image_get_data_float(reImage);
1220  pmdata=cpl_image_get_data_float(mask);
1221 
1222  for ( i = 0 ; i < (int) ix*iy ; i ++ )
1223  {
1224  if ( pmdata[i] == 0. )
1225  {
1226  podata[i] = ZERO ;
1227  }
1228  }
1229 
1230  return reImage ;
1231 }
1232 
1233 
1234 
1245 cpl_image *
1246 sinfo_new_thresh_image (cpl_image * im, float lo_cut, float hi_cut )
1247 {
1248  cpl_image * image=NULL ;
1249  float* p_inp_data=NULL;
1250  float* p_out_data=NULL;
1251  int lx=0;
1252  int ly=0;
1253 
1254  int i=0 ;
1255 
1256  if (im == NULL)
1257  {
1258  sinfo_msg_error ("null image given") ;
1259  return NULL ;
1260  }
1261  lx=cpl_image_get_size_x(im);
1262  ly=cpl_image_get_size_y(im);
1263 
1264  image = cpl_image_duplicate(im) ;
1265  p_inp_data=cpl_image_get_data(im);
1266  p_out_data=cpl_image_get_data(image);
1267  for ( i = 0 ; i < (int) lx*ly ; i ++ )
1268  {
1269  if ( p_inp_data[i] > (pixelvalue) hi_cut ||
1270  p_inp_data[i] < (pixelvalue) lo_cut )
1271  {
1272  p_out_data[i] = ZERO ;
1273  }
1274  }
1275  return image ;
1276 }
1277 
1278 
1279 
1280 
1306 cpl_image * sinfo_new_interpol_image ( cpl_image * im,
1307  cpl_image * mask,
1308  int max_radius,
1309  int n_pixels )
1310 {
1311  cpl_image * returnImage=NULL ;
1312  float* neighbors=NULL ;
1313  float sum=0;
1314  float mean=0;
1315  int i=0;
1316  int j=0;
1317  int k=0;
1318  int row=0;
1319  int col=0;
1320  int n_valid=0;
1321  int agreed=0;
1322 
1323  int ilx=0;
1324  int ily=0;
1325  int mlx=0;
1326  int mly=0;
1327  float* pidata=NULL;
1328  float* podata=NULL;
1329  float* pmdata=NULL;
1330 
1331  if ( NULL == im )
1332  {
1333  sinfo_msg_error("sorry, no input image given!") ;
1334  return NULL ;
1335  }
1336  ilx=cpl_image_get_size_x(im);
1337  ily=cpl_image_get_size_y(im);
1338  pidata=cpl_image_get_data_float(im);
1339 
1340  if ( NULL == mask )
1341  {
1342  sinfo_msg_error("sorry, no mask image given!") ;
1343  return NULL ;
1344  }
1345 
1346  mlx=cpl_image_get_size_x(mask);
1347  mly=cpl_image_get_size_y(mask);
1348  pmdata=cpl_image_get_data_float(mask);
1349 
1350  if ( mlx != ilx || mly != ily )
1351  {
1352  sinfo_msg_error("images not compatible !") ;
1353  return NULL ;
1354  }
1355 
1356  if ( max_radius <= 0 )
1357  {
1358  sinfo_msg_error("wrong number of pixels for maximal "
1359  "search radius given!") ;
1360  return NULL ;
1361  }
1362 
1363  if ( n_pixels <= 2 )
1364  {
1365  sinfo_msg_error("wrong number of pixels used "
1366  "for interpolation given!") ;
1367  return NULL ;
1368  }
1369 
1370  returnImage = cpl_image_duplicate ( im ) ;
1371  podata=cpl_image_get_data_float(returnImage);
1372 
1373  /* go through the columns and rows of the input and mask image */
1374  neighbors=cpl_calloc(4*max_radius*max_radius,sizeof(float)) ;
1375 
1376  for ( col = 0 ; col < ilx ; col++ )
1377  {
1378  for ( row = 0 ; row < ily ; row++ )
1379  {
1380  /* look for the ZEROS that means the detected bad pixels */
1381  if ( isnan(pmdata[col+row*ilx]) || pmdata[col+row*ilx] == 0. )
1382  {
1383  /* now the neighbors must be considered */
1384  n_valid = 0 ;
1385  agreed = 0 ;
1386  for ( j = 1 ; j <= max_radius ; j++ )
1387  {
1388 
1389  /* go through the left column */
1390  for ( k = -j ; k < j ; k++ )
1391  {
1392  if ( col-j >= 0 && row+k < ily && row+k >= 0 )
1393  {
1394  if ( !isnan(pmdata[col-j+(row+k)*mlx]) ||
1395  pmdata[col-j+(row+k)*mlx] != 0 )
1396  {
1397  neighbors[n_valid]=pidata[col-j+(row+k)*ilx] ;
1398  n_valid++ ;
1399  }
1400  }
1401  }
1402 
1403  /* go through the upper row */
1404  for ( k = -j ; k < j ; k++ )
1405  {
1406  if ( col+k < ilx && col+k >= 0 && row+j < ily )
1407  {
1408  if ( !isnan(pmdata[col+k+(row+j)*mlx]) ||
1409  pmdata[col+k+(row+j)*mlx] != 0. )
1410  {
1411  neighbors[n_valid]=pidata[col+k+(row+j)*ilx] ;
1412  n_valid++ ;
1413  }
1414  }
1415  }
1416 
1417  /* go through the right column */
1418  for ( k = -j ; k < j ; k++ )
1419  {
1420  if ( col+j < ilx && row-k >= 0 && row-k < ily )
1421  {
1422  if ( !isnan(pmdata[col+j+(row-k)*mlx]) ||
1423  pmdata[col+j+(row-k)*mlx] != 0. )
1424  {
1425  neighbors[n_valid]=pidata[col+j+(row-k)*ilx] ;
1426  n_valid++ ;
1427  }
1428  }
1429  }
1430 
1431  /* go through the lower row */
1432  for ( k = -j ; k < j ; k++ )
1433  {
1434  if ( col-k >= 0 && col-k < ilx && row-j < ily )
1435  {
1436  if ( !isnan(pmdata[col-k+(row-j)*mlx]) ||
1437  pmdata[col-k+(row-j)*mlx] != 0. )
1438  {
1439  neighbors[n_valid]=pidata[col-k+(row-j)*ilx] ;
1440  n_valid++ ;
1441  }
1442  }
1443  }
1444 
1445  /* control if the breaking criteria is fullfilled */
1446  if ( n_valid >= n_pixels )
1447  {
1448  agreed = 1 ;
1449  break ;
1450  }
1451  /* do a break if more than 2 nearest neighbors are found */
1452  if ( j == 1 && n_valid >= 2 )
1453  {
1454  agreed = 1 ;
1455  break ;
1456  }
1457  }
1458  if ( n_valid < n_pixels && agreed == 0 )
1459  {
1460  sinfo_msg_error("not enough valid neighbors found to "
1461  "interpolate bad pixel in col: "
1462  "%d, row: %d", col, row ) ;
1463  return NULL ;
1464  }
1465  else
1466  {
1467  /* ------------------------------------------------------
1468  * take the mean of the valid neighboring pixels if less
1469  * than 9 valid pixels are available else take the
1470  sinfo_median.
1471  */
1472  if ( n_valid <= 8 )
1473  {
1474  sum = 0. ;
1475 
1476  for ( i = 0 ; i < n_valid ; i++ )
1477  {
1478  sum += neighbors[i] ;
1479  }
1480  mean = sum / n_valid ;
1481 
1482  podata[col+row*ilx] = mean ;
1483  }
1484  else
1485  {
1486  podata[col+row*ilx]=sinfo_new_median(neighbors,n_valid);
1487  }
1488  }
1489  }
1490  }
1491  }
1492  cpl_free(neighbors);
1493  return returnImage ;
1494 }
1495 
1496 
1520 cpl_image * sinfo_interpol_source_image ( cpl_image * im,
1521  cpl_image * mask,
1522  int max_rad,
1523  float ** slit_edges )
1524 {
1525  cpl_image * returnImage=NULL ;
1526  float validpixel[6] ;
1527  float sum=0 ;
1528  int n=0;
1529  int row=0;
1530  int col=0;
1531  int i=0;
1532  int k=0;
1533  int slitlet=0;
1534  int n_slitlets=0;
1535  int ilx=0;
1536  int ily=0;
1537  int mlx=0;
1538  int mly=0;
1539 
1540  float* pidata=NULL;
1541  float* podata=NULL;
1542  float* pmdata=NULL;
1543 
1544 
1545  if ( NULL == im )
1546  {
1547  sinfo_msg_error("sorry, no input image given!") ;
1548  return NULL ;
1549  }
1550  ilx=cpl_image_get_size_x(im);
1551  ily=cpl_image_get_size_y(im);
1552  pidata=cpl_image_get_data_float(im);
1553 
1554  if ( NULL == mask )
1555  {
1556  sinfo_msg_error("sorry, no bad pixel mask image given!") ;
1557  return NULL ;
1558  }
1559  mlx=cpl_image_get_size_x(mask);
1560  mly=cpl_image_get_size_y(mask);
1561  pmdata=cpl_image_get_data_float(mask);
1562 
1563  if ( mlx != ilx || mly != ily )
1564  {
1565  sinfo_msg_error("images not compatible in size!") ;
1566  return NULL ;
1567  }
1568 
1569  if ( max_rad < 1 )
1570  {
1571  sinfo_msg_error("sorry, wrong maximum distance given!") ;
1572  return NULL ;
1573  }
1574 
1575  if ( slit_edges == NULL )
1576  {
1577  sinfo_msg_error("sorry, array slit_edges is empty!") ;
1578  return NULL ;
1579  }
1580 
1581  /* determine the number of slitlets */
1582  n_slitlets = N_SLITLETS ;
1583 
1584  /* copy the original image in the image that will be returned */
1585  returnImage = cpl_image_duplicate( im ) ;
1586  podata=cpl_image_get_data_float(returnImage);
1587 
1588  /* go through the rows and columns of the image and search for
1589  the bad pixels */
1590  for ( row = 0 ; row < ily ; row++ )
1591  {
1592  for ( col = 0 ; col < ilx ; col++ )
1593  {
1594  n = 0 ;
1595  if ( isnan(pmdata[col + row*mlx]) ||
1596  pmdata[col + row*mlx] == 0. ||
1597  isnan(pidata[col + row*mlx]) )
1598  {
1599  /* look for the slitlet where the bad pixel is found */
1600  slitlet = -1000 ;
1601  for ( k = 0 ; k < n_slitlets ; k++ )
1602  {
1603  if ( sinfo_new_nint(slit_edges[k][0]) <= col &&
1604  sinfo_new_nint(slit_edges[k][1]) >= col )
1605  {
1606  slitlet = k ;
1607  }
1608  /* The following else statement is wrong, because in the
1609  end slitlet will always be -1000
1610  else
1611  {
1612  slitlet = -1000 ;
1613  }
1614  */
1615  }
1616  for ( i = 0 ; i < 6 ; i++ )
1617  {
1618  validpixel[i] = 0. ;
1619  }
1620  /* look for the valid nearest neighbors
1621  and collect them but only a maximum of 4 */
1622  for ( i = 1 ; i <= max_rad ; i++ )
1623  {
1624  if ( row + i < ily)
1625  {
1626  if ( !isnan(pmdata[col + (row+i) * mlx])
1627  && pmdata[col + (row+i) * mlx] != 0. &&
1628  !isnan(pidata[col + (row+i) * ilx]) )
1629  {
1630  validpixel[n] = pidata[col + (row+i) * ilx] ;
1631  n++ ;
1632  }
1633  }
1634  if ( row - i >= 0 )
1635  {
1636  if ( !isnan(pmdata[col + (row-i) * mlx])
1637  && pmdata[col + (row-i) * mlx] != 0. &&
1638  !isnan(pidata[col + (row-i) * ilx]) )
1639  {
1640  validpixel[n] = pidata[col + (row-i) * ilx] ;
1641  n++ ;
1642  }
1643  }
1644 
1645  /* be aware of the slitlet edges in the
1646  spatial direction */
1647  if ( col + i < ilx )
1648  {
1649  if ( slitlet != -1000 )
1650  {
1651  if (col+i <= sinfo_new_nint(slit_edges[slitlet][1]) &&
1652  !isnan(pmdata[col + i + row * mlx]) &&
1653  pmdata[col + i + row * mlx] != 0. &&
1654  !isnan(pidata[col + i + row * ilx]) )
1655  {
1656  validpixel[n] = pidata[col + i + row * ilx] ;
1657  n++ ;
1658  }
1659  }
1660  }
1661  if ( col - i >= 0 )
1662  {
1663  if ( slitlet != -1000 )
1664  {
1665  if (col-i >= sinfo_new_nint(slit_edges[slitlet][0]) &&
1666  !isnan(pmdata[col - i + row * mlx]) &&
1667  pmdata[col - i + row * mlx] != 0. &&
1668  !isnan(pidata[col - i + row * ilx]) )
1669  {
1670  validpixel[n] = pidata[col - i + row * ilx] ;
1671  n++ ;
1672  }
1673  }
1674  }
1675 
1676  if ( i == 1 && n > 1 )
1677  {
1678  break ;
1679  }
1680  if ( n > 2 )
1681  {
1682  break ;
1683  }
1684  }
1685 
1686  if ( n == 0 )
1687  {
1688  podata[col + row*ilx] = ZERO ;
1689  /*sinfo_msg_warning("sinfo_interpolSourceImage:",
1690  "bad pixel in column: %d and row: %d"
1691  " could not be interpolated!",col,row);
1692  */
1693  }
1694  else
1695  {
1696  /* now compute the mean and replace
1697  the bad pixel value by the mean */
1698  sum = 0. ;
1699  for ( i = 0 ; i < n ; i++ )
1700  {
1701  sum += validpixel[i] ;
1702  }
1703  podata[col + row*ilx] = sum/n ;
1704  }
1705  }
1706  }
1707  }
1708 
1709  return returnImage ;
1710 }
1711 
1721 cpl_image * sinfo_new_stack_row_to_image ( Vector * row, int ly )
1722 {
1723  cpl_image * image=NULL;
1724  int col=0;
1725  int ro=0;
1726  float* podata=NULL;
1727 
1728  if ( row == NullVector )
1729  {
1730  sinfo_msg_error ("Null sinfo_vector as input" ) ;
1731  return NULL ;
1732  }
1733  if ( ly <= 1 )
1734  {
1735  sinfo_msg_error ("wrong image length given" ) ;
1736  return NULL ;
1737  }
1738 
1739  /* allocate memory */
1740  if (NULL == (image = cpl_image_new(row->n_elements ,ly,CPL_TYPE_FLOAT )) )
1741  {
1742  sinfo_msg_error ("cannot allocate new image" ) ;
1743  return NULL ;
1744  }
1745  podata=cpl_image_get_data_float(image);
1746 
1747  for ( col = 0 ; col < row -> n_elements ; col++ )
1748  {
1749  for ( ro = 0 ; ro < ly ; ro++ )
1750  {
1751  podata[col + ro*ly] = row -> data[col] ;
1752  }
1753  }
1754  return image ;
1755 }
1756 
1773 Stats * sinfo_new_image_stats_on_rectangle ( cpl_image * im,
1774  float loReject,
1775  float hiReject,
1776  int llx,
1777  int lly,
1778  int urx,
1779  int ury )
1780 {
1781  Stats * retstats=NULL;
1782  int i=0 ;
1783  int row=0;
1784  int col=0;
1785  int n=0;
1786  int npix=0;
1787  int lo_n=0;
1788  int hi_n=0;
1789  double pix_sum=0;
1790  double sqr_sum=0;
1791  float * pix_array=NULL;
1792  int im_lx=0;
1793  int im_ly=0;
1794  float* pim=NULL;
1795 
1796  if ( NULL == im )
1797  {
1798  sinfo_msg_error("sorry, no input image given!") ;
1799  return NULL ;
1800  }
1801  if ( loReject+hiReject >= 100. )
1802  {
1803  sinfo_msg_error("sorry, too much pixels rejected!") ;
1804  return NULL ;
1805  }
1806  if ( loReject < 0. || loReject >= 100. ||
1807  hiReject < 0. || hiReject >= 100. )
1808  {
1809  sinfo_msg_error("sorry, negative reject values!") ;
1810  return NULL ;
1811  }
1812 
1813  im_lx=cpl_image_get_size_x(im);
1814  im_ly=cpl_image_get_size_y(im);
1815 
1816  if ( llx < 0 || lly < 0 || urx < 0 || ury < 0 ||
1817  llx >= im_lx || lly >= im_ly || urx >= im_lx ||
1818  ury >= im_ly || ury <= lly || urx <= llx )
1819  {
1820  sinfo_msg_error("sorry, wrong pixel coordinates of rectangle!") ;
1821  return NULL ;
1822  }
1823 
1824  /* allocate memory */
1825  retstats = (Stats*) cpl_calloc(1, sizeof(Stats)) ;
1826  npix = (urx - llx + 1) * (ury - lly + 1) ;
1827  pix_array = (float*) cpl_calloc ( npix, sizeof(float) ) ;
1828 
1829  /*-------------------------------------------------------------------------
1830  * go through the rectangle and copy the pixel values into an array.
1831  */
1832  n = 0 ;
1833  pim = cpl_image_get_data_float(im);
1834  for ( row = lly ; row <= ury ; row++ )
1835  {
1836  for ( col = llx ; col <= urx ; col++ )
1837  {
1838  if ( !isnan(pim[col + row*im_lx]) )
1839  {
1840  pix_array[n] = pim[col + row*im_lx] ;
1841  n++ ;
1842  }
1843  }
1844  }
1845 
1846  npix = n;
1847  /*if (n != npix)
1848  {
1849  sinfo_msg_error("the computed number of pixel equals "
1850  "not the counted number, impossible!") ;
1851  cpl_free(retstats) ;
1852  cpl_free(pix_array) ;
1853  return NULL ;
1854  }*/
1855 
1856  /* determining the clean mean is already done in the recipes */
1857  if ( FLT_MAX == (retstats->cleanmean = sinfo_new_clean_mean(pix_array,
1858  npix, loReject, hiReject)) )
1859  {
1860  sinfo_msg_error("sinfo_new_clean_mean() did not work!") ;
1861  cpl_free(retstats) ;
1862  cpl_free(pix_array) ;
1863  return NULL ;
1864  }
1865 
1866  /* now the clean standard deviation must be calculated */
1867  /* initialize sums */
1868  lo_n = (int) (loReject / 100. * (float)npix) ;
1869  hi_n = (int) (hiReject / 100. * (float)npix) ;
1870  pix_sum = 0. ;
1871  sqr_sum = 0. ;
1872  n = 0 ;
1873  for ( i = lo_n ; i <= npix - hi_n ; i++ )
1874  {
1875  pix_sum += (double)pix_array[i] ;
1876  sqr_sum += ((double)pix_array[i] * (double)pix_array[i]) ;
1877  n++ ;
1878  }
1879 
1880  if ( n == 0 )
1881  {
1882  sinfo_msg_error("number of clean pixels is zero!") ;
1883  cpl_free(retstats) ;
1884  cpl_free(pix_array) ;
1885  return NULL ;
1886  }
1887  retstats -> npix = n ;
1888  pix_sum /= (double) n ;
1889  sqr_sum /= (double) n ;
1890  retstats -> cleanstdev = (float)sqrt(sqr_sum - pix_sum * pix_sum) ;
1891  cpl_free (pix_array) ;
1892  return retstats ;
1893 }
1894 
1895 
1896 
1906 cpl_image * sinfo_new_normalize_to_central_pixel ( cpl_image * image )
1907 {
1908  int col=0;
1909  int row=0;
1910  int i=0;
1911  int n=0;
1912  float* array=NULL ;
1913  float divisor=0;
1914  cpl_image * retImage=NULL;
1915  int ilx=0;
1916  int ily=0;
1917  float* pidata=NULL;
1918  float* podata=NULL;
1919 
1920  if ( image == NULL )
1921  {
1922  sinfo_msg_error("no image given!") ;
1923  return NULL ;
1924  }
1925  ilx=cpl_image_get_size_x(image);
1926  ily=cpl_image_get_size_y(image);
1927  pidata=cpl_image_get_data_float(image);
1928 
1929  retImage = cpl_image_duplicate(image) ;
1930  podata=cpl_image_get_data_float(retImage);
1931 
1932  n = 0 ;
1933  /* go through the central two image rows and store
1934  the values in an array */
1935  array=cpl_calloc(2*ilx,sizeof(float)) ;
1936 
1937  for ( row = ily/2 ; row < ily/2+1 ; row++ )
1938  {
1939  for ( col = 0 ; col < ilx ; col++ )
1940  {
1941  if ( !isnan(pidata[col+ilx*row]) )
1942  {
1943  array[n] = pidata[col+ilx*row] ;
1944  n++ ;
1945  }
1946  }
1947  }
1948  /* compute the sinfo_median of the central 2 spectral
1949  values of all spatial pixels*/
1950  if ( isnan(divisor = sinfo_new_median(array, n) ) )
1951  {
1952  sinfo_msg_error("no sinfo_median possible!") ;
1953  return NULL ;
1954  }
1955  if ( 0 == divisor )
1956  {
1957  sinfo_msg_error("cannot divide by 0") ;
1958  return NULL ;
1959  }
1960 
1961  for ( i = 0 ; i < (int) ilx*ily ; i++ )
1962  {
1963  if ( isnan(pidata[i]) )
1964  {
1965  podata[i] = ZERO ;
1966  }
1967  else
1968  {
1969  podata[i] = pidata[i]/divisor ;
1970  }
1971  }
1972  cpl_free(array);
1973  return retImage ;
1974 }
1975 
1976 /*-------------------------------------------------------------------------*/
2005 /*--------------------------------------------------------------------------*/
2006 
2007 cpl_image *
2008 sinfo_new_mpe_shift_image(
2009  cpl_image * image_in,
2010  double shift_x,
2011  double shift_y,
2012  double * interp_kernel)
2013 {
2014  cpl_image * shifted=NULL ;
2015  pixelvalue * first_pass=NULL ;
2016  pixelvalue * second_pass=NULL ;
2017  int samples = KERNEL_SAMPLES ;
2018  int i=0, j=0 ;
2019 
2020  double ry=0 ;
2021  int py=0 ;
2022  int taby=0 ;
2023  double value=0 ;
2024  size_t pos ;
2025  register pixelvalue * pix ;
2026  register pixelvalue * pixint ;
2027  int mid=0;
2028  double norm=0 ;
2029  double * ker=NULL ;
2030  int freeKernel = 1 ;
2031 
2032  int ilx=0;
2033  int ily=0;
2034  float* pidata=NULL;
2035  float* psdata=NULL;
2036 
2037 
2038  /* error handling: test entries */
2039  if (image_in==NULL) return NULL ;
2040 
2041  /* Shifting by a zero offset returns a copy of the input image */
2042  if ((fabs(shift_x)<1e-2) && (fabs(shift_y)<1e-2))
2043  return cpl_image_duplicate(image_in) ;
2044  ilx=cpl_image_get_size_x(image_in);
2045  ily=cpl_image_get_size_y(image_in);
2046  pidata=cpl_image_get_data_float(image_in);
2047 
2048 
2049  /* See if a kernel needs to be generated */
2050  if (interp_kernel == NULL) {
2051  ker = sinfo_generate_interpolation_kernel("default") ;
2052  if (ker == NULL) {
2053  sinfo_msg_error("kernel generation failure:aborting resampling") ;
2054  return NULL ;
2055  }
2056  } else {
2057  ker = interp_kernel ;
2058  freeKernel = 0 ;
2059  }
2060 
2061  mid = (int)samples/(int)2 ;
2062  first_pass = cpl_calloc(ilx, ily*sizeof(pixelvalue)) ;
2063  shifted = cpl_image_new(ilx, ily,CPL_TYPE_FLOAT) ;
2064  psdata=cpl_image_get_data_float(shifted);
2065 
2066  second_pass = psdata ;
2067 
2068  pix = pidata ;
2069  if ( ilx != 1 )
2070  {
2071  for (j=0 ; j<ily ; j++)
2072  {
2073  for (i=0 ; i<ilx ; i++) {
2074  double fx = (double)i-shift_x ;
2075  int px = (int)fx ;
2076  double rx = fx - (double)px ;
2077  pos = px + j * ilx ;
2078 
2079  if ((px>1) && (px<(ilx-2)))
2080  {
2081  int tabx = (int)(fabs((double)mid * rx)) ;
2082  /* exclude blank (ZERO) pixels from interpolation */
2083  if (isnan(pix[pos]))
2084  {
2085  value = ZERO ;
2086  }
2087  else
2088  {
2089  if (isnan(pix[pos-1]))
2090  {
2091  pix[pos-1] = 0. ;
2092  }
2093  if (isnan(pix[pos+1]))
2094  {
2095  pix[pos+1] = 0. ;
2096  }
2097  if (isnan(pix[pos+2]))
2098  {
2099  pix[pos+2] = 0. ;
2100  }
2101 
2102  /*
2103  * Sum up over 4 closest pixel values,
2104  * weighted by interpolation kernel values
2105  */
2106  value = (double)pix[pos-1] * ker[mid+tabx] +
2107  (double)pix[pos] * ker[tabx] +
2108  (double)pix[pos+1] * ker[mid-tabx] +
2109  (double)pix[pos+2] * ker[samples-tabx-1] ;
2110  /*
2111  * Also sum up interpolation kernel coefficients
2112  * for further normalization
2113  */
2114  norm = (double)ker[mid+tabx] +
2115  (double)ker[tabx] +
2116  (double)ker[mid-tabx] +
2117  (double)ker[samples-tabx-1] ;
2118  if (fabs(norm) > 1e-4) {
2119  value /= norm ;
2120  }
2121  }
2122  } else {
2123  value = ZERO ;
2124  }
2125  /*
2126  * There may be a problem of rounding here if pixelvalue
2127  * has not enough bits to sustain the accuracy.
2128  */
2129  if ( isnan(value) )
2130  {
2131  first_pass[i+j*ilx] = ZERO ;
2132  }
2133  else
2134  {
2135  first_pass[i+j*ilx] = (pixelvalue)value ;
2136  }
2137  }
2138  }
2139  }
2140  else
2141  {
2142  memcpy(first_pass,pix,ily*sizeof(pixelvalue));
2143  }
2144 
2145  pixint = first_pass ;
2146  for (i=0 ; i<ilx ; i++) {
2147  for (j=0 ; j<ily ; j++) {
2148  double fy = (double)j - shift_y ;
2149  py = (int)fy ;
2150  ry = fy - (double)py ;
2151  pos = i + py * ilx ;
2152 
2153  taby = (int)(fabs((double)mid * ry)) ;
2154 
2155  if ((py>(int)1) && (py<(ily-2))) {
2156  /* exclude blank (ZERO) pixels from interpolation */
2157  if (isnan(pixint[pos]) && ilx != 1 )
2158  {
2159  value = ZERO ;
2160  }
2161  else
2162  {
2163  if (isnan(pixint[pos-ilx]))
2164  {
2165  pixint[pos-ilx] = 0. ;
2166  }
2167  if (isnan(pixint[pos+ilx]))
2168  {
2169  pixint[pos+ilx] = 0. ;
2170  }
2171  if (isnan(pixint[pos+2*ilx]))
2172  {
2173  pixint[pos+2*ilx] = 0. ;
2174  }
2175  /*
2176  * Sum up over 4 closest pixel values,
2177  * weighted by interpolation kernel values
2178  */
2179  value = (double)pixint[pos-ilx] * ker[mid+taby] +
2180  (double)pixint[pos] * ker[taby] +
2181  (double)pixint[pos+ilx] * ker[mid-taby] +
2182  (double)pixint[pos+2*ilx]*ker[samples-taby-1];
2183  /*
2184  * Also sum up interpolation kernel coefficients
2185  * for further normalization
2186  */
2187  norm = (double)ker[mid+taby] +
2188  (double)ker[taby] +
2189  (double)ker[mid-taby] +
2190  (double)ker[samples-taby-1] ;
2191 
2192  if (fabs(norm) > 1e-4) {
2193  value /= norm ;
2194  }
2195  }
2196  } else {
2197  value = ZERO ;
2198  }
2199  if (isnan(value))
2200  {
2201  second_pass[i+j*ilx] = ZERO ;
2202  }
2203  else
2204  {
2205  second_pass[i+j*ilx] = (pixelvalue)value ;
2206  }
2207  }
2208  }
2209 
2210  cpl_free(first_pass) ;
2211  if (freeKernel)
2212  cpl_free(ker) ;
2213  return shifted ;
2214 }
2215 
2216 
2217 /*-------------------------------------------------------------------------*/
2248 /*--------------------------------------------------------------------------*/
2249 
2250 void
2251 sinfo_new_shift_image_in_cube(
2252  cpl_image * image_in,
2253  double shift_x,
2254  double shift_y,
2255  double * interp_kernel,
2256  cpl_image * shifted,
2257  pixelvalue * first_pass)
2258 {
2259  pixelvalue * second_pass=NULL ;
2260  int samples = KERNEL_SAMPLES ;
2261  int i=0, j=0 ;
2262  double fx=0, fy=0 ;
2263  double rx=0, ry=0 ;
2264  int px=0, py=0 ;
2265  int tabx=0, taby=0 ;
2266  double value=0 ;
2267  size_t pos ;
2268  register pixelvalue * pix ;
2269  int mid=0;
2270  double norm=0 ;
2271  double * ker=NULL ;
2272  int freeKernel = 1 ;
2273 
2274  int ilx=0;
2275  int ily=0;
2276  int slx=0;
2277  int sly=0;
2278  float* pidata=NULL;
2279  float* psdata=NULL;
2280 
2281  /* error handling: test entries */
2282  if (image_in==NULL) shifted = NULL ;
2283  pidata=cpl_image_get_data_float(image_in);
2284  ilx=cpl_image_get_size_x(image_in);
2285  ily=cpl_image_get_size_y(image_in);
2286 
2287  shifted=cpl_image_new(ilx,ily,CPL_TYPE_FLOAT);
2288  slx=ilx;
2289  sly=ily;
2290 
2291  psdata=cpl_image_get_data_float(shifted);
2292 
2293  /* Shifting by a zero offset returns a copy of the input image */
2294  if ((fabs(shift_x)<1e-2) && (fabs(shift_y)<1e-2))
2295  memcpy(psdata,pidata, (size_t) slx*sly * sizeof(pixelvalue)) ;
2296 
2297  /* See if a kernel needs to be generated */
2298  if (interp_kernel == NULL) {
2299  ker = sinfo_generate_interpolation_kernel("default") ;
2300  if (ker == NULL) {
2301  sinfo_msg_error("kernel generation failure:aborting resampling") ;
2302  shifted = NULL ;
2303  }
2304  } else {
2305  ker = interp_kernel ;
2306  freeKernel = 0 ;
2307  }
2308 
2309  mid = (int)samples/(int)2 ;
2310  second_pass = psdata ;
2311 
2312  pix = pidata ;
2313  for (j=0 ; j<ily ; j++) {
2314  for (i=1 ; i<ilx-2 ; i++) {
2315  fx = (double)i-shift_x ;
2316  px = (int)fx ;
2317  rx = fx - (double)px ;
2318 
2319  pos = px + j * ilx ;
2320 
2321  if ((px>1) && (px<(ilx-2))) {
2322  tabx = (int)(fabs((double)mid * rx)) ;
2323  /* exclude blank (ZERO) pixels from interpolation */
2324  if (isnan(pix[pos]))
2325  {
2326  value = ZERO ;
2327  }
2328  else
2329  {
2330  if (isnan(pix[pos-1]))
2331  {
2332  pix[pos-1] = 0. ;
2333  }
2334  if (isnan(pix[pos+1]))
2335  {
2336  pix[pos+1] = 0. ;
2337  }
2338  if (isnan(pix[pos+2]))
2339  {
2340  pix[pos+2] = 0. ;
2341  }
2342 
2343  /*
2344  * Sum up over 4 closest pixel values,
2345  * weighted by interpolation kernel values
2346  */
2347  value = (double)pix[pos-1] * ker[mid+tabx] +
2348  (double)pix[pos] * ker[tabx] +
2349  (double)pix[pos+1] * ker[mid-tabx] +
2350  (double)pix[pos+2] * ker[samples-tabx-1] ;
2351  /*
2352  * Also sum up interpolation kernel coefficients
2353  * for further normalization
2354  */
2355  norm = (double)ker[mid+tabx] +
2356  (double)ker[tabx] +
2357  (double)ker[mid-tabx] +
2358  (double)ker[samples-tabx-1] ;
2359  if (fabs(norm) > 1e-4) {
2360  value /= norm ;
2361  }
2362  }
2363  } else {
2364  value = 0.0 ;
2365  }
2366  /*
2367  * There may be a problem of rounding here if pixelvalue
2368  * has not enough bits to sustain the accuracy.
2369  */
2370  if ( isnan(value) )
2371  {
2372  first_pass[i+j*ilx] = ZERO ;
2373  }
2374  else
2375  {
2376  first_pass[i+j*ilx] = (pixelvalue)value ;
2377  }
2378  }
2379  }
2380  register pixelvalue* pixint = first_pass ;
2381  for (i=0 ; i< ilx ; i++) {
2382  for (j=1 ; j< ily-2 ; j++) {
2383  fy = (double)j - shift_y ;
2384  py = (int)fy ;
2385  ry = fy - (double)py ;
2386  pos = i + py * ilx ;
2387 
2388  taby = (int)(fabs((double)mid * ry)) ;
2389 
2390  if ((py>(int)1) && (py<(ily-2))) {
2391  /* exclude blank (ZERO) pixels from interpolation */
2392  if (isnan(pixint[pos]))
2393  {
2394  value = ZERO ;
2395  }
2396  else
2397  {
2398  if (isnan(pixint[pos-ilx]))
2399  {
2400  pixint[pos-ilx] = 0. ;
2401  }
2402  if (isnan(pixint[pos+ilx]))
2403  {
2404  pixint[pos+ilx] = 0. ;
2405  }
2406  if (isnan(pixint[pos+2*ilx]))
2407  {
2408  pixint[pos+2*ilx] = 0. ;
2409  }
2410  /*
2411  * Sum up over 4 closest pixel values,
2412  * weighted by interpolation kernel values
2413  */
2414  value = (double)pixint[pos-ilx] * ker[mid+taby] +
2415  (double)pixint[pos] * ker[taby] +
2416  (double)pixint[pos+ilx] * ker[mid-taby] +
2417  (double)pixint[pos+2*ilx]*ker[samples-taby-1];
2418  /*
2419  * Also sum up interpolation kernel coefficients
2420  * for further normalization
2421  */
2422  norm = (double)ker[mid+taby] +
2423  (double)ker[taby] +
2424  (double)ker[mid-taby] +
2425  (double)ker[samples-taby-1] ;
2426 
2427  if (fabs(norm) > 1e-4) {
2428  value /= norm ;
2429  }
2430  }
2431  } else {
2432  /* value = 0.0 ; AMo: This affect slitlet #1 */
2433  }
2434  if (isnan(value))
2435  {
2436  second_pass[i+j*ilx] = ZERO ;
2437  }
2438  else
2439  {
2440  second_pass[i+j*ilx] = (pixelvalue)value ;
2441  }
2442  }
2443  }
2444 
2445  if (freeKernel)
2446  cpl_free(ker) ;
2447 }
2448 
2449 /* function to delete the image statistics within python */
2450 void sinfo_new_del_Stats( Stats * st)
2451 {
2452  cpl_free (st) ;
2453 }
2454 
2462 cpl_image *
2463 sinfo_new_combine_masks ( cpl_image * firstMask, cpl_image * secondMask )
2464 {
2465  cpl_image * retMask=NULL ;
2466  int n=0 ;
2467  int olx=0;
2468  int oly=0;
2469  float* podata=NULL;
2470  //float* pm1data=NULL;
2471  float* pm2data=NULL;
2472 
2473  if ( firstMask == NULL || secondMask == NULL )
2474  {
2475  sinfo_msg_error ("no input mask image given!") ;
2476  return NULL ;
2477  }
2478  retMask = cpl_image_duplicate (firstMask) ;
2479  podata = cpl_image_get_data_float(retMask);
2480  //pm1data = cpl_image_get_data_float(firstMask);
2481  pm2data = cpl_image_get_data_float(secondMask);
2482  olx=cpl_image_get_size_x(retMask);
2483  oly=cpl_image_get_size_y(retMask);
2484 
2485  for ( n = 0 ; n < (int) olx*oly ; n++ )
2486  {
2487  if ( podata[n] == 0. || pm2data[n] == 0. )
2488  {
2489  podata[n] = 0. ;
2490  }
2491  else
2492  {
2493  podata[n] = 1. ;
2494  }
2495  }
2496  return retMask ;
2497 }
2498 
2508 cpl_image * sinfo_new_slice_cube (cpl_imagelist * cube, int x, int y )
2509 {
2510  cpl_image * retImage=NULL ;
2511 
2512  int inp=0;
2513  int ilx=0;
2514  int ily=0;
2515  cpl_image* img=NULL;
2516  float* podata=NULL;
2517  float* pidata=NULL;
2518 
2519  if ( cube == NULL )
2520  {
2521  sinfo_msg_error("no cube given!") ;
2522  return NULL ;
2523  }
2524  if ( x > 31 || y > 31 )
2525  {
2526  sinfo_msg_warning("wrong x or y values!") ;
2527  }
2528 
2529  img=cpl_imagelist_get(cube,0);
2530  ilx=cpl_image_get_size_x(img);
2531  ily=cpl_image_get_size_y(img);
2532  inp=cpl_imagelist_get_size(cube);
2533  int z=0;
2534  if ( x < 0 )
2535  {
2536  /* allocate memory */
2537  if ( NULL == (retImage = cpl_image_new(ilx, inp, CPL_TYPE_FLOAT)) )
2538  {
2539  sinfo_msg_error("could not allocate memory!") ;
2540  return NULL ;
2541  }
2542  podata=cpl_image_get_data_float(retImage);
2543  for ( z = 0 ; z < inp ; z++ )
2544  {
2545 
2546  pidata=cpl_image_get_data_float(cpl_imagelist_get(cube,z));
2547  int col;
2548  for ( col = 0 ; col < ilx ; col++ )
2549  {
2550  podata[col+z*ilx] = pidata[col+y*ilx] ;
2551  }
2552  }
2553  }
2554  else if ( y < 0 )
2555  {
2556  /* allocate memory */
2557  if ( NULL == (retImage = cpl_image_new(ily, inp,CPL_TYPE_FLOAT)) )
2558  {
2559  sinfo_msg_error("could not allocate memory!") ;
2560  return NULL ;
2561  }
2562  podata=cpl_image_get_data_float(retImage);
2563 
2564  for ( z = 0 ; z < inp ; z++ )
2565  {
2566  pidata=cpl_image_get_data_float(cpl_imagelist_get(cube,z));
2567  int row=0;
2568  for ( row = 0 ; row < ily ; row++ )
2569  {
2570  podata[row+z*ily] = pidata[x+row*ily] ;
2571  }
2572  }
2573  }
2574  else
2575  {
2576  sinfo_msg_error("wrong input!") ;
2577  return NULL ;
2578  }
2579  return retImage ;
2580 }
2581 
2593 cpl_image * sinfo_new_div_images_robust ( cpl_image * im1, cpl_image * im2 )
2594 {
2595  cpl_image * retIm=NULL ;
2596  float help=0 ;
2597  int i=0 ;
2598  int lx1=0;
2599  int ly1=0;
2600  int lx2=0;
2601  int ly2=0;
2602 
2603  float* p1data=NULL;
2604  float* p2data=NULL;
2605  float* podata=NULL;
2606 
2607  if ( im1 == NULL || im2 == NULL )
2608  {
2609  sinfo_msg_error("no input images given!") ;
2610  return NULL ;
2611  }
2612  lx1=cpl_image_get_size_x(im1);
2613  ly1=cpl_image_get_size_y(im1);
2614  lx2=cpl_image_get_size_x(im2);
2615  ly2=cpl_image_get_size_y(im2);
2616  p1data=cpl_image_get_data_float(im1);
2617  p2data=cpl_image_get_data_float(im2);
2618 
2619  if ( lx1 != lx2 || ly1 != ly2 )
2620  {
2621  sinfo_msg_error("images not compatible!") ;
2622  return NULL ;
2623  }
2624  if ( NULL == (retIm = cpl_image_new(lx1, ly1, CPL_TYPE_FLOAT)) )
2625  {
2626  sinfo_msg_error("could not allocate memory!") ;
2627  return NULL ;
2628  }
2629  podata=cpl_image_get_data_float(retIm);
2630 
2631  for ( i = 0 ; i < (int) lx2*ly2 ; i++ )
2632  {
2633  if ( !isnan(p2data[i]) )
2634  {
2635  help = 1./p2data[i] ;
2636  if (fabs( help )> THRESH )
2637  {
2638  help = 1. ;
2639  }
2640  }
2641  else
2642  {
2643  help = ZERO ;
2644  }
2645  if ( isnan(help) || isnan(p1data[i]) )
2646  {
2647  podata[i] = ZERO ;
2648  }
2649  else
2650  {
2651  podata[i] = p1data[i] * help ;
2652  }
2653  }
2654  return retIm ;
2655 }
2656 
2657 cpl_image * sinfo_new_null_edges ( cpl_image * image)
2658 {
2659  cpl_image * new=NULL ;
2660  int i=0,j=0 ;
2661  /*
2662  int ilx=0;
2663  int ily=0;
2664  */
2665  int olx=0;
2666  int oly=0;
2667 
2668  //float* pidata=NULL;
2669  float* podata=NULL;
2670 
2671  if ( image == NULL )
2672  {
2673  sinfo_msg_error ("no input image given!\n") ;
2674  return NULL ;
2675  }
2676 
2677 
2678  new = cpl_image_duplicate (image) ;
2679  /*
2680  ilx=cpl_image_get_size_x(image);
2681  ily=cpl_image_get_size_y(image);
2682  */
2683  olx=cpl_image_get_size_x(new);
2684  oly=cpl_image_get_size_y(new);
2685  //pidata=cpl_image_get_data_float(image);
2686  podata=cpl_image_get_data_float(new);
2687 
2688  for ( i = 0 ; i < olx ; i++ )
2689  {
2690  for ( j = 0 ; j < 4 ; j++)
2691  {
2692  podata[i+j*olx]=0;
2693  podata[i+(oly-j-1)*olx]=0;
2694  }
2695  }
2696  for ( i = 0 ; i < oly ; i++ )
2697  {
2698  for ( j = 0 ; j < 4 ; j++)
2699  {
2700  podata[j+i*olx]=0;
2701  podata[(olx-j-1)+i*olx]=0;
2702  }
2703  }
2704  return new ;
2705 }
2706 
2707 
2708 void sinfo_new_used_cor_map( cpl_image *im, cpl_image *map)
2709 {
2710  int i=0,j=0,loc_index=0;
2711  float temp_array[2048];
2712  int lx=cpl_image_get_size_x(im);
2713  int ly=cpl_image_get_size_y(im);
2714  float* pidata=cpl_image_get_data_float(im);
2715  float* pmdata=cpl_image_get_data_float(map);
2716 
2717  for( j=0; j<ly; j++)
2718  {
2719  for( i=0;i<lx;i++)
2720  {
2721  loc_index = (int)pmdata[i+j*lx];
2722  temp_array[i] = pidata[loc_index+j*lx];
2723  }
2724  for( i=0;i<lx;i++)
2725  {
2726  pidata[i+j*lx]= temp_array[i];
2727  }
2728  }
2729 }
2730 
2731 
2732 
2733 
2734 /*-------------------------------------------------------------------------*/
2764 /*--------------------------------------------------------------------------*/
2765 
2766 cpl_image *
2767 sinfo_new_shift_image(
2768  cpl_image * image_in,
2769  double shift_x,
2770  double shift_y,
2771  double * interp_kernel)
2772 {
2773  cpl_image * shifted=NULL ;
2774 
2775 
2776  int samples = KERNEL_SAMPLES ;
2777  double * ker=NULL ;
2778  int freeKernel = 1 ;
2779  int ilx=0;
2780  int ily=0;
2781 
2782  /* error handling: test entries */
2783  if (image_in==NULL) return NULL ;
2784 
2785  /* Shifting by a zero offset returns a copy of the input image */
2786  if ((fabs(shift_x)<1e-2) && (fabs(shift_y)<1e-2))
2787  return cpl_image_duplicate(image_in) ;
2788 
2789  /* See if a kernel needs to be generated */
2790  if (interp_kernel == NULL) {
2791  ker = sinfo_generate_interpolation_kernel("default") ;
2792  if (ker == NULL) {
2793  sinfo_msg_error("kernel generation failure: aborting resampling") ;
2794  return NULL ;
2795  }
2796  } else {
2797  ker = interp_kernel ;
2798  freeKernel = 0 ;
2799  }
2800 
2801  ilx=cpl_image_get_size_x(image_in);
2802  ily=cpl_image_get_size_y(image_in);
2803 
2804 
2805  register float* pix = cpl_image_get_data_float(image_in);
2806  float* first_pass=NULL;
2807 
2808  if (pix)
2809  {
2810  double value = 0;
2811  int mid = (int)samples/(int)2 ;
2812  first_pass = cpl_calloc(ilx, ily*sizeof(float)) ;
2813  shifted = cpl_image_new(ilx, ily,CPL_TYPE_FLOAT) ;
2814  float* second_pass = cpl_image_get_data_float(shifted);
2815  int i=0,j=0;
2816  double norm;
2817  size_t pos;
2818  for (j=0 ; j<ily ; j++) {
2819  for (i=1 ; i<ilx-2 ; i++) {
2820  double fx = (double)i-shift_x ;
2821  int px = (int)fx ;
2822  double rx = fx - (double)px ;
2823 
2824  pos = px + j * ilx ;
2825 
2826  if ((px>1) && (px<(ilx-3))) {
2827  int tabx = (int)(fabs((double)mid * rx)) ;
2828  /*
2829  * Sum up over 4 closest pixel values,
2830  * weighted by interpolation kernel values
2831  */
2832  value = (double)pix[pos-1] * ker[mid+tabx] +
2833  (double)pix[pos] * ker[tabx] +
2834  (double)pix[pos+1] * ker[mid-tabx] +
2835  (double)pix[pos+2] * ker[samples-tabx-1] ;
2836  /*
2837  * Also sum up interpolation kernel coefficients
2838  * for further normalization
2839  */
2840  norm = (double)ker[mid+tabx] +
2841  (double)ker[tabx] +
2842  (double)ker[mid-tabx] +
2843  (double)ker[samples-tabx-1] ;
2844  if (fabs(norm) > 1e-4) {
2845  value /= norm ;
2846  }
2847  } else {
2848  value = 0.0 ;
2849  }
2850  /*
2851  * There may be a problem of rounding here if pixelvalue
2852  * has not enough bits to sustain the accuracy.
2853  */
2854  first_pass[i+j*ilx] = (float)value ;
2855  }
2856  }
2857  register float* pixint = first_pass ;
2858  for (i=0 ; i<ilx ; i++) {
2859  for (j=1 ; j<ily-3 ; j++) {
2860  double fy = (double)j - shift_y ;
2861  int py = (int)fy ;
2862  double ry = fy - (double)py ;
2863  pos = i + py * ilx ;
2864 
2865  int taby = (int)(fabs((double)mid * ry)) ;
2866 
2867  if ((py>(int)1) && (py<(ily-2))) {
2868  /*
2869  * Sum up over 4 closest pixel values,
2870  * weighted by interpolation kernel values
2871  */
2872  value = (double)pixint[pos-ilx] * ker[mid+taby] +
2873  (double)pixint[pos] * ker[taby] +
2874  (double)pixint[pos+ilx] * ker[mid-taby] +
2875  (double)pixint[pos+2*ilx]*ker[samples-taby-1];
2876  /*
2877  * Also sum up interpolation kernel coefficients
2878  * for further normalization
2879  */
2880  norm = (double)ker[mid+taby] +
2881  (double)ker[taby] +
2882  (double)ker[mid-taby] +
2883  (double)ker[samples-taby-1] ;
2884 
2885  if (fabs(norm) > 1e-4) {
2886  value /= norm ;
2887  }
2888  } else {
2889  value = 0.0 ;
2890  }
2891  second_pass[i+j*ilx] = (float)value ;
2892  }
2893  }
2894  }
2895  else
2896  {
2897  cpl_msg_warning(cpl_func, "cannot get a data from an image");
2898  }
2899  cpl_free(first_pass) ;
2900  if (freeKernel)
2901  cpl_free(ker) ;
2902  return shifted ;
2903 }
2904 
2905 
2906 /*-------------------------------------------------------------------------*/
2920 /*--------------------------------------------------------------------------*/
2921 
2922 cpl_image *
2923 sinfo_image_hermite_interpol(cpl_image * inp)
2924 {
2925 
2926  /*
2927  @param xp x-value to interpolate
2928  @param x x-values
2929  @param y y-values
2930  @param n array length
2931  @param istart (input/output) initial row (set to 0 to search all row)
2932 
2933  sinfo_spline_hermite( double xp, const double *x,
2934  const double *y, int n, int *istart );
2935 
2936  */
2937  float* pinp=NULL;
2938  float* pout=NULL;
2939  int sx=0;
2940  int sy=0;
2941  int i=0;
2942  int j=0;
2943  int r=5;
2944  int k=0;
2945 
2946  cpl_image* out=NULL;
2947 
2948  cknull(inp,"Null in put image, exit");
2949  check_nomsg(out=cpl_image_duplicate(inp));
2950  check_nomsg(sx=cpl_image_get_size_x(inp));
2951  check_nomsg(sy=cpl_image_get_size_y(inp));
2952  check_nomsg(pinp=cpl_image_get_data_float(inp));
2953  check_nomsg(pout=cpl_image_get_data_float(out));
2954  for(j=r;j<sy-r;j++) {
2955  for(i=0;i<sx;i++) {
2956  for(k=-r;k<r;k++) {
2957  pout[j*sx+i]+=pinp[(j+k)*sx+i];
2958  }
2959  pout[j*sx+i]/=2*r;
2960  }
2961  }
2962 
2963  cleanup:
2964 
2965  if(cpl_error_get_code() != CPL_ERROR_NONE) {
2966  return NULL;
2967  } else {
2968  return out;
2969 
2970  }
2971 
2972 }
2973 
2974 
2975 
2976 /*-------------------------------------------------------------------------*/
2990 /*--------------------------------------------------------------------------*/
2991 
2992 cpl_image *
2993 sinfo_image_smooth_y(cpl_image * inp, const int r)
2994 {
2995 
2996  /*
2997  @param xp x-value to interpolate
2998  @param x x-values
2999  @param y y-values
3000  @param n array length
3001  @param istart (input/output) initial row (set to 0 to search all row)
3002 
3003  */
3004  float* pinp=NULL;
3005  float* pout=NULL;
3006  int sx=0;
3007  int sy=0;
3008  int i=0;
3009  int j=0;
3010  int k=0;
3011 
3012  cpl_image* out=NULL;
3013 
3014  cknull(inp,"Null in put image, exit");
3015  check_nomsg(out=cpl_image_duplicate(inp));
3016  check_nomsg(sx=cpl_image_get_size_x(inp));
3017  check_nomsg(sy=cpl_image_get_size_y(inp));
3018  check_nomsg(pinp=cpl_image_get_data_float(inp));
3019  check_nomsg(pout=cpl_image_get_data_float(out));
3020  for(j=r;j<sy-r;j++) {
3021  for(i=0;i<sx;i++) {
3022  for(k=-r;k<r;k++) {
3023  pout[j*sx+i]+=pinp[(j+k)*sx+i];
3024  }
3025  pout[j*sx+i]/=2*r;
3026  }
3027  }
3028 
3029  cleanup:
3030 
3031  if(cpl_error_get_code() != CPL_ERROR_NONE) {
3032  return NULL;
3033  } else {
3034  return out;
3035 
3036  }
3037 
3038 }
3039 
3040 
3041 /*-------------------------------------------------------------------------*/
3055 /*--------------------------------------------------------------------------*/
3056 
3057 cpl_image *
3058 sinfo_image_smooth_mean_y(cpl_image * inp, const int r)
3059 {
3060 
3061  /*
3062  @param xp x-value to interpolate
3063  @param x x-values
3064  @param y y-values
3065  @param n array length
3066  @param istart (input/output) initial row (set to 0 to search all row)
3067 
3068  */
3069  float* pinp=NULL;
3070  float* pout=NULL;
3071  int sx=0;
3072  int sy=0;
3073  int i=0;
3074  int j=0;
3075  int k=0;
3076 
3077  cpl_image* out=NULL;
3078 
3079  cknull(inp,"Null in put image, exit");
3080  check_nomsg(out=cpl_image_duplicate(inp));
3081  check_nomsg(sx=cpl_image_get_size_x(inp));
3082  check_nomsg(sy=cpl_image_get_size_y(inp));
3083  check_nomsg(pinp=cpl_image_get_data_float(inp));
3084  check_nomsg(pout=cpl_image_get_data_float(out));
3085  for(j=r;j<sy-r;j++) {
3086  for(i=0;i<sx;i++) {
3087  for(k=-r;k<r;k++) {
3088  pout[j*sx+i]+=pinp[(j+k)*sx+i];
3089  }
3090  pout[j*sx+i]/=2*r;
3091  }
3092  }
3093 
3094  cleanup:
3095 
3096  if(cpl_error_get_code() != CPL_ERROR_NONE) {
3097  return NULL;
3098  } else {
3099  return out;
3100 
3101  }
3102 
3103 }
3104 
3105 
3106 /*-------------------------------------------------------------------------*/
3120 /*--------------------------------------------------------------------------*/
3121 
3122 cpl_image *
3123 sinfo_image_smooth_median_y(cpl_image * inp, const int r)
3124 {
3125 
3126  /*
3127  @param xp x-value to interpolate
3128  @param x x-values
3129  @param y y-values
3130  @param n array length
3131  @param istart (input/output) initial row (set to 0 to search all row)
3132 
3133  */
3134  float* pout=NULL;
3135  int sx=0;
3136  int sy=0;
3137  int i=0;
3138  int j=0;
3139 
3140  cpl_image* out=NULL;
3141 
3142 
3143  cknull(inp,"Null in put image, exit");
3144  check_nomsg(out=cpl_image_duplicate(inp));
3145  check_nomsg(sx=cpl_image_get_size_x(inp));
3146  check_nomsg(sy=cpl_image_get_size_y(inp));
3147  check_nomsg(pout=cpl_image_get_data_float(out));
3148 
3149  for(j=r+1;j<sy-r;j++) {
3150  for(i=1;i<sx;i++) {
3151  pout[j*sx+i]=(float)cpl_image_get_median_window(inp,i,j,i,j+r);
3152  }
3153  }
3154 
3155  cleanup:
3156 
3157  if(cpl_error_get_code() != CPL_ERROR_NONE) {
3158  return NULL;
3159  } else {
3160  return out;
3161 
3162  }
3163 
3164 }
3165 
3166 /*-------------------------------------------------------------------------*/
3179 /*--------------------------------------------------------------------------*/
3180 
3181 cpl_image *
3182 sinfo_image_smooth_fft(cpl_image * inp, const int fy)
3183 {
3184 
3185  int sx=0;
3186  int sy=0;
3187 
3188  cpl_image* out=NULL;
3189  cpl_image* im_re=NULL;
3190  cpl_image* im_im=NULL;
3191  cpl_image* ifft_re=NULL;
3192  cpl_image* ifft_im=NULL;
3193  cpl_image* filter=NULL;
3194 
3195  int sigma_x=0;
3196  int sigma_y=fy;
3197 
3198  cknull(inp,"Null in put image, exit");
3199  check_nomsg(im_re = cpl_image_cast(inp, CPL_TYPE_DOUBLE));
3200  check_nomsg(im_im = cpl_image_cast(inp, CPL_TYPE_DOUBLE));
3201 
3202  // Compute FFT
3203  check_nomsg(cpl_image_fft(im_re,im_im,CPL_FFT_DEFAULT));
3204 
3205  check_nomsg(sx=cpl_image_get_size_x(inp));
3206  check_nomsg(sy=cpl_image_get_size_y(inp));
3207  sigma_x=sx;
3208 
3209  //Generates filter image
3210  check_nomsg(filter = sinfo_gen_lowpass(sx,sy,sigma_x,sigma_y));
3211 
3212  //Apply filter
3213  cpl_image_multiply(im_re,filter);
3214  cpl_image_multiply(im_im,filter);
3215 
3216  sinfo_free_image(&filter);
3217 
3218  check_nomsg(ifft_re = cpl_image_duplicate(im_re));
3219  check_nomsg(ifft_im = cpl_image_duplicate(im_im));
3220 
3221  sinfo_free_image(&im_re);
3222  sinfo_free_image(&im_im);
3223 
3224  //Computes FFT-INVERSE
3225  check_nomsg(cpl_image_fft(ifft_re,ifft_im,CPL_FFT_INVERSE));
3226  check_nomsg(out = cpl_image_cast(ifft_re, CPL_TYPE_FLOAT));
3227 
3228  cleanup:
3229 
3230  sinfo_free_image(&ifft_re);
3231  sinfo_free_image(&ifft_im);
3232  sinfo_free_image(&filter);
3233  sinfo_free_image(&im_re);
3234  sinfo_free_image(&im_im);
3235 
3236  if(cpl_error_get_code() != CPL_ERROR_NONE) {
3237  return NULL;
3238  } else {
3239  return out;
3240  }
3241 
3242 }
3243 
3244 
3245 
3246 /*-------------------------------------------------------------------------*/
3262 /*--------------------------------------------------------------------------*/
3263 static cpl_image *
3264 sinfo_gen_lowpass(const int xs,
3265  const int ys,
3266  const double sigma_x,
3267  const double sigma_y)
3268 {
3269 
3270 
3271 
3272  int hlx= 0.0;
3273  int hly = 0.0;
3274  double x= 0.0;
3275 
3276  double gaussval= 0.0;
3277  double inv_sigma_x=1./sigma_x;
3278  double inv_sigma_y=1./sigma_y;
3279 
3280  float *data;
3281 
3282  cpl_image *lowpass_image=NULL;
3283 
3284 
3285  lowpass_image = cpl_image_new (xs, ys, CPL_TYPE_FLOAT);
3286  if (lowpass_image == NULL) {
3287  sinfo_msg_error("Cannot generate lowpass filter <%s>",
3288  cpl_error_get_message());
3289  return NULL;
3290  }
3291 
3292  hlx = xs/2;
3293  hly = ys/2;
3294 
3295  data = cpl_image_get_data_float(lowpass_image);
3296 
3297  /* Given an image with pixels 0<=i<N, 0<=j<M then the convolution image
3298  has the following properties:
3299 
3300  ima[0][0] = 1
3301  ima[i][0] = ima[N-i][0] = exp (-0.5 * (i/sig_i)^2) 1<=i<N/2
3302  ima[0][j] = ima[0][M-j] = exp (-0.5 * (j/sig_j)^2) 1<=j<M/2
3303  ima[i][j] = ima[N-i][j] = ima[i][M-j] = ima[N-i][M-j]
3304  = exp (-0.5 * ((i/sig_i)^2 + (j/sig_j)^2))
3305  */
3306 
3307  data[0] = 1.0;
3308 
3309  /* first row */
3310  int i=0;
3311  for (i=1 ; i<=hlx ; i++) {
3312  x = i * inv_sigma_x;
3313  gaussval = exp(-0.5*x*x);
3314  data[i] = gaussval;
3315  data[xs-i] = gaussval;
3316  }
3317  int j=0;
3318  for (j=1; j<=hly ; j++) {
3319  double y = j * inv_sigma_y;
3320  /* first column */
3321  data[j*xs] = exp(-0.5*y*y);
3322  data[(ys-j)*xs] = exp(-0.5*y*y);
3323 
3324  for (i=1 ; i<=hlx ; i++) {
3325  /* Use internal symetries */
3326  x = i * inv_sigma_x;
3327  gaussval = exp (-0.5*(x*x+y*y));
3328  data[j*xs+i] = gaussval;
3329  data[(j+1)*xs-i] = gaussval;
3330  data[(ys-j)*xs+i] = gaussval;
3331  data[(ys+1-j)*xs-i] = gaussval;
3332 
3333  }
3334  }
3335 
3336  /* FIXME: for the moment, reset errno which is coming from exp()
3337  in first for-loop at i=348. This is causing cfitsio to
3338  fail when loading an extension image (bug in cfitsio too).
3339  */
3340  if(errno != 0)
3341  errno = 0;
3342 
3343  return lowpass_image;
3344 }
3345 
3346 static void quicksort_int(int* data, int left, int right)
3347 {
3348  int i = left;
3349  int j = right;
3350  int pivot = (i + j) / 2;
3351  double index_value = data[pivot];
3352  do
3353  {
3354  while(data[i] < index_value) i++;
3355  while(data[j] > index_value) j--;
3356  if (i <= j)
3357  {
3358  if(i < j)
3359  {
3360  int tmp = data[i];
3361  data[i]=data[j];
3362  data[j]=tmp;
3363  }
3364  i++;
3365  j--;
3366  }
3367  } while (i <= j);
3368 
3369  if (i < right)
3370  {
3371  quicksort_int(data, i, right);
3372  }
3373  if (left < j)
3374  {
3375  quicksort_int(data, left, j);
3376  }
3377 }
3378 
3379 /*--------------------------------------------------------------------------*/
#define sinfo_msg_debug(...)
Print a debug message.
Definition: sinfo_msg.h:103
#define sinfo_msg_error(...)
Print an error message.
Definition: sinfo_msg.h:69
#define sinfo_msg_warning(...)
Print an warning message.
Definition: sinfo_msg.h:93