Merge branch 'master' of github.com:jcupitt/libvips

This commit is contained in:
John Cupitt 2017-04-25 13:36:05 +01:00
commit 5cadbb9882
17 changed files with 174 additions and 22 deletions

View File

@ -1,6 +1,12 @@
15/4/17 started 8.6.0
- supports fits images with leading non-image HDUs, thanks benepo
23/4/17 started 8.5.5
- doc polishing
23/4/17 started 8.5.4
- don't depend on image width when setting n_lines, thanks kleisauke
7/4/17 started 8.5.3
- more link fixing in docs
- revise cache sizing again to help out of order errors under heavy load, thanks
@ -131,7 +137,6 @@
18/5/16 started 8.3.2
- more robust vips image reading
- more robust tiff read [Matt Richards]
>>>>>>> master
15/4/16 started 8.3.1
- rename vips wrapper script, it was still vips-8.2, thanks Benjamin

View File

@ -38,7 +38,7 @@ VIPS_VERSION_STRING=$VIPS_VERSION-`date`
# binary interface changes not backwards compatible?: reset age to 0
LIBRARY_CURRENT=49
LIBRARY_REVISION=4
LIBRARY_REVISION=5
LIBRARY_AGE=7
# patched into include/vips/version.h

21
doc/Cite.xml Normal file
View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<refentry id="Cite.md">
<para>
<refmeta> <refentrytitle>Cite</refentrytitle> <manvolnum>3</manvolnum> <refmiscinfo>libvips</refmiscinfo> </refmeta>
</para>
<para>
<refnamediv> <refname>Cite</refname> <refpurpose>References to cite for libvips</refpurpose> </refnamediv>
</para>
<para>
Martinez, K. and Cupitt, J. (2005) <ulink url="http://eprints.ecs.soton.ac.uk/12371">VIPS a highly tuned image processing software architecture</ulink>. In Proceedings of IEEE International Conference on Image Processing 2, pp. 574-577, Genova.
</para>
<para>
Cupitt, J. and Martinez, K. (1996) <ulink url="http://eprints.soton.ac.uk/252227/1/vipsspie96a.pdf">VIPS: An image processing system for large images</ulink>, Proc. SPIE, vol. 2663, pp. 1928.
</para>
</refentry>

View File

@ -17,10 +17,10 @@ The thumbnailing functionality is implemented by `vips_thumbnail()` and
see the docs for details. You can use these functions from any language
with a libvips binding. For example, from PHP you could write:
```php
$filename = ...;
```php?start_inline=1
$filename = "image.jpg";
$image = Vips\Image::thumbnail($filename, 200, ["height" => 200]);
$image.writeToFile("my-thumbnail.jpg");
$image->writeToFile("my-thumbnail.jpg");
```
# libvips options

View File

@ -16,10 +16,10 @@
<para>
The thumbnailing functionality is implemented by <literal>vips_thumbnail()</literal> and <literal>vips_thumbnail_buffer()</literal> (which thumbnails an image held as a string), see the docs for details. You can use these functions from any language with a libvips binding. For example, from PHP you could write:
</para>
<programlisting language="php">
$filename = ...;
<programlisting>
$filename = &quot;image.jpg&quot;;
$image = Vips\Image::thumbnail($filename, 200, [&quot;height&quot; =&gt; 200]);
$image.writeToFile(&quot;my-thumbnail.jpg&quot;);
$image-&gt;writeToFile(&quot;my-thumbnail.jpg&quot;);
</programlisting>
<refsect3 id="libvips-options">
<title>libvips options</title>
@ -115,7 +115,7 @@ $ vipsthumbnail owl.jpg --smartcrop attention -s 128
<refsect3 id="linear-light">
<title>Linear light</title>
<para>
Shrinking images involves combining many pixels into one. Arithmetic averaging really ought to be in terms of the number of photons, but (for historical reasons) the values stored in image files are usually related to the voltage that should be applied to a CRT electron gun.
Shrinking images involves combining many pixels into one. Arithmetic averaging really ought to be in terms of the number of photons, but (for historical reasons) the values stored in image files are usually related to the voltage that should be applied to the electron gun in a CRT display.
</para>
<para>
<literal>vipsthumbnail</literal> has an option to perform image shrinking in linear space, that is, a colourspace where values are proportional to photon numbers. For example:

View File

@ -328,6 +328,11 @@
<entry>extract an area from an image</entry>
<entry>vips_extract_area(), vips_crop()</entry>
</row>
<row>
<entry>smartcrop</entry>
<entry>extract an area from an image</entry>
<entry>vips_smartcrop()</entry>
</row>
<row>
<entry>extract_band</entry>
<entry>extract band from an image</entry>
@ -591,6 +596,16 @@
<entry>make a fractal surface</entry>
<entry>vips_fractsurf()</entry>
</row>
<row>
<entry>worley</entry>
<entry>make a worley noise image</entry>
<entry>vips_worley()</entry>
</row>
<row>
<entry>perlin</entry>
<entry>make a perlin noise image</entry>
<entry>vips_perlin()</entry>
</row>
<row>
<entry>radload</entry>
<entry>load a Radiance image from a file</entry>
@ -761,6 +776,11 @@
<entry>save image to deep zoom format</entry>
<entry>vips_dzsave()</entry>
</row>
<row>
<entry>dzsave_buffer</entry>
<entry>save image to dz buffer</entry>
<entry>vips_dzsave_buffer()</entry>
</row>
<row>
<entry>pngsave</entry>
<entry>save image to png file</entry>
@ -801,6 +821,11 @@
<entry>save image to tiff file</entry>
<entry>vips_tiffsave()</entry>
</row>
<row>
<entry>tiffsave_buffer</entry>
<entry>save image to tiff buffer</entry>
<entry>vips_tiffsave_buffer()</entry>
</row>
<row>
<entry>fitssave</entry>
<entry>save image to fits file</entry>
@ -836,6 +861,16 @@
<entry>reduce an image</entry>
<entry>vips_reduce()</entry>
</row>
<row>
<entry>thumbnail</entry>
<entry>generate thumbnail from file</entry>
<entry>vips_thumbnail()</entry>
</row>
<row>
<entry>thumbnail_buffer</entry>
<entry>generate thumbnail from buffer</entry>
<entry>vips_thumbnail_buffer()</entry>
</row>
<row>
<entry>mapim</entry>
<entry>resample an image with an arbitrary warp</entry>
@ -971,6 +1006,11 @@
<entry>convert an sRGB image to scRGB</entry>
<entry>vips_sRGB2scRGB()</entry>
</row>
<row>
<entry>scRGB2BW</entry>
<entry>convert scRGB to BW</entry>
<entry>vips_scRGB2BW()</entry>
</row>
<row>
<entry>scRGB2sRGB</entry>
<entry>convert an scRGB image to sRGB</entry>
@ -1066,6 +1106,21 @@
<entry>convolution operation</entry>
<entry>vips_conv()</entry>
</row>
<row>
<entry>conva</entry>
<entry>approximate integer convolution</entry>
<entry>vips_conva()</entry>
</row>
<row>
<entry>convf</entry>
<entry>float convolution operation</entry>
<entry>vips_convf()</entry>
</row>
<row>
<entry>convi</entry>
<entry>int convolution operation</entry>
<entry>vips_convi()</entry>
</row>
<row>
<entry>compass</entry>
<entry>convolve with rotating mask</entry>
@ -1076,6 +1131,11 @@
<entry>seperable convolution operation</entry>
<entry>vips_convsep()</entry>
</row>
<row>
<entry>convasep</entry>
<entry>approximate separable integer convolution</entry>
<entry>vips_convasep()</entry>
</row>
<row>
<entry>fastcor</entry>
<entry>fast correlation</entry>

View File

@ -11,6 +11,8 @@
# <entry>vips_gamma()</entry>
# </row>
import gi
gi.require_version('Vips', '8.0')
from gi.repository import Vips, GObject
vips_type_operation = GObject.GType.from_name("VipsOperation")

View File

@ -155,6 +155,12 @@ operation flags: sequential-unbuffered
See #VipsOperation for more information on running operations on images.
</para>
<para>
The API docs have a <link linkend="function-list">handy table of all vips
operations</link>, if you want to find out how to do something, try
searching that.
</para>
<para>
When you are done, you can write
the final image to a disc file, to a formatted memory buffer, or to

View File

@ -71,6 +71,12 @@ VipsOperation (operation), operations
<literal>VipsForeign</literal> will show some of the extra flags
supported by the file load/save operations.
</para>
<para>
The API docs have a <link linkend="function-list">handy table of all vips
operations</link>, if you want to find out how to do something, try
searching that.
</para>
</refsect3>
<refsect3 id="using-command-line-options">

View File

@ -219,6 +219,12 @@ VImage VImage::add( VImage right, VOption *options = 0 );
you can write to a memory array, to a formatted image in memory, or to
another image.
</para>
<para>
The API docs have a <link linkend="function-list">handy table of all vips
operations</link>, if you want to find out how to do something, try
searching that.
</para>
</refsect3>
<refsect3 id="cpp-expansion">

View File

@ -117,8 +117,10 @@ vips_sequential_generate( VipsRegion *or,
VipsRect *r = &or->valid;
VipsRegion *ir = (VipsRegion *) seq;
VIPS_DEBUG_MSG_GREEN( "thread %p request for line %d, height %d\n",
g_thread_self(), r->top, r->height );
if( sequential->trace )
printf( "vips_sequential_generate %p: "
"request for line %d, height %d\n",
sequential, r->top, r->height );
VIPS_GATE_START( "vips_sequential_generate: wait" );
@ -141,9 +143,10 @@ vips_sequential_generate( VipsRegion *or,
*/
VipsRect area;
VIPS_DEBUG_MSG_GREEN( "thread %p skipping to line %d ...\n",
g_thread_self(),
r->top );
if( sequential->trace )
printf( "vips_sequential_generate %p: "
"skipping to line %d ...\n",
sequential, r->top );
area.left = 0;
area.top = sequential->y_pos;
@ -236,7 +239,6 @@ vips_sequential_class_init( VipsSequentialClass *class )
G_STRUCT_OFFSET( VipsSequential, tile_height ),
1, 1000000, 1 );
VIPS_ARG_ENUM( class, "access", 6,
_( "Strategy" ),
_( "Expected access pattern" ),
@ -259,6 +261,7 @@ vips_sequential_init( VipsSequential *sequential )
sequential->lock = vips_g_mutex_new();
sequential->tile_height = 1;
sequential->error = 0;
sequential->trace = FALSE;
}
/**

View File

@ -88,6 +88,11 @@ typedef struct _VipsThreadState {
*/
void *a;
/* Set in allocate to stall this thread for a moment. Handy for
* debugging race conditions.
*/
gboolean stall;
} VipsThreadState;
typedef struct _VipsThreadStateClass {

View File

@ -331,6 +331,10 @@ wbuffer_allocate_fn( VipsThreadState *state, void *a, gboolean *stop )
sink_base->y += sink_base->tile_height;
if( sink_base->y >= VIPS_RECT_BOTTOM( &write->buf->area ) ) {
VIPS_DEBUG_MSG( "wbuffer_allocate_fn: "
"finished top = %d, height = %d\n",
write->buf->area.top, write->buf->area.height );
/* Block until the write of the previous buffer
* is done, then set write of this buffer going.
*/
@ -346,10 +350,6 @@ wbuffer_allocate_fn( VipsThreadState *state, void *a, gboolean *stop )
return( 0 );
}
VIPS_DEBUG_MSG( "wbuffer_allocate_fn: "
"finished top = %d, height = %d\n",
write->buf->area.top, write->buf->area.height );
VIPS_DEBUG_MSG( "wbuffer_allocate_fn: "
"starting top = %d, height = %d\n",
sink_base->y, sink_base->nlines );
@ -365,6 +365,11 @@ wbuffer_allocate_fn( VipsThreadState *state, void *a, gboolean *stop )
*stop = TRUE;
return( -1 );
}
/* This will be the first tile of a new buffer ...
* stall for a moment to stress the caching system.
*/
state->stall = TRUE;
}
}

View File

@ -18,6 +18,9 @@
* 6/3/17
* - remove single-thread-first-request thing, new seq system makes it
* unnecessary
* 23/4/17
* - add ->stall
* - don't depend on image width when setting n_lines
*/
/*
@ -111,6 +114,10 @@ int vips__n_active_threads = 0;
*/
static GPrivate *is_worker_key = NULL;
/* Set to stall threads for debugging.
*/
static gboolean vips__stall = FALSE;
/* Glib 2.32 revised the thread API. We need some compat functions.
*/
@ -466,6 +473,7 @@ vips_thread_state_init( VipsThreadState *state )
state->reg = NULL;
state->stop = FALSE;
state->stall = FALSE;
}
void *
@ -634,6 +642,17 @@ vips_thread_work_unit( VipsThread *thr )
g_mutex_unlock( pool->allocate_lock );
if( thr->state->stall &&
vips__stall ) {
/* Sleep for 0.5s. Handy for stressing the seq system. Stall
* is set by allocate funcs in various places.
*/
g_usleep( 500000 );
thr->state->stall = FALSE;
printf( "vips_thread_work_unit: "
"stall done, releasing y = %d ...\n", thr->state->y );
}
/* Process a work unit.
*/
if( pool->work( thr->state, pool->a ) ) {
@ -999,6 +1018,9 @@ vips__threadpool_init( void )
if( !is_worker_key )
is_worker_key = g_private_new( NULL );
#endif
if( g_getenv( "VIPS_STALL" ) )
vips__stall = TRUE;
}
/**
@ -1021,6 +1043,7 @@ vips_get_tile_size( VipsImage *im,
int *tile_width, int *tile_height, int *n_lines )
{
const int nthr = vips_concurrency_get();
const int typical_image_width = 1000;
/* Compiler warnings.
*/
@ -1054,11 +1077,15 @@ vips_get_tile_size( VipsImage *im,
* the pipeline might see a different hint and we need to synchronise
* buffer sizes everywhere.
*
* We also can't depend on the current image size, since that might
* change down the pipeline too. Pick a typical image width.
*
* Pick the maximum buffer size we might possibly need, then round up
* to a multiple of tileheight.
*/
*n_lines = vips__tile_height *
VIPS_ROUND_UP( vips__tile_width * nthr, im->Xsize ) / im->Xsize;
VIPS_ROUND_UP( vips__tile_width * nthr, typical_image_width ) /
typical_image_width;
*n_lines = VIPS_MAX( *n_lines, vips__fatstrip_height * nthr );
*n_lines = VIPS_MAX( *n_lines, vips__thinstrip_height * nthr );
*n_lines = VIPS_ROUND_UP( *n_lines, *tile_height );

View File

@ -835,8 +835,6 @@ vips_reducev_build( VipsObject *object )
if( VIPS_OBJECT_CLASS( vips_reducev_parent_class )->build( object ) )
return( -1 );
g_info( "reducev by factor %g", reducev->vshrink );
in = resample->in;
if( reducev->vshrink < 1 ) {
@ -895,6 +893,7 @@ vips_reducev_build( VipsObject *object )
if( vips_sequential( in, &t[3],
"tile_height", 10,
// "trace", TRUE,
NULL ) )
return( -1 );
in = t[3];

View File

@ -25,3 +25,7 @@ Darwin)
esac
$PYTHON -m unittest -v test_all
echo rerunning with VIPS_STALL enabled ...
export VIPS_STALL=1
$PYTHON -m unittest -v test_all

View File

@ -24,6 +24,9 @@ break_threshold() {
return $(echo "$diff > $threshold" | bc -l)
}
# run the test with VIPS_STALL enabled to stress the seq system
export VIPS_STALL=1
size=1000
while [ $size -gt 99 ]; do
printf "testing size to $size ... "