argh reapply seq removal
This commit is contained in:
parent
8c4abf7c42
commit
362c7efdfc
12
TODO
12
TODO
@ -1,14 +1,6 @@
|
|||||||
|
- check initial cache sizing in vips_line_cache_build
|
||||||
- VIPS_META_SEQUENTIAL will be saved to vips files, then loaded back again argh
|
|
||||||
|
|
||||||
we need to set a value that can't be saved
|
what about dynamic cache sizing?
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -633,7 +633,7 @@ vips_arithmetic_class_init( VipsArithmeticClass *class )
|
|||||||
vobject_class->description = _( "arithmetic operations" );
|
vobject_class->description = _( "arithmetic operations" );
|
||||||
vobject_class->build = vips_arithmetic_build;
|
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,
|
VIPS_ARG_IMAGE( class, "out", 100,
|
||||||
_( "Output" ),
|
_( "Output" ),
|
||||||
|
@ -161,7 +161,7 @@ vips_statistic_class_init( VipsStatisticClass *class )
|
|||||||
vobject_class->description = _( "VIPS statistic operations" );
|
vobject_class->description = _( "VIPS statistic operations" );
|
||||||
vobject_class->build = vips_statistic_build;
|
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,
|
VIPS_ARG_IMAGE( class, "in", 0,
|
||||||
_( "Input" ),
|
_( "Input" ),
|
||||||
|
@ -421,7 +421,7 @@ vips_colour_class_init( VipsColourClass *class )
|
|||||||
vobject_class->description = _( "color operations" );
|
vobject_class->description = _( "color operations" );
|
||||||
vobject_class->build = vips_colour_build;
|
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,
|
VIPS_ARG_IMAGE( class, "out", 100,
|
||||||
_( "Output" ),
|
_( "Output" ),
|
||||||
|
@ -580,7 +580,7 @@ vips_colourspace_class_init( VipsColourspaceClass *class )
|
|||||||
vobject_class->description = _( "convert to a new colorspace" );
|
vobject_class->description = _( "convert to a new colorspace" );
|
||||||
vobject_class->build = vips_colourspace_build;
|
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,
|
VIPS_ARG_IMAGE( class, "in", 1,
|
||||||
_( "Input" ),
|
_( "Input" ),
|
||||||
|
@ -237,7 +237,7 @@ vips_sRGB2scRGB_class_init( VipssRGB2scRGBClass *class )
|
|||||||
object_class->description = _( "convert an sRGB image to scRGB" );
|
object_class->description = _( "convert an sRGB image to scRGB" );
|
||||||
object_class->build = vips_sRGB2scRGB_build;
|
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,
|
VIPS_ARG_IMAGE( class, "in", 1,
|
||||||
_( "Input" ),
|
_( "Input" ),
|
||||||
|
@ -231,7 +231,7 @@ vips_scRGB2BW_class_init( VipsscRGB2BWClass *class )
|
|||||||
object_class->description = _( "convert scRGB to BW" );
|
object_class->description = _( "convert scRGB to BW" );
|
||||||
object_class->build = vips_scRGB2BW_build;
|
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,
|
VIPS_ARG_IMAGE( class, "in", 1,
|
||||||
_( "Input" ),
|
_( "Input" ),
|
||||||
|
@ -259,7 +259,7 @@ vips_scRGB2sRGB_class_init( VipsscRGB2sRGBClass *class )
|
|||||||
object_class->description = _( "convert an scRGB image to sRGB" );
|
object_class->description = _( "convert an scRGB image to sRGB" );
|
||||||
object_class->build = vips_scRGB2sRGB_build;
|
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,
|
VIPS_ARG_IMAGE( class, "in", 1,
|
||||||
_( "Input" ),
|
_( "Input" ),
|
||||||
|
@ -298,7 +298,7 @@ vips_arrayjoin_class_init( VipsArrayjoinClass *class )
|
|||||||
vobject_class->description = _( "join an array of images" );
|
vobject_class->description = _( "join an array of images" );
|
||||||
vobject_class->build = vips_arrayjoin_build;
|
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,
|
VIPS_ARG_BOXED( class, "in", -1,
|
||||||
_( "Input" ),
|
_( "Input" ),
|
||||||
|
@ -186,7 +186,7 @@ vips_bandary_class_init( VipsBandaryClass *class )
|
|||||||
vobject_class->description = _( "operations on image bands" );
|
vobject_class->description = _( "operations on image bands" );
|
||||||
vobject_class->build = vips_bandary_build;
|
vobject_class->build = vips_bandary_build;
|
||||||
|
|
||||||
operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED;
|
operation_class->flags = VIPS_OPERATION_SEQUENTIAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -154,7 +154,7 @@ vips_bandfold_class_init( VipsBandfoldClass *class )
|
|||||||
vobject_class->description = _( "fold up x axis into bands" );
|
vobject_class->description = _( "fold up x axis into bands" );
|
||||||
vobject_class->build = vips_bandfold_build;
|
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,
|
VIPS_ARG_IMAGE( class, "in", 1,
|
||||||
_( "Input" ),
|
_( "Input" ),
|
||||||
|
@ -157,7 +157,7 @@ vips_bandunfold_class_init( VipsBandunfoldClass *class )
|
|||||||
vobject_class->description = _( "unfold image bands into x axis" );
|
vobject_class->description = _( "unfold image bands into x axis" );
|
||||||
vobject_class->build = vips_bandunfold_build;
|
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,
|
VIPS_ARG_IMAGE( class, "in", 1,
|
||||||
_( "Input" ),
|
_( "Input" ),
|
||||||
|
@ -200,7 +200,7 @@ vips_byteswap_class_init( VipsByteswapClass *class )
|
|||||||
vobject_class->description = _( "byteswap an image" );
|
vobject_class->description = _( "byteswap an image" );
|
||||||
vobject_class->build = vips_byteswap_build;
|
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,
|
VIPS_ARG_IMAGE( class, "in", 1,
|
||||||
_( "Input" ),
|
_( "Input" ),
|
||||||
|
@ -542,7 +542,7 @@ vips_cast_class_init( VipsCastClass *class )
|
|||||||
vobject_class->description = _( "cast an image" );
|
vobject_class->description = _( "cast an image" );
|
||||||
vobject_class->build = vips_cast_build;
|
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,
|
VIPS_ARG_IMAGE( class, "in", 1,
|
||||||
_( "Input" ),
|
_( "Input" ),
|
||||||
|
@ -264,7 +264,7 @@ vips_copy_class_init( VipsCopyClass *class )
|
|||||||
* cache it. Plus copy is cheap.
|
* cache it. Plus copy is cheap.
|
||||||
*/
|
*/
|
||||||
operation_class->flags =
|
operation_class->flags =
|
||||||
VIPS_OPERATION_SEQUENTIAL_UNBUFFERED |
|
VIPS_OPERATION_SEQUENTIAL |
|
||||||
VIPS_OPERATION_NOCACHE;
|
VIPS_OPERATION_NOCACHE;
|
||||||
|
|
||||||
VIPS_ARG_IMAGE( class, "in", 1,
|
VIPS_ARG_IMAGE( class, "in", 1,
|
||||||
|
@ -557,7 +557,7 @@ vips_embed_class_init( VipsEmbedClass *class )
|
|||||||
vobject_class->description = _( "embed an image in a larger image" );
|
vobject_class->description = _( "embed an image in a larger image" );
|
||||||
vobject_class->build = vips_embed_build;
|
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,
|
VIPS_ARG_IMAGE( class, "in", -1,
|
||||||
_( "Input" ),
|
_( "Input" ),
|
||||||
|
@ -188,7 +188,7 @@ vips_extract_area_class_init( VipsExtractAreaClass *class )
|
|||||||
vobject_class->description = _( "extract an area from an image" );
|
vobject_class->description = _( "extract an area from an image" );
|
||||||
vobject_class->build = vips_extract_area_build;
|
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,
|
VIPS_ARG_IMAGE( class, "input", 0,
|
||||||
_( "Input" ),
|
_( "Input" ),
|
||||||
|
@ -375,7 +375,7 @@ vips_falsecolour_class_init( VipsFalsecolourClass *class )
|
|||||||
vobject_class->description = _( "false-color an image" );
|
vobject_class->description = _( "false-color an image" );
|
||||||
vobject_class->build = vips_falsecolour_build;
|
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,
|
VIPS_ARG_IMAGE( class, "in", 0,
|
||||||
_( "in" ),
|
_( "in" ),
|
||||||
|
@ -380,7 +380,7 @@ vips_flatten_class_init( VipsFlattenClass *class )
|
|||||||
vobject_class->description = _( "flatten alpha out of an image" );
|
vobject_class->description = _( "flatten alpha out of an image" );
|
||||||
vobject_class->build = vips_flatten_build;
|
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,
|
VIPS_ARG_IMAGE( class, "in", 1,
|
||||||
_( "Input" ),
|
_( "Input" ),
|
||||||
|
@ -137,7 +137,7 @@ vips_gamma_class_init( VipsGammaClass *class )
|
|||||||
vobject_class->description = _( "gamma an image" );
|
vobject_class->description = _( "gamma an image" );
|
||||||
vobject_class->build = vips_gamma_build;
|
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,
|
VIPS_ARG_IMAGE( class, "in", -1,
|
||||||
_( "in" ),
|
_( "in" ),
|
||||||
|
@ -238,7 +238,7 @@ vips_msb_class_init( VipsMsbClass *class )
|
|||||||
_( "pick most-significant byte from an image" );
|
_( "pick most-significant byte from an image" );
|
||||||
vobject_class->build = vips_msb_build;
|
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,
|
VIPS_ARG_IMAGE( class, "in", 0,
|
||||||
_( "Input" ),
|
_( "Input" ),
|
||||||
|
@ -253,7 +253,7 @@ vips_premultiply_class_init( VipsPremultiplyClass *class )
|
|||||||
vobject_class->description = _( "premultiply image alpha" );
|
vobject_class->description = _( "premultiply image alpha" );
|
||||||
vobject_class->build = vips_premultiply_build;
|
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,
|
VIPS_ARG_IMAGE( class, "in", 1,
|
||||||
_( "Input" ),
|
_( "Input" ),
|
||||||
|
@ -201,7 +201,7 @@ vips_recomb_class_init( VipsRecombClass *class )
|
|||||||
object_class->description = _( "linear recombination with matrix" );
|
object_class->description = _( "linear recombination with matrix" );
|
||||||
object_class->build = vips_recomb_build;
|
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,
|
VIPS_ARG_IMAGE( class, "in", 0,
|
||||||
_( "Input" ),
|
_( "Input" ),
|
||||||
|
@ -21,6 +21,8 @@
|
|||||||
* this broke on some busy, many-core systems, see comment below
|
* this broke on some busy, many-core systems, see comment below
|
||||||
* 10/6/14
|
* 10/6/14
|
||||||
* - re-enable skipahead now we have the single-thread-first-tile idea
|
* - 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"
|
#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 {
|
typedef struct _VipsSequential {
|
||||||
VipsConversion parent_instance;
|
VipsConversion parent_instance;
|
||||||
|
|
||||||
@ -87,11 +80,9 @@ typedef struct _VipsSequential {
|
|||||||
VipsAccess access;
|
VipsAccess access;
|
||||||
gboolean trace;
|
gboolean trace;
|
||||||
|
|
||||||
/* Lock access to y_pos with this, use the cond to wake up stalled
|
/* Lock access to y_pos with this.
|
||||||
* threads.
|
|
||||||
*/
|
*/
|
||||||
GMutex *lock;
|
GMutex *lock;
|
||||||
GCond *ready;
|
|
||||||
|
|
||||||
/* The next read from our source will fetch this scanline, ie. it's 0
|
/* The next read from our source will fetch this scanline, ie. it's 0
|
||||||
* when we start.
|
* when we start.
|
||||||
@ -114,7 +105,6 @@ vips_sequential_dispose( GObject *gobject )
|
|||||||
VipsSequential *sequential = (VipsSequential *) gobject;
|
VipsSequential *sequential = (VipsSequential *) gobject;
|
||||||
|
|
||||||
VIPS_FREEF( vips_g_mutex_free, sequential->lock );
|
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 );
|
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",
|
VIPS_DEBUG_MSG_GREEN( "thread %p request for line %d, height %d\n",
|
||||||
g_thread_self(), r->top, r->height );
|
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" );
|
VIPS_GATE_START( "vips_sequential_generate: wait" );
|
||||||
|
|
||||||
g_mutex_lock( sequential->lock );
|
g_mutex_lock( sequential->lock );
|
||||||
|
|
||||||
VIPS_GATE_STOP( "vips_sequential_generate: wait" );
|
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 we've seen an error, everything must stop.
|
||||||
*/
|
*/
|
||||||
if( sequential->error ) {
|
if( sequential->error ) {
|
||||||
@ -149,68 +133,8 @@ vips_sequential_generate( VipsRegion *or,
|
|||||||
return( -1 );
|
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 ) {
|
if( r->top > sequential->y_pos ) {
|
||||||
/* This is a request for something some way down the image,
|
/* This is a request for something some way down the image.
|
||||||
* and we've fallen through from the stall above.
|
|
||||||
*
|
|
||||||
* Probably the operation is something like extract_area and
|
* Probably the operation is something like extract_area and
|
||||||
* we should skip the initial part of the image. In fact,
|
* we should skip the initial part of the image. In fact,
|
||||||
* we read to cache, since it may be useful.
|
* we read to cache, since it may be useful.
|
||||||
@ -226,10 +150,7 @@ vips_sequential_generate( VipsRegion *or,
|
|||||||
area.width = 1;
|
area.width = 1;
|
||||||
area.height = r->top - sequential->y_pos;
|
area.height = r->top - sequential->y_pos;
|
||||||
if( vips_region_prepare( ir, &area ) ) {
|
if( vips_region_prepare( ir, &area ) ) {
|
||||||
VIPS_DEBUG_MSG( "thread %p error, unlocking #1 ...\n",
|
|
||||||
g_thread_self() );
|
|
||||||
sequential->error = -1;
|
sequential->error = -1;
|
||||||
g_cond_broadcast( sequential->ready );
|
|
||||||
g_mutex_unlock( sequential->lock );
|
g_mutex_unlock( sequential->lock );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
@ -240,32 +161,14 @@ vips_sequential_generate( VipsRegion *or,
|
|||||||
/* This is a request for old or present pixels -- serve from cache.
|
/* This is a request for old or present pixels -- serve from cache.
|
||||||
* This may trigger further, sequential reads.
|
* This may trigger further, sequential reads.
|
||||||
*/
|
*/
|
||||||
VIPS_DEBUG_MSG_GREEN( "thread %p reading ...\n", g_thread_self() );
|
|
||||||
if( vips_region_prepare( ir, r ) ||
|
if( vips_region_prepare( ir, r ) ||
|
||||||
vips_region_region( or, ir, r, r->left, r->top ) ) {
|
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;
|
sequential->error = -1;
|
||||||
g_cond_broadcast( sequential->ready );
|
|
||||||
g_mutex_unlock( sequential->lock );
|
g_mutex_unlock( sequential->lock );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( VIPS_RECT_BOTTOM( r ) > sequential->y_pos ) {
|
sequential->y_pos = VIPS_MAX( sequential->y_pos, VIPS_RECT_BOTTOM( r ) );
|
||||||
/* 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() );
|
|
||||||
|
|
||||||
g_mutex_unlock( sequential->lock );
|
g_mutex_unlock( sequential->lock );
|
||||||
|
|
||||||
@ -285,12 +188,9 @@ vips_sequential_build( VipsObject *object )
|
|||||||
if( VIPS_OBJECT_CLASS( vips_sequential_parent_class )->build( object ) )
|
if( VIPS_OBJECT_CLASS( vips_sequential_parent_class )->build( object ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
if( vips_image_pio_input( sequential->in ) )
|
|
||||||
return( -1 );
|
|
||||||
|
|
||||||
if( vips_linecache( sequential->in, &t,
|
if( vips_linecache( sequential->in, &t,
|
||||||
"tile_height", sequential->tile_height,
|
"tile_height", sequential->tile_height,
|
||||||
"access", sequential->access,
|
"access", VIPS_ACCESS_SEQUENTIAL,
|
||||||
NULL ) )
|
NULL ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
@ -329,13 +229,6 @@ vips_sequential_class_init( VipsSequentialClass *class )
|
|||||||
VIPS_ARGUMENT_REQUIRED_INPUT,
|
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||||
G_STRUCT_OFFSET( VipsSequential, in ) );
|
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,
|
VIPS_ARG_INT( class, "tile_height", 3,
|
||||||
_( "Tile height" ),
|
_( "Tile height" ),
|
||||||
_( "Tile height in pixels" ),
|
_( "Tile height in pixels" ),
|
||||||
@ -343,21 +236,27 @@ vips_sequential_class_init( VipsSequentialClass *class )
|
|||||||
G_STRUCT_OFFSET( VipsSequential, tile_height ),
|
G_STRUCT_OFFSET( VipsSequential, tile_height ),
|
||||||
1, 1000000, 1 );
|
1, 1000000, 1 );
|
||||||
|
|
||||||
|
|
||||||
VIPS_ARG_ENUM( class, "access", 6,
|
VIPS_ARG_ENUM( class, "access", 6,
|
||||||
_( "Strategy" ),
|
_( "Strategy" ),
|
||||||
_( "Expected access pattern" ),
|
_( "Expected access pattern" ),
|
||||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
VIPS_ARGUMENT_OPTIONAL_INPUT | VIPS_ARGUMENT_DEPRECATED,
|
||||||
G_STRUCT_OFFSET( VipsSequential, access ),
|
G_STRUCT_OFFSET( VipsSequential, access ),
|
||||||
VIPS_TYPE_ACCESS, VIPS_ACCESS_SEQUENTIAL );
|
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
|
static void
|
||||||
vips_sequential_init( VipsSequential *sequential )
|
vips_sequential_init( VipsSequential *sequential )
|
||||||
{
|
{
|
||||||
sequential->trace = FALSE;
|
|
||||||
sequential->access = VIPS_ACCESS_SEQUENTIAL;
|
|
||||||
sequential->lock = vips_g_mutex_new();
|
sequential->lock = vips_g_mutex_new();
|
||||||
sequential->ready = vips_g_cond_new();
|
|
||||||
sequential->tile_height = 1;
|
sequential->tile_height = 1;
|
||||||
sequential->error = 0;
|
sequential->error = 0;
|
||||||
}
|
}
|
||||||
@ -370,28 +269,16 @@ vips_sequential_init( VipsSequential *sequential )
|
|||||||
*
|
*
|
||||||
* Optional arguments:
|
* Optional arguments:
|
||||||
*
|
*
|
||||||
* * @trace: trace requests
|
|
||||||
* * @strip_height: height of cache strips
|
* * @strip_height: height of cache strips
|
||||||
* * @access: access pattern
|
|
||||||
*
|
*
|
||||||
* This operation behaves rather like vips_copy() between images
|
* This operation behaves rather like vips_copy() between images
|
||||||
* @in and @out, except that it checks that pixels are only requested
|
* @in and @out, except that it checks that pixels on @in are only requested
|
||||||
* top-to-bottom. If a thread makes an out of order request, it is stalled
|
* top-to-bottom. This operation is useful for loading file formats which are
|
||||||
* until the pack catches up.
|
|
||||||
*
|
|
||||||
* This operation is useful for loading file formats which are
|
|
||||||
* strictly top-to-bottom, like PNG.
|
* 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
|
* @strip_height can be used to set the size of the tiles that
|
||||||
* vips_sequential() uses. The default value is 1.
|
* 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().
|
* See also: vips_cache(), vips_linecache(), vips_tilecache().
|
||||||
*
|
*
|
||||||
* Returns: 0 on success, -1 on error.
|
* Returns: 0 on success, -1 on error.
|
||||||
|
@ -842,7 +842,7 @@ vips_tile_cache_init( VipsTileCache *cache )
|
|||||||
*
|
*
|
||||||
* When the cache fills, a tile is chosen for reuse. If @access is
|
* 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
|
* #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.
|
* the top-most tile is reused.
|
||||||
*
|
*
|
||||||
* By default, @tile_width and @tile_height are 128 pixels, and the operation
|
* 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;
|
VipsBlockCache *block_cache = (VipsBlockCache *) object;
|
||||||
VipsLineCache *cache = (VipsLineCache *) object;
|
VipsLineCache *cache = (VipsLineCache *) object;
|
||||||
|
|
||||||
|
int tile_width;
|
||||||
|
int tile_height;
|
||||||
|
int n_lines;
|
||||||
|
|
||||||
VIPS_DEBUG_MSG( "vips_line_cache_build\n" );
|
VIPS_DEBUG_MSG( "vips_line_cache_build\n" );
|
||||||
|
|
||||||
if( VIPS_OBJECT_CLASS( vips_line_cache_parent_class )->
|
if( VIPS_OBJECT_CLASS( vips_line_cache_parent_class )->
|
||||||
@ -929,31 +933,13 @@ vips_line_cache_build( VipsObject *object )
|
|||||||
|
|
||||||
block_cache->access = cache->access;
|
block_cache->access = cache->access;
|
||||||
|
|
||||||
if( cache->access == VIPS_ACCESS_SEQUENTIAL_UNBUFFERED )
|
/* This can go up with request size, see vips_line_cache_gen().
|
||||||
/* A tile per thread.
|
*/
|
||||||
*
|
vips_get_tile_size( block_cache->in,
|
||||||
* Imagine scanline tiles and four threads. And add a bit for
|
&tile_width, &tile_height, &n_lines );
|
||||||
* slop.
|
block_cache->max_tiles = 1 + 2 * n_lines / block_cache->tile_height;
|
||||||
*/
|
|
||||||
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;
|
|
||||||
|
|
||||||
vips_get_tile_size( block_cache->in,
|
VIPS_DEBUG_MSG( "vips_line_cache_build: n_lines = %d\n", n_lines );
|
||||||
&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: "
|
VIPS_DEBUG_MSG( "vips_line_cache_build: "
|
||||||
"max_tiles = %d, tile_height = %d\n",
|
"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.
|
* @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
|
* 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
|
* access.
|
||||||
* save some memory and set @access to #VIPS_ACCESS_SEQUENTIAL_UNBUFFERED.
|
|
||||||
*
|
*
|
||||||
* Each cache tile is made with a single call to
|
* Each cache tile is made with a single call to
|
||||||
* vips_region_prepare().
|
* vips_region_prepare().
|
||||||
*
|
*
|
||||||
* When the cache fills, a tile is chosen for reuse. If @access is
|
* 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
|
* #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.
|
* 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
|
* @tile_height can be used to set the size of the strips that
|
||||||
|
@ -262,7 +262,7 @@ vips_unpremultiply_class_init( VipsUnpremultiplyClass *class )
|
|||||||
vobject_class->description = _( "unpremultiply image alpha" );
|
vobject_class->description = _( "unpremultiply image alpha" );
|
||||||
vobject_class->build = vips_unpremultiply_build;
|
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,
|
VIPS_ARG_IMAGE( class, "in", 1,
|
||||||
_( "Input" ),
|
_( "Input" ),
|
||||||
|
@ -372,7 +372,7 @@ vips_zoom_class_init( VipsZoomClass *class )
|
|||||||
vobject_class->description = _( "zoom an image" );
|
vobject_class->description = _( "zoom an image" );
|
||||||
vobject_class->build = vips_zoom_build;
|
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,
|
VIPS_ARG_IMAGE( class, "input", 0,
|
||||||
_( "Input" ),
|
_( "Input" ),
|
||||||
|
@ -111,7 +111,7 @@ jpeg2vips( const char *name, IMAGE *out, gboolean header_only )
|
|||||||
|
|
||||||
#ifdef HAVE_JPEG
|
#ifdef HAVE_JPEG
|
||||||
if( vips__jpeg_read_file( filename, out,
|
if( vips__jpeg_read_file( filename, out,
|
||||||
header_only, shrink, fail_on_warn, TRUE, FALSE ) )
|
header_only, shrink, fail_on_warn, FALSE ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
#else
|
#else
|
||||||
vips_error( "im_jpeg2vips",
|
vips_error( "im_jpeg2vips",
|
||||||
|
@ -87,7 +87,7 @@ png2vips( const char *name, IMAGE *out, gboolean header_only )
|
|||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if( vips__png_read( filename, out, TRUE ) )
|
if( vips__png_read( filename, out ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
@ -98,7 +98,7 @@ tiff2vips( const char *name, IMAGE *out, gboolean header_only )
|
|||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if( vips__tiff_read( filename, out, page, 1, FALSE, TRUE ) )
|
if( vips__tiff_read( filename, out, page, 1, FALSE ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
@ -1502,7 +1502,7 @@ vips_foreign_save_class_init( VipsForeignSaveClass *class )
|
|||||||
* write and interlaced png write, which are not, add extra caches
|
* write and interlaced png write, which are not, add extra caches
|
||||||
* on their input.
|
* on their input.
|
||||||
*/
|
*/
|
||||||
operation_class->flags |= VIPS_OPERATION_SEQUENTIAL_UNBUFFERED;
|
operation_class->flags |= VIPS_OPERATION_SEQUENTIAL;
|
||||||
|
|
||||||
/* Must not cache savers.
|
/* Must not cache savers.
|
||||||
*/
|
*/
|
||||||
|
@ -152,10 +152,6 @@ typedef struct _ReadJpeg {
|
|||||||
*/
|
*/
|
||||||
gboolean fail;
|
gboolean fail;
|
||||||
|
|
||||||
/* Use a read behind buffer.
|
|
||||||
*/
|
|
||||||
gboolean readbehind;
|
|
||||||
|
|
||||||
/* Used for file input only.
|
/* Used for file input only.
|
||||||
*/
|
*/
|
||||||
char *filename;
|
char *filename;
|
||||||
@ -216,8 +212,7 @@ readjpeg_close( VipsObject *object, ReadJpeg *jpeg )
|
|||||||
}
|
}
|
||||||
|
|
||||||
static ReadJpeg *
|
static ReadJpeg *
|
||||||
readjpeg_new( VipsImage *out,
|
readjpeg_new( VipsImage *out, int shrink, gboolean fail, gboolean autorotate )
|
||||||
int shrink, gboolean fail, gboolean readbehind, gboolean autorotate )
|
|
||||||
{
|
{
|
||||||
ReadJpeg *jpeg;
|
ReadJpeg *jpeg;
|
||||||
|
|
||||||
@ -227,7 +222,6 @@ readjpeg_new( VipsImage *out,
|
|||||||
jpeg->out = out;
|
jpeg->out = out;
|
||||||
jpeg->shrink = shrink;
|
jpeg->shrink = shrink;
|
||||||
jpeg->fail = fail;
|
jpeg->fail = fail;
|
||||||
jpeg->readbehind = readbehind;
|
|
||||||
jpeg->filename = NULL;
|
jpeg->filename = NULL;
|
||||||
jpeg->cinfo.err = jpeg_std_error( &jpeg->eman.pub );
|
jpeg->cinfo.err = jpeg_std_error( &jpeg->eman.pub );
|
||||||
jpeg->eman.pub.error_exit = vips__new_error_exit;
|
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.
|
/* 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 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
@ -680,9 +674,6 @@ read_jpeg_image( ReadJpeg *jpeg, VipsImage *out )
|
|||||||
jpeg, NULL ) ||
|
jpeg, NULL ) ||
|
||||||
vips_sequential( t[0], &t[1],
|
vips_sequential( t[0], &t[1],
|
||||||
"tile_height", 8,
|
"tile_height", 8,
|
||||||
"access", jpeg->readbehind ?
|
|
||||||
VIPS_ACCESS_SEQUENTIAL :
|
|
||||||
VIPS_ACCESS_SEQUENTIAL_UNBUFFERED,
|
|
||||||
NULL ) )
|
NULL ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
@ -751,13 +742,12 @@ vips__jpeg_read( ReadJpeg *jpeg, VipsImage *out, gboolean header_only )
|
|||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
vips__jpeg_read_file( const char *filename, VipsImage *out,
|
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 )
|
gboolean autorotate )
|
||||||
{
|
{
|
||||||
ReadJpeg *jpeg;
|
ReadJpeg *jpeg;
|
||||||
|
|
||||||
if( !(jpeg = readjpeg_new( out,
|
if( !(jpeg = readjpeg_new( out, shrink, fail, autorotate )) )
|
||||||
shrink, fail, readbehind, autorotate )) )
|
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
/* Here for longjmp() from vips__new_error_exit() during startup.
|
/* 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
|
int
|
||||||
vips__jpeg_read_buffer( const void *buf, size_t len, VipsImage *out,
|
vips__jpeg_read_buffer( const void *buf, size_t len, VipsImage *out,
|
||||||
gboolean header_only, int shrink, int fail, gboolean readbehind,
|
gboolean header_only, int shrink, int fail, gboolean autorotate )
|
||||||
gboolean autorotate )
|
|
||||||
{
|
{
|
||||||
ReadJpeg *jpeg;
|
ReadJpeg *jpeg;
|
||||||
|
|
||||||
if( !(jpeg = readjpeg_new( out,
|
if( !(jpeg = readjpeg_new( out, shrink, fail, autorotate )) )
|
||||||
shrink, fail, readbehind, autorotate )) )
|
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
if( setjmp( jpeg->eman.jmp ) )
|
if( setjmp( jpeg->eman.jmp ) )
|
||||||
|
@ -182,7 +182,7 @@ vips_foreign_load_jpeg_file_header( VipsForeignLoad *load )
|
|||||||
VipsForeignLoadJpegFile *file = (VipsForeignLoadJpegFile *) load;
|
VipsForeignLoadJpegFile *file = (VipsForeignLoadJpegFile *) load;
|
||||||
|
|
||||||
if( vips__jpeg_read_file( file->filename, load->out,
|
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( -1 );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
@ -195,8 +195,7 @@ vips_foreign_load_jpeg_file_load( VipsForeignLoad *load )
|
|||||||
VipsForeignLoadJpegFile *file = (VipsForeignLoadJpegFile *) load;
|
VipsForeignLoadJpegFile *file = (VipsForeignLoadJpegFile *) load;
|
||||||
|
|
||||||
if( vips__jpeg_read_file( file->filename, load->real,
|
if( vips__jpeg_read_file( file->filename, load->real,
|
||||||
FALSE, jpeg->shrink, load->fail,
|
FALSE, jpeg->shrink, load->fail, jpeg->autorotate ) )
|
||||||
load->access == VIPS_ACCESS_SEQUENTIAL, jpeg->autorotate ) )
|
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
@ -262,8 +261,7 @@ vips_foreign_load_jpeg_buffer_header( VipsForeignLoad *load )
|
|||||||
VipsForeignLoadJpegBuffer *buffer = (VipsForeignLoadJpegBuffer *) load;
|
VipsForeignLoadJpegBuffer *buffer = (VipsForeignLoadJpegBuffer *) load;
|
||||||
|
|
||||||
if( vips__jpeg_read_buffer( buffer->buf->data, buffer->buf->length,
|
if( vips__jpeg_read_buffer( buffer->buf->data, buffer->buf->length,
|
||||||
load->out, TRUE, jpeg->shrink, load->fail, FALSE,
|
load->out, TRUE, jpeg->shrink, load->fail, jpeg->autorotate ) )
|
||||||
jpeg->autorotate ) )
|
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
@ -276,8 +274,7 @@ vips_foreign_load_jpeg_buffer_load( VipsForeignLoad *load )
|
|||||||
VipsForeignLoadJpegBuffer *buffer = (VipsForeignLoadJpegBuffer *) load;
|
VipsForeignLoadJpegBuffer *buffer = (VipsForeignLoadJpegBuffer *) load;
|
||||||
|
|
||||||
if( vips__jpeg_read_buffer( buffer->buf->data, buffer->buf->length,
|
if( vips__jpeg_read_buffer( buffer->buf->data, buffer->buf->length,
|
||||||
load->real, FALSE, jpeg->shrink, load->fail,
|
load->real, FALSE, jpeg->shrink, load->fail, jpeg->autorotate ) )
|
||||||
load->access == VIPS_ACCESS_SEQUENTIAL, jpeg->autorotate ) )
|
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
|
@ -68,7 +68,7 @@ int vips__tiff_write_buf( VipsImage *in,
|
|||||||
int vips__tiff_read_header( const char *filename, VipsImage *out,
|
int vips__tiff_read_header( const char *filename, VipsImage *out,
|
||||||
int page, int n, gboolean autorotate );
|
int page, int n, gboolean autorotate );
|
||||||
int vips__tiff_read( const char *filename, VipsImage *out,
|
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__istiff( const char *filename );
|
||||||
gboolean vips__istifftiled( 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 vips__tiff_read_header_buffer( const void *buf, size_t len, VipsImage *out,
|
||||||
int page, int n, gboolean autorotate );
|
int page, int n, gboolean autorotate );
|
||||||
int vips__tiff_read_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 );
|
int page, int n, gboolean autorotate );
|
||||||
|
|
||||||
extern const char *vips__foreign_tiff_suffs[];
|
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_israd( const char *filename );
|
||||||
int vips__rad_header( const char *filename, VipsImage *out );
|
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( VipsImage *in, const char *filename );
|
||||||
int vips__rad_save_buf( VipsImage *in, void **obuf, size_t *olen );
|
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_buffer( const void *buf, size_t len );
|
||||||
int vips__isjpeg( const char *filename );
|
int vips__isjpeg( const char *filename );
|
||||||
int vips__jpeg_read_file( const char *name, VipsImage *out,
|
int vips__jpeg_read_file( const char *name, VipsImage *out,
|
||||||
gboolean header_only, int shrink, gboolean fail, gboolean readbehind,
|
gboolean header_only, int shrink, gboolean fail, gboolean autorotate );
|
||||||
gboolean autorotate );
|
|
||||||
int vips__jpeg_read_buffer( const void *buf, size_t len, VipsImage *out,
|
int vips__jpeg_read_buffer( const void *buf, size_t len, VipsImage *out,
|
||||||
gboolean header_only, int shrink, int fail, gboolean readbehind,
|
gboolean header_only, int shrink, int fail, gboolean autorotate );
|
||||||
gboolean autorotate );
|
|
||||||
|
|
||||||
int vips__png_header( const char *name, VipsImage *out );
|
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 );
|
gboolean vips__png_ispng_buffer( const void *buf, size_t len );
|
||||||
int vips__png_ispng( const char *filename );
|
int vips__png_ispng( const char *filename );
|
||||||
gboolean vips__png_isinterlaced( const char *filename );
|
gboolean vips__png_isinterlaced( const char *filename );
|
||||||
gboolean vips__png_isinterlaced_buffer( const void *buffer, size_t length );
|
gboolean vips__png_isinterlaced_buffer( const void *buffer, size_t length );
|
||||||
extern const char *vips__png_suffs[];
|
extern const char *vips__png_suffs[];
|
||||||
int vips__png_read_buffer( const void *buffer, size_t length,
|
int vips__png_read_buffer( const void *buffer, size_t length, VipsImage *out );
|
||||||
VipsImage *out, gboolean readbehind );
|
|
||||||
int vips__png_header_buffer( const void *buffer, size_t length,
|
int vips__png_header_buffer( const void *buffer, size_t length,
|
||||||
VipsImage *out );
|
VipsImage *out );
|
||||||
|
|
||||||
|
@ -106,8 +106,7 @@ vips_foreign_load_png_load( VipsForeignLoad *load )
|
|||||||
{
|
{
|
||||||
VipsForeignLoadPng *png = (VipsForeignLoadPng *) load;
|
VipsForeignLoadPng *png = (VipsForeignLoadPng *) load;
|
||||||
|
|
||||||
if( vips__png_read( png->filename, load->real,
|
if( vips__png_read( png->filename, load->real ) )
|
||||||
load->access == VIPS_ACCESS_SEQUENTIAL ) )
|
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
@ -202,7 +201,7 @@ vips_foreign_load_png_buffer_load( VipsForeignLoad *load )
|
|||||||
VipsForeignLoadPngBuffer *buffer = (VipsForeignLoadPngBuffer *) load;
|
VipsForeignLoadPngBuffer *buffer = (VipsForeignLoadPngBuffer *) load;
|
||||||
|
|
||||||
if( vips__png_read_buffer( buffer->buf->data, buffer->buf->length,
|
if( vips__png_read_buffer( buffer->buf->data, buffer->buf->length,
|
||||||
load->real, load->access == VIPS_ACCESS_SEQUENTIAL ) )
|
load->real ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
|
@ -1084,7 +1084,7 @@ rad2vips_get_header( Read *read, VipsImage *out )
|
|||||||
|
|
||||||
/* Tell downstream we are reading sequentially.
|
/* 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 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
@ -1140,7 +1140,7 @@ rad2vips_generate( VipsRegion *or,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
vips__rad_load( const char *filename, VipsImage *out, gboolean readbehind )
|
vips__rad_load( const char *filename, VipsImage *out )
|
||||||
{
|
{
|
||||||
VipsImage **t = (VipsImage **)
|
VipsImage **t = (VipsImage **)
|
||||||
vips_object_local_array( VIPS_OBJECT( out ), 3 );
|
vips_object_local_array( VIPS_OBJECT( out ), 3 );
|
||||||
@ -1159,14 +1159,8 @@ vips__rad_load( const char *filename, VipsImage *out, gboolean readbehind )
|
|||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
if( vips_image_generate( t[0],
|
if( vips_image_generate( t[0],
|
||||||
NULL, rad2vips_generate, NULL,
|
NULL, rad2vips_generate, NULL, read, NULL ) ||
|
||||||
read, NULL ) ||
|
vips_sequential( t[0], &t[1], "tile_height", 8, NULL ) ||
|
||||||
vips_sequential( t[0], &t[1],
|
|
||||||
"tile_height", 8,
|
|
||||||
"access", readbehind ?
|
|
||||||
VIPS_ACCESS_SEQUENTIAL :
|
|
||||||
VIPS_ACCESS_SEQUENTIAL_UNBUFFERED,
|
|
||||||
NULL ) ||
|
|
||||||
vips_image_write( t[1], out ) )
|
vips_image_write( t[1], out ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
|
@ -100,8 +100,7 @@ vips_foreign_load_rad_load( VipsForeignLoad *load )
|
|||||||
{
|
{
|
||||||
VipsForeignLoadRad *rad = (VipsForeignLoadRad *) load;
|
VipsForeignLoadRad *rad = (VipsForeignLoadRad *) load;
|
||||||
|
|
||||||
if( vips__rad_load( rad->filename, load->real,
|
if( vips__rad_load( rad->filename, load->real ) )
|
||||||
load->access == VIPS_ACCESS_SEQUENTIAL ) )
|
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
|
@ -274,7 +274,6 @@ typedef struct _Rtiff {
|
|||||||
int page;
|
int page;
|
||||||
int n;
|
int n;
|
||||||
gboolean autorotate;
|
gboolean autorotate;
|
||||||
gboolean readbehind;
|
|
||||||
|
|
||||||
/* The TIFF we read.
|
/* The TIFF we read.
|
||||||
*/
|
*/
|
||||||
@ -1337,7 +1336,7 @@ rtiff_set_header( Rtiff *rtiff, VipsImage *out )
|
|||||||
/* Tell downstream if we are reading sequentially.
|
/* Tell downstream if we are reading sequentially.
|
||||||
*/
|
*/
|
||||||
if( !rtiff->header.tiled )
|
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 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
@ -1931,9 +1930,6 @@ rtiff_read_stripwise( Rtiff *rtiff, VipsImage *out )
|
|||||||
rtiff, NULL ) ||
|
rtiff, NULL ) ||
|
||||||
vips_sequential( t[0], &t[1],
|
vips_sequential( t[0], &t[1],
|
||||||
"tile_height", rtiff->header.rows_per_strip,
|
"tile_height", rtiff->header.rows_per_strip,
|
||||||
"access", rtiff->readbehind ?
|
|
||||||
VIPS_ACCESS_SEQUENTIAL :
|
|
||||||
VIPS_ACCESS_SEQUENTIAL_UNBUFFERED,
|
|
||||||
NULL ) ||
|
NULL ) ||
|
||||||
rtiff_autorotate( rtiff, t[1], &t[2] ) ||
|
rtiff_autorotate( rtiff, t[1], &t[2] ) ||
|
||||||
vips_image_write( t[2], out ) )
|
vips_image_write( t[2], out ) )
|
||||||
@ -1957,8 +1953,7 @@ rtiff_close( VipsObject *object, Rtiff *rtiff )
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Rtiff *
|
static Rtiff *
|
||||||
rtiff_new( VipsImage *out,
|
rtiff_new( VipsImage *out, int page, int n, gboolean autorotate )
|
||||||
int page, int n, gboolean autorotate, gboolean readbehind )
|
|
||||||
{
|
{
|
||||||
Rtiff *rtiff;
|
Rtiff *rtiff;
|
||||||
|
|
||||||
@ -1970,7 +1965,6 @@ rtiff_new( VipsImage *out,
|
|||||||
rtiff->page = page;
|
rtiff->page = page;
|
||||||
rtiff->n = n;
|
rtiff->n = n;
|
||||||
rtiff->autorotate = autorotate;
|
rtiff->autorotate = autorotate;
|
||||||
rtiff->readbehind = readbehind;
|
|
||||||
rtiff->tiff = NULL;
|
rtiff->tiff = NULL;
|
||||||
rtiff->current_page = -1;
|
rtiff->current_page = -1;
|
||||||
rtiff->sfn = NULL;
|
rtiff->sfn = NULL;
|
||||||
@ -2174,11 +2168,11 @@ rtiff_header_read_all( Rtiff *rtiff )
|
|||||||
|
|
||||||
static Rtiff *
|
static Rtiff *
|
||||||
rtiff_new_filename( const char *filename, VipsImage *out,
|
rtiff_new_filename( const char *filename, VipsImage *out,
|
||||||
int page, int n, gboolean autorotate, gboolean readbehind )
|
int page, int n, gboolean autorotate )
|
||||||
{
|
{
|
||||||
Rtiff *rtiff;
|
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->tiff = vips__tiff_openin( filename )) ||
|
||||||
rtiff_header_read_all( rtiff ) )
|
rtiff_header_read_all( rtiff ) )
|
||||||
return( NULL );
|
return( NULL );
|
||||||
@ -2190,11 +2184,11 @@ rtiff_new_filename( const char *filename, VipsImage *out,
|
|||||||
|
|
||||||
static Rtiff *
|
static Rtiff *
|
||||||
rtiff_new_buffer( const void *buf, size_t len, VipsImage *out,
|
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;
|
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->tiff = vips__tiff_openin_buffer( out, buf, len )) ||
|
||||||
rtiff_header_read_all( rtiff ) )
|
rtiff_header_read_all( rtiff ) )
|
||||||
return( NULL );
|
return( NULL );
|
||||||
@ -2225,7 +2219,7 @@ istiffpyramid( const char *name )
|
|||||||
|
|
||||||
int
|
int
|
||||||
vips__tiff_read( const char *filename, VipsImage *out,
|
vips__tiff_read( const char *filename, VipsImage *out,
|
||||||
int page, int n, gboolean autorotate, gboolean readbehind )
|
int page, int n, gboolean autorotate )
|
||||||
{
|
{
|
||||||
Rtiff *rtiff;
|
Rtiff *rtiff;
|
||||||
|
|
||||||
@ -2236,8 +2230,7 @@ vips__tiff_read( const char *filename, VipsImage *out,
|
|||||||
|
|
||||||
vips__tiff_init();
|
vips__tiff_init();
|
||||||
|
|
||||||
if( !(rtiff = rtiff_new_filename( filename,
|
if( !(rtiff = rtiff_new_filename( filename, out, page, n, autorotate )) )
|
||||||
out, page, n, autorotate, readbehind )) )
|
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
if( rtiff->header.tiled ) {
|
if( rtiff->header.tiled ) {
|
||||||
@ -2283,8 +2276,7 @@ vips__tiff_read_header( const char *filename, VipsImage *out,
|
|||||||
|
|
||||||
vips__tiff_init();
|
vips__tiff_init();
|
||||||
|
|
||||||
if( !(rtiff = rtiff_new_filename( filename, out,
|
if( !(rtiff = rtiff_new_filename( filename, out, page, n, autorotate )) )
|
||||||
page, n, autorotate, FALSE )) )
|
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
if( rtiff_set_header( rtiff, out ) )
|
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();
|
vips__tiff_init();
|
||||||
|
|
||||||
if( !(rtiff = rtiff_new_buffer( buf, len, out,
|
if( !(rtiff = rtiff_new_buffer( buf, len, out, page, n, autorotate )) )
|
||||||
page, n, autorotate, FALSE )) )
|
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
if( rtiff_set_header( rtiff, out ) )
|
if( rtiff_set_header( rtiff, out ) )
|
||||||
@ -2366,8 +2357,7 @@ vips__tiff_read_header_buffer( const void *buf, size_t len, VipsImage *out,
|
|||||||
|
|
||||||
int
|
int
|
||||||
vips__tiff_read_buffer( const void *buf, size_t len,
|
vips__tiff_read_buffer( const void *buf, size_t len,
|
||||||
VipsImage *out, int page, int n, gboolean autorotate,
|
VipsImage *out, int page, int n, gboolean autorotate )
|
||||||
gboolean readbehind )
|
|
||||||
{
|
{
|
||||||
Rtiff *rtiff;
|
Rtiff *rtiff;
|
||||||
|
|
||||||
@ -2378,8 +2368,7 @@ vips__tiff_read_buffer( const void *buf, size_t len,
|
|||||||
|
|
||||||
vips__tiff_init();
|
vips__tiff_init();
|
||||||
|
|
||||||
if( !(rtiff = rtiff_new_buffer( buf, len, out,
|
if( !(rtiff = rtiff_new_buffer( buf, len, out, page, n, autorotate )) )
|
||||||
page, n, autorotate, readbehind )) )
|
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
if( rtiff->header.tiled ) {
|
if( rtiff->header.tiled ) {
|
||||||
|
@ -183,8 +183,7 @@ vips_foreign_load_tiff_file_load( VipsForeignLoad *load )
|
|||||||
VipsForeignLoadTiffFile *file = (VipsForeignLoadTiffFile *) load;
|
VipsForeignLoadTiffFile *file = (VipsForeignLoadTiffFile *) load;
|
||||||
|
|
||||||
if( vips__tiff_read( file->filename, load->real,
|
if( vips__tiff_read( file->filename, load->real,
|
||||||
tiff->page, tiff->n, tiff->autorotate,
|
tiff->page, tiff->n, tiff->autorotate ) )
|
||||||
load->access == VIPS_ACCESS_SEQUENTIAL ) )
|
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
@ -284,8 +283,7 @@ vips_foreign_load_tiff_buffer_load( VipsForeignLoad *load )
|
|||||||
|
|
||||||
if( vips__tiff_read_buffer(
|
if( vips__tiff_read_buffer(
|
||||||
buffer->buf->data, buffer->buf->length, load->real,
|
buffer->buf->data, buffer->buf->length, load->real,
|
||||||
tiff->page, tiff->n, tiff->autorotate,
|
tiff->page, tiff->n, tiff->autorotate ) )
|
||||||
load->access == VIPS_ACCESS_SEQUENTIAL ) )
|
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
|
@ -140,7 +140,6 @@ user_warning_function( png_structp png_ptr, png_const_charp warning_msg )
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
char *name;
|
char *name;
|
||||||
VipsImage *out;
|
VipsImage *out;
|
||||||
gboolean readbehind;
|
|
||||||
|
|
||||||
int y_pos;
|
int y_pos;
|
||||||
png_structp pPng;
|
png_structp pPng;
|
||||||
@ -177,7 +176,7 @@ read_close_cb( VipsImage *out, Read *read )
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Read *
|
static Read *
|
||||||
read_new( VipsImage *out, gboolean readbehind )
|
read_new( VipsImage *out )
|
||||||
{
|
{
|
||||||
Read *read;
|
Read *read;
|
||||||
|
|
||||||
@ -185,7 +184,6 @@ read_new( VipsImage *out, gboolean readbehind )
|
|||||||
return( NULL );
|
return( NULL );
|
||||||
|
|
||||||
read->name = NULL;
|
read->name = NULL;
|
||||||
read->readbehind = readbehind;
|
|
||||||
read->out = out;
|
read->out = out;
|
||||||
read->y_pos = 0;
|
read->y_pos = 0;
|
||||||
read->pPng = NULL;
|
read->pPng = NULL;
|
||||||
@ -223,11 +221,11 @@ read_new( VipsImage *out, gboolean readbehind )
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Read *
|
static Read *
|
||||||
read_new_filename( VipsImage *out, const char *name, gboolean readbehind )
|
read_new_filename( VipsImage *out, const char *name )
|
||||||
{
|
{
|
||||||
Read *read;
|
Read *read;
|
||||||
|
|
||||||
if( !(read = read_new( out, readbehind )) )
|
if( !(read = read_new( out )) )
|
||||||
return( NULL );
|
return( NULL );
|
||||||
|
|
||||||
read->name = vips_strdup( VIPS_OBJECT( out ), name );
|
read->name = vips_strdup( VIPS_OBJECT( out ), name );
|
||||||
@ -386,7 +384,7 @@ png2vips_header( Read *read, VipsImage *out )
|
|||||||
* read via a huge memory buffer.
|
* read via a huge memory buffer.
|
||||||
*/
|
*/
|
||||||
if( interlace_type == PNG_INTERLACE_NONE ) {
|
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
|
/* Sequential mode needs thinstrip to work with things like
|
||||||
* vips_shrink().
|
* vips_shrink().
|
||||||
@ -439,7 +437,7 @@ vips__png_header( const char *name, VipsImage *out )
|
|||||||
{
|
{
|
||||||
Read *read;
|
Read *read;
|
||||||
|
|
||||||
if( !(read = read_new_filename( out, name, FALSE )) ||
|
if( !(read = read_new_filename( out, name )) ||
|
||||||
png2vips_header( read, out ) )
|
png2vips_header( read, out ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
@ -568,7 +566,7 @@ vips__png_isinterlaced( const char *filename )
|
|||||||
int interlace_type;
|
int interlace_type;
|
||||||
|
|
||||||
image = vips_image_new();
|
image = vips_image_new();
|
||||||
if( !(read = read_new_filename( image, filename, FALSE )) ) {
|
if( !(read = read_new_filename( image, filename )) ) {
|
||||||
g_object_unref( image );
|
g_object_unref( image );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
@ -603,9 +601,6 @@ png2vips_image( Read *read, VipsImage *out )
|
|||||||
read, NULL ) ||
|
read, NULL ) ||
|
||||||
vips_sequential( t[0], &t[1],
|
vips_sequential( t[0], &t[1],
|
||||||
"tile_height", 8,
|
"tile_height", 8,
|
||||||
"access", read->readbehind ?
|
|
||||||
VIPS_ACCESS_SEQUENTIAL :
|
|
||||||
VIPS_ACCESS_SEQUENTIAL_UNBUFFERED,
|
|
||||||
NULL ) ||
|
NULL ) ||
|
||||||
vips_image_write( t[1], out ) )
|
vips_image_write( t[1], out ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
@ -615,7 +610,7 @@ png2vips_image( Read *read, VipsImage *out )
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
vips__png_read( const char *filename, VipsImage *out, gboolean readbehind )
|
vips__png_read( const char *filename, VipsImage *out )
|
||||||
{
|
{
|
||||||
Read *read;
|
Read *read;
|
||||||
|
|
||||||
@ -623,7 +618,7 @@ vips__png_read( const char *filename, VipsImage *out, gboolean readbehind )
|
|||||||
printf( "vips__png_read: reading \"%s\"\n", filename );
|
printf( "vips__png_read: reading \"%s\"\n", filename );
|
||||||
#endif /*DEBUG*/
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
if( !(read = read_new_filename( out, filename, readbehind )) ||
|
if( !(read = read_new_filename( out, filename )) ||
|
||||||
png2vips_image( read, out ) )
|
png2vips_image( read, out ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
@ -670,12 +665,11 @@ vips_png_read_buffer( png_structp pPng, png_bytep data, png_size_t length )
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Read *
|
static Read *
|
||||||
read_new_buffer( VipsImage *out, const void *buffer, size_t length,
|
read_new_buffer( VipsImage *out, const void *buffer, size_t length )
|
||||||
gboolean readbehind )
|
|
||||||
{
|
{
|
||||||
Read *read;
|
Read *read;
|
||||||
|
|
||||||
if( !(read = read_new( out, readbehind )) )
|
if( !(read = read_new( out )) )
|
||||||
return( NULL );
|
return( NULL );
|
||||||
|
|
||||||
read->length = length;
|
read->length = length;
|
||||||
@ -701,7 +695,7 @@ vips__png_header_buffer( const void *buffer, size_t length, VipsImage *out )
|
|||||||
{
|
{
|
||||||
Read *read;
|
Read *read;
|
||||||
|
|
||||||
if( !(read = read_new_buffer( out, buffer, length, FALSE )) ||
|
if( !(read = read_new_buffer( out, buffer, length )) ||
|
||||||
png2vips_header( read, out ) )
|
png2vips_header( read, out ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
@ -709,12 +703,11 @@ vips__png_header_buffer( const void *buffer, size_t length, VipsImage *out )
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
vips__png_read_buffer( const void *buffer, size_t length, VipsImage *out,
|
vips__png_read_buffer( const void *buffer, size_t length, VipsImage *out )
|
||||||
gboolean readbehind )
|
|
||||||
{
|
{
|
||||||
Read *read;
|
Read *read;
|
||||||
|
|
||||||
if( !(read = read_new_buffer( out, buffer, length, readbehind )) ||
|
if( !(read = read_new_buffer( out, buffer, length )) ||
|
||||||
png2vips_image( read, out ) )
|
png2vips_image( read, out ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
@ -733,7 +726,7 @@ vips__png_isinterlaced_buffer( const void *buffer, size_t length )
|
|||||||
|
|
||||||
image = vips_image_new();
|
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 );
|
g_object_unref( image );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
@ -688,7 +688,7 @@ vips_maplut_class_init( VipsMaplutClass *class )
|
|||||||
object_class->description = _( "map an image though a lut" );
|
object_class->description = _( "map an image though a lut" );
|
||||||
object_class->build = vips_maplut_build;
|
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,
|
VIPS_ARG_IMAGE( class, "in", 1,
|
||||||
_( "Input" ),
|
_( "Input" ),
|
||||||
|
@ -147,7 +147,6 @@
|
|||||||
* VipsAccess:
|
* VipsAccess:
|
||||||
* @VIPS_ACCESS_RANDOM: can read anywhere
|
* @VIPS_ACCESS_RANDOM: can read anywhere
|
||||||
* @VIPS_ACCESS_SEQUENTIAL: top-to-bottom reading only, but with a small buffer
|
* @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()
|
* The type of access an operation has to supply. See vips_tilecache()
|
||||||
* and #VipsForeign.
|
* and #VipsForeign.
|
||||||
@ -156,9 +155,6 @@
|
|||||||
*
|
*
|
||||||
* @VIPS_ACCESS_SEQUENTIAL means requests will be top-to-bottom, but with some
|
* @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.
|
* 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
|
* 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
|
* 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
|
* allowed to make small non-local references, so area operations like
|
||||||
* convolution will work. #VIPS_ACCESS_SEQUENTIAL_UNBUFFERED does not allow
|
* convolution will work.
|
||||||
* non-local references, so will only work for very strict top-to-bottom
|
|
||||||
* operations, but does have very low memory needs.
|
|
||||||
*
|
*
|
||||||
* In #VIPS_ACCESS_RANDOM mode, small images are decompressed to memory and
|
* In #VIPS_ACCESS_RANDOM mode, small images are decompressed to memory and
|
||||||
* then processed from there. Large images are decompressed to temporary
|
* then processed from there. Large images are decompressed to temporary
|
||||||
|
@ -1830,9 +1830,8 @@ vips_object_set_argument_from_string( VipsObject *object,
|
|||||||
|
|
||||||
/* Read the filename.
|
/* Read the filename.
|
||||||
*/
|
*/
|
||||||
if( flags & VIPS_OPERATION_SEQUENTIAL_UNBUFFERED )
|
if( flags & (VIPS_OPERATION_SEQUENTIAL_UNBUFFERED |
|
||||||
access = VIPS_ACCESS_SEQUENTIAL_UNBUFFERED;
|
VIPS_OPERATION_SEQUENTIAL) )
|
||||||
else if( flags & VIPS_OPERATION_SEQUENTIAL )
|
|
||||||
access = VIPS_ACCESS_SEQUENTIAL;
|
access = VIPS_ACCESS_SEQUENTIAL;
|
||||||
else
|
else
|
||||||
access = VIPS_ACCESS_RANDOM;
|
access = VIPS_ACCESS_RANDOM;
|
||||||
@ -1869,9 +1868,8 @@ vips_object_set_argument_from_string( VipsObject *object,
|
|||||||
flags = vips_operation_get_flags(
|
flags = vips_operation_get_flags(
|
||||||
VIPS_OPERATION( object ) );
|
VIPS_OPERATION( object ) );
|
||||||
|
|
||||||
if( flags & VIPS_OPERATION_SEQUENTIAL_UNBUFFERED )
|
if( flags & (VIPS_OPERATION_SEQUENTIAL_UNBUFFERED |
|
||||||
access = VIPS_ACCESS_SEQUENTIAL_UNBUFFERED;
|
VIPS_OPERATION_SEQUENTIAL) )
|
||||||
else if( flags & VIPS_OPERATION_SEQUENTIAL )
|
|
||||||
access = VIPS_ACCESS_SEQUENTIAL;
|
access = VIPS_ACCESS_SEQUENTIAL;
|
||||||
else
|
else
|
||||||
access = VIPS_ACCESS_RANDOM;
|
access = VIPS_ACCESS_RANDOM;
|
||||||
|
@ -169,7 +169,6 @@
|
|||||||
* VipsOperationFlags:
|
* VipsOperationFlags:
|
||||||
* @VIPS_OPERATION_NONE: no flags
|
* @VIPS_OPERATION_NONE: no flags
|
||||||
* @VIPS_OPERATION_SEQUENTIAL: can work sequentially with a small buffer
|
* @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_NOCACHE: must not be cached
|
||||||
* @VIPS_OPERATION_DEPRECATED: a compatibility thing
|
* @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
|
* not at the top of the image. In this case, the first part of the image will
|
||||||
* be read and discarded
|
* 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
|
* 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
|
* 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
|
* not at the top of the image. In this case, the first part of the image will
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
* - more accurate resizing
|
* - more accurate resizing
|
||||||
* 9/9/16
|
* 9/9/16
|
||||||
* - add @centre option
|
* - add @centre option
|
||||||
|
* 6/3/17
|
||||||
|
* - moved the cache to shrinkv
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -316,7 +316,7 @@ vips_shrinkh_class_init( VipsShrinkhClass *class )
|
|||||||
vobject_class->description = _( "shrink an image horizontally" );
|
vobject_class->description = _( "shrink an image horizontally" );
|
||||||
vobject_class->build = vips_shrinkh_build;
|
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,
|
VIPS_ARG_INT( class, "hshrink", 8,
|
||||||
_( "Hshrink" ),
|
_( "Hshrink" ),
|
||||||
|
@ -457,7 +457,7 @@ vips_shrinkv_class_init( VipsShrinkvClass *class )
|
|||||||
vobject_class->description = _( "shrink an image vertically" );
|
vobject_class->description = _( "shrink an image vertically" );
|
||||||
vobject_class->build = vips_shrinkv_build;
|
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,
|
VIPS_ARG_INT( class, "vshrink", 9,
|
||||||
_( "Vshrink" ),
|
_( "Vshrink" ),
|
||||||
|
@ -376,10 +376,6 @@ vips_thumbnail_build( VipsObject *object )
|
|||||||
shrink = vips_thumbnail_calculate_shrink( thumbnail,
|
shrink = vips_thumbnail_calculate_shrink( thumbnail,
|
||||||
in->Xsize, in->Ysize );
|
in->Xsize, in->Ysize );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Use centre convention to better match imagemagick.
|
/* Use centre convention to better match imagemagick.
|
||||||
*/
|
*/
|
||||||
if( vips_resize( in, &t[4], 1.0 / shrink,
|
if( vips_resize( in, &t[4], 1.0 / shrink,
|
||||||
|
@ -43,3 +43,12 @@ if ! $vipsheader $tmp/x.png > /dev/null 2>&1 ; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
echo "ok"
|
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"
|
||||||
|
Loading…
Reference in New Issue
Block a user