libvips/doc/src/interpolate.tex

164 lines
4.5 KiB
TeX

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