Program: 26223
Project: 26223
Buggy source:
/** 
 * Method to update a current output (multi-thread).
 * @param c B-spline coefficients
 * @param intervals number of intervals in the deformation
 * @param bIsReverse flag to decide the deformation direction (source-target, target-source)
 */
private void update_current_output(final double[] c,int intervals,boolean bIsReverse){
  int cYdim=intervals + 3;
  int cXdim=cYdim;
  int Nk=cYdim * cXdim;
  BSplineModel auxTarget=target;
  BSplineModel auxSource=source;
  Mask auxTargetMsk=targetMsk;
  Mask auxSourceMsk=sourceMsk;
  BSplineModel swx=swxTargetToSource;
  BSplineModel swy=swyTargetToSource;
  int auxTargetWidth=this.targetWidth;
  int auxTargetHeight=this.targetHeight;
  int auxTargetCurrentWidth=this.targetCurrentWidth;
  int auxTargetCurrentHeight=this.targetCurrentHeight;
  int auxSourceWidth=this.sourceWidth;
  int auxSourceHeight=this.sourceHeight;
  ImagePlus auxSourceImp=this.sourceImp;
  ImagePlus output_ip=this.output_ip_1;
  double auxFactorWidth=this.targetFactorWidth;
  double auxFactorHeight=this.targetFactorHeight;
  double subFactorWidth=target.isSubOutput() ? (target.getWidth() / target.getSubWidth()) : 1;
  double subFactorHeight=target.isSubOutput() ? (target.getHeight() / target.getSubHeight()) : 1;
  if (bIsReverse) {
    auxTarget=source;
    auxSource=target;
    auxTargetMsk=sourceMsk;
    auxSourceMsk=targetMsk;
    swx=swxSourceToTarget;
    swy=swySourceToTarget;
    auxTargetWidth=this.sourceWidth;
    auxTargetHeight=this.sourceHeight;
    auxTargetCurrentWidth=sourceCurrentWidth;
    auxTargetCurrentHeight=sourceCurrentHeight;
    auxSourceWidth=this.targetWidth;
    auxSourceHeight=this.targetHeight;
    auxSourceImp=this.targetImp;
    output_ip=this.output_ip_2;
    auxFactorWidth=this.sourceFactorWidth;
    auxFactorHeight=this.sourceFactorHeight;
    subFactorWidth=source.isSubOutput() ? (source.getWidth() / source.getSubWidth()) : 1;
    subFactorHeight=source.isSubOutput() ? (source.getHeight() / source.getSubHeight()) : 1;
  }
  swx.setCoefficients(c,cYdim,cXdim,0);
  swy.setCoefficients(c,cYdim,cXdim,Nk);
  FloatProcessor fp=(FloatProcessor)output_ip.getProcessor();
  int uv=0;
  int nproc=Runtime.getRuntime().availableProcessors();
  int block_height=auxTargetHeight / ((int)subFactorHeight * nproc);
  if (auxTargetHeight % 2 != 0)   block_height++;
  int nThreads=nproc;
  Thread[] threads=new Thread[nThreads];
  Rectangle[] rects=new Rectangle[nThreads];
  FloatProcessor[] fp_tile=new FloatProcessor[nThreads];
  for (int i=0; i < nThreads; i++) {
    int x_start=i * block_height;
    if (nThreads - 1 == i)     block_height=auxTargetHeight / (int)subFactorWidth - i * block_height;
    rects[i]=new Rectangle(0,x_start,auxTargetWidth / (int)subFactorWidth,block_height);
    fp_tile[i]=new FloatProcessor(rects[i].width,rects[i].height);
    threads[i]=new Thread(new OutputTileMaker(swx,swy,auxSource,auxTarget,auxSourceMsk,auxTargetMsk,auxFactorWidth * subFactorWidth,auxFactorHeight * subFactorHeight,auxTargetCurrentHeight,auxTargetCurrentWidth,rects[i],fp_tile[i]));
    threads[i].start();
  }
  for (int i=0; i < nThreads; i++) {
    try {
      threads[i].join();
      threads[i]=null;
    }
 catch (    InterruptedException e) {
      e.printStackTrace();
    }
  }
  for (int i=0; i < nThreads; i++) {
    fp.insert(fp_tile[i],rects[i].x,rects[i].y);
    fp_tile[i]=null;
    rects[i]=null;
  }
  double min_val=output_ip.getProcessor().getMin();
  double max_val=output_ip.getProcessor().getMax();
  fp.setMinAndMax(min_val,max_val);
  output_ip.updateAndDraw();
  auxTargetHeight=bIsReverse ? this.originalSourceIP.getHeight() : this.originalTargetIP.getHeight();
  auxTargetWidth=bIsReverse ? this.originalSourceIP.getWidth() : this.originalTargetIP.getWidth();
  auxSourceHeight=bIsReverse ? this.originalTargetIP.getHeight() : this.originalSourceIP.getHeight();
  auxSourceWidth=bIsReverse ? this.originalTargetIP.getWidth() : this.originalSourceIP.getWidth();
  auxFactorWidth=(double)auxTargetCurrentWidth / auxTargetWidth;
  auxFactorHeight=(double)auxTargetCurrentHeight / auxTargetHeight;
  int stepv=Math.min(Math.max(10,auxTargetHeight / 15),60);
  int stepu=Math.min(Math.max(10,auxTargetWidth / 15),60);
  final double transformedImage[][]=new double[auxSourceHeight][auxSourceWidth];
  double grid_colour=-1e-10;
  uv=0;
  for (int v=0; v < auxSourceHeight; v++)   for (int u=0; u < auxSourceWidth; u++, uv++) {
    transformedImage[v][u]=auxSource.getOriginalImage()[uv];
    if (transformedImage[v][u] > grid_colour)     grid_colour=transformedImage[v][u];
  }
  for (int v=0; v < auxTargetHeight + stepv; v+=stepv)   for (int u=0; u < auxTargetWidth + stepu; u+=stepu) {
    double down_u=u * auxFactorWidth;
    double down_v=v * auxFactorHeight;
    final double tv=(double)(down_v * intervals) / (double)(auxTargetCurrentHeight - 1) + 1.0F;
    final double tu=(double)(down_u * intervals) / (double)(auxTargetCurrentWidth - 1) + 1.0F;
    swx.prepareForInterpolation(tu,tv,ORIGINAL);
    double x=swx.interpolateI();
    swy.prepareForInterpolation(tu,tv,ORIGINAL);
    double y=swy.interpolateI();
    double up_x=x / auxFactorWidth;
    double up_y=y / auxFactorHeight;
    int uh=u + stepu;
    if (uh < auxTargetWidth + stepu) {
      final double down_uh=uh * auxFactorWidth;
      final double tuh=(double)(down_uh * intervals) / (double)(auxTargetCurrentWidth - 1) + 1.0F;
      swx.prepareForInterpolation(tuh,tv,ORIGINAL);
      final double xh=swx.interpolateI();
      swy.prepareForInterpolation(tuh,tv,ORIGINAL);
      final double yh=swy.interpolateI();
      final double up_xh=xh / auxFactorWidth;
      final double up_yh=yh / auxFactorHeight;
      MiscTools.drawLine(transformedImage,(int)Math.round(up_x),(int)Math.round(up_y),(int)Math.round(up_xh),(int)Math.round(up_yh),grid_colour);
    }
    int vv=v + stepv;
    if (vv < auxTargetHeight + stepv) {
      double down_vv=vv * auxFactorHeight;
      final double tvv=(double)(down_vv * intervals) / (double)(auxTargetCurrentHeight - 1) + 1.0F;
      swx.prepareForInterpolation(tu,tvv,ORIGINAL);
      double xv=swx.interpolateI();
      swy.prepareForInterpolation(tu,tvv,ORIGINAL);
      double yv=swy.interpolateI();
      double up_xv=xv / auxFactorWidth;
      double up_yv=yv / auxFactorHeight;
      MiscTools.drawLine(transformedImage,(int)Math.round(up_x),(int)Math.round(up_y),(int)Math.round(up_xv),(int)Math.round(up_yv),grid_colour);
    }
  }
  FloatProcessor fpg=new FloatProcessor(auxSourceWidth,auxSourceHeight);
  for (int v=0; v < auxSourceHeight; v++)   for (int u=0; u < auxSourceWidth; u++)   fpg.setf(u,v,(float)transformedImage[v][u]);
  min_val=auxSourceImp.getProcessor().getMin();
  max_val=auxSourceImp.getProcessor().getMax();
  fpg.setMinAndMax(min_val,max_val);
  if (auxSourceImp.getImageStackSize() < 2)   auxSourceImp.setProcessor(auxSourceImp.getTitle(),fpg);
 else {
    final ImageProcessor ipToDisplay;
    if (auxSourceImp.getProcessor() instanceof ByteProcessor)     ipToDisplay=fpg.convertToByte(false);
 else     if (auxSourceImp.getProcessor() instanceof ShortProcessor)     ipToDisplay=fpg.convertToShort(false);
 else     ipToDisplay=fpg;
    auxSourceImp.setProcessor(auxSourceImp.getTitle(),ipToDisplay);
  }
  auxSourceImp.updateImage();
}

Fixed version (ground truth):
/** 
 * Method to update a current output (multi-thread).
 * @param c B-spline coefficients
 * @param intervals number of intervals in the deformation
 * @param bIsReverse flag to decide the deformation direction (source-target, target-source)
 */
private void update_current_output(final double[] c,int intervals,boolean bIsReverse){
  int cYdim=intervals + 3;
  int cXdim=cYdim;
  int Nk=cYdim * cXdim;
  BSplineModel auxTarget=target;
  BSplineModel auxSource=source;
  Mask auxTargetMsk=targetMsk;
  Mask auxSourceMsk=sourceMsk;
  BSplineModel swx=swxTargetToSource;
  BSplineModel swy=swyTargetToSource;
  int auxTargetWidth=this.targetWidth;
  int auxTargetHeight=this.targetHeight;
  int auxTargetCurrentWidth=this.targetCurrentWidth;
  int auxTargetCurrentHeight=this.targetCurrentHeight;
  int auxSourceWidth=this.sourceWidth;
  int auxSourceHeight=this.sourceHeight;
  ImagePlus auxSourceImp=this.sourceImp;
  ImagePlus output_ip=this.output_ip_1;
  double auxFactorWidth=this.targetFactorWidth;
  double auxFactorHeight=this.targetFactorHeight;
  double subFactorWidth=target.isSubOutput() ? (target.getWidth() / target.getSubWidth()) : 1;
  double subFactorHeight=target.isSubOutput() ? (target.getHeight() / target.getSubHeight()) : 1;
  if (bIsReverse) {
    auxTarget=source;
    auxSource=target;
    auxTargetMsk=sourceMsk;
    auxSourceMsk=targetMsk;
    swx=swxSourceToTarget;
    swy=swySourceToTarget;
    auxTargetWidth=this.sourceWidth;
    auxTargetHeight=this.sourceHeight;
    auxTargetCurrentWidth=sourceCurrentWidth;
    auxTargetCurrentHeight=sourceCurrentHeight;
    auxSourceWidth=this.targetWidth;
    auxSourceHeight=this.targetHeight;
    auxSourceImp=this.targetImp;
    output_ip=this.output_ip_2;
    auxFactorWidth=this.sourceFactorWidth;
    auxFactorHeight=this.sourceFactorHeight;
    subFactorWidth=source.isSubOutput() ? (source.getWidth() / source.getSubWidth()) : 1;
    subFactorHeight=source.isSubOutput() ? (source.getHeight() / source.getSubHeight()) : 1;
  }
  swx.setCoefficients(c,cYdim,cXdim,0);
  swy.setCoefficients(c,cYdim,cXdim,Nk);
  FloatProcessor fp=(FloatProcessor)output_ip.getProcessor();
  int uv=0;
  int nproc=Runtime.getRuntime().availableProcessors();
  int block_height=auxTargetHeight / ((int)subFactorHeight * nproc);
  int nThreads=nproc;
  Thread[] threads=new Thread[nThreads];
  Rectangle[] rects=new Rectangle[nThreads];
  FloatProcessor[] fp_tile=new FloatProcessor[nThreads];
  for (int i=0; i < nThreads; i++) {
    int x_start=i * block_height;
    if (nThreads - 1 == i)     block_height=auxTargetHeight / (int)subFactorWidth - i * block_height;
    rects[i]=new Rectangle(0,x_start,auxTargetWidth / (int)subFactorWidth,block_height);
    fp_tile[i]=new FloatProcessor(rects[i].width,rects[i].height);
    threads[i]=new Thread(new OutputTileMaker(swx,swy,auxSource,auxTarget,auxSourceMsk,auxTargetMsk,auxFactorWidth * subFactorWidth,auxFactorHeight * subFactorHeight,auxTargetCurrentHeight,auxTargetCurrentWidth,rects[i],fp_tile[i]));
    threads[i].start();
  }
  for (int i=0; i < nThreads; i++) {
    try {
      threads[i].join();
      threads[i]=null;
    }
 catch (    InterruptedException e) {
      e.printStackTrace();
    }
  }
  for (int i=0; i < nThreads; i++) {
    fp.insert(fp_tile[i],rects[i].x,rects[i].y);
    fp_tile[i]=null;
    rects[i]=null;
  }
  double min_val=output_ip.getProcessor().getMin();
  double max_val=output_ip.getProcessor().getMax();
  fp.setMinAndMax(min_val,max_val);
  output_ip.updateAndDraw();
  auxTargetHeight=bIsReverse ? this.originalSourceIP.getHeight() : this.originalTargetIP.getHeight();
  auxTargetWidth=bIsReverse ? this.originalSourceIP.getWidth() : this.originalTargetIP.getWidth();
  auxSourceHeight=bIsReverse ? this.originalTargetIP.getHeight() : this.originalSourceIP.getHeight();
  auxSourceWidth=bIsReverse ? this.originalTargetIP.getWidth() : this.originalSourceIP.getWidth();
  auxFactorWidth=(double)auxTargetCurrentWidth / auxTargetWidth;
  auxFactorHeight=(double)auxTargetCurrentHeight / auxTargetHeight;
  int stepv=Math.min(Math.max(10,auxTargetHeight / 15),60);
  int stepu=Math.min(Math.max(10,auxTargetWidth / 15),60);
  final double transformedImage[][]=new double[auxSourceHeight][auxSourceWidth];
  double grid_colour=-1e-10;
  uv=0;
  for (int v=0; v < auxSourceHeight; v++)   for (int u=0; u < auxSourceWidth; u++, uv++) {
    transformedImage[v][u]=auxSource.getOriginalImage()[uv];
    if (transformedImage[v][u] > grid_colour)     grid_colour=transformedImage[v][u];
  }
  for (int v=0; v < auxTargetHeight + stepv; v+=stepv)   for (int u=0; u < auxTargetWidth + stepu; u+=stepu) {
    double down_u=u * auxFactorWidth;
    double down_v=v * auxFactorHeight;
    final double tv=(double)(down_v * intervals) / (double)(auxTargetCurrentHeight - 1) + 1.0F;
    final double tu=(double)(down_u * intervals) / (double)(auxTargetCurrentWidth - 1) + 1.0F;
    swx.prepareForInterpolation(tu,tv,ORIGINAL);
    double x=swx.interpolateI();
    swy.prepareForInterpolation(tu,tv,ORIGINAL);
    double y=swy.interpolateI();
    double up_x=x / auxFactorWidth;
    double up_y=y / auxFactorHeight;
    int uh=u + stepu;
    if (uh < auxTargetWidth + stepu) {
      final double down_uh=uh * auxFactorWidth;
      final double tuh=(double)(down_uh * intervals) / (double)(auxTargetCurrentWidth - 1) + 1.0F;
      swx.prepareForInterpolation(tuh,tv,ORIGINAL);
      final double xh=swx.interpolateI();
      swy.prepareForInterpolation(tuh,tv,ORIGINAL);
      final double yh=swy.interpolateI();
      final double up_xh=xh / auxFactorWidth;
      final double up_yh=yh / auxFactorHeight;
      MiscTools.drawLine(transformedImage,(int)Math.round(up_x),(int)Math.round(up_y),(int)Math.round(up_xh),(int)Math.round(up_yh),grid_colour);
    }
    int vv=v + stepv;
    if (vv < auxTargetHeight + stepv) {
      double down_vv=vv * auxFactorHeight;
      final double tvv=(double)(down_vv * intervals) / (double)(auxTargetCurrentHeight - 1) + 1.0F;
      swx.prepareForInterpolation(tu,tvv,ORIGINAL);
      double xv=swx.interpolateI();
      swy.prepareForInterpolation(tu,tvv,ORIGINAL);
      double yv=swy.interpolateI();
      double up_xv=xv / auxFactorWidth;
      double up_yv=yv / auxFactorHeight;
      MiscTools.drawLine(transformedImage,(int)Math.round(up_x),(int)Math.round(up_y),(int)Math.round(up_xv),(int)Math.round(up_yv),grid_colour);
    }
  }
  FloatProcessor fpg=new FloatProcessor(auxSourceWidth,auxSourceHeight);
  for (int v=0; v < auxSourceHeight; v++)   for (int u=0; u < auxSourceWidth; u++)   fpg.setf(u,v,(float)transformedImage[v][u]);
  min_val=auxSourceImp.getProcessor().getMin();
  max_val=auxSourceImp.getProcessor().getMax();
  fpg.setMinAndMax(min_val,max_val);
  if (auxSourceImp.getImageStackSize() < 2)   auxSourceImp.setProcessor(auxSourceImp.getTitle(),fpg);
 else {
    final ImageProcessor ipToDisplay;
    if (auxSourceImp.getProcessor() instanceof ByteProcessor)     ipToDisplay=fpg.convertToByte(false);
 else     if (auxSourceImp.getProcessor() instanceof ShortProcessor)     ipToDisplay=fpg.convertToShort(false);
 else     ipToDisplay=fpg;
    auxSourceImp.setProcessor(auxSourceImp.getTitle(),ipToDisplay);
  }
  auxSourceImp.updateImage();
}