diff --git a/doc/Makefile.am b/doc/Makefile.am
index 60597702..befd7ce2 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -148,6 +148,7 @@ markdown_content_files = \
How-it-opens-files.md \
Examples.md \
Cite.md \
+ binding.md \
Making-image-pyramids.md
# converted to xml in this dir by pandoc
@@ -159,13 +160,11 @@ content_files = \
using-command-line.xml \
using-C.xml \
using-threads.xml \
- using-python.xml \
using-cpp.xml \
extending.xml \
function-list.xml \
file-format.xml \
- ${markdown_content_files_docbook} \
- binding.xml
+ ${markdown_content_files_docbook}
# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
# These files must be listed here *and* in content_files
@@ -174,13 +173,11 @@ expand_content_files = \
using-command-line.xml \
using-C.xml \
using-threads.xml \
- using-python.xml \
using-cpp.xml \
extending.xml \
function-list.xml \
file-format.xml \
- ${markdown_content_files_docbook} \
- binding.xml
+ ${markdown_content_files_docbook}
# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
# Only needed if you are using gtkdoc-scangobj to dynamically query widget
diff --git a/doc/binding.md b/doc/binding.md
new file mode 100644
index 00000000..187c130e
--- /dev/null
+++ b/doc/binding.md
@@ -0,0 +1,223 @@
+
+ How to write bindings
+ 3
+ libvips
+
+
+
+ Binding
+ Writing bindings for libvips
+
+
+There are full libvips bindings for quite a few languages now: C, C++, Ruby,
+PHP, Python and JavaScript.
+
+This chapter runs through the four main styles that have been found to work
+well. If you want to write a new binding, one of these should be close
+to what you need.
+
+# C API
+
+The libvips C API (vips_add() and so on) is very inconvenient to use from other
+languages due to its heavy use of varargs.
+
+It's much better to use the layer below. This lower layer is structured as:
+create operator, set parameters, execute, extract results. For example, you can
+execute vips_invert() like this:
+
+```C
+/* compile with
+ *
+ * gcc -g -Wall callvips.c `pkg-config vips --cflags --libs`
+ *
+ */
+
+#include
+
+int
+main( int argc, char **argv )
+{
+ VipsImage *in;
+ VipsImage *out;
+ VipsOperation *op;
+ VipsOperation *new_op;
+ GValue gvalue = { 0 };
+
+ if( VIPS_INIT( argv[0] ) )
+ /* This shows the vips error buffer and quits with a fail exit
+ * code.
+ */
+ vips_error_exit( NULL );
+
+ /* This will print a table of any ref leaks on exit, very handy for
+ * development.
+ */
+ vips_leak_set( TRUE );
+
+ if( argc != 3 )
+ vips_error_exit( "usage: %s input-filename output-filename",
+ argv[0] );
+
+ if( !(in = vips_image_new_from_file( argv[1], NULL )) )
+ vips_error_exit( NULL );
+
+ /* Create a new operator from a nickname. NULL for unknown operator.
+ */
+ op = vips_operation_new( "invert" );
+
+ /* Init a gvalue as an image, set it to in, use the gvalue to set the
+ * operator property.
+ */
+ g_value_init( &gvalue, VIPS_TYPE_IMAGE );
+ g_value_set_object( &gvalue, in );
+ g_object_set_property( G_OBJECT( op ), "in", &gvalue );
+ g_value_unset( &gvalue );
+
+ /* We no longer need in: op will hold a ref to it as long as it needs
+ * it.
+ */
+ g_object_unref( in );
+
+ /* Call the operation. This will look up the operation+args in the vips
+ * operation cache and either return a previous operation, or build
+ * this one. In either case, we have a new ref we mst release.
+ */
+ if( !(new_op = vips_cache_operation_build( op )) ) {
+ g_object_unref( op );
+ vips_error_exit( NULL );
+ }
+ g_object_unref( op );
+ op = new_op;
+
+ /* Now get the result from op. g_value_get_object() does not ref the
+ * object, so we need to make a ref for out to hold.
+ */
+ g_value_init( &gvalue, VIPS_TYPE_IMAGE );
+ g_object_get_property( G_OBJECT( op ), "out", &gvalue );
+ out = VIPS_IMAGE( g_value_get_object( &gvalue ) );
+ g_object_ref( out );
+ g_value_unset( &gvalue );
+
+ /* All done: we can unref op. The output objects from op actually hold
+ * refs back to it, so before we can unref op, we must unref them.
+ */
+ vips_object_unref_outputs( VIPS_OBJECT( op ) );
+ g_object_unref( op );
+
+ if( vips_image_write_to_file( out, argv[2], NULL ) )
+ vips_error_exit( NULL );
+
+ g_object_unref( out );
+
+ return( 0 );
+}
+```
+
+libvips has a couple of extra things to let you fetch the arguments and types
+of an operator. Use vips_lib.vips_argument_map() to loop over all the arguments
+of an operator, and vips_object_get_argument() to fetch the type and flags
+of a specific argument.
+
+Use vips_operation_get_flags() to get general information about an operator.
+
+# Compiled language which can call C
+
+The C++ binding uses this lower layer to define a function called
+`VImage::call()` which can call any libvips operator with a not-varargs set of
+variable arguments.
+
+A small Python program walks the set of all libvips operators and generates a
+set of static bindings. For example:
+
+```c++
+VImage VImage::invert( VOption *options )
+{
+ VImage out;
+
+ call( "invert", (options ? options : VImage::option()) ->
+ set( "in", *this ) ->
+ set( "out", &out ) );
+
+ return( out );
+}
+```
+
+So from C++ you can call any libvips operator, though without type-safety, with
+`VImage::call()`, or use the member functions on `VImage` to get type-safe
+calls for at least the required operator arguments.
+
+The `VImage` class also adds automatic reference counting, constant expansion,
+operator overloads, and various other useful features.
+
+# Dynamic language with FFI
+
+Languages like Ruby, Python, JavaScript and Lua can't call C directly, but
+they do support FFI. The bindings for these languages work rather like C++,
+but use FFI to call into libvips and run operations.
+
+Since these languages are dynamic, they can add another trick: they intercept
+the method-missing hook and attempt to run any method calls not implemented by
+the `Image` class as libvips operators. This makes these bindings self-writing:
+they only contain a small amount of codeand just expose everything they find in
+the libvips class hierarchy.
+
+# Dynamic langauge without FFI
+
+PHP does not have FFI, unfortunately, so for this language a small native
+module implements the general `vips_call()` function for PHP language types,
+and a larger pure PHP layer makes it convenient to use.
+
+# `gobject-introspection`
+
+The C source code to libvips has been marked up with special comments
+describing the interface in a standard way. These comments are read by
+the `gobject-introspection` package when libvips is compiled and used to
+generate a typelib, a description of how to call the library. Many languages
+have gobject-introspection packages: all you need to do to call libvips
+from your favorite language is to start g-o-i, load the libvips typelib,
+and you should have the whole library available. For example, from Python
+it's as simple as:
+
+```python
+from gi.repository import Vips
+```
+
+libvips used in this way is likely to be rather bare-bones. For Python, we
+wrote a set of overrides which layer a more Pythonesque interface on top
+of the one provided for libvips by pygobject. These overrides are simply
+a set of Python classes.
+
+To call a vips operation, you'll need to make a new operation with
+vips_operation_new() (all it does is look up the operation by name
+with vips_type_find(), then call g_object_new() for you), then use
+vips_argument_map() and friends to loop over the operation's arguments setting
+them. Once you have set all arguments, use vips_cache_operation_build()
+to look up the operation in the cache and either build or dup it. If
+something goes wrong, you'll need to use vips_object_unref_outputs() and
+g_object_unref() to free the partially-built object. The Python binding uses
+this technique to implement a function which can call any vips operation,
+turning optional vips arguments into Python keyword arguments.
+
+You can generate searchable docs from a .gir (the thing that
+is built from scanning libvips and which in turn turn the typelib is
+made from) with g-ir-doc-tool, for example:
+
+```
+$ g-ir-doc-tool --language=Python -o ~/mydocs Vips-8.0.gir
+```
+
+Then to view them, either:
+
+```
+$ yelp ~/mydocs
+```
+
+Or perhaps:
+
+```
+$ cd ~/mydocs
+$ yelp-build html .
+```
+
+To make HTML docs. This is an easy way to see what you can call in the
+library.
diff --git a/doc/binding.xml b/doc/binding.xml
index bf547fb0..7a6a7bfa 100644
--- a/doc/binding.xml
+++ b/doc/binding.xml
@@ -1,94 +1,202 @@
-
-
-
-
-
- Writing bindings for libvips
- 3
- VIPS Library
-
+
+
+
-
- Binding
- How to write bindings for libvips
-
-
- Binding and gobject-introspection
-
- The C source code
- to libvips has been marked up with special comments describing the
- interface in a standard way. These comments are read by
- gobject-introspection
- when libvips is compiled and used to generate a
- typelib, a description of how to call the library. Many languages have
- gobject-introspection packages: all you need to do to call libvips
- from your favorite language is to start g-o-i, load the libvips typelib,
- and you should have the whole library available. For example, from
- Python it's as simple as:
+
+ How to write bindings3libvips
+
+
+ BindingWriting bindings for libvips
+
+
+ There are full libvips bindings for quite a few languages now: C, C++, Ruby, PHP, Python and JavaScript.
+
+
+ This chapter runs through the four main styles that have been found to work well. If you want to write a new binding, one of these should be close to what you need.
+
+
+ C API
+
+ The libvips C API (vips_add() and so on) is very inconvenient to use from other languages due to its heavy use of varargs.
+
+
+ It’s much better to use the layer below. This lower layer is structured as: create operator, set parameters, execute, extract results. For example, you can execute vips_invert() like this:
+
+
+/* compile with
+ *
+ * gcc -g -Wall callvips.c `pkg-config vips --cflags --libs`
+ *
+ */
-
+#include <vips/vips.h>
+
+int
+main( int argc, char **argv )
+{
+ VipsImage *in;
+ VipsImage *out;
+ VipsOperation *op;
+ VipsOperation *new_op;
+ GValue gvalue = { 0 };
+
+ if( VIPS_INIT( argv[0] ) )
+ /* This shows the vips error buffer and quits with a fail exit
+ * code.
+ */
+ vips_error_exit( NULL );
+
+ /* This will print a table of any ref leaks on exit, very handy for
+ * development.
+ */
+ vips_leak_set( TRUE );
+
+ if( argc != 3 )
+ vips_error_exit( "usage: %s input-filename output-filename",
+ argv[0] );
+
+ if( !(in = vips_image_new_from_file( argv[1], NULL )) )
+ vips_error_exit( NULL );
+
+ /* Create a new operator from a nickname. NULL for unknown operator.
+ */
+ op = vips_operation_new( "invert" );
+
+ /* Init a gvalue as an image, set it to in, use the gvalue to set the
+ * operator property.
+ */
+ g_value_init( &gvalue, VIPS_TYPE_IMAGE );
+ g_value_set_object( &gvalue, in );
+ g_object_set_property( G_OBJECT( op ), "in", &gvalue );
+ g_value_unset( &gvalue );
+
+ /* We no longer need in: op will hold a ref to it as long as it needs
+ * it.
+ */
+ g_object_unref( in );
+
+ /* Call the operation. This will look up the operation+args in the vips
+ * operation cache and either return a previous operation, or build
+ * this one. In either case, we have a new ref we mst release.
+ */
+ if( !(new_op = vips_cache_operation_build( op )) ) {
+ g_object_unref( op );
+ vips_error_exit( NULL );
+ }
+ g_object_unref( op );
+ op = new_op;
+
+ /* Now get the result from op. g_value_get_object() does not ref the
+ * object, so we need to make a ref for out to hold.
+ */
+ g_value_init( &gvalue, VIPS_TYPE_IMAGE );
+ g_object_get_property( G_OBJECT( op ), "out", &gvalue );
+ out = VIPS_IMAGE( g_value_get_object( &gvalue ) );
+ g_object_ref( out );
+ g_value_unset( &gvalue );
+
+ /* All done: we can unref op. The output objects from op actually hold
+ * refs back to it, so before we can unref op, we must unref them.
+ */
+ vips_object_unref_outputs( VIPS_OBJECT( op ) );
+ g_object_unref( op );
+
+ if( vips_image_write_to_file( out, argv[2], NULL ) )
+ vips_error_exit( NULL );
+
+ g_object_unref( out );
+
+ return( 0 );
+}
+
+
+ libvips has a couple of extra things to let you fetch the arguments and types of an operator. Use vips_lib.vips_argument_map() to loop over all the arguments of an operator, and vips_object_get_argument() to fetch the type and flags of a specific argument.
+
+
+ Use vips_operation_get_flags() to get general information about an operator.
+
+
+
+ Compiled language which can call C
+
+ The C++ binding uses this lower layer to define a function called VImage::call() which can call any libvips operator with a not-varargs set of variable arguments.
+
+
+ A small Python program walks the set of all libvips operators and generates a set of static bindings. For example:
+
+
+VImage VImage::invert( VOption *options )
+{
+ VImage out;
+
+ call( "invert", (options ? options : VImage::option()) ->
+ set( "in", *this ) ->
+ set( "out", &out ) );
+
+ return( out );
+}
+
+
+ So from C++ you can call any libvips operator, though without type-safety, with VImage::call(), or use the member functions on VImage to get type-safe calls for at least the required operator arguments.
+
+
+ The VImage class also adds automatic reference counting, constant expansion, operator overloads, and various other useful features.
+
+
+
+ Dynamic language with FFI
+
+ Languages like Ruby, Python, JavaScript and Lua can’t call C directly, but they do support FFI. The bindings for these languages work rather like C++, but use FFI to call into libvips and run operations.
+
+
+ Since these languages are dynamic, they can add another trick: they intercept the method-missing hook and attempt to run any method calls not implemented by the Image class as libvips operators. This makes these bindings self-writing: they only contain a small amount of codeand just expose everything they find in the libvips class hierarchy.
+
+
+
+ Dynamic langauge without FFI
+
+ PHP does not have FFI, unfortunately, so for this language a small native module implements the general vips_call() function for PHP language types, and a larger pure PHP layer makes it convenient to use.
+
+
+
+ gobject-introspection
+
+ The C source code to libvips has been marked up with special comments describing the interface in a standard way. These comments are read by the gobject-introspection package when libvips is compiled and used to generate a typelib, a description of how to call the library. Many languages have gobject-introspection packages: all you need to do to call libvips from your favorite language is to start g-o-i, load the libvips typelib, and you should have the whole library available. For example, from Python it’s as simple as:
+
+
from gi.repository import Vips
-
-
-
- libvips used in this way is likely to be rather bare-bones. For Python,
- we wrote a set of overrides which layer a more Pythonesque interface
- on top of the one provided for libvips by pygobject. These overrides
- are simply a set of Python classes.
-
-
-
- To call a vips operation, you'll need to make a new operation with
- vips_operation_new() (all it does is look up the operation by name
- with vips_type_find(), then call g_object_new() for you), then
- use vips_argument_map() and friends to loop over the operation's
- arguments setting them. Once you have set all arguments, use
- vips_cache_operation_build() to look up the operation in the cache
- and either build or dup it. If something goes wrong, you'll need
- to use vips_object_unref_outputs() and g_object_unref() to free the
- partially-built object.
- The Python binding uses this technique to implement a function which
- can call any vips operation, turning optional vips arguments into
- Python keyword arguments.
-
-
-
- If your language does not have a gobject-introspection package, you'll
- need to write something in C or C++ doing approximately the same thing.
- The C++ API takes this route.
-
-
-
- You can generate searchable docs from a .gir (the thing that
- is built from scanning libvips and which in turn turn the typelib is
- made from) with g-ir-doc-tool, for example:
-
-
+
+ libvips used in this way is likely to be rather bare-bones. For Python, we wrote a set of overrides which layer a more Pythonesque interface on top of the one provided for libvips by pygobject. These overrides are simply a set of Python classes.
+
+
+ To call a vips operation, you’ll need to make a new operation with vips_operation_new() (all it does is look up the operation by name with vips_type_find(), then call g_object_new() for you), then use vips_argument_map() and friends to loop over the operation’s arguments setting them. Once you have set all arguments, use vips_cache_operation_build() to look up the operation in the cache and either build or dup it. If something goes wrong, you’ll need to use vips_object_unref_outputs() and g_object_unref() to free the partially-built object. The Python binding uses this technique to implement a function which can call any vips operation, turning optional vips arguments into Python keyword arguments.
+
+
+ You can generate searchable docs from a .gir (the thing that is built from scanning libvips and which in turn turn the typelib is made from) with g-ir-doc-tool, for example:
+
+
$ g-ir-doc-tool --language=Python -o ~/mydocs Vips-8.0.gir
-
- Then to view them, either:
-
-
+
+ Then to view them, either:
+
+
$ yelp ~/mydocs
-
- Or perhaps
-
-
+
+ Or perhaps:
+
+
$ cd ~/mydocs
$ yelp-build html .
+
+ To make HTML docs. This is an easy way to see what you can call in the library.
+
+
- To make HTML docs. This is an easy way to see what you can call in the
- library.
-
-
-
-
diff --git a/doc/libvips-docs.xml.in b/doc/libvips-docs.xml.in
index 4bd2a812..aa8ab93a 100644
--- a/doc/libvips-docs.xml.in
+++ b/doc/libvips-docs.xml.in
@@ -32,7 +32,6 @@
-
diff --git a/doc/using-python.xml b/doc/using-python.xml
deleted file mode 100644
index cafe1711..00000000
--- a/doc/using-python.xml
+++ /dev/null
@@ -1,681 +0,0 @@
-
-
-
-
-
- VIPS from Python
- 3
- VIPS Library
-
-
-
- Using VIPS
- How to use the VIPS library from Python
-
-
-
- Introduction
-
- VIPS comes with a convenient, high-level Python API built on
- on gobject-introspection. As long as you can get GOI
- for your platform, you should be able to use libvips.
-
-
-
- To test the binding, start up Python and at the console enter:
-
-
->>> from gi.repository import Vips
->>> x = Vips.Image.new_from_file("/path/to/some/image/file.jpg")
->>> x.width
-1450
->>>
-
-
-
-
-
- If import fails, check you have the Python
- gobject-introspection packages installed, that you have the
- libvips typelib installed, and that the typelib is either
- in the system area or on your GI_TYPELIB_PATH.
-
-
-
-
-
- If .new_from_file() fails, the vips overrides
- have not been found. Make sure Vips.py is in
- your system overrides area.
-
-
-
-
-
-
-
- Example program
-
-
- Here's a complete example program:
-
-
-#!/usr/bin/python
-
-import sys
-
-from gi.repository import Vips
-
-im = Vips.Image.new_from_file(sys.argv[1])
-
-im = im.extract_area(100, 100, im.width - 200, im.height - 200)
-im = im.similarity(scale = 0.9)
-mask = Vips.Image.new_from_array([[-1, -1, -1],
- [-1, 16, -1],
- [-1, -1, -1]], scale = 8)
-im = im.conv(mask)
-
-im.write_to_file(sys.argv[2])
-
-
-
-
- Reading this code, the first interesting line is:
-
-
-from gi.repository import Vips
-
-
- When Python executes the import line it performs the following steps:
-
-
-
-
-
- It searches for a file called Vips-x.y.typelib. This
- is a binary file generated automatically during libvips build
- by introspection of the libvips shared library plus scanning
- of the C headers. It lists all the API entry points, all the
- types the library uses, and has an extra set of hints for object
- ownership and reference counting. The typelib is searched for
- in /usr/lib/gi-repository-1.0 and along the path
- in the environment variable GI_TYPELIB_PATH.
-
-
-
-
-
- It uses the typelib to make a basic binding for libvips. It's
- just the C API with a little very light mangling, so for
- example the enum member VIPS_FORMAT_UCHAR
- of the enum VipsBandFormat becomes
- Vips.BandFormat.UCHAR.
-
-
-
-
-
- The binding you get can be rather unfriendly, so it also
- loads a set of overrides from Vips.py in
- /usr/lib/python2.7/dist-packages/gi/overrides
- (on my system at least). If you're using python3, it's
- /usr/lib/python3/dist-packages/gi/overrides.
- Unfortunately, as far as I know, there is no way to extend
- this search using environment variables. You MUST have
- Vips.py in exactly this directory. If you install
- vips via a package manager this will happen automatically,
- since vips and pygobject will have been built to the same
- prefix, but if you are installing vips from source and the
- prefix does not match, it will not be installed for you,
- you will need to copy it.
-
-
-
-
-
- Finally, Vips.py makes the rest of the binding. In
- fact, Vips.py makes almost all the binding: it
- defines __getattr__ on Vips.Image
- and binds at runtime by searching libvips for an operation of
- that name.
-
-
-
-
-
- The next line is:
-
-
-im = Vips.Image.new_from_file(sys.argv[1])
-
-
- This loads the input image. You can append
- load options to the argument list as keyword arguments, for example:
-
-
-im = Vips.Image.new_from_file(sys.argv[1], access = Vips.Access.SEQUENTIAL)
-
-
- See the various loaders for a list of the available options
- for each file format. The C equivalent to this function,
- vips_image_new_from_file(), has more extensive documentation. Try
- help(Vips.Image) to see a list of all the image
- constructors --- you can load from memory, create from an array,
- or create from a constant, for example.
-
-
-
- The next line is:
-
-
-im = im.extract_area(100, 100, im.width - 200, im.height - 200)
-
-
- The arguments are left, top, width, height, so this crops 100 pixels off
- every edge. Try help(im.extract_area) and the C API docs
- for vips_extract_area() for details. You can use .crop()
- as a synonym, if you like.
-
-
-
- im.width gets the image width
- in pixels, see help(Vips.Image) and vips_image_get_width()
- and friends for a list of the other getters.
-
-
-
- The next line:
-
-
-im = im.similarity(scale = 0.9)
-
-
- shrinks by 10%. By default it uses
- bilinear interpolation, use interpolate to pick another
- interpolator, for example:
-
-
-im = im.similarity(scale = 0.9, interpolate = Vips.Interpolate.new("bicubic"))
-
-
- see vips_similarity() for full documentation. The similarity operator
- will not give good results for large resizes (more than a factor of
- two). See vips_resize() if you need to make a large change.
-
-
-
- Next:
-
-
-mask = Vips.Image.new_from_array([[-1, -1, -1],
- [-1, 16, -1],
- [-1, -1, -1]], scale = 8)
-im = im.conv(mask)
-
-
- makes an image from a 2D array, then convolves with that. The
- scale keyword argument lets you set a divisor for
- convolution, handy for integer convolutions. You can set
- offset as well. See vips_conv() for details on the vips
- convolution operator.
-
-
-
- Finally,
-
-
-im.write_to_file(sys.argv[2])
-
-
- sends the image back to the
- filesystem. There's also .write_to_buffer() to make a
- string containing the formatted image, and .write() to
- write to another image.
-
-
-
- As with .new_from_file() you can append save options as
- keyword arguments. For example:
-
-
-im.write_to_file("test.jpg", Q = 90)
-
-
- will write a JPEG image with quality set to 90. See the various save
- operations for a list of all the save options, for example
- vips_jpegsave().
-
-
-
-
-
- Getting help
-
- Try help(Vips) for everything,
- help(Vips.Image) for something slightly more digestible, or
- something like help(Vips.Image.black) for help on a
- specific class member.
-
-
-
- You can't get help on dynamically bound member functions like
- .add() this way. Instead, make an image and get help
- from that, for example:
-
-
-image = Vips.Image.black(1, 1)
-help(image.add)
-
-
- And you'll get a summary of the operator's behaviour and how the
- arguments are represented in Python.
-
-
-
- The API docs have a handy table of all vips
- operations, if you want to find out how to do something, try
- searching that.
-
-
-
- The vips command can be useful too. For example, in a
- terminal you can type vips jpegsave to get a
- summary of an operation:
-
-
-$ vips jpegsave
-save image to jpeg file
-usage:
- jpegsave in filename
-where:
- in - Image to save, input VipsImage
- filename - Filename to save to, input gchararray
-optional arguments:
- Q - Q factor, input gint
- default: 75
- min: 1, max: 100
- profile - ICC profile to embed, input gchararray
- optimize-coding - Compute optimal Huffman coding tables, input gboolean
- default: false
- interlace - Generate an interlaced (progressive) jpeg, input gboolean
- default: false
- no-subsample - Disable chroma subsample, input gboolean
- default: false
- trellis-quant - Apply trellis quantisation to each 8x8 block, input gboolean
- default: false
- overshoot-deringing - Apply overshooting to samples with extreme values, input gboolean
- default: false
- optimize-scans - Split the spectrum of DCT coefficients into separate scans, input gboolean
- default: false
- strip - Strip all metadata from image, input gboolean
- default: false
- background - Background value, input VipsArrayDouble
-operation flags: sequential-unbuffered nocache
-
-
-
-
-
-
- pyvips8 basics
-
- As noted above, the Python interface comes in two main parts,
- an automatically generated binding based on the vips typelib,
- plus a set of extra features provided by overrides.
- The rest of this chapter runs through the features provided by the
- overrides.
-
-
-
-
- Automatic wrapping
-
- The overrides intercept member lookup
- on the Vips.Image class and look for vips operations
- with that name. So the vips operation "add", which appears in the
- C API as vips_add(), appears in Python as
- image.add().
-
-
-
- The first input image argument becomes the self
- argument. If there are no input image arguments, the operation
- appears as a class member. Optional input arguments become
- keyword arguments. The result is a list of all the output
- arguments, or a single output if there is only one.
-
-
-
- Optional output arguments are enabled with a boolean keyword
- argument of that name. For example, "min" (the operation which
- appears in the C API as vips_min()), can be called like this:
-
-
-min_value = im.min()
-
-
- and min_value will be a floating point value giving
- the minimum value in the image. "min" can also find the position
- of the minimum value with the x and y
- optional output arguments. Call it like this:
-
-
-min_value, opts = im.min(x = True, y = True)
-x = opts['x']
-y = opts['y']
-
-
- In other words, if optional output args are requested, an extra
- dictionary is returned containing those objects.
- Of course in this case, the .minpos() convenience
- function would be simpler, see below.
-
-
-
- Because operations are member functions and return the result image,
- you can chain them. For example, you can write:
-
-
-result_image = image.sin().pow(2)
-
-
- to calculate the square of the sine for each pixel. There is also a
- full set of arithmetic operator overloads, see below.
-
-
-
- VIPS types are also automatically wrapped. The override looks
- at the type of argument required by the operation and converts
- the value you supply, when it can. For example, "linear" takes a
- #VipsArrayDouble as an argument for the set of constants to use for
- multiplication. You can supply this value as an integer, a float,
- or some kind of compound object and it will be converted for you.
- You can write:
-
-
-result_image = image.linear(1, 3)
-result_image = image.linear(12.4, 13.9)
-result_image = image.linear([1, 2, 3], [4, 5, 6])
-result_image = image.linear(1, [4, 5, 6])
-
-
- And so on. A set of overloads are defined for .linear(),
- see below.
-
-
-
- It does a couple of more ambitious conversions. It will
- automatically convert to and from the various vips types,
- like #VipsBlob and #VipsArrayImage. For example, you can read the
- ICC profile out of an image like this:
-
-
-profile = im.get_value("icc-profile-data")
-
-
- and profile will be a string.
-
-
-
- You can use array constants instead of images. A 2D array is simply
- changed into a one-band double image. This is handy for things like
- .erode(), for example:
-
-
-im = im.erode([[128, 255, 128],
- [255, 255, 255],
- [128, 255, 128]])
-
-
- will erode an image with a 4-connected structuring element.
-
-
-
- If an operation takes several input images, you can use a 1D array
- constant or a number constant
- for all but one of them and the wrapper will expand it
- to an image for you. For example, .ifthenelse() uses
- a condition image to pick pixels between a then and an else image:
-
-
-result_image = condition_image.ifthenelse(then_image, else_image)
-
-
- You can use a constant instead of either the then or the else
- parts, and it will be expanded to an image for you. If you use a
- constant for both then and else, it will be expanded to match the
- condition image. For example:
-
-
-result_image = condition_image.ifthenelse([0, 255, 0], [255, 0, 0])
-
-
- Will make an image where true pixels are green and false pixels
- are red.
-
-
-
- This is also useful for .bandjoin(), the thing to join
- two or more images up bandwise. You can write:
-
-
-rgba = rgb.bandjoin(255)
-
-
- to add a constant 255 band to an image, perhaps to add an alpha
- channel. Of course you can also write:
-
-
-result_image = image1.bandjoin(image2)
-result_image = image1.bandjoin([image2, image3])
-result_image = image1.bandjoin([image2, 255])
-
-
- and so on.
-
-
-
-
-
- Exceptions
-
- The wrapper spots errors from vips operations and raises the
- Vips.Error exception. You can catch it in the
- usual way. The .detail member gives the detailed
- error message.
-
-
-
-
- Reading and writing areas of memory
-
- You can use the C API functions vips_image_new_from_memory(),
- vips_image_new_from_memory_copy() and
- vips_image_write_to_memory() directly from Python to read and write
- areas of memory. This can be useful if you need to get images to and
- from other other image processing libraries, like PIL or numpy.
-
-
-
- Use them from Python like this:
-
-
-image = Vips.Image.new_from_file("/path/to/some/image/file.jpg")
-memory_area = image.write_to_memory()
-
-
- memory_area is now a string containing uncompressed binary
- image data. For an RGB image, it will have bytes
- RGBRGBRGB..., being
- the first three pixels of the first scanline of the image. You can pass
- this string to the numpy or PIL constructors and make an image there.
-
-
-
- Note that .write_to_memory() will make a copy of the image.
- It would
- be better to use a Python buffer to pass the data, but sadly this isn't
- possible with gobject-introspection, as far as I know.
-
-
-
- Going the other way, you can construct a vips image from a string of
- binary data. For example:
-
-
-image = Vips.Image.new_from_file("/path/to/some/image/file.jpg")
-memory_area = image.write_to_memory()
-image2 = Vips.Image.new_from_memory(memory_area,
- image.width, image.height, image.bands,
- Vips.BandFormat.UCHAR)
-
-
- Now image2 should be an identical copy of image.
-
-
-
- Be careful: in this direction, vips does not make a copy of the memory
- area, so if memory_area is freed by the Python garbage
- collector and
- you later try to use image2, you'll get a crash.
- Make sure you keep a reference to memory_area around
- for as long as you need it. A simple solution is to use
- new_from_memory_copy instead. This will take a copy of the
- memory area for vips. Of course this will raise memory usage.
-
-
-
-
-
- Draw operations
-
- Paint operations like draw_circle and draw_line
- modify their input image. This makes them hard to use with the rest of
- libvips: you need to be very careful about the order in which operations
- execute or you can get nasty crashes.
-
-
-
- The wrapper spots operations of this type and makes a private copy of
- the image in memory before calling the operation. This stops crashes,
- but it does make it inefficient. If you draw 100 lines on an image,
- for example, you'll copy the image 100 times. The wrapper does make sure
- that memory is recycled where possible, so you won't have 100 copies in
- memory. At least you can execute these operations.
-
-
-
- If you want to avoid the copies, you'll need to call drawing
- operations yourself.
-
-
-
-
- Overloads
-
- The wrapper defines the usual set of arithmetic, boolean and
- relational overloads on
- image. You can mix images, constants and lists of
- constants (almost) freely. For example, you can write:
-
-
-result_image = ((image * [1, 2, 3]).abs() < 128) | 4
-
-
-
-
- The wrapper overloads [] to be vips_extract_band(). You
- can write:
-
-
-result_image = image[2]
-
-
- to extract the third band of the image. It implements the usual
- slicing and negative indexes, so you can write:
-
-
-result_image = image[1:]
-result_image = image[:3]
-result_image = image[-2:]
-result_image = [x.avg() for x in image]
-
-
- and so on.
-
-
-
- The wrapper overloads () to be vips_getpoint(). You can
- write:
-
-
-r, g, b = image(10, 10)
-
-
- to read out the value of the pixel at coordinates (10, 10) from an RGB
- image.
-
-
-
-
-
- Expansions
-
- Some vips operators take an enum to select an action, for example
- .math() can be used to calculate sine of every pixel
- like this:
-
-
-result_image = image.math(Vips.OperationMath.SIN)
-
-
- This is annoying, so the wrapper expands all these enums into
- separate members named after the enum. So you can write:
-
-
-result_image = image.sin()
-
-
- See help(Vips.Image) for a list.
-
-
-
-
- Convenience functions
-
- The wrapper defines a few extra useful utility functions:
- .get_value(),
- .set_value(),
- .bandsplit(),
- .maxpos(),
- .minpos(),
- .median().
- Again, see help(Vips.Image) for a list.
-
-
-
-
- Command-line option parsing
-
- GLib includes a command-line option parser, and Vips defines a set of
- standard flags you can use with it. For example:
-
-
-import sys
-from gi.repository import GLib, Vips
-
-context = GLib.OptionContext(" - test stuff")
-main_group = GLib.OptionGroup("main",
- "Main options", "Main options for this program",
- None)
-context.set_main_group(main_group)
-Vips.add_option_entries(main_group)
-context.parse(sys.argv)
-
-
-
-
-
-