stuff
This commit is contained in:
parent
26dff6bb73
commit
158a933151
@ -33,6 +33,7 @@
|
||||
- added "nickname" and "description" properties to VipsObject
|
||||
- shift/and/or/eor ops were broken for non-int types
|
||||
- added nohalo interpolator
|
||||
- updated format docs
|
||||
- IM_INPUT_INTERPOLATE() now used by affinei and affinei_all
|
||||
|
||||
11/9/08 started 7.16.3
|
||||
|
17
TODO
17
TODO
@ -1,16 +1,17 @@
|
||||
- make properties for nickname etc. so we can get class properties from
|
||||
objects
|
||||
|
||||
- dir on a Managedgobject should list properties
|
||||
- interpolate.c never calls vips_object_build() for bilinear etc., is this OK?
|
||||
|
||||
- (get_member "poop" (Managedgobject)) should work
|
||||
try to add this
|
||||
|
||||
- dir on a gtype should also list properties? how should we list subclasses?
|
||||
- need to write interpolate docs ... manpages and tutorial
|
||||
|
||||
difficult without docs for vips_object
|
||||
|
||||
- need a section for vipsobject in the tutorial
|
||||
|
||||
also a manpage?
|
||||
|
||||
- maybe IM_INTERPOLATE() isn't a good idea? maybe just IM_GOBJECT?
|
||||
not really stable yet :( don't document
|
||||
|
||||
- try making vips_add(), an operator as a class
|
||||
|
||||
@ -18,9 +19,7 @@
|
||||
|
||||
- make a "deprecated" package too
|
||||
|
||||
- im_affinei and im_affinei_all need docs
|
||||
|
||||
- update format docs
|
||||
- remove yafrnohalo.c
|
||||
|
||||
- how to expose things like yafrsmooth's "sharpening" parameter to
|
||||
C++/Python?
|
||||
|
@ -2,7 +2,7 @@
|
||||
\label{sec:format}
|
||||
|
||||
VIPS has a simple system for adding support for new image file formats.
|
||||
You can ask VIPS to find a format to load a file with,
|
||||
You can ask VIPS to find a format to load a file with
|
||||
or to select a image file writer based on a filename. Convenience functions
|
||||
copy a file to an \verb+IMAGE+, or an \verb+IMAGE+ to a file. New formats may
|
||||
be added to VIPS by simply defining a new subclass of \verb+VipsFormat+.
|
||||
@ -42,7 +42,17 @@ version is one indicating that the file can be opened lazily
|
||||
|
||||
\end{itemize}
|
||||
|
||||
\subsection{The format table}
|
||||
A switch to the \verb+vips+ command-line program is handy for listing the
|
||||
supported formats. Try:
|
||||
|
||||
\begin{verbatim}
|
||||
vips --list classes
|
||||
\end{verbatim}
|
||||
|
||||
\noindent
|
||||
And look for subclasses of \verb+VipsFormat+.
|
||||
|
||||
\subsection{The format class}
|
||||
|
||||
The interface to the format system is defined by the abstract base class
|
||||
\verb+VipsFormat+. Formats subclass this and implement some or all of the
|
||||
@ -50,13 +60,6 @@ methods. Any of the functions may be left NULL and VIPS will try to make do
|
||||
with what you do supply. Of course a format with all functions as NULL will
|
||||
not be very useful.
|
||||
|
||||
A switch to the \verb+vips+ command-line program is handy for listing the
|
||||
supported formats. Try:
|
||||
|
||||
\begin{verbatim}
|
||||
vips --list formats
|
||||
\end{verbatim}
|
||||
|
||||
As an example, \fref{fg:newformat} shows how to register a new format in a
|
||||
plugin.
|
||||
|
||||
@ -82,7 +85,7 @@ typedef VipsFormat VipsFormatMyformat;
|
||||
typedef VipsFormatClass VipsFormatMyformatClass;
|
||||
|
||||
static void
|
||||
vips_format_myformat_class_init( VipsFormatVipsClass *class )
|
||||
vips_format_myformat_class_init( VipsFormatMyformatClass *class )
|
||||
{
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
VipsFormatClass *format_class = (VipsFormatClass *) class;
|
||||
@ -100,17 +103,17 @@ vips_format_myformat_class_init( VipsFormatVipsClass *class )
|
||||
}
|
||||
|
||||
static void
|
||||
vips_format_vips_init( VipsFormatVips *object )
|
||||
vips_format_myformat_init( VipsFormatMyformat *object )
|
||||
{
|
||||
}
|
||||
|
||||
G_DEFINE_TYPE( VipsFormatVips, vips_format_vips, VIPS_TYPE_FORMAT );
|
||||
G_DEFINE_TYPE( VipsFormatMyformat, vips_format_myformat, VIPS_TYPE_FORMAT );
|
||||
|
||||
char *
|
||||
g_module_check_init( GModule *self )
|
||||
{
|
||||
// register the type
|
||||
vips_format_vips_get_type();
|
||||
vips_format_myformat_get_type();
|
||||
}
|
||||
\end{verbatim}
|
||||
\caption{Registering a format in a plugin}
|
||||
@ -119,14 +122,15 @@ g_module_check_init( GModule *self )
|
||||
|
||||
\subsection{Finding a format}
|
||||
|
||||
You can loop over the format table in order with \verb+vips_format_map()+. Like
|
||||
all the map functions in VIPS, this take a function and applies it to every
|
||||
element in the table until it returns non-zero, or until the table ends.
|
||||
You can loop over the subclasses of \verb+VipsFormat+ in order of priority
|
||||
with \verb+vips_format_map()+. Like all the map functions in VIPS, this take
|
||||
a function and applies it to every element in the table until the function
|
||||
returns non-zero or until the table ends.
|
||||
|
||||
You find an \verb+VipsFormatClass+ to use to open a file with
|
||||
\verb+vips_format_for_file()+. This searches the type system and returns
|
||||
the first format whose test function returns true, setting an error message
|
||||
and returning NULL if no format is found.
|
||||
\verb+vips_format_for_file()+. This finds the first format whose \verb+is_a()+
|
||||
function returns true or whose suffix list matches the suffix of the filename,
|
||||
setting an error message and returning NULL if no format is found.
|
||||
|
||||
You find a format to write a file with \verb+vips_format_for_name()+. This
|
||||
returns the first format with a save function whose suffix list matches the
|
||||
|
110
doc/src/interpolate.tex
Normal file
110
doc/src/interpolate.tex
Normal file
@ -0,0 +1,110 @@
|
||||
\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}
|
||||
|
||||
A switch to the \verb+vips+ command-line program is handy for listing the
|
||||
supported interpolators. Try:
|
||||
|
||||
\begin{verbatim}
|
||||
vips --list classes
|
||||
\end{verbatim}
|
||||
|
||||
\noindent
|
||||
And look for subclasses of \verb+VipsInterpolate+.
|
||||
|
||||
\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 VipsInterpolateMyinterpolator;
|
||||
typedef VipsInterpolateClass VipsInterpolateMyinterpolator;
|
||||
|
||||
|
||||
static void
|
||||
vips_interpolate_myinterpolator_interpolate( VipsInterpolate *interpolate,
|
||||
PEL *out, REGION *in, double x, double y )
|
||||
{
|
||||
VipsInterpolateBilinearClass *class =
|
||||
VIPS_INTERPOLATE_BILINEAR_GET_CLASS( interpolate );
|
||||
|
||||
static void
|
||||
vips_interpolate_myinterpolator_class_init(
|
||||
VipsInterpolateMyinterpolatorClass *class )
|
||||
{
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
VipsInterpolateClass *interpolate_class = (VipsInterpolateClass *) class;
|
||||
|
||||
object_class->nickname = "myinterpolator";
|
||||
object_class->description = _( "My interpolator" );
|
||||
|
||||
interpolate_class->interpolate = my_interpolate;
|
||||
}
|
||||
|
||||
static void
|
||||
vips_interpolate_myinterpolate_init( VipsInterpolateMyinterpolate *object )
|
||||
{
|
||||
}
|
||||
|
||||
G_DEFINE_TYPE( VipsInterpolateMyinterpolator, vips_interpolate_myinterpolator,
|
||||
VIPS_TYPE_INTERPOLATE );
|
||||
|
||||
char *
|
||||
g_module_check_init( GModule *self )
|
||||
{
|
||||
// register the type
|
||||
vips_format_myformat_get_type();
|
||||
}
|
||||
\end{verbatim}
|
||||
\caption{Registering an interpolator in a plugin}
|
||||
\label{fg:newinterpolator}
|
||||
\end{fig2}
|
||||
|
||||
\subsection{Passing an interpolator to a VIPS operation}
|
||||
|
||||
\subsection{Writing a VIPS operation that takes an interpolator as an argument}
|
||||
|
@ -73,6 +73,7 @@ This manual formatted \today
|
||||
\input{iosys}
|
||||
\input{func}
|
||||
\input{format}
|
||||
\input{interpolate}
|
||||
|
||||
\chapter{Writing VIPS operations}
|
||||
|
||||
|
@ -241,6 +241,10 @@ GType vips_object_get_type( void );
|
||||
void vips_object_class_install_argument( VipsObjectClass *,
|
||||
GParamSpec *pspec, VipsArgumentFlags flags, guint offset );
|
||||
|
||||
typedef void *(*VipsObjectSetArguments)( VipsObject *, void *, void * );
|
||||
VipsObject *vips_object_new( GType type,
|
||||
VipsObjectSetArguments set, void *a, void *b );
|
||||
|
||||
VipsObject *vips_object_new_from_string( const char *base, const char *str );
|
||||
void vips_object_to_string( VipsObject *object, VipsBuf *buf );
|
||||
|
||||
|
@ -220,7 +220,8 @@ vips_argument_init2( VipsObject *object, GParamSpec *pspec,
|
||||
|
||||
/* Create a VipsArgumentInstance for each installed argument property. Ideally
|
||||
* we'd do this during _init() but g_object_class_find_property() does not seem
|
||||
* to work then :-( so we have to delay it until first access.
|
||||
* to work then :-( so we have to delay it until first access. See
|
||||
* vips__argument_get_instance().
|
||||
*/
|
||||
static void
|
||||
vips_argument_init( VipsObject *object )
|
||||
@ -699,6 +700,10 @@ vips_object_real_build( VipsObject *object )
|
||||
"nickname", object_class->nickname,
|
||||
"description", object_class->description, NULL );
|
||||
|
||||
/* Signal changed, since all properties should now be set.
|
||||
*/
|
||||
vips_object_changed( object );
|
||||
|
||||
return( result );
|
||||
}
|
||||
|
||||
@ -952,6 +957,41 @@ vips_object_set_args( VipsObject *object, const char *p )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
VipsObject *
|
||||
vips_object_new( GType type, VipsObjectSetArguments set, void *a, void *b )
|
||||
{
|
||||
VipsObject *object;
|
||||
|
||||
object = VIPS_OBJECT( g_object_new( type, NULL ) );
|
||||
|
||||
if( set( object, a, b ) ||
|
||||
vips_object_build( object ) ) {
|
||||
g_object_unref( object );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
return( object );
|
||||
}
|
||||
|
||||
static void *
|
||||
vips_object_new_from_string_set( VipsObject *object, void *a, void *b )
|
||||
{
|
||||
const char *p = (const char *) a;
|
||||
VipsToken token;
|
||||
char string[PATH_MAX];
|
||||
|
||||
if( (p = vips__token_get( p, &token, string, PATH_MAX )) ) {
|
||||
if( token == VIPS_TOKEN_LEFT &&
|
||||
vips_object_set_args( object, p ) ) {
|
||||
im_error( "object_new", "%s",
|
||||
_( "bad object arguments" ) );
|
||||
return( object );
|
||||
}
|
||||
}
|
||||
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
VipsObject *
|
||||
vips_object_new_from_string( const char *basename, const char *p )
|
||||
{
|
||||
@ -964,24 +1004,8 @@ vips_object_new_from_string( const char *basename, const char *p )
|
||||
!(type = vips_type_find( basename, string )) )
|
||||
return( NULL );
|
||||
|
||||
object = VIPS_OBJECT( g_object_new( type, NULL ) );
|
||||
|
||||
if( (p = vips__token_get( p, &token, string, PATH_MAX )) ) {
|
||||
if( token == VIPS_TOKEN_LEFT &&
|
||||
vips_object_set_args( object, p ) ) {
|
||||
im_error( "object_new", "%s",
|
||||
_( "bad object arguments" ) );
|
||||
g_object_unref( object );
|
||||
return( NULL );
|
||||
}
|
||||
}
|
||||
|
||||
if( vips_object_build( object ) ) {
|
||||
g_object_unref( object );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
return( object );
|
||||
return( vips_object_new( type,
|
||||
vips_object_new_from_string_set, (void *) p, NULL ) );
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -100,7 +100,7 @@ vips_interpolate_init( VipsInterpolate *interpolate )
|
||||
}
|
||||
|
||||
/* Set the point out_x, out_y in REGION out to be the point interpolated at
|
||||
* in_x, in_y in REGION in. Don't do this as a signal ffor speed.
|
||||
* in_x, in_y in REGION in. Don't do this as a signal for speed.
|
||||
*/
|
||||
void
|
||||
vips_interpolate( VipsInterpolate *interpolate,
|
||||
|
@ -15,7 +15,11 @@ int im_affine(in, out, a, b, c, d, dx, dy, x, y, w, h)
|
||||
.B int w, h;
|
||||
|
||||
.SH DESCRIPTION
|
||||
.B im_affine()
|
||||
This function is deprecated. See
|
||||
.B im_affine(3)
|
||||
for the replacement.
|
||||
|
||||
.B im_affine(3)
|
||||
applies an affine transformation on the image held by the IMAGE descriptor
|
||||
in and puts the result at the location pointed by the IMAGE descriptor out. in
|
||||
many have any number of bands, be any size, and have any non-complex type.
|
||||
@ -23,26 +27,15 @@ many have any number of bands, be any size, and have any non-complex type.
|
||||
The transformation is described by a, b, c, d, dx, dy. The point (x,y) in
|
||||
the input is mapped onto point (X,Y) in the output by
|
||||
|
||||
X = a * x + b * y + dx
|
||||
Y = c * x + d * y + dy
|
||||
X = a * x + b * y + dx
|
||||
Y = c * x + d * y + dy
|
||||
|
||||
The area of the output image given by w, h, x, y is generated. (0,0) is
|
||||
the position of the transformed top-left-hand corner of the input image.
|
||||
Function im_affine resamples the transformed image using bilinear
|
||||
interpolation.
|
||||
|
||||
You can use
|
||||
.B im_affine(3)
|
||||
to resize an image with something like:
|
||||
|
||||
scale xfac yfac im
|
||||
= im_affine im xfac 0 0 yfac 0 0 0 0
|
||||
(im.width * xfac) (im.height * yfac);
|
||||
|
||||
.SH RETURN VALUE
|
||||
The functions return 0 on success and -1 on error.
|
||||
.SH BUGS
|
||||
As with most resamplers, im_affine(3) performs poorly at the edges of
|
||||
images.
|
||||
.SH SEE ALSO
|
||||
im_similarity(3)
|
||||
|
58
man/im_affinei.3
Normal file
58
man/im_affinei.3
Normal file
@ -0,0 +1,58 @@
|
||||
.TH IM_AFFINEI 3 "8 February 2009"
|
||||
.SH NAME
|
||||
im_affinei \- apply an affine transform to an image
|
||||
.SH SYNOPSIS
|
||||
.B #include <vips/vips.h>
|
||||
|
||||
int im_affinei(in, out, interpolate, a, b, c, d, dx, dy, x, y, w, h)
|
||||
.br
|
||||
.B IMAGE *in, *out;
|
||||
.br
|
||||
.B VipsInterpolate *interpolate;
|
||||
.br
|
||||
.B double a, b, c, d, dx, dy;
|
||||
.br
|
||||
.B int x, y;
|
||||
.br
|
||||
.B int w, h;
|
||||
|
||||
int im_affinei_all(in, out, interpolate, a, b, c, d, dx, dy)
|
||||
.br
|
||||
.B IMAGE *in, *out;
|
||||
.br
|
||||
.B VipsInterpolate *interpolate;
|
||||
.br
|
||||
.B double a, b, c, d, dx, dy;
|
||||
|
||||
.SH DESCRIPTION
|
||||
.B im_affinei()
|
||||
applies an affine transformation on the image held by the IMAGE descriptor
|
||||
in and puts the result at the location pointed by the IMAGE descriptor out. in
|
||||
many have any number of bands, be any size, and have any non-complex type.
|
||||
|
||||
The transformation is described by a, b, c, d, dx, dy. The point (x,y) in
|
||||
the input is mapped onto point (X,Y) in the output by
|
||||
|
||||
X = a * x + b * y + dx
|
||||
Y = c * x + d * y + dy
|
||||
|
||||
The area of the output image given by w, h, x, y is generated. (0,0) is
|
||||
the position of the transformed top-left-hand corner of the input image.
|
||||
|
||||
Points are generated using the supplied interpolator. See
|
||||
.B VipsInterpolate(3)
|
||||
for a list of the interpolators that come with vips.
|
||||
|
||||
.B im_affinei_all(3)
|
||||
is a convenience function that transforms the whole of the input image. It
|
||||
calls
|
||||
.B im_affine(3)
|
||||
for you, with x y w h set to exactly enclose the transformed image.
|
||||
|
||||
.SH RETURN VALUE
|
||||
The functions return 0 on success and -1 on error.
|
||||
.SH BUGS
|
||||
As with most resamplers, im_affine(3) performs poorly at the edges of
|
||||
images.
|
||||
.SH SEE ALSO
|
||||
im_similarity(3)
|
1
man/im_affinei_all.3
Normal file
1
man/im_affinei_all.3
Normal file
@ -0,0 +1 @@
|
||||
.so man3/im_affinei.3
|
@ -23,7 +23,8 @@ then you can use that link to call an operation directly. For example:
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B -l PACKAGE, --list=PACKAGE
|
||||
List operations defined in PACKAGE.
|
||||
List operations defined in PACKAGE. PACKAGE can also be "classes", "packages"
|
||||
or "all".
|
||||
|
||||
.TP
|
||||
.B -u OPERATION, --usage=OPERATION
|
||||
@ -45,11 +46,6 @@ Print C++ header for PACKAGE. PACKAGE can also be a function name, or "all".
|
||||
.B -c PACKAGE, --cppc=PACKAGE
|
||||
Print C++ binding for PACKAGE. PACKAGE can also be a function name, or "all".
|
||||
|
||||
.TP
|
||||
.B -s PACKAGE, --swig=PACKAGE
|
||||
Print SWIG declaration for PACKAGE. PACKAGE can also be a function name,
|
||||
or "all".
|
||||
|
||||
.SH RETURN VALUE
|
||||
returns 0 on success and non-zero on error.
|
||||
.SH SEE ALSO
|
||||
|
@ -28,6 +28,8 @@
|
||||
* - add --list formats
|
||||
* 29/11/08
|
||||
* - add --list interpolators
|
||||
* 9/2/09
|
||||
* - and now we just have --list packages/classes/package-name
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -86,7 +88,8 @@ static gboolean *main_option_version;
|
||||
|
||||
static GOptionEntry main_option[] = {
|
||||
{ "list", 'l', 0, G_OPTION_ARG_STRING, &main_option_list,
|
||||
N_( "list operations in PACKAGE (or \"all\", \"packages\")" ),
|
||||
N_( "list operations in PACKAGE "
|
||||
"(or \"all\", \"packages\", \"classes\")" ),
|
||||
"PACKAGE" },
|
||||
{ "usage", 'u', 0, G_OPTION_ARG_STRING, &main_option_usage,
|
||||
N_( "show usage message for OPERATION" ),
|
||||
|
Loading…
Reference in New Issue
Block a user