\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 ); \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()+.