diff --git a/ChangeLog b/ChangeLog index 3f857b7d..9e348d48 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,6 +9,11 @@ - better resolution unit handling in deprecated im_vips2tiff() - use TIFF_CFLAGS output from pkg-config (thanks Jay) - much faster vips_argument_map() +- make jpeg pyramids work with tiff4 +- tiff loader always offers THINSTRIP (thanks Diuming) +- add "nocache" operation flag, set for sequential load (thanks Diuming) +- fix a crash in the tiff reader for huge values of RowsPerStrip (thanks + Nicolas) 19/4/12 started 7.28.5 - ifthenelse blend mode was broken diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index 9f2337fb..92482efd 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -698,6 +698,10 @@ vips_foreign_load_temp( VipsForeignLoad *load ) printf( "vips_foreign_load_temp: partial sequential temp\n" ); #endif /*DEBUG*/ + /* You can't reuse sequential operations. + */ + vips_operation_set_nocache( VIPS_OPERATION( load ), TRUE ); + return( vips_image_new() ); } @@ -927,6 +931,8 @@ vips_foreign_load_init( VipsForeignLoad *load ) load->disc = TRUE; } +/* Make a sequential cache for a file reader. + */ int vips_foreign_tilecache( VipsImage *in, VipsImage **out, int strip_height ) { @@ -2153,19 +2159,10 @@ vips_fitssave( VipsImage *in, const char *filename, ... ) * * Optional arguments: * - * @sequential: sequential read only - * * Read a PNG file into a VIPS image. It can read all png images, including 8- * and 16-bit images, 1 and 3 channel, with and without an alpha channel. * - * Setting @sequential to %TRUE means you promise to only demand tiles from - * this image top-top-bottom, ie. to read sequentially. This means the png - * loader can read directly from the image without having to generate a - * random-access intermediate. This can save a lot of time and memory for - * large images, but limits the sorts of operation you can perform. It's - * useful for things like generating thumbnails. - * - * There is no support for embedded ICC profiles. + * Any ICC profile is read and attached to the VIPS image. * * See also: vips_image_new_from_file(). * @@ -2204,7 +2201,9 @@ vips_pngload( const char *filename, VipsImage **out, ... ) * than an interlaced PNG can be up to 7 times slower to write than a * non-interlaced image. * - * There is no support for attaching ICC profiles to PNG images. + * If the VIPS header + * contains an ICC profile named VIPS_META_ICC_NAME ("icc-profile-data"), the + * profile from the VIPS header will be attached. * * The image is automatically converted to RGB, RGBA, Monochrome or Mono + * alpha before saving. Images with more than one byte per band element are diff --git a/libvips/foreign/tiff2vips.c b/libvips/foreign/tiff2vips.c index 74b21428..5d3331b4 100644 --- a/libvips/foreign/tiff2vips.c +++ b/libvips/foreign/tiff2vips.c @@ -128,6 +128,13 @@ * 18/2/12 * - switch to sequential read * - remove the lock ... tilecache does this for us + * 3/6/12 + * - always offer THINSTRIP ... later stages can ask for something more + * relaxed if they wish + * 7/6/12 + * - clip rows_per_strip down to image height to avoid overflows for huge + * values (thanks Nicolas) + * - better error msg for not PLANARCONFIG_CONTIG images */ /* @@ -250,29 +257,6 @@ tfexists( TIFF *tif, ttag_t tag ) return( 0 ); } -/* Test a uint16 field. Field must be defined and equal to the value. - */ -static int -tfequals( TIFF *tif, ttag_t tag, uint16 val ) -{ - uint16 fld; - - if( !TIFFGetFieldDefaulted( tif, tag, &fld ) ) { - vips_error( "tiff2vips", - _( "required field %d missing" ), tag ); - return( 0 ); - } - if( fld != val ) { - vips_error( "tiff2vips", _( "required field %d=%d, not %d" ), - tag, fld, val ); - return( 0 ); - } - - /* All ok. - */ - return( 1 ); -} - /* Get a uint32 field. */ static int @@ -304,9 +288,26 @@ tfget16( TIFF *tif, ttag_t tag, int *out ) return( 0 ); } - /* All ok. - */ *out = fld; + + return( 1 ); +} + +/* Test a uint16 field. Field must be defined and equal to the value. + */ +static int +tfequals( TIFF *tif, ttag_t tag, uint16 val ) +{ + int v; + + if( !tfget16( tif, tag, &v ) ) + return( 0 ); + if( v != val ) { + vips_error( "tiff2vips", + _( "required field %d = %d, not %d" ), tag, v, val ); + return( 0 ); + } + return( 1 ); } @@ -897,10 +898,16 @@ parse_header( ReadTiff *rtiff, VipsImage *out ) /* Ban separate planes, too annoying. */ - if( tfexists( rtiff->tiff, TIFFTAG_PLANARCONFIG ) && - !tfequals( rtiff->tiff, - TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG ) ) - return( -1 ); + if( tfexists( rtiff->tiff, TIFFTAG_PLANARCONFIG ) ) { + int v; + + tfget16( rtiff->tiff, TIFFTAG_PLANARCONFIG, &v ); + if( v != PLANARCONFIG_CONTIG ) { + vips_error( "tiff2vips", + "%s", _( "not a PLANARCONFIG_CONTIG image" ) ); + return( -1 ); + } + } /* Always need dimensions. */ @@ -1090,6 +1097,12 @@ parse_header( ReadTiff *rtiff, VipsImage *out ) (VipsCallbackFn) vips_free, data_copy, data_length ); } + /* Offer the most restrictive style. This can be changed downstream if + * necessary. + */ + vips_demand_hint( out, + VIPS_DEMAND_STYLE_THINSTRIP, NULL ); + return( 0 ); } @@ -1257,16 +1270,19 @@ read_tilewise( ReadTiff *rtiff, VipsImage *out ) if( parse_header( rtiff, raw ) ) return( -1 ); - /* Process and save as VIPS. + /* Process and save as VIPS. + * + * Even though this is a tiled reader, we hint thinstrip since with + * the cache we are quite happy serving that if anything downstream + * would like it. */ vips_demand_hint( raw, - VIPS_DEMAND_STYLE_SMALLTILE, NULL ); + VIPS_DEMAND_STYLE_THINSTRIP, NULL ); if( vips_image_generate( raw, tiff_seq_start, tiff_fill_region, tiff_seq_stop, rtiff, NULL ) ) return( -1 ); - /* Copy to out, adding a cache. Enough tiles for two complete rows. */ if( vips_tilecache( raw, &t, @@ -1335,8 +1351,8 @@ tiff2vips_stripwise_generate( VipsRegion *or, /* If necessary, unpack to destination. */ if( !rtiff->memcpy ) { - int height = VIPS_MIN( rtiff->rows_per_strip, - or->im->Ysize - (r->top + y) ); + int height = VIPS_MIN( VIPS_MIN( rtiff->rows_per_strip, + or->im->Ysize - (r->top + y) ), r->height ); int z; for( z = 0; z < height; z++ ) { @@ -1386,6 +1402,11 @@ read_stripwise( ReadTiff *rtiff, VipsImage *out ) rtiff->strip_size = TIFFStripSize( rtiff->tiff ); rtiff->number_of_strips = TIFFNumberOfStrips( rtiff->tiff ); + /* rows_per_strip can be 2**32-1, meaning the whole image. Clip this + * down to ysize to avoid confusing vips. + */ + rtiff->rows_per_strip = VIPS_MIN( rtiff->rows_per_strip, t[0]->Ysize ); + #ifdef DEBUG printf( "read_stripwise: rows_per_strip = %u\n", rtiff->rows_per_strip ); diff --git a/libvips/foreign/vips2tiff.c b/libvips/foreign/vips2tiff.c index 81920ade..116922b7 100644 --- a/libvips/foreign/vips2tiff.c +++ b/libvips/foreign/vips2tiff.c @@ -128,6 +128,9 @@ * VipsForeign class * 21/3/12 * - bump max layer buffer up + * 2/6/12 + * - copy jpeg pyramid in gather in RGB mode ... tiff4 doesn't do ycbcr + * mode */ /* @@ -906,7 +909,8 @@ shrink_region( VipsRegion *from, VipsRect *area, /* Write a tile from a layer. */ static int -save_tile( TiffWrite *tw, TIFF *tif, VipsPel *tbuf, VipsRegion *reg, VipsRect *area ) +save_tile( TiffWrite *tw, + TIFF *tif, VipsPel *tbuf, VipsRegion *reg, VipsRect *area ) { /* Have to repack pixels. */ @@ -1342,9 +1346,21 @@ tiff_copy( TiffWrite *tw, TIFF *out, TIFF *in ) /* TIFFTAG_JPEGQUALITY is a pesudo-tag, so we can't copy it. * Set explicitly from TiffWrite. */ - if( tw->compression == COMPRESSION_JPEG ) + if( tw->compression == COMPRESSION_JPEG ) { TIFFSetField( out, TIFFTAG_JPEGQUALITY, tw->jpqual ); + /* Enable rgb->ycbcr conversion in the jpeg write. See also + * the photometric selection below. + */ + TIFFSetField( out, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB ); + + /* And we want ycbcr expanded to rgb on read. Otherwise + * TIFFTileSize() will give us the size of a chrominance + * subsampled tile. + */ + TIFFSetField( in, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB ); + } + /* We can't copy profiles :( Set again from TiffWrite. */ if( embed_profile( tw, out ) ) @@ -1359,7 +1375,7 @@ tiff_copy( TiffWrite *tw, TIFF *out, TIFF *in ) * here to save compression/decompression, but sadly it seems * not to work :-( investigate at some point. */ - len = TIFFReadEncodedTile( in, tile, buf, (tsize_t) -1 ); + len = TIFFReadEncodedTile( in, tile, buf, -1 ); if( len < 0 || TIFFWriteEncodedTile( out, tile, buf, len ) < 0 ) { vips_free( buf ); @@ -1527,7 +1543,8 @@ vips__tiff_write( VipsImage *in, const char *filename, /* Gather layers together into final pyramid file. */ - if( tw->pyramid && gather_pyramid( tw ) ) { + if( tw->pyramid && + gather_pyramid( tw ) ) { free_tiff_write( tw ); return( -1 ); } diff --git a/libvips/include/vips/operation.h b/libvips/include/vips/operation.h index 4cf3cf40..e771c011 100644 --- a/libvips/include/vips/operation.h +++ b/libvips/include/vips/operation.h @@ -66,6 +66,12 @@ typedef struct _VipsOperation { guint hash; gboolean found_hash; + /* Set this before the end of _build() to stop this operation from + * being cached. Some things, like sequential read from a TIFF file, + * can't be reused. + */ + gboolean nocache; + } VipsOperation; typedef struct _VipsOperationClass { @@ -89,6 +95,7 @@ void vips_call_options( GOptionGroup *group, VipsOperation *operation ); int vips_call_argv( VipsOperation *operation, int argc, char **argv ); void vips_cache_drop_all( void ); +void vips_operation_set_nocache( VipsOperation *operation, gboolean nocache ); int vips_cache_operation_buildp( VipsOperation **operation ); VipsOperation *vips_cache_operation_build( VipsOperation *operation ); void vips_cache_set_max( int max ); diff --git a/libvips/iofuncs/cache.c b/libvips/iofuncs/cache.c index 8acb9923..67ea5273 100644 --- a/libvips/iofuncs/cache.c +++ b/libvips/iofuncs/cache.c @@ -621,7 +621,7 @@ vips_cache_operation_buildp( VipsOperation **operation ) #ifdef VIPS_DEBUG printf( "vips_cache_operation_build: " ); - vips_object_print_summary_stdout( VIPS_OBJECT( *operation ) ); + vips_object_print_dump( VIPS_OBJECT( *operation ) ); #endif /*VIPS_DEBUG*/ vips_cache_init(); @@ -643,15 +643,22 @@ vips_cache_operation_buildp( VipsOperation **operation ) } else { if( vips__cache_trace ) { - printf( "vips cache: miss %p\n ", *operation ); + if( (*operation)->nocache ) + printf( "vips cache: uncacheable %p\n ", + *operation ); + else + printf( "vips cache: miss %p\n ", *operation ); vips_object_print_summary( VIPS_OBJECT( *operation ) ); } if( vips_object_build( VIPS_OBJECT( *operation ) ) ) return( -1 ); - vips_cache_ref( *operation ); - g_hash_table_insert( vips_cache_table, *operation, *operation ); + if( !(*operation)->nocache ) { + vips_cache_ref( *operation ); + g_hash_table_insert( vips_cache_table, + *operation, *operation ); + } } return( 0 ); diff --git a/libvips/iofuncs/operation.c b/libvips/iofuncs/operation.c index 3422f7bb..52b469ec 100644 --- a/libvips/iofuncs/operation.c +++ b/libvips/iofuncs/operation.c @@ -949,3 +949,23 @@ vips_call_argv( VipsOperation *operation, int argc, char **argv ) return( 0 ); } +/** + * vips_operation_set_nocache: + * @operation: operation to set + * @nocache: TRUE means don't cache this operation + * + * Set this before the end of _build() to stop this operation being cached. + * Some operations, like sequential read from a TIFF file, for example, cannot + * be reused. + */ +void +vips_operation_set_nocache( VipsOperation *operation, gboolean nocache ) +{ +#ifdef VIPS_DEBUG + printf( "vips_operation_set_nocache: " ); + vips_object_print_name( VIPS_OBJECT( operation ) ); + printf( " %d\n", nocache ); +#endif /*VIPS_DEBUG*/ + + operation->nocache = nocache; +} diff --git a/libvips/iofuncs/threadpool.c b/libvips/iofuncs/threadpool.c index b7c78b64..37a3ef30 100644 --- a/libvips/iofuncs/threadpool.c +++ b/libvips/iofuncs/threadpool.c @@ -121,6 +121,19 @@ void vips__g_mutex_lock( GMutex *d ) {} void vips__g_mutex_unlock( GMutex *d ) {} #endif /*!HAVE_THREADS*/ +/** + * vips_concurrency_set: + * @concurrency: number of threads to run + * + * Sets the number of worker threads that vips should use when running a + * #VipsThreadPool. + * + * The special value 0 means "default". In this case, the number of threads is + * set by the environmnt variable IM_CONCURRENCY, or if that is not set, the + * number of threads availble on the hist machine. + * + * See also: vips_concurrency_get(). + */ void vips_concurrency_set( int concurrency ) { @@ -190,8 +203,29 @@ get_num_processors( void ) return( nproc ); } -/* Set (p)thr_concurrency() from IM_CONCURRENCY environment variable. Return - * the number of regions we should pass over the image. +/** + * vips_concurrency_get: + * + * Returns the number of worker threads that vips should use when running a + * #VipsThreadPool. + * + * vips gets this values from these sources in turn: + * + * If vips_concurrency_set() has been called, this value is used. The special + * value 0 means "default". You can also use the command-line argument + * "--vips-concurrency" to set this value. + * + * If vips_concurrency_set() has not been called and no command-line argument + * was used, vips uses the value of the environment variable IM_CONCURRENCY, + * + * If IM_CONCURRENCY has not been set, vips find the number of hardware + * threads that the host machine can run in parallel and uses that value. + * + * The final value is clipped to the range 1 - 1024. + * + * See also: vips_concurrency_get(). + * + * Returns: number of worker threads to use. */ int vips_concurrency_get( void ) diff --git a/libvips/resample/im_shrink.c b/libvips/resample/im_shrink.c index 98d53d85..ecb9fedb 100644 --- a/libvips/resample/im_shrink.c +++ b/libvips/resample/im_shrink.c @@ -58,6 +58,10 @@ */ +/* +#define DEBUG + */ + #ifdef HAVE_CONFIG_H #include #endif /*HAVE_CONFIG_H*/ @@ -244,6 +248,11 @@ shrink_gen( REGION *or, void *vseq, void *a, void *b ) int x, y; +#ifdef DEBUG + printf( "shrink_gen: generating %d x %d at %d x %d\n", + r->width, r->height, r->left, r->top ); +#endif /*DEBUG*/ + for( y = 0; y < r->height; y += ystep ) for( x = 0; x < r->width; x += xstep ) { /* Clip the this rect against the demand size. @@ -257,6 +266,10 @@ shrink_gen( REGION *or, void *vseq, void *a, void *b ) s.top = (r->top + y) * st->yshrink; s.width = 1 + ceil( width * st->xshrink ); s.height = 1 + ceil( height * st->yshrink ); +#ifdef DEBUG + printf( "shrink_gen: requesting %d x %d at %d x %d\n", + s.width, s.height, s.left, s.top ); +#endif /*DEBUG*/ if( im_prepare( ir, &s ) ) return( -1 ); diff --git a/po/vips7.pot b/po/vips7.pot index d106f887..db828e52 100644 --- a/po/vips7.pot +++ b/po/vips7.pot @@ -799,7 +799,7 @@ msgid "factors should both be >= 1" msgstr "" #: ../libvips/conversion/im_subsample.c:221 -#: ../libvips/resample/im_shrink.c:286 +#: ../libvips/resample/im_shrink.c:299 msgid "image has shrunk to nothing" msgstr "" @@ -1429,7 +1429,7 @@ msgstr "" msgid "error reading radiance header" msgstr "" -#: ../libvips/foreign/radiance.c:959 ../libvips/foreign/tiff2vips.c:1331 +#: ../libvips/foreign/radiance.c:959 ../libvips/foreign/tiff2vips.c:1343 msgid "read error" msgstr "" @@ -1709,91 +1709,91 @@ msgstr "" msgid "EXR error: %s" msgstr "" -#: ../libvips/foreign/tiff2vips.c:262 ../libvips/foreign/tiff2vips.c:285 -#: ../libvips/foreign/tiff2vips.c:303 +#: ../libvips/foreign/tiff2vips.c:265 ../libvips/foreign/tiff2vips.c:288 +#: ../libvips/foreign/tiff2vips.c:306 #, c-format msgid "required field %d missing" msgstr "" -#: ../libvips/foreign/tiff2vips.c:266 +#: ../libvips/foreign/tiff2vips.c:269 #, c-format msgid "required field %d=%d, not %d" msgstr "" -#: ../libvips/foreign/tiff2vips.c:650 +#: ../libvips/foreign/tiff2vips.c:653 #, c-format msgid "%d bits per sample palette image not supported" msgstr "" -#: ../libvips/foreign/tiff2vips.c:659 +#: ../libvips/foreign/tiff2vips.c:662 msgid "bad colormap" msgstr "" -#: ../libvips/foreign/tiff2vips.c:716 ../libvips/foreign/tiff2vips.c:747 +#: ../libvips/foreign/tiff2vips.c:719 ../libvips/foreign/tiff2vips.c:750 msgid "3 or 4 bands RGB TIFF only" msgstr "" -#: ../libvips/foreign/tiff2vips.c:818 +#: ../libvips/foreign/tiff2vips.c:821 msgid "4 or 5 bands CMYK TIFF only" msgstr "" -#: ../libvips/foreign/tiff2vips.c:869 +#: ../libvips/foreign/tiff2vips.c:872 msgid "unknown resolution unit" msgstr "" -#: ../libvips/foreign/tiff2vips.c:874 +#: ../libvips/foreign/tiff2vips.c:877 #, c-format msgid "" "no resolution information for TIFF image \"%s\" -- defaulting to 1 pixel per " "mm" msgstr "" -#: ../libvips/foreign/tiff2vips.c:946 +#: ../libvips/foreign/tiff2vips.c:949 #, c-format msgid "unsupported sample format %d for lab image" msgstr "" -#: ../libvips/foreign/tiff2vips.c:956 +#: ../libvips/foreign/tiff2vips.c:959 #, c-format msgid "unsupported depth %d for LAB image" msgstr "" -#: ../libvips/foreign/tiff2vips.c:995 +#: ../libvips/foreign/tiff2vips.c:998 #, c-format msgid "unsupported sample format %d for greyscale image" msgstr "" -#: ../libvips/foreign/tiff2vips.c:1004 +#: ../libvips/foreign/tiff2vips.c:1007 #, c-format msgid "unsupported depth %d for greyscale image" msgstr "" -#: ../libvips/foreign/tiff2vips.c:1052 +#: ../libvips/foreign/tiff2vips.c:1055 #, c-format msgid "unsupported sample format %d for rgb image" msgstr "" -#: ../libvips/foreign/tiff2vips.c:1061 +#: ../libvips/foreign/tiff2vips.c:1064 #, c-format msgid "unsupported depth %d for RGB image" msgstr "" -#: ../libvips/foreign/tiff2vips.c:1075 +#: ../libvips/foreign/tiff2vips.c:1078 #, c-format msgid "unknown photometric interpretation %d" msgstr "" -#: ../libvips/foreign/tiff2vips.c:1444 +#: ../libvips/foreign/tiff2vips.c:1456 #, c-format msgid "bad page number %d" msgstr "" -#: ../libvips/foreign/tiff2vips.c:1465 ../libvips/foreign/vips2tiff.c:286 +#: ../libvips/foreign/tiff2vips.c:1477 ../libvips/foreign/vips2tiff.c:289 #, c-format msgid "unable to open \"%s\" for input" msgstr "" -#: ../libvips/foreign/tiff2vips.c:1520 ../libvips/foreign/tiff2vips.c:1550 +#: ../libvips/foreign/tiff2vips.c:1532 ../libvips/foreign/tiff2vips.c:1562 #, c-format msgid "TIFF file does not contain page %d" msgstr "" @@ -1932,44 +1932,44 @@ msgstr "" msgid "save image to png buffer" msgstr "" -#: ../libvips/foreign/vips2tiff.c:270 +#: ../libvips/foreign/vips2tiff.c:273 #, c-format msgid "unable to open \"%s\" for output" msgstr "" -#: ../libvips/foreign/vips2tiff.c:692 +#: ../libvips/foreign/vips2tiff.c:695 msgid "layer buffer exhausted -- try making TIFF output tiles smaller" msgstr "" -#: ../libvips/foreign/vips2tiff.c:922 +#: ../libvips/foreign/vips2tiff.c:926 msgid "TIFF write tile failed" msgstr "" -#: ../libvips/foreign/vips2tiff.c:998 +#: ../libvips/foreign/vips2tiff.c:1002 msgid "internal error #9876345" msgstr "" -#: ../libvips/foreign/vips2tiff.c:1251 +#: ../libvips/foreign/vips2tiff.c:1255 msgid "tile size not a multiple of 16" msgstr "" -#: ../libvips/foreign/vips2tiff.c:1257 +#: ../libvips/foreign/vips2tiff.c:1261 msgid "can't have strip pyramid -- enabling tiling" msgstr "" -#: ../libvips/foreign/vips2tiff.c:1268 +#: ../libvips/foreign/vips2tiff.c:1272 msgid "can only pyramid LABQ and non-complex images" msgstr "" -#: ../libvips/foreign/vips2tiff.c:1285 +#: ../libvips/foreign/vips2tiff.c:1289 msgid "can't have 1-bit JPEG -- disabling JPEG" msgstr "" -#: ../libvips/foreign/vips2tiff.c:1463 +#: ../libvips/foreign/vips2tiff.c:1479 msgid "unsigned 8-bit int, 16-bit int, and 32-bit float only" msgstr "" -#: ../libvips/foreign/vips2tiff.c:1470 +#: ../libvips/foreign/vips2tiff.c:1486 msgid "1 to 5 bands only" msgstr "" @@ -2237,7 +2237,7 @@ msgstr "" msgid "usage:" msgstr "" -#: ../libvips/iofuncs/operation.c:287 ../libvips/iofuncs/object.c:1248 +#: ../libvips/iofuncs/operation.c:287 ../libvips/iofuncs/object.c:1239 #: ../libvips/resample/interpolate.c:615 #, c-format msgid "class \"%s\" not found" @@ -2897,56 +2897,56 @@ msgstr "" msgid "parameter %s not set" msgstr "" -#: ../libvips/iofuncs/object.c:505 +#: ../libvips/iofuncs/object.c:500 #, c-format msgid "no property named `%s'" msgstr "" -#: ../libvips/iofuncs/object.c:513 +#: ../libvips/iofuncs/object.c:508 #, c-format msgid "no vips argument named `%s'" msgstr "" -#: ../libvips/iofuncs/object.c:520 +#: ../libvips/iofuncs/object.c:515 #, c-format msgid "argument `%s' has no instance" msgstr "" -#: ../libvips/iofuncs/object.c:1297 +#: ../libvips/iofuncs/object.c:1288 msgid "base class" msgstr "" -#: ../libvips/iofuncs/object.c:1311 +#: ../libvips/iofuncs/object.c:1302 msgid "Nickname" msgstr "" -#: ../libvips/iofuncs/object.c:1312 +#: ../libvips/iofuncs/object.c:1303 msgid "Class nickname" msgstr "" -#: ../libvips/iofuncs/object.c:1318 +#: ../libvips/iofuncs/object.c:1309 msgid "Description" msgstr "" -#: ../libvips/iofuncs/object.c:1319 +#: ../libvips/iofuncs/object.c:1310 msgid "Class description" msgstr "" -#: ../libvips/iofuncs/object.c:1509 +#: ../libvips/iofuncs/object.c:1537 #, c-format msgid "enum '%s' has no member '%s'" msgstr "" -#: ../libvips/iofuncs/object.c:1769 +#: ../libvips/iofuncs/object.c:1797 #, c-format msgid "unable to set '%s'" msgstr "" -#: ../libvips/iofuncs/object.c:1777 +#: ../libvips/iofuncs/object.c:1805 msgid "not , or ) after parameter" msgstr "" -#: ../libvips/iofuncs/object.c:1784 +#: ../libvips/iofuncs/object.c:1812 msgid "extra tokens after ')'" msgstr "" @@ -3143,7 +3143,7 @@ msgstr "" msgid "factor should be in [1,0)" msgstr "" -#: ../libvips/resample/im_shrink.c:346 +#: ../libvips/resample/im_shrink.c:359 msgid "shrink factors should be >= 1" msgstr ""