sinfo_image_ops.c

00001 /*
00002  * This file is part of the ESO SINFONI Pipeline
00003  * Copyright (C) 2004,2005 European Southern Observatory
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA
00018  */
00019 /*************************************************************************
00020 * M.P.E. - SPIFFI project
00021 *
00022 *
00023 *
00024 * who       when      what
00025 * --------  --------  ----------------------------------------------
00026 * rabuter 2004-12-03 support one dimensional image in sinfo_shiftImage
00027 * schreib  23/05/00  created
00028 */
00029 
00030 /************************************************************************
00031 *   NAME
00032 *        sinfo_image_ops.c -
00033 *        image arithmetic routines
00034 *
00035 *   SYNOPSIS
00036 *   #include "sinfo_image_ops.h"
00037 *
00038 *   1) Vector * sinfo_new_mean_of_columns( cpl_image *im )
00039 *   2) Vector * sinfo_new_clean_mean_of_columns( cpl_image *im,
00040 *                                   double lo_reject,
00041 *                                   double hi_reject)
00042 *   3) cpl_image * sinfo_new_div_image_by_row( cpl_image *im, Vector *row )
00043 *   4) cpl_image * sinfo_new_mult_row_to_image( cpl_image *im, Vector *row )
00044 *   5) cpl_image * sinfo_new_col_tilt ( cpl_image * image, float sigmaFactor )
00045 *   6) cpl_image * sinfo_new_median_image( cpl_image * im, float fmedian )
00046 *   7) cpl_image * sinfo_new_compare_images( cpl_image * im1,
00047                                              cpl_image * im2,
00048                                              cpl_image * origim )
00049 *   8) cpl_image * sinfo_new_thresh_image ( cpl_image * im,
00050                                             float lo_cut, float hi_cut )
00051 *   9) pixel_map * sinfo_new_promote_image_to_pixelmap ( cpl_image * im )
00052 *  10) cpl_image * sinfo_new_promote_image_to_mask ( cpl_image * im,
00053                                                      int * n_badpixels )
00054 *  11) cpl_image * sinfo_new_mult_image_by_mask ( cpl_image * im,
00055                                                   cpl_image * mask )
00056 *  12) cpl_image * sinfo_new_interpol_image ( cpl_image * im,
00057 *                                 cpl_image * mask,
00058 *                                 int        max_radius,
00059 *                                 int        n_pixels )
00060 *  13) cpl_image * sinfo_interpol_source_image ( cpl_image * im,
00061 *                                       cpl_image * mask,
00062 *                                       int        max_rad,
00063 *                                       float   ** slit_edges )
00064 *  14) cpl_image * sinfo_new_stack_row_to_image ( Vector * row, int ly )
00065 *  15) Stats * sinfo_new_image_stats_on_rectangle ( cpl_image * im,
00066 *                                      float      loReject,
00067 *                                      float      hiReject,
00068 *                                      int        llx,
00069 *                                      int        lly,
00070 *                                      int        urx,
00071 *                                      int        ury )
00072 *  16) cpl_image * sinfo_new_normalize_to_central_pixel ( cpl_image * image )
00073 *  17) cpl_image *
00074 *      sinfo_new_shift_image(
00075 *            cpl_image    *    image_in,
00076 *            double           shift_x,
00077 *            double           shift_y,
00078 *            double       *   interp_kernel)
00079 *  18) cpl_image * sinfo_new_combine_masks ( cpl_image * firstMask,
00080                                              cpl_image * secondMask )
00081 *  19) cpl_image * sinfo_new_slice_cube (cpl_imagelist * cube, int x, int y )
00082 *  20) cpl_image * sinfo_new_div_images_robust ( cpl_image * im1,
00083                                                  cpl_image * im2 )
00084 *
00085 *
00086 *   DESCRIPTION
00087 *   1) takes the average of each image column
00088 *   2) takes the average of each image column by sorting the
00089 *      column values and rejecting the given percentage of
00090 *      the highest and lowest values  [0...1]
00091 *   3) divides each image column by a row value
00092 *   4) multiplies each image column with a row value
00093 *   5) first calculates statistics for each column of an image.
00094 *      sinfo_median value and standard deviation of columns are de-
00095 *      termined, blank values are excluded. Fits a straight
00096 *      line through the pixel values of each column and subtracts
00097 *      the fit in order to remove the tilt of each column.
00098 *      Only those pixels are used for the fit that are within
00099 *      a defined factor of sigma noise limit. The noise is
00100 *      calculated from pixels between the 10percentil and
00101 *      90percentil points.
00102 *      if the straight line could not be determined, the sinfo_median
00103 *      of the column is subtracted from the column
00104 *   6) sinfo_median filter, calculates the sinfo_median for an image
00105 *      by using the 8 closest pixels to each pixel.
00106 *      The values in the output image are determined according
00107 *      to the values of the input parameter.
00108 *      If fmedian = 0: always replace by sinfo_median
00109 *      if fmedian < 0: replace by sinfo_median if |pixel - sinfo_median| >
00110 *                      -fmedian
00111 *      if fmedian > 0: replace by sinfo_median (fmedian as a factor of
00112 *                      the square root of the sinfo_median itself)
00113 *                      if |pixel - median| >= fmedian * sqrt ( median )
00114 *                      This can be used to consider photon noise.
00115 *                      This considers a dependence of the differences on the
00116 *                      pixel values themselves.
00117 *   7) if a pixel value of one image (im1) equals
00118 *      the pixel value of the other image keep the
00119 *      pixel value of the original image otherwise replace
00120 *      it with ZEROs
00121 *   8) simple search for static bad pixels for a flat field
00122 *      or sinfo_dark frame, values below and above the threshold
00123 *      values are set to ZERO.
00124 *   9) changes an image with ZERO indicated bad pixels to
00125 *      a bad pixel map.
00126 *  10) changes an image with ZERO indicated bad pixels to
00127 *      a bad pixel mask image, that means the returned
00128 *      image has values 1 at positions of good pixels and
00129 *      ZEROs at positions of bad pixels.
00130 *  11) changes an image to an image that has ZERO indicated
00131 *      static bad pixels
00132 *  12) interpolates all bad pixels indicated by the bad pixel mask.
00133 *      Therefore, the mean of at least 2 valid values of
00134 *      the nearest 8 neighbors is taken. If too much
00135 *      neighbors are also bad pixels
00136 *      the neighbor radius is increased to a maximum of
00137 *      max_radius until n_pixels valid pixels are found.
00138 *      The valid neighbors are searched by going through
00139 *      the columns and rows around the central square that
00140 *      was already searched.
00141 *      The bad pixel is interpolated by the mean of these
00142 *      valid pixels (less than 9) or by the sinfo_median of them
00143 *      (more than 8).
00144 *  13) interpolates all bad pixels indicated by the bad pixel mask.
00145 *      Therefore, the mean of the nearest 4 neighbors is taken,
00146 *      two in spectral direction and 2 in spatial direction.
00147 *      The routine cares about the image and slitlet edges.
00148 *      If there are no good pixel found within the nearest neighbors,
00149 *      the next 4 nearest neighbors in spatial and spectral direction
00150 *      are searched for valid pixels until a limit of max_rad.
00151 *      A maximum of 4 valid pixels are used for interpolation by their mean.
00152 *  14) stack a given image row to build a whole image
00153 *  15) computes the mean and standard deviation of
00154 *      a given rectangle on an image by leaving the extreme
00155 *      intensity values.
00156 *  16) normalizes a raw flatfield image by dividing by the median of the
00157        central spectral pixels to produce a master flatfield
00158 *  17) This function is a conversion to CPL of the ECLIPSE function
00159        shift_image()
00160 *      but slightly changed. If a blank (ZERO) pixel appears the blank pixel
00161 *      is shifted but preserved as blank.
00162 *      If a blank (ZERO) pixel appears within the
00163 *      interpolation kernel the blank pixel is set to 0.
00164 *
00165 *      This function shifts an image by a non-integer offset, using
00166 *      interpolation. You can either generate an interpolation kernel once and
00167 *      pass it to this function, or let it generate a default kernel. In the
00168 *      former case, use sinfo_generate_interpolation_kernel() to generate an
00169 *      appropriate kernel. In the latter case, pass NULL as last argument. A
00170 *      default interpolation kernel is then generated then discarded
00171        before this function returns.
00172 *
00173 *      The returned image is a newly allocated object, it must be deallocated
00174 *      using cpl_image_delete().
00175 *  18) combines two bad pixel mask to one using an or relation
00176 *  19) slices a data cube in x or y direction
00177 *  20) divides two images by considering blanks and
00178 *      calculating first 1/im2 by
00179 *      cutting the very high values and setting to 1,
00180 *      then multiplying im1 * 1/im2.
00181 *
00182 *   FILES
00183 *
00184 *   ENVIRONMENT
00185 *
00186 *   RETURN VALUES
00187 *
00188 *   CAUTIONS
00189 *
00190 *   EXAMPLES
00191 *
00192 *   SEE ALSO
00193 *
00194 *   BUGS
00195 *
00196 *------------------------------------------------------------------------
00197 */
00198 
00199 #ifdef HAVE_CONFIG_H
00200 #  include <config.h>
00201 #endif
00202 #include "sinfo_vltPort.h"
00203 
00204 /*
00205  * System Headers
00206  */
00207 #include <errno.h>
00208 /*
00209  * Local Headers
00210  */
00211 
00212 #include "sinfo_image_ops.h"
00213 #include "sinfo_error.h"
00214 #include "sinfo_resampling.h"
00215 #include "sinfo_local_types.h"
00216 #include "sinfo_utils_wrappers.h"
00217 
00225 static cpl_image *
00226 sinfo_gen_lowpass(const int xs,
00227                   const int ys,
00228                   const double sigma_x,
00229                   const double sigma_y);
00230 
00231 
00232 static void quicksort_int(int* data, int left, int right);
00235 /*----------------------------------------------------------------------------
00236  *                            Function codes
00237  *--------------------------------------------------------------------------*/
00238 
00239 
00240 
00252 cpl_error_code
00253 sinfo_image_line_corr(const int width,
00254                 const int filt_rad,
00255                 const int kappa,
00256                 cpl_image* ima_in,
00257                 cpl_image** ima_out)
00258 {
00259 
00260   cpl_image* mask=NULL;
00261 
00262   cpl_image* ima_backpix=NULL;
00263   cpl_image* ima_backpos=NULL;
00264   cpl_image* ima_ybackpix=NULL;
00265   cpl_image* ima_diffbackpix=NULL;
00266   cpl_image* ima_filt=NULL;
00267   cpl_image* ima = NULL;
00268 
00269   cpl_matrix* filter=NULL;
00270   //cpl_mask* bpm_good=NULL; //Is this really useful?
00271   cpl_mask* bpm_bad=NULL;
00272 
00273   int sx=0;
00274   int sy=0;
00275   int i=0;
00276   int j=0;
00277   int k=0;
00278   double med_back=0;
00279   double sigma_back=0;
00280   double medvalue=0;
00281 
00282   float* pima=NULL;
00283   float* ppix=NULL;
00284   float* pmsk=NULL;
00285   int* ppos=NULL;
00286   int* pbackpix=NULL;
00287   cpl_binary* pbin=NULL;
00288   double tot=0;
00289   double mean=0;
00290   int* ybad=NULL;
00291 
00292   int nrow=0;
00293   int nbad=0;
00294   int yval=0;
00295   int yprev=0;
00296 
00297 
00298   check_nomsg(sx=cpl_image_get_size_x(ima_in));
00299   check_nomsg(sy=cpl_image_get_size_y(ima_in));
00300   check_nomsg(*ima_out=cpl_image_duplicate(ima_in));
00301 
00302   check_nomsg(mask=cpl_image_new(sx,sy,CPL_TYPE_FLOAT));
00303   check_nomsg(pmsk=cpl_image_get_data_float(mask));
00304 
00305   for(i=0;i<width;i++) {
00306     for(j=width;j<sy-width;j++) {
00307       pmsk[j*sx+i]=1;
00308     }
00309   }
00310 
00311   for(i=sx-width;i<sx;i++) {
00312     for(j=width;j<sy-width;j++) {
00313       pmsk[j*sx+i]=1;
00314     }
00315   }
00316   sinfo_free_image(&mask); //is mask needed?
00317 
00318 
00319   nrow=2*width*(sy-2*width);
00320   check_nomsg(ima_backpix=cpl_image_new(nrow,1,CPL_TYPE_FLOAT));
00321   check_nomsg(ima_backpos=cpl_image_new(nrow,1,CPL_TYPE_INT));
00322 
00323   check_nomsg(pima=cpl_image_get_data_float(ima_in));
00324   check_nomsg(ppix=cpl_image_get_data_float(ima_backpix));
00325   check_nomsg(ppos=cpl_image_get_data_int(ima_backpos));
00326 
00327   k=0;
00328   for(i=0;i<width;i++) {
00329     for(j=width;j<sy-width;j++) {
00330       ppix[k]=pima[j*sx+i];
00331       ppos[k]=j*sx+i;
00332       k++;
00333     }
00334   }
00335 
00336   for(i=sx-width;i<sx;i++) {
00337     for(j=width;j<sy-width;j++) {
00338       ppix[k]=pima[j*sx+i];
00339       ppos[k]=j*sx+i;
00340       k++;
00341     }
00342   }
00343 
00344   check_nomsg(ima_ybackpix=cpl_image_duplicate(ima_backpos));
00345   sinfo_free_image(&ima_backpos);
00346 
00347   check_nomsg(pbackpix=cpl_image_get_data_int(ima_ybackpix));
00348 
00349   check_nomsg(cpl_image_divide_scalar(ima_ybackpix,sx));
00350   check_nomsg(pbackpix=cpl_image_get_data_int(ima_ybackpix));
00351 
00352 
00353   check_nomsg(med_back=cpl_image_get_median(ima_backpix));
00354   check_nomsg(ima_diffbackpix=cpl_image_duplicate(ima_backpix));
00355   check_nomsg(cpl_image_subtract_scalar(ima_diffbackpix,med_back));
00356   //check_nomsg(cpl_image_save(ima_diffbackpix,"ima_diff.fits",
00357   //                           CPL_BPP_IEEE_FLOAT,NULL,CPL_IO_DEFAULT));
00358 
00359   check_nomsg(filter=cpl_matrix_new(1,filt_rad));
00360   check_nomsg(cpl_matrix_fill(filter,1.));
00361   check_nomsg(ima_filt=sinfo_image_filter_median(ima_diffbackpix,filter));
00362   sinfoni_free_matrix(&filter);
00363   //check_nomsg(cpl_image_save(ima_filt,"ima_filt.fits",CPL_BPP_IEEE_FLOAT,
00364   //             NULL,CPL_IO_DEFAULT));
00365 
00366 
00367   check_nomsg(sigma_back=cpl_image_get_stdev(ima_filt));
00368   sinfo_free_image(&ima_filt);
00369 
00370   check_nomsg(ima=cpl_image_duplicate(ima_diffbackpix));
00371   sinfo_free_image(&ima_diffbackpix);
00372 
00373   check_nomsg(cpl_image_abs(ima));
00374 
00375   //find good pixels
00376   check_nomsg(bpm_bad=cpl_mask_threshold_image_create(ima,kappa*sigma_back,
00377                               SINFO_DBL_MAX));
00378   /*check_nomsg(bpm_good=cpl_mask_threshold_image_create(ima,SINFO_DBL_MIN,
00379                                kappa*sigma_back));
00380   sinfo_free_mask(&bpm_good);
00381 */
00382   check_nomsg(cpl_image_reject_from_mask(ima_backpix,bpm_bad));
00383   check_nomsg(medvalue=cpl_image_get_median(ima_backpix));
00384   check_nomsg(nbad=cpl_mask_count(bpm_bad));
00385 
00386   check_nomsg(cpl_image_reject_from_mask(ima_backpix,bpm_bad));
00387   sinfo_free_image(&ima_backpix);
00388 
00389   yprev=-1;
00390 
00391   check_nomsg(pbin=cpl_mask_get_data(bpm_bad));
00392   check_nomsg(pbackpix=cpl_image_get_data_int(ima_ybackpix));
00393   cpl_msg_debug(cpl_func, "%d lines detected", nbad);
00394   if(nbad)
00395   {
00396 
00397       ybad = cpl_calloc(nbad,sizeof(int));
00398       k=0;
00399 
00400       for(i=0;i<nrow;i++) {
00401         if(pbin[i] == CPL_BINARY_1) {
00402            ybad[k]=pbackpix[i] + 1;
00403            k++;
00404         }
00405       }
00406       sinfo_free_mask(&bpm_bad);
00407       sinfo_free_image(&ima_ybackpix);
00408 
00409       quicksort_int(&(ybad[0]), 0, nbad-1);
00410       yprev=-1;
00411       for(k=0;k<nbad;k++) {
00412         yval=ybad[k];
00413         if(yval == yprev) {
00414           sinfo_msg_debug("skyp %d",yval);
00415         }
00416         else {
00417           yprev=yval;
00418           sinfo_msg_debug("correct raw %d",yval);
00419           check_nomsg(tot=cpl_image_get_flux_window(ima_in,1,yval,width,yval));
00420           check_nomsg(tot+=cpl_image_get_flux_window(ima_in,sx-width+1,
00421                             yval,sx,yval));
00422           mean=tot/(2. * width);
00423           check_nomsg(pima=cpl_image_get_data_float(*ima_out));
00424           for(i=width;i<sx-width;i++) {
00425         pima[i+(yval-1)*sx]+=(float)(mean-medvalue);
00426           }
00427 
00428         }
00429       }
00430   }
00431 
00432 
00433  cleanup:
00434 
00435   sinfo_free_image(&mask); //is mask needed?
00436   sinfo_free_image(&ima_backpos);
00437   sinfoni_free_matrix(&filter);
00438   sinfo_free_image(&ima_filt);
00439   sinfo_free_image(&ima_diffbackpix);
00440 //  sinfo_free_mask(&bpm_good);
00441   sinfo_free_image(&ima_backpix);
00442   sinfo_free_mask(&bpm_bad);
00443   sinfo_free_image(&ima_ybackpix);
00444   cpl_image_delete(ima);
00445   cpl_free(ybad);
00446   return cpl_error_get_code();
00447 
00448 }
00449 
00450 
00459 double sinfo_new_my_median_image(cpl_image* im)
00460 {
00461   double m=0;
00462   register int i=0;
00463   int n=0;
00464   pixelvalue* pv=0;
00465   int ilx=0;
00466   int ily=0;
00467   float* pidata=NULL;
00468 
00469 
00470   if(im==NULL) sinfo_msg_error("Null Image");
00471   ilx=cpl_image_get_size_x(im);
00472   ily=cpl_image_get_size_y(im);
00473   pidata=cpl_image_get_data_float(im);
00474 
00475    for ( i = 0 ; i < (int) ilx*ily ; i++ )
00476     {
00477       if ( isnan(pidata[i]) )
00478         {
00479 
00480     } else {
00481       n++;
00482     }
00483     }
00484    pv = cpl_calloc(n,sizeof(pixelvalue));
00485    n=0;
00486    for ( i = 0 ; i < (int) ilx*ily ; i++ )
00487     {
00488       if ( isnan(pidata[i]) )
00489         {
00490 
00491     } else {
00492       pv[n]=pidata[i];
00493           n++;
00494     }
00495     }
00496    if(pv == NULL || n == 0) {
00497      m=0;
00498    } else {
00499      m=sinfo_new_median(pv,n);
00500    }
00501    cpl_free(pv);
00502    if(isnan(m)){
00503      m=0;
00504    }
00505   return m;
00506 }
00507 
00516 Vector * sinfo_new_mean_of_columns( cpl_image *im )
00517 {
00518     Vector * row=NULL ;
00519     int i=0;
00520     int j=0;
00521     int ilx=0;
00522     int ily=0;
00523     float* pidata=NULL;
00524 
00525     if ( im == NULL )
00526     {
00527         sinfo_msg_error ("null image") ;
00528         return NullVector ;
00529     }
00530     ilx=cpl_image_get_size_x(im);
00531     ily=cpl_image_get_size_y(im);
00532     pidata=cpl_image_get_data_float(im);
00533 
00534     /* allocate memory for a row with the length of the image x-axis */
00535     if ( NULL == (row = sinfo_new_vector (ilx)) )
00536     {
00537         sinfo_msg_error ("not able to allocate a sinfo_vector" ) ;
00538         return NullVector ;
00539     }
00540 
00541     for ( i = 0 ; i < ilx ; i++ )
00542     {
00543         for ( j = 0 ; j < ily ; j++ )
00544         {
00545             if (!isnan(pidata[i+j*ilx]))
00546             {
00547                 row->data[i] += pidata[i + j*(ilx)] ;
00548             }
00549         }
00550 
00551         row->data[i] /= ily ;
00552     }
00553     return row ;
00554 }
00566 cpl_image * sinfo_new_clean_mean_of_columns( cpl_image *im,
00567                              float lo_reject,
00568                              float hi_reject)
00569 {
00570     cpl_image     * row=NULL ;
00571     pixelvalue*   buffer=NULL ;
00572     int          i=0;
00573     int          j=0;
00574     int          k=0;
00575     int          nv=0;
00576     int          lo_n=0;
00577     int          hi_n=0;
00578     int ilx=0;
00579     int ily=0;
00580     float* pidata=NULL;
00581     float* podata=NULL;
00582 
00583     if ( im == NULL )
00584     {
00585         sinfo_msg_error ("null image") ;
00586         return NULL ;
00587     }
00588     ilx=cpl_image_get_size_x(im);
00589     ily=cpl_image_get_size_y(im);
00590     pidata=cpl_image_get_data_float(im);
00591 
00592     if ((lo_reject + hi_reject) > 0.9)
00593     {
00594         sinfo_msg_error("illegal rejection thresholds: [%f] and [%f]",
00595                         lo_reject, hi_reject) ;
00596         sinfo_msg_error("threshold sum should not be over "
00597                         "0.90 aborting average") ;
00598         return NULL ;
00599     }
00600 
00601     lo_n = (int) (ily * lo_reject + 0.5) ;
00602     hi_n = (int) (ily * hi_reject + 0.5) ;
00603     if (lo_n + hi_n >= ily)
00604     {
00605         sinfo_msg_error ("everything would be rejected") ;
00606         return NULL ;
00607     }
00608 
00609     /* allocate memory for a row with the length of the image x-axis */
00610     if ( NULL == (row = cpl_image_new (ilx, 1,CPL_TYPE_FLOAT)) )
00611     {
00612         sinfo_msg_error ("cannot allocate new image") ;
00613         return NULL ;
00614     }
00615     podata=cpl_image_get_data_float(row);
00616 
00617     buffer=(pixelvalue*) cpl_calloc(ily,sizeof(pixelvalue)) ;
00618 
00619     for ( i = 0 ; i < ilx ; i++ )
00620     {
00621         for ( j = 0 ; j < ily ; j++ )
00622         {
00623             buffer[j] = pidata[i + j*(ilx)] ;
00624         }
00625         sinfo_pixel_qsort (buffer, ily) ;
00626 
00627         nv = 0 ;
00628         for (k = lo_n ; k < ily - hi_n ; k ++)
00629         {
00630             if ( !isnan(buffer[k]) )
00631             {
00632                 podata[i] += buffer[k] ;
00633                 nv ++ ;
00634             }
00635         }
00636         podata[i] /= nv ;
00637 
00638     }
00639     cpl_free(buffer);
00640     return row ;
00641 }
00642 
00643 
00653 cpl_image * sinfo_new_div_image_by_row( cpl_image *im, Vector *row )
00654 {
00655     cpl_image *image=NULL ;
00656     int         i=0;
00657     int         j=0;
00658     int ilx=0;
00659     int ily=0;
00660     float* pidata=NULL;
00661     float* podata=NULL;
00662 
00663     if ( im == NULL || row == NULL )
00664     {
00665         sinfo_msg_error ("null image or null row") ;
00666         return NULL ;
00667     }
00668     ilx=cpl_image_get_size_x(im);
00669     ily=cpl_image_get_size_y(im);
00670     pidata=cpl_image_get_data_float(im);
00671 
00672     if ( ilx != row -> n_elements )
00673     {
00674         sinfo_msg_error("image and row size not compatible") ;
00675         return NULL ;
00676     }
00677 
00678     if ( NULL == (image = cpl_image_duplicate (im)) )
00679     {
00680         sinfo_msg_error ("cannot copy image") ;
00681         return NULL ;
00682     }
00683     podata=cpl_image_get_data_float(image);
00684 
00685     for (i = 0 ; i < ilx ; i++ )
00686     {
00687         for (j = 0 ; j < ily ; j++)
00688         {
00689             if ( !isnan(pidata[i + j*(ilx)]) )
00690             {
00691                 podata[i + j*(ilx)] = pidata[i + j*(ilx)] / row -> data[i] ;
00692             }
00693         }
00694     }
00695     return image ;
00696 }
00697 
00698 
00708 cpl_image * sinfo_new_mult_row_to_image( cpl_image *im, Vector *row )
00709 {
00710     cpl_image *image=NULL;
00711     int         i=0;
00712     int         j=0;
00713     int ilx=0;
00714     int ily=0;
00715     float* pidata=NULL;
00716     float* podata=NULL;
00717 
00718 
00719 
00720 
00721     if ( im == NULL || row == NULL )
00722     {
00723         sinfo_msg_error ("null image or null row") ;
00724         return NULL ;
00725     }
00726     ilx=cpl_image_get_size_x(im);
00727     ily=cpl_image_get_size_y(im);
00728     pidata=cpl_image_get_data_float(im);
00729 
00730     if ( ilx != row -> n_elements )
00731     {
00732         sinfo_msg_error("image and row size not compatible") ;
00733         return NULL ;
00734     }
00735 
00736     if ( NULL == (image = cpl_image_duplicate (im)) )
00737     {
00738         sinfo_msg_error ("cannot copy image") ;
00739         return NULL ;
00740     }
00741     podata=cpl_image_get_data_float(image);
00742 
00743     for (i = 0 ; i < ilx ; i++ )
00744     {
00745         for (j = 0 ; j < ily ; j++)
00746         {
00747             if ( !isnan(pidata[i + j*(ilx)]) )
00748             {
00749                 podata[i + j*(ilx)] = pidata[i + j*(ilx)] * row -> data[i] ;
00750             }
00751         }
00752     }
00753     return image ;
00754 }
00755 
00756 
00757 
00758 
00759 
00760 
00784 cpl_image * sinfo_new_col_tilt ( cpl_image * image, float sigmaFactor )
00785 {
00786     cpl_image   * im=NULL;
00787     float      * column=NULL ;
00788     double       sum=0;
00789     double  sum2=0;
00790     double  mean=0;
00791     float   sinfo_median=0;
00792     float   noise=0 ;
00793     float      * sig=NULL;
00794     float    * dat=NULL;
00795     float        a=0;
00796     float        b=0;
00797     float        siga=0;
00798     float        sigb=0;
00799     float        chi2=0;
00800     float        q=0;
00801     int          i=0;
00802     int          j=0;
00803     int          colnum=0;
00804     int         npix=0;
00805     int         mwt=0 ;
00806     int lx=0;
00807     int ly=0;
00808     float* p_in_data=NULL;
00809     float* p_ou_data=NULL;
00810 
00811 
00812     if ( image == NULL )
00813     {
00814         sinfo_msg_error ("no image given" ) ;
00815         return NULL ;
00816     }
00817 
00818     if ( sigmaFactor <= 0. )
00819     {
00820         sinfo_msg_error ("no or negative sigma factor") ;
00821         return NULL ;
00822     }
00823     lx = cpl_image_get_size_x(image);
00824     ly = cpl_image_get_size_y(image);
00825 
00826 
00827     /* allocate memory */
00828     if ( NULL == (im = cpl_image_new (lx,ly,CPL_TYPE_FLOAT )) )
00829     {
00830         sinfo_msg_error ("cannot allocate new image" ) ;
00831         return NULL ;
00832     }
00833 
00834     /* go through the columns */
00835     p_in_data = cpl_image_get_data_float(image);
00836     p_ou_data = cpl_image_get_data_float(im);
00837     for ( i = 0 ; i < lx ; i ++ )
00838     {
00839         /* initialize the buffer variables for each column */
00840         colnum = 0 ;
00841         column = (float *) cpl_calloc ( ly , sizeof (float *) ) ;
00842         sig    = (float *) cpl_calloc ( ly , sizeof (float *) ) ;
00843         dat    = (float *) cpl_calloc ( ly , sizeof (float *) ) ;
00844 
00845         /*select only non-ZERO values of one column*/
00846         for ( j = 0 ; j < ly ; j++ )
00847         {
00848             if ( !isnan(p_in_data[i + j*lx]) )
00849             {
00850                 column[j] = p_in_data[i + j*lx] ;
00851                 colnum ++ ;
00852             }
00853         }
00854         if ( colnum < 10 )
00855         {
00856             /*sinfo_msg_warning ("sinfo_new_col_tilt:",
00857           "column %d has almost only blank pixels and is set to blank", i+1) ;*/
00858             for ( j = 0 ; j < ly ; j++ )
00859             {
00860                 p_ou_data[i + j*lx] = ZERO;
00861             }
00862             /*
00863             cpl_free (column) ;
00864             cpl_free (sig);
00865             cpl_free (dat) ;
00866             continue ;
00867             */
00868         }
00869 
00870         /*-------------------------------------------------------------------
00871          * sort the data, clip off the extremes, determine the noise
00872          * and get the range for the valid data. It is assumed here
00873          * that most pixels are o.k.
00874          */
00875 
00876         sinfo_pixel_qsort (column, colnum) ;
00877 
00878         sum   = 0. ;
00879         sum2  = 0. ;
00880         npix  = 0  ;
00881 
00882         for ( j = 0.1*colnum + 1 ; j <= 0.9*colnum ; j++ )
00883         {
00884             sum  += column[j] ;
00885             sum2 += column[j] * column[j] ;
00886             npix ++ ;
00887         }
00888 
00889         if (npix <= 1)
00890         {
00891             noise = sigmaFactor * 1000.;
00892         }
00893         else
00894         {
00895             mean   = sum/(float)npix ;
00896             noise  = sqrt( (sum2 - sum*mean)/(double)(npix -1) ) ;
00897             noise *= sigmaFactor ;
00898         }
00899 
00900         /* -------------------------------------------------------------
00901          * determine sinfo_median if colnum is odd, sinfo_median will be the
00902            colnum/2 th value, otherwise
00903          * sinfo_median is the mean of colnum/2-1 th and colnum/2 th value.
00904          */
00905 
00906         if ( colnum % 2 == 1 )
00907         {
00908             sinfo_median = column[colnum/2] ;
00909         }
00910         else
00911         {
00912             sinfo_median = (column[colnum/2 - 1] + column[colnum/2])/2. ;
00913         }
00914 
00915         /* now select the pixels for the tilt calculation */
00916 
00917         colnum = 0 ;
00918         for ( j = 0; j < ly ; j ++ )
00919         {
00920             if ( !isnan(p_in_data[i+j*lx]) &&
00921                  fabs ( (p_in_data[i+j*lx]) - sinfo_median) <= noise )
00922             {
00923                 column[colnum] = p_in_data[i+j*lx] ;
00924                 dat[colnum] = (float) j ;
00925                 sig[colnum] = 1. ;
00926                 colnum ++ ;
00927             }
00928         }
00929 
00930         if ( colnum == 0 )
00931         {
00932             /*for ( j = 0; j < ly; j++ )
00933             {
00934                 p_ou_data[i+j*lx] -= sinfo_median ;
00935             }
00936             cpl_free (column) ;
00937             cpl_free (sig)    ;
00938             cpl_free (dat)    ;
00939             continue ;*/
00940         a=0./0.;
00941         b=0./0.;
00942         }
00943     else
00944     {
00945         mwt = 0 ;
00946         sinfo_my_fit ( dat, column, colnum, sig, mwt, &a,
00947                        &b, &siga, &sigb, &chi2, &q ) ;
00948     }
00949         if ( fabs(b) >= SLOPE || fabs(a) >= SATURATION  ||
00950              isnan(b) || isnan(a))
00951         {
00952             sinfo_msg_warning ("linear fit: slope is greater than limit: %f"
00953                                " saturation level is reached: %f in column"
00954                                " number %d ", b, a , i+1) ;
00955         }
00956 
00957         /* subtract fit or sinfo_median from data */
00958         for ( j = 0; j < ly; j++ )
00959         {
00960             if ( !isnan(p_in_data[i+j*lx]) &&
00961                  fabs(b) < SLOPE && fabs(a) < SATURATION )
00962             {
00963                 p_ou_data[i+j*lx] = p_in_data[i+j*lx] - (a + b * (float)j) ;
00964             }
00965             else if ( isnan(p_in_data[i+j*lx]) )
00966             {
00967                 p_ou_data[i+j*lx] = ZERO ;
00968             }
00969             else if ( (fabs(b) >= SLOPE ||
00970                        fabs(a) >= SATURATION || isnan(a) || isnan(b)) &&
00971                       !isnan(p_in_data[i+j*lx]) )
00972             {
00973                 p_ou_data[i+j*lx] -= sinfo_median ;
00974             }
00975             else
00976             {
00977                 sinfo_msg_error (" case is not possible! %f %f", b,a) ;
00978                 /*cpl_free (column) ;
00979                 cpl_free (sig)    ;
00980                 cpl_free (dat)    ;
00981                 cpl_image_delete(im) ;
00982                 return NULL ;*/
00983             }
00984         }
00985         cpl_free (column) ;
00986         cpl_free (sig)    ;
00987         cpl_free (dat)    ;
00988     }
00989 
00990     return im     ;
00991 }
00992 
00993 
00994 
00995 
00996 
01020 cpl_image * sinfo_new_median_image( cpl_image * im, float fmedian )
01021 {
01022     cpl_image *   image=NULL       ;
01023     pixelvalue * value=NULL       ;
01024     pixelvalue   sinfo_median=0      ;
01025     int        * position=NULL    ;
01026     int          nposition=0   ;
01027     int          n=0;
01028     int          i=0;
01029     int          j=0;
01030     int lx=0;
01031     int ly=0;
01032     float* p_in_data=NULL;
01033     float* p_ou_data=NULL;
01034     int im_size=0;
01035     if ( im == NULL )
01036     {
01037         sinfo_msg_error ("no image input") ;
01038         return NULL ;
01039     }
01040 
01041     image = cpl_image_duplicate ( im ) ;
01042     lx=cpl_image_get_size_x(im);
01043     ly=cpl_image_get_size_y(im);
01044     im_size=lx*ly;
01045     p_in_data=cpl_image_get_data_float(im);
01046     p_ou_data=cpl_image_get_data_float(image);
01047 
01048     /*----------------------------------------------------------------------
01049      * go through all pixels
01050      */
01051 
01052     for ( i = 0 ; i < im_size ; i++ )
01053     {
01054         /* blank pixels are not replaced */
01055         if ( isnan(p_in_data[i]) )
01056         {
01057             continue ;
01058         }
01059 
01060         /* initialize the buffer variables for the 8 nearest neighbors */
01061         value = (pixelvalue * )cpl_calloc ( 8, sizeof ( pixelvalue * ) ) ;
01062         position = ( int * ) cpl_calloc ( 8, sizeof ( int * ) ) ;
01063 
01064         /*--------------------------------------------------------------------
01065          * determine the pixel position of the 8 nearest neighbors
01066          */
01067 
01068         position[0] = i + lx - 1 ; /* upper left  */
01069         position[1] = i + lx     ; /* upper       */
01070         position[2] = i + lx + 1 ; /* upper right */
01071         position[3] = i + 1      ; /* right       */
01072         position[4] = i - lx + 1 ; /* lower right */
01073         position[5] = i - lx     ; /* lower       */
01074         position[6] = i - lx - 1 ; /* lower left  */
01075         position[7] = i - 1      ; /* left        */
01076 
01077         /*-------------------------------------------------------------------
01078          * determine the positions of the image margins, top positions are
01079            changed to low positions and vice versa. Right positions are
01080            changed to left positions and vice versa.
01081          */
01082 
01083         if ( i >= 0 && i < lx )    /* bottom line */
01084         {
01085             position[4] += 2 * lx ;
01086             position[5] += 2 * lx ;
01087             position[6] += 2 * lx ;
01088         }
01089         else if ( i >= ((int) lx*ly - lx ) && i < (int) lx*ly ) /* top line */
01090         {
01091             position[0] -= 2 * lx ;
01092             position[1] -= 2 * lx ;
01093             position[2] -= 2 * lx ;
01094         }
01095         else if ( i % lx == 0 )    /* left side */
01096         {
01097             position[0] += 2 ;
01098             position[6] += 2 ;
01099             position[7] += 2 ;
01100         }
01101         else if ( i % lx == lx - 1 )    /* right side */
01102         {
01103             position[2] -= 2 ;
01104             position[3] -= 2 ;
01105             position[4] -= 2 ;
01106         }
01107 
01108         /* --------------------------------------------------------------------
01109          * read the pixel values of the neighboring pixels,
01110          * blanks are not considered
01111          */
01112 
01113         nposition = 8 ;
01114         n = 0 ;
01115         for ( j = 0 ; j < nposition ; j ++ )
01116         {
01117            if((position[j] >-1 ) && (position[j]<im_size)) {
01118               if ( !isnan(p_in_data[position[j]]) )
01119               {
01120                 value[n] = p_in_data[position[j]] ;
01121                 n ++ ;
01122               }
01123            }
01124         }
01125         nposition = n ;
01126 
01127         if ( nposition <= 1 )  /* almost all neighbors are blank */
01128         {
01129             p_ou_data[i] = ZERO ;
01130             cpl_free(value) ;
01131             cpl_free(position) ;
01132             continue ;
01133         }
01134 
01135         /* sort the values and determine the sinfo_median */
01136 
01137         sinfo_pixel_qsort ( value, nposition ) ;
01138         if ( nposition % 2 == 1 )
01139         {
01140             sinfo_median = value [ nposition/2 ] ;
01141         }
01142         else
01143         {
01144             sinfo_median = ( value [nposition/2 - 1] +
01145                              value [nposition/2] ) / 2. ;
01146         }
01147 
01148         /* -----------------------------------------------------------------
01149          * replace the pixel value by the sinfo_median on conditions:
01150          * fmedian = 0: always replace with sinfo_median.
01151          * fmedian < 0: interpret as absolute condition:
01152          *              if |pixel - sinfo_median| > -fmedian
01153          *              replace with sinfo_median.
01154          * fmedian > 0: replace by sinfo_median (fmedian as a factor of
01155          *              the square root of the sinfo_median itself)
01156          *              if |pixel - sinfo_median| >= fmedian *
01157                                                      sqrt ( sinfo_median )
01158          *              considers a dependence on the pixel value.
01159          *              This can be used to consider photon noise.
01160          */
01161 
01162         if ( fmedian == 0 )
01163         {
01164             p_ou_data[i] = sinfo_median ;
01165         }
01166         else if ( fmedian < 0 &&
01167                   fabs ( sinfo_median - p_in_data[i] ) >= -fmedian )
01168         {
01169             p_ou_data[i] = sinfo_median ;
01170         }
01171         else if ( fmedian > 0 &&
01172                   fabs ( sinfo_median - p_in_data[i] ) >= fmedian *
01173                                                       sqrt(fabs(sinfo_median)) )
01174         {
01175             p_ou_data[i] = sinfo_median ;
01176         }
01177         else
01178         {
01179             cpl_free (value) ;
01180             cpl_free (position) ;
01181             continue ;
01182         }
01183 
01184         cpl_free (value) ;
01185         cpl_free (position) ;
01186     }
01187     return image ;
01188 }
01189 
01190 
01191 
01192 
01203 cpl_image *
01204 sinfo_new_compare_images(cpl_image * im1,cpl_image * im2,cpl_image * origim )
01205 {
01206     cpl_image * image=NULL ;
01207     int            i=0 ;
01208     int lx1=0;
01209     int ly1=0;
01210     int lx2=0;
01211     int ly2=0;
01212     float* p_in1_data=NULL;
01213     float* p_in2_data=NULL;
01214     float* p_ou_data=NULL;
01215     float* p_org_data=NULL;
01216 
01217 
01218     if ( im1 == NULL || im2 == NULL || origim == NULL )
01219     {
01220         sinfo_msg_error ("Null images as input" ) ;
01221         return NULL ;
01222     }
01223     lx1=cpl_image_get_size_x(im1);
01224     ly1=cpl_image_get_size_y(im1);
01225 
01226     lx2=cpl_image_get_size_x(im2);
01227     ly2=cpl_image_get_size_y(im2);
01228 
01229     p_in1_data=cpl_image_get_data_float(im1);
01230     p_in2_data=cpl_image_get_data_float(im2);
01231     p_org_data=cpl_image_get_data_float(origim);
01232     if ( lx1 != lx2 || ly1 != ly2 )
01233     {
01234         sinfo_msg_error ("incompatible image sizes" ) ;
01235         return NULL ;
01236     }
01237 
01238     /* allocate memory */
01239     if ( NULL == (image = cpl_image_new ( lx1, ly1, CPL_TYPE_FLOAT )) )
01240     {
01241         sinfo_msg_error ("cannot allocate new image" ) ;
01242         return NULL ;
01243     }
01244     p_ou_data=cpl_image_get_data_float(image);
01245     for ( i = 0 ; i < (int) lx1*ly1 ; i ++ )
01246     {
01247         if ( isnan(p_in1_data[i]) && isnan(p_in2_data[i]) )
01248         {
01249             p_ou_data[i] = ZERO ;
01250         }
01251         else
01252         {
01253             if ( p_in1_data[i] == p_in2_data[i] )
01254             {
01255                 p_ou_data[i] = p_org_data[i] ;
01256             }
01257             else
01258             {
01259                 p_ou_data[i] = ZERO ;
01260             }
01261         }
01262     }
01263     return image ;
01264 }
01265 
01266 
01267 
01279 cpl_image *
01280 sinfo_new_promote_image_to_mask (cpl_image * im, int * n_badpixels )
01281 {
01282     cpl_image * reImage=NULL ;
01283     int        i=0 ;
01284     int lx=0;
01285     int ly=0;
01286     float* p_in_data=NULL;
01287     float* p_ou_data=NULL;
01288 
01289     if ( NULL == im )
01290     {
01291         sinfo_msg_error("no input image given!") ;
01292         return NULL ;
01293     }
01294     lx=cpl_image_get_size_x(im);
01295     ly=cpl_image_get_size_y(im);
01296     p_in_data=cpl_image_get_data_float(im);
01297 
01298     /* allocate memory for the returned image */
01299     if ( NULL == (reImage = cpl_image_new (lx,ly,CPL_TYPE_FLOAT )) )
01300     {
01301         sinfo_msg_error ("cannot allocate new image!") ;
01302         return NULL ;
01303     }
01304     p_ou_data=cpl_image_get_data_float(reImage);
01305 
01306     *n_badpixels = 0 ;
01307     for ( i = 0 ; i < (int) lx*ly ; i ++ )
01308     {
01309         if ( isnan(p_in_data[i]) )
01310         {
01311             p_ou_data[i] = 0. ;
01312             (*n_badpixels)++ ;
01313         }
01314         else
01315         {
01316             p_ou_data[i] = 1. ;
01317         }
01318     }
01319     return reImage ;
01320 }
01321 
01322 
01333 cpl_image * sinfo_new_mult_image_by_mask (cpl_image * im,cpl_image * mask )
01334 {
01335     cpl_image * reImage=NULL ;
01336     int        i=0 ;
01337     int ix=0;
01338     int iy=0;
01339     int mx=0;
01340     int my=0;
01341 
01342 
01343     float* pmdata=NULL;
01344     float* podata=NULL;
01345 
01346     if ( NULL == im )
01347     {
01348         sinfo_msg_error("no input image given!") ;
01349         return NULL ;
01350     }
01351     if ( NULL == mask )
01352     {
01353         sinfo_msg_error("no mask image given!") ;
01354         return NULL ;
01355     }
01356     ix=cpl_image_get_size_x(im);
01357     iy=cpl_image_get_size_y(im);
01358     mx=cpl_image_get_size_x(mask);
01359     my=cpl_image_get_size_y(mask);
01360 
01361     if ( ix != mx || iy != my)
01362     {
01363         sinfo_msg_error("image sizes are not correspondent!") ;
01364         return NULL ;
01365     }
01366 
01367     reImage = cpl_image_duplicate( im ) ;
01368     podata=cpl_image_get_data_float(reImage);
01369     pmdata=cpl_image_get_data_float(mask);
01370 
01371     for ( i = 0 ; i < (int) ix*iy ; i ++ )
01372     {
01373         if ( pmdata[i] == 0. )
01374         {
01375             podata[i] = ZERO ;
01376         }
01377     }
01378 
01379     return reImage ;
01380 }
01381 
01382 
01383 
01393 cpl_image *
01394 sinfo_new_thresh_image (cpl_image * im, float lo_cut, float hi_cut )
01395 {
01396     cpl_image * image=NULL ;
01397     float* p_inp_data=NULL;
01398     float* p_out_data=NULL;
01399     int lx=0;
01400     int ly=0;
01401 
01402     int            i=0 ;
01403 
01404     if (im == NULL)
01405     {
01406         sinfo_msg_error ("null image given") ;
01407         return NULL ;
01408     }
01409     lx=cpl_image_get_size_x(im);
01410     ly=cpl_image_get_size_y(im);
01411 
01412     image = cpl_image_duplicate(im) ;
01413     p_inp_data=cpl_image_get_data(im);
01414     p_out_data=cpl_image_get_data(image);
01415     for ( i = 0 ; i < (int) lx*ly ; i ++ )
01416     {
01417         if ( p_inp_data[i] > (pixelvalue) hi_cut ||
01418              p_inp_data[i] < (pixelvalue) lo_cut )
01419         {
01420              p_out_data[i] = ZERO ;
01421         }
01422     }
01423     return image ;
01424 }
01425 
01426 
01427 
01428 
01453 cpl_image * sinfo_new_interpol_image ( cpl_image * im,
01454                            cpl_image * mask,
01455                            int        max_radius,
01456                            int        n_pixels )
01457 {
01458     cpl_image * returnImage=NULL ;
01459     float* neighbors=NULL ;
01460     float sum=0;
01461     float mean=0;
01462     int i=0;
01463     int j=0;
01464     int k=0;
01465     int row=0;
01466     int col=0;
01467     int n_valid=0;
01468     int agreed=0;
01469 
01470     int ilx=0;
01471     int ily=0;
01472     int mlx=0;
01473     int mly=0;
01474     float* pidata=NULL;
01475     float* podata=NULL;
01476     float* pmdata=NULL;
01477 
01478     if ( NULL == im )
01479     {
01480         sinfo_msg_error("sorry, no input image given!") ;
01481         return NULL ;
01482     }
01483     ilx=cpl_image_get_size_x(im);
01484     ily=cpl_image_get_size_y(im);
01485     pidata=cpl_image_get_data_float(im);
01486 
01487     if ( NULL == mask )
01488     {
01489         sinfo_msg_error("sorry, no mask image given!") ;
01490         return NULL ;
01491     }
01492 
01493     mlx=cpl_image_get_size_x(mask);
01494     mly=cpl_image_get_size_y(mask);
01495     pmdata=cpl_image_get_data_float(mask);
01496 
01497     if ( mlx != ilx || mly != mly )
01498     {
01499         sinfo_msg_error("images not compatible !") ;
01500         return NULL ;
01501     }
01502 
01503     if ( max_radius <= 0 )
01504     {
01505         sinfo_msg_error("wrong number of pixels for maximal "
01506                         "search radius given!") ;
01507         return NULL ;
01508     }
01509 
01510     if ( n_pixels <= 2 )
01511     {
01512         sinfo_msg_error("wrong number of pixels used "
01513                         "for interpolation given!") ;
01514         return NULL ;
01515     }
01516 
01517     returnImage = cpl_image_duplicate ( im ) ;
01518     podata=cpl_image_get_data_float(returnImage);
01519 
01520     /* go through the columns and rows of the input and mask image */
01521     neighbors=cpl_calloc(4*max_radius*max_radius,sizeof(float)) ;
01522 
01523     for ( col = 0 ; col < ilx ; col++ )
01524     {
01525         for ( row = 0 ; row < ily ; row++ )
01526         {
01527             /* look for the ZEROS that means the detected bad pixels */
01528             if ( isnan(pmdata[col+row*ilx]) || pmdata[col+row*ilx] == 0. )
01529             {
01530                 /* now the neighbors must be considered */
01531                 n_valid = 0 ;
01532                 agreed  = 0 ;
01533                 for ( j = 1 ; j <= max_radius ; j++ )
01534                 {
01535 
01536                     /* go through the left column */
01537                     for ( k = -j ; k < j ; k++ )
01538                     {
01539                         if ( col-j >= 0 && row+k < ily && row+k >= 0 )
01540                         {
01541                             if ( !isnan(pmdata[col-j+(row+k)*mlx]) ||
01542                                  pmdata[col-j+(row+k)*mlx] != 0 )
01543                             {
01544                                 neighbors[n_valid]=pidata[col-j+(row+k)*ilx] ;
01545                                 n_valid++ ;
01546                             }
01547                         }
01548                     }
01549 
01550                     /* go through the upper row */
01551                     for ( k = -j ; k < j ; k++ )
01552                     {
01553                         if ( col+k < ilx && col+k >= 0 && row+j < ily )
01554                         {
01555                             if ( !isnan(pmdata[col+k+(row+j)*mlx]) ||
01556                                  pmdata[col+k+(row+j)*mlx] != 0. )
01557                             {
01558                                 neighbors[n_valid]=pidata[col+k+(row+j)*ilx] ;
01559                                 n_valid++ ;
01560                             }
01561                         }
01562                     }
01563 
01564                     /* go through the right column */
01565                     for ( k = -j ; k < j ; k++ )
01566                     {
01567                         if ( col+j < ilx  && row-k >= 0 && row-k < ily )
01568                         {
01569                             if ( !isnan(pmdata[col+j+(row-k)*mlx]) ||
01570                                  pmdata[col+j+(row-k)*mlx] != 0. )
01571                             {
01572                                 neighbors[n_valid]=pidata[col+j+(row-k)*ilx] ;
01573                                 n_valid++ ;
01574                             }
01575                         }
01576                     }
01577 
01578                     /* go through the lower row */
01579                     for ( k = -j ; k < j ; k++ )
01580                     {
01581                         if ( col-k >= 0 && col-k < ilx && row-j < ily )
01582                         {
01583                             if ( !isnan(pmdata[col-k+(row-j)*mlx]) ||
01584                                  pmdata[col-k+(row-j)*mlx] != 0. )
01585                             {
01586                                 neighbors[n_valid]=pidata[col-k+(row-j)*ilx] ;
01587                                 n_valid++ ;
01588                             }
01589                         }
01590                     }
01591 
01592                     /* control if the breaking criteria is fullfilled */
01593                     if ( n_valid >= n_pixels )
01594                     {
01595                         agreed = 1 ;
01596                         break ;
01597                     }
01598                     /* do a break if more than 2 nearest neighbors are found */
01599                     if ( j == 1 && n_valid >= 2 )
01600                     {
01601                         agreed = 1 ;
01602                         break ;
01603                     }
01604                 }
01605                 if ( n_valid < n_pixels && agreed == 0 )
01606                 {
01607                     sinfo_msg_error("not enough valid neighbors found to "
01608                                     "interpolate bad pixel in col: "
01609                                     "%d, row: %d", col, row ) ;
01610                     return NULL ;
01611                 }
01612                 else
01613                 {
01614                     /* ------------------------------------------------------
01615                      * take the mean of the valid neighboring pixels if less
01616                      * than 9 valid pixels are available else take the
01617                        sinfo_median.
01618                      */
01619                     if ( n_valid <= 8 )
01620                     {
01621                         sum = 0. ;
01622 
01623                         for ( i = 0 ; i < n_valid ; i++ )
01624                         {
01625                             sum += neighbors[i] ;
01626                         }
01627                         mean = sum / n_valid ;
01628 
01629                         podata[col+row*ilx] = mean ;
01630                     }
01631                     else
01632                     {
01633                        podata[col+row*ilx]=sinfo_new_median(neighbors,n_valid);
01634                     }
01635                 }
01636             }
01637         }
01638     }
01639     cpl_free(neighbors);
01640     return returnImage ;
01641 }
01642 
01643 
01666 cpl_image * sinfo_interpol_source_image ( cpl_image * im,
01667                                  cpl_image * mask,
01668                                  int        max_rad,
01669                                  float   ** slit_edges )
01670 {
01671     cpl_image * returnImage=NULL ;
01672     float validpixel[6] ;
01673     float sum=0 ;
01674     int n=0;
01675     int row=0;
01676     int col=0;
01677     int i=0;
01678     int k=0;
01679     int slitlet=0;
01680     int n_slitlets=0;
01681     int ilx=0;
01682     int ily=0;
01683     int mlx=0;
01684     int mly=0;
01685 
01686     float* pidata=NULL;
01687     float* podata=NULL;
01688     float* pmdata=NULL;
01689 
01690 
01691     if ( NULL == im )
01692     {
01693         sinfo_msg_error("sorry, no input image given!") ;
01694         return NULL ;
01695     }
01696     ilx=cpl_image_get_size_x(im);
01697     ily=cpl_image_get_size_y(im);
01698     pidata=cpl_image_get_data_float(im);
01699 
01700     if ( NULL == mask )
01701     {
01702         sinfo_msg_error("sorry, no bad pixel mask image given!") ;
01703         return NULL ;
01704     }
01705     mlx=cpl_image_get_size_x(mask);
01706     mly=cpl_image_get_size_y(mask);
01707     pmdata=cpl_image_get_data_float(mask);
01708 
01709     if ( mlx != ilx || mly != ily )
01710     {
01711         sinfo_msg_error("images not compatible in size!") ;
01712         return NULL ;
01713     }
01714 
01715     if ( max_rad < 1 )
01716     {
01717         sinfo_msg_error("sorry, wrong maximum distance given!") ;
01718         return NULL ;
01719     }
01720 
01721     if ( slit_edges == NULL )
01722     {
01723         sinfo_msg_error("sorry, array slit_edges is empty!") ;
01724         return NULL ;
01725     }
01726 
01727     /* determine the number of slitlets */
01728     n_slitlets = N_SLITLETS ;
01729 
01730     /* copy the original image in the image that will be returned */
01731     returnImage = cpl_image_duplicate( im ) ;
01732     podata=cpl_image_get_data_float(returnImage);
01733 
01734     /* go through the rows and columns of the image and search for
01735       the bad pixels */
01736     for ( row = 0 ; row < ily ; row++ )
01737     {
01738         for ( col = 0 ; col < ilx ; col++ )
01739         {
01740             n = 0 ;
01741             if ( isnan(pmdata[col + row*mlx]) ||
01742                  pmdata[col + row*mlx] == 0. ||
01743                  isnan(pidata[col + row*mlx]) )
01744             {
01745                 /* look for the slitlet where the bad pixel is found */
01746                 slitlet = -1000 ;
01747                 for ( k = 0 ; k < n_slitlets ; k++ )
01748                 {
01749                     if ( sinfo_new_nint(slit_edges[k][0]) <= col &&
01750                          sinfo_new_nint(slit_edges[k][1]) >= col )
01751                     {
01752                         slitlet = k ;
01753                     }
01754 /* The following else statement is wrong, because in the
01755      end slitlet will always be -1000
01756             else
01757                     {
01758                         slitlet = -1000 ;
01759                     }
01760 */
01761                 }
01762                 for ( i = 0 ; i < 6 ; i++ )
01763                 {
01764                     validpixel[i] = 0. ;
01765                 }
01766                 /* look for the valid nearest neighbors
01767                    and collect them but only a maximum of 4 */
01768                 for ( i = 1 ; i <= max_rad ; i++ )
01769                 {
01770                     if ( row + i < ily)
01771                     {
01772                         if ( !isnan(pmdata[col + (row+i) * mlx])
01773                              && pmdata[col + (row+i) * mlx] != 0. &&
01774                                 !isnan(pidata[col + (row+i) * ilx]) )
01775                         {
01776                             validpixel[n] = pidata[col + (row+i) * ilx] ;
01777                             n++ ;
01778                         }
01779                     }
01780                     if ( row - i >= 0 )
01781                     {
01782                         if ( !isnan(pmdata[col + (row-i) * mlx])
01783                              && pmdata[col + (row-i) * mlx] != 0. &&
01784                                 !isnan(pidata[col + (row-i) * ilx]) )
01785                         {
01786                             validpixel[n] = pidata[col + (row-i) * ilx] ;
01787                             n++ ;
01788                         }
01789                     }
01790 
01791                     /* be aware of the slitlet edges in the
01792                        spatial direction */
01793                     if ( col + i < ilx )
01794                     {
01795                       if (  slitlet != -1000 )
01796                       {
01797                          if (col+i <= sinfo_new_nint(slit_edges[slitlet][1]) &&
01798                              !isnan(pmdata[col + i + row * mlx]) &&
01799                              pmdata[col + i + row * mlx] != 0. &&
01800                              !isnan(pidata[col + i + row * ilx]) )
01801                          {
01802                              validpixel[n] = pidata[col + i + row * ilx] ;
01803                              n++ ;
01804                          }
01805                       }
01806                     }
01807                     if ( col - i >= 0 )
01808                     {
01809                       if ( slitlet != -1000 )
01810                       {
01811                          if (col-i >= sinfo_new_nint(slit_edges[slitlet][0]) &&
01812                              !isnan(pmdata[col - i + row * mlx]) &&
01813                              pmdata[col - i + row * mlx] != 0. &&
01814                              !isnan(pidata[col - i + row * ilx]) )
01815                          {
01816                              validpixel[n] = pidata[col - i + row * ilx] ;
01817                              n++ ;
01818                          }
01819                       }
01820                     }
01821 
01822                     if ( i == 1 && n > 1 )
01823                     {
01824                         break ;
01825                     }
01826                     if ( n > 2 )
01827                     {
01828                         break ;
01829                     }
01830                 }
01831 
01832                 if ( n == 0 )
01833                 {
01834                     podata[col + row*ilx] = ZERO ;
01835             /*sinfo_msg_warning("sinfo_interpolSourceImage:",
01836                                         "bad pixel in column: %d and row: %d"
01837                                         " could not be interpolated!",col,row);
01838                              */
01839                 }
01840                 else
01841                 {
01842                     /* now compute the mean and replace
01843                        the bad pixel value by the mean */
01844                     sum = 0. ;
01845                     for ( i = 0 ; i < n ; i++ )
01846                     {
01847                         sum += validpixel[i] ;
01848                     }
01849                     podata[col + row*ilx] = sum/n ;
01850                 }
01851             }
01852         }
01853     }
01854 
01855     return returnImage ;
01856 }
01857 
01867 cpl_image * sinfo_new_stack_row_to_image ( Vector * row, int ly )
01868 {
01869     cpl_image * image=NULL;
01870     int        col=0;
01871     int        ro=0;
01872     float* podata=NULL;
01873 
01874     if ( row == NullVector )
01875     {
01876         sinfo_msg_error ("Null sinfo_vector as input" ) ;
01877         return NULL ;
01878     }
01879     if ( ly <= 1 )
01880     {
01881         sinfo_msg_error ("wrong image length given" ) ;
01882         return NULL ;
01883     }
01884 
01885     /* allocate memory */
01886     if (NULL == (image = cpl_image_new(row->n_elements ,ly,CPL_TYPE_FLOAT )) )
01887     {
01888         sinfo_msg_error ("cannot allocate new image" ) ;
01889         return NULL ;
01890     }
01891     podata=cpl_image_get_data_float(image);
01892 
01893     for ( col = 0 ; col < row -> n_elements ; col++ )
01894     {
01895         for ( ro = 0 ; ro < ly ; ro++ )
01896         {
01897             podata[col + ro*ly] = row -> data[col] ;
01898         }
01899     }
01900     return image ;
01901 }
01902 
01918 Stats * sinfo_new_image_stats_on_rectangle ( cpl_image * im,
01919                                 float      loReject,
01920                                 float      hiReject,
01921                                 int        llx,
01922                                 int        lly,
01923                                 int        urx,
01924                                 int        ury )
01925 {
01926     Stats * retstats=NULL;
01927     int i=0 ;
01928     int row=0;
01929     int col=0;
01930     int n=0;
01931     int npix=0;
01932     int lo_n=0;
01933     int hi_n=0;
01934     double pix_sum=0;
01935     double sqr_sum=0;
01936     float * pix_array=NULL;
01937     int im_lx=0;
01938     int im_ly=0;
01939     float* pim=NULL;
01940 
01941     if ( NULL == im )
01942     {
01943         sinfo_msg_error("sorry, no input image given!") ;
01944         return NULL ;
01945     }
01946     if ( loReject+hiReject >= 100. )
01947     {
01948         sinfo_msg_error("sorry, too much pixels rejected!") ;
01949         return NULL ;
01950     }
01951     if ( loReject < 0. || loReject >= 100. ||
01952          hiReject < 0. || hiReject >= 100. )
01953     {
01954         sinfo_msg_error("sorry, negative reject values!") ;
01955         return NULL ;
01956     }
01957 
01958     im_lx=cpl_image_get_size_x(im);
01959     im_ly=cpl_image_get_size_y(im);
01960 
01961     if ( llx < 0 || lly < 0 || urx < 0 || ury < 0 ||
01962          llx >= im_lx || lly >= im_ly || urx >= im_lx ||
01963          ury >= im_ly || ury <= lly || urx <= llx )
01964     {
01965         sinfo_msg_error("sorry, wrong pixel coordinates of rectangle!") ;
01966         return NULL ;
01967     }
01968 
01969      /* allocate memory */
01970     retstats = (Stats*) cpl_calloc(1, sizeof(Stats)) ;
01971     npix = (urx - llx + 1) * (ury - lly + 1) ;
01972     pix_array = (float*) cpl_calloc ( npix, sizeof(float) ) ;
01973 
01974     /*-------------------------------------------------------------------------
01975      * go through the rectangle and copy the pixel values into an array.
01976      */
01977     n = 0 ;
01978     pim = cpl_image_get_data_float(im);
01979     for ( row = lly ; row <= ury ; row++ )
01980     {
01981         for ( col = llx ; col <= urx ; col++ )
01982         {
01983             if ( !isnan(pim[col + row*im_lx]) )
01984             {
01985                 pix_array[n] = pim[col + row*im_lx] ;
01986                 n++ ;
01987             }
01988     }
01989     }
01990 
01991     npix = n;
01992     /*if (n != npix)
01993     {
01994         sinfo_msg_error("the computed number of pixel equals "
01995                         "not the counted number, impossible!") ;
01996         cpl_free(retstats) ;
01997         cpl_free(pix_array) ;
01998         return NULL ;
01999     }*/
02000 
02001     /* determining the clean mean is already done in the recipes */
02002     if ( FLT_MAX == (retstats->cleanmean = sinfo_new_clean_mean(pix_array,
02003                                            npix, loReject, hiReject)) )
02004     {
02005         sinfo_msg_error("sinfo_new_clean_mean() did not work!") ;
02006         cpl_free(retstats) ;
02007         cpl_free(pix_array) ;
02008         return NULL ;
02009     }
02010 
02011     /* now the clean standard deviation must be calculated */
02012     /* initialize sums */
02013     lo_n = (int) (loReject / 100. * (float)npix) ;
02014     hi_n = (int) (hiReject / 100. * (float)npix) ;
02015     pix_sum = 0. ;
02016     sqr_sum = 0. ;
02017     n = 0 ;
02018     for ( i = lo_n ; i <= npix - hi_n ; i++ )
02019     {
02020         pix_sum += (double)pix_array[i] ;
02021         sqr_sum += ((double)pix_array[i] * (double)pix_array[i]) ;
02022         n++ ;
02023     }
02024 
02025     if ( n == 0 )
02026     {
02027         sinfo_msg_error("number of clean pixels is zero!") ;
02028         cpl_free(retstats) ;
02029         cpl_free(pix_array) ;
02030         return NULL ;
02031     }
02032     retstats -> npix = n ;
02033     pix_sum /= (double) n ;
02034     sqr_sum /= (double) n ;
02035     retstats -> cleanstdev = (float)sqrt(sqr_sum - pix_sum * pix_sum) ;
02036     cpl_free (pix_array) ;
02037     return retstats ;
02038 }
02039 
02040 
02041 
02050 cpl_image * sinfo_new_normalize_to_central_pixel ( cpl_image * image )
02051 {
02052     int col=0;
02053     int row=0;
02054     int i=0;
02055     int n=0;
02056     float* array=NULL ;
02057     float divisor=0;
02058     cpl_image * retImage=NULL;
02059     int ilx=0;
02060     int ily=0;
02061     float* pidata=NULL;
02062     float* podata=NULL;
02063 
02064     if ( image == NULL )
02065     {
02066         sinfo_msg_error("no image given!") ;
02067         return NULL ;
02068     }
02069     ilx=cpl_image_get_size_x(image);
02070     ily=cpl_image_get_size_y(image);
02071     pidata=cpl_image_get_data_float(image);
02072 
02073     retImage = cpl_image_duplicate(image) ;
02074     podata=cpl_image_get_data_float(retImage);
02075 
02076     n = 0 ;
02077     /* go through the central two image rows and store
02078        the values in an array */
02079     array=cpl_calloc(2*ilx,sizeof(float)) ;
02080 
02081     for ( row = ily/2 ; row < ily/2+1 ; row++ )
02082     {
02083         for ( col = 0 ; col < ilx ; col++ )
02084         {
02085             if ( !isnan(pidata[col+ilx*row]) )
02086             {
02087                 array[n] = pidata[col+ilx*row] ;
02088                 n++ ;
02089             }
02090         }
02091     }
02092     /* compute the sinfo_median of the central 2 spectral
02093        values of all spatial pixels*/
02094     if ( isnan(divisor = sinfo_new_median(array, n) ) )
02095     {
02096         sinfo_msg_error("no sinfo_median possible!") ;
02097         return NULL ;
02098     }
02099     if ( 0 == divisor )
02100     {
02101         sinfo_msg_error("cannot divide by 0") ;
02102         return NULL ;
02103     }
02104 
02105     for ( i = 0 ; i < (int) ilx*ily ; i++ )
02106     {
02107         if ( isnan(pidata[i]) )
02108         {
02109             podata[i] = ZERO ;
02110         }
02111         else
02112         {
02113             podata[i] = pidata[i]/divisor ;
02114         }
02115     }
02116     cpl_free(array);
02117     return retImage ;
02118 }
02119 
02120 /*-------------------------------------------------------------------------*/
02149 /*--------------------------------------------------------------------------*/
02150 
02151 cpl_image *
02152 sinfo_new_mpe_shift_image(
02153     cpl_image    *    image_in,
02154     double           shift_x,
02155     double           shift_y,
02156     double       *   interp_kernel)
02157 {
02158     cpl_image    *       shifted=NULL ;
02159     pixelvalue  *       first_pass=NULL ;
02160     pixelvalue  *       second_pass=NULL ;
02161     int             samples = KERNEL_SAMPLES ;
02162     int          i=0, j=0 ;
02163     double           fx=0, fy=0 ;
02164     double           rx=0, ry=0 ;
02165     int             px=0, py=0 ;
02166     int             tabx=0, taby=0 ;
02167     double           value=0 ;
02168     size_t          pos ;
02169     register pixelvalue     *   pix ;
02170     register pixelvalue     *   pixint ;
02171     int             mid=0;
02172     double          norm=0 ;
02173     double       *      ker=NULL ;
02174     int                         freeKernel = 1 ;
02175 
02176     int ilx=0;
02177     int ily=0;
02178     float* pidata=NULL;
02179     float* psdata=NULL;
02180 
02181 
02182     /* error handling: test entries */
02183     if (image_in==NULL) return NULL ;
02184 
02185     /* Shifting by a zero offset returns a copy of the input image */
02186     if ((fabs(shift_x)<1e-2) && (fabs(shift_y)<1e-2))
02187       return cpl_image_duplicate(image_in) ;
02188     ilx=cpl_image_get_size_x(image_in);
02189     ily=cpl_image_get_size_y(image_in);
02190     pidata=cpl_image_get_data_float(image_in);
02191 
02192 
02193         /* See if a kernel needs to be generated */
02194     if (interp_kernel == NULL) {
02195         ker = sinfo_generate_interpolation_kernel("default") ;
02196         if (ker == NULL) {
02197             sinfo_msg_error("kernel generation failure:aborting resampling") ;
02198             return NULL ;
02199         }
02200     } else {
02201         ker = interp_kernel ;
02202         freeKernel = 0 ;
02203     }
02204 
02205     mid = (int)samples/(int)2 ;
02206     first_pass = cpl_calloc(ilx, ily*sizeof(pixelvalue)) ;
02207     shifted = cpl_image_new(ilx, ily,CPL_TYPE_FLOAT) ;
02208     psdata=cpl_image_get_data_float(shifted);
02209 
02210     second_pass = psdata ;
02211 
02212     pix = pidata ;
02213     if ( ilx != 1 )
02214     {
02215     for (j=0 ; j<ily ; j++)
02216         {
02217          for (i=0 ; i<ilx ; i++) {
02218            fx = (double)i-shift_x ;
02219            px = (int)fx ;
02220            rx = fx - (double)px ;
02221            pos = px + j * ilx ;
02222 
02223            if ((px>1) && (px<(ilx-2)))
02224            {
02225            tabx = (int)(fabs((double)mid * rx)) ;
02226            /* exclude blank (ZERO) pixels from interpolation */
02227            if (isnan(pix[pos]))
02228                {
02229                value = ZERO ;
02230                }
02231            else
02232                {
02233                if (isnan(pix[pos-1]))
02234                {
02235                pix[pos-1] = 0. ;
02236                }
02237                if (isnan(pix[pos+1]))
02238                {
02239                pix[pos+1] = 0. ;
02240                }
02241                if (isnan(pix[pos+2]))
02242                {
02243                pix[pos+2] = 0. ;
02244                }
02245 
02246                /*
02247             * Sum up over 4 closest pixel values,
02248             * weighted by interpolation kernel values
02249             */
02250                value =     (double)pix[pos-1] * ker[mid+tabx] +
02251                (double)pix[pos] * ker[tabx] +
02252                (double)pix[pos+1] * ker[mid-tabx] +
02253                (double)pix[pos+2] * ker[samples-tabx-1] ;
02254                /*
02255             * Also sum up interpolation kernel coefficients
02256             * for further normalization
02257             */
02258                norm =      (double)ker[mid+tabx] +
02259                (double)ker[tabx] +
02260                (double)ker[mid-tabx] +
02261                (double)ker[samples-tabx-1] ;
02262                if (fabs(norm) > 1e-4) {
02263                value /= norm ;
02264                }
02265                }
02266            } else {
02267            value = ZERO ;
02268            }
02269            /*
02270         * There may be a problem of rounding here if pixelvalue
02271         * has not enough bits to sustain the accuracy.
02272         */
02273            if ( isnan(value) )
02274            {
02275            first_pass[i+j*ilx] = ZERO ;
02276            }
02277            else
02278            {
02279            first_pass[i+j*ilx] = (pixelvalue)value ;
02280            }
02281          }
02282         }
02283     }
02284     else
02285     {
02286     memcpy(first_pass,pix,ily*sizeof(pixelvalue));
02287     }
02288 
02289     pixint = first_pass ;
02290     for (i=0 ; i<ilx ; i++) {
02291         for (j=0 ; j<ily ; j++) {
02292             fy = (double)j - shift_y ;
02293             py = (int)fy ;
02294             ry = fy - (double)py ;
02295             pos = i + py * ilx ;
02296 
02297             taby = (int)(fabs((double)mid * ry)) ;
02298 
02299             if ((py>(int)1) && (py<(ily-2))) {
02300                 /* exclude blank (ZERO) pixels from interpolation */
02301                 if (isnan(pixint[pos]) && ilx != 1 )
02302                 {
02303                     value = ZERO ;
02304                 }
02305                 else
02306                 {
02307                     if (isnan(pixint[pos-ilx]))
02308                     {
02309                         pixint[pos-ilx] = 0. ;
02310                     }
02311                     if (isnan(pixint[pos+ilx]))
02312                     {
02313                         pixint[pos+ilx] = 0. ;
02314                     }
02315                     if (isnan(pixint[pos+2*ilx]))
02316                     {
02317                         pixint[pos+2*ilx] = 0. ;
02318                     }
02319                     /*
02320                      * Sum up over 4 closest pixel values,
02321                      * weighted by interpolation kernel values
02322                      */
02323                     value = (double)pixint[pos-ilx] * ker[mid+taby] +
02324                             (double)pixint[pos] * ker[taby] +
02325                             (double)pixint[pos+ilx] * ker[mid-taby] +
02326                             (double)pixint[pos+2*ilx]*ker[samples-taby-1];
02327                     /*
02328                      * Also sum up interpolation kernel coefficients
02329                      * for further normalization
02330                      */
02331                     norm =      (double)ker[mid+taby] +
02332                                 (double)ker[taby] +
02333                                 (double)ker[mid-taby] +
02334                                 (double)ker[samples-taby-1] ;
02335 
02336                     if (fabs(norm) > 1e-4) {
02337                         value /= norm ;
02338                     }
02339                 }
02340             } else {
02341                 value = ZERO ;
02342             }
02343             if (isnan(value))
02344             {
02345                 second_pass[i+j*ilx] = ZERO ;
02346             }
02347             else
02348             {
02349                 second_pass[i+j*ilx] = (pixelvalue)value ;
02350             }
02351         }
02352     }
02353 
02354     cpl_free(first_pass) ;
02355     if (freeKernel)
02356         cpl_free(ker) ;
02357     return shifted ;
02358 }
02359 
02360 
02361 /*-------------------------------------------------------------------------*/
02392 /*--------------------------------------------------------------------------*/
02393 
02394 void
02395 sinfo_new_shift_image_in_cube(
02396     cpl_image     *   image_in,
02397     double           shift_x,
02398     double           shift_y,
02399     double       *   interp_kernel,
02400     cpl_image     *   shifted,
02401     pixelvalue   *   first_pass)
02402 {
02403     pixelvalue  *       second_pass=NULL ;
02404     int             samples = KERNEL_SAMPLES ;
02405     int          i=0, j=0 ;
02406     double           fx=0, fy=0 ;
02407     double           rx=0, ry=0 ;
02408     int             px=0, py=0 ;
02409     int             tabx=0, taby=0 ;
02410     double           value=0 ;
02411     size_t          pos ;
02412     register pixelvalue     *   pix ;
02413     register pixelvalue     *   pixint ;
02414     int             mid=0;
02415     double          norm=0 ;
02416     double       *      ker=NULL ;
02417     int                         freeKernel = 1 ;
02418 
02419     int ilx=0;
02420     int ily=0;
02421     int slx=0;
02422     int sly=0;
02423     float* pidata=NULL;
02424     float* psdata=NULL;
02425 
02426     /* error handling: test entries */
02427         if (image_in==NULL) shifted = NULL ;
02428         pidata=cpl_image_get_data_float(image_in);
02429         ilx=cpl_image_get_size_x(image_in);
02430         ily=cpl_image_get_size_y(image_in);
02431 
02432         shifted=cpl_image_new(ilx,ily,CPL_TYPE_FLOAT);
02433         slx=ilx;
02434         sly=ily;
02435 
02436         psdata=cpl_image_get_data_float(shifted);
02437 
02438         /* Shifting by a zero offset returns a copy of the input image */
02439         if ((fabs(shift_x)<1e-2) && (fabs(shift_y)<1e-2))
02440                 memcpy(psdata,pidata, (size_t) slx*sly * sizeof(pixelvalue)) ;
02441 
02442         /* See if a kernel needs to be generated */
02443     if (interp_kernel == NULL) {
02444         ker = sinfo_generate_interpolation_kernel("default") ;
02445         if (ker == NULL) {
02446             sinfo_msg_error("kernel generation failure:aborting resampling") ;
02447             shifted = NULL ;
02448         }
02449     } else {
02450         ker = interp_kernel ;
02451         freeKernel = 0 ;
02452     }
02453 
02454     mid = (int)samples/(int)2 ;
02455     second_pass = psdata ;
02456 
02457     pix = pidata ;
02458     for (j=0 ; j<ily ; j++) {
02459         for (i=1 ; i<ilx-2 ; i++) {
02460             fx = (double)i-shift_x ;
02461             px = (int)fx ;
02462             rx = fx - (double)px ;
02463 
02464             pos = px + j * ilx ;
02465 
02466             if ((px>1) && (px<(ilx-2))) {
02467                 tabx = (int)(fabs((double)mid * rx)) ;
02468                 /* exclude blank (ZERO) pixels from interpolation */
02469                 if (isnan(pix[pos]))
02470                 {
02471                     value = ZERO ;
02472                 }
02473                 else
02474                 {
02475                     if (isnan(pix[pos-1]))
02476                     {
02477                         pix[pos-1] = 0. ;
02478                     }
02479                     if (isnan(pix[pos+1]))
02480                     {
02481                         pix[pos+1] = 0. ;
02482                     }
02483                     if (isnan(pix[pos+2]))
02484                     {
02485                         pix[pos+2] = 0. ;
02486                     }
02487 
02488                     /*
02489                      * Sum up over 4 closest pixel values,
02490                      * weighted by interpolation kernel values
02491                      */
02492                     value =     (double)pix[pos-1] * ker[mid+tabx] +
02493                                 (double)pix[pos] * ker[tabx] +
02494                                 (double)pix[pos+1] * ker[mid-tabx] +
02495                                 (double)pix[pos+2] * ker[samples-tabx-1] ;
02496                     /*
02497                      * Also sum up interpolation kernel coefficients
02498                      * for further normalization
02499                      */
02500                     norm =      (double)ker[mid+tabx] +
02501                                 (double)ker[tabx] +
02502                                 (double)ker[mid-tabx] +
02503                                 (double)ker[samples-tabx-1] ;
02504                     if (fabs(norm) > 1e-4) {
02505                         value /= norm ;
02506                     }
02507                 }
02508             } else {
02509                 value = 0.0 ;
02510             }
02511             /*
02512              * There may be a problem of rounding here if pixelvalue
02513              * has not enough bits to sustain the accuracy.
02514              */
02515             if ( isnan(value) )
02516             {
02517                 first_pass[i+j*ilx] = ZERO ;
02518             }
02519             else
02520             {
02521                 first_pass[i+j*ilx] = (pixelvalue)value ;
02522             }
02523         }
02524     }
02525     pixint = first_pass ;
02526     for (i=0 ; i< ilx ; i++) {
02527         for (j=1 ; j< ily-2 ; j++) {
02528             fy = (double)j - shift_y ;
02529             py = (int)fy ;
02530             ry = fy - (double)py ;
02531             pos = i + py * ilx ;
02532 
02533             taby = (int)(fabs((double)mid * ry)) ;
02534 
02535             if ((py>(int)1) && (py<(ily-2))) {
02536                 /* exclude blank (ZERO) pixels from interpolation */
02537                 if (isnan(pixint[pos]))
02538                 {
02539                     value = ZERO ;
02540                 }
02541                 else
02542                 {
02543                     if (isnan(pixint[pos-ilx]))
02544                     {
02545                         pixint[pos-ilx] = 0. ;
02546                     }
02547                     if (isnan(pixint[pos+ilx]))
02548                     {
02549                         pixint[pos+ilx] = 0. ;
02550                     }
02551                     if (isnan(pixint[pos+2*ilx]))
02552                     {
02553                         pixint[pos+2*ilx] = 0. ;
02554                     }
02555                     /*
02556                      * Sum up over 4 closest pixel values,
02557                      * weighted by interpolation kernel values
02558                      */
02559                     value = (double)pixint[pos-ilx] * ker[mid+taby] +
02560                             (double)pixint[pos] * ker[taby] +
02561                             (double)pixint[pos+ilx] * ker[mid-taby] +
02562                             (double)pixint[pos+2*ilx]*ker[samples-taby-1];
02563                     /*
02564                      * Also sum up interpolation kernel coefficients
02565                      * for further normalization
02566                      */
02567                     norm =      (double)ker[mid+taby] +
02568                                 (double)ker[taby] +
02569                                 (double)ker[mid-taby] +
02570                                 (double)ker[samples-taby-1] ;
02571 
02572                     if (fabs(norm) > 1e-4) {
02573                         value /= norm ;
02574                     }
02575                 }
02576             } else {
02577           /* value = 0.0 ; AMo: This affect slitlet #1 */
02578             }
02579             if (isnan(value))
02580             {
02581                 second_pass[i+j*ilx] = ZERO ;
02582             }
02583             else
02584             {
02585                 second_pass[i+j*ilx] = (pixelvalue)value ;
02586             }
02587         }
02588     }
02589 
02590     if (freeKernel)
02591         cpl_free(ker) ;
02592 }
02593 
02594 /* function to delete the image statistics within python */
02595 void sinfo_new_del_Stats( Stats * st)
02596 {
02597     cpl_free (st) ;
02598 }
02599 
02606 cpl_image *
02607 sinfo_new_combine_masks ( cpl_image * firstMask, cpl_image * secondMask )
02608 {
02609     cpl_image * retMask=NULL ;
02610     int n=0 ;
02611     int olx=0;
02612     int oly=0;
02613     float* podata=NULL;
02614     float* pm1data=NULL;
02615     float* pm2data=NULL;
02616 
02617     if ( firstMask == NULL || secondMask == NULL )
02618     {
02619         sinfo_msg_error ("no input mask image given!") ;
02620         return NULL ;
02621     }
02622     retMask = cpl_image_duplicate (firstMask) ;
02623     podata = cpl_image_get_data_float(retMask);
02624     pm1data = cpl_image_get_data_float(firstMask);
02625     pm2data = cpl_image_get_data_float(secondMask);
02626     olx=cpl_image_get_size_x(retMask);
02627     oly=cpl_image_get_size_y(retMask);
02628 
02629     for ( n = 0 ; n < (int) olx*oly ; n++ )
02630     {
02631        if ( podata[n] == 0. || pm2data[n] == 0. )
02632        {
02633            podata[n] = 0. ;
02634        }
02635        else
02636        {
02637            podata[n] = 1. ;
02638        }
02639     }
02640     return retMask ;
02641 }
02642 
02651 cpl_image * sinfo_new_slice_cube (cpl_imagelist * cube, int x, int y )
02652 {
02653     cpl_image * retImage=NULL ;
02654     int col=0, row=0, z=0 ;
02655     int inp=0;
02656     int ilx=0;
02657     int ily=0;
02658     cpl_image* img=NULL;
02659     float* podata=NULL;
02660     float* pidata=NULL;
02661 
02662     if ( cube == NULL )
02663     {
02664         sinfo_msg_error("no cube given!") ;
02665         return NULL ;
02666     }
02667     if ( x > 31 || y > 31 )
02668     {
02669         sinfo_msg_warning("wrong x or y values!") ;
02670     }
02671 
02672     img=cpl_imagelist_get(cube,0);
02673     ilx=cpl_image_get_size_x(img);
02674     ily=cpl_image_get_size_y(img);
02675     inp=cpl_imagelist_get_size(cube);
02676     if ( x < 0 )
02677     {
02678         /* allocate memory */
02679         if ( NULL == (retImage = cpl_image_new(ilx, inp, CPL_TYPE_FLOAT)) )
02680         {
02681             sinfo_msg_error("could not allocate memory!") ;
02682             return NULL ;
02683         }
02684         podata=cpl_image_get_data_float(retImage);
02685         for ( z = 0 ; z < inp ; z++ )
02686         {
02687 
02688             pidata=cpl_image_get_data_float(cpl_imagelist_get(cube,z));
02689             for ( col = 0 ; col < ilx ; col++ )
02690             {
02691                 podata[col+z*ilx] = pidata[col+y*ilx] ;
02692             }
02693         }
02694     }
02695     else if ( y < 0 )
02696     {
02697         /* allocate memory */
02698         if ( NULL == (retImage = cpl_image_new(ily, inp,CPL_TYPE_FLOAT)) )
02699         {
02700             sinfo_msg_error("could not allocate memory!") ;
02701             return NULL ;
02702         }
02703         podata=cpl_image_get_data_float(retImage);
02704 
02705         for ( z = 0 ; z < inp ; z++ )
02706         {
02707             pidata=cpl_image_get_data_float(cpl_imagelist_get(cube,z));
02708             for ( row = 0 ; row < ily ; row++ )
02709             {
02710                 podata[row+z*ily] = pidata[x+row*ily] ;
02711             }
02712         }
02713     }
02714     else
02715     {
02716         sinfo_msg_error("wrong input!") ;
02717         return NULL ;
02718     }
02719     return retImage ;
02720 }
02721 
02733 cpl_image * sinfo_new_div_images_robust ( cpl_image * im1, cpl_image * im2 )
02734 {
02735     cpl_image * retIm=NULL ;
02736     float help=0 ;
02737     int i=0 ;
02738     int lx1=0;
02739     int ly1=0;
02740     int lx2=0;
02741     int ly2=0;
02742 
02743     float* p1data=NULL;
02744     float* p2data=NULL;
02745     float* podata=NULL;
02746 
02747     if ( im1 == NULL || im2 == NULL )
02748     {
02749         sinfo_msg_error("no input images given!") ;
02750         return NULL ;
02751     }
02752     lx1=cpl_image_get_size_x(im1);
02753     ly1=cpl_image_get_size_y(im1);
02754     lx2=cpl_image_get_size_x(im2);
02755     ly2=cpl_image_get_size_y(im2);
02756     p1data=cpl_image_get_data_float(im1);
02757     p2data=cpl_image_get_data_float(im2);
02758 
02759     if ( lx1 != lx2 || ly1 != ly2 )
02760     {
02761         sinfo_msg_error("images not compatible!") ;
02762         return NULL ;
02763     }
02764     if ( NULL == (retIm = cpl_image_new(lx1, ly1, CPL_TYPE_FLOAT)) )
02765     {
02766         sinfo_msg_error("could not allocate memory!") ;
02767         return NULL ;
02768     }
02769     podata=cpl_image_get_data_float(retIm);
02770 
02771     for ( i = 0 ; i < (int) lx2*ly2 ; i++ )
02772     {
02773         if ( !isnan(p2data[i]) )
02774         {
02775             help = 1./p2data[i] ;
02776             if (fabs( help )> THRESH )
02777             {
02778                help = 1. ;
02779             }
02780         }
02781         else
02782         {
02783             help = ZERO ;
02784         }
02785         if ( isnan(help) || isnan(p1data[i]) )
02786         {
02787             podata[i] = ZERO ;
02788         }
02789         else
02790         {
02791             podata[i] = p1data[i] * help ;
02792         }
02793     }
02794     return retIm ;
02795 }
02796 
02797 cpl_image * sinfo_new_null_edges ( cpl_image * image)
02798 {
02799     cpl_image * new=NULL ;
02800     int i=0,j=0 ;
02801     int ilx=0;
02802     int ily=0;
02803     int olx=0;
02804     int oly=0;
02805 
02806     float* pidata=NULL;
02807     float* podata=NULL;
02808 
02809     if ( image == NULL )
02810     {
02811         sinfo_msg_error ("no input image given!\n") ;
02812         return NULL ;
02813     }
02814 
02815 
02816     new = cpl_image_duplicate (image) ;
02817     ilx=cpl_image_get_size_x(image);
02818     ily=cpl_image_get_size_y(image);
02819     olx=cpl_image_get_size_x(new);
02820     oly=cpl_image_get_size_y(new);
02821     pidata=cpl_image_get_data_float(image);
02822     podata=cpl_image_get_data_float(new);
02823 
02824     for ( i = 0 ; i < olx ; i++ )
02825     {
02826         for ( j = 0 ; j < 4 ; j++)
02827     {
02828         podata[i+j*olx]=0;
02829         podata[i+(oly-j-1)*olx]=0;
02830     }
02831     }
02832     for ( i = 0 ; i < oly ; i++ )
02833     {
02834         for ( j = 0 ; j < 4 ; j++)
02835     {
02836         podata[j+i*olx]=0;
02837         podata[(olx-j-1)+i*olx]=0;
02838     }
02839     }
02840     return new ;
02841 }
02842 
02843 
02844 void sinfo_new_used_cor_map( cpl_image *im, cpl_image *map)
02845 {
02846     int i=0,j=0,loc_index=0;
02847     float temp_array[2048];
02848     int lx=cpl_image_get_size_x(im);
02849     int ly=cpl_image_get_size_y(im);
02850     float* pidata=cpl_image_get_data_float(im);
02851     float* pmdata=cpl_image_get_data_float(map);
02852 
02853     for( j=0; j<ly; j++)
02854     {
02855     for( i=0;i<lx;i++)
02856         {
02857           loc_index = (int)pmdata[i+j*lx];
02858            temp_array[i] = pidata[loc_index+j*lx];
02859         }
02860     for( i=0;i<lx;i++)
02861         {
02862           pidata[i+j*lx]= temp_array[i];
02863         }
02864     }
02865 }
02866 
02867 
02868 
02869 
02870 /*-------------------------------------------------------------------------*/
02893 /*--------------------------------------------------------------------------*/
02894 
02895 cpl_image *
02896 sinfo_new_shift_image(
02897     cpl_image    *    image_in,
02898     double           shift_x,
02899     double           shift_y,
02900     double       *    interp_kernel)
02901 {
02902     cpl_image    *    shifted=NULL ;
02903     float  *    first_pass=NULL ;
02904     float  *    second_pass=NULL ;
02905     int             samples = KERNEL_SAMPLES ;
02906     int          i=0, j=0 ;
02907     double           fx=0, fy=0 ;
02908     double           rx=0, ry=0 ;
02909     int             px=0, py=0 ;
02910     int             tabx=0, taby=0 ;
02911     double           value=0 ;
02912     size_t          pos ;
02913     register float     *    pix=NULL ;
02914     register float     *    pixint=NULL ;
02915     int             mid=0;
02916     double          norm=0 ;
02917     double       *    ker=NULL ;
02918     int                freeKernel = 1 ;
02919     int ilx=0;
02920     int ily=0;
02921 
02922     /* error handling: test entries */
02923     if (image_in==NULL) return NULL ;
02924 
02925     /* Shifting by a zero offset returns a copy of the input image */
02926     if ((fabs(shift_x)<1e-2) && (fabs(shift_y)<1e-2))
02927         return cpl_image_duplicate(image_in) ;
02928 
02929     /* See if a kernel needs to be generated */
02930     if (interp_kernel == NULL) {
02931         ker = sinfo_generate_interpolation_kernel("default") ;
02932         if (ker == NULL) {
02933             sinfo_msg_error("kernel generation failure: aborting resampling") ;
02934             return NULL ;
02935         }
02936     } else {
02937         ker = interp_kernel ;
02938         freeKernel = 0 ;
02939     }
02940 
02941     ilx=cpl_image_get_size_x(image_in);
02942     ily=cpl_image_get_size_y(image_in);
02943 
02944 
02945     pix = cpl_image_get_data_float(image_in);
02946     if (pix)
02947     {
02948         mid = (int)samples/(int)2 ;
02949         first_pass = cpl_calloc(ilx, ily*sizeof(float)) ;
02950         shifted = cpl_image_new(ilx, ily,CPL_TYPE_FLOAT) ;
02951         second_pass = cpl_image_get_data_float(shifted);
02952         for (j=0 ; j<ily ; j++) {
02953             for (i=1 ; i<ilx-2 ; i++) {
02954                 fx = (double)i-shift_x ;
02955                 px = (int)fx ;
02956                 rx = fx - (double)px ;
02957 
02958                 pos = px + j * ilx ;
02959 
02960                 if ((px>1) && (px<(ilx-3))) {
02961                     tabx = (int)(fabs((double)mid * rx)) ;
02962                     /*
02963                      * Sum up over 4 closest pixel values,
02964                      * weighted by interpolation kernel values
02965                      */
02966                     value =     (double)pix[pos-1] * ker[mid+tabx] +
02967                                 (double)pix[pos] * ker[tabx] +
02968                                 (double)pix[pos+1] * ker[mid-tabx] +
02969                                 (double)pix[pos+2] * ker[samples-tabx-1] ;
02970                     /*
02971                      * Also sum up interpolation kernel coefficients
02972                      * for further normalization
02973                      */
02974                     norm =      (double)ker[mid+tabx] +
02975                                 (double)ker[tabx] +
02976                                 (double)ker[mid-tabx] +
02977                                 (double)ker[samples-tabx-1] ;
02978                     if (fabs(norm) > 1e-4) {
02979                         value /= norm ;
02980                     }
02981                 } else {
02982                     value = 0.0 ;
02983                 }
02984                 /*
02985                  * There may be a problem of rounding here if pixelvalue
02986                  * has not enough bits to sustain the accuracy.
02987                  */
02988                 first_pass[i+j*ilx] = (float)value ;
02989             }
02990         }
02991         pixint = first_pass ;
02992         for (i=0 ; i<ilx ; i++) {
02993             for (j=1 ; j<ily-3 ; j++) {
02994                 fy = (double)j - shift_y ;
02995                 py = (int)fy ;
02996                 ry = fy - (double)py ;
02997                 pos = i + py * ilx ;
02998 
02999                 taby = (int)(fabs((double)mid * ry)) ;
03000 
03001                 if ((py>(int)1) && (py<(ily-2))) {
03002                     /*
03003                      * Sum up over 4 closest pixel values,
03004                      * weighted by interpolation kernel values
03005                      */
03006                     value = (double)pixint[pos-ilx] * ker[mid+taby] +
03007                             (double)pixint[pos] * ker[taby] +
03008                             (double)pixint[pos+ilx] * ker[mid-taby] +
03009                             (double)pixint[pos+2*ilx]*ker[samples-taby-1];
03010                     /*
03011                      * Also sum up interpolation kernel coefficients
03012                      * for further normalization
03013                      */
03014                     norm =      (double)ker[mid+taby] +
03015                                 (double)ker[taby] +
03016                                 (double)ker[mid-taby] +
03017                                 (double)ker[samples-taby-1] ;
03018 
03019                     if (fabs(norm) > 1e-4) {
03020                         value /= norm ;
03021                     }
03022                 } else {
03023                     value = 0.0 ;
03024                 }
03025                 second_pass[i+j*ilx] = (float)value ;
03026             }
03027         }
03028     }
03029     else
03030     {
03031         cpl_msg_warning(cpl_func, "cannot get a data from an image");
03032     }
03033     cpl_free(first_pass) ;
03034     if (freeKernel)
03035         cpl_free(ker) ;
03036     return shifted ;
03037 }
03038 
03039 
03040 /*-------------------------------------------------------------------------*/
03054 /*--------------------------------------------------------------------------*/
03055 
03056 cpl_image *
03057 sinfo_image_hermite_interpol(cpl_image * inp)
03058 {
03059 
03060   /*
03061    @param xp     x-value to interpolate
03062    @param x      x-values
03063    @param y      y-values
03064    @param n      array length
03065    @param istart    (input/output) initial row (set to 0 to search all row)
03066 
03067   sinfo_spline_hermite( double xp, const double *x,
03068                         const double *y, int n, int *istart );
03069 
03070   */
03071   float* pinp=NULL;
03072   float* pout=NULL;
03073   int sx=0;
03074   int sy=0;
03075   int i=0;
03076   int j=0;
03077   int r=5;
03078   int k=0;
03079 
03080   cpl_image* out=NULL;
03081 
03082   cknull(inp,"Null in put image, exit");
03083   check_nomsg(out=cpl_image_duplicate(inp));
03084   check_nomsg(sx=cpl_image_get_size_x(inp));
03085   check_nomsg(sy=cpl_image_get_size_y(inp));
03086   check_nomsg(pinp=cpl_image_get_data_float(inp));
03087   check_nomsg(pout=cpl_image_get_data_float(out));
03088   for(j=r;j<sy-r;j++) {
03089     for(i=0;i<sx;i++) {
03090       for(k=-r;k<r;k++) {
03091     pout[j*sx+i]+=pinp[(j+k)*sx+i];
03092       }
03093       pout[j*sx+i]/=2*r;
03094     }
03095   }
03096 
03097  cleanup:
03098 
03099   if(cpl_error_get_code() != CPL_ERROR_NONE) {
03100     return NULL;
03101   } else {
03102     return out;
03103 
03104   }
03105 
03106 }
03107 
03108 
03109 
03110 /*-------------------------------------------------------------------------*/
03124 /*--------------------------------------------------------------------------*/
03125 
03126 cpl_image *
03127 sinfo_image_smooth_y(cpl_image * inp, const int r)
03128 {
03129 
03130   /*
03131    @param xp     x-value to interpolate
03132    @param x      x-values
03133    @param y      y-values
03134    @param n      array length
03135    @param istart    (input/output) initial row (set to 0 to search all row)
03136 
03137   */
03138   float* pinp=NULL;
03139   float* pout=NULL;
03140   int sx=0;
03141   int sy=0;
03142   int i=0;
03143   int j=0;
03144   int k=0;
03145 
03146   cpl_image* out=NULL;
03147 
03148   cknull(inp,"Null in put image, exit");
03149   check_nomsg(out=cpl_image_duplicate(inp));
03150   check_nomsg(sx=cpl_image_get_size_x(inp));
03151   check_nomsg(sy=cpl_image_get_size_y(inp));
03152   check_nomsg(pinp=cpl_image_get_data_float(inp));
03153   check_nomsg(pout=cpl_image_get_data_float(out));
03154   for(j=r;j<sy-r;j++) {
03155     for(i=0;i<sx;i++) {
03156       for(k=-r;k<r;k++) {
03157     pout[j*sx+i]+=pinp[(j+k)*sx+i];
03158       }
03159       pout[j*sx+i]/=2*r;
03160     }
03161   }
03162 
03163  cleanup:
03164 
03165   if(cpl_error_get_code() != CPL_ERROR_NONE) {
03166     return NULL;
03167   } else {
03168     return out;
03169 
03170   }
03171 
03172 }
03173 
03174 
03175 /*-------------------------------------------------------------------------*/
03189 /*--------------------------------------------------------------------------*/
03190 
03191 cpl_image *
03192 sinfo_image_smooth_mean_y(cpl_image * inp, const int r)
03193 {
03194 
03195   /*
03196    @param xp     x-value to interpolate
03197    @param x      x-values
03198    @param y      y-values
03199    @param n      array length
03200    @param istart    (input/output) initial row (set to 0 to search all row)
03201 
03202   */
03203   float* pinp=NULL;
03204   float* pout=NULL;
03205   int sx=0;
03206   int sy=0;
03207   int i=0;
03208   int j=0;
03209   int k=0;
03210 
03211   cpl_image* out=NULL;
03212 
03213   cknull(inp,"Null in put image, exit");
03214   check_nomsg(out=cpl_image_duplicate(inp));
03215   check_nomsg(sx=cpl_image_get_size_x(inp));
03216   check_nomsg(sy=cpl_image_get_size_y(inp));
03217   check_nomsg(pinp=cpl_image_get_data_float(inp));
03218   check_nomsg(pout=cpl_image_get_data_float(out));
03219   for(j=r;j<sy-r;j++) {
03220     for(i=0;i<sx;i++) {
03221       for(k=-r;k<r;k++) {
03222     pout[j*sx+i]+=pinp[(j+k)*sx+i];
03223       }
03224       pout[j*sx+i]/=2*r;
03225     }
03226   }
03227 
03228  cleanup:
03229 
03230   if(cpl_error_get_code() != CPL_ERROR_NONE) {
03231     return NULL;
03232   } else {
03233     return out;
03234 
03235   }
03236 
03237 }
03238 
03239 
03240 /*-------------------------------------------------------------------------*/
03254 /*--------------------------------------------------------------------------*/
03255 
03256 cpl_image *
03257 sinfo_image_smooth_median_y(cpl_image * inp, const int r)
03258 {
03259 
03260   /*
03261    @param xp     x-value to interpolate
03262    @param x      x-values
03263    @param y      y-values
03264    @param n      array length
03265    @param istart    (input/output) initial row (set to 0 to search all row)
03266 
03267   */
03268   float* pout=NULL;
03269   int sx=0;
03270   int sy=0;
03271   int i=0;
03272   int j=0;
03273 
03274   cpl_image* out=NULL;
03275 
03276 
03277   cknull(inp,"Null in put image, exit");
03278   check_nomsg(out=cpl_image_duplicate(inp));
03279   check_nomsg(sx=cpl_image_get_size_x(inp));
03280   check_nomsg(sy=cpl_image_get_size_y(inp));
03281   check_nomsg(pout=cpl_image_get_data_float(out));
03282 
03283   for(j=r+1;j<sy-r;j++) {
03284     for(i=1;i<sx;i++) {
03285       pout[j*sx+i]=(float)cpl_image_get_median_window(inp,i,j,i,j+r);
03286     }
03287   }
03288 
03289  cleanup:
03290 
03291   if(cpl_error_get_code() != CPL_ERROR_NONE) {
03292     return NULL;
03293   } else {
03294     return out;
03295 
03296   }
03297 
03298 }
03299 
03300 /*-------------------------------------------------------------------------*/
03313 /*--------------------------------------------------------------------------*/
03314 
03315 cpl_image *
03316 sinfo_image_smooth_fft(cpl_image * inp, const int fy)
03317 {
03318 
03319   int sx=0;
03320   int sy=0;
03321 
03322   cpl_image* out=NULL;
03323   cpl_image* im_re=NULL;
03324   cpl_image* im_im=NULL;
03325   cpl_image* ifft_re=NULL;
03326   cpl_image* ifft_im=NULL;
03327   cpl_image* filter=NULL;
03328 
03329   int sigma_x=0;
03330   int sigma_y=fy;
03331 
03332   cknull(inp,"Null in put image, exit");
03333   check_nomsg(im_re = cpl_image_cast(inp, CPL_TYPE_DOUBLE));
03334   check_nomsg(im_im = cpl_image_cast(inp, CPL_TYPE_DOUBLE));
03335 
03336   // Compute FFT
03337   check_nomsg(cpl_image_fft(im_re,im_im,CPL_FFT_DEFAULT));
03338 
03339   check_nomsg(sx=cpl_image_get_size_x(inp));
03340   check_nomsg(sy=cpl_image_get_size_y(inp));
03341   sigma_x=sx;
03342 
03343   //Generates filter image
03344   check_nomsg(filter = sinfo_gen_lowpass(sx,sy,sigma_x,sigma_y));
03345 
03346   //Apply filter
03347   cpl_image_multiply(im_re,filter);
03348   cpl_image_multiply(im_im,filter);
03349 
03350   sinfo_free_image(&filter);
03351 
03352   check_nomsg(ifft_re = cpl_image_duplicate(im_re));
03353   check_nomsg(ifft_im = cpl_image_duplicate(im_im));
03354 
03355   sinfo_free_image(&im_re);
03356   sinfo_free_image(&im_im);
03357 
03358   //Computes FFT-INVERSE
03359   check_nomsg(cpl_image_fft(ifft_re,ifft_im,CPL_FFT_INVERSE));
03360   check_nomsg(out = cpl_image_cast(ifft_re, CPL_TYPE_FLOAT));
03361 
03362  cleanup:
03363 
03364   sinfo_free_image(&ifft_re);
03365   sinfo_free_image(&ifft_im);
03366   sinfo_free_image(&filter);
03367   sinfo_free_image(&im_re);
03368   sinfo_free_image(&im_im);
03369 
03370   if(cpl_error_get_code() != CPL_ERROR_NONE) {
03371     return NULL;
03372   } else {
03373     return out;
03374   }
03375 
03376 }
03377 
03378 
03379 
03380 /*-------------------------------------------------------------------------*/
03396 /*--------------------------------------------------------------------------*/
03397 static cpl_image *
03398 sinfo_gen_lowpass(const int xs,
03399                   const int ys,
03400                   const double sigma_x,
03401                   const double sigma_y)
03402 {
03403 
03404     int i= 0.0;
03405     int j= 0.0;
03406     int hlx= 0.0;
03407     int hly = 0.0;
03408     double x= 0.0;
03409     double y= 0.0;
03410     double gaussval= 0.0;
03411     double inv_sigma_x=1./sigma_x;
03412     double inv_sigma_y=1./sigma_y;
03413 
03414     float *data;
03415 
03416     cpl_image   *lowpass_image=NULL;
03417 
03418 
03419     lowpass_image = cpl_image_new (xs, ys, CPL_TYPE_FLOAT);
03420     if (lowpass_image == NULL) {
03421         sinfo_msg_error("Cannot generate lowpass filter <%s>",
03422                         cpl_error_get_message());
03423         return NULL;
03424     }
03425 
03426     hlx = xs/2;
03427     hly = ys/2;
03428 
03429     data = cpl_image_get_data_float(lowpass_image);
03430 
03431 /* Given an image with pixels 0<=i<N, 0<=j<M then the convolution image
03432    has the following properties:
03433 
03434    ima[0][0] = 1
03435    ima[i][0] = ima[N-i][0] = exp (-0.5 * (i/sig_i)^2)   1<=i<N/2
03436    ima[0][j] = ima[0][M-j] = exp (-0.5 * (j/sig_j)^2)   1<=j<M/2
03437    ima[i][j] = ima[N-i][j] = ima[i][M-j] = ima[N-i][M-j]
03438              = exp (-0.5 * ((i/sig_i)^2 + (j/sig_j)^2))
03439 */
03440 
03441     data[0] = 1.0;
03442 
03443     /* first row */
03444     for (i=1 ; i<=hlx ; i++) {
03445         x = i * inv_sigma_x;
03446         gaussval = exp(-0.5*x*x);
03447         data[i] = gaussval;
03448         data[xs-i] = gaussval;
03449     }
03450 
03451     for (j=1; j<=hly ; j++) {
03452         y = j * inv_sigma_y;
03453       /* first column */
03454         data[j*xs] = exp(-0.5*y*y);
03455         data[(ys-j)*xs] = exp(-0.5*y*y);
03456 
03457         for (i=1 ; i<=hlx ; i++) {
03458     /* Use internal symetries */
03459             x = i * inv_sigma_x;
03460             gaussval = exp (-0.5*(x*x+y*y));
03461             data[j*xs+i] = gaussval;
03462             data[(j+1)*xs-i] = gaussval;
03463             data[(ys-j)*xs+i] = gaussval;
03464             data[(ys+1-j)*xs-i] = gaussval;
03465 
03466         }
03467     }
03468 
03469     /* FIXME: for the moment, reset errno which is coming from exp()
03470             in first for-loop at i=348. This is causing cfitsio to
03471             fail when loading an extension image (bug in cfitsio too).
03472     */
03473     if(errno != 0)
03474         errno = 0;
03475 
03476     return lowpass_image;
03477 }
03478 
03479 static void quicksort_int(int* data, int left, int right)
03480 {
03481     int i = left;
03482     int j = right;
03483     int pivot = (i + j) / 2;
03484     double index_value = data[pivot];
03485     do
03486     {
03487         while(data[i] < index_value) i++;
03488         while(data[j] > index_value) j--;
03489         if (i <= j)
03490         {
03491             if(i < j)
03492             {
03493                 int tmp = data[i];
03494                 data[i]=data[j];
03495                 data[j]=tmp;
03496             }
03497             i++;
03498             j--;
03499         }
03500     } while (i <= j);
03501 
03502     if (i < right)
03503     {
03504         quicksort_int(data, i, right);
03505     }
03506     if (left < j)
03507     {
03508         quicksort_int(data, left, j);
03509     }
03510 }
03511 
03512 /*--------------------------------------------------------------------------*/

Generated on 8 Mar 2011 for SINFONI Pipeline Reference Manual by  doxygen 1.6.1