\section{Interpolators}
\label{sec:interpolate}

VIPS has a general system for representing pixel interpolators. You can select
an interpolator to pass to other VIPS operations, such as \verb+im_affinei()+,
you can add new interpolators, and you can write operations which take a
general interpolator as a parameter. 

An interpolator is a function of the form:

\begin{verbatim}
typedef void (*VipsInterpolateMethod)( VipsInterpolate *,
  PEL *out, REGION *in, double x, double y );
\end{verbatim}

\noindent
given the set of input pixels \verb+in+, it has to calculate a value for the
fractional position $(x, y)$ and write this value to the memory pointed to by
\verb+out+.

VIPS uses corner convention, so the value of pixel $(0, 0)$ is the value of
the surface the interpolator fits at the fractional position $(0.0, 0.0)$.

\subsection{How an interpolator is represented}

See the man page for \verb+VipsInterpolate+ for full details, but briefly,
an interpolator is a subclass of \verb+VipsInterpolate+ implementing the 
following items:

\begin{itemize}
\item
An interpolation method, with the type signature above.

\item
A function \verb+get_window_size()+ which returns the size of the area of
pixels that the interpolator needs in order to calculate a value. For example,
a bilinear interpolator needs the four pixels surrounding the point to be
calculated, or a 2 by 2 window, so window size should be 2.

\item
Or if the window size is constant, you can leave \verb+get_window_size()+
NULL and just set the int value \verb+window_size+.

\end{itemize}

\subsection{A sample interpolator}

As an example, \fref{fg:newinterpolator} shows how to register a new
interpolator in a plugin.

\begin{fig2}
\begin{verbatim}
// This interpolator adds no new members.
typedef VipsInterpolate Myinterpolator;
typedef VipsInterpolateClass MyinterpolatorClass;

G_DEFINE_TYPE( Myinterpolator, myinterpolator, VIPS_TYPE_INTERPOLATE );

static void
myinterpolator_interpolate( VipsInterpolate *interpolate, 
	PEL *out, REGION *in, double x, double y )
{
  MyinterpolatorClass *class = 
    MYINTERPOLATOR_GET_CLASS( interpolate );

  /* Nearest-neighbor.
   */
  memcpy( out, 
    IM_REGION_ADDR( in, floor( x ), floor( y ) ),
    IM_IMAGE_SIZEOF_PEL( in->im ) );
}

static void
myinterpolator_class_init( MyinterpolatorClass *class )
{
  VipsObjectClass *object_class = (VipsObjectClass *) class;
  VipsInterpolateClass *interpolate_class = (VipsInterpolateClass *) class;

  object_class->nickname = "myinterpolator";
  object_class->description = _( "My interpolator" );

  interpolate_class->interpolate = myinterpolator_interpolate;
}

static void
myinterpolate_init( Myinterpolate *object )
{
}

char *
g_module_check_init( GModule *self )
{
  // register the type
  myinterpolator_get_type(); 
}
\end{verbatim}
\caption{Registering an interpolator in a plugin}
\label{fg:newinterpolator}
\end{fig2}

\subsection{Writing a VIPS operation that takes an interpolator as an argument}

Operations just take a \verb+VipsInterpolate+ as an argument, for example:

\begin{verbatim}
int im_affinei_all( IMAGE *in, IMAGE *out, 
  VipsInterpolate *interpolate,
  double a, double b, double c, double d, 
  double dx, double dy );
\end{verbatim}

To use the interpolator, use \verb+vips_interpolate()+:

\begin{verbatim}
void vips_interpolate( VipsInterpolate *interpolate,
  PEL *out, REGION *in, double x, double y );
\end{verbatim}

\noindent
This looks up the interpolate method for the object and calls it for you.

You can save the cost of the lookup in an inner loop with
\verb+vips_interpolate_get_method()+:

\begin{verbatim}
VipsInterpolateMethod 
  vips_interpolate_get_method( 
    VipsInterpolate *interpolate );
\end{verbatim}

\subsection{Passing an interpolator to a VIPS operation}

You can build an instance of a \verb+VipsInterpolator+ with
the \verb+vips_object_*()+ family of functions, see \pref{sec:object}.

Convenience functions return a static instance of one of the standard
interpolators:

\begin{verbatim}
VipsInterpolate *vips_interpolate_nearest_static( void );
VipsInterpolate *vips_interpolate_bilinear_static( void );
VipsInterpolate *vips_interpolate_bicubic_static( void );
\end{verbatim}

\noindent
Don't free the result.

Finally, \verb+vips_interpolate_new()+ makes a \verb+VipsInterpolate+ from a
nickname:

\begin{verbatim}
VipsInterpolate *vips_interpolate_new( const char *nickname );
\end{verbatim}

For example:

\begin{verbatim}
VipsInterpolate *interpolate = vips_interpolate_new( "nohalo" );
\end{verbatim}

\noindent
You must drop your ref after you're done with the object with
\verb+g_object_unref()+.
