164 lines
4.5 KiB
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()+.
|