From d98f5a28fc92a5de41eedc6fbe3a801a9599ad85 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Fri, 1 Jun 2012 17:45:50 +0100 Subject: [PATCH 1/6] we broke binary compat, bump library version the extra object fields for the new argument mapping system broke binary compat, bump ABI version --- configure.in | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.in b/configure.in index 66dc6b6a..ac54431a 100644 --- a/configure.in +++ b/configure.in @@ -34,9 +34,9 @@ VIPS_VERSION_STRING=$VIPS_VERSION-`date` # interface changes backwards compatible?: increment age # interface changes not backwards compatible?: reset age to 0 -LIBRARY_CURRENT=31 -LIBRARY_REVISION=6 -LIBRARY_AGE=16 +LIBRARY_CURRENT=32 +LIBRARY_REVISION=0 +LIBRARY_AGE=0 # patched into include/vips/version.h AC_SUBST(VIPS_VERSION) From f65f9088f6b9c2470d6cd377000ddc7842c45022 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Sat, 2 Jun 2012 17:42:42 +0100 Subject: [PATCH 2/6] make jpeg pyr write work with tiff4 there was a problem with sizing tiles in chrominance subsample mode --- ChangeLog | 1 + libvips/foreign/vips2tiff.c | 25 +++++++++++++++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9c0f6df7..c94f9afa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,7 @@ - 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 19/4/12 started 7.28.5 - ifthenelse blend mode was broken diff --git a/libvips/foreign/vips2tiff.c b/libvips/foreign/vips2tiff.c index 059d2bd5..ddec2f5f 100644 --- a/libvips/foreign/vips2tiff.c +++ b/libvips/foreign/vips2tiff.c @@ -126,6 +126,9 @@ * 2/12/11 * - make into a simple function call ready to be wrapped as a new-style * VipsForeign class + * 2/6/12 + * - copy jpeg pyramid in gather in RGB mode ... tiff4 doesn't do ycbcr + * mode */ /* @@ -904,7 +907,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. */ @@ -1340,9 +1344,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 ) ) @@ -1357,7 +1373,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 ); @@ -1525,7 +1541,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 ); } From fc3d4192d7a8f17978cc7ab997e35af583d70353 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Sun, 3 Jun 2012 11:44:03 +0100 Subject: [PATCH 3/6] tiff loader always offers thinstrip the tiff loader now always offers thinstrip ... later stages can then pick any demand style they like (thanks Diuming) --- ChangeLog | 1 + libvips/foreign/foreign.c | 15 ++++----------- libvips/foreign/tiff2vips.c | 18 +++++++++++++++--- libvips/resample/im_shrink.c | 13 +++++++++++++ 4 files changed, 33 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index c94f9afa..66890d73 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,7 @@ - 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) 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 3eafd96c..c8710ac9 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -2151,19 +2151,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(). * @@ -2202,7 +2193,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 212d16c5..63c00c26 100644 --- a/libvips/foreign/tiff2vips.c +++ b/libvips/foreign/tiff2vips.c @@ -128,6 +128,9 @@ * 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 */ /* @@ -1090,6 +1093,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 +1266,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, 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 ); From b6f902560fa547b32a25d0953014c120516fdcf6 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Sun, 3 Jun 2012 13:01:21 +0100 Subject: [PATCH 4/6] add doc comments for vips_concurrency_*() --- libvips/iofuncs/threadpool.c | 38 +++++++++++- po/vips7.pot | 112 +++++++++++++++++------------------ 2 files changed, 92 insertions(+), 58 deletions(-) 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/po/vips7.pot b/po/vips7.pot index c3b6e0e4..0bdff591 100644 --- a/po/vips7.pot +++ b/po/vips7.pot @@ -9,7 +9,7 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=glib&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-04-17 11:25+0100\n" +"POT-Creation-Date: 2012-06-03 12:36+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -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 "" @@ -1053,7 +1053,7 @@ msgstr "" msgid "invalid markup in text" msgstr "" -#: ../libvips/conversion/im_text.c:252 +#: ../libvips/conversion/im_text.c:251 msgid "pangoft2 support disabled" msgstr "" @@ -1167,39 +1167,39 @@ msgstr "" msgid "How to generate the extra pixels" msgstr "" -#: ../libvips/conversion/ifthenelse.c:395 +#: ../libvips/conversion/ifthenelse.c:468 msgid "ifthenelse an image" msgstr "" -#: ../libvips/conversion/ifthenelse.c:399 +#: ../libvips/conversion/ifthenelse.c:472 msgid "Condition" msgstr "" -#: ../libvips/conversion/ifthenelse.c:400 +#: ../libvips/conversion/ifthenelse.c:473 msgid "Condition input image" msgstr "" -#: ../libvips/conversion/ifthenelse.c:405 +#: ../libvips/conversion/ifthenelse.c:478 msgid "Then image" msgstr "" -#: ../libvips/conversion/ifthenelse.c:406 +#: ../libvips/conversion/ifthenelse.c:479 msgid "Source for TRUE pixels" msgstr "" -#: ../libvips/conversion/ifthenelse.c:411 +#: ../libvips/conversion/ifthenelse.c:484 msgid "Else image" msgstr "" -#: ../libvips/conversion/ifthenelse.c:412 +#: ../libvips/conversion/ifthenelse.c:485 msgid "Source for FALSE pixels" msgstr "" -#: ../libvips/conversion/ifthenelse.c:417 +#: ../libvips/conversion/ifthenelse.c:490 msgid "blend" msgstr "" -#: ../libvips/conversion/ifthenelse.c:418 +#: ../libvips/conversion/ifthenelse.c:491 msgid "Blend smoothly between then and else parts" 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 "" From 1ee48e4cd62b2b2e6253a163b103db8c9d605410 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Wed, 6 Jun 2012 19:33:11 +0100 Subject: [PATCH 5/6] add nocache flag, use for sequential file ops stop it caching sequential file read (eg. sequential tiff read), since you can only read sequentially once --- ChangeLog | 1 + libvips/foreign/foreign.c | 4 ++++ libvips/include/vips/operation.h | 7 +++++++ libvips/iofuncs/cache.c | 15 +++++++++++---- libvips/iofuncs/operation.c | 20 ++++++++++++++++++++ 5 files changed, 43 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 66890d73..ea7ad00f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,7 @@ - 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) 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 c8710ac9..28ce048c 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() ); } 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 df7b757b..ee7d458b 100644 --- a/libvips/iofuncs/operation.c +++ b/libvips/iofuncs/operation.c @@ -946,3 +946,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; +} From 75a68100bd131a232df7130f4d927e7f664a108f Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 7 Jun 2012 13:54:05 +0100 Subject: [PATCH 6/6] fix a crash in the tiff reader some tiffs have HUGE values for RowsPerStrip ... clip these down to avoid confusing later bits of vips also, a better error msg for non-contig images --- ChangeLog | 2 ++ libvips/foreign/foreign.c | 2 ++ libvips/foreign/tiff2vips.c | 71 +++++++++++++++++++++---------------- 3 files changed, 44 insertions(+), 31 deletions(-) diff --git a/ChangeLog b/ChangeLog index ea7ad00f..e0b69c17 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,8 @@ - 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 28ce048c..6b5eceed 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -931,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 ) { diff --git a/libvips/foreign/tiff2vips.c b/libvips/foreign/tiff2vips.c index 63c00c26..41acde1a 100644 --- a/libvips/foreign/tiff2vips.c +++ b/libvips/foreign/tiff2vips.c @@ -131,6 +131,10 @@ * 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 */ /* @@ -253,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 @@ -307,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 ); } @@ -900,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. */ @@ -1347,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++ ) { @@ -1398,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 );