/**
 SamplesToCoefficients.<br>
 Implement the algorithm that converts the image samples into B-spline coefficients. 
 This efficient procedure essentially relies on the three papers cited above; 
 data are processed in-place. 
 Even though this algorithm is robust with respect to quantization, 
 we advocate the use of a floating-point format for the data. 

 @param Image Input / Output image (in-place processing)
 @param Width Width of the image
 @param Height Height of the image
 @param spline_degree Degree of the spline model
 @return Returns true if success, false otherwise
*/
static bool	
SamplesToCoefficients(double *Image, long Width, long Height, long spline_degree) {
	double	*Line;
	double	Pole[2];
	long	NbPoles;
	long	x, y;

	// recover the poles from a lookup table
	switch (spline_degree) {
		case 2L:
			NbPoles = 1L;
			Pole[0] = sqrt(8.0) - 3.0;
			break;
		case 3L:
			NbPoles = 1L;
			Pole[0] = sqrt(3.0) - 2.0;
			break;
		case 4L:
			NbPoles = 2L;
			Pole[0] = sqrt(664.0 - sqrt(438976.0)) + sqrt(304.0) - 19.0;
			Pole[1] = sqrt(664.0 + sqrt(438976.0)) - sqrt(304.0) - 19.0;
			break;
		case 5L:
			NbPoles = 2L;
			Pole[0] = sqrt(135.0 / 2.0 - sqrt(17745.0 / 4.0)) + sqrt(105.0 / 4.0)
				- 13.0 / 2.0;
			Pole[1] = sqrt(135.0 / 2.0 + sqrt(17745.0 / 4.0)) - sqrt(105.0 / 4.0)
				- 13.0 / 2.0;
			break;
		default:
			// Invalid spline degree
			return false;
	}

	// convert the image samples into interpolation coefficients 

	// in-place separable process, along x 
	Line = (double *)malloc(Width * sizeof(double));
	if (Line == NULL) {
		// Row allocation failed
		return false;
	}
	for (y = 0L; y < Height; y++) {
		GetRow(Image, y, Line, Width);
		ConvertToInterpolationCoefficients(Line, Width, Pole, NbPoles, DBL_EPSILON);
		PutRow(Image, y, Line, Width);
	}
	free(Line);

	// in-place separable process, along y 
	Line = (double *)malloc(Height * sizeof(double));
	if (Line == NULL) {
		// Column allocation failed
		return false;
	}
	for (x = 0L; x < Width; x++) {
		GetColumn(Image, Width, x, Line, Height);
		ConvertToInterpolationCoefficients(Line, Height, Pole, NbPoles, DBL_EPSILON);
		PutColumn(Image, Width, x, Line, Height);
	}
	free(Line);

	return true;
}
/*--------------------------------------------------------------------------*/
int  SamplesToCoefficients
(
  MRI *mri_vol,  /* in-place processing */
  long SplineDegree /* degree of the spline model */
)

{ /* begin SamplesToCoefficients */

  double  *Line;
  double  Pole[2];
  long NbPoles;
  long x, y, z;
  long Width, Height, Depth;

  /* recover the poles from a lookup table */
  switch (SplineDegree)
  {
  case 2L:
    NbPoles = 1L;
    Pole[0] = sqrt(8.0) - 3.0;
    break;
  case 3L:
    NbPoles = 1L;
    Pole[0] = sqrt(3.0) - 2.0;
    break;
  case 4L:
    NbPoles = 2L;
    Pole[0] = sqrt(664.0 - sqrt(438976.0)) + sqrt(304.0) - 19.0;
    Pole[1] = sqrt(664.0 + sqrt(438976.0)) - sqrt(304.0) - 19.0;
    break;
  case 5L:
    NbPoles = 2L;
    Pole[0] = sqrt(135.0 / 2.0 - sqrt(17745.0 / 4.0)) + sqrt(105.0 / 4.0)
              - 13.0 / 2.0;
    Pole[1] = sqrt(135.0 / 2.0 + sqrt(17745.0 / 4.0)) - sqrt(105.0 / 4.0)
              - 13.0 / 2.0;
    break;
  default:
    printf("Invalid spline degree\n");
    return(1);
  }

  Width = mri_vol->width;
  Height = mri_vol->height;
  Depth = mri_vol->depth;

  /* convert the image samples into interpolation coefficients */
  /* in-place separable process, along x */
  Line = (double *)malloc((size_t)(Width * (long)sizeof(double)));
  if (Line == (double *)NULL)
  {
    printf("Row allocation failed\n");
    return(1);
  }

  for (z = 0L; z < Depth; z++)
  {
    for (y = 0L; y < Height; y++)
    {
      GetRow(mri_vol, y, z, Line);
      ConvertToInterpolationCoefficients(Line, Width, Pole, NbPoles, DBL_EPSILON);
      PutRow(mri_vol, y, z, Line);

    }
  }
  free(Line);

  /* in-place separable process, along y */
  Line = (double *)malloc((size_t)(Height * (long)sizeof(double)));
  if (Line == (double *)NULL)
  {
    printf("Column allocation failed\n");
    return(1);
  }
  for (z = 0L; z < Depth; z++)
  {
    for (x = 0L; x < Width; x++)
    {
      GetColumn(mri_vol,  x, z, Line);
      ConvertToInterpolationCoefficients(Line, Height, Pole, NbPoles, DBL_EPSILON);
      PutColumn(mri_vol, x, z, Line);
    }
  }
  free(Line);

  /* in-place separable process, along z */
  Line = (double *)malloc((size_t)(Depth * (long)sizeof(double)));
  if (Line == (double *)NULL)
  {
    printf("Column allocation failed\n");
    return(1);
  }
  for (y = 0L; y < Height; y++)
  {
    for (x = 0L; x < Width; x++)
    {
      GetVertical(mri_vol, x, y, Line);
      ConvertToInterpolationCoefficients(Line, Depth, Pole, NbPoles, DBL_EPSILON);
      PutVertical(mri_vol, x, y, Line);
    }
  }
  free(Line);

  return(0);
} /* end SamplesToCoefficients */