Merge branch 'affine-bug'

Conflicts:
	libvips/resample/transform.c
This commit is contained in:
John Cupitt 2014-08-01 16:35:59 +01:00
commit ecd771cde7
17 changed files with 412 additions and 1207 deletions

View File

@ -4,6 +4,9 @@
25/7/14 started 7.40.5
- fix a race in im_maxpos_avg()
- limit n_thr on tiny images
- don't exit() on memleak detected, just warn
- add "autocrop" option to openslide load
- argh fix affine, again
4/7/14 started 7.40.4
- fix vips_rawsave_fd(), thanks aferrero2707

12
TODO
View File

@ -1,3 +1,15 @@
- affine makes black lines with interp window_offset > 1, see nohalo
- experiment with size down to two sizes above in vipsthumbnail
how does this affect speed and sharpness?
- vipsthumbnail -t plus large -s seems to fail?
- bicubic adds noise to 255/255/255, why? try babe.jpg background
- vips_object_unref_outputs() needs docs ... bindings will need it
- rewrite im_conv() etc. as vips_conv()

View File

@ -2,549 +2,23 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
]>
<refentry id="glib-building">
<refentry id="binding">
<refmeta>
<refentrytitle>Compiling the GLib package</refentrytitle>
<refentrytitle>Writing bindings for libvips</refentrytitle>
<manvolnum>3</manvolnum>
<refmiscinfo>GLib Library</refmiscinfo>
<refmiscinfo>VIPS Library</refmiscinfo>
</refmeta>
<refnamediv>
<refname>Compiling the GLib Package</refname>
<refpurpose>How to compile GLib itself</refpurpose>
<refname>Binding</refname>
<refpurpose>How to write bindings for libvips</refpurpose>
</refnamediv>
<refsect1 id="building">
<title>Building the Library on UNIX</title>
<refsect1 id="binding-goi">
<title>Binding and gobject-introspection</title>
<para>
On UNIX, GLib uses the standard GNU build system,
using <application>autoconf</application> for package
configuration and resolving portability issues,
<application>automake</application> for building makefiles
that comply with the GNU Coding Standards, and
<application>libtool</application> for building shared
libraries on multiple platforms. The normal sequence for
compiling and installing the GLib library is thus:
<literallayout>
<userinput>./configure</userinput>
<userinput>make</userinput>
<userinput>make install</userinput>
</literallayout>
Stuff about goi.
</para>
<para>
The standard options provided by <application>GNU
autoconf</application> may be passed to the
<command>configure</command> script. Please see the
<application>autoconf</application> documentation or run
<command>./configure --help</command> for information about
the standard options.
</para>
<para>
The GTK+ documentation contains
<ulink url="../gtk/gtk-building.html">further details</ulink>
about the build process and ways to influence it.
</para>
</refsect1>
<refsect1 id="dependencies">
<title>Dependencies</title>
<para>
Before you can compile the GLib library, you need to have
various other tools and libraries installed on your system.
Beyond a C compiler (which must implement C90, but does not need
to implement C99), the two tools needed during the build process
(as differentiated from the tools used in when creating GLib
mentioned above such as <application>autoconf</application>) are
<command>pkg-config</command> and GNU make.
</para>
<itemizedlist>
<listitem>
<para>
<ulink url="http://www.freedesktop.org/software/pkgconfig/">pkg-config</ulink>
is a tool for tracking the compilation flags needed for
libraries that are used by the GLib library. (For each
library, a small <literal>.pc</literal> text file is
installed in a standard location that contains the compilation
flags needed for that library along with version number
information.) The version of <command>pkg-config</command>
needed to build GLib is mirrored in the
<filename>dependencies</filename> directory
on the <ulink url="ftp://ftp.gtk.org/pub/gtk/v2.2/">GTK+ FTP
site.</ulink>
</para>
</listitem>
<listitem>
<para>
The GLib Makefiles make use of several features specific to
<ulink url="http://www.gnu.org/software/make">GNU
make</ulink>, and will not build correctly with other
versions of <command>make</command>. You will need to
install it if you don't already have it on your system. (It
may be called <command>gmake</command> rather than
<command>make</command>.)
</para>
</listitem>
</itemizedlist>
<para>
A UNIX build of GLib requires that the system implements at
least the original 1990 version of POSIX. Beyond this, it
depends on a number of other libraries.
</para>
<itemizedlist>
<listitem>
<para>
The <ulink url="http://www.gnu.org/software/libiconv/">GNU
libiconv library</ulink> is needed to build GLib if your
system doesn't have the <function>iconv()</function>
function for doing conversion between character
encodings. Most modern systems should have
<function>iconv()</function>, however many older systems lack
an <function>iconv()</function> implementation. On such systems,
you must install the libiconv library. This can be found at:
<ulink url="http://www.gnu.org/software/libiconv">http://www.gnu.org/software/libiconv</ulink>.
</para>
<para>
If your system has an <function>iconv()</function> implementation but
you want to use libiconv instead, you can pass the
--with-libiconv option to configure. This forces
libiconv to be used.
</para>
<para>
Note that if you have libiconv installed in your default include
search path (for instance, in <filename>/usr/local/</filename>), but
don't enable it, you will get an error while compiling GLib because
the <filename>iconv.h</filename> that libiconv installs hides the
system iconv.
</para>
<para>
If you are using the native iconv implementation on Solaris
instead of libiconv, you'll need to make sure that you have
the converters between locale encodings and UTF-8 installed.
At a minimum you'll need the SUNWuiu8 package. You probably
should also install the SUNWciu8, SUNWhiu8, SUNWjiu8, and
SUNWkiu8 packages.
</para>
<para>
The native iconv on Compaq Tru64 doesn't contain support for
UTF-8, so you'll need to use GNU libiconv instead. (When
using GNU libiconv for GLib, you'll need to use GNU libiconv
for GNU gettext as well.) This probably applies to related
operating systems as well.
</para>
</listitem>
<listitem>
<para>
The libintl library from the <ulink
url="http://www.gnu.org/software/gettext">GNU gettext
package</ulink> is needed if your system doesn't have the
<function>gettext()</function> functionality for handling
message translation databases.
</para>
</listitem>
<listitem>
<para>
A thread implementation is needed. The thread support in GLib
can be based upon POSIX threads or win32 threads.
</para>
</listitem>
<listitem>
<para>
GRegex uses the <ulink url="http://www.pcre.org/">PCRE library</ulink>
for regular expression matching. The default is to use the internal
version of PCRE that is patched to use GLib for memory management
and Unicode handling. If you prefer to use the system-supplied PCRE
library you can pass the <option>--with-pcre=system</option> option
to, but it is not recommended.
</para>
</listitem>
<listitem>
<para>
The optional extended attribute support in GIO requires the
getxattr() family of functions that may be provided by glibc or
by the standalone libattr library. To build GLib without extended
attribute support, use the <option>--disable-xattr</option>
option.
</para>
</listitem>
<listitem>
<para>
The optional SELinux support in GIO requires libselinux.
To build GLib without SELinux support, use the
<option>--disable-selinux</option> option.
</para>
</listitem>
<listitem>
<para>
The optional support for DTrace requires the
<filename>sys/sdt.h</filename> header, which is provided
by SystemTap on Linux. To build GLib without DTrace, use
the <option>--disable-dtrace</option> configure option.
</para>
</listitem>
<listitem>
<para>
The optional support for
<ulink url="http://sourceware.org/systemtap/">SystemTap</ulink>
can be disabled with the <option>--disable-systemtap</option>
configure option.
</para>
</listitem>
</itemizedlist>
</refsect1>
<refsect1 id="extra-configuration-options">
<title>Extra Configuration Options</title>
<para>
In addition to the normal options, the
<command>configure</command> script in the GLib
library supports these additional arguments:
</para>
<formalpara>
<title><systemitem>--enable-debug</systemitem></title>
<para>
Turns on various amounts of debugging support. Setting this to 'no'
disables g_assert(), g_return_if_fail(), g_return_val_if_fail() and
all cast checks between different object types. Setting it to 'minimum' disables only cast checks. Setting it to 'yes' enables
<link linkend="G-DEBUG:CAPS">runtime debugging</link>.
The default is 'minimum'.
Note that 'no' is fast, but dangerous as it tends to destabilize
even mostly bug-free software by changing the effect of many bugs
from simple warnings into fatal crashes. Thus
<option>--enable-debug=no</option> should <emphasis>not</emphasis>
be used for stable releases of GLib.
</para>
</formalpara>
<formalpara>
<title><systemitem>--disable-gc-friendly</systemitem> and
<systemitem>--enable-gc-friendly</systemitem></title>
<para>
By default, and with <systemitem>--disable-gc-friendly</systemitem>
as well, Glib does not clear the memory for certain objects before
they are freed. For example, Glib may decide to recycle GList nodes
by putting them in a free list. However, memory profiling and debugging
tools like <ulink url="http://www.valgrind.org">Valgrind</ulink> work
better if an application does not keep dangling pointers to freed
memory (even though these pointers are no longer dereferenced), or
invalid pointers inside uninitialized memory.
The <systemitem>--enable-gc-friendly</systemitem> option makes Glib
clear memory in these situations:
</para>
<itemizedlist>
<listitem>
<para>
When shrinking a GArray, Glib will clear the memory no longer
available in the array: shrink an array from 10 bytes to 7, and
the last 3 bytes will be cleared. This includes removals of single
and multiple elements.
</para>
</listitem>
<listitem>
<para>
When growing a GArray, Glib will clear the new chunk of memory.
Grow an array from 7 bytes to 10 bytes, and the last 3 bytes will
be cleared.
</para>
</listitem>
<listitem>
<para>
The above applies to GPtrArray as well.
</para>
</listitem>
<listitem>
<para>
When freeing a node from a GHashTable, Glib will first clear
the node, which used to have pointers to the key and the value
stored at that node.
</para>
</listitem>
<listitem>
<para>
When destroying or removing a GTree node, Glib will clear the node,
which used to have pointers to the node's value, and the left and
right subnodes.
</para>
</listitem>
</itemizedlist>
<para>
Since clearing the memory has a cost,
<systemitem>--disable-gc-friendly</systemitem> is the default.
</para>
</formalpara>
<formalpara>
<title><systemitem>--disable-mem-pools</systemitem> and
<systemitem>--enable-mem-pools</systemitem></title>
<para>
Many small chunks of memory are often allocated via collective pools
in GLib and are cached after release to speed up reallocations.
For sparse memory systems this behaviour is often inferior, so
memory pools can be disabled to avoid excessive caching and force
atomic maintenance of chunks through the <function>g_malloc()</function>
and <function>g_free()</function> functions. Code currently affected by
this:
<itemizedlist>
<listitem>
<para>
<structname>GMemChunk</structname>s become basically non-effective
</para>
</listitem>
<listitem>
<para>
<structname>GSignal</structname> disables all caching
(potentially very slow)
</para>
</listitem>
<listitem>
<para>
<structname>GType</structname> doesn't honour the
<structname>GTypeInfo</structname>
<structfield>n_preallocs</structfield> field anymore
</para>
</listitem>
<listitem>
<para>
the <structname>GBSearchArray</structname> flag
<literal>G_BSEARCH_ALIGN_POWER2</literal> becomes non-functional
</para>
</listitem>
</itemizedlist>
</para>
</formalpara>
<formalpara>
<title><systemitem>--with-threads</systemitem></title>
<para>
Specify a thread implementation to use. Available options are
'posix' or 'win32'. Normally, <command>configure</command>
should be able to work out the system threads API on its own.
</para>
</formalpara>
<formalpara>
<title><systemitem>--disable-regex</systemitem> and
<systemitem>--enable-regex</systemitem></title>
<para>
Do not compile GLib with regular expression support.
GLib will be smaller because it will not need the
PCRE library. This is however not recommended, as
programs may need GRegex.
</para>
</formalpara>
<formalpara>
<title><systemitem>--with-pcre</systemitem></title>
<para>
Specify whether to use the internal or the system-supplied
PCRE library.
<itemizedlist>
<listitem>
<para>
'internal' means that GRegex will be compiled to use
the internal PCRE library.
</para>
</listitem>
<listitem>
<para>
'system' means that GRegex will be compiled to use
the system-supplied PCRE library.
</para>
</listitem>
</itemizedlist>
Using the internal PCRE is the preferred solution:
<itemizedlist>
<listitem>
<para>
System-supplied PCRE has a separated copy of the big tables
used for Unicode handling.
</para>
</listitem>
<listitem>
<para>
Some systems have PCRE libraries compiled without some needed
features, such as UTF-8 and Unicode support.
</para>
</listitem>
<listitem>
<para>
PCRE uses some global variables for memory management and
other features. In the rare case of a program using both
GRegex and PCRE (maybe indirectly through a library),
this variables could lead to problems when they are modified.
</para>
</listitem>
</itemizedlist>
</para>
</formalpara>
<formalpara>
<title><systemitem>--disable-included-printf</systemitem> and
<systemitem>--enable-included-printf</systemitem></title>
<para>
By default the <command>configure</command> script will try
to auto-detect whether the C library provides a suitable set
of printf() functions. In detail, <command>configure</command>
checks that the semantics of snprintf() are as specified by C99
and that positional parameters as specified in the Single Unix
Specification are supported. If this not the case, GLib will
include an implementation of the printf() family.
</para>
<para>
These options can be used to explicitly control whether
an implementation of the printf() family should be included or not.
</para>
</formalpara>
<formalpara>
<title><systemitem>--disable-Bsymbolic</systemitem> and
<systemitem>--enable-Bsymbolic</systemitem></title>
<para>
By default, GLib uses the -Bsymbolic-functions linker
flag to avoid intra-library PLT jumps. A side-effect
of this is that it is no longer possible to override
internal uses of GLib functions with
<envar>LD_PRELOAD</envar>. Therefore, it may make
sense to turn this feature off in some situations.
The <option>--disable-Bsymbolic</option> option allows
to do that.
</para>
</formalpara>
<formalpara>
<title><systemitem>--disable-gtk-doc</systemitem> and
<systemitem>--enable-gtk-doc</systemitem></title>
<para>
By default the <command>configure</command> script will try
to auto-detect whether the
<application>gtk-doc</application> package is installed.
If it is, then it will use it to extract and build the
documentation for the GLib library. These options
can be used to explicitly control whether
<application>gtk-doc</application> should be
used or not. If it is not used, the distributed,
pre-generated HTML files will be installed instead of
building them on your machine.
</para>
</formalpara>
<formalpara>
<title><systemitem>--disable-man</systemitem> and
<systemitem>--enable-man</systemitem></title>
<para>
By default the <command>configure</command> script will try
to auto-detect whether <application>xsltproc</application>
and the necessary Docbook stylesheets are installed.
If they are, then it will use them to rebuild the included
man pages from the XML sources. These options can be used
to explicitly control whether man pages should be rebuilt
used or not. The distribution includes pre-generated man
pages.
</para>
</formalpara>
<formalpara>
<title><systemitem>--disable-xattr</systemitem> and
<systemitem>--enable-xattr</systemitem></title>
<para>
By default the <command>configure</command> script will try
to auto-detect whether the getxattr() family of functions
is available. If it is, then extended attribute support
will be included in GIO. These options can be used to
explicitly control whether extended attribute support
should be included or not. getxattr() and friends can
be provided by glibc or by the standalone libattr library.
</para>
</formalpara>
<formalpara>
<title><systemitem>--disable-selinux</systemitem> and
<systemitem>--enable-selinux</systemitem></title>
<para>
By default the <command>configure</command> script will
auto-detect if libselinux is available and include
SELinux support in GIO if it is. These options can be
used to explicitly control whether SELinux support should
be included.
</para>
</formalpara>
<formalpara>
<title><systemitem>--disable-dtrace</systemitem> and
<systemitem>--enable-dtrace</systemitem></title>
<para>
By default the <command>configure</command> script will
detect if DTrace support is available, and use it.
</para>
</formalpara>
<formalpara>
<title><systemitem>--disable-systemtap</systemitem> and
<systemitem>--enable-systemtap</systemitem></title>
<para>
This option requires DTrace support. If it is available, then
the <command>configure</command> script will also check for
the presence of SystemTap.
</para>
</formalpara>
<formalpara>
<title><systemitem>--enable-gcov</systemitem> and
<systemitem>--disable-gcov</systemitem></title>
<para>
Enable the generation of coverage reports for the GLib tests.
This requires the lcov frontend to gcov from the
<ulink url="http://ltp.sourceforge.net">Linux Test Project</ulink>.
To generate a coverage report, use the lcov make target. The
report is placed in the <filename>glib-lcov</filename> directory.
</para>
</formalpara>
<formalpara>
<title><systemitem>--with-runtime-libdir=RELPATH</systemitem></title>
<para>
Allows specifying a relative path to where to install the runtime
libraries (meaning library files used for running, not developing,
GLib applications). This can be used in operating system setups where
programs using GLib needs to run before e.g. <filename>/usr</filename>
is mounted.
For example, if LIBDIR is <filename>/usr/lib</filename> and
<filename>../../lib</filename> is passed to
<systemitem>--with-runtime-libdir</systemitem> then the
runtime libraries are installed into <filename>/lib</filename> rather
than <filename>/usr/lib</filename>.
</para>
</formalpara>
<formalpara>
<title><systemitem>--with-python</systemitem></title>
<para>
Allows specifying the Python interpreter to use, either as an absolute path,
or as a program name. GLib can be built with Python 2 (at least version 2.5)
or Python 3.
</para>
</formalpara>
</refsect1>
</refentry>

View File

@ -2,549 +2,23 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
]>
<refentry id="glib-building">
<refentry id="extending">
<refmeta>
<refentrytitle>Compiling the GLib package</refentrytitle>
<refentrytitle>Extending VIPS</refentrytitle>
<manvolnum>3</manvolnum>
<refmiscinfo>GLib Library</refmiscinfo>
<refmiscinfo>VIPS Library</refmiscinfo>
</refmeta>
<refnamediv>
<refname>Compiling the GLib Package</refname>
<refpurpose>How to compile GLib itself</refpurpose>
<refname>Extending</refname>
<refpurpose>How to add operations to VIPS</refpurpose>
</refnamediv>
<refsect1 id="building">
<title>Building the Library on UNIX</title>
<refsect1 id="extending-subclassing">
<title>Adding operations to VIPS</title>
<para>
On UNIX, GLib uses the standard GNU build system,
using <application>autoconf</application> for package
configuration and resolving portability issues,
<application>automake</application> for building makefiles
that comply with the GNU Coding Standards, and
<application>libtool</application> for building shared
libraries on multiple platforms. The normal sequence for
compiling and installing the GLib library is thus:
<literallayout>
<userinput>./configure</userinput>
<userinput>make</userinput>
<userinput>make install</userinput>
</literallayout>
all about subclassing.
</para>
<para>
The standard options provided by <application>GNU
autoconf</application> may be passed to the
<command>configure</command> script. Please see the
<application>autoconf</application> documentation or run
<command>./configure --help</command> for information about
the standard options.
</para>
<para>
The GTK+ documentation contains
<ulink url="../gtk/gtk-building.html">further details</ulink>
about the build process and ways to influence it.
</para>
</refsect1>
<refsect1 id="dependencies">
<title>Dependencies</title>
<para>
Before you can compile the GLib library, you need to have
various other tools and libraries installed on your system.
Beyond a C compiler (which must implement C90, but does not need
to implement C99), the two tools needed during the build process
(as differentiated from the tools used in when creating GLib
mentioned above such as <application>autoconf</application>) are
<command>pkg-config</command> and GNU make.
</para>
<itemizedlist>
<listitem>
<para>
<ulink url="http://www.freedesktop.org/software/pkgconfig/">pkg-config</ulink>
is a tool for tracking the compilation flags needed for
libraries that are used by the GLib library. (For each
library, a small <literal>.pc</literal> text file is
installed in a standard location that contains the compilation
flags needed for that library along with version number
information.) The version of <command>pkg-config</command>
needed to build GLib is mirrored in the
<filename>dependencies</filename> directory
on the <ulink url="ftp://ftp.gtk.org/pub/gtk/v2.2/">GTK+ FTP
site.</ulink>
</para>
</listitem>
<listitem>
<para>
The GLib Makefiles make use of several features specific to
<ulink url="http://www.gnu.org/software/make">GNU
make</ulink>, and will not build correctly with other
versions of <command>make</command>. You will need to
install it if you don't already have it on your system. (It
may be called <command>gmake</command> rather than
<command>make</command>.)
</para>
</listitem>
</itemizedlist>
<para>
A UNIX build of GLib requires that the system implements at
least the original 1990 version of POSIX. Beyond this, it
depends on a number of other libraries.
</para>
<itemizedlist>
<listitem>
<para>
The <ulink url="http://www.gnu.org/software/libiconv/">GNU
libiconv library</ulink> is needed to build GLib if your
system doesn't have the <function>iconv()</function>
function for doing conversion between character
encodings. Most modern systems should have
<function>iconv()</function>, however many older systems lack
an <function>iconv()</function> implementation. On such systems,
you must install the libiconv library. This can be found at:
<ulink url="http://www.gnu.org/software/libiconv">http://www.gnu.org/software/libiconv</ulink>.
</para>
<para>
If your system has an <function>iconv()</function> implementation but
you want to use libiconv instead, you can pass the
--with-libiconv option to configure. This forces
libiconv to be used.
</para>
<para>
Note that if you have libiconv installed in your default include
search path (for instance, in <filename>/usr/local/</filename>), but
don't enable it, you will get an error while compiling GLib because
the <filename>iconv.h</filename> that libiconv installs hides the
system iconv.
</para>
<para>
If you are using the native iconv implementation on Solaris
instead of libiconv, you'll need to make sure that you have
the converters between locale encodings and UTF-8 installed.
At a minimum you'll need the SUNWuiu8 package. You probably
should also install the SUNWciu8, SUNWhiu8, SUNWjiu8, and
SUNWkiu8 packages.
</para>
<para>
The native iconv on Compaq Tru64 doesn't contain support for
UTF-8, so you'll need to use GNU libiconv instead. (When
using GNU libiconv for GLib, you'll need to use GNU libiconv
for GNU gettext as well.) This probably applies to related
operating systems as well.
</para>
</listitem>
<listitem>
<para>
The libintl library from the <ulink
url="http://www.gnu.org/software/gettext">GNU gettext
package</ulink> is needed if your system doesn't have the
<function>gettext()</function> functionality for handling
message translation databases.
</para>
</listitem>
<listitem>
<para>
A thread implementation is needed. The thread support in GLib
can be based upon POSIX threads or win32 threads.
</para>
</listitem>
<listitem>
<para>
GRegex uses the <ulink url="http://www.pcre.org/">PCRE library</ulink>
for regular expression matching. The default is to use the internal
version of PCRE that is patched to use GLib for memory management
and Unicode handling. If you prefer to use the system-supplied PCRE
library you can pass the <option>--with-pcre=system</option> option
to, but it is not recommended.
</para>
</listitem>
<listitem>
<para>
The optional extended attribute support in GIO requires the
getxattr() family of functions that may be provided by glibc or
by the standalone libattr library. To build GLib without extended
attribute support, use the <option>--disable-xattr</option>
option.
</para>
</listitem>
<listitem>
<para>
The optional SELinux support in GIO requires libselinux.
To build GLib without SELinux support, use the
<option>--disable-selinux</option> option.
</para>
</listitem>
<listitem>
<para>
The optional support for DTrace requires the
<filename>sys/sdt.h</filename> header, which is provided
by SystemTap on Linux. To build GLib without DTrace, use
the <option>--disable-dtrace</option> configure option.
</para>
</listitem>
<listitem>
<para>
The optional support for
<ulink url="http://sourceware.org/systemtap/">SystemTap</ulink>
can be disabled with the <option>--disable-systemtap</option>
configure option.
</para>
</listitem>
</itemizedlist>
</refsect1>
<refsect1 id="extra-configuration-options">
<title>Extra Configuration Options</title>
<para>
In addition to the normal options, the
<command>configure</command> script in the GLib
library supports these additional arguments:
</para>
<formalpara>
<title><systemitem>--enable-debug</systemitem></title>
<para>
Turns on various amounts of debugging support. Setting this to 'no'
disables g_assert(), g_return_if_fail(), g_return_val_if_fail() and
all cast checks between different object types. Setting it to 'minimum' disables only cast checks. Setting it to 'yes' enables
<link linkend="G-DEBUG:CAPS">runtime debugging</link>.
The default is 'minimum'.
Note that 'no' is fast, but dangerous as it tends to destabilize
even mostly bug-free software by changing the effect of many bugs
from simple warnings into fatal crashes. Thus
<option>--enable-debug=no</option> should <emphasis>not</emphasis>
be used for stable releases of GLib.
</para>
</formalpara>
<formalpara>
<title><systemitem>--disable-gc-friendly</systemitem> and
<systemitem>--enable-gc-friendly</systemitem></title>
<para>
By default, and with <systemitem>--disable-gc-friendly</systemitem>
as well, Glib does not clear the memory for certain objects before
they are freed. For example, Glib may decide to recycle GList nodes
by putting them in a free list. However, memory profiling and debugging
tools like <ulink url="http://www.valgrind.org">Valgrind</ulink> work
better if an application does not keep dangling pointers to freed
memory (even though these pointers are no longer dereferenced), or
invalid pointers inside uninitialized memory.
The <systemitem>--enable-gc-friendly</systemitem> option makes Glib
clear memory in these situations:
</para>
<itemizedlist>
<listitem>
<para>
When shrinking a GArray, Glib will clear the memory no longer
available in the array: shrink an array from 10 bytes to 7, and
the last 3 bytes will be cleared. This includes removals of single
and multiple elements.
</para>
</listitem>
<listitem>
<para>
When growing a GArray, Glib will clear the new chunk of memory.
Grow an array from 7 bytes to 10 bytes, and the last 3 bytes will
be cleared.
</para>
</listitem>
<listitem>
<para>
The above applies to GPtrArray as well.
</para>
</listitem>
<listitem>
<para>
When freeing a node from a GHashTable, Glib will first clear
the node, which used to have pointers to the key and the value
stored at that node.
</para>
</listitem>
<listitem>
<para>
When destroying or removing a GTree node, Glib will clear the node,
which used to have pointers to the node's value, and the left and
right subnodes.
</para>
</listitem>
</itemizedlist>
<para>
Since clearing the memory has a cost,
<systemitem>--disable-gc-friendly</systemitem> is the default.
</para>
</formalpara>
<formalpara>
<title><systemitem>--disable-mem-pools</systemitem> and
<systemitem>--enable-mem-pools</systemitem></title>
<para>
Many small chunks of memory are often allocated via collective pools
in GLib and are cached after release to speed up reallocations.
For sparse memory systems this behaviour is often inferior, so
memory pools can be disabled to avoid excessive caching and force
atomic maintenance of chunks through the <function>g_malloc()</function>
and <function>g_free()</function> functions. Code currently affected by
this:
<itemizedlist>
<listitem>
<para>
<structname>GMemChunk</structname>s become basically non-effective
</para>
</listitem>
<listitem>
<para>
<structname>GSignal</structname> disables all caching
(potentially very slow)
</para>
</listitem>
<listitem>
<para>
<structname>GType</structname> doesn't honour the
<structname>GTypeInfo</structname>
<structfield>n_preallocs</structfield> field anymore
</para>
</listitem>
<listitem>
<para>
the <structname>GBSearchArray</structname> flag
<literal>G_BSEARCH_ALIGN_POWER2</literal> becomes non-functional
</para>
</listitem>
</itemizedlist>
</para>
</formalpara>
<formalpara>
<title><systemitem>--with-threads</systemitem></title>
<para>
Specify a thread implementation to use. Available options are
'posix' or 'win32'. Normally, <command>configure</command>
should be able to work out the system threads API on its own.
</para>
</formalpara>
<formalpara>
<title><systemitem>--disable-regex</systemitem> and
<systemitem>--enable-regex</systemitem></title>
<para>
Do not compile GLib with regular expression support.
GLib will be smaller because it will not need the
PCRE library. This is however not recommended, as
programs may need GRegex.
</para>
</formalpara>
<formalpara>
<title><systemitem>--with-pcre</systemitem></title>
<para>
Specify whether to use the internal or the system-supplied
PCRE library.
<itemizedlist>
<listitem>
<para>
'internal' means that GRegex will be compiled to use
the internal PCRE library.
</para>
</listitem>
<listitem>
<para>
'system' means that GRegex will be compiled to use
the system-supplied PCRE library.
</para>
</listitem>
</itemizedlist>
Using the internal PCRE is the preferred solution:
<itemizedlist>
<listitem>
<para>
System-supplied PCRE has a separated copy of the big tables
used for Unicode handling.
</para>
</listitem>
<listitem>
<para>
Some systems have PCRE libraries compiled without some needed
features, such as UTF-8 and Unicode support.
</para>
</listitem>
<listitem>
<para>
PCRE uses some global variables for memory management and
other features. In the rare case of a program using both
GRegex and PCRE (maybe indirectly through a library),
this variables could lead to problems when they are modified.
</para>
</listitem>
</itemizedlist>
</para>
</formalpara>
<formalpara>
<title><systemitem>--disable-included-printf</systemitem> and
<systemitem>--enable-included-printf</systemitem></title>
<para>
By default the <command>configure</command> script will try
to auto-detect whether the C library provides a suitable set
of printf() functions. In detail, <command>configure</command>
checks that the semantics of snprintf() are as specified by C99
and that positional parameters as specified in the Single Unix
Specification are supported. If this not the case, GLib will
include an implementation of the printf() family.
</para>
<para>
These options can be used to explicitly control whether
an implementation of the printf() family should be included or not.
</para>
</formalpara>
<formalpara>
<title><systemitem>--disable-Bsymbolic</systemitem> and
<systemitem>--enable-Bsymbolic</systemitem></title>
<para>
By default, GLib uses the -Bsymbolic-functions linker
flag to avoid intra-library PLT jumps. A side-effect
of this is that it is no longer possible to override
internal uses of GLib functions with
<envar>LD_PRELOAD</envar>. Therefore, it may make
sense to turn this feature off in some situations.
The <option>--disable-Bsymbolic</option> option allows
to do that.
</para>
</formalpara>
<formalpara>
<title><systemitem>--disable-gtk-doc</systemitem> and
<systemitem>--enable-gtk-doc</systemitem></title>
<para>
By default the <command>configure</command> script will try
to auto-detect whether the
<application>gtk-doc</application> package is installed.
If it is, then it will use it to extract and build the
documentation for the GLib library. These options
can be used to explicitly control whether
<application>gtk-doc</application> should be
used or not. If it is not used, the distributed,
pre-generated HTML files will be installed instead of
building them on your machine.
</para>
</formalpara>
<formalpara>
<title><systemitem>--disable-man</systemitem> and
<systemitem>--enable-man</systemitem></title>
<para>
By default the <command>configure</command> script will try
to auto-detect whether <application>xsltproc</application>
and the necessary Docbook stylesheets are installed.
If they are, then it will use them to rebuild the included
man pages from the XML sources. These options can be used
to explicitly control whether man pages should be rebuilt
used or not. The distribution includes pre-generated man
pages.
</para>
</formalpara>
<formalpara>
<title><systemitem>--disable-xattr</systemitem> and
<systemitem>--enable-xattr</systemitem></title>
<para>
By default the <command>configure</command> script will try
to auto-detect whether the getxattr() family of functions
is available. If it is, then extended attribute support
will be included in GIO. These options can be used to
explicitly control whether extended attribute support
should be included or not. getxattr() and friends can
be provided by glibc or by the standalone libattr library.
</para>
</formalpara>
<formalpara>
<title><systemitem>--disable-selinux</systemitem> and
<systemitem>--enable-selinux</systemitem></title>
<para>
By default the <command>configure</command> script will
auto-detect if libselinux is available and include
SELinux support in GIO if it is. These options can be
used to explicitly control whether SELinux support should
be included.
</para>
</formalpara>
<formalpara>
<title><systemitem>--disable-dtrace</systemitem> and
<systemitem>--enable-dtrace</systemitem></title>
<para>
By default the <command>configure</command> script will
detect if DTrace support is available, and use it.
</para>
</formalpara>
<formalpara>
<title><systemitem>--disable-systemtap</systemitem> and
<systemitem>--enable-systemtap</systemitem></title>
<para>
This option requires DTrace support. If it is available, then
the <command>configure</command> script will also check for
the presence of SystemTap.
</para>
</formalpara>
<formalpara>
<title><systemitem>--enable-gcov</systemitem> and
<systemitem>--disable-gcov</systemitem></title>
<para>
Enable the generation of coverage reports for the GLib tests.
This requires the lcov frontend to gcov from the
<ulink url="http://ltp.sourceforge.net">Linux Test Project</ulink>.
To generate a coverage report, use the lcov make target. The
report is placed in the <filename>glib-lcov</filename> directory.
</para>
</formalpara>
<formalpara>
<title><systemitem>--with-runtime-libdir=RELPATH</systemitem></title>
<para>
Allows specifying a relative path to where to install the runtime
libraries (meaning library files used for running, not developing,
GLib applications). This can be used in operating system setups where
programs using GLib needs to run before e.g. <filename>/usr</filename>
is mounted.
For example, if LIBDIR is <filename>/usr/lib</filename> and
<filename>../../lib</filename> is passed to
<systemitem>--with-runtime-libdir</systemitem> then the
runtime libraries are installed into <filename>/lib</filename> rather
than <filename>/usr/lib</filename>.
</para>
</formalpara>
<formalpara>
<title><systemitem>--with-python</systemitem></title>
<para>
Allows specifying the Python interpreter to use, either as an absolute path,
or as a program name. GLib can be built with Python 2 (at least version 2.5)
or Python 3.
</para>
</formalpara>
</refsect1>
</refentry>

View File

@ -21,27 +21,41 @@
docs for full details, but this section will try to give a brief
overview. The <command>vips</command> program is handy for getting a
summary of an operation's parameters.
</para>
<para>
When your program starts, use <function>vips_init()</function> to set up
the VIPS library. You should pass it the name of your program, usually
<literal>argv[0]</literal>. Use <function>vips_shutdown()</function>
when you exit.
</para>
<para>
You can add the VIPS flags to your GObject command-line processing
with vips_get_option_group(), see below.
</para>
The basic data object is #VipsImage. You can create an image from a
file on disc or from an area of memory, either as a C-style array,
or as a formatted object, like JPEG. See vips_image_new_from_file() and
friends.
Loading an image is fast. VIPS read just enough of the image to be able
to get the various properties, such as width in pixels. It delays
reading any pixels until they are really needed.
<para>
The basic data object is the #VipsImage, see <link
linkend="VipsImage">VIPS Image</link> for details on the
image class. You can create an image from a file on disc or from an
area of memory, either as a C-style array, or as a formatted object,
like JPEG. See vips_image_new_from_file() and friends. Loading an
image is fast. VIPS read just enough of the image to be able to get
the various properties, such as width in pixels. It delays reading
any pixels until they are really needed.
</para>
<para>
Once you have an image, you can get properties from it in the usual way.
You can use projection functions like vips_image_get_width(), or
g_object_get() to get GObject properties.
You can use projection functions, like vips_image_get_width() or
g_object_get(), to get GObject properties. All VIPS objects are
immutable, meaning you can only get properties, you can't set them.
See <link linkend="libvips-header">VIPS Header</link> to read about
image properties.
</para>
<para>
VIPS is based on the GObject library and is therefore refcounted.
vips_image_new_from_file() returns an object with a count of 1.
When you are done with an image, use g_object_unref() to dispose of it.
@ -49,25 +63,89 @@
copy of the image, it will ref it. So you can unref an image as soon as
you no longer need it, you don't need to hang on to it in case anyone
else is still using it.
VIPS images are three-dimensional arrays, the dimensions being width,
height and bands. Each dimension can be up to 2 ** 31 pixels (or band
elements). An image has a format, meaning the machine number type used
to represent each value. VIPS supports 10 formats, from 8-bit unsigned
integer up to 128-bit double complex, see #VipsBandFormat.
In VIPS, images are uninterpreted arrays, meaning that from the point of
view of most operations, they are just large collections of numbers.
There's no difference between an RGBA (RGB with alpha) image and a CMYK
image, for example, they are both just four-band images. It's up to the
user of the library to pass the right sort of image to each operation.
To take an example, VIPS has vips_Lab2XYZ(), an operation to transform
an image from CIE LAB colour space to CIE XYZ space. It assumes the
first three bands represent pixels in LAB colour space and returns an
image where the first three bands
</para>
<para>
Use things like vips_invert() to manipulate your images. See <link
linkend="VipsOperation">VIPS Operations</link> for information on
running operations on images. When you are done, you can write
the final image to a disc file, to a formatted memory buffer, or to
C-style memory array. See vips_image_write_to_file() and friends.
</para>
<para>
VIPS keeps a log of error message, see <link
linkend="libvips-error">VIPS Error</link> to find out how to get and
set the error log.
</para>
<example>
<title>VIPS from C example</title>
<programlisting language="C">
/* compile with:
*
* gcc -g -Wall try211.c `pkg-config vips --cflags --libs`
*/
#include &lt;stdio.h&gt;
#include &lt;vips/vips.h&gt;
int
main( int argc, char **argv )
{
GOptionContext *context;
GOptionGroup *main_group;
GError *error = NULL;
VipsImage *in;
double mean;
VipsImage *out;
if( vips_init( argv[0] ) )
vips_error_exit( NULL );
context = g_option_context_new( "hello infile outfile - VIPS demo" );
main_group = g_option_group_new( NULL, NULL, NULL, NULL, NULL );
g_option_context_set_main_group( context, main_group );
g_option_context_add_group( context, vips_get_option_group() );
if( !g_option_context_parse( context, &amp;argc, &amp;argv, &amp;error ) ) {
if( error ) {
fprintf( stderr, "%s\n", error-&gt;message );
g_error_free( error );
}
vips_error_exit( NULL );
}
if( argc != 3 )
vips_error_exit( "usage: %s infile outfile", argv[0] );
if( !(in = vips_image_new_from_file( argv[1], NULL )) )
vips_error_exit( NULL );
printf( "image width = %d\n", vips_image_get_width( in ) );
if( vips_avg( in, &amp;mean, NULL ) )
vips_error_exit( NULL );
printf( "mean pixel value = %g\n", mean );
if( vips_invert( in, &amp;out, NULL ) )
vips_error_exit( NULL );
g_object_unref( in );
if( vips_image_write_to_file( out, argv[2], NULL ) )
vips_error_exit( NULL );
g_object_unref( out );
return( 0 );
}
</programlisting>
</example>
</refsect1>
</refentry>

View File

@ -76,7 +76,7 @@ typedef struct _VipsBuildlut {
int xlow; /* Index 0 in output is this x */
int lut_size; /* Number of output elements to generate */
double **data; /* Matrix row pointers */
double *buf; /* Ouput buffer */
double *buf; /* Output buffer */
} VipsBuildlut;
typedef VipsCreateClass VipsBuildlutClass;

View File

@ -2307,6 +2307,7 @@ vips_openexrload( const char *filename, VipsImage **out, ... )
*
* @level: load this level
* @associated: load this associated image
* @autocrop: crop to image bounds
*
* Read a virtual slide supported by the OpenSlide library into a VIPS image.
* OpenSlide supports images in Aperio, Hamamatsu, MIRAX, Sakura, Trestle,
@ -2324,8 +2325,7 @@ vips_openexrload( const char *filename, VipsImage **out, ... )
* A slide's associated images are listed in the
* "slide-associated-images" metadata item.
*
* The output of this operator is in pre-multipled ARGB format. Use
* im_argb2rgba() to decode to png-style RGBA.
* The output of this operator is always RGBA.
*
* See also: vips_image_new_from_file().
*

View File

@ -41,6 +41,8 @@
* - always output solid (not transparent) pixels
* 25/1/14
* - use openslide_detect_vendor() on >= 3.4.0
* 30/7/14
* - add autocrop toggle
*/
/*
@ -92,6 +94,11 @@ typedef struct {
char *associated;
/* Crop to image bounds if @autocrop is set.
*/
gboolean autocrop;
VipsRect bounds;
/* Only valid if associated == NULL.
*/
int32_t level;
@ -178,9 +185,39 @@ check_associated_image( openslide_t *osr, const char *name )
return( -1 );
}
static gboolean
get_bounds( openslide_t *osr, VipsRect *rect )
{
static const char *openslide_names[] = {
"openslide.bounds-x",
"openslide.bounds-y",
"openslide.bounds-width",
"openslide.bounds-height"
};
static int vips_offsets[] = {
G_STRUCT_OFFSET( VipsRect, left ),
G_STRUCT_OFFSET( VipsRect, top ),
G_STRUCT_OFFSET( VipsRect, width ),
G_STRUCT_OFFSET( VipsRect, height )
};
const char *value;
int i;
for( i = 0; i < 4; i++ ) {
if( !(value = openslide_get_property_value( osr,
openslide_names[i] )) )
return( FALSE );
G_STRUCT_MEMBER( int, rect, vips_offsets[i] ) =
atoi( value );
}
return( TRUE );
}
static ReadSlide *
readslide_new( const char *filename, VipsImage *out,
int level, const char *associated )
int level, gboolean autocrop, const char *associated )
{
ReadSlide *rslide;
int64_t w, h;
@ -188,7 +225,8 @@ readslide_new( const char *filename, VipsImage *out,
const char *background;
const char * const *properties;
if( level && associated ) {
if( level &&
associated ) {
vips_error( "openslide2vips",
"%s", _( "specify only one of level or associated "
"image" ) );
@ -201,6 +239,7 @@ readslide_new( const char *filename, VipsImage *out,
rslide );
rslide->level = level;
rslide->autocrop = autocrop;
rslide->associated = g_strdup( associated );
/* Non-crazy defaults, override below if we can.
@ -264,6 +303,39 @@ readslide_new( const char *filename, VipsImage *out,
rslide->tile_height = atoi( value );
if( value )
VIPS_DEBUG_MSG( "readslide_new: found tile-size\n" );
/* Some images have a bounds in the header. Crop to
* that if autocrop is set.
*/
if( rslide->autocrop )
if( !get_bounds( rslide->osr, &rslide->bounds ) )
rslide->autocrop = FALSE;
if( rslide->autocrop ) {
VipsRect image;
rslide->bounds.left /= rslide->downsample;
rslide->bounds.top /= rslide->downsample;
rslide->bounds.width /= rslide->downsample;
rslide->bounds.height /= rslide->downsample;
/* Clip against image size.
*/
image.left = 0;
image.top = 0;
image.width = w;
image.height = h;
vips_rect_intersectrect( &rslide->bounds, &image,
&rslide->bounds );
/* If we've clipped to nothing, ignore bounds.
*/
if( vips_rect_isempty( &rslide->bounds ) )
rslide->autocrop = FALSE;
}
if( rslide->autocrop ) {
w = rslide->bounds.width;
h = rslide->bounds.height;
}
}
rslide->bg = 0xffffff;
@ -271,7 +343,9 @@ readslide_new( const char *filename, VipsImage *out,
OPENSLIDE_PROPERTY_NAME_BACKGROUND_COLOR )) )
rslide->bg = strtoul( background, NULL, 16 );
if( w < 0 || h < 0 || rslide->downsample < 0 ) {
if( w <= 0 ||
h <= 0 ||
rslide->downsample < 0 ) {
vips_error( "openslide2vips", _( "getting dimensions: %s" ),
openslide_get_error( rslide->osr ) );
return( NULL );
@ -283,6 +357,13 @@ readslide_new( const char *filename, VipsImage *out,
return( NULL );
}
if( !rslide->autocrop ) {
rslide->bounds.left = 0;
rslide->bounds.top = 0;
rslide->bounds.width = w;
rslide->bounds.height = h;
}
vips_image_init_fields( out, w, h, 4, VIPS_FORMAT_UCHAR,
VIPS_CODING_NONE, VIPS_INTERPRETATION_RGB, 1.0, 1.0 );
@ -301,9 +382,9 @@ readslide_new( const char *filename, VipsImage *out,
int
vips__openslide_read_header( const char *filename, VipsImage *out,
int level, char *associated )
int level, gboolean autocrop, char *associated )
{
if( !readslide_new( filename, out, level, associated ) )
if( !readslide_new( filename, out, level, autocrop, associated ) )
return( -1 );
return( 0 );
@ -340,8 +421,8 @@ vips__openslide_generate( VipsRegion *out,
openslide_read_region( rslide->osr,
buf,
r->left * rslide->downsample,
r->top * rslide->downsample,
(r->left + rslide->bounds.left) * rslide->downsample,
(r->top + rslide->bounds.top) * rslide->downsample,
rslide->level,
r->width, r->height );
@ -391,7 +472,8 @@ vips__openslide_generate( VipsRegion *out,
}
int
vips__openslide_read( const char *filename, VipsImage *out, int level )
vips__openslide_read( const char *filename, VipsImage *out,
int level, gboolean autocrop )
{
ReadSlide *rslide;
VipsImage *raw;
@ -403,7 +485,8 @@ vips__openslide_read( const char *filename, VipsImage *out, int level )
raw = vips_image_new();
vips_object_local( out, raw );
if( !(rslide = readslide_new( filename, raw, level, NULL )) )
if( !(rslide = readslide_new( filename, raw,
level, autocrop, NULL )) )
return( -1 );
if( vips_image_generate( raw,
@ -446,7 +529,7 @@ vips__openslide_read_associated( const char *filename, VipsImage *out,
raw = vips_image_new_memory();
vips_object_local( out, raw );
if( !(rslide = readslide_new( filename, raw, 0, associated )) ||
if( !(rslide = readslide_new( filename, raw, 0, FALSE, associated )) ||
vips_image_write_prepare( raw ) )
return( -1 );
openslide_read_associated_image( rslide->osr, rslide->associated,

View File

@ -37,9 +37,9 @@ extern "C" {
int vips__openslide_isslide( const char *filename );
int vips__openslide_read_header( const char *filename, VipsImage *out,
int level, char *associated );
int level, gboolean autocrop, char *associated );
int vips__openslide_read( const char *filename, VipsImage *out,
int level );
int level, gboolean autocrop );
int vips__openslide_read_associated( const char *filename, VipsImage *out,
const char *associated );

View File

@ -70,6 +70,10 @@ typedef struct _VipsForeignLoadOpenslide {
*/
int level;
/* Crop to image bounds.
*/
gboolean autocrop;
/* Load this associated image.
*/
char *associated;
@ -109,7 +113,8 @@ vips_foreign_load_openslide_header( VipsForeignLoad *load )
VipsForeignLoadOpenslide *openslide = (VipsForeignLoadOpenslide *) load;
if( vips__openslide_read_header( openslide->filename, load->out,
openslide->level, openslide->associated ) )
openslide->level, openslide->autocrop,
openslide->associated ) )
return( -1 );
VIPS_SETSTR( load->out->filename, openslide->filename );
@ -124,7 +129,7 @@ vips_foreign_load_openslide_load( VipsForeignLoad *load )
if( !openslide->associated ) {
if( vips__openslide_read( openslide->filename, load->real,
openslide->level ) )
openslide->level, openslide->autocrop ) )
return( -1 );
}
else {
@ -190,7 +195,14 @@ vips_foreign_load_openslide_class_init( VipsForeignLoadOpenslideClass *class )
G_STRUCT_OFFSET( VipsForeignLoadOpenslide, level ),
0, 100000, 0 );
VIPS_ARG_STRING( class, "associated", 11,
VIPS_ARG_BOOL( class, "autocrop", 11,
_( "Autocrop" ),
_( "Crop to image bounds" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadOpenslide, autocrop ),
FALSE );
VIPS_ARG_STRING( class, "associated", 12,
_( "Associated" ),
_( "Load this associated image" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,

View File

@ -254,7 +254,7 @@ vips_invfft_class_init( VipsInvfftClass *class )
VIPS_ARG_BOOL( class, "real", 4,
_( "Real" ),
_( "Ouput only the real part of the transform" ),
_( "Output only the real part of the transform" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsInvfft, real ),
FALSE );

View File

@ -582,7 +582,10 @@ vips_buffer_print( VipsBuffer *buffer )
static void
vips__buffer_init_cb( VipsBufferThread *buffer_thread )
{
vips_error_exit( "vips_thread_shutdown() not called for thread %p",
/* This is a mem leak, not catastrophic.
*/
vips_warn( "VipsBuffer",
_( "vips_thread_shutdown() not called for thread %p" ),
g_thread_self() );
}

View File

@ -130,7 +130,9 @@ vips_thread_profile_save( VipsThreadProfile *profile )
vips__file_open_write( "vips-profile.txt", TRUE );
if( !vips__thread_fp ) {
g_mutex_unlock( vips__global_lock );
vips_error_exit( "unable to create profile log" );
vips_warn( "VipsGate",
"%s", "unable to create profile log" );
return;
}
printf( "recording profile in vips-profile.txt\n" );
@ -192,7 +194,8 @@ vips__thread_profile_init_cb( VipsThreadProfile *profile )
* We can't do the freeing in this callback since GPrivate has already
* stopped working.
*/
vips_error_exit( "vips_thread_shutdown() not called for thread %p",
vips_warn( "VipsBuffer",
_( "vips_thread_shutdown() not called for thread %p" ),
g_thread_self() );
}

View File

@ -63,9 +63,45 @@
*
* The image class and associated types and macros.
*
* Images can be created from files on disc (with vips_image_new_from_file()),
* from formatted buffers held in memory (with vips_image_new_from_buffer()),
* and from C-style arrays held in memory (with vips_image_new_from_memory()).
* Images can be created from formatted files on disc, from C-style arrays on
* disc, from formatted areas of memory, or from C-style arrays in memory. See
* vips_image_new_from_file() and friends.
* Creating an image is fast. VIPS reads just enough of
* the image to be able to get the various properties, such as width in
* pixels. It delays reading any pixels until they are really needed.
*
* Once you have an image, you can get properties from it in the usual way.
* You can use projection functions, like vips_image_get_width() or
* g_object_get(), to get %GObject properties.
*
* VIPS images are three-dimensional arrays, the dimensions being width,
* height and bands. Each dimension can be up to 2 ** 31 pixels (or band
* elements). An image has a format, meaning the machine number type used
* to represent each value. VIPS supports 10 formats, from 8-bit unsigned
* integer up to 128-bit double complex, see vips_image_get_format()..
*
* In VIPS, images are uninterpreted arrays, meaning that from the point of
* view of most operations, they are just large collections of numbers.
* There's no difference between an RGBA (RGB with alpha) image and a CMYK
* image, for example, they are both just four-band images. It's up to the
* user of the library to pass the right sort of image to each operation.
*
* To take an example, VIPS has vips_Lab2XYZ(), an operation to transform
* an image from CIE LAB colour space to CIE XYZ space. It assumes the
* first three bands represent pixels in LAB colour space and returns an
* image where the first three bands are transformed to XYZ and any
* remaining bands are just copied. Pass it a RGB image by mistake and
* you'll just get nonsense.
*
* VIPS has a feature to help (a little) with this: it sets a
* #VipsInterpretation hint for each image (see
* vips_image_get_interpretation()); a hint which says how pixels should
* probably be interpreted. For example, vips_Lab2XYZ() will set the
* interpretation of the output image to #VIPS_INTERPRETATION_XYZ. A
* few utility operations will also use interpretation as a guide. For
* example, you can give vips_colourspace() an input image and a desired
* colourspace and it will use the input's interpretation hint to apply
* the best sequence of colourspace transforms to get to the desired space.
*
* Use things like vips_invert() to manipulate your images. When you are done,
* you can write images to disc files (with vips_image_write_to_file()),
@ -77,7 +113,6 @@
* linkend="libvips-header">header</link> for getting and setting image
* metadata. See <link linkend="VipsObject">object</link> for a discussion of
* the lower levels.
*
*/
/**
@ -674,10 +709,6 @@ vips_image_rewind( VipsObject *object )
/* Delayed save.
*/
/* If we write to (eg.) TIFF, actually do the write
* to a "p" and on "written" do im_vips2tiff() or whatever.
*/
/* From "written" callback: save to image->filename using VipsForeign.
*/
static void
@ -1067,10 +1098,10 @@ vips_image_class_init( VipsImageClass *class )
* can't :-(
*
* For example, a "p" image might be made with vips_image_new() and
* constructed, then passed to im_copy() of whatever to be written to.
* constructed, then passed to vips_copy() of whatever to be written to.
* That operation will then need to set width/height etc.
*
* We can't set_once either, since im_copy_set() etc. need to update
* We can't set_once either, since vips_copy() etc. need to update
* xoffset and friends on the way through.
*/
@ -2286,10 +2317,10 @@ vips_image_write_to_memory( VipsImage *in, void **buf_out, size_t *len_out )
len = VIPS_IMAGE_SIZEOF_IMAGE( in );
if( !(buf = g_try_malloc( len )) ) {
vips_error( "vips_image_write_to_buffer",
vips_error( "vips_image_write_to_memory",
_( "out of memory --- size == %dMB" ),
(int) (len / (1024.0 * 1024.0)) );
vips_warn( "vips_image_write_to_buffer",
vips_warn( "vips_image_write_to_memory",
_( "out of memory --- size == %dMB" ),
(int) (len / (1024.0*1024.0)) );
return( -1 );
@ -2990,7 +3021,7 @@ vips_image_pio_output( VipsImage *image )
case VIPS_IMAGE_PARTIAL:
if( image->generate_fn ) {
vips_error( "im_poutcheck",
vips_error( "vips_image_pio_output",
"%s", _( "image already written" ) );
return( -1 );
}

View File

@ -419,6 +419,9 @@ vips_vsnprintf( char *str, size_t size, const char *format, va_list ap )
int n;
static char buf[MAX_BUF];
/* We can't return an error code, we may already have trashed the
* stack. We must stop immediately.
*/
if( size > MAX_BUF )
vips_error_exit( "panic: buffer overflow "
"(request to write %d bytes to buffer of %d bytes)",

View File

@ -81,6 +81,9 @@
* - added input space translation
* 22/1/14
* - auto RAD decode
* 1/8/14
* - revise transform ... again
* - see new stress test in nip2/test/extras
*/
/*
@ -111,6 +114,7 @@
*/
/*
#define DEBUG_VERBOSE
#define DEBUG
*/
@ -177,11 +181,12 @@ G_DEFINE_TYPE( VipsAffine, vips_affine, VIPS_TYPE_RESAMPLE );
/* We have five (!!) coordinate systems. Working forward through them, these
* are:
*
* 1. The original input image
* 1. The original input image. iarea is defined on this image.
*
* 2. This is embedded in a larger image to provide borders for the
* interpolator. iarea->left/top give the offset. These are the coordinates we
* pass to VIPS_REGION_ADDR()/vips_region_prepare() for the input image.
* interpolator. window_offset and window_size control the embedding.
* These are the coordinates we pass to VIPS_REGION_ADDR()/
* vips_region_prepare() and the interpolator.
*
* The borders are sized by the interpolator's window_size property and offset
* by the interpolator's window_offset property. For example,
@ -194,7 +199,7 @@ G_DEFINE_TYPE( VipsAffine, vips_affine, VIPS_TYPE_RESAMPLE );
* 3. We need point (0, 0) in (1) to be at (0, 0) for the transformation. So
* shift everything up and left to make the displaced input image. This is the
* space that the transformation maps from, and can have negative pixels
* (up and left of the image, for interpolation).
* (up and left of the image, for interpolation). iarea works here too.
*
* 4. Output transform space. This is the where the transform maps to. Pixels
* can be negative, since a rotated image can go up and left of the origin.
@ -233,21 +238,23 @@ vips_affine_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop )
VipsRect image, want, need, clipped;
#ifdef DEBUG
printf( "affine: generating left=%d, top=%d, width=%d, height=%d\n",
#ifdef DEBUG_VERBOSE
printf( "vips_affine_gen: "
"generating left=%d, top=%d, width=%d, height=%d\n",
r->left,
r->top,
r->width,
r->height );
#endif /*DEBUG*/
#endif /*DEBUG_VERBOSE*/
/* We are generating this chunk of the transformed image.
/* We are generating this chunk of the transformed image. This takes
* us to space 4.
*/
want = *r;
want.left += oarea->left;
want.top += oarea->top;
/* Find the area of the input image we need.
/* Find the area of the input image we need. This takes us to space 3.
*/
vips__transform_invert_rect( &affine->trn, &want, &need );
@ -260,17 +267,18 @@ vips_affine_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop )
*/
vips_rect_marginadjust( &need, 1 );
/* Now go to space (2) above.
*/
need.left += iarea->left;
need.top += iarea->top;
/* Add a border for interpolation.
/* We need to fetch a larger area for the interpolator.
*/
need.left -= window_offset;
need.top -= window_offset;
need.width += window_size - 1;
need.height += window_size - 1;
need.left -= window_offset;
need.top -= window_offset;
/* Now go to space 2, the expanded input image. This is the one we
* read pixels from.
*/
need.left += window_offset;
need.top += window_offset;
/* Clip against the size of (2).
*/
@ -280,38 +288,34 @@ vips_affine_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop )
image.height = in->Ysize;
vips_rect_intersectrect( &need, &image, &clipped );
/* Outside input image? All black.
*/
if( vips_rect_isempty( &clipped ) ) {
vips_region_black( or );
return( 0 );
}
/* We do need some pixels from the input image to make our output -
* ask for them.
*/
if( vips_region_prepare( ir, &clipped ) )
return( -1 );
#ifdef DEBUG
printf( "affine: preparing left=%d, top=%d, width=%d, height=%d\n",
#ifdef DEBUG_VERBOSE
printf( "vips_affine_gen: "
"preparing left=%d, top=%d, width=%d, height=%d\n",
clipped.left,
clipped.top,
clipped.width,
clipped.height );
#endif /*DEBUG*/
#endif /*DEBUG_VERBOSE*/
if( vips_rect_isempty( &clipped ) ) {
vips_region_black( or );
return( 0 );
}
if( vips_region_prepare( ir, &clipped ) )
return( -1 );
VIPS_GATE_START( "vips_affine_gen: work" );
/* Resample! x/y loop over pixels in the output image (5).
*/
for( y = to; y < bo; y++ ) {
/* Input clipping rectangle.
/* Input clipping rectangle. We offset this so we can clip in
* space 2.
*/
const int ile = iarea->left;
const int ito = iarea->top;
const int iri = iarea->left + iarea->width;
const int ibo = iarea->top + iarea->height;
const int ile = iarea->left + window_offset;
const int ito = iarea->top + window_offset;
const int iri = ile + iarea->width;
const int ibo = ito + iarea->height;
/* Derivative of matrix.
*/
@ -334,16 +338,16 @@ vips_affine_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop )
ix = affine->trn.ia * ox + affine->trn.ib * oy;
iy = affine->trn.ic * ox + affine->trn.id * oy;
/* Now move to (2).
*/
ix += iarea->left;
iy += iarea->top;
/* And the input offset.
/* And the input offset in (3).
*/
ix -= affine->trn.idx;
iy -= affine->trn.idy;
/* Finally to 2.
*/
ix += window_offset;
iy += window_offset;
q = VIPS_REGION_ADDR( or, le, y );
for( x = le; x < ri; x++ ) {
@ -352,19 +356,31 @@ vips_affine_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop )
fx = FAST_PSEUDO_FLOOR( ix );
fy = FAST_PSEUDO_FLOOR( iy );
/* Clipping!
/* Clip against iarea.
*/
if( fx < ile ||
fx > iri ||
fy < ito ||
fy > ibo ) {
for( z = 0; z < ps; z++ )
q[z] = 0;
}
else {
if( fx >= ile &&
fx < iri &&
fy >= ito &&
fy < ibo ) {
/* Verify that we can read the whole stencil.
* With DEBUG on this will range-check.
*/
g_assert( VIPS_REGION_ADDR( ir,
(int) ix - window_offset,
(int) iy - window_offset ) );
g_assert( VIPS_REGION_ADDR( ir,
(int) ix - window_offset +
window_size - 1,
(int) iy - window_offset +
window_size - 1 ) );
interpolate( affine->interpolate,
q, ir, ix, iy );
}
else {
for( z = 0; z < ps; z++ )
q[z] = 0;
}
ix += ddx;
iy += ddy;
@ -416,8 +432,8 @@ vips_affine_build( VipsObject *object )
window_offset =
vips_interpolate_get_window_offset( affine->interpolate );
affine->trn.iarea.left = window_offset;
affine->trn.iarea.top = window_offset;
affine->trn.iarea.left = 0;
affine->trn.iarea.top = 0;
affine->trn.iarea.width = in->Xsize;
affine->trn.iarea.height = in->Ysize;
affine->trn.a = ((double *) affine->matrix->data)[0];
@ -429,7 +445,13 @@ vips_affine_build( VipsObject *object )
affine->trn.odx = 0;
affine->trn.ody = 0;
if( vips__transform_calc_inverse( &affine->trn ) )
return( -1 );
/* Set the default value for oarea.
*/
vips__transform_set_area( &affine->trn );
if( vips_object_argument_isset( object, "oarea" ) ) {
affine->trn.oarea.left = ((int *) affine->oarea->data)[0];
affine->trn.oarea.top = ((int *) affine->oarea->data)[1];
@ -447,15 +469,16 @@ vips_affine_build( VipsObject *object )
if( vips_object_argument_isset( object, "idy" ) )
affine->trn.idy = affine->idy;
if( vips__transform_calc_inverse( &affine->trn ) )
return( -1 );
#ifdef DEBUG
printf( "vips_affine_build: copy on identity transform disabled\n" );
#else /*!DEBUG*/
if( vips__transform_isidentity( &affine->trn ) &&
affine->trn.oarea.left == 0 &&
affine->trn.oarea.top == 0 &&
affine->trn.oarea.width == in->Xsize &&
affine->trn.oarea.height == in->Ysize )
return( vips_image_write( in, resample->out ) );
#endif /*!DEBUG*/
/* Check for coordinate overflow ... we want to be able to hold the
* output space inside INT_MAX / TRANSFORM_SCALE.
@ -478,13 +501,14 @@ vips_affine_build( VipsObject *object )
*/
if( vips_embed( in, &t[2],
window_offset, window_offset,
in->Xsize + window_size, in->Ysize + window_size,
in->Xsize + window_size - 1, in->Ysize + window_size - 1,
"extend", VIPS_EXTEND_COPY,
NULL ) )
return( -1 );
in = t[2];
/* Normally SMALLTILE ... except if this is a size up/down affine.
/* Normally SMALLTILE ... except if this is strictly a size
* up/down affine.
*/
if( affine->trn.b == 0.0 &&
affine->trn.c == 0.0 )
@ -499,12 +523,14 @@ vips_affine_build( VipsObject *object )
resample->out->Ysize = affine->trn.oarea.height;
#ifdef DEBUG
printf( "vips_affine_build: transform: "
"a = %g, b = %g, c = %g, d = %g\n",
affine->trn.a,
affine->trn.b,
affine->trn.c,
affine->trn.d );
printf( "vips_affine_build: transform: " );
vips__transform_print( &affine->trn );
printf( " window_offset = %d, window_size = %d\n",
window_offset, window_size );
printf( " input image width = %d, height = %d\n",
in->Xsize, in->Ysize );
printf( " output image width = %d, height = %d\n",
resample->out->Xsize, resample->out->Ysize );
#endif /*DEBUG*/
/* Generate!

View File

@ -156,8 +156,8 @@ vips__transform_print( const VipsTransformation *trn )
*/
void
vips__transform_forward_point( const VipsTransformation *trn,
double x, double y, /* In input space */
double *ox, double *oy ) /* In output space */
double x, double y, /* In input space */
double *ox, double *oy )/* In output space */
{
x += trn->idx;
y += trn->idy;
@ -170,11 +170,11 @@ vips__transform_forward_point( const VipsTransformation *trn,
*/
void
vips__transform_invert_point( const VipsTransformation *trn,
double x, double y, /* In output space */
double *ox, double *oy ) /* In input space */
double x, double y, /* In output space */
double *ox, double *oy )/* In input space */
{
x -= trn->odx;
y -= trn->ody;
x -= trn->odx;
y -= trn->ody;
*ox = trn->ia * x + trn->ib * y - trn->idx;
*oy = trn->ic * x + trn->id * y - trn->idy;
@ -187,7 +187,7 @@ typedef void (*transform_fn)( const VipsTransformation *,
*/
static void
transform_rect( const VipsTransformation *trn, transform_fn transform,
const VipsRect *in, /* In input space */
const VipsRect *in, /* In input space */
VipsRect *out ) /* In output space */
{
double x1, y1; /* Map corners */
@ -198,9 +198,12 @@ transform_rect( const VipsTransformation *trn, transform_fn transform,
/* Map input VipsRect.
*/
transform( trn, in->left, in->top, &x1, &y1 );
transform( trn, in->left, VIPS_RECT_BOTTOM( in ), &x3, &y3 );
transform( trn, VIPS_RECT_RIGHT( in ), in->top, &x2, &y2 );
transform( trn, in->left, in->top,
&x1, &y1 );
transform( trn, in->left, VIPS_RECT_BOTTOM( in ),
&x3, &y3 );
transform( trn, VIPS_RECT_RIGHT( in ), in->top,
&x2, &y2 );
transform( trn, VIPS_RECT_RIGHT( in ), VIPS_RECT_BOTTOM( in ),
&x4, &y4 );
@ -234,7 +237,7 @@ vips__transform_forward_rect( const VipsTransformation *trn,
*/
void
vips__transform_invert_rect( const VipsTransformation *trn,
const VipsRect *in, /* In output space */
const VipsRect *in, /* In output space */
VipsRect *out ) /* In input space */
{
transform_rect( trn, vips__transform_invert_point, in, out );