Merge branch 'master' into add-smartcrop

This commit is contained in:
John Cupitt 2017-03-13 20:41:22 +00:00
commit fd6006bacb
19 changed files with 357 additions and 282 deletions

View File

@ -36,10 +36,8 @@
we get expat as part of glib
- add vips_smartcrop(), based on sharp's smartcropper
- vipsthumbnail has a --smartcrop option
- the C functions vips_math2_const(), vips_boolean_const() and
vips_relational_const() have changed argument order to match
Python/CLI/C++ ... sorry
- added vips_rot90() etc. convenience functions
- fix vips_resize() bug when hscale and vscale were very different
8/12/16 started 8.4.5
- allow libgsf-1.14.26 to help centos, thanks tdiprima

31
TODO
View File

@ -17,10 +17,6 @@
- try moving some more of the CLI tests to py
- try SEQ_UNBUFFERED on jpg source, get out of order error?
- could load pdf thumbnails?
- colour needs to split _build() into preprocess / process / postprocess
phases
@ -63,32 +59,20 @@
- why can't we do
im = Vips.Image.new_from_file("/data/john/pics/k2.jpg", access = "sequential")
import logging
logging.basicConfig(level = logging.DEBUG)
from gi.repository import Vips
im = Vips.Image.new_from_file("/data/john/pics/k2.jpg", access = "sequential")
DEBUG:gi.overrides.Vips:assigning sequential to access
DEBUG:gi.overrides.Vips:access needs a <GType VipsAccess (20432752)>
DEBUG:gi.overrides.Vips:assigning sequential
ValueError: invalid literal for int() with base 10: 'sequential'
im = Vips.Image.new_from_file("/data/john/pics/k2.jpg", access = "sequential")
no idea ... this works fine:
im.embed(10, 10, 100, 100, extend = "copy")
what about
test:
im = Vips.Image.jpegload(sys.argv[1], access = "sequential")
nope, fails too ... mysterious!
op = Vips.Operation.new("embed")
op.props.__setattr__("extend", "copy")
op = Vips.Operation.new("jpegload")
op.props.__setattr__("access", "sequential")
first setattr works fine, second fails with invalid literal
@ -437,4 +421,3 @@ new operations
http://www.nature.com/srep/2015/150730/srep12096/full/srep12096.html
sounds useful for BM?

View File

@ -982,29 +982,29 @@ operator<( VImage a, VImage b )
VImage
operator<( double a, VImage b )
{
return( b.relational_const( to_vector( a ),
VIPS_OPERATION_RELATIONAL_MORE ) );
return( b.relational_const( VIPS_OPERATION_RELATIONAL_MORE,
to_vector( a ) ) );
}
VImage
operator<( VImage a, double b )
{
return( a.relational_const( to_vector( b ),
VIPS_OPERATION_RELATIONAL_LESS ) );
return( a.relational_const( VIPS_OPERATION_RELATIONAL_LESS,
to_vector( b ) ) );
}
VImage
operator<( std::vector<double> a, VImage b )
{
return( b.relational_const( a,
VIPS_OPERATION_RELATIONAL_MORE ) );
return( b.relational_const( VIPS_OPERATION_RELATIONAL_MORE,
a ) );
}
VImage
operator<( VImage a, std::vector<double> b )
{
return( a.relational_const( b,
VIPS_OPERATION_RELATIONAL_LESS ) );
return( a.relational_const( VIPS_OPERATION_RELATIONAL_LESS,
b ) );
}
VImage
@ -1016,29 +1016,29 @@ operator<=( VImage a, VImage b )
VImage
operator<=( double a, VImage b )
{
return( b.relational_const( to_vector( a ),
VIPS_OPERATION_RELATIONAL_MOREEQ ) );
return( b.relational_const( VIPS_OPERATION_RELATIONAL_MOREEQ,
to_vector( a ) ) );
}
VImage
operator<=( VImage a, double b )
{
return( a.relational_const( to_vector( b ),
VIPS_OPERATION_RELATIONAL_LESSEQ ) );
return( a.relational_const( VIPS_OPERATION_RELATIONAL_LESSEQ,
to_vector( b ) ) );
}
VImage
operator<=( std::vector<double> a, VImage b )
{
return( b.relational_const( a,
VIPS_OPERATION_RELATIONAL_MOREEQ ) );
return( b.relational_const( VIPS_OPERATION_RELATIONAL_MOREEQ,
a ) );
}
VImage
operator<=( VImage a, std::vector<double> b )
{
return( a.relational_const( b,
VIPS_OPERATION_RELATIONAL_LESSEQ ) );
return( a.relational_const( VIPS_OPERATION_RELATIONAL_LESSEQ,
b ) );
}
VImage
@ -1050,29 +1050,29 @@ operator>( VImage a, VImage b )
VImage
operator>( double a, VImage b )
{
return( b.relational_const( to_vector( a ),
VIPS_OPERATION_RELATIONAL_LESS ) );
return( b.relational_const( VIPS_OPERATION_RELATIONAL_LESS,
to_vector( a ) ) );
}
VImage
operator>( VImage a, double b )
{
return( a.relational_const( to_vector( b ),
VIPS_OPERATION_RELATIONAL_MORE ) );
return( a.relational_const( VIPS_OPERATION_RELATIONAL_MORE,
to_vector( b ) ) );
}
VImage
operator>( std::vector<double> a, VImage b )
{
return( b.relational_const( a,
VIPS_OPERATION_RELATIONAL_LESS ) );
return( b.relational_const( VIPS_OPERATION_RELATIONAL_LESS,
a ) );
}
VImage
operator>( VImage a, std::vector<double> b )
{
return( a.relational_const( b,
VIPS_OPERATION_RELATIONAL_MORE ) );
return( a.relational_const( VIPS_OPERATION_RELATIONAL_MORE,
b ) );
}
VImage
@ -1084,29 +1084,29 @@ operator>=( VImage a, VImage b )
VImage
operator>=( double a, VImage b )
{
return( b.relational_const( to_vector( a ),
VIPS_OPERATION_RELATIONAL_LESSEQ ) );
return( b.relational_const( VIPS_OPERATION_RELATIONAL_LESSEQ,
to_vector( a ) ) );
}
VImage
operator>=( VImage a, double b )
{
return( a.relational_const( to_vector( b ),
VIPS_OPERATION_RELATIONAL_MOREEQ ) );
return( a.relational_const( VIPS_OPERATION_RELATIONAL_MOREEQ,
to_vector( b ) ) );
}
VImage
operator>=( std::vector<double> a, VImage b )
{
return( b.relational_const( a,
VIPS_OPERATION_RELATIONAL_LESSEQ ) );
return( b.relational_const( VIPS_OPERATION_RELATIONAL_LESSEQ,
a ) );
}
VImage
operator>=( VImage a, std::vector<double> b )
{
return( a.relational_const( b,
VIPS_OPERATION_RELATIONAL_MOREEQ ) );
return( a.relational_const( VIPS_OPERATION_RELATIONAL_MOREEQ,
b ) );
}
VImage
@ -1118,29 +1118,29 @@ operator==( VImage a, VImage b )
VImage
operator==( double a, VImage b )
{
return( b.relational_const( to_vector( a ),
VIPS_OPERATION_RELATIONAL_EQUAL ) );
return( b.relational_const( VIPS_OPERATION_RELATIONAL_EQUAL,
to_vector( a ) ) );
}
VImage
operator==( VImage a, double b )
{
return( a.relational_const( to_vector( b ),
VIPS_OPERATION_RELATIONAL_EQUAL ) );
return( a.relational_const( VIPS_OPERATION_RELATIONAL_EQUAL,
to_vector( b ) ) );
}
VImage
operator==( std::vector<double> a, VImage b )
{
return( b.relational_const( a,
VIPS_OPERATION_RELATIONAL_EQUAL ) );
return( b.relational_const( VIPS_OPERATION_RELATIONAL_EQUAL,
a ) );
}
VImage
operator==( VImage a, std::vector<double> b )
{
return( a.relational_const( b,
VIPS_OPERATION_RELATIONAL_EQUAL ) );
return( a.relational_const( VIPS_OPERATION_RELATIONAL_EQUAL,
b ) );
}
VImage
@ -1152,29 +1152,29 @@ operator!=( VImage a, VImage b )
VImage
operator!=( double a, VImage b )
{
return( b.relational_const( to_vector( a ),
VIPS_OPERATION_RELATIONAL_NOTEQ ) );
return( b.relational_const( VIPS_OPERATION_RELATIONAL_NOTEQ,
to_vector( a ) ) );
}
VImage
operator!=( VImage a, double b )
{
return( a.relational_const( to_vector( b ),
VIPS_OPERATION_RELATIONAL_NOTEQ ) );
return( a.relational_const( VIPS_OPERATION_RELATIONAL_NOTEQ,
to_vector( b ) ) );
}
VImage
operator!=( std::vector<double> a, VImage b )
{
return( b.relational_const( a,
VIPS_OPERATION_RELATIONAL_NOTEQ ) );
return( b.relational_const( VIPS_OPERATION_RELATIONAL_NOTEQ,
a ) );
}
VImage
operator!=( VImage a, std::vector<double> b )
{
return( a.relational_const( b,
VIPS_OPERATION_RELATIONAL_NOTEQ ) );
return( a.relational_const( VIPS_OPERATION_RELATIONAL_NOTEQ,
b ) );
}
VImage
@ -1186,27 +1186,27 @@ operator&( VImage a, VImage b )
VImage
operator&( double a, VImage b )
{
return( b.boolean_const( to_vector( a ),
VIPS_OPERATION_BOOLEAN_AND ) );
return( b.boolean_const( VIPS_OPERATION_BOOLEAN_AND,
to_vector( a ) ) );
}
VImage
operator&( VImage a, double b )
{
return( a.boolean_const( to_vector( b ),
VIPS_OPERATION_BOOLEAN_AND ) );
return( a.boolean_const( VIPS_OPERATION_BOOLEAN_AND,
to_vector( b ) ) );
}
VImage
operator&( std::vector<double> a, VImage b )
{
return( b.boolean_const( a, VIPS_OPERATION_BOOLEAN_AND ) );
return( b.boolean_const( VIPS_OPERATION_BOOLEAN_AND, a ) );
}
VImage
operator&( VImage a, std::vector<double> b )
{
return( a.boolean_const( b, VIPS_OPERATION_BOOLEAN_AND ) );
return( a.boolean_const( VIPS_OPERATION_BOOLEAN_AND, b ) );
}
VImage &
@ -1236,27 +1236,29 @@ operator|( VImage a, VImage b )
VImage
operator|( double a, VImage b )
{
return( b.boolean_const( to_vector( a ),
VIPS_OPERATION_BOOLEAN_OR ) );
return( b.boolean_const( VIPS_OPERATION_BOOLEAN_OR,
to_vector( a ) ) );
}
VImage
operator|( VImage a, double b )
{
return( a.boolean_const( to_vector( b ),
VIPS_OPERATION_BOOLEAN_OR ) );
return( a.boolean_const( VIPS_OPERATION_BOOLEAN_OR,
to_vector( b ) ) );
}
VImage
operator|( std::vector<double> a, VImage b )
{
return( b.boolean_const( a, VIPS_OPERATION_BOOLEAN_OR ) );
return( b.boolean_const( VIPS_OPERATION_BOOLEAN_OR,
a ) );
}
VImage
operator|( VImage a, std::vector<double> b )
{
return( a.boolean_const( b, VIPS_OPERATION_BOOLEAN_OR ) );
return( a.boolean_const( VIPS_OPERATION_BOOLEAN_OR,
b ) );
}
VImage &
@ -1286,27 +1288,29 @@ operator^( VImage a, VImage b )
VImage
operator^( double a, VImage b )
{
return( b.boolean_const( to_vector( a ),
VIPS_OPERATION_BOOLEAN_EOR ) );
return( b.boolean_const( VIPS_OPERATION_BOOLEAN_EOR,
to_vector( a ) ) );
}
VImage
operator^( VImage a, double b )
{
return( a.boolean_const( to_vector( b ),
VIPS_OPERATION_BOOLEAN_EOR ) );
return( a.boolean_const( VIPS_OPERATION_BOOLEAN_EOR,
to_vector( b ) ) );
}
VImage
operator^( std::vector<double> a, VImage b )
{
return( b.boolean_const( a, VIPS_OPERATION_BOOLEAN_EOR ) );
return( b.boolean_const( VIPS_OPERATION_BOOLEAN_EOR,
a ) );
}
VImage
operator^( VImage a, std::vector<double> b )
{
return( a.boolean_const( b, VIPS_OPERATION_BOOLEAN_EOR ) );
return( a.boolean_const( VIPS_OPERATION_BOOLEAN_EOR,
b ) );
}
VImage &
@ -1336,14 +1340,15 @@ operator<<( VImage a, VImage b )
VImage
operator<<( VImage a, double b )
{
return( a.boolean_const( to_vector( b ),
VIPS_OPERATION_BOOLEAN_LSHIFT ) );
return( a.boolean_const( VIPS_OPERATION_BOOLEAN_LSHIFT,
to_vector( b ) ) );
}
VImage
operator<<( VImage a, std::vector<double> b )
{
return( a.boolean_const( b, VIPS_OPERATION_BOOLEAN_LSHIFT ) );
return( a.boolean_const( VIPS_OPERATION_BOOLEAN_LSHIFT,
b ) );
}
VImage &
@ -1373,14 +1378,15 @@ operator>>( VImage a, VImage b )
VImage
operator>>( VImage a, double b )
{
return( a.boolean_const( to_vector( b ),
VIPS_OPERATION_BOOLEAN_RSHIFT ) );
return( a.boolean_const( VIPS_OPERATION_BOOLEAN_RSHIFT,
to_vector( b ) ) );
}
VImage
operator>>( VImage a, std::vector<double> b )
{
return( a.boolean_const( b, VIPS_OPERATION_BOOLEAN_RSHIFT ) );
return( a.boolean_const( VIPS_OPERATION_BOOLEAN_RSHIFT,
b ) );
}
VImage &

View File

@ -699,15 +699,15 @@ public:
VImage
pow( double other, VOption *options = 0 )
{
return( math2_const( to_vector( other ),
VIPS_OPERATION_MATH2_POW, options ) );
return( math2_const( VIPS_OPERATION_MATH2_POW,
to_vector( other ), options ) );
}
VImage
pow( std::vector<double> other, VOption *options = 0 )
{
return( math2_const( other,
VIPS_OPERATION_MATH2_POW, options ) );
return( math2_const( VIPS_OPERATION_MATH2_POW,
other, options ) );
}
VImage
@ -719,15 +719,15 @@ public:
VImage
wop( double other, VOption *options = 0 )
{
return( math2_const( to_vector( other ),
VIPS_OPERATION_MATH2_WOP, options ) );
return( math2_const( VIPS_OPERATION_MATH2_WOP,
to_vector( other ), options ) );
}
VImage
wop( std::vector<double> other, VOption *options = 0 )
{
return( math2_const( other,
VIPS_OPERATION_MATH2_WOP, options ) );
return( math2_const( VIPS_OPERATION_MATH2_WOP,
other, options ) );
}
VImage

View File

@ -1,5 +1,5 @@
// headers for vips operations
// Wed 1 Mar 15:40:22 GMT 2017
// Mon 13 Mar 13:22:09 GMT 2017
// this file is generated automatically, do not edit!
static void system( char * cmd_format , VOption *options = 0 );
@ -20,10 +20,10 @@ VImage math( VipsOperationMath math , VOption *options = 0 );
VImage abs( VOption *options = 0 );
VImage sign( VOption *options = 0 );
VImage round( VipsOperationRound round , VOption *options = 0 );
VImage relational_const( std::vector<double> c , VipsOperationRelational relational , VOption *options = 0 );
VImage relational_const( VipsOperationRelational relational , std::vector<double> c , VOption *options = 0 );
VImage remainder_const( std::vector<double> c , VOption *options = 0 );
VImage boolean_const( std::vector<double> c , VipsOperationBoolean boolean , VOption *options = 0 );
VImage math2_const( std::vector<double> c , VipsOperationMath2 math2 , VOption *options = 0 );
VImage boolean_const( VipsOperationBoolean boolean , std::vector<double> c , VOption *options = 0 );
VImage math2_const( VipsOperationMath2 math2 , std::vector<double> c , VOption *options = 0 );
VImage complex( VipsOperationComplex cmplx , VOption *options = 0 );
VImage complexget( VipsOperationComplexget get , VOption *options = 0 );
double avg( VOption *options = 0 );

View File

@ -1,5 +1,5 @@
// bodies for vips operations
// Wed 1 Mar 15:40:06 GMT 2017
// Mon 13 Mar 13:22:17 GMT 2017
// this file is generated automatically, do not edit!
void VImage::system( char * cmd_format , VOption *options )
@ -231,7 +231,7 @@ VImage VImage::round( VipsOperationRound round , VOption *options )
return( out );
}
VImage VImage::relational_const( std::vector<double> c , VipsOperationRelational relational , VOption *options )
VImage VImage::relational_const( VipsOperationRelational relational , std::vector<double> c , VOption *options )
{
VImage out;
@ -239,8 +239,8 @@ VImage VImage::relational_const( std::vector<double> c , VipsOperationRelational
(options ? options : VImage::option()) ->
set( "in", *this ) ->
set( "out", &out ) ->
set( "c", c ) ->
set( "relational", relational ) );
set( "relational", relational ) ->
set( "c", c ) );
return( out );
}
@ -258,7 +258,7 @@ VImage VImage::remainder_const( std::vector<double> c , VOption *options )
return( out );
}
VImage VImage::boolean_const( std::vector<double> c , VipsOperationBoolean boolean , VOption *options )
VImage VImage::boolean_const( VipsOperationBoolean boolean , std::vector<double> c , VOption *options )
{
VImage out;
@ -266,13 +266,13 @@ VImage VImage::boolean_const( std::vector<double> c , VipsOperationBoolean boole
(options ? options : VImage::option()) ->
set( "in", *this ) ->
set( "out", &out ) ->
set( "c", c ) ->
set( "boolean", boolean ) );
set( "boolean", boolean ) ->
set( "c", c ) );
return( out );
}
VImage VImage::math2_const( std::vector<double> c , VipsOperationMath2 math2 , VOption *options )
VImage VImage::math2_const( VipsOperationMath2 math2 , std::vector<double> c , VOption *options )
{
VImage out;
@ -280,8 +280,8 @@ VImage VImage::math2_const( std::vector<double> c , VipsOperationMath2 math2 , V
(options ? options : VImage::option()) ->
set( "in", *this ) ->
set( "out", &out ) ->
set( "c", c ) ->
set( "math2", math2 ) );
set( "math2", math2 ) ->
set( "c", c ) );
return( out );
}
@ -493,8 +493,8 @@ VImage VImage::copy( VOption *options )
call( "copy" ,
(options ? options : VImage::option()) ->
set( "out", &out ) ->
set( "in", *this ) );
set( "in", *this ) ->
set( "out", &out ) );
return( out );
}
@ -505,8 +505,8 @@ VImage VImage::tilecache( VOption *options )
call( "tilecache" ,
(options ? options : VImage::option()) ->
set( "out", &out ) ->
set( "in", *this ) );
set( "in", *this ) ->
set( "out", &out ) );
return( out );
}
@ -517,8 +517,8 @@ VImage VImage::linecache( VOption *options )
call( "linecache" ,
(options ? options : VImage::option()) ->
set( "out", &out ) ->
set( "in", *this ) );
set( "in", *this ) ->
set( "out", &out ) );
return( out );
}
@ -529,8 +529,8 @@ VImage VImage::sequential( VOption *options )
call( "sequential" ,
(options ? options : VImage::option()) ->
set( "out", &out ) ->
set( "in", *this ) );
set( "in", *this ) ->
set( "out", &out ) );
return( out );
}
@ -541,8 +541,8 @@ VImage VImage::cache( VOption *options )
call( "cache" ,
(options ? options : VImage::option()) ->
set( "out", &out ) ->
set( "in", *this ) );
set( "in", *this ) ->
set( "out", &out ) );
return( out );
}
@ -569,8 +569,8 @@ VImage VImage::flip( VipsDirection direction , VOption *options )
call( "flip" ,
(options ? options : VImage::option()) ->
set( "out", &out ) ->
set( "in", *this ) ->
set( "out", &out ) ->
set( "direction", direction ) );
return( out );
@ -742,8 +742,8 @@ VImage VImage::cast( VipsBandFormat format , VOption *options )
call( "cast" ,
(options ? options : VImage::option()) ->
set( "out", &out ) ->
set( "in", *this ) ->
set( "out", &out ) ->
set( "format", format ) );
return( out );
@ -755,8 +755,8 @@ VImage VImage::rot( VipsAngle angle , VOption *options )
call( "rot" ,
(options ? options : VImage::option()) ->
set( "out", &out ) ->
set( "in", *this ) ->
set( "out", &out ) ->
set( "angle", angle ) );
return( out );
@ -768,8 +768,8 @@ VImage VImage::rot45( VOption *options )
call( "rot45" ,
(options ? options : VImage::option()) ->
set( "out", &out ) ->
set( "in", *this ) );
set( "in", *this ) ->
set( "out", &out ) );
return( out );
}
@ -780,8 +780,8 @@ VImage VImage::autorot( VOption *options )
call( "autorot" ,
(options ? options : VImage::option()) ->
set( "out", &out ) ->
set( "in", *this ) );
set( "in", *this ) ->
set( "out", &out ) );
return( out );
}
@ -819,8 +819,8 @@ VImage VImage::bandfold( VOption *options )
call( "bandfold" ,
(options ? options : VImage::option()) ->
set( "out", &out ) ->
set( "in", *this ) );
set( "in", *this ) ->
set( "out", &out ) );
return( out );
}
@ -831,8 +831,8 @@ VImage VImage::bandunfold( VOption *options )
call( "bandunfold" ,
(options ? options : VImage::option()) ->
set( "out", &out ) ->
set( "in", *this ) );
set( "in", *this ) ->
set( "out", &out ) );
return( out );
}
@ -843,8 +843,8 @@ VImage VImage::flatten( VOption *options )
call( "flatten" ,
(options ? options : VImage::option()) ->
set( "out", &out ) ->
set( "in", *this ) );
set( "in", *this ) ->
set( "out", &out ) );
return( out );
}
@ -855,8 +855,8 @@ VImage VImage::premultiply( VOption *options )
call( "premultiply" ,
(options ? options : VImage::option()) ->
set( "out", &out ) ->
set( "in", *this ) );
set( "in", *this ) ->
set( "out", &out ) );
return( out );
}
@ -867,8 +867,8 @@ VImage VImage::unpremultiply( VOption *options )
call( "unpremultiply" ,
(options ? options : VImage::option()) ->
set( "out", &out ) ->
set( "in", *this ) );
set( "in", *this ) ->
set( "out", &out ) );
return( out );
}
@ -879,8 +879,8 @@ VImage VImage::grid( int tile_height , int across , int down , VOption *options
call( "grid" ,
(options ? options : VImage::option()) ->
set( "out", &out ) ->
set( "in", *this ) ->
set( "out", &out ) ->
set( "tile-height", tile_height ) ->
set( "across", across ) ->
set( "down", down ) );
@ -894,8 +894,8 @@ VImage VImage::scale( VOption *options )
call( "scale" ,
(options ? options : VImage::option()) ->
set( "out", &out ) ->
set( "in", *this ) );
set( "in", *this ) ->
set( "out", &out ) );
return( out );
}
@ -906,8 +906,8 @@ VImage VImage::wrap( VOption *options )
call( "wrap" ,
(options ? options : VImage::option()) ->
set( "out", &out ) ->
set( "in", *this ) );
set( "in", *this ) ->
set( "out", &out ) );
return( out );
}
@ -958,8 +958,8 @@ VImage VImage::byteswap( VOption *options )
call( "byteswap" ,
(options ? options : VImage::option()) ->
set( "out", &out ) ->
set( "in", *this ) );
set( "in", *this ) ->
set( "out", &out ) );
return( out );
}

View File

@ -533,7 +533,7 @@ vips_boolean_const_init( VipsBooleanConst *boolean_const )
static int
vips_boolean_constv( VipsImage *in, VipsImage **out,
double *c, int n, VipsOperationBoolean operation, va_list ap )
VipsOperationBoolean operation, double *c, int n, va_list ap )
{
VipsArea *area_c;
double *array;
@ -546,7 +546,7 @@ vips_boolean_constv( VipsImage *in, VipsImage **out,
array[i] = c[i];
result = vips_call_split( "boolean_const", ap,
in, out, area_c, operation );
in, out, operation, area_c );
vips_area_unref( area_c );
@ -557,9 +557,9 @@ vips_boolean_constv( VipsImage *in, VipsImage **out,
* vips_boolean_const:
* @in: input image
* @out: output image
* @boolean: boolean operation to perform
* @c: array of constants
* @n: number of constants in @c
* @boolean: boolean operation to perform
* @...: %NULL-terminated list of optional named arguments
*
* Perform various boolean operations on an image against an array of
@ -580,13 +580,13 @@ vips_boolean_constv( VipsImage *in, VipsImage **out,
*/
int
vips_boolean_const( VipsImage *in, VipsImage **out,
double *c, int n, VipsOperationBoolean boolean, ... )
VipsOperationBoolean boolean, double *c, int n, ... )
{
va_list ap;
int result;
va_start( ap, boolean );
result = vips_boolean_constv( in, out, c, n, boolean, ap );
va_start( ap, n );
result = vips_boolean_constv( in, out, boolean, c, n, ap );
va_end( ap );
return( result );
@ -615,7 +615,7 @@ vips_andimage_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
va_start( ap, n );
result = vips_boolean_constv( in, out,
c, n, VIPS_OPERATION_BOOLEAN_AND, ap );
VIPS_OPERATION_BOOLEAN_AND, c, n, ap );
va_end( ap );
return( result );
@ -644,7 +644,7 @@ vips_orimage_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
va_start( ap, n );
result = vips_boolean_constv( in, out,
c, n, VIPS_OPERATION_BOOLEAN_OR, ap );
VIPS_OPERATION_BOOLEAN_OR, c, n, ap );
va_end( ap );
return( result );
@ -673,7 +673,7 @@ vips_eorimage_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
va_start( ap, n );
result = vips_boolean_constv( in, out,
c, n, VIPS_OPERATION_BOOLEAN_EOR, ap );
VIPS_OPERATION_BOOLEAN_EOR, c, n, ap );
va_end( ap );
return( result );
@ -702,7 +702,7 @@ vips_lshift_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
va_start( ap, n );
result = vips_boolean_constv( in, out,
c, n, VIPS_OPERATION_BOOLEAN_LSHIFT, ap );
VIPS_OPERATION_BOOLEAN_LSHIFT, c, n, ap );
va_end( ap );
return( result );
@ -731,7 +731,7 @@ vips_rshift_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
va_start( ap, n );
result = vips_boolean_constv( in, out,
c, n, VIPS_OPERATION_BOOLEAN_RSHIFT, ap );
VIPS_OPERATION_BOOLEAN_RSHIFT, c, n, ap );
va_end( ap );
return( result );
@ -754,13 +754,13 @@ vips_rshift_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
*/
int
vips_boolean_const1( VipsImage *in, VipsImage **out,
double c, VipsOperationBoolean boolean, ... )
VipsOperationBoolean boolean, double c, ... )
{
va_list ap;
int result;
va_start( ap, boolean );
result = vips_boolean_constv( in, out, &c, 1, boolean, ap );
va_start( ap, c );
result = vips_boolean_constv( in, out, boolean, &c, 1, ap );
va_end( ap );
return( result );
@ -788,7 +788,7 @@ vips_andimage_const1( VipsImage *in, VipsImage **out, double c, ... )
va_start( ap, c );
result = vips_boolean_constv( in, out,
&c, 1, VIPS_OPERATION_BOOLEAN_AND, ap );
VIPS_OPERATION_BOOLEAN_AND, &c, 1, ap );
va_end( ap );
return( result );
@ -816,7 +816,7 @@ vips_orimage_const1( VipsImage *in, VipsImage **out, double c, ... )
va_start( ap, c );
result = vips_boolean_constv( in, out,
&c, 1, VIPS_OPERATION_BOOLEAN_OR, ap );
VIPS_OPERATION_BOOLEAN_OR, &c, 1, ap );
va_end( ap );
return( result );
@ -844,7 +844,7 @@ vips_eorimage_const1( VipsImage *in, VipsImage **out, double c, ... )
va_start( ap, c );
result = vips_boolean_constv( in, out,
&c, 1, VIPS_OPERATION_BOOLEAN_EOR, ap );
VIPS_OPERATION_BOOLEAN_EOR, &c, 1, ap );
va_end( ap );
return( result );
@ -872,7 +872,7 @@ vips_lshift_const1( VipsImage *in, VipsImage **out, double c, ... )
va_start( ap, c );
result = vips_boolean_constv( in, out,
&c, 1, VIPS_OPERATION_BOOLEAN_LSHIFT, ap );
VIPS_OPERATION_BOOLEAN_LSHIFT, &c, 1, ap );
va_end( ap );
return( result );
@ -900,7 +900,7 @@ vips_rshift_const1( VipsImage *in, VipsImage **out, double c, ... )
va_start( ap, c );
result = vips_boolean_constv( in, out,
&c, 1, VIPS_OPERATION_BOOLEAN_RSHIFT, ap );
VIPS_OPERATION_BOOLEAN_RSHIFT, &c, 1, ap );
va_end( ap );
return( result );

View File

@ -421,7 +421,7 @@ vips_math2_const_init( VipsMath2Const *math2_const )
static int
vips_math2_constv( VipsImage *in, VipsImage **out,
double *c, int n, VipsOperationMath2 math2, va_list ap )
VipsOperationMath2 math2, double *c, int n, va_list ap )
{
VipsArea *area_c;
double *array;
@ -433,7 +433,7 @@ vips_math2_constv( VipsImage *in, VipsImage **out,
for( i = 0; i < n; i++ )
array[i] = c[i];
result = vips_call_split( "math2_const", ap, in, out, area_c, math2 );
result = vips_call_split( "math2_const", ap, in, out, math2, area_c );
vips_area_unref( area_c );
@ -444,9 +444,9 @@ vips_math2_constv( VipsImage *in, VipsImage **out,
* vips_math2_const:
* @in: input image
* @out: output image
* @math2: math operation to perform
* @c: array of constants
* @n: number of constants in @c
* @math2: math operation to perform
* @...: %NULL-terminated list of optional named arguments
*
* This operation calculates various 2-ary maths operations on an image and
@ -471,13 +471,13 @@ vips_math2_constv( VipsImage *in, VipsImage **out,
*/
int
vips_math2_const( VipsImage *in, VipsImage **out,
double *c, int n, VipsOperationMath2 math2, ... )
VipsOperationMath2 math2, double *c, int n, ... )
{
va_list ap;
int result;
va_start( ap, math2 );
result = vips_math2_constv( in, out, c, n, math2, ap );
va_start( ap, n );
result = vips_math2_constv( in, out, math2, c, n, ap );
va_end( ap );
return( result );
@ -504,7 +504,7 @@ vips_pow_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
va_start( ap, n );
result = vips_math2_constv( in, out,
c, n, VIPS_OPERATION_MATH2_POW, ap );
VIPS_OPERATION_MATH2_POW, c, n, ap );
va_end( ap );
return( result );
@ -531,7 +531,7 @@ vips_wop_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
va_start( ap, n );
result = vips_math2_constv( in, out,
c, n, VIPS_OPERATION_MATH2_WOP, ap );
VIPS_OPERATION_MATH2_WOP, c, n, ap );
va_end( ap );
return( result );
@ -552,13 +552,13 @@ vips_wop_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
*/
int
vips_math2_const1( VipsImage *in, VipsImage **out,
double c, VipsOperationMath2 math2, ... )
VipsOperationMath2 math2, double c, ... )
{
va_list ap;
int result;
va_start( ap, math2 );
result = vips_math2_constv( in, out, &c, 1, math2, ap );
va_start( ap, c );
result = vips_math2_constv( in, out, math2, &c, 1, ap );
va_end( ap );
return( result );
@ -584,7 +584,7 @@ vips_pow_const1( VipsImage *in, VipsImage **out, double c, ... )
va_start( ap, c );
result = vips_math2_constv( in, out,
&c, 1, VIPS_OPERATION_MATH2_POW, ap );
VIPS_OPERATION_MATH2_POW, &c, 1, ap );
va_end( ap );
return( result );
@ -610,7 +610,7 @@ vips_wop_const1( VipsImage *in, VipsImage **out, double c, ... )
va_start( ap, c );
result = vips_math2_constv( in, out,
&c, 1, VIPS_OPERATION_MATH2_WOP, ap );
VIPS_OPERATION_MATH2_WOP, &c, 1, ap );
va_end( ap );
return( result );

View File

@ -574,7 +574,7 @@ vips_relational_const_init( VipsRelationalConst *relational_const )
static int
vips_relational_constv( VipsImage *in, VipsImage **out,
double *c, int n, VipsOperationRelational relational, va_list ap )
VipsOperationRelational relational, double *c, int n, va_list ap )
{
VipsArea *area_c;
double *array;
@ -587,7 +587,7 @@ vips_relational_constv( VipsImage *in, VipsImage **out,
array[i] = c[i];
result = vips_call_split( "relational_const", ap,
in, out, area_c, relational );
in, out, relational, area_c );
vips_area_unref( area_c );
@ -598,9 +598,9 @@ vips_relational_constv( VipsImage *in, VipsImage **out,
* vips_relational_const:
* @in: input image
* @out: output image
* @relational: relational operation to perform
* @c: array of constants
* @n: number of constants in @c
* @relational: relational operation to perform
* @...: %NULL-terminated list of optional named arguments
*
* Perform various relational operations on an image and an array of
@ -621,13 +621,13 @@ vips_relational_constv( VipsImage *in, VipsImage **out,
*/
int
vips_relational_const( VipsImage *in, VipsImage **out,
double *c, int n, VipsOperationRelational relational, ... )
VipsOperationRelational relational, double *c, int n, ... )
{
va_list ap;
int result;
va_start( ap, relational );
result = vips_relational_constv( in, out, c, n, relational, ap );
va_start( ap, n );
result = vips_relational_constv( in, out, relational, c, n, ap );
va_end( ap );
return( result );
@ -654,7 +654,7 @@ vips_equal_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
va_start( ap, n );
result = vips_relational_constv( in, out,
c, n, VIPS_OPERATION_RELATIONAL_EQUAL, ap );
VIPS_OPERATION_RELATIONAL_EQUAL, c, n, ap );
va_end( ap );
return( result );
@ -681,7 +681,7 @@ vips_notequal_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
va_start( ap, n );
result = vips_relational_constv( in, out,
c, n, VIPS_OPERATION_RELATIONAL_NOTEQ, ap );
VIPS_OPERATION_RELATIONAL_NOTEQ, c, n, ap );
va_end( ap );
return( result );
@ -708,7 +708,7 @@ vips_less_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
va_start( ap, n );
result = vips_relational_constv( in, out,
c, n, VIPS_OPERATION_RELATIONAL_LESS, ap );
VIPS_OPERATION_RELATIONAL_LESS, c, n, ap );
va_end( ap );
return( result );
@ -735,7 +735,7 @@ vips_lesseq_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
va_start( ap, n );
result = vips_relational_constv( in, out,
c, n, VIPS_OPERATION_RELATIONAL_LESSEQ, ap );
VIPS_OPERATION_RELATIONAL_LESSEQ, c, n, ap );
va_end( ap );
return( result );
@ -762,7 +762,7 @@ vips_more_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
va_start( ap, n );
result = vips_relational_constv( in, out,
c, n, VIPS_OPERATION_RELATIONAL_MORE, ap );
VIPS_OPERATION_RELATIONAL_MORE, c, n, ap );
va_end( ap );
return( result );
@ -789,7 +789,7 @@ vips_moreeq_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
va_start( ap, n );
result = vips_relational_constv( in, out,
c, n, VIPS_OPERATION_RELATIONAL_MOREEQ, ap );
VIPS_OPERATION_RELATIONAL_MOREEQ, c, n, ap );
va_end( ap );
return( result );
@ -799,8 +799,8 @@ vips_moreeq_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
* vips_relational_const1:
* @in: input image
* @out: output image
* @c: constant
* @relational: relational operation to perform
* @c: constant
* @...: %NULL-terminated list of optional named arguments
*
* Perform various relational operations on an image and a constant. See
@ -812,13 +812,13 @@ vips_moreeq_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
*/
int
vips_relational_const1( VipsImage *in, VipsImage **out,
double c, VipsOperationRelational relational, ... )
VipsOperationRelational relational, double c, ... )
{
va_list ap;
int result;
va_start( ap, relational );
result = vips_relational_constv( in, out, &c, 1, relational, ap );
va_start( ap, c );
result = vips_relational_constv( in, out, relational, &c, 1, ap );
va_end( ap );
return( result );
@ -844,7 +844,7 @@ vips_equal_const1( VipsImage *in, VipsImage **out, double c, ... )
va_start( ap, c );
result = vips_relational_constv( in, out,
&c, 1, VIPS_OPERATION_RELATIONAL_EQUAL, ap );
VIPS_OPERATION_RELATIONAL_EQUAL, &c, 1, ap );
va_end( ap );
return( result );
@ -870,7 +870,7 @@ vips_notequal_const1( VipsImage *in, VipsImage **out, double c, ... )
va_start( ap, c );
result = vips_relational_constv( in, out,
&c, 1, VIPS_OPERATION_RELATIONAL_NOTEQ, ap );
VIPS_OPERATION_RELATIONAL_NOTEQ, &c, 1, ap );
va_end( ap );
return( result );
@ -896,7 +896,7 @@ vips_less_const1( VipsImage *in, VipsImage **out, double c, ... )
va_start( ap, c );
result = vips_relational_constv( in, out,
&c, 1, VIPS_OPERATION_RELATIONAL_LESS, ap );
VIPS_OPERATION_RELATIONAL_LESS, &c, 1, ap );
va_end( ap );
return( result );
@ -922,7 +922,7 @@ vips_lesseq_const1( VipsImage *in, VipsImage **out, double c, ... )
va_start( ap, c );
result = vips_relational_constv( in, out,
&c, 1, VIPS_OPERATION_RELATIONAL_LESSEQ, ap );
VIPS_OPERATION_RELATIONAL_LESSEQ, &c, 1, ap );
va_end( ap );
return( result );
@ -948,7 +948,7 @@ vips_more_const1( VipsImage *in, VipsImage **out, double c, ... )
va_start( ap, c );
result = vips_relational_constv( in, out,
&c, 1, VIPS_OPERATION_RELATIONAL_MORE, ap );
VIPS_OPERATION_RELATIONAL_MORE, &c, 1, ap );
va_end( ap );
return( result );
@ -974,7 +974,7 @@ vips_moreeq_const1( VipsImage *in, VipsImage **out, double c, ... )
va_start( ap, c );
result = vips_relational_constv( in, out,
&c, 1, VIPS_OPERATION_RELATIONAL_MOREEQ, ap );
VIPS_OPERATION_RELATIONAL_MOREEQ, &c, 1, ap );
va_end( ap );
return( result );

View File

@ -203,7 +203,7 @@ vips_unary_const_class_init( VipsUnaryConstClass *class )
object_class->description = _( "unary operations with a constant" );
object_class->build = vips_unary_const_build;
VIPS_ARG_BOXED( class, "c", 199,
VIPS_ARG_BOXED( class, "c", 201,
_( "c" ),
_( "Array of constants" ),
VIPS_ARGUMENT_REQUIRED_INPUT,

View File

@ -2749,7 +2749,7 @@ vips__relational_vec( IMAGE *in, IMAGE *out,
{
VipsImage *t;
if( vips_relational_const( in, &t, c, n, relational,
if( vips_relational_const( in, &t, relational, c, n,
NULL ) )
return( -1 );
if( vips_image_write( t, out ) ) {
@ -2921,7 +2921,7 @@ vips__boolean_vec( IMAGE *in, IMAGE *out,
{
VipsImage *t;
if( vips_boolean_const( in, &t, c, n, boolean,
if( vips_boolean_const( in, &t, boolean, c, n,
NULL ) )
return( -1 );
if( vips_image_write( t, out ) ) {
@ -3008,7 +3008,7 @@ vips__math2_vec( IMAGE *in, IMAGE *out,
{
VipsImage *t;
if( vips_math2_const( in, &t, c, n, math2,
if( vips_math2_const( in, &t, math2, c, n,
NULL ) )
return( -1 );
if( vips_image_write( t, out ) ) {

View File

@ -805,7 +805,7 @@ vips_foreign_load_gif_class_init( VipsForeignLoadGifClass *class )
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
object_class->nickname = "gifload";
object_class->nickname = "gifload_base";
object_class->description = _( "load GIF with giflib" );
load_class->get_flags_filename =

View File

@ -455,7 +455,7 @@ vips_foreign_load_pdf_class_init( VipsForeignLoadPdfClass *class )
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
object_class->nickname = "pdfload";
object_class->nickname = "pdfload_base";
object_class->description = _( "load PDF with libpoppler" );
object_class->build = vips_foreign_load_pdf_build;

View File

@ -279,7 +279,7 @@ int vips_more( VipsImage *left, VipsImage *right, VipsImage **out, ... )
int vips_moreeq( VipsImage *left, VipsImage *right, VipsImage **out, ... )
__attribute__((sentinel));
int vips_relational_const( VipsImage *in, VipsImage **out,
double *c, int n, VipsOperationRelational relational, ... )
VipsOperationRelational relational, double *c, int n, ... )
__attribute__((sentinel));
int vips_equal_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
__attribute__((sentinel));
@ -294,7 +294,7 @@ int vips_more_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
int vips_moreeq_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
__attribute__((sentinel));
int vips_relational_const1( VipsImage *in, VipsImage **out,
double c, VipsOperationRelational relational, ... )
VipsOperationRelational relational, double c, ... )
__attribute__((sentinel));
int vips_equal_const1( VipsImage *in, VipsImage **out, double c, ... )
__attribute__((sentinel));
@ -324,7 +324,7 @@ int vips_rshift( VipsImage *left, VipsImage *right, VipsImage **out, ... )
__attribute__((sentinel));
int vips_boolean_const( VipsImage *in, VipsImage **out,
double *c, int n, VipsOperationBoolean boolean, ... )
VipsOperationBoolean boolean, double *c, int n, ... )
__attribute__((sentinel));
int vips_andimage_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
__attribute__((sentinel));
@ -337,7 +337,7 @@ int vips_lshift_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
int vips_rshift_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
__attribute__((sentinel));
int vips_boolean_const1( VipsImage *in, VipsImage **out,
double c, VipsOperationBoolean boolean, ... )
VipsOperationBoolean boolean, double c, ... )
__attribute__((sentinel));
int vips_andimage_const1( VipsImage *in, VipsImage **out, double c, ... )
__attribute__((sentinel));
@ -358,14 +358,14 @@ int vips_pow( VipsImage *left, VipsImage *right, VipsImage **out, ... )
int vips_wop( VipsImage *left, VipsImage *right, VipsImage **out, ... )
__attribute__((sentinel));
int vips_math2_const( VipsImage *in, VipsImage **out,
double *c, int n, VipsOperationMath2 math2, ... )
VipsOperationMath2 math2, double *c, int n, ... )
__attribute__((sentinel));
int vips_pow_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
__attribute__((sentinel));
int vips_wop_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
__attribute__((sentinel));
int vips_math2_const1( VipsImage *in, VipsImage **out,
double c, VipsOperationMath2 math2, ... )
VipsOperationMath2 math2, double c, ... )
__attribute__((sentinel));
int vips_pow_const1( VipsImage *in, VipsImage **out, double c, ... )
__attribute__((sentinel));

View File

@ -1622,12 +1622,12 @@ vips_image_set_progress( VipsImage *image, gboolean progress )
* vips_image_iskilled:
* @image: image to test
*
* If @image has been killed (see vips_image_kill()), set an error message,
* If @image has been killed (see vips_image_set_kill()), set an error message,
* clear the #VipsImage.kill flag and return %FALSE. Otherwise return %TRUE.
*
* Handy for loops which need to run sets of threads which can fail.
*
* See also: vips_image_kill().
* See also: vips_image_set_kill().
*
* Returns: %FALSE if @image has been killed.
*/

View File

@ -832,6 +832,8 @@ vips_reducev_build( VipsObject *object )
if( VIPS_OBJECT_CLASS( vips_reducev_parent_class )->build( object ) )
return( -1 );
g_info( "reducev by factor %g", reducev->vshrink );
in = resample->in;
if( reducev->vshrink < 1 ) {

View File

@ -127,7 +127,7 @@ vips_resize_int_shrink( VipsResize *resize, double scale )
case VIPS_KERNEL_LANCZOS2:
case VIPS_KERNEL_LANCZOS3:
return( VIPS_MAX( 1, VIPS_FLOOR( 1.0 / (resize->scale * 2) ) ) );
return( VIPS_MAX( 1, VIPS_FLOOR( 1.0 / (scale * 2) ) ) );
}
}

View File

@ -60,6 +60,11 @@ vips_type_image = GObject.GType.from_name("VipsImage")
vips_type_operation = GObject.GType.from_name("VipsOperation")
vips_type_ref_string = GObject.GType.from_name("VipsRefString")
# 8.4 and earlier had a bug which swapped the order of const args to enum
# operations
swap_const_args = Vips.version(0) < 8 or (Vips.version(0) == 8 and
Vips.version(1) <= 4)
def is_2D(value):
if not isinstance(value, list):
return False
@ -415,6 +420,27 @@ def _call_base(name, required, optional, self = None, option_string = None):
return out
# handy for expanding enums
def _call_enum(self, name, enum, other):
if isinstance(other, Vips.Image):
return _call_base(name, [other, enum], {}, self)
elif swap_const_args:
return _call_base(name + "_const", [other, enum], {}, self)
else:
return _call_base(name + "_const", [enum, other], {}, self)
# for equality style operations, we need to allow comparison with None
def _call_enum_eq(self, name, enum, other):
if isinstance(other, Vips.Image):
return _call_base(name, [other, enum], {}, self)
elif isinstance(other, list) or isinstance(other, numbers.Number):
if swap_const_args:
return _call_base(name + "_const", [other, enum], {}, self)
else:
return _call_base(name + "_const", [enum, other], {}, self)
else:
return False
# general user entrypoint
def call(name, *args, **kwargs):
return _call_base(name, args, kwargs)
@ -712,52 +738,34 @@ class Image(Vips.Image):
return self.remainder_const(other)
def __pow__(self, other):
if isinstance(other, Vips.Image):
return self.math2(other, Vips.OperationMath2.POW)
else:
return self.math2_const(other, Vips.OperationMath2.POW)
return _call_enum(self, "math2", Vips.OperationMath2.POW, other)
def __rpow__(self, other):
return self.math2_const(other, Vips.OperationMath2.WOP)
return _call_enum(self, "math2", Vips.OperationMath2.WOP, other)
def __abs__(self):
return self.abs()
def __lshift__(self, other):
if isinstance(other, Vips.Image):
return self.boolean(other, Vips.OperationBoolean.LSHIFT)
else:
return self.boolean_const(other, Vips.OperationBoolean.LSHIFT)
return _call_enum(self, "boolean", Vips.OperationBoolean.LSHIFT, other)
def __rshift__(self, other):
if isinstance(other, Vips.Image):
return self.boolean(other, Vips.OperationBoolean.RSHIFT)
else:
return self.boolean_const(other, Vips.OperationBoolean.RSHIFT)
return _call_enum(self, "boolean", Vips.OperationBoolean.RSHIFT, other)
def __and__(self, other):
if isinstance(other, Vips.Image):
return self.boolean(other, Vips.OperationBoolean.AND)
else:
return self.boolean_const(other, Vips.OperationBoolean.AND)
return _call_enum(self, "boolean", Vips.OperationBoolean.AND, other)
def __rand__(self, other):
return self.__and__(other)
def __or__(self, other):
if isinstance(other, Vips.Image):
return self.boolean(other, Vips.OperationBoolean.OR)
else:
return self.boolean_const(other, Vips.OperationBoolean.OR)
return _call_enum(self, "boolean", Vips.OperationBoolean.OR, other)
def __ror__(self, other):
return self.__or__(other)
def __xor__(self, other):
if isinstance(other, Vips.Image):
return self.boolean(other, Vips.OperationBoolean.EOR)
else:
return self.boolean_const(other, Vips.OperationBoolean.EOR)
return _call_enum(self, "boolean", Vips.OperationBoolean.EOR, other)
def __rxor__(self, other):
return self.__xor__(other)
@ -772,49 +780,30 @@ class Image(Vips.Image):
return self ^ -1
def __gt__(self, other):
if isinstance(other, Vips.Image):
return self.relational(other, Vips.OperationRelational.MORE)
else:
return self.relational_const(other, Vips.OperationRelational.MORE)
return _call_enum(self,
"relational", Vips.OperationRelational.MORE, other)
def __ge__(self, other):
if isinstance(other, Vips.Image):
return self.relational(other, Vips.OperationRelational.MOREEQ)
else:
return self.relational_const(other, Vips.OperationRelational.MOREEQ)
return _call_enum(self,
"relational", Vips.OperationRelational.MOREEQ, other)
def __lt__(self, other):
if isinstance(other, Vips.Image):
return self.relational(other, Vips.OperationRelational.LESS)
else:
return self.relational_const(other, Vips.OperationRelational.LESS)
return _call_enum(self,
"relational", Vips.OperationRelational.LESS, other)
def __le__(self, other):
if isinstance(other, Vips.Image):
return self.relational(other, Vips.OperationRelational.LESSEQ)
else:
return self.relational_const(other, Vips.OperationRelational.LESSEQ)
return _call_enum(self,
"relational", Vips.OperationRelational.LESSEQ, other)
def __eq__(self, other):
# for == and != we need to allow comparison to None
if isinstance(other, Vips.Image):
return self.relational(other, Vips.OperationRelational.EQUAL)
elif isinstance(other, list):
return self.relational_const(other, Vips.OperationRelational.EQUAL)
elif isinstance(other, numbers.Number):
return self.relational_const(other, Vips.OperationRelational.EQUAL)
else:
return False
# _eq version allows comparison to None
return _call_enum_eq(self,
"relational", Vips.OperationRelational.EQUAL, other)
def __ne__(self, other):
if isinstance(other, Vips.Image):
return self.relational(other, Vips.OperationRelational.NOTEQ)
elif isinstance(other, list):
return self.relational_const(other, Vips.OperationRelational.NOTEQ)
elif isinstance(other, numbers.Number):
return self.relational_const(other, Vips.OperationRelational.NOTEQ)
else:
return False
# _eq version allows comparison to None
return _call_enum_eq(self,
"relational", Vips.OperationRelational.NOTEQ, other)
def __getitem__(self, arg):
if isinstance(arg, slice):

97
whatsnew-8.5.md Normal file
View File

@ -0,0 +1,97 @@
This branch has a new implementation of sequential mode:
https://github.com/jcupitt/libvips/tree/remove-seq-stalling
It'd be great to get this merged to master for 8.5, but it needs some testing.
How seq used to work:
* The vips sink functions create a set of N threads and scan images
top-to-bottom in tiles, allocating tiles to workers as they finish.
* They have extra logic to keep workers together. They track the position
of the most-delayed worker and if the lead thread gets more than M scanlines
ahead, it stalls until the stragglers catch up.
* There is more logic in the loaders: they keep track of the current
Y position, and if the lead request thread gets ahead of the current
read point, it stalls with a 60s timeout until the intermediate tiles are
requested. This logic is implemented in the `vips_sequential()` operation.
The point of trying to keep thread locality and ordering is that we want
to limit the number of scanlines that loaders have to keep behind the read
point. We want to stream images through memory, not be forced into a load /
process / save model.
This works reasonably well for simple cases, like thumbnailing single images,
but can fail in more complex cases, such as repeated `vips_insert()`. Consider
this Python program:
```python
#!/usr/bin/python
import sys import random
import gi gi.require_version('Vips', '8.0') from gi.repository import Vips
composite = Vips.Image.black(100000, 100000)
for filename in sys.argv[2:]:
tile = Vips.Image.new_from_file(filename, access = Vips.Access.SEQUENTIAL)
x = random.randint(0, composite.width - tile.width) y = random.randint(0,
composite.height - tile.height) composite = composite.insert(tile, x, y)
composite.write_to_file(sys.argv[1])
```
This makes a 100,000 x 100,000 pixel black image, then inserts a lot of
other files into it and writes the result.
With vips8.4, this could very easily fail. Imagine this situation:
* image1 is very tall and thin
* image2 is short and fat, and by chance covers the centre of image1
* we'll write the top part of image1, then write the body of image2
* after image2 has been written, we need to write the bottom of image1,
so a thread will ask for a set of pixels near the end of image1
* image1 knows that the previous request was for some scanlines near the top,
so it thinks this request must be from a thread that has run way ahead of
the pack and stalls it
And we have a deadlock. In fact, vips wouldn't deadlock, it would just
pause on a 60s timeout on each thread. Sad!
Here's how the new seq works:
* Sinks work as before.
* Loaders use a revised `vips_sequential()` with the stalling logic
removed. All it does now is track the read position, cache a few 100 lines
behind the read point, and makes sure that lines are evaluated in order
with no missing areas.
* Operations like `vips_shrinkv()` which can cause large non-local references
have an extra bit of code which, if the input comes from a sequential source,
adds a an extra `vips_sequential()` operator on the output. This forces
`vips_shrinkv()` input to be sequential.
The old one constrained thread location on output, and on input as well. The
new idea is to get rid of input constraints, and instead add extra code
to the operations which could trigger large non-local references. Rather
than tying threads down to stop them drifting apart, it makes sure they
can never get too far apart in the first place.
Running the test program with git master gives this result:
```
real 1m2.317s
user 2m58.472s
sys 0m7.568s
peak mem: 10gb
```
Not bad!