diff --git a/ChangeLog b/ChangeLog index 7f672e02..91da761c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -22,6 +22,7 @@ - added vips_image_new_matrixv() - dzsave basename param now called filename, so you can use .dz as a destination (basename is still there but deprecated) +- new _UNBUFFERED sequential mode saves memory in some important cases 3/7/13 started 7.34.2 - lower priority for Matlab load to reduce segvs from Mat_Open(), thanks diff --git a/TODO b/TODO index b1505ccd..4b00e424 100644 --- a/TODO +++ b/TODO @@ -1,49 +1,4 @@ -- need a new uncached mode for open via disc - - currently we have a huge linecache for "vips copy x.png x.v", in - effect what vips does for open-via-disc, and therefore see >100mb ram - use even in open-via-disc mode - - add SEQUENTIAL_UNBUFFERED? - - could we spot from the demand style? they do almost the same thing, - though one is static and one dynamic, I guess - - - vips_object_set_argument_from_string() looks at the operation class and - sets ("sequential", TRUE) for image arguments - - the "seq" arg needs to be an enum with various settings - - "access", - RANDOM, SEQUENTIAL, SEQUENTIAL_UNBUFFERED - - - - - todo: - - add a new operation flag, try setting it on vips_copy(), pass the flag down - to "access" - - in foreign/*.c, evey place that uses vips_sequential() needs to be passed a - copy of "access" - - when it calls vips_sequential(), it needs to set an access hint - - vips_sequential() needs to pass this down to vips_linecache() - - vips_linecache_build() needs to use this to adjust the setting of - max_tiles - - - - - - - - - finish hist_ismonotonic() needs im_conv() diff --git a/libvips/arithmetic/arithmetic.c b/libvips/arithmetic/arithmetic.c index 8dbdce7d..59fe05aa 100644 --- a/libvips/arithmetic/arithmetic.c +++ b/libvips/arithmetic/arithmetic.c @@ -577,7 +577,7 @@ vips_arithmetic_class_init( VipsArithmeticClass *class ) vobject_class->description = _( "arithmetic operations" ); vobject_class->build = vips_arithmetic_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; VIPS_ARG_IMAGE( class, "out", 100, _( "Output" ), diff --git a/libvips/colour/colour.c b/libvips/colour/colour.c index cbf177e1..3d31e2bb 100644 --- a/libvips/colour/colour.c +++ b/libvips/colour/colour.c @@ -356,7 +356,7 @@ vips_colour_class_init( VipsColourClass *class ) vobject_class->description = _( "colour operations" ); vobject_class->build = vips_colour_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; VIPS_ARG_IMAGE( class, "out", 100, _( "Output" ), diff --git a/libvips/colour/colourspace.c b/libvips/colour/colourspace.c index 42d1feb1..1ae1e721 100644 --- a/libvips/colour/colourspace.c +++ b/libvips/colour/colourspace.c @@ -328,7 +328,7 @@ vips_colourspace_class_init( VipsColourspaceClass *class ) vobject_class->description = _( "convert to a new colourspace" ); vobject_class->build = vips_colourspace_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; VIPS_ARG_IMAGE( class, "in", 1, _( "Input" ), diff --git a/libvips/conversion/bandary.c b/libvips/conversion/bandary.c index bd9eb894..5e4e4f0b 100644 --- a/libvips/conversion/bandary.c +++ b/libvips/conversion/bandary.c @@ -178,7 +178,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; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; } static void diff --git a/libvips/conversion/cast.c b/libvips/conversion/cast.c index 84746321..38df919a 100644 --- a/libvips/conversion/cast.c +++ b/libvips/conversion/cast.c @@ -477,7 +477,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; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; VIPS_ARG_IMAGE( class, "in", 1, _( "Input" ), diff --git a/libvips/conversion/conversion.c b/libvips/conversion/conversion.c index 4e94d75b..4b00a8eb 100644 --- a/libvips/conversion/conversion.c +++ b/libvips/conversion/conversion.c @@ -69,6 +69,81 @@ * */ +/** + * VipsAlign: + * @VIPS_ALIGN_LOW: align low coordinate edge + * @VIPS_ALIGN_CENTRE: align centre + * @VIPS_ALIGN_HIGH: align high coordinate edge + * + * See vips_join() and so on. + * + * Operations like vips_join() need to be told whether to align images on the + * low or high coordinate edge, or centre. + * + * See also: vips_join(). + */ + +/** + * VipsAngle: + * @VIPS_ANGLE_0: no rotate + * @VIPS_ANGLE_90: 90 degrees anti-clockwise + * @VIPS_ANGLE_180: 180 degree rotate + * @VIPS_ANGLE_270: 90 degrees clockwise + * + * See vips_rot() and so on. + * + * Fixed rotate angles. + * + * See also: vips_rot(). + */ + +/** + * VipsExtend: + * @VIPS_EXTEND_BLACK: extend with black (all 0) pixels + * @VIPS_EXTEND_COPY: copy the image edges + * @VIPS_EXTEND_REPEAT: repeat the whole image + * @VIPS_EXTEND_MIRROR: mirror the whole image + * @VIPS_EXTEND_WHITE: extend with white (all bits set) pixels + * @VIPS_EXTEND_BACKGROUND: extend with colour from the @background property + * + * See vips_embed(), vips_conv(), vips_affine() and so on. + * + * When the edges of an image are extended, you can specify + * how you want the extension done. + * + * #VIPS_EXTEND_BLACK --- new pixels are black, ie. all bits are zero. + * + * #VIPS_EXTEND_COPY --- each new pixel takes the value of the nearest edge + * pixel + * + * #VIPS_EXTEND_REPEAT --- the image is tiled to fill the new area + * + * #VIPS_EXTEND_MIRROR --- the image is reflected and tiled to reduce hash + * edges + * + * #VIPS_EXTEND_WHITE --- new pixels are white, ie. all bits are set + * + * #VIPS_EXTEND_BACKGROUND --- colour set from the @background property + * + * We have to specify the exact value of each enum member since we have to + * keep these frozen for back compat with vips7. + * + * See also: vips_embed(). + */ + +/** + * VipsDirection: + * @VIPS_DIRECTION_HORIZONTAL: left-right + * @VIPS_DIRECTION_VERTICAL: top-bottom + * + * See vips_flip(), vips_join() and so on. + * + * Operations like vips_flip() need to be told whether to flip left-right or + * top-bottom. + * + * See also: vips_flip(), vips_join(). + */ + G_DEFINE_ABSTRACT_TYPE( VipsConversion, vips_conversion, VIPS_TYPE_OPERATION ); static int diff --git a/libvips/conversion/copy.c b/libvips/conversion/copy.c index 57c58f69..2b3981a9 100644 --- a/libvips/conversion/copy.c +++ b/libvips/conversion/copy.c @@ -320,7 +320,7 @@ vips_copy_class_init( VipsCopyClass *class ) * cache it. Plus copy is cheap. */ operation_class->flags = - VIPS_OPERATION_SEQUENTIAL | + VIPS_OPERATION_SEQUENTIAL_UNBUFFERED | VIPS_OPERATION_NOCACHE; VIPS_ARG_IMAGE( class, "in", 1, diff --git a/libvips/conversion/embed.c b/libvips/conversion/embed.c index 9e0dacb7..8f33e248 100644 --- a/libvips/conversion/embed.c +++ b/libvips/conversion/embed.c @@ -545,7 +545,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; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; VIPS_ARG_IMAGE( class, "in", -1, _( "Input" ), diff --git a/libvips/conversion/extract.c b/libvips/conversion/extract.c index e99ee5ef..5f3a00bf 100644 --- a/libvips/conversion/extract.c +++ b/libvips/conversion/extract.c @@ -194,7 +194,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; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; VIPS_ARG_IMAGE( class, "input", 0, _( "Input" ), diff --git a/libvips/conversion/falsecolour.c b/libvips/conversion/falsecolour.c index d522744a..697c7125 100644 --- a/libvips/conversion/falsecolour.c +++ b/libvips/conversion/falsecolour.c @@ -369,7 +369,7 @@ vips_falsecolour_class_init( VipsFalsecolourClass *class ) vobject_class->description = _( "false colour an image" ); vobject_class->build = vips_falsecolour_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; VIPS_ARG_IMAGE( class, "in", 0, _( "in" ), diff --git a/libvips/conversion/flatten.c b/libvips/conversion/flatten.c index 3b16673d..352e3734 100644 --- a/libvips/conversion/flatten.c +++ b/libvips/conversion/flatten.c @@ -371,7 +371,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; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; VIPS_ARG_IMAGE( class, "in", 1, _( "Input" ), diff --git a/libvips/conversion/gammacorrect.c b/libvips/conversion/gammacorrect.c index 6de28524..bd7b5bed 100644 --- a/libvips/conversion/gammacorrect.c +++ b/libvips/conversion/gammacorrect.c @@ -105,7 +105,7 @@ vips_gammacorrect_class_init( VipsGammacorrectClass *class ) vobject_class->description = _( "gammacorrect a pair of images" ); vobject_class->build = vips_gammacorrect_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; VIPS_ARG_IMAGE( class, "in", -1, _( "in" ), diff --git a/libvips/conversion/ifthenelse.c b/libvips/conversion/ifthenelse.c index 3f2cbd66..450cfd3a 100644 --- a/libvips/conversion/ifthenelse.c +++ b/libvips/conversion/ifthenelse.c @@ -471,7 +471,7 @@ vips_ifthenelse_class_init( VipsIfthenelseClass *class ) vobject_class->description = _( "ifthenelse an image" ); vobject_class->build = vips_ifthenelse_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; VIPS_ARG_IMAGE( class, "cond", -2, _( "Condition" ), diff --git a/libvips/conversion/insert.c b/libvips/conversion/insert.c index 15ab5197..4b1fbbf9 100644 --- a/libvips/conversion/insert.c +++ b/libvips/conversion/insert.c @@ -355,7 +355,7 @@ vips_insert_class_init( VipsInsertClass *class ) vobject_class->description = _( "insert an image" ); vobject_class->build = vips_insert_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; VIPS_ARG_IMAGE( class, "main", -1, _( "Main" ), diff --git a/libvips/conversion/join.c b/libvips/conversion/join.c index 3f125680..ad1ab9e3 100644 --- a/libvips/conversion/join.c +++ b/libvips/conversion/join.c @@ -228,7 +228,7 @@ vips_join_class_init( VipsJoinClass *class ) vobject_class->description = _( "join a pair of images" ); vobject_class->build = vips_join_build; - operation_class->flags = VIPS_OPERATION_SEQUENTIAL; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; VIPS_ARG_IMAGE( class, "in1", -1, _( "in1" ), diff --git a/libvips/conversion/msb.c b/libvips/conversion/msb.c index 4eadae1e..cefb366b 100644 --- a/libvips/conversion/msb.c +++ b/libvips/conversion/msb.c @@ -1,4 +1,4 @@ -/* im_msb +/* vips_msb() * * Copyright: 2006, The Nottingham Trent University * @@ -239,7 +239,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; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; VIPS_ARG_IMAGE( class, "in", 0, _( "Input" ), diff --git a/libvips/conversion/recomb.c b/libvips/conversion/recomb.c index 76d6e3f4..abc2b265 100644 --- a/libvips/conversion/recomb.c +++ b/libvips/conversion/recomb.c @@ -196,7 +196,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; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; VIPS_ARG_IMAGE( class, "in", 0, _( "Input" ), diff --git a/libvips/conversion/sequential.c b/libvips/conversion/sequential.c index 17cd68d7..d5b473f5 100644 --- a/libvips/conversion/sequential.c +++ b/libvips/conversion/sequential.c @@ -76,6 +76,7 @@ typedef struct _VipsSequential { VipsImage *in; int tile_height; + VipsAccess access; gboolean trace; /* Lock access to y_pos with this, use the cond to wake up stalled @@ -266,7 +267,7 @@ vips_sequential_build( VipsObject *object ) if( vips_linecache( sequential->in, &t, "tile_height", sequential->tile_height, - "strategy", VIPS_CACHE_SEQUENTIAL, + "access", sequential->access, NULL ) ) return( -1 ); @@ -319,12 +320,20 @@ vips_sequential_class_init( VipsSequentialClass *class ) VIPS_ARGUMENT_OPTIONAL_INPUT, G_STRUCT_OFFSET( VipsSequential, tile_height ), 1, 1000000, 1 ); + + VIPS_ARG_ENUM( class, "access", 6, + _( "Strategy" ), + _( "Expected access pattern" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsSequential, access ), + VIPS_TYPE_ACCESS, VIPS_ACCESS_SEQUENTIAL ); } 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; @@ -341,6 +350,7 @@ vips_sequential_init( VipsSequential *sequential ) * * @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 @@ -357,6 +367,9 @@ vips_sequential_init( VipsSequential *sequential ) * @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_image_cache(). * * Returns: 0 on success, -1 on error. diff --git a/libvips/conversion/tilecache.c b/libvips/conversion/tilecache.c index e9d857da..52c63c2b 100644 --- a/libvips/conversion/tilecache.c +++ b/libvips/conversion/tilecache.c @@ -119,7 +119,7 @@ typedef struct _VipsBlockCache { int tile_width; int tile_height; int max_tiles; - VipsCacheStrategy strategy; + VipsAccess access; gboolean threaded; gboolean persistent; @@ -261,15 +261,16 @@ vips_tile_search_recycle( gpointer key, gpointer value, gpointer user_data ) /* Only consider unreffed tiles for recycling. */ if( !tile->ref_count ) { - switch( cache->strategy ) { - case VIPS_CACHE_RANDOM: + switch( cache->access ) { + case VIPS_ACCESS_RANDOM: if( tile->time < search->oldest ) { search->oldest = tile->time; search->tile = tile; } break; - case VIPS_CACHE_SEQUENTIAL: + case VIPS_ACCESS_SEQUENTIAL: + case VIPS_ACCESS_SEQUENTIAL_UNBUFFERED: if( tile->pos.top < search->topmost ) { search->topmost = tile->pos.top; search->tile = tile; @@ -410,12 +411,12 @@ vips_block_cache_class_init( VipsBlockCacheClass *class ) G_STRUCT_OFFSET( VipsBlockCache, tile_height ), 1, 1000000, 128 ); - VIPS_ARG_ENUM( class, "strategy", 6, - _( "Strategy" ), + VIPS_ARG_ENUM( class, "access", 6, + _( "Access" ), _( "Expected access pattern" ), VIPS_ARGUMENT_OPTIONAL_INPUT, - G_STRUCT_OFFSET( VipsBlockCache, strategy ), - VIPS_TYPE_CACHE_STRATEGY, VIPS_CACHE_RANDOM ); + G_STRUCT_OFFSET( VipsBlockCache, access ), + VIPS_TYPE_ACCESS, VIPS_ACCESS_RANDOM ); VIPS_ARG_BOOL( class, "threaded", 7, _( "Threaded" ), @@ -476,7 +477,7 @@ vips_block_cache_init( VipsBlockCache *cache ) cache->tile_width = 128; cache->tile_height = 128; cache->max_tiles = 1000; - cache->strategy = VIPS_CACHE_RANDOM; + cache->access = VIPS_ACCESS_RANDOM; cache->threaded = FALSE; cache->persistent = FALSE; @@ -799,7 +800,7 @@ vips_tile_cache_init( VipsTileCache *cache ) * @tile_width: width of tiles in cache * @tile_height: height of tiles in cache * @max_tiles: maximum number of tiles to cache - * @strategy: hint expected access pattern #VipsCacheStrategy + * @access: hint expected access pattern #VipsAccess * @threaded: allow many threads * @persistent: don't drop cache at end of computation * @@ -812,12 +813,13 @@ vips_tile_cache_init( VipsTileCache *cache ) * Each cache tile is made with a single call to * vips_image_prepare(). * - * When the cache fills, a tile is chosen for reuse. If @strategy is - * #VIPS_CACHE_RANDOM, then the least-recently-used tile is reused. If - * @strategy is #VIPS_CACHE_SEQUENTIAL, the top-most tile is reused. + * 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, + * the top-most tile is reused. * * By default, @tile_width and @tile_height are 128 pixels, and the operation - * will cache up to 1,000 tiles. @strategy defaults to #VIPS_CACHE_RANDOM. + * will cache up to 1,000 tiles. @access defaults to #VIPS_ACCESS_RANDOM. * * Normally, only a single thread at once is allowed to calculate tiles. If * you set @threaded to %TRUE, vips_tilecache() will allow many threads to @@ -846,6 +848,8 @@ vips_tilecache( VipsImage *in, VipsImage **out, ... ) typedef struct _VipsLineCache { VipsBlockCache parent_instance; + VipsAccess access; + } VipsLineCache; typedef VipsBlockCacheClass VipsLineCacheClass; @@ -863,9 +867,12 @@ vips_line_cache_gen( VipsRegion *or, /* We size up the cache to the largest request. */ if( or->valid.height > - block_cache->max_tiles * block_cache->tile_height ) + block_cache->max_tiles * block_cache->tile_height ) { block_cache->max_tiles = 1 + (or->valid.height / block_cache->tile_height); + VIPS_DEBUG_MSG( "vips_line_cache_gen: bumped max_tiles to %d\n", + block_cache->max_tiles ); + } g_mutex_unlock( block_cache->lock ); @@ -879,10 +886,6 @@ vips_line_cache_build( VipsObject *object ) VipsBlockCache *block_cache = (VipsBlockCache *) object; VipsLineCache *cache = (VipsLineCache *) object; - int tile_width; - int tile_height; - int nlines; - VIPS_DEBUG_MSG( "vips_line_cache_build\n" ); if( VIPS_OBJECT_CLASS( vips_line_cache_parent_class )-> @@ -893,18 +896,32 @@ vips_line_cache_build( VipsObject *object ) */ block_cache->tile_width = block_cache->in->Xsize; - /* Enough lines for two complete buffers would be exactly right. Make - * it 3 to give us some slop room. - * - * This can go up with request size, see vips_line_cache_gen(). - */ - vips_get_tile_size( block_cache->in, - &tile_width, &tile_height, &nlines ); - block_cache->max_tiles = 3 * (1 + nlines / block_cache->tile_height); + block_cache->access = cache->access; - VIPS_DEBUG_MSG( "vips_line_cache_build: max_tiles = %d, " - "tile_height = %d, nlines = %d\n", - block_cache->max_tiles, block_cache->tile_height, nlines ); + if( cache->access == VIPS_ACCESS_SEQUENTIAL_UNBUFFERED ) + block_cache->max_tiles = 1; + else { + /* Enough lines for two complete buffers would be exactly + * right. Make it 3 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 nlines; + + vips_get_tile_size( block_cache->in, + &tile_width, &tile_height, &nlines ); + block_cache->max_tiles = 3 * + (1 + nlines / block_cache->tile_height); + + VIPS_DEBUG_MSG( "vips_line_cache_build: nlines = %d\n", + nlines ); + } + + VIPS_DEBUG_MSG( "vips_line_cache_build: " + "max_tiles = %d, tile_height = %d\n", + block_cache->max_tiles, block_cache->tile_height ); if( vips_image_pio_input( block_cache->in ) ) return( -1 ); @@ -937,11 +954,19 @@ vips_line_cache_class_init( VipsLineCacheClass *class ) vobject_class->description = _( "cache an image as a set of lines" ); vobject_class->build = vips_line_cache_build; + VIPS_ARG_ENUM( class, "access", 6, + _( "Access" ), + _( "Expected access pattern" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsLineCache, access ), + VIPS_TYPE_ACCESS, VIPS_ACCESS_SEQUENTIAL ); + } static void vips_line_cache_init( VipsLineCache *cache ) { + cache->access = VIPS_ACCESS_SEQUENTIAL; } /** @@ -952,29 +977,31 @@ vips_line_cache_init( VipsLineCache *cache ) * * Optional arguments: * - * @strategy: hint expected access pattern #VipsCacheStrategy + * @access: hint expected access pattern #VipsAccess * @tile_height: height of tiles in cache * @threaded: allow many threads * * This operation behaves rather like vips_copy() between images - * @in and @out, except that it keeps a cache of computed pixels. - * This cache is made of a set of scanlines. The number of lines cached is - * equal to the maximum prepare request. + * @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. * * Each cache tile is made with a single call to * vips_image_prepare(). * - * When the cache fills, a tile is chosen for reuse. If @strategy is - * #VIPS_CACHE_RANDOM, then the least-recently-used tile is reused. If - * @strategy is #VIPS_CACHE_SEQUENTIAL, the top-most tile is reused. - * @strategy defaults to #VIPS_CACHE_RANDOM. + * 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, + * 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 * vips_linecache() uses. The default is 1 (a single scanline). * * Normally, only a single thread at once is allowed to calculate tiles. If * you set @threaded to %TRUE, vips_linecache() will allow many threads to - * calculate tiles at once, and share the cache between them. + * calculate tiles at once and share the cache between them. * * See also: vips_cache(), vips_tilecache(). * diff --git a/libvips/conversion/zoom.c b/libvips/conversion/zoom.c index 07ae476e..0e7553f5 100644 --- a/libvips/conversion/zoom.c +++ b/libvips/conversion/zoom.c @@ -386,7 +386,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; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; VIPS_ARG_IMAGE( class, "input", 0, _( "Input" ), diff --git a/libvips/deprecated/im_jpeg2vips.c b/libvips/deprecated/im_jpeg2vips.c index 8ba81b3b..eda579fb 100644 --- a/libvips/deprecated/im_jpeg2vips.c +++ b/libvips/deprecated/im_jpeg2vips.c @@ -115,7 +115,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 ) ) + header_only, shrink, fail_on_warn, TRUE ) ) return( -1 ); #else vips_error( "im_jpeg2vips", diff --git a/libvips/deprecated/im_png2vips.c b/libvips/deprecated/im_png2vips.c index 39e84bc7..deaa32cc 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 ) ) + if( vips__png_read( filename, out, TRUE ) ) return( -1 ); } #else diff --git a/libvips/deprecated/im_tiff2vips.c b/libvips/deprecated/im_tiff2vips.c index f6678f7a..1bb1c90d 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 ) ) + if( vips__tiff_read( filename, out, page, TRUE ) ) return( -1 ); } #else diff --git a/libvips/deprecated/vips7compat.c b/libvips/deprecated/vips7compat.c index 154d372f..062c2b06 100644 --- a/libvips/deprecated/vips7compat.c +++ b/libvips/deprecated/vips7compat.c @@ -3770,7 +3770,7 @@ im_tile_cache( IMAGE *in, IMAGE *out, "tile_width", tile_width, "tile_height", tile_height, "max_tiles", max_tiles, - "strategy", VIPS_CACHE_SEQUENTIAL, + "access", VIPS_ACCESS_SEQUENTIAL, "threaded", TRUE, NULL ) ) return( -1 ); diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index 5b92723b..edf72480 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -135,26 +135,6 @@ * need to swap bytes. See vips_copy(). */ -/** - * VipsForeignAccess: - * @VIPS_FOREIGN_ACCESS_RANDOM: can read anywhere - * @VIPS_FOREIGN_ACCESS_SEQUENTIAL: top-to-bottom reading only, but with a small buffer - * @VIPS_FOREIGN_ACCESS_SEQUENTIAL_UNBUFFERED: top-to-bottom reading only - * - * Set this flag on a loader to indicate the type of access you need. - * - * @VIPS_FOREIGN_ACCESS_RANDOM means you require full random access to the - * image. This is usually the most expensive type of access to provide. - * - * @VIPS_FOREIGN_ACCESS_SEQUENTIAL means you only need need top-to-bottom - * reading, but you need a smll buffer (a few hundred scanlines) behind the - * read point. - * - * @VIPS_FOREIGN_ACCESS_SEQUENTIAL_UNBUFFERED means you only need - * top-to-bottom access. This is usually the cheapest type of access to - * provide. - */ - /** * VipsForeignClass: * @@ -705,7 +685,7 @@ vips_foreign_load_temp( VipsForeignLoad *load ) * directly. */ if( (load->flags & VIPS_FOREIGN_SEQUENTIAL) && - load->access != VIPS_FOREIGN_ACCESS_RANDOM ) { + load->access != VIPS_ACCESS_RANDOM ) { #ifdef DEBUG printf( "vips_foreign_load_temp: partial sequential temp\n" ); #endif /*DEBUG*/ @@ -961,7 +941,7 @@ vips_foreign_load_class_init( VipsForeignLoadClass *class ) _( "Required access pattern for this file" ), VIPS_ARGUMENT_OPTIONAL_INPUT, G_STRUCT_OFFSET( VipsForeignLoad, access ), - VIPS_TYPE_FOREIGN_ACCESS, VIPS_FOREIGN_ACCESS_RANDOM ); + VIPS_TYPE_ACCESS, VIPS_ACCESS_RANDOM ); VIPS_ARG_BOOL( class, "sequential", 10, _( "Sequential" ), @@ -976,7 +956,7 @@ static void vips_foreign_load_init( VipsForeignLoad *load ) { load->disc = TRUE; - load->access = VIPS_FOREIGN_ACCESS_RANDOM; + load->access = VIPS_ACCESS_RANDOM; } /* Abstract base class for image savers. diff --git a/libvips/foreign/jpeg.h b/libvips/foreign/jpeg.h index b8a9f793..ac0f6f3c 100644 --- a/libvips/foreign/jpeg.h +++ b/libvips/foreign/jpeg.h @@ -60,11 +60,9 @@ int vips__jpeg_write_buffer( VipsImage *in, int vips__isjpeg( const char *filename ); int vips__jpeg_read_file( const char *name, VipsImage *out, - gboolean header_only, - int shrink, gboolean fail ); + gboolean header_only, int shrink, gboolean fail, gboolean readbehind ); int vips__jpeg_read_buffer( void *buf, size_t len, VipsImage *out, - gboolean header_only, - int shrink, int fail ); + gboolean header_only, int shrink, int fail, gboolean readbehind ); #ifdef __cplusplus } diff --git a/libvips/foreign/jpeg2vips.c b/libvips/foreign/jpeg2vips.c index 777088e2..50fd43d3 100644 --- a/libvips/foreign/jpeg2vips.c +++ b/libvips/foreign/jpeg2vips.c @@ -144,6 +144,10 @@ typedef struct _ReadJpeg { */ gboolean fail; + /* Use a read behind buffer. + */ + gboolean readbehind; + /* Used for file input only. */ char *filename; @@ -208,7 +212,7 @@ readjpeg_close( VipsObject *object, ReadJpeg *jpeg ) } static ReadJpeg * -readjpeg_new( VipsImage *out, int shrink, gboolean fail ) +readjpeg_new( VipsImage *out, int shrink, gboolean fail, gboolean readbehind ) { ReadJpeg *jpeg; @@ -218,6 +222,7 @@ readjpeg_new( VipsImage *out, int shrink, gboolean fail ) jpeg->out = out; jpeg->shrink = shrink; jpeg->fail = fail; + jpeg->readbehind = readbehind; jpeg->filename = NULL; jpeg->decompressing = FALSE; @@ -959,6 +964,9 @@ 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 ) || vips_image_write( t[1], out ) ) return( -1 ); @@ -970,12 +978,12 @@ read_jpeg_image( ReadJpeg *jpeg, VipsImage *out ) */ int vips__jpeg_read_file( const char *filename, VipsImage *out, - gboolean header_only, int shrink, gboolean fail ) + gboolean header_only, int shrink, gboolean fail, gboolean readbehind ) { ReadJpeg *jpeg; int result; - if( !(jpeg = readjpeg_new( out, shrink, fail )) ) + if( !(jpeg = readjpeg_new( out, shrink, fail, readbehind )) ) return( -1 ); /* Here for longjmp() from vips__new_error_exit() during startup. @@ -1189,12 +1197,12 @@ readjpeg_buffer (ReadJpeg *jpeg, void *buf, size_t len) int vips__jpeg_read_buffer( void *buf, size_t len, VipsImage *out, - gboolean header_only, int shrink, int fail ) + gboolean header_only, int shrink, int fail, gboolean readbehind ) { ReadJpeg *jpeg; int result; - if( !(jpeg = readjpeg_new( out, shrink, fail )) ) + if( !(jpeg = readjpeg_new( out, shrink, fail, readbehind )) ) return( -1 ); if( setjmp( jpeg->eman.jmp ) ) { diff --git a/libvips/foreign/jpegload.c b/libvips/foreign/jpegload.c index e9d80784..e89d66f3 100644 --- a/libvips/foreign/jpegload.c +++ b/libvips/foreign/jpegload.c @@ -199,7 +199,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, jpeg->fail ) ) + TRUE, jpeg->shrink, jpeg->fail, FALSE ) ) return( -1 ); return( 0 ); @@ -212,7 +212,8 @@ vips_foreign_load_jpeg_file_load( VipsForeignLoad *load ) VipsForeignLoadJpegFile *file = (VipsForeignLoadJpegFile *) load; if( vips__jpeg_read_file( file->filename, load->real, - FALSE, jpeg->shrink, jpeg->fail ) ) + FALSE, jpeg->shrink, jpeg->fail, + load->access == VIPS_ACCESS_SEQUENTIAL ) ) return( -1 ); return( 0 ); @@ -276,7 +277,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, jpeg->fail ) ) + load->out, TRUE, jpeg->shrink, jpeg->fail, FALSE ) ) return( -1 ); return( 0 ); @@ -289,7 +290,8 @@ 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, jpeg->fail ) ) + load->real, FALSE, jpeg->shrink, jpeg->fail, + load->access == VIPS_ACCESS_SEQUENTIAL ) ) return( -1 ); return( 0 ); diff --git a/libvips/foreign/pngload.c b/libvips/foreign/pngload.c index cf49b6dd..a4954f66 100644 --- a/libvips/foreign/pngload.c +++ b/libvips/foreign/pngload.c @@ -104,7 +104,8 @@ vips_foreign_load_png_load( VipsForeignLoad *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( 0 ); @@ -178,7 +179,7 @@ vips_foreign_load_png_buffer_load( VipsForeignLoad *load ) VipsForeignLoadPngBuffer *png = (VipsForeignLoadPngBuffer *) load; if( vips__png_read_buffer( png->buf->data, png->buf->length, - load->real ) ) + load->real, load->access == VIPS_ACCESS_SEQUENTIAL ) ) return( -1 ); return( 0 ); diff --git a/libvips/foreign/tiff.h b/libvips/foreign/tiff.h index 73cc0bfb..af8a308f 100644 --- a/libvips/foreign/tiff.h +++ b/libvips/foreign/tiff.h @@ -49,7 +49,8 @@ int vips__tiff_write( VipsImage *in, const char *filename, VipsForeignTiffResunit resunit, double xres, double yres, gboolean bigtiff ); -int vips__tiff_read( const char *filename, VipsImage *out, int page ); +int vips__tiff_read( const char *filename, VipsImage *out, int page, + gboolean readbehind ); int vips__tiff_read_header( const char *filename, VipsImage *out, int page ); gboolean vips__istifftiled( const char *filename ); gboolean vips__istiff( const char *filename ); diff --git a/libvips/foreign/tiff2vips.c b/libvips/foreign/tiff2vips.c index 49749e8e..8367fc25 100644 --- a/libvips/foreign/tiff2vips.c +++ b/libvips/foreign/tiff2vips.c @@ -206,10 +206,8 @@ typedef struct _ReadTiff { */ char *filename; VipsImage *out; - - /* From filename. - */ int page; + gboolean readbehind; /* The TIFF we read. */ @@ -1497,6 +1495,9 @@ read_stripwise( ReadTiff *rtiff, VipsImage *out ) rtiff, NULL ) || vips_sequential( t[0], &t[1], "tile_height", rtiff->rows_per_strip, + "access", rtiff->readbehind ? + VIPS_ACCESS_SEQUENTIAL : + VIPS_ACCESS_SEQUENTIAL_UNBUFFERED, NULL ) || vips_image_write( t[1], out ) ) return( -1 ); @@ -1511,7 +1512,8 @@ readtiff_destroy( VipsObject *object, ReadTiff *rtiff ) } static ReadTiff * -readtiff_new( const char *filename, VipsImage *out, int page ) +readtiff_new( const char *filename, VipsImage *out, int page, + gboolean readbehind ) { ReadTiff *rtiff; @@ -1521,6 +1523,7 @@ readtiff_new( const char *filename, VipsImage *out, int page ) rtiff->filename = vips_strdup( VIPS_OBJECT( out ), filename ); rtiff->out = out; rtiff->page = page; + rtiff->readbehind = readbehind; rtiff->tiff = NULL; rtiff->sfn = NULL; rtiff->client = NULL; @@ -1594,7 +1597,8 @@ istiffpyramid( const char *name ) */ int -vips__tiff_read( const char *filename, VipsImage *out, int page ) +vips__tiff_read( const char *filename, VipsImage *out, int page, + gboolean readbehind ) { ReadTiff *rtiff; @@ -1605,7 +1609,7 @@ vips__tiff_read( const char *filename, VipsImage *out, int page ) vips__tiff_init(); - if( !(rtiff = readtiff_new( filename, out, page )) ) + if( !(rtiff = readtiff_new( filename, out, page, readbehind )) ) return( -1 ); if( !(rtiff->tiff = get_directory( rtiff->filename, rtiff->page )) ) { @@ -1633,7 +1637,7 @@ vips__tiff_read_header( const char *filename, VipsImage *out, int page ) vips__tiff_init(); - if( !(rtiff = readtiff_new( filename, out, page )) ) + if( !(rtiff = readtiff_new( filename, out, page, FALSE )) ) return( -1 ); if( !(rtiff->tiff = get_directory( rtiff->filename, rtiff->page )) ) { diff --git a/libvips/foreign/tiffload.c b/libvips/foreign/tiffload.c index e1f3c6f5..cbcff533 100644 --- a/libvips/foreign/tiffload.c +++ b/libvips/foreign/tiffload.c @@ -108,7 +108,8 @@ vips_foreign_load_tiff_load( VipsForeignLoad *load ) { VipsForeignLoadTiff *tiff = (VipsForeignLoadTiff *) load; - if( vips__tiff_read( tiff->filename, load->real, tiff->page ) ) + if( vips__tiff_read( tiff->filename, load->real, tiff->page, + load->access == VIPS_ACCESS_SEQUENTIAL ) ) return( -1 ); return( 0 ); diff --git a/libvips/foreign/vipspng.c b/libvips/foreign/vipspng.c index a403940c..02a87e38 100644 --- a/libvips/foreign/vipspng.c +++ b/libvips/foreign/vipspng.c @@ -126,6 +126,7 @@ 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; @@ -141,6 +142,7 @@ typedef struct { char *buffer; size_t length; size_t read_pos; + } Read; static void @@ -153,7 +155,7 @@ read_destroy( VipsImage *out, Read *read ) } static Read * -read_new( VipsImage *out ) +read_new( VipsImage *out, gboolean readbehind ) { Read *read; @@ -161,6 +163,7 @@ read_new( VipsImage *out ) return( NULL ); read->name = NULL; + read->readbehind = readbehind; read->out = out; read->y_pos = 0; read->pPng = NULL; @@ -191,11 +194,11 @@ read_new( VipsImage *out ) } static Read * -read_new_filename( VipsImage *out, const char *name ) +read_new_filename( VipsImage *out, const char *name, gboolean readbehind ) { Read *read; - if( !(read = read_new( out )) ) + if( !(read = read_new( out, readbehind )) ) return( NULL ); read->name = vips_strdup( VIPS_OBJECT( out ), name ); @@ -393,7 +396,7 @@ vips__png_header( const char *name, VipsImage *out ) { Read *read; - if( !(read = read_new_filename( out, name )) || + if( !(read = read_new_filename( out, name, FALSE )) || png2vips_header( read, out ) ) return( -1 ); @@ -492,7 +495,7 @@ vips__png_isinterlaced( const char *filename ) int interlace_type; image = vips_image_new(); - if( !(read = read_new_filename( image, filename )) ) { + if( !(read = read_new_filename( image, filename, FALSE )) ) { g_object_unref( image ); return( -1 ); } @@ -527,6 +530,9 @@ 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 ); @@ -536,7 +542,7 @@ png2vips_image( Read *read, VipsImage *out ) } int -vips__png_read( const char *filename, VipsImage *out ) +vips__png_read( const char *filename, VipsImage *out, gboolean readbehind ) { Read *read; @@ -544,7 +550,7 @@ vips__png_read( const char *filename, VipsImage *out ) printf( "vips__png_read: reading \"%s\"\n", filename ); #endif /*DEBUG*/ - if( !(read = read_new_filename( out, filename )) || + if( !(read = read_new_filename( out, filename, readbehind )) || png2vips_image( read, out ) ) return( -1 ); @@ -581,15 +587,16 @@ vips_png_read_buffer( png_structp pPng, png_bytep data, png_size_t length ) } static Read * -read_new_buffer( VipsImage *out, char *buffer, size_t length ) +read_new_buffer( VipsImage *out, char *buffer, size_t length, + gboolean readbehind ) { Read *read; - if( !(read = read_new( out )) ) + if( !(read = read_new( out, readbehind )) ) return( NULL ); - read->buffer = buffer; read->length = length; + read->buffer = buffer; png_set_read_fn( read->pPng, read, vips_png_read_buffer ); @@ -606,7 +613,7 @@ vips__png_header_buffer( char *buffer, size_t length, VipsImage *out ) { Read *read; - if( !(read = read_new_buffer( out, buffer, length )) || + if( !(read = read_new_buffer( out, buffer, length, FALSE )) || png2vips_header( read, out ) ) return( -1 ); @@ -614,11 +621,12 @@ vips__png_header_buffer( char *buffer, size_t length, VipsImage *out ) } int -vips__png_read_buffer( char *buffer, size_t length, VipsImage *out ) +vips__png_read_buffer( char *buffer, size_t length, VipsImage *out, + gboolean readbehind ) { Read *read; - if( !(read = read_new_buffer( out, buffer, length )) || + if( !(read = read_new_buffer( out, buffer, length, readbehind )) || png2vips_image( read, out ) ) return( -1 ); diff --git a/libvips/foreign/vipspng.h b/libvips/foreign/vipspng.h index 9922eecd..051ac55b 100644 --- a/libvips/foreign/vipspng.h +++ b/libvips/foreign/vipspng.h @@ -36,11 +36,12 @@ extern "C" { #endif /*__cplusplus*/ int vips__png_header( const char *name, VipsImage *out ); -int vips__png_read( const char *name, VipsImage *out ); +int vips__png_read( const char *name, VipsImage *out, gboolean readbehind ); int vips__png_ispng( const char *filename ); gboolean vips__png_isinterlaced( const char *filename ); extern const char *vips__png_suffs[]; -int vips__png_read_buffer( char *buffer, size_t length, VipsImage *out ); +int vips__png_read_buffer( char *buffer, size_t length, VipsImage *out, + gboolean readbehind ); int vips__png_header_buffer( char *buffer, size_t length, VipsImage *out ); int vips__png_write( VipsImage *in, const char *filename, diff --git a/libvips/histogram/maplut.c b/libvips/histogram/maplut.c index 7316692a..2f92fc3d 100644 --- a/libvips/histogram/maplut.c +++ b/libvips/histogram/maplut.c @@ -606,7 +606,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; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; VIPS_ARG_IMAGE( class, "in", 1, _( "Input" ), diff --git a/libvips/include/vips/conversion.h b/libvips/include/vips/conversion.h index 320e9909..f2c891f6 100644 --- a/libvips/include/vips/conversion.h +++ b/libvips/include/vips/conversion.h @@ -38,39 +38,6 @@ extern "C" { #endif /*__cplusplus*/ -/** - * VipsExtend: - * @VIPS_EXTEND_BLACK: extend with black (all 0) pixels - * @VIPS_EXTEND_COPY: copy the image edges - * @VIPS_EXTEND_REPEAT: repeat the whole image - * @VIPS_EXTEND_MIRROR: mirror the whole image - * @VIPS_EXTEND_WHITE: extend with white (all bits set) pixels - * @VIPS_EXTEND_BACKGROUND: extend with colour from the @background property - * - * See vips_embed(), vips_conv(), vips_affine() and so on. - * - * When the edges of an image are extended, you can specify - * how you want the extension done. - * - * #VIPS_EXTEND_BLACK --- new pixels are black, ie. all bits are zero. - * - * #VIPS_EXTEND_COPY --- each new pixel takes the value of the nearest edge - * pixel - * - * #VIPS_EXTEND_REPEAT --- the image is tiled to fill the new area - * - * #VIPS_EXTEND_MIRROR --- the image is reflected and tiled to reduce hash - * edges - * - * #VIPS_EXTEND_WHITE --- new pixels are white, ie. all bits are set - - * #VIPS_EXTEND_BACKGROUND --- colour set from the @background property - * - * We have to specify the exact value of each enum member since we have to - * keep these frozen for back compat with vips7. - * - * See also: vips_embed(). - */ typedef enum { VIPS_EXTEND_BLACK, VIPS_EXTEND_COPY, @@ -81,39 +48,12 @@ typedef enum { VIPS_EXTEND_LAST } VipsExtend; -/** - * VipsDirection: - * @VIPS_DIRECTION_HORIZONTAL: left-right - * @VIPS_DIRECTION_VERTICAL: top-bottom - * - * See vips_flip(), vips_join() and so on. - * - * Operations like vips_flip() need to be told whether to flip left-right or - * top-bottom. - * - * See also: vips_flip(), vips_join(). - */ typedef enum { VIPS_DIRECTION_HORIZONTAL, VIPS_DIRECTION_VERTICAL, VIPS_DIRECTION_LAST } VipsDirection; -/** - * VipsAlign: - * @VIPS_ALIGN_LOW: align low coordinate edge - * @VIPS_ALIGN_CENTRE: align centre - * @VIPS_ALIGN_HIGH: align high coordinate edge - * - * See vips_join() and so on. - * - * Operations like vips_join() need to be told whether to align images on the - * low or high coordinate edge, or centre. - * - * - * - * See also: vips_join(). - */ typedef enum { VIPS_ALIGN_LOW, VIPS_ALIGN_CENTRE, @@ -121,19 +61,6 @@ typedef enum { VIPS_ALIGN_LAST } VipsAlign; -/** - * VipsAngle: - * @VIPS_ANGLE_0: no rotate - * @VIPS_ANGLE_90: 90 degrees anti-clockwise - * @VIPS_ANGLE_180: 180 degree rotate - * @VIPS_ANGLE_270: 90 degrees clockwise - * - * See vips_rot() and so on. - * - * Fixed rotate angles. - * - * See also: vips_rot(). - */ typedef enum { VIPS_ANGLE_0, VIPS_ANGLE_90, @@ -142,24 +69,6 @@ typedef enum { VIPS_ANGLE_LAST } VipsAngle; -/** - * VipsCacheStrategy: - * @VIPS_CACHE_RANDOM: expect random access - * @VIPS_CACHE_SEQUENTIAL: expect sequential access - * - * See vips_tilecache() and friends. - * - * Used to hint to caches about the expected access pattern. RANDOM might mean - * LRU eviction, SEQUENTIAL might mean top-most eviction. - * - * See also: vips_tilecache(). - */ -typedef enum { - VIPS_CACHE_RANDOM, - VIPS_CACHE_SEQUENTIAL, - VIPS_CACHE_LAST -} VipsCacheStrategy; - int vips_copy( VipsImage *in, VipsImage **out, ... ) __attribute__((sentinel)); int vips_tilecache( VipsImage *in, VipsImage **out, ... ) diff --git a/libvips/include/vips/enumtypes.h b/libvips/include/vips/enumtypes.h index 4f0527c6..66393cbd 100644 --- a/libvips/include/vips/enumtypes.h +++ b/libvips/include/vips/enumtypes.h @@ -9,8 +9,6 @@ G_BEGIN_DECLS /* enumerations from "../../../libvips/include/vips/foreign.h" */ GType vips_foreign_flags_get_type (void) G_GNUC_CONST; #define VIPS_TYPE_FOREIGN_FLAGS (vips_foreign_flags_get_type()) -GType vips_foreign_access_get_type (void) G_GNUC_CONST; -#define VIPS_TYPE_FOREIGN_ACCESS (vips_foreign_access_get_type()) GType vips_saveable_get_type (void) G_GNUC_CONST; #define VIPS_TYPE_SAVEABLE (vips_saveable_get_type()) GType vips_foreign_tiff_compression_get_type (void) G_GNUC_CONST; @@ -49,8 +47,6 @@ GType vips_align_get_type (void) G_GNUC_CONST; #define VIPS_TYPE_ALIGN (vips_align_get_type()) GType vips_angle_get_type (void) G_GNUC_CONST; #define VIPS_TYPE_ANGLE (vips_angle_get_type()) -GType vips_cache_strategy_get_type (void) G_GNUC_CONST; -#define VIPS_TYPE_CACHE_STRATEGY (vips_cache_strategy_get_type()) /* enumerations from "../../../libvips/include/vips/util.h" */ GType vips_token_get_type (void) G_GNUC_CONST; #define VIPS_TYPE_TOKEN (vips_token_get_type()) @@ -65,6 +61,8 @@ GType vips_band_format_get_type (void) G_GNUC_CONST; #define VIPS_TYPE_BAND_FORMAT (vips_band_format_get_type()) GType vips_coding_get_type (void) G_GNUC_CONST; #define VIPS_TYPE_CODING (vips_coding_get_type()) +GType vips_access_get_type (void) G_GNUC_CONST; +#define VIPS_TYPE_ACCESS (vips_access_get_type()) /* enumerations from "../../../libvips/include/vips/colour.h" */ GType vips_intent_get_type (void) G_GNUC_CONST; #define VIPS_TYPE_INTENT (vips_intent_get_type()) diff --git a/libvips/include/vips/foreign.h b/libvips/include/vips/foreign.h index 38507dcc..b3b1e79d 100644 --- a/libvips/include/vips/foreign.h +++ b/libvips/include/vips/foreign.h @@ -110,12 +110,6 @@ typedef enum /*< flags >*/ { (G_TYPE_INSTANCE_GET_CLASS( (obj), \ VIPS_TYPE_FOREIGN_LOAD, VipsForeignLoadClass )) -typedef enum { - VIPS_FOREIGN_ACCESS_RANDOM, - VIPS_FOREIGN_ACCESS_SEQUENTIAL, - VIPS_FOREIGN_ACCESS_SEQUENTIAL_UNBUFFERED -} VipsForeignAccess; - typedef struct _VipsForeignLoad { VipsForeign parent_object; /*< private >*/ @@ -124,9 +118,9 @@ typedef struct _VipsForeignLoad { */ gboolean disc; - /* Type of access the reader requires. + /* Type of access upstream wants and the loader must supply. */ - VipsForeignAccess access; + VipsAccess access; /* Flags for this load operation. */ diff --git a/libvips/include/vips/image.h b/libvips/include/vips/image.h index 83b06185..5ba8689b 100644 --- a/libvips/include/vips/image.h +++ b/libvips/include/vips/image.h @@ -47,44 +47,6 @@ extern "C" { #define VIPS_MAGIC_INTEL (0xb6a6f208U) #define VIPS_MAGIC_SPARC (0x08f2a6b6U) -/** - * VipsDemandStyle: - * @VIPS_DEMAND_STYLE_SMALLTILE: demand in small (typically 64x64 pixel) tiles - * @VIPS_DEMAND_STYLE_FATSTRIP: demand in fat (typically 10 pixel high) strips - * @VIPS_DEMAND_STYLE_THINSTRIP: demand in thin (typically 1 pixel high) strips - * @VIPS_DEMAND_STYLE_ANY: demand geometry does not matter - * - * See vips_demand_hint(). Operations can hint to the VIPS image IO system about - * the kind of demand geometry they prefer. - * - * These demand styles are given below in order of increasing - * restrictiveness. When demanding output from a pipeline, - * vips_image_generate() - * will use the most restrictive of the styles requested by the operations - * in the pipeline. - * - * #VIPS_DEMAND_STYLE_THINSTRIP --- This operation would like to output strips - * the width of the image and a few pels high. This is option suitable for - * point-to-point operations, such as those in the arithmetic package. - * - * This option is only efficient for cases where each output pel depends - * upon the pel in the corresponding position in the input image. - * - * #VIPS_DEMAND_STYLE_FATSTRIP --- This operation would like to output strips - * the width of the image and as high as possible. This option is suitable - * for area operations which do not violently transform coordinates, such - * as im_conv(). - * - * #VIPS_DEMAND_STYLE_SMALLTILE --- This is the most general demand format. - * Output is demanded in small (around 100x100 pel) sections. This style works - * reasonably efficiently, even for bizzare operations like 45 degree rotate. - * - * #VIPS_DEMAND_STYLE_ANY --- This image is not being demand-read from a disc - * file (even indirectly) so any demand style is OK. It's used for things like - * im_black() where the pixels are calculated. - * - * See also: vips_demand_hint(). - */ typedef enum { VIPS_DEMAND_STYLE_ERROR = -1, VIPS_DEMAND_STYLE_SMALLTILE, @@ -108,38 +70,6 @@ typedef enum { VIPS_IMAGE_PARTIAL /* partial image */ } VipsImageType; -/** - * VipsInterpretation: - * @VIPS_INTERPRETATION_MULTIBAND: generic many-band image - * @VIPS_INTERPRETATION_B_W: some kind of single-band image - * @VIPS_INTERPRETATION_HISTOGRAM: a 1D image, eg. histogram or lookup table - * @VIPS_INTERPRETATION_FOURIER: image is in fourier space - * @VIPS_INTERPRETATION_XYZ: the first three bands are CIE XYZ - * @VIPS_INTERPRETATION_LAB: pixels are in CIE Lab space - * @VIPS_INTERPRETATION_CMYK: the first four bands are in CMYK space - * @VIPS_INTERPRETATION_LABQ: implies #VIPS_CODING_LABQ - * @VIPS_INTERPRETATION_RGB: generic RGB space - * @VIPS_INTERPRETATION_CMC: a uniform colourspace based on CMC(1:1) - * @VIPS_INTERPRETATION_LCH: pixels are in CIE LCh space - * @VIPS_INTERPRETATION_LABS: CIE LAB coded as three signed 16-bit values - * @VIPS_INTERPRETATION_sRGB: pixels are sRGB - * @VIPS_INTERPRETATION_scRGB: pixels are scRGB - * @VIPS_INTERPRETATION_YXY: pixels are CIE Yxy - * @VIPS_INTERPRETATION_RGB16: generic 16-bit RGB - * @VIPS_INTERPRETATION_GREY16: generic 16-bit mono - * @VIPS_INTERPRETATION_MATRIX: a matrix - * - * How the values in an image should be interpreted. For example, a - * three-band float image of type #VIPS_INTERPRETATION_LAB should have its - * pixels interpreted as coordinates in CIE Lab space. - * - * These values are set by operations as hints to user-interfaces built on top - * of VIPS to help them show images to the user in a meaningful way. - * Operations do not use these values to decide their action. - * - * The gaps in the numbering are historical and must be maintained. Allocate - * new numbers from the end. - */ typedef enum { VIPS_INTERPRETATION_ERROR = -1, VIPS_INTERPRETATION_MULTIBAND = 0, @@ -162,25 +92,6 @@ typedef enum { VIPS_INTERPRETATION_scRGB = 28 } VipsInterpretation; -/** - * VipsBandFormat: - * @VIPS_FORMAT_NOTSET: invalid setting - * @VIPS_FORMAT_UCHAR: unsigned char format - * @VIPS_FORMAT_CHAR: char format - * @VIPS_FORMAT_USHORT: unsigned short format - * @VIPS_FORMAT_SHORT: short format - * @VIPS_FORMAT_UINT: unsigned int format - * @VIPS_FORMAT_INT: int format - * @VIPS_FORMAT_FLOAT: float format - * @VIPS_FORMAT_COMPLEX: complex (two floats) format - * @VIPS_FORMAT_DOUBLE: double float format - * @VIPS_FORMAT_DPCOMPLEX: double complex (two double) format - * - * The format used for each band element. - * - * Each corresponnds to a native C type for the current machine. For example, - * #VIPS_FORMAT_USHORT is unsigned short. - */ typedef enum { VIPS_FORMAT_NOTSET = -1, VIPS_FORMAT_UCHAR = 0, @@ -196,21 +107,6 @@ typedef enum { VIPS_FORMAT_LAST = 10 } VipsBandFormat; -/** - * VipsCoding: - * @VIPS_CODING_NONE: pixels are not coded - * @VIPS_CODING_LABQ: pixels encode 3 float CIELAB values as 4 uchar - * @VIPS_CODING_RAD: pixels encode 3 float RGB as 4 uchar (Radiance coding) - * - * How pixels are coded. - * - * Normally, pixels are uncoded and can be manipulated as you would expect. - * However some file formats code pixels for compression, and sometimes it's - * useful to be able to manipulate images in the coded format. - * - * The gaps in the numbering are historical and must be maintained. Allocate - * new numbers from the end. - */ typedef enum { VIPS_CODING_ERROR = -1, VIPS_CODING_NONE = 0, @@ -219,6 +115,13 @@ typedef enum { VIPS_CODING_LAST = 7 } VipsCoding; +typedef enum { + VIPS_ACCESS_RANDOM, + VIPS_ACCESS_SEQUENTIAL, + VIPS_ACCESS_SEQUENTIAL_UNBUFFERED, + VIPS_ACCESS_LAST +} VipsAccess; + /* Struct we keep a record of execution time in. Passed to eval signal so * it can assess progress. */ diff --git a/libvips/include/vips/operation.h b/libvips/include/vips/operation.h index c10ba8eb..a03eb24b 100644 --- a/libvips/include/vips/operation.h +++ b/libvips/include/vips/operation.h @@ -37,25 +37,11 @@ extern "C" { #include -/** - * VipsOperationFlags: - * @VIPS_OPERATION_NONE: no flags - * @VIPS_OPERATION_SEQUENTIAL: can work sequentially - * @VIPS_OPERATION_NOCACHE: must not be cached - * - * Flags we associate with an operation. - * - * @VIPS_OPERATION_SEQUENTIAL means that the operation works like vips_copy: - * it can happily process images top-to-bottom with only small non-local - * references. - * - * @VIPS_OPERATION_NOCACHE means that the operation must not be cached by - * vips. - */ typedef enum /*< flags >*/ { VIPS_OPERATION_NONE = 0, VIPS_OPERATION_SEQUENTIAL = 1, - VIPS_OPERATION_NOCACHE = 2 + VIPS_OPERATION_SEQUENTIAL_UNBUFFERED = 2, + VIPS_OPERATION_NOCACHE = 3 } VipsOperationFlags; #define VIPS_TYPE_OPERATION (vips_operation_get_type()) diff --git a/libvips/iofuncs/enumtypes.c b/libvips/iofuncs/enumtypes.c index 2f534e12..c343eaaa 100644 --- a/libvips/iofuncs/enumtypes.c +++ b/libvips/iofuncs/enumtypes.c @@ -26,24 +26,6 @@ vips_foreign_flags_get_type( void ) return( etype ); } GType -vips_foreign_access_get_type( void ) -{ - static GType etype = 0; - - if( etype == 0 ) { - static const GEnumValue values[] = { - {VIPS_FOREIGN_ACCESS_RANDOM, "VIPS_FOREIGN_ACCESS_RANDOM", "random"}, - {VIPS_FOREIGN_ACCESS_SEQUENTIAL, "VIPS_FOREIGN_ACCESS_SEQUENTIAL", "sequential"}, - {VIPS_FOREIGN_ACCESS_SEQUENTIAL_UNBUFFERED, "VIPS_FOREIGN_ACCESS_SEQUENTIAL_UNBUFFERED", "sequential-unbuffered"}, - {0, NULL, NULL} - }; - - etype = g_enum_register_static( "VipsForeignAccess", values ); - } - - return( etype ); -} -GType vips_saveable_get_type( void ) { static GType etype = 0; @@ -241,24 +223,6 @@ vips_angle_get_type( void ) return( etype ); } -GType -vips_cache_strategy_get_type( void ) -{ - static GType etype = 0; - - if( etype == 0 ) { - static const GEnumValue values[] = { - {VIPS_CACHE_RANDOM, "VIPS_CACHE_RANDOM", "random"}, - {VIPS_CACHE_SEQUENTIAL, "VIPS_CACHE_SEQUENTIAL", "sequential"}, - {VIPS_CACHE_LAST, "VIPS_CACHE_LAST", "last"}, - {0, NULL, NULL} - }; - - etype = g_enum_register_static( "VipsCacheStrategy", values ); - } - - return( etype ); -} /* enumerations from "../../libvips/include/vips/arithmetic.h" */ GType vips_operation_math_get_type( void ) @@ -567,6 +531,25 @@ vips_coding_get_type( void ) return( etype ); } +GType +vips_access_get_type( void ) +{ + static GType etype = 0; + + if( etype == 0 ) { + static const GEnumValue values[] = { + {VIPS_ACCESS_RANDOM, "VIPS_ACCESS_RANDOM", "random"}, + {VIPS_ACCESS_SEQUENTIAL, "VIPS_ACCESS_SEQUENTIAL", "sequential"}, + {VIPS_ACCESS_SEQUENTIAL_UNBUFFERED, "VIPS_ACCESS_SEQUENTIAL_UNBUFFERED", "sequential-unbuffered"}, + {VIPS_ACCESS_LAST, "VIPS_ACCESS_LAST", "last"}, + {0, NULL, NULL} + }; + + etype = g_enum_register_static( "VipsAccess", values ); + } + + return( etype ); +} /* enumerations from "../../libvips/include/vips/operation.h" */ GType vips_operation_flags_get_type( void ) @@ -577,6 +560,7 @@ vips_operation_flags_get_type( void ) static const GFlagsValue values[] = { {VIPS_OPERATION_NONE, "VIPS_OPERATION_NONE", "none"}, {VIPS_OPERATION_SEQUENTIAL, "VIPS_OPERATION_SEQUENTIAL", "sequential"}, + {VIPS_OPERATION_SEQUENTIAL_UNBUFFERED, "VIPS_OPERATION_SEQUENTIAL_UNBUFFERED", "sequential-unbuffered"}, {VIPS_OPERATION_NOCACHE, "VIPS_OPERATION_NOCACHE", "nocache"}, {0, NULL, NULL} }; diff --git a/libvips/iofuncs/image.c b/libvips/iofuncs/image.c index 6c84e91b..386415b1 100644 --- a/libvips/iofuncs/image.c +++ b/libvips/iofuncs/image.c @@ -80,6 +80,132 @@ * The first four bytes of a VIPS file in SPARC byte ordering. */ +/** + * 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. + * + * @VIPS_ACCESS_RANDOM means requests can come in any order. + * + * @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. + */ + +/** + * VipsDemandStyle: + * @VIPS_DEMAND_STYLE_SMALLTILE: demand in small (typically 64x64 pixel) tiles + * @VIPS_DEMAND_STYLE_FATSTRIP: demand in fat (typically 10 pixel high) strips + * @VIPS_DEMAND_STYLE_THINSTRIP: demand in thin (typically 1 pixel high) strips + * @VIPS_DEMAND_STYLE_ANY: demand geometry does not matter + * + * See vips_demand_hint(). Operations can hint to the VIPS image IO system about + * the kind of demand geometry they prefer. + * + * These demand styles are given below in order of increasing + * restrictiveness. When demanding output from a pipeline, + * vips_image_generate() + * will use the most restrictive of the styles requested by the operations + * in the pipeline. + * + * #VIPS_DEMAND_STYLE_THINSTRIP --- This operation would like to output strips + * the width of the image and a few pels high. This is option suitable for + * point-to-point operations, such as those in the arithmetic package. + * + * This option is only efficient for cases where each output pel depends + * upon the pel in the corresponding position in the input image. + * + * #VIPS_DEMAND_STYLE_FATSTRIP --- This operation would like to output strips + * the width of the image and as high as possible. This option is suitable + * for area operations which do not violently transform coordinates, such + * as im_conv(). + * + * #VIPS_DEMAND_STYLE_SMALLTILE --- This is the most general demand format. + * Output is demanded in small (around 100x100 pel) sections. This style works + * reasonably efficiently, even for bizzare operations like 45 degree rotate. + * + * #VIPS_DEMAND_STYLE_ANY --- This image is not being demand-read from a disc + * file (even indirectly) so any demand style is OK. It's used for things like + * im_black() where the pixels are calculated. + * + * See also: vips_demand_hint(). + */ + +/** + * VipsInterpretation: + * @VIPS_INTERPRETATION_MULTIBAND: generic many-band image + * @VIPS_INTERPRETATION_B_W: some kind of single-band image + * @VIPS_INTERPRETATION_HISTOGRAM: a 1D image, eg. histogram or lookup table + * @VIPS_INTERPRETATION_FOURIER: image is in fourier space + * @VIPS_INTERPRETATION_XYZ: the first three bands are CIE XYZ + * @VIPS_INTERPRETATION_LAB: pixels are in CIE Lab space + * @VIPS_INTERPRETATION_CMYK: the first four bands are in CMYK space + * @VIPS_INTERPRETATION_LABQ: implies #VIPS_CODING_LABQ + * @VIPS_INTERPRETATION_RGB: generic RGB space + * @VIPS_INTERPRETATION_CMC: a uniform colourspace based on CMC(1:1) + * @VIPS_INTERPRETATION_LCH: pixels are in CIE LCh space + * @VIPS_INTERPRETATION_LABS: CIE LAB coded as three signed 16-bit values + * @VIPS_INTERPRETATION_sRGB: pixels are sRGB + * @VIPS_INTERPRETATION_scRGB: pixels are scRGB + * @VIPS_INTERPRETATION_YXY: pixels are CIE Yxy + * @VIPS_INTERPRETATION_RGB16: generic 16-bit RGB + * @VIPS_INTERPRETATION_GREY16: generic 16-bit mono + * @VIPS_INTERPRETATION_MATRIX: a matrix + * + * How the values in an image should be interpreted. For example, a + * three-band float image of type #VIPS_INTERPRETATION_LAB should have its + * pixels interpreted as coordinates in CIE Lab space. + * + * These values are set by operations as hints to user-interfaces built on top + * of VIPS to help them show images to the user in a meaningful way. + * Operations do not use these values to decide their action. + * + * The gaps in the numbering are historical and must be maintained. Allocate + * new numbers from the end. + */ + +/** + * VipsBandFormat: + * @VIPS_FORMAT_NOTSET: invalid setting + * @VIPS_FORMAT_UCHAR: unsigned char format + * @VIPS_FORMAT_CHAR: char format + * @VIPS_FORMAT_USHORT: unsigned short format + * @VIPS_FORMAT_SHORT: short format + * @VIPS_FORMAT_UINT: unsigned int format + * @VIPS_FORMAT_INT: int format + * @VIPS_FORMAT_FLOAT: float format + * @VIPS_FORMAT_COMPLEX: complex (two floats) format + * @VIPS_FORMAT_DOUBLE: double float format + * @VIPS_FORMAT_DPCOMPLEX: double complex (two double) format + * + * The format used for each band element. + * + * Each corresponnds to a native C type for the current machine. For example, + * #VIPS_FORMAT_USHORT is unsigned short. + */ + +/** + * VipsCoding: + * @VIPS_CODING_NONE: pixels are not coded + * @VIPS_CODING_LABQ: pixels encode 3 float CIELAB values as 4 uchar + * @VIPS_CODING_RAD: pixels encode 3 float RGB as 4 uchar (Radiance coding) + * + * How pixels are coded. + * + * Normally, pixels are uncoded and can be manipulated as you would expect. + * However some file formats code pixels for compression, and sometimes it's + * useful to be able to manipulate images in the coded format. + * + * The gaps in the numbering are historical and must be maintained. Allocate + * new numbers from the end. + */ + /** * VipsProgress: * @run: Time we have been running diff --git a/libvips/iofuncs/object.c b/libvips/iofuncs/object.c index 722f57b7..88fdecbb 100644 --- a/libvips/iofuncs/object.c +++ b/libvips/iofuncs/object.c @@ -1519,6 +1519,7 @@ vips_object_set_argument_from_string( VipsObject *object, if( g_type_is_a( otype, VIPS_TYPE_IMAGE ) ) { VipsImage *out; VipsOperationFlags flags; + VipsAccess access; flags = 0; if( VIPS_IS_OPERATION( object ) ) @@ -1533,17 +1534,17 @@ vips_object_set_argument_from_string( VipsObject *object, /* Read the filename. vips_foreign_load_options() * handles embedded options. */ - if( flags & VIPS_OPERATION_SEQUENTIAL ) { - if( vips_foreign_load_options( value, &out, - "access", VIPS_FOREIGN_ACCESS_SEQUENTIAL, - NULL ) ) - return( -1 ); - } - else { - if( vips_foreign_load_options( value, &out, - NULL ) ) - return( -1 ); - } + if( flags & VIPS_OPERATION_SEQUENTIAL_UNBUFFERED ) + access = VIPS_ACCESS_SEQUENTIAL_UNBUFFERED; + else if( flags & VIPS_OPERATION_SEQUENTIAL ) + access = VIPS_ACCESS_SEQUENTIAL; + else + access = VIPS_ACCESS_RANDOM; + + if( vips_foreign_load_options( value, &out, + "access", access, + NULL ) ) + return( -1 ); g_value_init( &gvalue, VIPS_TYPE_IMAGE ); g_value_set_object( &gvalue, out ); diff --git a/libvips/iofuncs/operation.c b/libvips/iofuncs/operation.c index 837b7ad2..6deb4db0 100644 --- a/libvips/iofuncs/operation.c +++ b/libvips/iofuncs/operation.c @@ -65,6 +65,26 @@ * */ +/** + * VipsOperationFlags: + * @VIPS_OPERATION_NONE: no flags + * @VIPS_OPERATION_SEQUENTIAL: can work sequentially + * @VIPS_OPERATION_NOCACHE: must not be cached + * + * Flags we associate with an operation. + * + * @VIPS_OPERATION_SEQUENTIAL means that the operation works like vips_conv(): + * it can happily process images top-to-bottom with only small non-local + * references. + * + * @VIPS_OPERATION_SEQUENTIAL_UNBUFFERED means that the operation works like + * vips_copy(): it can happily process images top-to-bottom and makes no + * non-local references. + * + * @VIPS_OPERATION_NOCACHE means that the operation must not be cached by + * vips. + */ + /* Abstract base class for operations. */