From 362c7efdfc7d4cd0a8e7a1f75834575e0574e14e Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Mon, 6 Mar 2017 11:55:38 +0000 Subject: [PATCH] argh reapply seq removal --- TODO | 12 +-- libvips/arithmetic/arithmetic.c | 2 +- libvips/arithmetic/statistic.c | 2 +- libvips/colour/colour.c | 2 +- libvips/colour/colourspace.c | 2 +- libvips/colour/sRGB2scRGB.c | 2 +- libvips/colour/scRGB2BW.c | 2 +- libvips/colour/scRGB2sRGB.c | 2 +- libvips/conversion/arrayjoin.c | 2 +- libvips/conversion/bandary.c | 2 +- libvips/conversion/bandfold.c | 2 +- libvips/conversion/bandunfold.c | 2 +- libvips/conversion/byteswap.c | 2 +- libvips/conversion/cast.c | 2 +- libvips/conversion/copy.c | 2 +- libvips/conversion/embed.c | 2 +- libvips/conversion/extract.c | 2 +- libvips/conversion/falsecolour.c | 2 +- libvips/conversion/flatten.c | 2 +- libvips/conversion/gamma.c | 2 +- libvips/conversion/msb.c | 2 +- libvips/conversion/premultiply.c | 2 +- libvips/conversion/recomb.c | 2 +- libvips/conversion/sequential.c | 149 ++++------------------------- libvips/conversion/tilecache.c | 41 +++----- libvips/conversion/unpremultiply.c | 2 +- libvips/conversion/zoom.c | 2 +- libvips/deprecated/im_jpeg2vips.c | 2 +- libvips/deprecated/im_png2vips.c | 2 +- libvips/deprecated/im_tiff2vips.c | 2 +- libvips/foreign/foreign.c | 2 +- libvips/foreign/jpeg2vips.c | 24 ++--- libvips/foreign/jpegload.c | 11 +-- libvips/foreign/pforeign.h | 17 ++-- libvips/foreign/pngload.c | 5 +- libvips/foreign/radiance.c | 14 +-- libvips/foreign/radload.c | 3 +- libvips/foreign/tiff2vips.c | 35 +++---- libvips/foreign/tiffload.c | 6 +- libvips/foreign/vipspng.c | 35 +++---- libvips/histogram/maplut.c | 2 +- libvips/iofuncs/image.c | 8 +- libvips/iofuncs/object.c | 10 +- libvips/iofuncs/operation.c | 5 - libvips/resample/resize.c | 2 + libvips/resample/shrinkh.c | 2 +- libvips/resample/shrinkv.c | 2 +- libvips/resample/thumbnail.c | 4 - test/test_seq.sh | 9 ++ 49 files changed, 132 insertions(+), 320 deletions(-) diff --git a/TODO b/TODO index 4231971d..6a3f24b5 100644 --- a/TODO +++ b/TODO @@ -1,14 +1,6 @@ - -- VIPS_META_SEQUENTIAL will be saved to vips files, then loaded back again argh +- check initial cache sizing in vips_line_cache_build - we need to set a value that can't be saved - - maybe a NULL boxed pointer? - - looks like vips_image_set_area(im, "poop", NULL, NULL); might work - -- do we need a seq cache for reducev as well? we could have up to a 3x - reduction there + what about dynamic cache sizing? diff --git a/libvips/arithmetic/arithmetic.c b/libvips/arithmetic/arithmetic.c index df6ec224..d67995ff 100644 --- a/libvips/arithmetic/arithmetic.c +++ b/libvips/arithmetic/arithmetic.c @@ -633,7 +633,7 @@ vips_arithmetic_class_init( VipsArithmeticClass *class ) vobject_class->description = _( "arithmetic operations" ); vobject_class->build = vips_arithmetic_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; VIPS_ARG_IMAGE( class, "out", 100, _( "Output" ), diff --git a/libvips/arithmetic/statistic.c b/libvips/arithmetic/statistic.c index 746a944f..23f30ca8 100644 --- a/libvips/arithmetic/statistic.c +++ b/libvips/arithmetic/statistic.c @@ -161,7 +161,7 @@ vips_statistic_class_init( VipsStatisticClass *class ) vobject_class->description = _( "VIPS statistic operations" ); vobject_class->build = vips_statistic_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; VIPS_ARG_IMAGE( class, "in", 0, _( "Input" ), diff --git a/libvips/colour/colour.c b/libvips/colour/colour.c index 61988a89..f57e0a08 100644 --- a/libvips/colour/colour.c +++ b/libvips/colour/colour.c @@ -421,7 +421,7 @@ vips_colour_class_init( VipsColourClass *class ) vobject_class->description = _( "color operations" ); vobject_class->build = vips_colour_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; VIPS_ARG_IMAGE( class, "out", 100, _( "Output" ), diff --git a/libvips/colour/colourspace.c b/libvips/colour/colourspace.c index 8fe6967d..ef260a86 100644 --- a/libvips/colour/colourspace.c +++ b/libvips/colour/colourspace.c @@ -580,7 +580,7 @@ vips_colourspace_class_init( VipsColourspaceClass *class ) vobject_class->description = _( "convert to a new colorspace" ); vobject_class->build = vips_colourspace_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; VIPS_ARG_IMAGE( class, "in", 1, _( "Input" ), diff --git a/libvips/colour/sRGB2scRGB.c b/libvips/colour/sRGB2scRGB.c index 330d756b..24389506 100644 --- a/libvips/colour/sRGB2scRGB.c +++ b/libvips/colour/sRGB2scRGB.c @@ -237,7 +237,7 @@ vips_sRGB2scRGB_class_init( VipssRGB2scRGBClass *class ) object_class->description = _( "convert an sRGB image to scRGB" ); object_class->build = vips_sRGB2scRGB_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; VIPS_ARG_IMAGE( class, "in", 1, _( "Input" ), diff --git a/libvips/colour/scRGB2BW.c b/libvips/colour/scRGB2BW.c index 19ee0411..a7f6fddd 100644 --- a/libvips/colour/scRGB2BW.c +++ b/libvips/colour/scRGB2BW.c @@ -231,7 +231,7 @@ vips_scRGB2BW_class_init( VipsscRGB2BWClass *class ) object_class->description = _( "convert scRGB to BW" ); object_class->build = vips_scRGB2BW_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; VIPS_ARG_IMAGE( class, "in", 1, _( "Input" ), diff --git a/libvips/colour/scRGB2sRGB.c b/libvips/colour/scRGB2sRGB.c index 83702485..6f8534f5 100644 --- a/libvips/colour/scRGB2sRGB.c +++ b/libvips/colour/scRGB2sRGB.c @@ -259,7 +259,7 @@ vips_scRGB2sRGB_class_init( VipsscRGB2sRGBClass *class ) object_class->description = _( "convert an scRGB image to sRGB" ); object_class->build = vips_scRGB2sRGB_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; VIPS_ARG_IMAGE( class, "in", 1, _( "Input" ), diff --git a/libvips/conversion/arrayjoin.c b/libvips/conversion/arrayjoin.c index 35370c7d..9d1cfcd7 100644 --- a/libvips/conversion/arrayjoin.c +++ b/libvips/conversion/arrayjoin.c @@ -298,7 +298,7 @@ vips_arrayjoin_class_init( VipsArrayjoinClass *class ) vobject_class->description = _( "join an array of images" ); vobject_class->build = vips_arrayjoin_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; VIPS_ARG_BOXED( class, "in", -1, _( "Input" ), diff --git a/libvips/conversion/bandary.c b/libvips/conversion/bandary.c index 2f14b494..efc0b8cb 100644 --- a/libvips/conversion/bandary.c +++ b/libvips/conversion/bandary.c @@ -186,7 +186,7 @@ vips_bandary_class_init( VipsBandaryClass *class ) vobject_class->description = _( "operations on image bands" ); vobject_class->build = vips_bandary_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; } static void diff --git a/libvips/conversion/bandfold.c b/libvips/conversion/bandfold.c index b5a1d309..9ad72c5e 100644 --- a/libvips/conversion/bandfold.c +++ b/libvips/conversion/bandfold.c @@ -154,7 +154,7 @@ vips_bandfold_class_init( VipsBandfoldClass *class ) vobject_class->description = _( "fold up x axis into bands" ); vobject_class->build = vips_bandfold_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; VIPS_ARG_IMAGE( class, "in", 1, _( "Input" ), diff --git a/libvips/conversion/bandunfold.c b/libvips/conversion/bandunfold.c index c0491031..0aa6064a 100644 --- a/libvips/conversion/bandunfold.c +++ b/libvips/conversion/bandunfold.c @@ -157,7 +157,7 @@ vips_bandunfold_class_init( VipsBandunfoldClass *class ) vobject_class->description = _( "unfold image bands into x axis" ); vobject_class->build = vips_bandunfold_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; VIPS_ARG_IMAGE( class, "in", 1, _( "Input" ), diff --git a/libvips/conversion/byteswap.c b/libvips/conversion/byteswap.c index 1d29d9e2..be6a834a 100644 --- a/libvips/conversion/byteswap.c +++ b/libvips/conversion/byteswap.c @@ -200,7 +200,7 @@ vips_byteswap_class_init( VipsByteswapClass *class ) vobject_class->description = _( "byteswap an image" ); vobject_class->build = vips_byteswap_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; VIPS_ARG_IMAGE( class, "in", 1, _( "Input" ), diff --git a/libvips/conversion/cast.c b/libvips/conversion/cast.c index 6e658ee5..f984af9e 100644 --- a/libvips/conversion/cast.c +++ b/libvips/conversion/cast.c @@ -542,7 +542,7 @@ vips_cast_class_init( VipsCastClass *class ) vobject_class->description = _( "cast an image" ); vobject_class->build = vips_cast_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; VIPS_ARG_IMAGE( class, "in", 1, _( "Input" ), diff --git a/libvips/conversion/copy.c b/libvips/conversion/copy.c index 168a0281..5e94a4bf 100644 --- a/libvips/conversion/copy.c +++ b/libvips/conversion/copy.c @@ -264,7 +264,7 @@ vips_copy_class_init( VipsCopyClass *class ) * cache it. Plus copy is cheap. */ operation_class->flags = - VIPS_OPERATION_SEQUENTIAL_UNBUFFERED | + VIPS_OPERATION_SEQUENTIAL | VIPS_OPERATION_NOCACHE; VIPS_ARG_IMAGE( class, "in", 1, diff --git a/libvips/conversion/embed.c b/libvips/conversion/embed.c index 14c1071d..52d23825 100644 --- a/libvips/conversion/embed.c +++ b/libvips/conversion/embed.c @@ -557,7 +557,7 @@ vips_embed_class_init( VipsEmbedClass *class ) vobject_class->description = _( "embed an image in a larger image" ); vobject_class->build = vips_embed_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; VIPS_ARG_IMAGE( class, "in", -1, _( "Input" ), diff --git a/libvips/conversion/extract.c b/libvips/conversion/extract.c index 6042a2cc..0f1ab70e 100644 --- a/libvips/conversion/extract.c +++ b/libvips/conversion/extract.c @@ -188,7 +188,7 @@ vips_extract_area_class_init( VipsExtractAreaClass *class ) vobject_class->description = _( "extract an area from an image" ); vobject_class->build = vips_extract_area_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; VIPS_ARG_IMAGE( class, "input", 0, _( "Input" ), diff --git a/libvips/conversion/falsecolour.c b/libvips/conversion/falsecolour.c index 1719833d..862799ba 100644 --- a/libvips/conversion/falsecolour.c +++ b/libvips/conversion/falsecolour.c @@ -375,7 +375,7 @@ vips_falsecolour_class_init( VipsFalsecolourClass *class ) vobject_class->description = _( "false-color an image" ); vobject_class->build = vips_falsecolour_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; VIPS_ARG_IMAGE( class, "in", 0, _( "in" ), diff --git a/libvips/conversion/flatten.c b/libvips/conversion/flatten.c index 9c86de62..cfe5fe28 100644 --- a/libvips/conversion/flatten.c +++ b/libvips/conversion/flatten.c @@ -380,7 +380,7 @@ vips_flatten_class_init( VipsFlattenClass *class ) vobject_class->description = _( "flatten alpha out of an image" ); vobject_class->build = vips_flatten_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; VIPS_ARG_IMAGE( class, "in", 1, _( "Input" ), diff --git a/libvips/conversion/gamma.c b/libvips/conversion/gamma.c index 91fe63af..ef26ea0a 100644 --- a/libvips/conversion/gamma.c +++ b/libvips/conversion/gamma.c @@ -137,7 +137,7 @@ vips_gamma_class_init( VipsGammaClass *class ) vobject_class->description = _( "gamma an image" ); vobject_class->build = vips_gamma_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; VIPS_ARG_IMAGE( class, "in", -1, _( "in" ), diff --git a/libvips/conversion/msb.c b/libvips/conversion/msb.c index 34858166..01e89c9b 100644 --- a/libvips/conversion/msb.c +++ b/libvips/conversion/msb.c @@ -238,7 +238,7 @@ vips_msb_class_init( VipsMsbClass *class ) _( "pick most-significant byte from an image" ); vobject_class->build = vips_msb_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; VIPS_ARG_IMAGE( class, "in", 0, _( "Input" ), diff --git a/libvips/conversion/premultiply.c b/libvips/conversion/premultiply.c index 3999e6c9..24c61522 100644 --- a/libvips/conversion/premultiply.c +++ b/libvips/conversion/premultiply.c @@ -253,7 +253,7 @@ vips_premultiply_class_init( VipsPremultiplyClass *class ) vobject_class->description = _( "premultiply image alpha" ); vobject_class->build = vips_premultiply_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; VIPS_ARG_IMAGE( class, "in", 1, _( "Input" ), diff --git a/libvips/conversion/recomb.c b/libvips/conversion/recomb.c index e8d332c1..b6ce8eaf 100644 --- a/libvips/conversion/recomb.c +++ b/libvips/conversion/recomb.c @@ -201,7 +201,7 @@ vips_recomb_class_init( VipsRecombClass *class ) object_class->description = _( "linear recombination with matrix" ); object_class->build = vips_recomb_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; VIPS_ARG_IMAGE( class, "in", 0, _( "Input" ), diff --git a/libvips/conversion/sequential.c b/libvips/conversion/sequential.c index 0942c2a1..69f2b048 100644 --- a/libvips/conversion/sequential.c +++ b/libvips/conversion/sequential.c @@ -21,6 +21,8 @@ * this broke on some busy, many-core systems, see comment below * 10/6/14 * - re-enable skipahead now we have the single-thread-first-tile idea + * 6/3/17 + * - deprecate @trace, @access now seq is much simpler */ /* @@ -70,15 +72,6 @@ #include "pconversion.h" -/* Stall threads that run ahead for up to this long, in seconds. Normally they - * will be woken once their data is ready and long before this. The timeout is - * just to prevent a total crash in the case of accidental deadlock. - * - * This has to be a long time: if we're trying to use all cores on a busy - * system, it could be ages until all the other threads get a chance to run. - */ -#define STALL_TIME (60.0) - typedef struct _VipsSequential { VipsConversion parent_instance; @@ -87,11 +80,9 @@ typedef struct _VipsSequential { VipsAccess access; gboolean trace; - /* Lock access to y_pos with this, use the cond to wake up stalled - * threads. + /* Lock access to y_pos with this. */ GMutex *lock; - GCond *ready; /* The next read from our source will fetch this scanline, ie. it's 0 * when we start. @@ -114,7 +105,6 @@ vips_sequential_dispose( GObject *gobject ) VipsSequential *sequential = (VipsSequential *) gobject; VIPS_FREEF( vips_g_mutex_free, sequential->lock ); - VIPS_FREEF( vips_g_cond_free, sequential->ready ); G_OBJECT_CLASS( vips_sequential_parent_class )->dispose( gobject ); } @@ -130,18 +120,12 @@ vips_sequential_generate( VipsRegion *or, VIPS_DEBUG_MSG_GREEN( "thread %p request for line %d, height %d\n", g_thread_self(), r->top, r->height ); - if( sequential->trace ) - g_info( "request for line %d, height %d", - r->top, r->height ); - VIPS_GATE_START( "vips_sequential_generate: wait" ); g_mutex_lock( sequential->lock ); VIPS_GATE_STOP( "vips_sequential_generate: wait" ); - VIPS_DEBUG_MSG_GREEN( "thread %p has lock ...\n", g_thread_self() ); - /* If we've seen an error, everything must stop. */ if( sequential->error ) { @@ -149,68 +133,8 @@ vips_sequential_generate( VipsRegion *or, return( -1 ); } - if( r->top > sequential->y_pos && - sequential->y_pos > 0 ) { - /* This request is for stuff beyond the current read position, - * and this is not the first request. We - * stall for a while to give other threads time to catch up. - * - * The stall can be cancelled by a signal on @ready. - * - * We don't stall forever, since an error would be better than - * deadlock, and we don't fail on timeout, since the timeout - * may be harmless. - */ - -#ifdef HAVE_COND_INIT - gint64 time; - - time = g_get_monotonic_time() + - STALL_TIME * G_TIME_SPAN_SECOND; -#else - GTimeVal time; - - g_get_current_time( &time ); - g_time_val_add( &time, STALL_TIME * 1000000 ); -#endif - - VIPS_DEBUG_MSG_GREEN( "thread %p stalling for up to %gs ...\n", - g_thread_self(), STALL_TIME ); - - VIPS_GATE_START( "vips_sequential_generate: wait" ); - - /* Exit the loop on timeout or condition passes. We have to - * be wary of spurious wakeups. - */ - while( r->top > sequential->y_pos ) { -#ifdef HAVE_COND_INIT - if( !g_cond_wait_until( sequential->ready, - sequential->lock, time ) ) - break; -#else - if( !g_cond_timed_wait( sequential->ready, - sequential->lock, &time ) ) - break; -#endif - - /* We may have woken up because of an eval error. - */ - if( sequential->error ) { - g_mutex_unlock( sequential->lock ); - return( -1 ); - } - } - - VIPS_GATE_STOP( "vips_sequential_generate: wait" ); - - VIPS_DEBUG_MSG_GREEN( "thread %p awake again ...\n", - g_thread_self() ); - } - if( r->top > sequential->y_pos ) { - /* This is a request for something some way down the image, - * and we've fallen through from the stall above. - * + /* This is a request for something some way down the image. * Probably the operation is something like extract_area and * we should skip the initial part of the image. In fact, * we read to cache, since it may be useful. @@ -226,10 +150,7 @@ vips_sequential_generate( VipsRegion *or, area.width = 1; area.height = r->top - sequential->y_pos; if( vips_region_prepare( ir, &area ) ) { - VIPS_DEBUG_MSG( "thread %p error, unlocking #1 ...\n", - g_thread_self() ); sequential->error = -1; - g_cond_broadcast( sequential->ready ); g_mutex_unlock( sequential->lock ); return( -1 ); } @@ -240,32 +161,14 @@ vips_sequential_generate( VipsRegion *or, /* This is a request for old or present pixels -- serve from cache. * This may trigger further, sequential reads. */ - VIPS_DEBUG_MSG_GREEN( "thread %p reading ...\n", g_thread_self() ); if( vips_region_prepare( ir, r ) || vips_region_region( or, ir, r, r->left, r->top ) ) { - VIPS_DEBUG_MSG( "thread %p error, unlocking #2 ...\n", - g_thread_self() ); sequential->error = -1; - g_cond_broadcast( sequential->ready ); g_mutex_unlock( sequential->lock ); return( -1 ); } - if( VIPS_RECT_BOTTOM( r ) > sequential->y_pos ) { - /* This request has moved the read point. Update it, and wake - * up all stalled threads for a retry. - */ - sequential->y_pos = VIPS_RECT_BOTTOM( r ); - - VIPS_DEBUG_MSG_GREEN( "thread %p updating y_pos to %d and " - "waking stalled\n", - g_thread_self(), - sequential->y_pos ); - - g_cond_broadcast( sequential->ready ); - } - - VIPS_DEBUG_MSG_GREEN( "thread %p unlocking ...\n", g_thread_self() ); + sequential->y_pos = VIPS_MAX( sequential->y_pos, VIPS_RECT_BOTTOM( r ) ); g_mutex_unlock( sequential->lock ); @@ -285,12 +188,9 @@ vips_sequential_build( VipsObject *object ) if( VIPS_OBJECT_CLASS( vips_sequential_parent_class )->build( object ) ) return( -1 ); - if( vips_image_pio_input( sequential->in ) ) - return( -1 ); - if( vips_linecache( sequential->in, &t, "tile_height", sequential->tile_height, - "access", sequential->access, + "access", VIPS_ACCESS_SEQUENTIAL, NULL ) ) return( -1 ); @@ -329,13 +229,6 @@ vips_sequential_class_init( VipsSequentialClass *class ) VIPS_ARGUMENT_REQUIRED_INPUT, G_STRUCT_OFFSET( VipsSequential, in ) ); - VIPS_ARG_BOOL( class, "trace", 2, - _( "trace" ), - _( "trace pixel requests" ), - VIPS_ARGUMENT_OPTIONAL_INPUT, - G_STRUCT_OFFSET( VipsSequential, trace ), - TRUE ); - VIPS_ARG_INT( class, "tile_height", 3, _( "Tile height" ), _( "Tile height in pixels" ), @@ -343,21 +236,27 @@ 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" ), - VIPS_ARGUMENT_OPTIONAL_INPUT, + VIPS_ARGUMENT_OPTIONAL_INPUT | VIPS_ARGUMENT_DEPRECATED, G_STRUCT_OFFSET( VipsSequential, access ), VIPS_TYPE_ACCESS, VIPS_ACCESS_SEQUENTIAL ); + + VIPS_ARG_BOOL( class, "trace", 2, + _( "trace" ), + _( "trace pixel requests" ), + VIPS_ARGUMENT_OPTIONAL_INPUT | VIPS_ARGUMENT_DEPRECATED, + G_STRUCT_OFFSET( VipsSequential, trace ), + TRUE ); + } static void vips_sequential_init( VipsSequential *sequential ) { - sequential->trace = FALSE; - sequential->access = VIPS_ACCESS_SEQUENTIAL; sequential->lock = vips_g_mutex_new(); - sequential->ready = vips_g_cond_new(); sequential->tile_height = 1; sequential->error = 0; } @@ -370,28 +269,16 @@ vips_sequential_init( VipsSequential *sequential ) * * Optional arguments: * - * * @trace: trace requests * * @strip_height: height of cache strips - * * @access: access pattern * * This operation behaves rather like vips_copy() between images - * @in and @out, except that it checks that pixels are only requested - * top-to-bottom. If a thread makes an out of order request, it is stalled - * until the pack catches up. - * - * This operation is useful for loading file formats which are + * @in and @out, except that it checks that pixels on @in are only requested + * top-to-bottom. This operation is useful for loading file formats which are * strictly top-to-bottom, like PNG. * - * If @trace is true, the operation will print diagnostic messages for each - * block of pixels which are processed. This can help find the cause of - * non-sequential accesses. - * * @strip_height can be used to set the size of the tiles that * vips_sequential() uses. The default value is 1. * - * @access can be set to #VIPS_ACCESS_SEQUENTIAL_UNBUFFERED, meaning don't - * keep a large cache behind the read point. This can save some memory. - * * See also: vips_cache(), vips_linecache(), vips_tilecache(). * * Returns: 0 on success, -1 on error. diff --git a/libvips/conversion/tilecache.c b/libvips/conversion/tilecache.c index 789e73a6..707cd6ed 100644 --- a/libvips/conversion/tilecache.c +++ b/libvips/conversion/tilecache.c @@ -842,7 +842,7 @@ vips_tile_cache_init( VipsTileCache *cache ) * * When the cache fills, a tile is chosen for reuse. If @access is * #VIPS_ACCESS_RANDOM, then the least-recently-used tile is reused. If - * @access is #VIPS_ACCESS_SEQUENTIAL or #VIPS_ACCESS_SEQUENTIAL_UNBUFFERED, + * @access is #VIPS_ACCESS_SEQUENTIAL * the top-most tile is reused. * * By default, @tile_width and @tile_height are 128 pixels, and the operation @@ -917,6 +917,10 @@ vips_line_cache_build( VipsObject *object ) VipsBlockCache *block_cache = (VipsBlockCache *) object; VipsLineCache *cache = (VipsLineCache *) object; + int tile_width; + int tile_height; + int n_lines; + VIPS_DEBUG_MSG( "vips_line_cache_build\n" ); if( VIPS_OBJECT_CLASS( vips_line_cache_parent_class )-> @@ -929,31 +933,13 @@ vips_line_cache_build( VipsObject *object ) block_cache->access = cache->access; - if( cache->access == VIPS_ACCESS_SEQUENTIAL_UNBUFFERED ) - /* A tile per thread. - * - * Imagine scanline tiles and four threads. And add a bit for - * slop. - */ - block_cache->max_tiles = 2 * vips_concurrency_get(); - else { - /* Enough lines for two complete buffers would be exactly - * right. Make it 4 to give us some slop room. - * - * This can go up with request size, see vips_line_cache_gen(). - */ - int tile_width; - int tile_height; - int n_lines; + /* This can go up with request size, see vips_line_cache_gen(). + */ + vips_get_tile_size( block_cache->in, + &tile_width, &tile_height, &n_lines ); + block_cache->max_tiles = 1 + 2 * n_lines / block_cache->tile_height; - vips_get_tile_size( block_cache->in, - &tile_width, &tile_height, &n_lines ); - block_cache->max_tiles = 4 * - (1 + n_lines / block_cache->tile_height); - - VIPS_DEBUG_MSG( "vips_line_cache_build: n_lines = %d\n", - n_lines ); - } + VIPS_DEBUG_MSG( "vips_line_cache_build: n_lines = %d\n", n_lines ); VIPS_DEBUG_MSG( "vips_line_cache_build: " "max_tiles = %d, tile_height = %d\n", @@ -1026,15 +1012,14 @@ vips_line_cache_init( VipsLineCache *cache ) * @in and @out, except that it keeps a cache of computed scanlines. * * The number of lines cached is enough for a small amount of non-local - * access. If you know you will not be making any non-local access, you can - * save some memory and set @access to #VIPS_ACCESS_SEQUENTIAL_UNBUFFERED. + * access. * * Each cache tile is made with a single call to * vips_region_prepare(). * * When the cache fills, a tile is chosen for reuse. If @access is * #VIPS_ACCESS_RANDOM, then the least-recently-used tile is reused. If - * @access is #VIPS_ACCESS_SEQUENTIAL or #VIPS_ACCESS_SEQUENTIAL_UNBUFFERED, + * @access is #VIPS_ACCESS_SEQUENTIAL, then * the top-most tile is reused. @access defaults to #VIPS_ACCESS_RANDOM. * * @tile_height can be used to set the size of the strips that diff --git a/libvips/conversion/unpremultiply.c b/libvips/conversion/unpremultiply.c index 39623bab..d10c7a40 100644 --- a/libvips/conversion/unpremultiply.c +++ b/libvips/conversion/unpremultiply.c @@ -262,7 +262,7 @@ vips_unpremultiply_class_init( VipsUnpremultiplyClass *class ) vobject_class->description = _( "unpremultiply image alpha" ); vobject_class->build = vips_unpremultiply_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; VIPS_ARG_IMAGE( class, "in", 1, _( "Input" ), diff --git a/libvips/conversion/zoom.c b/libvips/conversion/zoom.c index af6800e9..ad21847a 100644 --- a/libvips/conversion/zoom.c +++ b/libvips/conversion/zoom.c @@ -372,7 +372,7 @@ vips_zoom_class_init( VipsZoomClass *class ) vobject_class->description = _( "zoom an image" ); vobject_class->build = vips_zoom_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; VIPS_ARG_IMAGE( class, "input", 0, _( "Input" ), diff --git a/libvips/deprecated/im_jpeg2vips.c b/libvips/deprecated/im_jpeg2vips.c index 2e3e5d09..11696663 100644 --- a/libvips/deprecated/im_jpeg2vips.c +++ b/libvips/deprecated/im_jpeg2vips.c @@ -111,7 +111,7 @@ jpeg2vips( const char *name, IMAGE *out, gboolean header_only ) #ifdef HAVE_JPEG if( vips__jpeg_read_file( filename, out, - header_only, shrink, fail_on_warn, TRUE, FALSE ) ) + header_only, shrink, fail_on_warn, FALSE ) ) return( -1 ); #else vips_error( "im_jpeg2vips", diff --git a/libvips/deprecated/im_png2vips.c b/libvips/deprecated/im_png2vips.c index a1b24579..61eb7fef 100644 --- a/libvips/deprecated/im_png2vips.c +++ b/libvips/deprecated/im_png2vips.c @@ -87,7 +87,7 @@ png2vips( const char *name, IMAGE *out, gboolean header_only ) return( -1 ); } else { - if( vips__png_read( filename, out, TRUE ) ) + if( vips__png_read( filename, out ) ) return( -1 ); } #else diff --git a/libvips/deprecated/im_tiff2vips.c b/libvips/deprecated/im_tiff2vips.c index 74479115..d94019e9 100644 --- a/libvips/deprecated/im_tiff2vips.c +++ b/libvips/deprecated/im_tiff2vips.c @@ -98,7 +98,7 @@ tiff2vips( const char *name, IMAGE *out, gboolean header_only ) return( -1 ); } else { - if( vips__tiff_read( filename, out, page, 1, FALSE, TRUE ) ) + if( vips__tiff_read( filename, out, page, 1, FALSE ) ) return( -1 ); } #else diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index 6dd59d8d..3afc5bb2 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -1502,7 +1502,7 @@ vips_foreign_save_class_init( VipsForeignSaveClass *class ) * write and interlaced png write, which are not, add extra caches * on their input. */ - operation_class->flags |= VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; + operation_class->flags |= VIPS_OPERATION_SEQUENTIAL; /* Must not cache savers. */ diff --git a/libvips/foreign/jpeg2vips.c b/libvips/foreign/jpeg2vips.c index 903e51ac..87cb615c 100644 --- a/libvips/foreign/jpeg2vips.c +++ b/libvips/foreign/jpeg2vips.c @@ -152,10 +152,6 @@ typedef struct _ReadJpeg { */ gboolean fail; - /* Use a read behind buffer. - */ - gboolean readbehind; - /* Used for file input only. */ char *filename; @@ -216,8 +212,7 @@ readjpeg_close( VipsObject *object, ReadJpeg *jpeg ) } static ReadJpeg * -readjpeg_new( VipsImage *out, - int shrink, gboolean fail, gboolean readbehind, gboolean autorotate ) +readjpeg_new( VipsImage *out, int shrink, gboolean fail, gboolean autorotate ) { ReadJpeg *jpeg; @@ -227,7 +222,6 @@ readjpeg_new( VipsImage *out, jpeg->out = out; jpeg->shrink = shrink; jpeg->fail = fail; - jpeg->readbehind = readbehind; jpeg->filename = NULL; jpeg->cinfo.err = jpeg_std_error( &jpeg->eman.pub ); jpeg->eman.pub.error_exit = vips__new_error_exit; @@ -516,7 +510,7 @@ read_jpeg_header( ReadJpeg *jpeg, VipsImage *out ) /* Tell downstream we are reading sequentially. */ - vips_image_set_int( out, VIPS_META_SEQUENTIAL, 1 ); + vips_image_set_area( out, VIPS_META_SEQUENTIAL, NULL, NULL ); return( 0 ); } @@ -680,9 +674,6 @@ read_jpeg_image( ReadJpeg *jpeg, VipsImage *out ) jpeg, NULL ) || vips_sequential( t[0], &t[1], "tile_height", 8, - "access", jpeg->readbehind ? - VIPS_ACCESS_SEQUENTIAL : - VIPS_ACCESS_SEQUENTIAL_UNBUFFERED, NULL ) ) return( -1 ); @@ -751,13 +742,12 @@ vips__jpeg_read( ReadJpeg *jpeg, VipsImage *out, gboolean header_only ) */ int vips__jpeg_read_file( const char *filename, VipsImage *out, - gboolean header_only, int shrink, gboolean fail, gboolean readbehind, + gboolean header_only, int shrink, gboolean fail, gboolean autorotate ) { ReadJpeg *jpeg; - if( !(jpeg = readjpeg_new( out, - shrink, fail, readbehind, autorotate )) ) + if( !(jpeg = readjpeg_new( out, shrink, fail, autorotate )) ) return( -1 ); /* Here for longjmp() from vips__new_error_exit() during startup. @@ -958,13 +948,11 @@ readjpeg_buffer (ReadJpeg *jpeg, const void *buf, size_t len) int vips__jpeg_read_buffer( const void *buf, size_t len, VipsImage *out, - gboolean header_only, int shrink, int fail, gboolean readbehind, - gboolean autorotate ) + gboolean header_only, int shrink, int fail, gboolean autorotate ) { ReadJpeg *jpeg; - if( !(jpeg = readjpeg_new( out, - shrink, fail, readbehind, autorotate )) ) + if( !(jpeg = readjpeg_new( out, shrink, fail, autorotate )) ) return( -1 ); if( setjmp( jpeg->eman.jmp ) ) diff --git a/libvips/foreign/jpegload.c b/libvips/foreign/jpegload.c index bc0e2559..4868b950 100644 --- a/libvips/foreign/jpegload.c +++ b/libvips/foreign/jpegload.c @@ -182,7 +182,7 @@ vips_foreign_load_jpeg_file_header( VipsForeignLoad *load ) VipsForeignLoadJpegFile *file = (VipsForeignLoadJpegFile *) load; if( vips__jpeg_read_file( file->filename, load->out, - TRUE, jpeg->shrink, load->fail, FALSE, jpeg->autorotate ) ) + TRUE, jpeg->shrink, load->fail, jpeg->autorotate ) ) return( -1 ); return( 0 ); @@ -195,8 +195,7 @@ vips_foreign_load_jpeg_file_load( VipsForeignLoad *load ) VipsForeignLoadJpegFile *file = (VipsForeignLoadJpegFile *) load; if( vips__jpeg_read_file( file->filename, load->real, - FALSE, jpeg->shrink, load->fail, - load->access == VIPS_ACCESS_SEQUENTIAL, jpeg->autorotate ) ) + FALSE, jpeg->shrink, load->fail, jpeg->autorotate ) ) return( -1 ); return( 0 ); @@ -262,8 +261,7 @@ vips_foreign_load_jpeg_buffer_header( VipsForeignLoad *load ) VipsForeignLoadJpegBuffer *buffer = (VipsForeignLoadJpegBuffer *) load; if( vips__jpeg_read_buffer( buffer->buf->data, buffer->buf->length, - load->out, TRUE, jpeg->shrink, load->fail, FALSE, - jpeg->autorotate ) ) + load->out, TRUE, jpeg->shrink, load->fail, jpeg->autorotate ) ) return( -1 ); return( 0 ); @@ -276,8 +274,7 @@ vips_foreign_load_jpeg_buffer_load( VipsForeignLoad *load ) VipsForeignLoadJpegBuffer *buffer = (VipsForeignLoadJpegBuffer *) load; if( vips__jpeg_read_buffer( buffer->buf->data, buffer->buf->length, - load->real, FALSE, jpeg->shrink, load->fail, - load->access == VIPS_ACCESS_SEQUENTIAL, jpeg->autorotate ) ) + load->real, FALSE, jpeg->shrink, load->fail, jpeg->autorotate ) ) return( -1 ); return( 0 ); diff --git a/libvips/foreign/pforeign.h b/libvips/foreign/pforeign.h index 796c1d38..358102c4 100644 --- a/libvips/foreign/pforeign.h +++ b/libvips/foreign/pforeign.h @@ -68,7 +68,7 @@ int vips__tiff_write_buf( VipsImage *in, int vips__tiff_read_header( const char *filename, VipsImage *out, int page, int n, gboolean autorotate ); int vips__tiff_read( const char *filename, VipsImage *out, - int page, int n, gboolean autorotate, gboolean readbehind ); + int page, int n, gboolean autorotate ); gboolean vips__istiff( const char *filename ); gboolean vips__istifftiled( const char *filename ); @@ -79,7 +79,7 @@ gboolean vips__istifftiled_buffer( const void *buf, size_t len ); int vips__tiff_read_header_buffer( const void *buf, size_t len, VipsImage *out, int page, int n, gboolean autorotate ); int vips__tiff_read_buffer( const void *buf, size_t len, VipsImage *out, - int page, int n, gboolean autorotate, gboolean readbehind ); + int page, int n, gboolean autorotate ); extern const char *vips__foreign_tiff_suffs[]; @@ -149,7 +149,7 @@ int vips__ppm_save( VipsImage *in, const char *filename, int vips__rad_israd( const char *filename ); int vips__rad_header( const char *filename, VipsImage *out ); -int vips__rad_load( const char *filename, VipsImage *out, gboolean readbehind ); +int vips__rad_load( const char *filename, VipsImage *out ); int vips__rad_save( VipsImage *in, const char *filename ); int vips__rad_save_buf( VipsImage *in, void **obuf, size_t *olen ); @@ -172,21 +172,18 @@ int vips__jpeg_write_buffer( VipsImage *in, int vips__isjpeg_buffer( const void *buf, size_t len ); int vips__isjpeg( const char *filename ); int vips__jpeg_read_file( const char *name, VipsImage *out, - gboolean header_only, int shrink, gboolean fail, gboolean readbehind, - gboolean autorotate ); + gboolean header_only, int shrink, gboolean fail, gboolean autorotate ); int vips__jpeg_read_buffer( const void *buf, size_t len, VipsImage *out, - gboolean header_only, int shrink, int fail, gboolean readbehind, - gboolean autorotate ); + gboolean header_only, int shrink, int fail, gboolean autorotate ); int vips__png_header( const char *name, VipsImage *out ); -int vips__png_read( const char *name, VipsImage *out, gboolean readbehind ); +int vips__png_read( const char *name, VipsImage *out ); gboolean vips__png_ispng_buffer( const void *buf, size_t len ); int vips__png_ispng( const char *filename ); gboolean vips__png_isinterlaced( const char *filename ); gboolean vips__png_isinterlaced_buffer( const void *buffer, size_t length ); extern const char *vips__png_suffs[]; -int vips__png_read_buffer( const void *buffer, size_t length, - VipsImage *out, gboolean readbehind ); +int vips__png_read_buffer( const void *buffer, size_t length, VipsImage *out ); int vips__png_header_buffer( const void *buffer, size_t length, VipsImage *out ); diff --git a/libvips/foreign/pngload.c b/libvips/foreign/pngload.c index 7d10605d..01ffb7f1 100644 --- a/libvips/foreign/pngload.c +++ b/libvips/foreign/pngload.c @@ -106,8 +106,7 @@ vips_foreign_load_png_load( VipsForeignLoad *load ) { VipsForeignLoadPng *png = (VipsForeignLoadPng *) load; - if( vips__png_read( png->filename, load->real, - load->access == VIPS_ACCESS_SEQUENTIAL ) ) + if( vips__png_read( png->filename, load->real ) ) return( -1 ); return( 0 ); @@ -202,7 +201,7 @@ vips_foreign_load_png_buffer_load( VipsForeignLoad *load ) VipsForeignLoadPngBuffer *buffer = (VipsForeignLoadPngBuffer *) load; if( vips__png_read_buffer( buffer->buf->data, buffer->buf->length, - load->real, load->access == VIPS_ACCESS_SEQUENTIAL ) ) + load->real ) ) return( -1 ); return( 0 ); diff --git a/libvips/foreign/radiance.c b/libvips/foreign/radiance.c index 23b25361..77b556b5 100644 --- a/libvips/foreign/radiance.c +++ b/libvips/foreign/radiance.c @@ -1084,7 +1084,7 @@ rad2vips_get_header( Read *read, VipsImage *out ) /* Tell downstream we are reading sequentially. */ - vips_image_set_int( out, VIPS_META_SEQUENTIAL, 1 ); + vips_image_set_area( out, VIPS_META_SEQUENTIAL, NULL, NULL ); return( 0 ); } @@ -1140,7 +1140,7 @@ rad2vips_generate( VipsRegion *or, } int -vips__rad_load( const char *filename, VipsImage *out, gboolean readbehind ) +vips__rad_load( const char *filename, VipsImage *out ) { VipsImage **t = (VipsImage **) vips_object_local_array( VIPS_OBJECT( out ), 3 ); @@ -1159,14 +1159,8 @@ vips__rad_load( const char *filename, VipsImage *out, gboolean readbehind ) return( -1 ); if( vips_image_generate( t[0], - NULL, rad2vips_generate, NULL, - read, NULL ) || - vips_sequential( t[0], &t[1], - "tile_height", 8, - "access", readbehind ? - VIPS_ACCESS_SEQUENTIAL : - VIPS_ACCESS_SEQUENTIAL_UNBUFFERED, - NULL ) || + NULL, rad2vips_generate, NULL, read, NULL ) || + vips_sequential( t[0], &t[1], "tile_height", 8, NULL ) || vips_image_write( t[1], out ) ) return( -1 ); diff --git a/libvips/foreign/radload.c b/libvips/foreign/radload.c index 518ae8a8..e35a322b 100644 --- a/libvips/foreign/radload.c +++ b/libvips/foreign/radload.c @@ -100,8 +100,7 @@ vips_foreign_load_rad_load( VipsForeignLoad *load ) { VipsForeignLoadRad *rad = (VipsForeignLoadRad *) load; - if( vips__rad_load( rad->filename, load->real, - load->access == VIPS_ACCESS_SEQUENTIAL ) ) + if( vips__rad_load( rad->filename, load->real ) ) return( -1 ); return( 0 ); diff --git a/libvips/foreign/tiff2vips.c b/libvips/foreign/tiff2vips.c index 12ca7638..72053bad 100644 --- a/libvips/foreign/tiff2vips.c +++ b/libvips/foreign/tiff2vips.c @@ -274,7 +274,6 @@ typedef struct _Rtiff { int page; int n; gboolean autorotate; - gboolean readbehind; /* The TIFF we read. */ @@ -1337,7 +1336,7 @@ rtiff_set_header( Rtiff *rtiff, VipsImage *out ) /* Tell downstream if we are reading sequentially. */ if( !rtiff->header.tiled ) - vips_image_set_int( out, VIPS_META_SEQUENTIAL, 1 ); + vips_image_set_area( out, VIPS_META_SEQUENTIAL, NULL, NULL ); return( 0 ); } @@ -1931,9 +1930,6 @@ rtiff_read_stripwise( Rtiff *rtiff, VipsImage *out ) rtiff, NULL ) || vips_sequential( t[0], &t[1], "tile_height", rtiff->header.rows_per_strip, - "access", rtiff->readbehind ? - VIPS_ACCESS_SEQUENTIAL : - VIPS_ACCESS_SEQUENTIAL_UNBUFFERED, NULL ) || rtiff_autorotate( rtiff, t[1], &t[2] ) || vips_image_write( t[2], out ) ) @@ -1957,8 +1953,7 @@ rtiff_close( VipsObject *object, Rtiff *rtiff ) } static Rtiff * -rtiff_new( VipsImage *out, - int page, int n, gboolean autorotate, gboolean readbehind ) +rtiff_new( VipsImage *out, int page, int n, gboolean autorotate ) { Rtiff *rtiff; @@ -1970,7 +1965,6 @@ rtiff_new( VipsImage *out, rtiff->page = page; rtiff->n = n; rtiff->autorotate = autorotate; - rtiff->readbehind = readbehind; rtiff->tiff = NULL; rtiff->current_page = -1; rtiff->sfn = NULL; @@ -2174,11 +2168,11 @@ rtiff_header_read_all( Rtiff *rtiff ) static Rtiff * rtiff_new_filename( const char *filename, VipsImage *out, - int page, int n, gboolean autorotate, gboolean readbehind ) + int page, int n, gboolean autorotate ) { Rtiff *rtiff; - if( !(rtiff = rtiff_new( out, page, n, autorotate, readbehind )) || + if( !(rtiff = rtiff_new( out, page, n, autorotate )) || !(rtiff->tiff = vips__tiff_openin( filename )) || rtiff_header_read_all( rtiff ) ) return( NULL ); @@ -2190,11 +2184,11 @@ rtiff_new_filename( const char *filename, VipsImage *out, static Rtiff * rtiff_new_buffer( const void *buf, size_t len, VipsImage *out, - int page, int n, gboolean autorotate, gboolean readbehind ) + int page, int n, gboolean autorotate ) { Rtiff *rtiff; - if( !(rtiff = rtiff_new( out, page, n, autorotate, readbehind )) || + if( !(rtiff = rtiff_new( out, page, n, autorotate )) || !(rtiff->tiff = vips__tiff_openin_buffer( out, buf, len )) || rtiff_header_read_all( rtiff ) ) return( NULL ); @@ -2225,7 +2219,7 @@ istiffpyramid( const char *name ) int vips__tiff_read( const char *filename, VipsImage *out, - int page, int n, gboolean autorotate, gboolean readbehind ) + int page, int n, gboolean autorotate ) { Rtiff *rtiff; @@ -2236,8 +2230,7 @@ vips__tiff_read( const char *filename, VipsImage *out, vips__tiff_init(); - if( !(rtiff = rtiff_new_filename( filename, - out, page, n, autorotate, readbehind )) ) + if( !(rtiff = rtiff_new_filename( filename, out, page, n, autorotate )) ) return( -1 ); if( rtiff->header.tiled ) { @@ -2283,8 +2276,7 @@ vips__tiff_read_header( const char *filename, VipsImage *out, vips__tiff_init(); - if( !(rtiff = rtiff_new_filename( filename, out, - page, n, autorotate, FALSE )) ) + if( !(rtiff = rtiff_new_filename( filename, out, page, n, autorotate )) ) return( -1 ); if( rtiff_set_header( rtiff, out ) ) @@ -2352,8 +2344,7 @@ vips__tiff_read_header_buffer( const void *buf, size_t len, VipsImage *out, vips__tiff_init(); - if( !(rtiff = rtiff_new_buffer( buf, len, out, - page, n, autorotate, FALSE )) ) + if( !(rtiff = rtiff_new_buffer( buf, len, out, page, n, autorotate )) ) return( -1 ); if( rtiff_set_header( rtiff, out ) ) @@ -2366,8 +2357,7 @@ vips__tiff_read_header_buffer( const void *buf, size_t len, VipsImage *out, int vips__tiff_read_buffer( const void *buf, size_t len, - VipsImage *out, int page, int n, gboolean autorotate, - gboolean readbehind ) + VipsImage *out, int page, int n, gboolean autorotate ) { Rtiff *rtiff; @@ -2378,8 +2368,7 @@ vips__tiff_read_buffer( const void *buf, size_t len, vips__tiff_init(); - if( !(rtiff = rtiff_new_buffer( buf, len, out, - page, n, autorotate, readbehind )) ) + if( !(rtiff = rtiff_new_buffer( buf, len, out, page, n, autorotate )) ) return( -1 ); if( rtiff->header.tiled ) { diff --git a/libvips/foreign/tiffload.c b/libvips/foreign/tiffload.c index d4152b6f..76d2a365 100644 --- a/libvips/foreign/tiffload.c +++ b/libvips/foreign/tiffload.c @@ -183,8 +183,7 @@ vips_foreign_load_tiff_file_load( VipsForeignLoad *load ) VipsForeignLoadTiffFile *file = (VipsForeignLoadTiffFile *) load; if( vips__tiff_read( file->filename, load->real, - tiff->page, tiff->n, tiff->autorotate, - load->access == VIPS_ACCESS_SEQUENTIAL ) ) + tiff->page, tiff->n, tiff->autorotate ) ) return( -1 ); return( 0 ); @@ -284,8 +283,7 @@ vips_foreign_load_tiff_buffer_load( VipsForeignLoad *load ) if( vips__tiff_read_buffer( buffer->buf->data, buffer->buf->length, load->real, - tiff->page, tiff->n, tiff->autorotate, - load->access == VIPS_ACCESS_SEQUENTIAL ) ) + tiff->page, tiff->n, tiff->autorotate ) ) return( -1 ); return( 0 ); diff --git a/libvips/foreign/vipspng.c b/libvips/foreign/vipspng.c index 38f4be8e..9925ebe9 100644 --- a/libvips/foreign/vipspng.c +++ b/libvips/foreign/vipspng.c @@ -140,7 +140,6 @@ user_warning_function( png_structp png_ptr, png_const_charp warning_msg ) typedef struct { char *name; VipsImage *out; - gboolean readbehind; int y_pos; png_structp pPng; @@ -177,7 +176,7 @@ read_close_cb( VipsImage *out, Read *read ) } static Read * -read_new( VipsImage *out, gboolean readbehind ) +read_new( VipsImage *out ) { Read *read; @@ -185,7 +184,6 @@ read_new( VipsImage *out, gboolean readbehind ) return( NULL ); read->name = NULL; - read->readbehind = readbehind; read->out = out; read->y_pos = 0; read->pPng = NULL; @@ -223,11 +221,11 @@ read_new( VipsImage *out, gboolean readbehind ) } static Read * -read_new_filename( VipsImage *out, const char *name, gboolean readbehind ) +read_new_filename( VipsImage *out, const char *name ) { Read *read; - if( !(read = read_new( out, readbehind )) ) + if( !(read = read_new( out )) ) return( NULL ); read->name = vips_strdup( VIPS_OBJECT( out ), name ); @@ -386,7 +384,7 @@ png2vips_header( Read *read, VipsImage *out ) * read via a huge memory buffer. */ if( interlace_type == PNG_INTERLACE_NONE ) { - vips_image_set_int( out, VIPS_META_SEQUENTIAL, 1 ); + vips_image_set_area( out, VIPS_META_SEQUENTIAL, NULL, NULL ); /* Sequential mode needs thinstrip to work with things like * vips_shrink(). @@ -439,7 +437,7 @@ vips__png_header( const char *name, VipsImage *out ) { Read *read; - if( !(read = read_new_filename( out, name, FALSE )) || + if( !(read = read_new_filename( out, name )) || png2vips_header( read, out ) ) return( -1 ); @@ -568,7 +566,7 @@ vips__png_isinterlaced( const char *filename ) int interlace_type; image = vips_image_new(); - if( !(read = read_new_filename( image, filename, FALSE )) ) { + if( !(read = read_new_filename( image, filename )) ) { g_object_unref( image ); return( -1 ); } @@ -603,9 +601,6 @@ png2vips_image( Read *read, VipsImage *out ) read, NULL ) || vips_sequential( t[0], &t[1], "tile_height", 8, - "access", read->readbehind ? - VIPS_ACCESS_SEQUENTIAL : - VIPS_ACCESS_SEQUENTIAL_UNBUFFERED, NULL ) || vips_image_write( t[1], out ) ) return( -1 ); @@ -615,7 +610,7 @@ png2vips_image( Read *read, VipsImage *out ) } int -vips__png_read( const char *filename, VipsImage *out, gboolean readbehind ) +vips__png_read( const char *filename, VipsImage *out ) { Read *read; @@ -623,7 +618,7 @@ vips__png_read( const char *filename, VipsImage *out, gboolean readbehind ) printf( "vips__png_read: reading \"%s\"\n", filename ); #endif /*DEBUG*/ - if( !(read = read_new_filename( out, filename, readbehind )) || + if( !(read = read_new_filename( out, filename )) || png2vips_image( read, out ) ) return( -1 ); @@ -670,12 +665,11 @@ vips_png_read_buffer( png_structp pPng, png_bytep data, png_size_t length ) } static Read * -read_new_buffer( VipsImage *out, const void *buffer, size_t length, - gboolean readbehind ) +read_new_buffer( VipsImage *out, const void *buffer, size_t length ) { Read *read; - if( !(read = read_new( out, readbehind )) ) + if( !(read = read_new( out )) ) return( NULL ); read->length = length; @@ -701,7 +695,7 @@ vips__png_header_buffer( const void *buffer, size_t length, VipsImage *out ) { Read *read; - if( !(read = read_new_buffer( out, buffer, length, FALSE )) || + if( !(read = read_new_buffer( out, buffer, length )) || png2vips_header( read, out ) ) return( -1 ); @@ -709,12 +703,11 @@ vips__png_header_buffer( const void *buffer, size_t length, VipsImage *out ) } int -vips__png_read_buffer( const void *buffer, size_t length, VipsImage *out, - gboolean readbehind ) +vips__png_read_buffer( const void *buffer, size_t length, VipsImage *out ) { Read *read; - if( !(read = read_new_buffer( out, buffer, length, readbehind )) || + if( !(read = read_new_buffer( out, buffer, length )) || png2vips_image( read, out ) ) return( -1 ); @@ -733,7 +726,7 @@ vips__png_isinterlaced_buffer( const void *buffer, size_t length ) image = vips_image_new(); - if( !(read = read_new_buffer( image, buffer, length, FALSE )) ) { + if( !(read = read_new_buffer( image, buffer, length )) ) { g_object_unref( image ); return( -1 ); } diff --git a/libvips/histogram/maplut.c b/libvips/histogram/maplut.c index 95cb7054..f1dce435 100644 --- a/libvips/histogram/maplut.c +++ b/libvips/histogram/maplut.c @@ -688,7 +688,7 @@ vips_maplut_class_init( VipsMaplutClass *class ) object_class->description = _( "map an image though a lut" ); object_class->build = vips_maplut_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; VIPS_ARG_IMAGE( class, "in", 1, _( "Input" ), diff --git a/libvips/iofuncs/image.c b/libvips/iofuncs/image.c index 79475600..3a8cbfd8 100644 --- a/libvips/iofuncs/image.c +++ b/libvips/iofuncs/image.c @@ -147,7 +147,6 @@ * VipsAccess: * @VIPS_ACCESS_RANDOM: can read anywhere * @VIPS_ACCESS_SEQUENTIAL: top-to-bottom reading only, but with a small buffer - * @VIPS_ACCESS_SEQUENTIAL_UNBUFFERED: top-to-bottom reading only * * The type of access an operation has to supply. See vips_tilecache() * and #VipsForeign. @@ -156,9 +155,6 @@ * * @VIPS_ACCESS_SEQUENTIAL means requests will be top-to-bottom, but with some * amount of buffering behind the read point for small non-local accesses. - * - * @VIPS_ACCESS_SEQUENTIAL_UNBUFFERED means requests will be strictly - * top-to-bottom with no read-behind. This can save some memory. */ /** @@ -1856,9 +1852,7 @@ vips_filename_get_options( const char *vips_filename ) * whole image exactly once, top-to-bottom. In this mode, vips can avoid * converting the whole image in one go, for a large memory saving. You are * allowed to make small non-local references, so area operations like - * convolution will work. #VIPS_ACCESS_SEQUENTIAL_UNBUFFERED does not allow - * non-local references, so will only work for very strict top-to-bottom - * operations, but does have very low memory needs. + * convolution will work. * * In #VIPS_ACCESS_RANDOM mode, small images are decompressed to memory and * then processed from there. Large images are decompressed to temporary diff --git a/libvips/iofuncs/object.c b/libvips/iofuncs/object.c index 77841dcc..bfa5e505 100644 --- a/libvips/iofuncs/object.c +++ b/libvips/iofuncs/object.c @@ -1830,9 +1830,8 @@ vips_object_set_argument_from_string( VipsObject *object, /* Read the filename. */ - if( flags & VIPS_OPERATION_SEQUENTIAL_UNBUFFERED ) - access = VIPS_ACCESS_SEQUENTIAL_UNBUFFERED; - else if( flags & VIPS_OPERATION_SEQUENTIAL ) + if( flags & (VIPS_OPERATION_SEQUENTIAL_UNBUFFERED | + VIPS_OPERATION_SEQUENTIAL) ) access = VIPS_ACCESS_SEQUENTIAL; else access = VIPS_ACCESS_RANDOM; @@ -1869,9 +1868,8 @@ vips_object_set_argument_from_string( VipsObject *object, flags = vips_operation_get_flags( VIPS_OPERATION( object ) ); - if( flags & VIPS_OPERATION_SEQUENTIAL_UNBUFFERED ) - access = VIPS_ACCESS_SEQUENTIAL_UNBUFFERED; - else if( flags & VIPS_OPERATION_SEQUENTIAL ) + if( flags & (VIPS_OPERATION_SEQUENTIAL_UNBUFFERED | + VIPS_OPERATION_SEQUENTIAL) ) access = VIPS_ACCESS_SEQUENTIAL; else access = VIPS_ACCESS_RANDOM; diff --git a/libvips/iofuncs/operation.c b/libvips/iofuncs/operation.c index e9065549..0d6760b9 100644 --- a/libvips/iofuncs/operation.c +++ b/libvips/iofuncs/operation.c @@ -169,7 +169,6 @@ * VipsOperationFlags: * @VIPS_OPERATION_NONE: no flags * @VIPS_OPERATION_SEQUENTIAL: can work sequentially with a small buffer - * @VIPS_OPERATION_SEQUENTIAL_UNBUFFERED: can work sequentially with no buffer * @VIPS_OPERATION_NOCACHE: must not be cached * @VIPS_OPERATION_DEPRECATED: a compatibility thing * @@ -184,10 +183,6 @@ * not at the top of the image. In this case, the first part of the image will * be read and discarded * - * @VIPS_OPERATION_SEQUENTIAL_UNBUFFERED means that the operation works like - * vips_copy(): it can process images top-to-bottom and makes no - * non-local references. - * * Every scan-line must be requested, you are not allowed to skip * ahead, but as a special case, the very first request can be for a region * not at the top of the image. In this case, the first part of the image will diff --git a/libvips/resample/resize.c b/libvips/resample/resize.c index c3667dae..19b6fdbb 100644 --- a/libvips/resample/resize.c +++ b/libvips/resample/resize.c @@ -22,6 +22,8 @@ * - more accurate resizing * 9/9/16 * - add @centre option + * 6/3/17 + * - moved the cache to shrinkv */ /* diff --git a/libvips/resample/shrinkh.c b/libvips/resample/shrinkh.c index 1f704d22..e44f8352 100644 --- a/libvips/resample/shrinkh.c +++ b/libvips/resample/shrinkh.c @@ -316,7 +316,7 @@ vips_shrinkh_class_init( VipsShrinkhClass *class ) vobject_class->description = _( "shrink an image horizontally" ); vobject_class->build = vips_shrinkh_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; VIPS_ARG_INT( class, "hshrink", 8, _( "Hshrink" ), diff --git a/libvips/resample/shrinkv.c b/libvips/resample/shrinkv.c index 1b4a96b9..087db3ef 100644 --- a/libvips/resample/shrinkv.c +++ b/libvips/resample/shrinkv.c @@ -457,7 +457,7 @@ vips_shrinkv_class_init( VipsShrinkvClass *class ) vobject_class->description = _( "shrink an image vertically" ); vobject_class->build = vips_shrinkv_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; VIPS_ARG_INT( class, "vshrink", 9, _( "Vshrink" ), diff --git a/libvips/resample/thumbnail.c b/libvips/resample/thumbnail.c index 2894138f..b4ac77e4 100644 --- a/libvips/resample/thumbnail.c +++ b/libvips/resample/thumbnail.c @@ -376,10 +376,6 @@ vips_thumbnail_build( VipsObject *object ) shrink = vips_thumbnail_calculate_shrink( thumbnail, in->Xsize, in->Ysize ); - - - - /* Use centre convention to better match imagemagick. */ if( vips_resize( in, &t[4], 1.0 / shrink, diff --git a/test/test_seq.sh b/test/test_seq.sh index 627943e0..0474bbc1 100755 --- a/test/test_seq.sh +++ b/test/test_seq.sh @@ -43,3 +43,12 @@ if ! $vipsheader $tmp/x.png > /dev/null 2>&1 ; then exit 1 fi echo "ok" + +printf "testing reduce does not make temps ... " +rm -f $tmp/x.png +$vips reduce $huge $tmp/x.png 3 3 +if ! $vipsheader $tmp/x.png > /dev/null 2>&1 ; then + echo "reduce made a temp" + exit 1 +fi +echo "ok"