medialib_get_interpolation (mlInterp * ml_interp,
                            PixopsInterpType interp_type,
                            double scale_x,
                            double scale_y,
                            double overall_alpha)
{
  mlib_s32 leftPadding, topPadding;
  ml_interp->interp_table = NULL;

 /*
  * medialib 2.1 and later supports scaling with user-defined interpolation
  * tables, so this logic is used.  
  *
  * bilinear_magnify_make_weights builds an interpolation table of size 2x2 if
  * the scale factor >= 1.0 and "ceil (1.0 + 1.0/scale)" otherwise.  These map
  * most closely to MLIB_BILINEAR, which uses an interpolation table of size
  * 2x2.
  *
  * tile_make_weights builds an interpolation table of size 2x2 if the scale
  * factor >= 1.0 and "ceil (1.0 + 1.0/scale)" otherwise.  These map most
  * closely to MLIB_BILINEAR, which uses an interpolation table of size 2x2.
  *
  * bilinear_box_make_weights builds an interpolation table of size 4x4 if the
  * scale factor >= 1.0 and "ceil (1.0 + 1.0/scale)" otherwise.  These map most
  * closely to MLIB_BICUBIC, which uses an interpolation table of size 4x4.
  *
  * PIXOPS_INTERP_NEAREST calls pixops_scale_nearest which does not use an
  * interpolation table.  This maps to MLIB_NEAREST.
  */
  switch (interp_type)
    {
    case PIXOPS_INTERP_BILINEAR:
      bilinear_magnify_make_weights (&(ml_interp->po_filter.x), scale_x);
      bilinear_magnify_make_weights (&(ml_interp->po_filter.y), scale_y);
      leftPadding = 0;
      topPadding  = 0;

      if (scale_x <= 1.0)
          ml_interp->tx = 0.5 * (1 - scale_x);
      else
          ml_interp->tx = 0.0;

      if (scale_y <= 1.0)
          ml_interp->ty = 0.5 * (1 - scale_y);
      else
          ml_interp->ty = 0.0;

      break;

    case PIXOPS_INTERP_TILES:
      tile_make_weights (&(ml_interp->po_filter.x), scale_x);
      tile_make_weights (&(ml_interp->po_filter.y), scale_y);
      leftPadding   = 0;
      topPadding    = 0;
      ml_interp->tx = 0.5 * (1 - scale_x);
      ml_interp->ty = 0.5 * (1 - scale_y);
      break;

    case PIXOPS_INTERP_HYPER:
      bilinear_box_make_weights (&(ml_interp->po_filter.x), scale_x);
      bilinear_box_make_weights (&(ml_interp->po_filter.y), scale_y);
      leftPadding   = 1;
      topPadding    = 1;
      ml_interp->tx = 0.5 * (1 - scale_x);
      ml_interp->ty = 0.5 * (1 - scale_y);
      break;

    case PIXOPS_INTERP_NEAREST:
    default:
      /*
       * Note that this function should not be called in the
       * PIXOPS_INTERP_NEAREST case since it does not use an interpolation
       * table.
       */
      g_assert_not_reached ();
      break;
    }

 /* 
  * If overall_alpha is not 1.0, then multiply the vectors built by the
  * sqrt (overall_alpha).  This will cause overall_alpha to get evenly
  * blended across both axis.
  *
  * Note there is no need to multiply the vectors built by the various
  * make-weight functions by sqrt (overall_alpha) since the make-weight
  * functions are called with overall_alpha hardcoded to 1.0.
  */
  if (overall_alpha != 1.0)
    {
      double sqrt_alpha = sqrt (overall_alpha);
      int i;

      for (i=0; i < SUBSAMPLE * ml_interp->po_filter.x.n; i++)
         ml_interp->po_filter.x.weights[i] *= sqrt_alpha;
      for (i=0; i < SUBSAMPLE * ml_interp->po_filter.y.n; i++)
         ml_interp->po_filter.y.weights[i] *= sqrt_alpha;
    }
    
  ml_interp->interp_table = (void *) mlib_ImageInterpTableCreate (MLIB_DOUBLE,
    ml_interp->po_filter.x.n, ml_interp->po_filter.y.n, leftPadding,
    topPadding, SUBSAMPLE_BITS, SUBSAMPLE_BITS, 8,
    ml_interp->po_filter.x.weights, ml_interp->po_filter.y.weights);

  g_free (ml_interp->po_filter.x.weights);
  g_free (ml_interp->po_filter.y.weights);  
}
medialib_get_interpolation (mlInterp * ml_interp,
                            PixopsInterpType interp_type,
                            double scale_x,
                            double scale_y,
                            double overall_alpha)
{
  mlib_s32 leftPadding, topPadding;
  ml_interp->interp_table = NULL;

  
  switch (interp_type)
    {
    case PIXOPS_INTERP_BILINEAR:
      bilinear_magnify_make_weights (&(ml_interp->po_filter.x), scale_x);
      bilinear_magnify_make_weights (&(ml_interp->po_filter.y), scale_y);
      leftPadding = 0;
      topPadding  = 0;

      if (scale_x <= 1.0)
          ml_interp->tx = 0.5 * (1 - scale_x);
      else
          ml_interp->tx = 0.0;

      if (scale_y <= 1.0)
          ml_interp->ty = 0.5 * (1 - scale_y);
      else
          ml_interp->ty = 0.0;

      break;

    case PIXOPS_INTERP_TILES:
      tile_make_weights (&(ml_interp->po_filter.x), scale_x);
      tile_make_weights (&(ml_interp->po_filter.y), scale_y);
      leftPadding   = 0;
      topPadding    = 0;
      ml_interp->tx = 0.5 * (1 - scale_x);
      ml_interp->ty = 0.5 * (1 - scale_y);
      break;

    case PIXOPS_INTERP_HYPER:
      bilinear_box_make_weights (&(ml_interp->po_filter.x), scale_x);
      bilinear_box_make_weights (&(ml_interp->po_filter.y), scale_y);
      leftPadding   = 1;
      topPadding    = 1;
      ml_interp->tx = 0.5 * (1 - scale_x);
      ml_interp->ty = 0.5 * (1 - scale_y);
      break;

    case PIXOPS_INTERP_NEAREST:
    default:
       
      g_assert_not_reached ();
      break;
    }

  
  if (overall_alpha != 1.0)
    {
      double sqrt_alpha = sqrt (overall_alpha);
      int i;

      for (i=0; i < SUBSAMPLE * ml_interp->po_filter.x.n; i++)
         ml_interp->po_filter.x.weights[i] *= sqrt_alpha;
      for (i=0; i < SUBSAMPLE * ml_interp->po_filter.y.n; i++)
         ml_interp->po_filter.y.weights[i] *= sqrt_alpha;
    }
    
  ml_interp->interp_table = (void *) mlib_ImageInterpTableCreate (MLIB_DOUBLE,
    ml_interp->po_filter.x.n, ml_interp->po_filter.y.n, leftPadding,
    topPadding, SUBSAMPLE_BITS, SUBSAMPLE_BITS, 8,
    ml_interp->po_filter.x.weights, ml_interp->po_filter.y.weights);

  g_free (ml_interp->po_filter.x.weights);
  g_free (ml_interp->po_filter.y.weights);  
}