Esempio n. 1
0
static void chanfunc_CalcStatistics (channelPtr chan)
{
    double mean, std_dev, variance, rms, moment, median, mode, min, max;
    int err, order, min_i, max_i, intervals;
    char newnote[256];

    Fmt (chanfunc.note, "");
    err = MaxMin1D (chan->readings, chan->pts, &max, &max_i, &min, &min_i);
    SetInputMode (chanfunc.p, STATISTICS_MIN, !err);
    SetCtrlVal (chanfunc.p, STATISTICS_MIN, min);
    SetInputMode (chanfunc.p, STATISTICS_MAX, !err);
    SetCtrlVal (chanfunc.p, STATISTICS_MAX, max);
    if (err == NoErr)
    {
        Fmt (chanfunc.note, "%s<Min: %f[e2p5]\n", min);
        Fmt (chanfunc.note, "%s[a]<Max: %f[e2p5]\n", max);
    }

    err = Mean (chan->readings, chan->pts, &mean);
    SetInputMode (chanfunc.p, STATISTICS_MEAN, !err);
    SetCtrlVal (chanfunc.p, STATISTICS_MEAN, mean);
    if (err == NoErr) Fmt (chanfunc.note, "%s[a]<Mean: %f[e2p5]\n", mean);

    err = StdDev (chan->readings, chan->pts, &mean, &std_dev);
    SetInputMode (chanfunc.p, STATISTICS_STDDEV, !err);
    SetCtrlVal (chanfunc.p, STATISTICS_STDDEV, std_dev);
    if (err == NoErr) Fmt (chanfunc.note, "%s[a]<StdDev: %f[e2p5]\n", std_dev);

    err = Variance (chan->readings, chan->pts, &mean, &variance);
    SetInputMode (chanfunc.p, STATISTICS_VAR, !err);
    SetCtrlVal (chanfunc.p, STATISTICS_VAR, variance);
    if (err == NoErr) Fmt (chanfunc.note, "%s[a]<Variance: %f[e2p5]\n", variance);

    err = RMS (chan->readings, chan->pts, &rms);
    SetInputMode (chanfunc.p, STATISTICS_RMS, !err);
    SetCtrlVal (chanfunc.p, STATISTICS_RMS, rms);
    if (err == NoErr) Fmt (chanfunc.note, "%s[a]<RMS: %f[e2p5]\n", rms);

    GetCtrlVal (chanfunc.p, STATISTICS_ORDER, &order);
    err = Moment (chan->readings, chan->pts, order, &moment);
    SetInputMode (chanfunc.p, STATISTICS_MOMENT, !err);
    SetInputMode (chanfunc.p, STATISTICS_ORDER, !err);
    SetCtrlVal (chanfunc.p, STATISTICS_MOMENT, moment);
    if (err == NoErr) Fmt (chanfunc.note, "%s[a]<Moment: %f[e2p5] (order: %i)\n", moment, order);

    err = Median (chan->readings, chan->pts, &median);
    SetInputMode (chanfunc.p, STATISTICS_MEDIAN, !err);
    SetCtrlVal (chanfunc.p, STATISTICS_MEDIAN, median);
    if (err == NoErr) Fmt (chanfunc.note, "%s[a]<Median: %f[e2p5]\n", median);

    GetCtrlVal (chanfunc.p, STATISTICS_INTERVAL, &intervals);
    err = Mode (chan->readings, chan->pts, min, max, intervals, &mode);
    SetInputMode (chanfunc.p, STATISTICS_INTERVAL, !err);
    SetInputMode (chanfunc.p, STATISTICS_MODE, !err);
    SetCtrlVal (chanfunc.p, STATISTICS_INTERVAL, intervals);
    SetCtrlVal (chanfunc.p, STATISTICS_MODE, mode);
    if (err == NoErr) Fmt (chanfunc.note, "%s[a]<Mode: %f[e2p5] (intervals: %i)\n", mode, intervals);
}
Esempio n. 2
0
int Calibration::calibrateVar(){
	double largetemp=1000000;
  	double result=0;

	for(int i=0;i<Calibration::step;i++)
      for(int j=0;j<Calibration::step;j++)
        for(int k=0;k<Calibration::step;k++){
          init[0] = Calibration::sigarr[i];
          init[1] = Calibration::muarr[j];
          init[2] = Calibration::thetaarr[k];          
          result = RMS(init);
          if(result<largetemp){
            largetemp=result;           
            initguess[0] = Calibration::sigarr[i];
            initguess[1] = Calibration::muarr[j];
            initguess[2] = Calibration::thetaarr[k];            
          }
        }
    cout<<"Initial guess "<<initguess[0]<<" "<<initguess[1]<<" "<<initguess[2]<<endl;  
    //printcon( Simplex(RMS,initguess, 1e-8) );    
    //Simplex(RMS,initguess, 1e-8);
    return 0;
}
Esempio n. 3
0
double arlCore::ICP::computeCriterion( const arlCore::vnl_rigid_matrix &M, vnl_vector< double > &fx )
{
    vnl_vector<double> RMS(1, 0.0), nbPoints(1, 0.0);
    const arlCore::vnl_rigid_matrix InvM = M.computeInverse();
    unsigned int i, j, noTriangle;
    double n = 0.0, result = 0.0;
    if(m_point2PointMode)
    {   // Points to points
#ifdef ANN
        const unsigned int Dimension = 3;
        vnl_vector_fixed<double,3> traInit = InvM.getTranslation();
        vnl_matrix_fixed<double,3,3> rotInit = InvM.getRotation();
        const double Epsilon = 0.0;// Error bound
        ANNpoint Pt = annAllocPt(Dimension); // Query point
        for( i=0 ; i<m_cloudSize ; ++i )
        {   // Search the matching point for every point of cloud
            for( j=0 ; j<3; ++j )
                Pt[j] = rotInit[j][0]*m_cloudPoints[i][0]+rotInit[j][1]*m_cloudPoints[i][1]+rotInit[j][2]*m_cloudPoints[i][2]+traInit[j];
            m_ANNtree->annkSearch( Pt, m_nbNN, m_nn_idx, m_squaredDists, Epsilon );
            if(fx.size()>i) fx[i] = m_squaredDists[0];
            RMS[0] += m_squaredDists[0];
        }
        annDeallocPt(Pt);
        n = (double)m_cloudSize;
#endif // ANN
    }else
    {   // Point to mesh
        assert(m_cloud!=0 && m_modelMesh!=0);
        RMS.set_size((unsigned int)m_modelMesh->getTriangles().size());
        RMS.fill(0.0);
        nbPoints.set_size(RMS.size());
        nbPoints.fill(0.0);
        unsigned int i;
        arlCore::Point::sptr point = arlCore::Point::New(3);
        for( i=0 ; i<m_cloud->size() ; ++i )
            if(m_cloud->get(i))
                if(!m_justVisible || m_cloud->get(i)->isVisible())
                {
                    InvM.trf(m_cloud->get(i), point);
                    const double SquaredDist = m_modelMesh->computeDistance2(point, noTriangle);
                    if(SquaredDist>0.0)
                    {
                        RMS[noTriangle] += SquaredDist;
                        if(fx.size()>i) fx[i] = SquaredDist;
                        nbPoints[noTriangle] += 1;
                    }
                }
    }
    assert(nbPoints.size()==RMS.size());
    if(RMS.size()==1)
    {
        if(nbPoints[0]>0) return sqrt(RMS[i]/nbPoints[i]);
        else return -1.0;
    }
    for( i=0 ; i<RMS.size() ; ++i )
        if(nbPoints[i]>0)
        {
            result += sqrt(RMS[i]/nbPoints[i]);
            n += 1.0;
        }
    if(n>0) return result/n;
    else return -1;
}
Esempio n. 4
0
   int PRSolution3::RAIM2Compute(const CommonTime& Tr,
                               vector<SatID>& Satellite,
                               const vector<double>& Pseudorange,
                               const XvtStore<SatID>& Eph,
                               TropModel *pTropModel)
      throw(Exception)
   {
      try
      {
         int iret,N,Nreject,MinSV;
         size_t i, j;
         vector<bool> UseSat, UseSave;
         vector<int> GoodIndexes;
         // Use these to save the 'best' solution within the loop.
         int BestNIter=0;
         double BestRMS=0.0, BestSL=0.0, BestConv=0.0;
         Vector<double> BestSol(3,0.0);
         vector<bool> BestUse;
         BestRMS = -1.0;      // this marks the 'Best' set as unused.
	 Matrix<double> BestCovariance;

         // ----------------------------------------------------------------
         // initialize

         Valid = false;

         bool hasGlonass = false;
         bool hasOther = false;
         Vector<int> satSystems(Satellite.size());
         //Check if we have a mixed system
         for ( i = 0; i < Satellite.size(); ++i)
         {
            satSystems[i] = ((Satellite[i].system == SatID::systemGlonass) ? (1) : (0) );

            if (satSystems[i] == 1) hasGlonass = true;
            else hasOther = true;
         }

         // Save the input solution
         // (for use in rejection when ResidualCriterion is false).
         if (!hasGlonass && Solution.size() != 4)
         {
            Solution.resize(4);
         }
         else if (hasGlonass && hasOther && Solution.size() != 5)
         {
            Solution.resize(5);
         }
         Solution = 0.0;

         // ----------------------------------------------------------------
         // fill the SVP matrix, and use it for every solution
         // NB this routine can set Satellite[.]=negative when no ephemeris

         i = PrepareAutonomousSolution(Tr, Satellite, Pseudorange, Eph, SVP,
             Debug?pDebugStream:0);
         if(Debug && pDebugStream) {
            *pDebugStream << "In RAIMCompute after PAS(): Satellites:";
            for(j=0; j<Satellite.size(); j++) {
               RinexSatID rs(::abs(Satellite[j].id), Satellite[j].system);
               *pDebugStream << " " << (Satellite[j].id < 0 ? "-":"") << rs;
            }
            *pDebugStream << endl;
            *pDebugStream << " SVP matrix("
               << SVP.rows() << "," << SVP.cols() << ")" << endl;
            *pDebugStream << fixed << setw(16) << setprecision(3) << SVP << endl;
         }
         if (i) return i;  // return is 0 (ok) or -4 (no ephemeris)
         
         // count how many good satellites we have
         // Initialize UseSat based on Satellite, and build GoodIndexes.
         // UseSat is used to mark good sats (true) and those to ignore (false).
         // UseSave saves the original so it can be reused for each solution.
         // Let GoodIndexes be all the indexes of Satellites that are good:
         // UseSat[GoodIndexes[.]] == true by definition

         for (N=0,i=0; i<Satellite.size(); i++)
         {
            if (Satellite[i].id > 0)
            {
               N++;
               UseSat.push_back(true);
               GoodIndexes.push_back(i);
            }
            else
            {
               UseSat.push_back(false);
            }
         }
         UseSave = UseSat;
         
         // don't even try if there are not 4 good satellites

         if (!hasGlonass && N < 4)
            return -3;
         else if (hasGlonass && hasOther && N < 5)
            return -3;

         // minimum number of sats needed for algorithm
         MinSV = 5;   // this would be RAIM
         // ( not really RAIM || not RAIM at all - just one solution)
         if (!ResidualCriterion || NSatsReject==0)
            MinSV=4;
         
         // how many satellites can RAIM reject, if we have to?
         // default is -1, meaning as many as possible
         Nreject = NSatsReject;
         if (Nreject == -1 || Nreject > N-MinSV)
            Nreject=N-MinSV;
            
         // ----------------------------------------------------------------
         // now compute the solution, first with all the data. If this fails,
         // reject 1 satellite at a time and try again, then 2, etc.
         
         // Slopes for each satellite are computed (cf. the RAIM algorithm)
         Vector<double> Slopes(Pseudorange.size());
         
         // Residuals stores the post-fit data residuals.
         Vector<double> Residuals(Satellite.size(),0.0);
         
         
         // compute all the Combinations of N satellites taken 4 at a time
         Combinations Combo(N,N-4);
         
         // compute a solution for each combination of marked satellites
         do{
            // Mark the satellites for this combination
            UseSat = UseSave;
            for (i = 0; i < GoodIndexes.size(); i++)
            {
               if (Combo.isSelected(i))
                  UseSat[i]=false;
            }
            // ----------------------------------------------------------------
            // Compute a solution given the data; ignore ranges for marked
            // satellites. Fill Vector 'Slopes' with slopes for each unmarked
            // satellite.
            // Return 0  ok
            //       -1  failed to converge
            //       -2  singular problem
            //       -3  not enough good data
            NIterations = MaxNIterations;             // pass limits in
            Convergence = ConvergenceLimit;
            iret = AutonomousPRSolution(Tr, UseSat, SVP, pTropModel, Algebraic,
               NIterations, Convergence, Solution, Covariance, Residuals, Slopes,
               pDebugStream, ((hasGlonass && hasOther)?(&satSystems):(NULL)) );
            
            // ----------------------------------------------------------------
            // Compute RMS residual...
               // and in the usual case
               RMSResidual = RMS(Residuals);
            // ... and find the maximum slope
            MaxSlope = 0.0;
            if (iret == 0)
            {
               for (i=0; i<UseSat.size(); i++)
               {
                  if (UseSat[i] && Slopes(i)>MaxSlope)
                     MaxSlope=Slopes[i];
               }
            }
            // ----------------------------------------------------------------
            // print solution with diagnostic information
            if (Debug && pDebugStream)
            {
               GPSWeekSecond weeksec(Tr);
               *pDebugStream << "RPS " << setw(2) << "4" 
                  << " " << setw(4) << weeksec.week
                  << " " << fixed << setw(10) << setprecision(3) << weeksec.sow
                  << " " << setw(2) << N-4 << setprecision(6)
                  << " " << setw(16) << Solution(0)
                  << " " << setw(16) << Solution(1)
                  << " " << setw(16) << Solution(2)
                  << " " << setw(14) << Solution(3);
               if (hasGlonass && hasOther)
                  *pDebugStream << " " << setw(16) << Solution(4);
               *pDebugStream << " " << setw(12) << RMSResidual
                  << " " << fixed << setw(5) << setprecision(1) << MaxSlope
                  << " " << NIterations
                  << " " << scientific << setw(8) << setprecision(2)<< Convergence;
                  // print the SatID for good sats
               for (i=0; i<UseSat.size(); i++)
               {
                  if (UseSat[i])
                     *pDebugStream << " " << setw(3)<< Satellite[i].id;
                  else
                     *pDebugStream << " " << setw(3) << -::abs(Satellite[i].id);
               }
                  // also print the return value
               *pDebugStream << " (" << iret << ")" << endl;
            }// end debug print
            
            // ----------------------------------------------------------------
            // deal with the results of AutonomousPRSolution()
            if (iret)
            {     // failure for this combination
               RMSResidual = 0.0;
               Solution = 0.0;
            }
            else
            {  // success
                  // save 'best' solution for later
               if (BestRMS < 0.0 || RMSResidual < BestRMS)
               {
                  BestRMS = RMSResidual;
                  BestSol = Solution;
                  BestUse = UseSat;
                  BestSL = MaxSlope;
                  BestConv = Convergence;
                  BestNIter = NIterations;
               }
	       // assign to the combo
	       ComboSolution.push_back(Solution);
	       ComboSolSat.push_back(UseSat);

                  // quit immediately?
               if ((ReturnAtOnce) && RMSResidual < RMSLimit)
                  break;
            }
            
            // get the next Combinations and repeat
         } while(Combo.Next() != -1);
         /*
         // end of the stage
         if (BestRMS > 0.0 && BestRMS < RMSLimit)
         {     // success
            iret=0;
         }
	 */
         
         // ----------------------------------------------------------------
         // copy out the best solution and return
         Convergence = BestConv;
         NIterations = BestNIter;
         RMSResidual = BestRMS;
         Solution = BestSol;
         MaxSlope = BestSL;
	 Covariance =BestCovariance;
         for (Nsvs=0,i=0; i<BestUse.size(); i++)
         {
            if (!BestUse[i])
               Satellite[i].id = -::abs(Satellite[i].id);
            else
               Nsvs++;
         }

         // FIXME should this be removed? I don't even know what slope is.
         if (iret==0 && BestSL > SlopeLimit)
            iret=1;
         if (iret==0 && BestSL > SlopeLimit/2.0 && Nsvs == 5)
            iret=1;
         if (iret>=0 && BestRMS >= RMSLimit)
            iret=2;
            
         if (iret==0)
            Valid=true;

         
         return iret;
      }
      catch(Exception& e)
      {
         GPSTK_RETHROW(e);
      }
   }  // end PRSolution2::RAIMCompute()
Esempio n. 5
0
static void
edge_sobel (GeglBuffer          *src,
            const GeglRectangle *src_rect,
            GeglBuffer          *dst,
            const GeglRectangle *dst_rect,
            gboolean            horizontal,
            gboolean            vertical,
            gboolean            keep_signal,
            gboolean            has_alpha)
{

  gint x,y;
  gint offset;
  gfloat *src_buf;
  gfloat *dst_buf;

  gint src_width = src_rect->width;

  src_buf = g_new0 (gfloat, src_rect->width * src_rect->height * 4);
  dst_buf = g_new0 (gfloat, dst_rect->width * dst_rect->height * 4);

  gegl_buffer_get (src, src_rect, 1.0, babl_format ("RGBA float"), src_buf, GEGL_AUTO_ROWSTRIDE,
                   GEGL_ABYSS_NONE);

  offset = 0;

  for (y=0; y<dst_rect->height; y++)
    for (x=0; x<dst_rect->width; x++)
      {

        gfloat hor_grad[3] = {0.0f, 0.0f, 0.0f};
        gfloat ver_grad[3] = {0.0f, 0.0f, 0.0f};
        gfloat gradient[4] = {0.0f, 0.0f, 0.0f, 0.0f};

        gfloat *center_pix = src_buf + ((x+SOBEL_RADIUS)+((y+SOBEL_RADIUS) * src_width)) * 4;

        gint c;

        if (horizontal)
          {
            gint i=x+SOBEL_RADIUS, j=y+SOBEL_RADIUS;
            gfloat *src_pix = src_buf + (i + j * src_width) * 4;

            for (c=0;c<3;c++)
                hor_grad[c] +=
                    -1.0f*src_pix[c-4-src_width*4]+ src_pix[c+4-src_width*4] +
                    -2.0f*src_pix[c-4] + 2.0f*src_pix[c+4] +
                    -1.0f*src_pix[c-4+src_width*4]+ src_pix[c+4+src_width*4];
          }

        if (vertical)
          {
            gint i=x+SOBEL_RADIUS, j=y+SOBEL_RADIUS;
            gfloat *src_pix = src_buf + (i + j * src_width) * 4;

            for (c=0;c<3;c++)
                ver_grad[c] +=
                  -1.0f*src_pix[c-4-src_width*4]-2.0f*src_pix[c-src_width*4]-1.0f*src_pix[c+4-src_width*4] +
                  src_pix[c-4+src_width*4]+2.0f*src_pix[c+src_width*4]+     src_pix[c+4+src_width*4];
        }

        if (horizontal && vertical)
          {
            for (c=0;c<3;c++)
              // normalization to [0, 1]
              gradient[c] = RMS(hor_grad[c],ver_grad[c])/1.41f;
          }
        else
          {
            if (keep_signal)
              {
                for (c=0;c<3;c++)
                  gradient[c] = hor_grad[c]+ver_grad[c];
              }
            else
              {
                for (c=0;c<3;c++)
                  gradient[c] = fabsf(hor_grad[c]+ver_grad[c]);
              }
          }

        if (has_alpha)
          gradient[3] = center_pix[3];
        else
          gradient[3] = 1.0f;


        for (c=0; c<4;c++)
          dst_buf[offset*4+c] = gradient[c];

        offset++;
      }

  gegl_buffer_set (dst, dst_rect, 0, babl_format ("RGBA float"), dst_buf,
                   GEGL_AUTO_ROWSTRIDE);
  g_free (src_buf);
  g_free (dst_buf);
}
Esempio n. 6
0
static void
sobel (GimpDrawable *drawable,
       gboolean      do_horizontal,
       gboolean      do_vertical,
       gboolean      keep_sign,
       GimpPreview  *preview)
{
  GimpPixelRgn  srcPR, destPR;
  gint          width, height;
  gint          bytes;
  gint          gradient, hor_gradient, ver_gradient;
  guchar       *dest, *d;
  guchar       *prev_row, *pr;
  guchar       *cur_row, *cr;
  guchar       *next_row, *nr;
  guchar       *tmp;
  gint          row, col;
  gint          x1, y1, x2, y2;
  gboolean      alpha;
  gint          counter;
  guchar       *preview_buffer = NULL;

  if (preview)
    {
      gimp_preview_get_position (preview, &x1, &y1);
      gimp_preview_get_size (preview, &width, &height);
      x2 = x1 + width;
      y2 = y1 + height;
    }
  else
    {
      gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2);
      gimp_progress_init (_("Sobel edge detecting"));
      width  = x2 - x1;
      height = y2 - y1;
    }

  /* Get the size of the input image. (This will/must be the same
   *  as the size of the output image.
   */
  bytes  = drawable->bpp;
  alpha  = gimp_drawable_has_alpha (drawable->drawable_id);

  /*  allocate row buffers  */
  prev_row = g_new (guchar, (width + 2) * bytes);
  cur_row  = g_new (guchar, (width + 2) * bytes);
  next_row = g_new (guchar, (width + 2) * bytes);
  dest     = g_new (guchar, width * bytes);

  /*  initialize the pixel regions  */
  gimp_pixel_rgn_init (&srcPR, drawable, 0, 0,
                       drawable->width, drawable->height,
                       FALSE, FALSE);

  if (preview)
    {
      preview_buffer = g_new (guchar, width * height * bytes);
    }
  else
    {
      gimp_pixel_rgn_init (&destPR, drawable, 0, 0,
                           drawable->width, drawable->height,
                           TRUE, TRUE);
    }

  pr = prev_row + bytes;
  cr = cur_row  + bytes;
  nr = next_row + bytes;

  sobel_prepare_row (&srcPR, pr, x1, y1 - 1, width);
  sobel_prepare_row (&srcPR, cr, x1, y1, width);
  counter =0;
  /*  loop through the rows, applying the sobel convolution  */
  for (row = y1; row < y2; row++)
    {
      /*  prepare the next row  */
      sobel_prepare_row (&srcPR, nr, x1, row + 1, width);

      d = dest;
      for (col = 0; col < width * bytes; col++)
        {
          hor_gradient = (do_horizontal ?
                          ((pr[col - bytes] +  2 * pr[col] + pr[col + bytes]) -
                           (nr[col - bytes] + 2 * nr[col] + nr[col + bytes]))
                          : 0);
          ver_gradient = (do_vertical ?
                          ((pr[col - bytes] + 2 * cr[col - bytes] + nr[col - bytes]) -
                           (pr[col + bytes] + 2 * cr[col + bytes] + nr[col + bytes]))
                          : 0);
          gradient = (do_vertical && do_horizontal) ?
            (ROUND (RMS (hor_gradient, ver_gradient)) / 5.66) /* always >0 */
            : (keep_sign ? (127 + (ROUND ((hor_gradient + ver_gradient) / 8.0)))
               : (ROUND (abs (hor_gradient + ver_gradient) / 4.0)));

          if (alpha && (((col + 1) % bytes) == 0))
            { /* the alpha channel */
              *d++ = (counter == 0) ? 0 : 255;
              counter = 0;
            }
          else
            {
              *d++ = gradient;
              if (gradient > 10) counter ++;
            }
        }
      /*  shuffle the row pointers  */
      tmp = pr;
      pr = cr;
      cr = nr;
      nr = tmp;

      /*  store the dest  */
      if (preview)
        {
          memcpy (preview_buffer + width * (row - y1) * bytes,
                  dest,
                  width * bytes);
        }
      else
        {
          gimp_pixel_rgn_set_row (&destPR, dest, x1, row, width);

          if ((row % 20) == 0)
            gimp_progress_update ((double) row / (double) (y2 - y1));
        }
    }

  if (preview)
    {
      gimp_preview_draw_buffer (preview, preview_buffer, width * bytes);
      g_free (preview_buffer);
    }
  else
    {
      gimp_progress_update (1.0);
      /*  update the sobeled region  */
      gimp_drawable_flush (drawable);
      gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
      gimp_drawable_update (drawable->drawable_id, x1, y1, width, height);
    }

  g_free (prev_row);
  g_free (cur_row);
  g_free (next_row);
  g_free (dest);
}
Esempio n. 7
0
static void
sobel (TileDrawable *drawable,
	   gint       do_horizontal,
	   gint       do_vertical,
	   gint       keep_sign)
{
  GPixelRgn srcPR, destPR;
  gint width, height;
  gint num_channels;

  guchar *dest;
  guchar *prev_row;
  guchar *cur_row;
  guchar *next_row;
  guchar *pr;
  guchar *cr;
  guchar *nr;
  guchar *tmp;

  gint row, col;
  gint x1, y1, x2, y2;
  gint alpha;
  gint counter;
  GPrecisionType precision = gimp_drawable_precision (drawable->id);

  /* Get the input area. This is the bounding box of the selection in
   *  the image (or the entire image if there is no selection). Only
   *  operating on the input area is simply an optimization. It doesn't
   *  need to be done for correct operation. (It simply makes it go
   *  faster, since fewer pixels need to be operated on).
   */

  gimp_drawable_mask_bounds (drawable->id, &x1, &y1, &x2, &y2);
  gimp_progress_init (_("Sobel Edge Detect"));

  /* Get the size of the input image. (This will/must be the same
   *  as the size of the output image.
   */
  width = drawable->width;
  height = drawable->height;
  num_channels = drawable->num_channels;
  alpha = gimp_drawable_has_alpha (drawable -> id);

  /*  allocate generic data row buffers  */
  prev_row = (guchar *) malloc ((x2 - x1 + 2) * drawable->bpp);
  cur_row = (guchar *) malloc ((x2 - x1 + 2) * drawable->bpp);
  next_row = (guchar *) malloc ((x2 - x1 + 2) * drawable->bpp);
  dest = (guchar *) malloc ((x2 - x1) * drawable->bpp);

  /*  initialize the pixel regions  */
  gimp_pixel_rgn_init (&srcPR, drawable, 0, 0, width, height, FALSE, FALSE);
  gimp_pixel_rgn_init (&destPR, drawable, 0, 0, width, height, TRUE, TRUE);

  /* generic data pointers to the three rows */ 
  pr = prev_row + drawable->bpp;
  cr = cur_row + drawable->bpp;
  nr = next_row + drawable->bpp;

  sobel_prepare_row (&srcPR, pr, x1, y1 - 1, (x2 - x1));
  sobel_prepare_row (&srcPR, cr, x1, y1, (x2 - x1));
  counter = 0;

  /*  loop through the rows, applying the sobel convolution  */
  for (row = y1; row < y2; row++)
    {
      /*  prepare the next row  */
      sobel_prepare_row (&srcPR, nr, x1, row + 1, (x2 - x1));

      switch(precision)
      {
	  case PRECISION_U8:
	    {
	      guint8* d = (guint8*)dest;
	      guint8* p = (guint8*)pr; 
	      guint8* c = (guint8*)cr;
	      guint8* n = (guint8*)nr;
  	      gint gradient, hor_gradient, ver_gradient;

	      for (col = 0; col < (x2 - x1) * num_channels; col++) {
		  if (do_horizontal)
		    hor_gradient = (p[col - num_channels] + 2 * p[col] + p[col + num_channels]) -
				   (n[col - num_channels] + 2 * n[col] + n[col + num_channels]);
		  else
		    hor_gradient = 0;

		  if (do_vertical)
		    ver_gradient = (p[col - num_channels] + 2 * c[col - num_channels] + n[col - num_channels]) -
				   (p[col + num_channels] + 2 * c[col + num_channels] + n[col + num_channels]);
		  else
		    ver_gradient = 0;

		  if (do_vertical && do_horizontal)
		      gradient = ROUND_TO_INT (RMS (hor_gradient, ver_gradient)) / 5.66;
		  else
		    {
		       if (keep_sign)
			 gradient = 127 + (ROUND_TO_INT ((hor_gradient + ver_gradient) / 8.0));
		       else
			 gradient =  ROUND_TO_INT (abs (hor_gradient + ver_gradient) / 4.0);
		    }

		  if (alpha && (((col + 1) % num_channels) == 0))  
		  { 
		    *d++ = (counter == 0) ? 0 : 255;
		    counter = 0; 
		  }
		  else 
		  {
		    *d++ = gradient;
		    if (gradient > 10) counter ++;
		  }
	       }
	     }
	    break;
	  case PRECISION_U16:
	    {
	      guint16* d = (guint16*)dest;
	      guint16* p = (guint16*)pr; 
	      guint16* c = (guint16*)cr;
	      guint16* n = (guint16*)nr;
  	      gint gradient, hor_gradient, ver_gradient;

	      for (col = 0; col < (x2 - x1) * num_channels; col++) {
		  if (do_horizontal)
		    hor_gradient = (p[col - num_channels] + 2 * p[col] + p[col + num_channels]) -
				   (n[col - num_channels] + 2 * n[col] + n[col + num_channels]);
		  else
		    hor_gradient = 0;

		  if (do_vertical)
		    ver_gradient = (p[col - num_channels] + 2 * c[col - num_channels] + n[col - num_channels]) -
				   (p[col + num_channels] + 2 * c[col + num_channels] + n[col + num_channels]);
		  else
		    ver_gradient = 0;

		  if (do_vertical && do_horizontal)
		      gradient = ROUND_TO_INT (RMS (hor_gradient, ver_gradient)) / 5.66;
		  else
		    {
		       if (keep_sign)
			 gradient = 32767 + (ROUND_TO_INT ((hor_gradient + ver_gradient) / 8.0));
		       else
			 gradient =  ROUND_TO_INT (abs (hor_gradient + ver_gradient) / 4.0);
		    }

		  if (alpha && (((col + 1) % num_channels) == 0))  
		  { 
		    *d++ = (counter == 0) ? 0 : 65535;
		    counter = 0; 
		  }
		  else 
		  {
		    *d++ = gradient;
		    if (gradient > (10/255.0) * 65535) counter ++;
		  }
	       }
	     }
	    break;
	  case PRECISION_FLOAT:
	    {
	      gfloat* d = (gfloat*)dest;
	      gfloat* p = (gfloat*)pr; 
	      gfloat* c = (gfloat*)cr;
	      gfloat* n = (gfloat*)nr;
  	      gfloat gradient, hor_gradient, ver_gradient;

	      for (col = 0; col < (x2 - x1) * num_channels; col++) {
		  if (do_horizontal)
		    hor_gradient = (p[col - num_channels] + 2 * p[col] + p[col + num_channels]) -
				   (n[col - num_channels] + 2 * n[col] + n[col + num_channels]);
		  else
		    hor_gradient = 0;

		  if (do_vertical)
		    ver_gradient = (p[col - num_channels] + 2 * c[col - num_channels] + n[col - num_channels]) -
				   (p[col + num_channels] + 2 * c[col + num_channels] + n[col + num_channels]);
		  else
		    ver_gradient = 0;

		  if (do_vertical && do_horizontal)
		      gradient = (RMS (hor_gradient, ver_gradient)) / 5.66;
		  else
		    {
		       if (keep_sign)
			 gradient = .5 + (hor_gradient + ver_gradient) / 8.0;
		       else
			 gradient =  abs (hor_gradient + ver_gradient) / 4.0;
		    }

		  if (alpha && (((col + 1) % num_channels) == 0))  
		  { 
		    *d++ = (counter == 0) ? 0.0 : 1.0;
		    counter = 0; 
		  }
		  else 
		  {
		    *d++ = gradient;
		    if (gradient > (10/255.0)) counter ++;
		  }
	       }
	     }
	    break;
	  case PRECISION_FLOAT16: 
	    {
	      guint16* d = (guint16*)dest;
	      guint16* p = (guint16*)pr; 
	      guint16* c = (guint16*)cr;
	      guint16* n = (guint16*)nr;
  	      gfloat gradient, hor_gradient, ver_gradient;
	      ShortsFloat u,v,s, u1, v1, s1;

	      for (col = 0; col < (x2 - x1) * num_channels; col++) {
		  if (do_horizontal)
		    hor_gradient = (
				      FLT(p[col - num_channels],u) +     
				      2 * FLT(p[col], v) +             
				      FLT(p[col + num_channels], s)          
								) -
				    (
				      FLT(n[col - num_channels],u1) + 
				      2 * FLT(n[col], v1) 
				      + FLT(n[col + num_channels], s1)
								   );
		  else
		    hor_gradient = 0;

		  if (do_vertical)
		    ver_gradient = (
				     FLT(p[col - num_channels], u) + 
				     2 * FLT (c[col - num_channels],v) + 
				     FLT(n[col - num_channels],s)
								) -
				   (
				     FLT(p[col + num_channels], u1) + 
				     2 * FLT (c[col + num_channels],v1) + 
				     FLT(n[col + num_channels], s1)
								);
		  else
		    ver_gradient = 0;

		  if (do_vertical && do_horizontal)
		      gradient = (RMS (hor_gradient, ver_gradient)) / 5.66;
		  else
		    {
		       if (keep_sign)
			 gradient = .5 + (hor_gradient + ver_gradient) / 8.0;
		       else
			 gradient =  abs (hor_gradient + ver_gradient) / 4.0;
		    }

		  if (alpha && (((col + 1) % num_channels) == 0))  
		  { 
		    *d++ = (counter == 0) ? 0.0 : 1.0;
		    counter = 0; 
		  }
		  else 
		  {
		    *d++ = FLT16(gradient, u);
		    if (gradient > (10/255.0)) counter ++;
		  }
	       }
	     }
	    break;
      }

      /*  store the dest  */
      gimp_pixel_rgn_set_row (&destPR, dest, x1, row, (x2 - x1));

      /*  shuffle the row pointers  */
      tmp = pr;
      pr = cr;
      cr = nr;
      nr = tmp;

      if ((row % 5) == 0)
	gimp_progress_update ((double) row / (double) (y2 - y1));
    }

  /*  update the sobeled region  */
  gimp_drawable_flush (drawable);
  gimp_drawable_merge_shadow (drawable->id, TRUE);
  gimp_drawable_update (drawable->id, x1, y1, (x2 - x1), (y2 - y1));

  free (prev_row);
  free (cur_row);
  free (next_row);
  free (dest);
}
void KisSobelFilter::process(KisPaintDeviceSP device,
                            const QRect& applyRect,
                            const KisFilterConfiguration* configuration,
                            KoUpdater* progressUpdater
                            ) const
{
    QPoint srcTopLeft = applyRect.topLeft();
    Q_ASSERT(!device.isNull());

    //read the filter configuration values from the KisFilterConfiguration object
    bool doHorizontal = configuration->getBool("doHorizontally", true);
    bool doVertical = configuration->getBool("doVertically", true);
    bool keepSign = configuration->getBool("keepSign", true);
    bool makeOpaque = configuration->getBool("makeOpaque", true);

    quint32 width = applyRect.width();
    quint32 height = applyRect.height();
    quint32 pixelSize = device->pixelSize();

    int cost = applyRect.height();

    /*  allocate row buffers  */
    quint8* prevRow = new quint8[(width + 2) * pixelSize];
    Q_CHECK_PTR(prevRow);
    quint8* curRow = new quint8[(width + 2) * pixelSize];
    Q_CHECK_PTR(curRow);
    quint8* nextRow = new quint8[(width + 2) * pixelSize];
    Q_CHECK_PTR(nextRow);
    quint8* dest = new quint8[ width  * pixelSize];
    Q_CHECK_PTR(dest);

    quint8* pr = prevRow + pixelSize;
    quint8* cr = curRow + pixelSize;
    quint8* nr = nextRow + pixelSize;

    prepareRow(device, pr, srcTopLeft.x(), srcTopLeft.y() - 1, width, height);
    prepareRow(device, cr, srcTopLeft.x(), srcTopLeft.y(), width, height);

    quint32 counter = 0;
    quint8* d;
    quint8* tmp;
    qint32 gradient, horGradient, verGradient;
    // loop through the rows, applying the sobel convolution

    KisHLineIteratorSP dstIt = device->createHLineIteratorNG(srcTopLeft.x(), srcTopLeft.y(), width);

    for (quint32 row = 0; row < height; row++) {

        // prepare the next row
        prepareRow(device, nr, srcTopLeft.x(), srcTopLeft.y() + row + 1, width, height);
        d = dest;

        for (quint32 col = 0; col < width * pixelSize; col++) {
            int positive = col + pixelSize;
            int negative = col - pixelSize;
            horGradient = (doHorizontal ?
                           ((pr[negative] +  2 * pr[col] + pr[positive]) -
                            (nr[negative] + 2 * nr[col] + nr[positive]))
                           : 0);

            verGradient = (doVertical ?
                           ((pr[negative] + 2 * cr[negative] + nr[negative]) -
                            (pr[positive] + 2 * cr[positive] + nr[positive]))
                           : 0);
            gradient = (qint32)((doVertical && doHorizontal) ?
                                (ROUND(RMS(horGradient, verGradient)) / 5.66)   // always >0
                                : (keepSign ? (127 + (ROUND((horGradient + verGradient) / 8.0)))
                                   : (ROUND(qAbs(horGradient + verGradient) / 4.0))));

            *d++ = gradient;
            if (gradient > 10) counter ++;
        }

        //  shuffle the row pointers
        tmp = pr;
        pr = cr;
        cr = nr;
        nr = tmp;

        //store the dest
        device->writeBytes(dest, srcTopLeft.x(), row, width, 1);

        if (makeOpaque) {
            do {
                device->colorSpace()->setOpacity(dstIt->rawData(), OPACITY_OPAQUE_U8, 1);
            } while(dstIt->nextPixel());
            dstIt->nextRow();
        }
        if (progressUpdater) progressUpdater->setProgress(row / cost);
    }

    delete[] prevRow;
    delete[] curRow;
    delete[] nextRow;
    delete[] dest;
}