From 12cf71a6a97d6f068e11b14b569e324b64b3b324 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Tue, 22 Oct 2013 09:29:40 +0100 Subject: [PATCH] combin copy_fields and demand_hint We had two API calls, vips_image_copy_fields() and vips_demand_hint(). They are now combined in the single vips_image_pipeline() call. All operations are now slightly smaller and simpler. --- ChangeLog | 2 + TODO | 15 ++--- libvips/arithmetic/arithmetic.c | 6 +- libvips/arithmetic/hist_find.c | 3 +- libvips/arithmetic/hist_find_indexed.c | 3 +- libvips/arithmetic/hist_find_ndim.c | 3 +- libvips/arithmetic/profile.c | 6 +- libvips/arithmetic/project.c | 6 +- libvips/colour/colour.c | 5 +- libvips/conversion/bandary.c | 5 +- libvips/conversion/cast.c | 5 +- libvips/conversion/copy.c | 5 +- libvips/conversion/embed.c | 8 +-- libvips/conversion/extract.c | 5 +- libvips/conversion/flatten.c | 5 +- libvips/conversion/flip.c | 5 +- libvips/conversion/grid.c | 7 +- libvips/conversion/ifthenelse.c | 5 +- libvips/conversion/insert.c | 5 +- libvips/conversion/msb.c | 5 +- libvips/conversion/recomb.c | 5 +- libvips/conversion/replicate.c | 5 +- libvips/conversion/rot.c | 11 ++-- libvips/conversion/rot45.c | 8 ++- libvips/conversion/sequential.c | 5 +- libvips/conversion/subsample.c | 14 ++-- libvips/conversion/tilecache.c | 10 ++- libvips/conversion/zoom.c | 7 +- libvips/create/black.c | 2 +- libvips/create/gaussmat.c | 2 +- libvips/create/gaussnoise.c | 2 +- libvips/create/identity.c | 2 +- libvips/create/logmat.c | 2 +- libvips/create/point.c | 2 +- libvips/create/text.c | 2 +- libvips/create/xyz.c | 2 +- libvips/deprecated/lazy.c | 2 +- libvips/deprecated/vips7compat.c | 36 ++++++++-- libvips/foreign/csv.c | 2 +- libvips/foreign/dzsave.c | 3 +- libvips/foreign/fits.c | 2 +- libvips/foreign/foreign.c | 4 +- libvips/foreign/jpeg2vips.c | 2 +- libvips/foreign/magick2vips.c | 2 +- libvips/foreign/openexr2vips.c | 4 +- libvips/foreign/openslide2vips.c | 4 +- libvips/foreign/tiff2vips.c | 4 +- libvips/foreign/vipspng.c | 2 +- libvips/foreign/webp2vips.c | 2 +- libvips/histogram/hist_local.c | 12 ++-- libvips/histogram/histogram.c | 5 +- libvips/histogram/maplut.c | 5 +- libvips/histogram/stdif.c | 12 ++-- libvips/include/vips/generate.h | 4 +- libvips/include/vips/header.h | 5 -- libvips/include/vips/private.h | 5 ++ libvips/include/vips/vips7compat.h | 12 ++-- libvips/iofuncs/generate.c | 89 +++++++++++++++++-------- libvips/iofuncs/header.c | 91 ++------------------------ libvips/iofuncs/image.c | 9 ++- libvips/iofuncs/sinkscreen.c | 8 +-- libvips/resample/affine.c | 19 +++--- libvips/resample/quadratic.c | 12 ++-- libvips/resample/shrink.c | 8 +-- 64 files changed, 256 insertions(+), 299 deletions(-) diff --git a/ChangeLog b/ChangeLog index 62edaf02..ba178acf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,8 @@ - vips_init() now does some ABI compat checking, though this change requires an ABI break - add "interlace" option to vips_jpegsave() +- remove vips_image_copy_fields() and vips_demand_hint() and add + vips_image_pipeline() to do both jobs 18/10/13 started 7.36.3 - fix compiler warnings in ubuntu 13.10 diff --git a/TODO b/TODO index 657cd48f..0f325b8b 100644 --- a/TODO +++ b/TODO @@ -1,11 +1,3 @@ -- get rid of vips_image_copy_fields(out, in) ... very confusing - - just have - - vips_image_copy_fieldsv( out, in1, in2, .. NULL ) - - makes arg order clearer - - do conv and morph quickly as simple wrappers over the vips7 operations - do much fancier profiling with timing on all locks saved in memory and @@ -24,6 +16,13 @@ combine the two into one call? + hist_find at least does not call demand_hint, same for all writeline output + operators I guess + + how about + + vips_image_pipelinev( out, hint, in1, ... ) + - object construction is threadsafe, but class construction is not https://github.com/jcupitt/libvips/issues/64 diff --git a/libvips/arithmetic/arithmetic.c b/libvips/arithmetic/arithmetic.c index 59fe05aa..c4fb82e5 100644 --- a/libvips/arithmetic/arithmetic.c +++ b/libvips/arithmetic/arithmetic.c @@ -545,11 +545,9 @@ vips_arithmetic_build( VipsObject *object ) */ arithmetic->ready = size; - if( vips_image_copy_fields_array( arithmetic->out, - arithmetic->ready ) ) + if( vips_image_pipeline_array( arithmetic->out, + VIPS_DEMAND_STYLE_THINSTRIP, arithmetic->ready ) ) return( -1 ); - vips_demand_hint_array( arithmetic->out, - VIPS_DEMAND_STYLE_THINSTRIP, arithmetic->ready ); arithmetic->out->Bands = arithmetic->ready[0]->Bands; arithmetic->out->BandFmt = diff --git a/libvips/arithmetic/hist_find.c b/libvips/arithmetic/hist_find.c index 175adcb5..5c98ee26 100644 --- a/libvips/arithmetic/hist_find.c +++ b/libvips/arithmetic/hist_find.c @@ -150,7 +150,8 @@ vips_hist_find_build( VipsObject *object ) /* Make the output image. */ - if( vips_image_copy_fields( hist_find->out, statistic->ready ) ) + if( vips_image_pipelinev( hist_find->out, + VIPS_DEMAND_STYLE_ANY, statistic->ready, NULL ) ) return( -1 ); vips_image_init_fields( hist_find->out, hist_find->hist->mx + 1, 1, hist_find->hist->bands, diff --git a/libvips/arithmetic/hist_find_indexed.c b/libvips/arithmetic/hist_find_indexed.c index 7ce56fea..e2632a42 100644 --- a/libvips/arithmetic/hist_find_indexed.c +++ b/libvips/arithmetic/hist_find_indexed.c @@ -163,7 +163,8 @@ vips_hist_find_indexed_build( VipsObject *object ) VIPS_UNREF( indexed->hist->reg ); - if( vips_image_copy_fieldsv( indexed->out, + if( vips_image_pipelinev( indexed->out, + VIPS_DEMAND_STYLE_ANY, statistic->ready, indexed->index_ready, NULL ) ) return( -1 ); vips_image_init_fields( indexed->out, diff --git a/libvips/arithmetic/hist_find_ndim.c b/libvips/arithmetic/hist_find_ndim.c index f170599d..85db4a98 100644 --- a/libvips/arithmetic/hist_find_ndim.c +++ b/libvips/arithmetic/hist_find_ndim.c @@ -154,7 +154,8 @@ vips_hist_find_ndim_build( VipsObject *object ) build( object ) ) return( -1 ); - if( vips_image_copy_fields( ndim->out, statistic->ready ) ) + if( vips_image_pipelinev( ndim->out, + VIPS_DEMAND_STYLE_ANY, statistic->ready, NULL ) ) return( -1 ); vips_image_init_fields( ndim->out, ndim->bins, diff --git a/libvips/arithmetic/profile.c b/libvips/arithmetic/profile.c index 11cc7f53..7777b60c 100644 --- a/libvips/arithmetic/profile.c +++ b/libvips/arithmetic/profile.c @@ -136,8 +136,10 @@ vips_profile_build( VipsObject *object ) /* Make the output image. */ - if( vips_image_copy_fields( profile->columns, statistic->ready ) || - vips_image_copy_fields( profile->rows, statistic->ready ) ) + if( vips_image_pipelinev( profile->columns, + VIPS_DEMAND_STYLE_ANY, statistic->ready, NULL ) || + vips_image_pipelinev( profile->rows, + VIPS_DEMAND_STYLE_ANY, statistic->ready, NULL ) ) return( -1 ); profile->columns->Ysize = 1; profile->columns->BandFmt = VIPS_FORMAT_INT; diff --git a/libvips/arithmetic/project.c b/libvips/arithmetic/project.c index c2159179..6b61686a 100644 --- a/libvips/arithmetic/project.c +++ b/libvips/arithmetic/project.c @@ -141,8 +141,10 @@ vips_project_build( VipsObject *object ) /* Make the output image. */ - if( vips_image_copy_fields( project->columns, statistic->ready ) || - vips_image_copy_fields( project->rows, statistic->ready ) ) + if( vips_image_pipelinev( project->columns, + VIPS_DEMAND_STYLE_ANY, statistic->ready, NULL ) || + vips_image_pipelinev( project->rows, + VIPS_DEMAND_STYLE_ANY, statistic->ready, NULL ) ) return( -1 ); project->columns->Ysize = 1; project->columns->BandFmt = diff --git a/libvips/colour/colour.c b/libvips/colour/colour.c index 3d31e2bb..eb70d8e1 100644 --- a/libvips/colour/colour.c +++ b/libvips/colour/colour.c @@ -320,10 +320,9 @@ vips_colour_build( VipsObject *object ) */ g_assert( !colour->in[colour->n] ); - if( vips_image_copy_fields_array( colour->out, colour->in ) ) + if( vips_image_pipeline_array( colour->out, + VIPS_DEMAND_STYLE_THINSTRIP, colour->in ) ) return( -1 ); - vips_demand_hint_array( colour->out, - VIPS_DEMAND_STYLE_THINSTRIP, colour->in ); colour->out->Coding = colour->coding; colour->out->Type = colour->interpretation; colour->out->BandFmt = colour->format; diff --git a/libvips/conversion/bandary.c b/libvips/conversion/bandary.c index 5e4e4f0b..99594aa0 100644 --- a/libvips/conversion/bandary.c +++ b/libvips/conversion/bandary.c @@ -147,10 +147,9 @@ vips_bandary_build( VipsObject *object ) return( -1 ); bandary->ready = size; - if( vips_image_copy_fields_array( conversion->out, bandary->ready ) ) + if( vips_image_pipeline_array( conversion->out, + VIPS_DEMAND_STYLE_THINSTRIP, bandary->ready ) ) return( -1 ); - vips_demand_hint_array( conversion->out, - VIPS_DEMAND_STYLE_THINSTRIP, bandary->ready ); conversion->out->Bands = bandary->out_bands; diff --git a/libvips/conversion/cast.c b/libvips/conversion/cast.c index 38df919a..be048d0c 100644 --- a/libvips/conversion/cast.c +++ b/libvips/conversion/cast.c @@ -441,10 +441,9 @@ vips_cast_build( VipsObject *object ) vips_image_pio_input( cast->in ) ) return( -1 ); - if( vips_image_copy_fields( conversion->out, cast->in ) ) + if( vips_image_pipelinev( conversion->out, + VIPS_DEMAND_STYLE_THINSTRIP, cast->in, NULL ) ) return( -1 ); - vips_demand_hint( conversion->out, - VIPS_DEMAND_STYLE_THINSTRIP, cast->in, NULL ); conversion->out->BandFmt = cast->format; diff --git a/libvips/conversion/copy.c b/libvips/conversion/copy.c index 2b3981a9..e2753a2b 100644 --- a/libvips/conversion/copy.c +++ b/libvips/conversion/copy.c @@ -250,10 +250,9 @@ vips_copy_build( VipsObject *object ) if( vips_image_pio_input( copy->in ) ) return( -1 ); - if( vips_image_copy_fields( conversion->out, copy->in ) ) + if( vips_image_pipelinev( conversion->out, + VIPS_DEMAND_STYLE_THINSTRIP, copy->in, NULL ) ) return( -1 ); - vips_demand_hint( conversion->out, - VIPS_DEMAND_STYLE_THINSTRIP, copy->in, NULL ); /* Use props to adjust header fields. */ diff --git a/libvips/conversion/embed.c b/libvips/conversion/embed.c index 8f33e248..46a2d557 100644 --- a/libvips/conversion/embed.c +++ b/libvips/conversion/embed.c @@ -426,14 +426,12 @@ vips_embed_build( VipsObject *object ) case VIPS_EXTEND_WHITE: case VIPS_EXTEND_BACKGROUND: case VIPS_EXTEND_COPY: - if( vips_image_copy_fields( conversion->out, embed->in ) ) - return( -1 ); - /* embed is used in many places. We don't really care about * geometry, so use ANY to avoid disturbing all pipelines. */ - vips_demand_hint( conversion->out, - VIPS_DEMAND_STYLE_ANY, embed->in, NULL ); + if( vips_image_pipelinev( conversion->out, + VIPS_DEMAND_STYLE_ANY, embed->in, NULL ) ) + return( -1 ); conversion->out->Xsize = embed->width; conversion->out->Ysize = embed->height; diff --git a/libvips/conversion/extract.c b/libvips/conversion/extract.c index 5f3a00bf..8f674170 100644 --- a/libvips/conversion/extract.c +++ b/libvips/conversion/extract.c @@ -155,10 +155,9 @@ vips_extract_area_build( VipsObject *object ) vips_check_coding_known( class->nickname, extract->in ) ) return( -1 ); - if( vips_image_copy_fields( conversion->out, extract->in ) ) + if( vips_image_pipelinev( conversion->out, + VIPS_DEMAND_STYLE_THINSTRIP, extract->in, NULL ) ) return( -1 ); - vips_demand_hint( conversion->out, - VIPS_DEMAND_STYLE_THINSTRIP, extract->in, NULL ); conversion->out->Xsize = extract->width; conversion->out->Ysize = extract->height; diff --git a/libvips/conversion/flatten.c b/libvips/conversion/flatten.c index 352e3734..889844a9 100644 --- a/libvips/conversion/flatten.c +++ b/libvips/conversion/flatten.c @@ -316,10 +316,9 @@ vips_flatten_build( VipsObject *object ) vips_image_pio_input( flatten->in ) ) return( -1 ); - if( vips_image_copy_fields( conversion->out, flatten->in ) ) + if( vips_image_pipelinev( conversion->out, + VIPS_DEMAND_STYLE_THINSTRIP, flatten->in, NULL ) ) return( -1 ); - vips_demand_hint( conversion->out, - VIPS_DEMAND_STYLE_THINSTRIP, flatten->in, NULL ); conversion->out->Bands -= 1; diff --git a/libvips/conversion/flip.c b/libvips/conversion/flip.c index 824e1f8f..ed70a3c6 100644 --- a/libvips/conversion/flip.c +++ b/libvips/conversion/flip.c @@ -198,10 +198,9 @@ vips_flip_build( VipsObject *object ) if( vips_image_pio_input( flip->in ) ) return( -1 ); - if( vips_image_copy_fields( conversion->out, flip->in ) ) + if( vips_image_pipelinev( conversion->out, + VIPS_DEMAND_STYLE_THINSTRIP, flip->in, NULL ) ) return( -1 ); - vips_demand_hint( conversion->out, - VIPS_DEMAND_STYLE_THINSTRIP, flip->in, NULL ); if( flip->direction == VIPS_DIRECTION_HORIZONTAL ) { generate_fn = vips_flip_horizontal_gen; diff --git a/libvips/conversion/grid.c b/libvips/conversion/grid.c index de5d45ef..be39dfd5 100644 --- a/libvips/conversion/grid.c +++ b/libvips/conversion/grid.c @@ -166,12 +166,11 @@ vips_grid_build( VipsObject *object ) return( -1 ); } - if( vips_image_copy_fields( conversion->out, grid->in ) ) - return( -1 ); /* We can render small tiles with pointer copies. */ - vips_demand_hint( conversion->out, - VIPS_DEMAND_STYLE_SMALLTILE, grid->in, NULL ); + if( vips_image_pipelinev( conversion->out, + VIPS_DEMAND_STYLE_SMALLTILE, grid->in, NULL ) ) + return( -1 ); conversion->out->Xsize = grid->in->Xsize * grid->across; conversion->out->Ysize = grid->tile_height * grid->down; diff --git a/libvips/conversion/ifthenelse.c b/libvips/conversion/ifthenelse.c index 450cfd3a..7c088e77 100644 --- a/libvips/conversion/ifthenelse.c +++ b/libvips/conversion/ifthenelse.c @@ -442,10 +442,9 @@ vips_ifthenelse_build( VipsObject *object ) if( vips__formatalike_vec( size, format, 2 ) ) return( -1 ); - if( vips_image_copy_fields_array( conversion->out, format ) ) + if( vips_image_pipeline_array( conversion->out, + VIPS_DEMAND_STYLE_SMALLTILE, format ) ) return( -1 ); - vips_demand_hint_array( conversion->out, - VIPS_DEMAND_STYLE_SMALLTILE, format ); if( vips_image_generate( conversion->out, vips_start_many, generate_fn, vips_stop_many, diff --git a/libvips/conversion/insert.c b/libvips/conversion/insert.c index 4b1fbbf9..f0c3a15a 100644 --- a/libvips/conversion/insert.c +++ b/libvips/conversion/insert.c @@ -284,10 +284,9 @@ vips_insert_build( VipsObject *object ) insert->main_processed, insert->sub_processed, NULL )) ) return( -1 ); - if( vips_image_copy_fields_array( conversion->out, arry ) ) + if( vips_image_pipeline_array( conversion->out, + VIPS_DEMAND_STYLE_ANY, arry ) ) return( -1 ); - vips_demand_hint_array( conversion->out, - VIPS_DEMAND_STYLE_ANY, arry ); /* Calculate geometry. */ diff --git a/libvips/conversion/msb.c b/libvips/conversion/msb.c index cefb366b..9a526e6f 100644 --- a/libvips/conversion/msb.c +++ b/libvips/conversion/msb.c @@ -201,10 +201,9 @@ vips_msb_build( VipsObject *object ) msb->in->BandFmt == VIPS_FORMAT_UCHAR ) return( vips_image_write( msb->in, conversion->out ) ); - if( vips_image_copy_fields( conversion->out, msb->in ) ) + if( vips_image_pipelinev( conversion->out, + VIPS_DEMAND_STYLE_THINSTRIP, msb->in, NULL ) ) return( -1 ); - vips_demand_hint( conversion->out, - VIPS_DEMAND_STYLE_THINSTRIP, msb->in, NULL ); if( msb->band != -1 ) conversion->out->Bands = 1; diff --git a/libvips/conversion/recomb.c b/libvips/conversion/recomb.c index 5339b080..38bc2867 100644 --- a/libvips/conversion/recomb.c +++ b/libvips/conversion/recomb.c @@ -164,10 +164,9 @@ vips_recomb_build( VipsObject *object ) return( -1 ); recomb->coeff = t[0]; - if( vips_image_copy_fields( conversion->out, recomb->in ) ) + if( vips_image_pipelinev( conversion->out, + VIPS_DEMAND_STYLE_THINSTRIP, recomb->in, NULL ) ) return( -1 ); - vips_demand_hint( conversion->out, - VIPS_DEMAND_STYLE_THINSTRIP, recomb->in, NULL ); conversion->out->Bands = recomb->m->Ysize; if( vips_bandfmt_isint( recomb->in->BandFmt ) ) diff --git a/libvips/conversion/replicate.c b/libvips/conversion/replicate.c index 8d0ec6ff..ee8e9d27 100644 --- a/libvips/conversion/replicate.c +++ b/libvips/conversion/replicate.c @@ -162,10 +162,9 @@ vips_replicate_build( VipsObject *object ) if( vips_image_pio_input( replicate->in ) ) return( -1 ); - if( vips_image_copy_fields( conversion->out, replicate->in ) ) + if( vips_image_pipelinev( conversion->out, + VIPS_DEMAND_STYLE_SMALLTILE, replicate->in, NULL ) ) return( -1 ); - vips_demand_hint( conversion->out, - VIPS_DEMAND_STYLE_SMALLTILE, replicate->in, NULL ); conversion->out->Xsize *= replicate->across; conversion->out->Ysize *= replicate->down; diff --git a/libvips/conversion/rot.c b/libvips/conversion/rot.c index 19de6b85..8c9c9e73 100644 --- a/libvips/conversion/rot.c +++ b/libvips/conversion/rot.c @@ -294,13 +294,16 @@ vips_rot_build( VipsObject *object ) if( vips_image_pio_input( rot->in ) ) return( -1 ); - if( vips_image_copy_fields( conversion->out, rot->in ) ) + hint = rot->angle == VIPS_ANGLE_180 ? + VIPS_DEMAND_STYLE_THINSTRIP : + VIPS_DEMAND_STYLE_SMALLTILE; + + if( vips_image_pipelinev( conversion->out, hint, rot->in, NULL ) ) return( -1 ); switch( rot->angle ) { case VIPS_ANGLE_90: generate_fn = vips_rot90_gen; - hint = VIPS_DEMAND_STYLE_SMALLTILE; conversion->out->Xsize = rot->in->Ysize; conversion->out->Ysize = rot->in->Xsize; conversion->out->Xoffset = rot->in->Ysize; @@ -309,14 +312,12 @@ vips_rot_build( VipsObject *object ) case VIPS_ANGLE_180: generate_fn = vips_rot180_gen; - hint = VIPS_DEMAND_STYLE_THINSTRIP; conversion->out->Xoffset = rot->in->Xsize; conversion->out->Yoffset = rot->in->Ysize; break; case VIPS_ANGLE_270: generate_fn = vips_rot270_gen; - hint = VIPS_DEMAND_STYLE_SMALLTILE; conversion->out->Xsize = rot->in->Ysize; conversion->out->Ysize = rot->in->Xsize; conversion->out->Xoffset = 0; @@ -331,8 +332,6 @@ vips_rot_build( VipsObject *object ) return( 0 ); } - vips_demand_hint( conversion->out, hint, rot->in, NULL ); - if( vips_image_generate( conversion->out, vips_start_one, generate_fn, vips_stop_one, rot->in, rot ) ) diff --git a/libvips/conversion/rot45.c b/libvips/conversion/rot45.c index 46514608..99712ab6 100644 --- a/libvips/conversion/rot45.c +++ b/libvips/conversion/rot45.c @@ -113,7 +113,7 @@ vips_rot45_rot45( VipsImage *out, VipsImage *in ) g_assert( in->Xsize == in->Ysize ); g_assert( out->Xsize == out->Ysize ); g_assert( in->Xsize == out->Xsize ); - g_assert( in->Xsize % 2 == 0 ); + g_assert( in->Xsize % 2 == 1 ); /* Split the square into 8 triangles. Loop over the top-left one, * reflect into the others. @@ -201,8 +201,10 @@ vips_rot45_build( VipsObject *object ) return( -1 ); t[0] = vips_image_new_buffer(); - if( vips_image_copy_fields( t[0], rot45->in ) || - vips_image_write_prepare( t[0] ) ) + if( vips_image_pipelinev( t[0], + VIPS_DEMAND_STYLE_ANY, rot45->in, NULL ) ) + return( -1 ); + if( vips_image_write_prepare( t[0] ) ) return( -1 ); from = rot45->in; diff --git a/libvips/conversion/sequential.c b/libvips/conversion/sequential.c index d5b473f5..f64c031e 100644 --- a/libvips/conversion/sequential.c +++ b/libvips/conversion/sequential.c @@ -273,10 +273,9 @@ vips_sequential_build( VipsObject *object ) vips_object_local( object, t ); - if( vips_image_copy_fields( conversion->out, t ) ) + if( vips_image_pipelinev( conversion->out, + VIPS_DEMAND_STYLE_THINSTRIP, t, NULL ) ) return( -1 ); - vips_demand_hint( conversion->out, - VIPS_DEMAND_STYLE_THINSTRIP, t, NULL ); if( vips_image_generate( conversion->out, vips_start_one, vips_sequential_generate, vips_stop_one, t, sequential ) ) diff --git a/libvips/conversion/subsample.c b/libvips/conversion/subsample.c index 45f58643..d4ace719 100644 --- a/libvips/conversion/subsample.c +++ b/libvips/conversion/subsample.c @@ -209,10 +209,14 @@ vips_subsample_build( VipsObject *object ) vips_check_coding_known( class->nickname, subsample->in ) ) return( -1 ); + /* Set demand hints. We want THINSTRIP, as we will be demanding a + * large area of input for each output line. + */ + if( vips_image_pipelinev( conversion->out, + VIPS_DEMAND_STYLE_THINSTRIP, subsample->in, NULL ) ) + return( -1 ); /* Prepare output. Note: we round the output width down! */ - if( vips_image_copy_fields( conversion->out, subsample->in ) ) - return( -1 ); conversion->out->Xsize = subsample->in->Xsize / subsample->xfac; conversion->out->Ysize = subsample->in->Ysize / subsample->yfac; conversion->out->Xres = subsample->in->Xres / subsample->xfac; @@ -224,12 +228,6 @@ vips_subsample_build( VipsObject *object ) return( -1 ); } - /* Set demand hints. We want THINSTRIP, as we will be demanding a - * large area of input for each output line. - */ - vips_demand_hint( conversion->out, - VIPS_DEMAND_STYLE_THINSTRIP, subsample->in, NULL ); - /* Generate! If this is a very large shrink, then it's * probably faster to do it a pixel at a time. */ diff --git a/libvips/conversion/tilecache.c b/libvips/conversion/tilecache.c index 52c63c2b..058d94dc 100644 --- a/libvips/conversion/tilecache.c +++ b/libvips/conversion/tilecache.c @@ -740,10 +740,9 @@ vips_tile_cache_build( VipsObject *object ) if( vips_image_pio_input( block_cache->in ) ) return( -1 ); - if( vips_image_copy_fields( conversion->out, block_cache->in ) ) + if( vips_image_pipelinev( conversion->out, + VIPS_DEMAND_STYLE_SMALLTILE, block_cache->in, NULL ) ) return( -1 ); - vips_demand_hint( conversion->out, - VIPS_DEMAND_STYLE_SMALLTILE, block_cache->in, NULL ); if( vips_image_generate( conversion->out, vips_start_one, vips_tile_cache_gen, vips_stop_one, @@ -926,10 +925,9 @@ vips_line_cache_build( VipsObject *object ) if( vips_image_pio_input( block_cache->in ) ) return( -1 ); - if( vips_image_copy_fields( conversion->out, block_cache->in ) ) + if( vips_image_pipelinev( conversion->out, + VIPS_DEMAND_STYLE_THINSTRIP, block_cache->in, NULL ) ) return( -1 ); - vips_demand_hint( conversion->out, - VIPS_DEMAND_STYLE_THINSTRIP, block_cache->in, NULL ); if( vips_image_generate( conversion->out, vips_start_one, vips_line_cache_gen, vips_stop_one, diff --git a/libvips/conversion/zoom.c b/libvips/conversion/zoom.c index 0e7553f5..c41d4e05 100644 --- a/libvips/conversion/zoom.c +++ b/libvips/conversion/zoom.c @@ -349,13 +349,12 @@ vips_zoom_build( VipsObject *object ) vips_check_coding_known( class->nickname, zoom->in ) ) return( -1 ); - if( vips_image_copy_fields( conversion->out, zoom->in ) ) - return( -1 ); /* Set demand hints. THINSTRIP will prevent us from using * vips_zoom_paint_whole() much ... so go for FATSTRIP. */ - vips_demand_hint( conversion->out, - VIPS_DEMAND_STYLE_FATSTRIP, zoom->in, NULL ); + if( vips_image_pipelinev( conversion->out, + VIPS_DEMAND_STYLE_FATSTRIP, zoom->in, NULL ) ) + return( -1 ); conversion->out->Xsize = zoom->in->Xsize * zoom->xfac; conversion->out->Ysize = zoom->in->Ysize * zoom->yfac; diff --git a/libvips/create/black.c b/libvips/create/black.c index 0081a2cf..9c4ad4a1 100644 --- a/libvips/create/black.c +++ b/libvips/create/black.c @@ -100,7 +100,7 @@ vips_black_build( VipsObject *object ) black->bands == 1 ? VIPS_INTERPRETATION_B_W : VIPS_INTERPRETATION_MULTIBAND, 1.0, 1.0 ); - vips_demand_hint( create->out, + vips_image_pipelinev( create->out, VIPS_DEMAND_STYLE_ANY, NULL ); if( vips_image_generate( create->out, diff --git a/libvips/create/gaussmat.c b/libvips/create/gaussmat.c index e7ec4705..e1f624cf 100644 --- a/libvips/create/gaussmat.c +++ b/libvips/create/gaussmat.c @@ -116,7 +116,7 @@ vips_gaussmat_build( VipsObject *object ) width, height, 1, VIPS_FORMAT_DOUBLE, VIPS_CODING_NONE, VIPS_INTERPRETATION_B_W, 1.0, 1.0 ); - vips_demand_hint( create->out, + vips_image_pipelinev( create->out, VIPS_DEMAND_STYLE_ANY, NULL ); if( vips_image_write_prepare( create->out ) ) return( -1 ); diff --git a/libvips/create/gaussnoise.c b/libvips/create/gaussnoise.c index 035063a9..ccbae21c 100644 --- a/libvips/create/gaussnoise.c +++ b/libvips/create/gaussnoise.c @@ -131,7 +131,7 @@ vips_gaussnoise_build( VipsObject *object ) gaussnoise->width, gaussnoise->height, 1, VIPS_FORMAT_FLOAT, VIPS_CODING_NONE, VIPS_INTERPRETATION_B_W, 1.0, 1.0 ); - vips_demand_hint( create->out, + vips_image_pipelinev( create->out, VIPS_DEMAND_STYLE_ANY, NULL ); if( vips_image_generate( create->out, diff --git a/libvips/create/identity.c b/libvips/create/identity.c index d30d72b5..d596bd12 100644 --- a/libvips/create/identity.c +++ b/libvips/create/identity.c @@ -116,7 +116,7 @@ vips_identity_build( VipsObject *object ) VIPS_CODING_NONE, VIPS_INTERPRETATION_HISTOGRAM, 1.0, 1.0 ); - vips_demand_hint( create->out, + vips_image_pipelinev( create->out, VIPS_DEMAND_STYLE_ANY, NULL ); if( vips_image_generate( create->out, diff --git a/libvips/create/logmat.c b/libvips/create/logmat.c index e5af0ee4..536599bb 100644 --- a/libvips/create/logmat.c +++ b/libvips/create/logmat.c @@ -138,7 +138,7 @@ vips_logmat_build( VipsObject *object ) width, height, 1, VIPS_FORMAT_DOUBLE, VIPS_CODING_NONE, VIPS_INTERPRETATION_B_W, 1.0, 1.0 ); - vips_demand_hint( create->out, + vips_image_pipelinev( create->out, VIPS_DEMAND_STYLE_ANY, NULL ); if( vips_image_write_prepare( create->out ) ) return( -1 ); diff --git a/libvips/create/point.c b/libvips/create/point.c index 0e03e515..b26c6cb4 100644 --- a/libvips/create/point.c +++ b/libvips/create/point.c @@ -103,7 +103,7 @@ vips_point_build( VipsObject *object ) point->width, point->height, 1, VIPS_FORMAT_FLOAT, VIPS_CODING_NONE, VIPS_INTERPRETATION_B_W, 1.0, 1.0 ); - vips_demand_hint( t[0], + vips_image_pipelinev( t[0], VIPS_DEMAND_STYLE_ANY, NULL ); if( vips_image_generate( t[0], NULL, vips_point_gen, NULL, point, NULL ) ) diff --git a/libvips/create/text.c b/libvips/create/text.c index 6677fdda..bb53fb91 100644 --- a/libvips/create/text.c +++ b/libvips/create/text.c @@ -233,7 +233,7 @@ vips_text_build( VipsObject *object ) text->bitmap.width, text->bitmap.rows, 1, VIPS_FORMAT_UCHAR, VIPS_CODING_NONE, VIPS_INTERPRETATION_B_W, 1.0, 1.0 ); - vips_demand_hint( create->out, + vips_image_pipelinev( create->out, VIPS_DEMAND_STYLE_ANY, NULL ); for( y = 0; y < text->bitmap.rows; y++ ) diff --git a/libvips/create/xyz.c b/libvips/create/xyz.c index b50fad65..d4a9940e 100644 --- a/libvips/create/xyz.c +++ b/libvips/create/xyz.c @@ -163,7 +163,7 @@ vips_xyz_build( VipsObject *object ) VIPS_FORMAT_UINT, VIPS_CODING_NONE, VIPS_INTERPRETATION_MULTIBAND, 1.0, 1.0 ); - vips_demand_hint( create->out, + vips_image_pipelinev( create->out, VIPS_DEMAND_STYLE_ANY, NULL ); if( vips_image_generate( create->out, diff --git a/libvips/deprecated/lazy.c b/libvips/deprecated/lazy.c index 0980d169..0985e527 100644 --- a/libvips/deprecated/lazy.c +++ b/libvips/deprecated/lazy.c @@ -221,7 +221,7 @@ vips_image_open_lazy( VipsImage *image, /* Then 'start' creates the real image and 'gen' paints 'image' * with pixels from the real image on demand. */ - vips_demand_hint( image, image->dhint, NULL ); + vips_image_pipelinev( image, image->dhint, NULL ); if( vips_image_generate( image, open_lazy_start, open_lazy_generate, vips_stop_one, lazy, NULL ) ) diff --git a/libvips/deprecated/vips7compat.c b/libvips/deprecated/vips7compat.c index 3c31ff14..4200847f 100644 --- a/libvips/deprecated/vips7compat.c +++ b/libvips/deprecated/vips7compat.c @@ -486,7 +486,7 @@ im_wrapmany( IMAGE **in, IMAGE *out, im_wrapmany_fn fn, void *a, void *b ) if( vips_image_pio_input( in[i] ) ) return( -1 ); } - vips_demand_hint_array( out, VIPS_DEMAND_STYLE_THINSTRIP, in ); + vips_image_pipeline_array( out, VIPS_DEMAND_STYLE_THINSTRIP, in ); /* Generate! */ @@ -959,7 +959,35 @@ im_demand_hint (IMAGE * im, VipsDemandStyle hint, ...) return (-1); } - return (im_demand_hint_array (im, hint, ar)); + vips__demand_hint_array (im, hint, ar); + + return (0); +} + +int +im_cp_descv (IMAGE * im, ...) +{ + va_list ap; + int i; + IMAGE *ar[MAX_IMAGES]; + + va_start (ap, im); + for (i = 0; i < MAX_IMAGES && (ar[i] = va_arg (ap, IMAGE *)); i++) + ; + va_end (ap); + if (i == MAX_IMAGES) + { + im_error ("im_cp_descv", "%s", _("too many images")); + return (-1); + } + + return (vips__image_copy_fields_array (im, ar)); +} + +int +im_cp_desc(IMAGE *out, IMAGE *in ) +{ + return( im_cp_descv( out, in, NULL)); } int @@ -1925,7 +1953,7 @@ im_gauss_dmask_sep( const char *filename, double sigma, double min_ampl ) DOUBLEMASK *msk; if( vips_gaussmat( &t, sigma, min_ampl, - "seperable", TRUE, + "separable", TRUE, NULL ) ) return( NULL ); if( !(msk = im_vips2mask( t, filename )) ) { @@ -1964,7 +1992,7 @@ im_gauss_imask_sep( const char *filename, double sigma, double min_ampl ) if( vips_gaussmat( &t, sigma, min_ampl, "integer", TRUE, - "seperable", TRUE, + "separable", TRUE, NULL ) ) return( NULL ); if( !(msk = im_vips2imask( t, filename )) ) { diff --git a/libvips/foreign/csv.c b/libvips/foreign/csv.c index 78689740..eed5d08c 100644 --- a/libvips/foreign/csv.c +++ b/libvips/foreign/csv.c @@ -280,11 +280,11 @@ read_csv( FILE *fp, VipsImage *out, fsetpos( fp, &pos ); } + vips_image_pipelinev( out, VIPS_DEMAND_STYLE_THINSTRIP, NULL ); vips_image_init_fields( out, columns, lines, 1, VIPS_FORMAT_DOUBLE, VIPS_CODING_NONE, VIPS_INTERPRETATION_B_W, 1.0, 1.0 ); - vips_demand_hint( out, VIPS_DEMAND_STYLE_THINSTRIP, NULL ); /* Just reading the header? We are done. */ diff --git a/libvips/foreign/dzsave.c b/libvips/foreign/dzsave.c index f070527c..877846c8 100644 --- a/libvips/foreign/dzsave.c +++ b/libvips/foreign/dzsave.c @@ -263,7 +263,8 @@ pyramid_build( VipsForeignSaveDz *dz, Layer *above, * easy. */ layer->image = vips_image_new(); - if( vips_image_copy_fields( layer->image, save->ready ) ) { + if( vips_image_pipelinev( layer->image, + VIPS_DEMAND_STYLE_ANY, save->ready, NULL ) ) { layer_free( layer ); return( NULL ); } diff --git a/libvips/foreign/fits.c b/libvips/foreign/fits.c index db0ebdef..ac0e4a9c 100644 --- a/libvips/foreign/fits.c +++ b/libvips/foreign/fits.c @@ -296,11 +296,11 @@ vips_fits_get_header( VipsFits *fits, VipsImage *out ) else type = VIPS_INTERPRETATION_MULTIBAND; + vips_image_pipelinev( out, VIPS_DEMAND_STYLE_SMALLTILE, NULL ); vips_image_init_fields( out, width, height, bands, format, VIPS_CODING_NONE, type, 1.0, 1.0 ); - vips_demand_hint( out, VIPS_DEMAND_STYLE_SMALLTILE, NULL ); /* Read all keys into meta. */ diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index b539aa25..e9bb5048 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -776,7 +776,7 @@ vips_foreign_load_start( VipsImage *out, void *a, void *b ) /* We have to tell vips that out depends on real. We've set * the demand hint below, but not given an input there. */ - vips_demand_hint( load->out, load->out->dhint, + vips_image_pipelinev( load->out, load->out->dhint, load->real, NULL ); } @@ -874,7 +874,7 @@ vips_foreign_load_build( VipsObject *object ) /* ->header() should set the dhint. It'll default to the safe * SMALLTILE if header() did not set it. */ - vips_demand_hint( load->out, load->out->dhint, NULL ); + vips_image_pipelinev( load->out, load->out->dhint, NULL ); /* Then 'start' creates the real image and 'gen' fetches * pixels for @out from @real on demand. diff --git a/libvips/foreign/jpeg2vips.c b/libvips/foreign/jpeg2vips.c index 90ef0c5f..a7e2a234 100644 --- a/libvips/foreign/jpeg2vips.c +++ b/libvips/foreign/jpeg2vips.c @@ -764,7 +764,7 @@ read_jpeg_header( ReadJpeg *jpeg, VipsImage *out ) interpretation, xres, yres ); - vips_demand_hint( out, VIPS_DEMAND_STYLE_THINSTRIP, NULL ); + vips_image_pipelinev( out, VIPS_DEMAND_STYLE_THINSTRIP, NULL ); /* Interlaced jpegs need lots of memory to read, so our caller needs * to know. diff --git a/libvips/foreign/magick2vips.c b/libvips/foreign/magick2vips.c index 75e0e27a..f64d35f8 100644 --- a/libvips/foreign/magick2vips.c +++ b/libvips/foreign/magick2vips.c @@ -337,7 +337,7 @@ parse_header( Read *read ) */ im->Coding = VIPS_CODING_NONE; - vips_demand_hint( im, VIPS_DEMAND_STYLE_SMALLTILE, NULL ); + vips_image_pipelinev( im, VIPS_DEMAND_STYLE_SMALLTILE, NULL ); /* Three ways to loop over attributes / properties :-( */ diff --git a/libvips/foreign/openexr2vips.c b/libvips/foreign/openexr2vips.c index bef7f1e3..c6a13f53 100644 --- a/libvips/foreign/openexr2vips.c +++ b/libvips/foreign/openexr2vips.c @@ -212,9 +212,9 @@ read_header( Read *read, VipsImage *out ) VIPS_FORMAT_FLOAT, VIPS_CODING_NONE, VIPS_INTERPRETATION_sRGB, 1.0, 1.0 ); if( read->tiles ) - vips_demand_hint( out, VIPS_DEMAND_STYLE_SMALLTILE, NULL ); + vips_image_pipelinev( out, VIPS_DEMAND_STYLE_SMALLTILE, NULL ); else - vips_demand_hint( out, VIPS_DEMAND_STYLE_FATSTRIP, NULL ); + vips_image_pipelinev( out, VIPS_DEMAND_STYLE_FATSTRIP, NULL ); } int diff --git a/libvips/foreign/openslide2vips.c b/libvips/foreign/openslide2vips.c index a2a7760b..59ccd931 100644 --- a/libvips/foreign/openslide2vips.c +++ b/libvips/foreign/openslide2vips.c @@ -220,7 +220,7 @@ readslide_new( const char *filename, VipsImage *out, associated, &w, &h ); vips_image_set_string( out, "slide-associated-image", associated ); - vips_demand_hint( out, VIPS_DEMAND_STYLE_THINSTRIP, NULL ); + vips_image_pipelinev( out, VIPS_DEMAND_STYLE_THINSTRIP, NULL ); } else { char buf[256]; @@ -231,7 +231,7 @@ readslide_new( const char *filename, VipsImage *out, rslide->downsample = openslide_get_level_downsample( rslide->osr, level ); vips_image_set_int( out, "slide-level", level ); - vips_demand_hint( out, VIPS_DEMAND_STYLE_SMALLTILE, NULL ); + vips_image_pipelinev( out, VIPS_DEMAND_STYLE_SMALLTILE, NULL ); /* Try to get tile width/height. An undocumented, experimental * feature. diff --git a/libvips/foreign/tiff2vips.c b/libvips/foreign/tiff2vips.c index 8367fc25..bd139538 100644 --- a/libvips/foreign/tiff2vips.c +++ b/libvips/foreign/tiff2vips.c @@ -1236,7 +1236,7 @@ read_tilewise( ReadTiff *rtiff, VipsImage *out ) * the cache we are quite happy serving that if anything downstream * would like it. */ - vips_demand_hint( raw, VIPS_DEMAND_STYLE_THINSTRIP, NULL ); + vips_image_pipelinev( raw, VIPS_DEMAND_STYLE_THINSTRIP, NULL ); if( vips_image_generate( raw, tiff_seq_start, tiff_fill_region, tiff_seq_stop, @@ -1413,7 +1413,7 @@ read_stripwise( ReadTiff *rtiff, VipsImage *out ) if( parse_header( rtiff, t[0] ) ) return( -1 ); - vips_demand_hint( t[0], VIPS_DEMAND_STYLE_THINSTRIP, NULL ); + vips_image_pipelinev( t[0], VIPS_DEMAND_STYLE_THINSTRIP, NULL ); if( !tfget32( rtiff->tiff, TIFFTAG_ROWSPERSTRIP, &rtiff->rows_per_strip ) ) diff --git a/libvips/foreign/vipspng.c b/libvips/foreign/vipspng.c index 02a87e38..5062741a 100644 --- a/libvips/foreign/vipspng.c +++ b/libvips/foreign/vipspng.c @@ -351,7 +351,7 @@ png2vips_header( Read *read, VipsImage *out ) /* Sequential mode needs thinstrip to work with things like * vips_shrink(). */ - vips_demand_hint( out, VIPS_DEMAND_STYLE_THINSTRIP, NULL ); + vips_image_pipelinev( out, VIPS_DEMAND_STYLE_THINSTRIP, NULL ); /* Fetch the ICC profile. @name is useless, something like "icc" or * "ICC Profile" etc. Ignore it. diff --git a/libvips/foreign/webp2vips.c b/libvips/foreign/webp2vips.c index 4996e5c2..031ebad5 100644 --- a/libvips/foreign/webp2vips.c +++ b/libvips/foreign/webp2vips.c @@ -153,7 +153,7 @@ read_header( Read *read, VipsImage *out ) VIPS_INTERPRETATION_sRGB, 1.0, 1.0 ); - vips_demand_hint( out, VIPS_DEMAND_STYLE_THINSTRIP, NULL ); + vips_image_pipelinev( out, VIPS_DEMAND_STYLE_THINSTRIP, NULL ); return( 0 ); } diff --git a/libvips/histogram/hist_local.c b/libvips/histogram/hist_local.c index 70456091..41365738 100644 --- a/libvips/histogram/hist_local.c +++ b/libvips/histogram/hist_local.c @@ -256,16 +256,14 @@ vips_hist_local_build( VipsObject *object ) g_object_set( object, "out", vips_image_new(), NULL ); - if( vips_image_copy_fields( local->out, in ) ) - return( -1 ); - local->out->Xsize -= local->width - 1; - local->out->Ysize -= local->height - 1; - /* Set demand hints. FATSTRIP is good for us, as THINSTRIP will cause * too many recalculations on overlaps. */ - vips_demand_hint( local->out, - VIPS_DEMAND_STYLE_FATSTRIP, in, NULL ); + if( vips_image_pipelinev( local->out, + VIPS_DEMAND_STYLE_FATSTRIP, in, NULL ) ) + return( -1 ); + local->out->Xsize -= local->width - 1; + local->out->Ysize -= local->height - 1; if( vips_image_generate( local->out, vips_hist_local_start, diff --git a/libvips/histogram/histogram.c b/libvips/histogram/histogram.c index a2c024ef..48c1c6b3 100644 --- a/libvips/histogram/histogram.c +++ b/libvips/histogram/histogram.c @@ -157,10 +157,9 @@ vips_histogram_build( VipsObject *object ) */ histogram->ready = size; - if( vips_image_copy_fields_array( histogram->out, histogram->ready ) ) + if( vips_image_pipeline_array( histogram->out, + VIPS_DEMAND_STYLE_THINSTRIP, histogram->ready ) ) return( -1 ); - vips_demand_hint_array( histogram->out, - VIPS_DEMAND_STYLE_THINSTRIP, histogram->ready ); histogram->out->Xsize = VIPS_IMAGE_N_PELS( histogram->ready[0] ); histogram->out->Ysize = 1; diff --git a/libvips/histogram/maplut.c b/libvips/histogram/maplut.c index d6df93fb..f3366c9e 100644 --- a/libvips/histogram/maplut.c +++ b/libvips/histogram/maplut.c @@ -564,10 +564,9 @@ vips_maplut_build( VipsObject *object ) vips_image_pio_input( in ) ) return( -1 ); - if( vips_image_copy_fieldsv( maplut->out, in, lut, NULL ) ) + if( vips_image_pipelinev( maplut->out, + VIPS_DEMAND_STYLE_THINSTRIP, in, lut, NULL ) ) return( -1 ); - vips_demand_hint( maplut->out, VIPS_DEMAND_STYLE_THINSTRIP, - in, lut, NULL ); maplut->out->BandFmt = lut->BandFmt; /* Output has same number of bands as LUT, unless LUT has 1 band, in diff --git a/libvips/histogram/stdif.c b/libvips/histogram/stdif.c index b64052c8..59e0fe95 100644 --- a/libvips/histogram/stdif.c +++ b/libvips/histogram/stdif.c @@ -249,16 +249,14 @@ vips_stdif_build( VipsObject *object ) g_object_set( object, "out", vips_image_new(), NULL ); - if( vips_image_copy_fields( stdif->out, in ) ) - return( -1 ); - stdif->out->Xsize -= stdif->width - 1; - stdif->out->Ysize -= stdif->height - 1; - /* Set demand hints. FATSTRIP is good for us, as THINSTRIP will cause * too many recalculations on overlaps. */ - vips_demand_hint( stdif->out, - VIPS_DEMAND_STYLE_FATSTRIP, in, NULL ); + if( vips_image_pipelinev( stdif->out, + VIPS_DEMAND_STYLE_FATSTRIP, in, NULL ) ) + return( -1 ); + stdif->out->Xsize -= stdif->width - 1; + stdif->out->Ysize -= stdif->height - 1; if( vips_image_generate( stdif->out, vips_start_one, diff --git a/libvips/include/vips/generate.h b/libvips/include/vips/generate.h index 4e26d833..f7af6884 100644 --- a/libvips/include/vips/generate.h +++ b/libvips/include/vips/generate.h @@ -73,9 +73,9 @@ int vips_image_generate( VipsImage *im, void *a, void *b ); -void vips_demand_hint_array( VipsImage *image, +int vips_image_pipeline_array( VipsImage *image, VipsDemandStyle hint, VipsImage **in ); -void vips_demand_hint( VipsImage *image, VipsDemandStyle hint, ... ) +int vips_image_pipelinev( VipsImage *image, VipsDemandStyle hint, ... ) __attribute__((sentinel)); #ifdef __cplusplus diff --git a/libvips/include/vips/header.h b/libvips/include/vips/header.h index 95da4126..f27f205d 100644 --- a/libvips/include/vips/header.h +++ b/libvips/include/vips/header.h @@ -118,11 +118,6 @@ void vips_image_init_fields( VipsImage *image, VipsInterpretation interpretation, double xres, double yres ); -int vips_image_copy_fields_array( VipsImage *out, VipsImage *in[] ); -int vips_image_copy_fieldsv( VipsImage *out, VipsImage *in1, ... ) - __attribute__((sentinel)); -int vips_image_copy_fields( VipsImage *out, VipsImage *in ); - void vips_image_set( VipsImage *image, const char *field, GValue *value ); int vips_image_get( const VipsImage *image, const char *field, GValue *value_copy ); diff --git a/libvips/include/vips/private.h b/libvips/include/vips/private.h index 123dda67..7b270002 100644 --- a/libvips/include/vips/private.h +++ b/libvips/include/vips/private.h @@ -170,6 +170,11 @@ VipsArgumentInstance *vips__argument_get_instance( VipsArgument *vips__argument_table_lookup( VipsArgumentTable *table, GParamSpec *pspec); +void vips__demand_hint_array( struct _VipsImage *image, + int hint, struct _VipsImage **in ); +int vips__image_copy_fields_array( struct _VipsImage *out, + struct _VipsImage *in[] ); + #ifdef __cplusplus } #endif /*__cplusplus*/ diff --git a/libvips/include/vips/vips7compat.h b/libvips/include/vips/vips7compat.h index 04a0e151..7324c653 100644 --- a/libvips/include/vips/vips7compat.h +++ b/libvips/include/vips/vips7compat.h @@ -208,9 +208,12 @@ extern "C" { #define im_guess_libdir vips_guess_libdir #define im__global_lock vips__global_lock -#define im_cp_desc vips_image_copy_fields -#define im_cp_descv vips_image_copy_fieldsv -#define im_cp_desc_array vips_image_copy_fields_array +int im_cp_desc(IMAGE *out, IMAGE *in ); +int im_cp_descv (IMAGE * im, ...); +#define im_cp_desc_array(I, A) vips__image_copy_fields_array(I, A) +int im_demand_hint (IMAGE * im, VipsDemandStyle hint, ...); +#define im_demand_hint_array( A, B, C ) (vips__demand_hint_array( A, B, C ), 0) + #define im_image vips_image_new_from_memory #define im_binfile vips_image_new_from_file_raw #define im__open_temp vips_image_new_temp_file @@ -324,9 +327,6 @@ VipsDemandStyle im_char2dhint( const char *str ); #define im_rect_dup vips_rect_dup #define im_rect_normalise vips_rect_normalise -int im_demand_hint (IMAGE * im, VipsDemandStyle hint, ...); -#define im_demand_hint_array( A, B, C ) (vips_demand_hint_array( A, B, C ), 0) - #define im_start_one vips_start_one #define im_stop_one vips_stop_one #define im_start_many vips_start_many diff --git a/libvips/iofuncs/generate.c b/libvips/iofuncs/generate.c index 174671fe..f23dccc1 100644 --- a/libvips/iofuncs/generate.c +++ b/libvips/iofuncs/generate.c @@ -274,26 +274,12 @@ vips__link_map( VipsImage *image, gboolean upstream, return( result ); } -/** - * vips_demand_hint_array: - * @image: image to set hint for - * @hint: hint for this image - * @in: array of input images to this operation - * - * Operations can set demand hints, that is, hints to the VIPS IO system about - * the type of region geometry this operation works best with. For example, - * operations which transform coordinates will usually work best with - * %VIPS_DEMAND_STYLE_SMALLTILE, operations which work on local windows of - * pixels will like %VIPS_DEMAND_STYLE_FATSTRIP. - * - * VIPS uses the list of input images to build the tree of operations it needs - * for the cache invalidation system. You have to call this function, or its - * varargs friend vips_demand_hint(). - * - * See also: vips_demand_hint(), vips_image_generate(). +/* We have to have this as a separate entry point so we can support the old + * vips7 API. */ void -vips_demand_hint_array( VipsImage *image, VipsDemandStyle hint, VipsImage **in ) +vips__demand_hint_array( VipsImage *image, + VipsDemandStyle hint, VipsImage **in ) { int i, len, nany; VipsDemandStyle set_hint; @@ -327,7 +313,7 @@ vips_demand_hint_array( VipsImage *image, VipsDemandStyle hint, VipsImage **in ) image->dhint = set_hint; #ifdef DEBUG - printf( "vips_demand_hint_array: set dhint for \"%s\" to %s\n", + printf( "vips_image_pipeline_array: set dhint for \"%s\" to %s\n", image->filename, vips_enum_nick( VIPS_TYPE_DEMAND_STYLE, image->dhint ) ); printf( "\toperation requested %s\n", @@ -354,17 +340,62 @@ vips_demand_hint_array( VipsImage *image, VipsDemandStyle hint, VipsImage **in ) } /** - * vips_demand_hint: - * @image: image to set hint for - * @hint: hint for this image - * @Varargs: %NULL-terminated list of input images to this operation + * vips_image_pipeline_array: + * @image: output image + * @hint: demand hint for @image + * @in: %NULL-terminated array of input images * - * Build an array and call vips_demand_hint_array(). + * Add an image to a pipeline. @image depends on all of the images in @in, + * @image prefers to supply pixels according to @hint. * - * See also: vips_demand_hint(), vips_image_generate(). + * Operations can set demand hints, that is, hints to the VIPS IO system about + * the type of region geometry this operation works best with. For example, + * operations which transform coordinates will usually work best with + * %VIPS_DEMAND_STYLE_SMALLTILE, operations which work on local windows of + * pixels will like %VIPS_DEMAND_STYLE_FATSTRIP. + * + * Header fields in @image are set from the fields in @in, with lower-numbered + * images in @in taking priority. + * For example, if @in[0] and @in[1] both have an item + * called "icc-profile", it's the profile attached to @in[0] that will end up + * on @image. + * Image history is completely copied from all @in. @image will have the history + * of all the input images. + * The array of input images can be empty, meaning @image is at the start of a + * pipeline. + * + * VIPS uses the list of input images to build the tree of operations it needs + * for the cache invalidation system. + * + * See also: vips_image_pipelinev(), vips_image_generate(). + * + * Returns: 0 on success, -1 on error. */ -void -vips_demand_hint( VipsImage *image, VipsDemandStyle hint, ... ) +int +vips_image_pipeline_array( VipsImage *image, + VipsDemandStyle hint, VipsImage **in ) +{ + vips__demand_hint_array( image, hint, in ); + + if( in[0] && + vips__image_copy_fields_array( image, in ) ) + return( -1 ); + + return( 0 ); +} + +/** + * vips_image_pipelinev: + * @image: output image of pipeline + * @hint: hint for this image + * @...: %NULL-terminated list of input images + * + * Build an array and call vips_image_pipeline_array(). + * + * See also: vips_image_generate(). + */ +int +vips_image_pipelinev( VipsImage *image, VipsDemandStyle hint, ... ) { va_list ap; int i; @@ -376,14 +407,14 @@ vips_demand_hint( VipsImage *image, VipsDemandStyle hint, ... ) ; va_end( ap ); if( i == MAX_IMAGES ) { - vips_warn( "vips_demand_hint", "%s", _( "too many images" ) ); + vips_warn( "vips_image_pipeline", "%s", _( "too many images" ) ); /* Make sure we have a sentinel there. */ ar[i - 1] = NULL; } - vips_demand_hint_array( image, hint, ar ); + return( vips_image_pipeline_array( image, hint, ar ) ); } /** diff --git a/libvips/iofuncs/header.c b/libvips/iofuncs/header.c index f430bd53..d3ebbb4c 100644 --- a/libvips/iofuncs/header.c +++ b/libvips/iofuncs/header.c @@ -604,13 +604,13 @@ vips_image_get_data( VipsImage *image ) * @yres: vertical resolution, pixels per millimetre * * A convenience function to set the header fields after creating an image. - * Normally you copy the fields from one of your input images with - * vips_image_copy_fields() and then make + * Normally you copy the fields from your input images with + * vips_image_pipelinev() and then make * any adjustments you need, but if you are creating an image from scratch, * for example im_black() or im_jpeg2vips(), you do need to set all the * fields yourself. * - * See also: vips_image_copy_fields(). + * See also: vips_image_pipelinev(). */ void vips_image_init_fields( VipsImage *image, @@ -655,7 +655,7 @@ meta_cp_field( VipsMeta *meta, VipsImage *dst ) return( NULL ); } -/* Copy meta on to dst. Called from vips_cp_desc(). +/* Copy meta on to dst. */ static int meta_cp( VipsImage *dst, const VipsImage *src ) @@ -671,31 +671,11 @@ meta_cp( VipsImage *dst, const VipsImage *src ) return( 0 ); } -/** - * vips_image_copy_fields_array: - * @out: image to copy to - * @in: %NULL-terminated array of images to copy from - * - * Copy fields from all the input images to the output image. There must be at - * least one input image. - * - * The first input image is used to set the main fields of @out (@width, - * @coding and so on). - * - * Metadata from all the images is merged on to @out, with lower-numbered items - * overriding higher. So for example, if @in[0] and @in[1] both have an item - * called "icc-profile", it's the profile attached to @in[0] that will end up - * on @out. - * - * Image history is completely copied from all @in. @out will have the history - * of all the input images. - * - * See also: vips_image_copy_fieldsv(), vips_image_copy_fields(). - * - * Returns: 0 on success, -1 on error. +/* We have to have this as a separate entry point so we can support the old + * vips7 API. */ int -vips_image_copy_fields_array( VipsImage *out, VipsImage *in[] ) +vips__image_copy_fields_array( VipsImage *out, VipsImage *in[] ) { int i; int ni; @@ -740,63 +720,6 @@ vips_image_copy_fields_array( VipsImage *out, VipsImage *in[] ) return( 0 ); } -/* Max number of images we can handle. - */ -#define MAX_IMAGES (1000) - -/** - * vips_image_copy_fieldsv: - * @out: image to copy to - * @in1: first image to copy from - * @Varargs: %NULL-terminated list of images to copy from - * - * Copy fields from all the input images to the output image. A convenience - * function over vips_image_copy_fields_array(). - * - * See also: vips_image_copy_fields_array(), vips_image_copy_fields(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_image_copy_fieldsv( VipsImage *out, VipsImage *in1, ... ) -{ - va_list ap; - int i; - VipsImage *in[MAX_IMAGES]; - - in[0] = in1; - va_start( ap, in1 ); - for( i = 1; i < MAX_IMAGES && - (in[i] = va_arg( ap, VipsImage * )); i++ ) - ; - va_end( ap ); - if( i == MAX_IMAGES ) { - vips_error( "vips_image_copy_fieldsv", - "%s", _( "too many images" ) ); - return( -1 ); - } - - return( vips_image_copy_fields_array( out, in ) ); -} - -/** - * vips_image_copy_fields: - * @out: image to copy to - * @in: image to copy from - * - * Copy fields from @in to @out. A convenience - * function over vips_image_copy_fields_array(). - * - * See also: vips_image_copy_fields_array(), vips_image_copy_fieldsv(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_image_copy_fields( VipsImage *out, VipsImage *in ) -{ - return( vips_image_copy_fieldsv( out, in, NULL ) ); -} - /** * vips_image_set: * @image: image to set the metadata on diff --git a/libvips/iofuncs/image.c b/libvips/iofuncs/image.c index 4775d554..22ac7927 100644 --- a/libvips/iofuncs/image.c +++ b/libvips/iofuncs/image.c @@ -105,7 +105,7 @@ * @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 + * See vips_image_pipelinev(). 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 @@ -134,7 +134,7 @@ * 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(). + * See also: vips_image_pipelinev(). */ /** @@ -1939,10 +1939,9 @@ int vips_image_write( VipsImage *image, VipsImage *out ) { if( vips_image_pio_input( image ) || - vips_image_copy_fields( out, image ) ) + vips_image_pipelinev( out, + VIPS_DEMAND_STYLE_THINSTRIP, image, NULL ) ) return( -1 ); - vips_demand_hint( out, - VIPS_DEMAND_STYLE_THINSTRIP, image, NULL ); /* We generate from @image partially, so we need to keep it about as * long as @out is about. diff --git a/libvips/iofuncs/sinkscreen.c b/libvips/iofuncs/sinkscreen.c index 4e91f9ef..358fbadd 100644 --- a/libvips/iofuncs/sinkscreen.c +++ b/libvips/iofuncs/sinkscreen.c @@ -1067,14 +1067,14 @@ vips_sink_screen( VipsImage *in, VipsImage *out, VipsImage *mask, } if( vips_image_pio_input( in ) || - vips_image_copy_fields( out, in ) ) + vips_image_pipelinev( out, + VIPS_DEMAND_STYLE_SMALLTILE, in, NULL ) ) return( -1 ); - vips_demand_hint( out, VIPS_DEMAND_STYLE_SMALLTILE, in, NULL ); if( mask ) { - if( vips_image_copy_fields( mask, in ) ) + if( vips_image_pipelinev( mask, + VIPS_DEMAND_STYLE_SMALLTILE, in, NULL ) ) return( -1 ); - vips_demand_hint( mask, VIPS_DEMAND_STYLE_SMALLTILE, in, NULL ); mask->Bands = 1; mask->BandFmt = VIPS_FORMAT_UCHAR; diff --git a/libvips/resample/affine.c b/libvips/resample/affine.c index 76789ba6..6d07d1d2 100644 --- a/libvips/resample/affine.c +++ b/libvips/resample/affine.c @@ -381,6 +381,7 @@ vips_affine_build( VipsObject *object ) VipsImage *in; gboolean repack; + VipsDemandStyle hint; int window_size; int window_offset; double edge; @@ -479,21 +480,19 @@ vips_affine_build( VipsObject *object ) return( -1 ); in = t[1]; - if( vips_image_copy_fields( resample->out, in ) ) - return( -1 ); - - resample->out->Xsize = affine->trn.oarea.width; - resample->out->Ysize = affine->trn.oarea.height; - /* Normally SMALLTILE ... except if this is a size up/down affine. */ if( affine->trn.b == 0.0 && affine->trn.c == 0.0 ) - vips_demand_hint( resample->out, - VIPS_DEMAND_STYLE_FATSTRIP, in, NULL ); + hint = VIPS_DEMAND_STYLE_FATSTRIP; else - vips_demand_hint( resample->out, - VIPS_DEMAND_STYLE_SMALLTILE, in, NULL ); + hint = VIPS_DEMAND_STYLE_SMALLTILE; + + if( vips_image_pipelinev( resample->out, hint, in, NULL ) ) + return( -1 ); + + resample->out->Xsize = affine->trn.oarea.width; + resample->out->Ysize = affine->trn.oarea.height; /* Generate! */ diff --git a/libvips/resample/quadratic.c b/libvips/resample/quadratic.c index 5ab0158b..5fedd545 100644 --- a/libvips/resample/quadratic.c +++ b/libvips/resample/quadratic.c @@ -251,7 +251,11 @@ vips_quadratic_build( VipsObject *object ) if( VIPS_OBJECT_CLASS( vips_quadratic_parent_class )->build( object ) ) return( -1 ); - if( vips_image_copy_fields( resample->out, resample->in ) ) + /* We have the whole of the input in memory, so we can generate any + * output. + */ + if( vips_image_pipelinev( resample->out, + VIPS_DEMAND_STYLE_ANY, resample->in, NULL ) ) return( -1 ); in = resample->in; @@ -315,12 +319,6 @@ vips_quadratic_build( VipsObject *object ) if( vips_image_wio_input( in ) ) return( -1 ); - /* We have the whole of the input in memory, so we can generate any - * output. - */ - vips_demand_hint( resample->out, - VIPS_DEMAND_STYLE_ANY, resample->in, NULL ); - if( vips_image_generate( resample->out, vips_start_one, vips_quadratic_gen, vips_stop_one, in, quadratic ) ) diff --git a/libvips/resample/shrink.c b/libvips/resample/shrink.c index cff50c7c..14ee61a1 100644 --- a/libvips/resample/shrink.c +++ b/libvips/resample/shrink.c @@ -336,15 +336,13 @@ vips_shrink_build( VipsObject *object ) shrink->yshrink == 1.0 ) return( vips_image_write( resample->in, resample->out ) ); - if( vips_image_copy_fields( resample->out, resample->in ) ) - return( -1 ); - /* THINSTRIP will work, anything else will break seq mode. If you * combine shrink with conv you'll need to use a line cache to maintain * sequentiality. */ - vips_demand_hint( resample->out, - VIPS_DEMAND_STYLE_THINSTRIP, resample->in, NULL ); + if( vips_image_pipelinev( resample->out, + VIPS_DEMAND_STYLE_THINSTRIP, resample->in, NULL ) ) + return( -1 ); /* Size output. Note: we round the output width down! *