diff --git a/ChangeLog b/ChangeLog index 76eb4d15..4227fac9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -35,6 +35,7 @@ - redone im_affine*() as a class - added input space displacement to affine - VipsArea is threadsafe +- dzsave has a --centre option 31/12/12 started 7.30.7 - better option parsing for "vips", thanks Haida diff --git a/libvips/foreign/dzsave.c b/libvips/foreign/dzsave.c index 8c692789..893bce56 100644 --- a/libvips/foreign/dzsave.c +++ b/libvips/foreign/dzsave.c @@ -28,6 +28,8 @@ * - add @background option * 1/11/12 * - add @depth option + * 21/1/13 + * - add @centre option */ /* @@ -135,8 +137,9 @@ struct _VipsForeignSaveDz { int overlap; int tile_size; VipsForeignDzLayout layout; - VipsArea *background; + VipsArrayDouble *background; VipsForeignDzDepth depth; + gboolean centre; Layer *layer; /* x2 shrink pyr layer */ @@ -367,18 +370,39 @@ static int write_blank( VipsForeignSaveDz *dz ) { char buf[PATH_MAX]; - VipsImage *black; + VipsImage *x, *t; + int n; + VipsArea *ones; + double *d; + int i; vips_snprintf( buf, PATH_MAX, "%s/blank.png", dz->basename ); - if( vips_black( &black, dz->tile_size, dz->tile_size, - "bands", 3, - NULL ) ) + if( vips_black( &x, dz->tile_size, dz->tile_size, NULL ) ) return( -1 ); - if( vips_image_write_to_file( black, buf ) ) { - g_object_unref( black ); + + vips_area_get_data( (VipsArea *) dz->background, NULL, &n, NULL, NULL ); + ones = vips_area_new_array( G_TYPE_DOUBLE, sizeof( double ), n ); + d = (double *) vips_area_get_data( ones, NULL, NULL, NULL, NULL ); + for( i = 0; i < n; i++ ) + d[i] = 1.0; + if( vips_linear( x, &t, + d, + (double *) vips_area_get_data( (VipsArea *) dz->background, + NULL, NULL, NULL, NULL ), + n, NULL ) ) { + vips_area_unref( ones ); + g_object_unref( x ); return( -1 ); } - g_object_unref( black ); + vips_area_unref( ones ); + g_object_unref( x ); + x = t; + + if( vips_image_write_to_file( x, buf ) ) { + g_object_unref( x ); + return( -1 ); + } + g_object_unref( x ); return( 0 ); } @@ -708,8 +732,9 @@ strip_work( VipsThreadState *state, void *a ) Layer *layer = strip->layer; VipsForeignSaveDz *dz = layer->dz; - VipsImage *x; char buf[PATH_MAX]; + VipsImage *x; + VipsImage *t; #ifdef DEBUG printf( "strip_work\n" ); @@ -731,9 +756,7 @@ strip_work( VipsThreadState *state, void *a ) /* Google tiles need to be padded up to tilesize. */ if( dz->layout == VIPS_FOREIGN_DZ_LAYOUT_GOOGLE ) { - VipsImage *z; - - if( vips_embed( x, &z, 0, 0, dz->tile_size, dz->tile_size, + if( vips_embed( x, &t, 0, 0, dz->tile_size, dz->tile_size, "background", dz->background, NULL ) ) { g_object_unref( x ); @@ -741,7 +764,35 @@ strip_work( VipsThreadState *state, void *a ) } g_object_unref( x ); - x = z; + x = t; + } + + /* If we are centreing we may have a tile which is entirely blank. + * Skip the write in this case, the viewer will use blank.png instead. + */ + if( dz->centre ) { + double *d; + int n; + double m; + + d = (double *) vips_area_get_data( (VipsArea *) dz->background, + NULL, &n, NULL, NULL ); + if( vips_equal_const( x, &t, d, n, NULL ) ) { + g_object_unref( x ); + return( -1 ); + } + + if( vips_min( t, &m, NULL ) ) { + g_object_unref( x ); + g_object_unref( t ); + return( -1 ); + } + g_object_unref( t ); + + if( m == 255 ) { + g_object_unref( x ); + return( 0 ); + } } #ifdef DEBUG @@ -1091,6 +1142,45 @@ vips_foreign_save_dz_build( VipsObject *object ) build( object ) ) return( -1 ); + /* For centred images, imagine shrinking so that the image fits in a + * single tile, centering in that tile, then expanding back again. + */ + if( dz->layout == VIPS_FOREIGN_DZ_LAYOUT_GOOGLE && + dz->centre ) { + VipsImage *z; + Layer *layer; + int n_layers; + int size; + + if( !(layer = pyramid_build( dz, + NULL, save->ready->Xsize, save->ready->Ysize )) ) + return( -1 ); + n_layers = layer->n; + /* This would cause interesting problems. + */ + g_assert( n_layers < 30 ); + layer_free( layer ); + size = dz->tile_size * (1 << n_layers); + + if( vips_embed( save->ready, &z, + (size - save->ready->Xsize) / 2, + (size - save->ready->Ysize) / 2, + size, size, + "background", dz->background, + NULL ) ) + return( -1 ); + + VIPS_UNREF( save->ready ); + save->ready = z; + + +#ifdef DEBUG + printf( "centre: centreing within a %d x %d image\n", + size, size ); +#endif + + } + /* Build the skeleton of the image pyramid. */ if( !(dz->layer = pyramid_build( dz, @@ -1219,6 +1309,13 @@ vips_foreign_save_dz_class_init( VipsForeignSaveDzClass *class ) VIPS_TYPE_FOREIGN_DZ_DEPTH, VIPS_FOREIGN_DZ_DEPTH_1PIXEL ); + VIPS_ARG_BOOL( class, "centre", 13, + _( "Center" ), + _( "Center image in tile" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsForeignSaveDz, centre ), + FALSE ); + /* How annoying. We stupidly had these in earlier versions. */ @@ -1270,6 +1367,7 @@ vips_foreign_save_dz_init( VipsForeignSaveDz *dz ) * @tile_size; set tile size * @background: background colour * @depth: how deep to make the pyramid + * @centre: centre the tiles * * Save an image as a set of tiles at various resolutions. By default dzsave * uses DeepZoom layout -- use @layout to pick other conventions. @@ -1286,7 +1384,8 @@ vips_foreign_save_dz_init( VipsForeignSaveDz *dz ) * * In Google layout mode, edge tiles are expanded to @tile_size by @tile_size * pixels. Normally they are filled with white, but you can set another colour - * with @background. + * with @background. Images are usually placed at the top-left of the tile, + * but you can have them centred by turning on @centre. * * You can set the size and overlap of tiles with @tile_size and @overlap. * They default to the correct settings for the selected @layout. diff --git a/po/vips7.pot b/po/vips7.pot index d02f828e..5b06d578 100644 --- a/po/vips7.pot +++ b/po/vips7.pot @@ -7,8 +7,9 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-01-15 14:43+0000\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=glib&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2013-01-17 13:26+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -186,7 +187,7 @@ msgstr "" #: ../libvips/conversion/rot.c:359 ../libvips/conversion/replicate.c:196 #: ../libvips/conversion/tilecache.c:424 ../libvips/conversion/embed.c:550 #: ../libvips/conversion/cache.c:100 ../libvips/conversion/recomb.c:204 -#: ../libvips/conversion/sequential.c:289 ../libvips/foreign/foreign.c:1357 +#: ../libvips/conversion/sequential.c:303 ../libvips/foreign/foreign.c:1357 #: ../libvips/resample/resample.c:89 msgid "Input" msgstr "" @@ -389,7 +390,7 @@ msgstr "" #: ../libvips/conversion/extract.c:360 ../libvips/conversion/copy.c:322 #: ../libvips/conversion/rot.c:360 ../libvips/conversion/replicate.c:197 #: ../libvips/conversion/tilecache.c:425 ../libvips/conversion/embed.c:551 -#: ../libvips/conversion/cache.c:101 ../libvips/conversion/sequential.c:290 +#: ../libvips/conversion/cache.c:101 ../libvips/conversion/sequential.c:304 msgid "Input image" msgstr "" @@ -643,7 +644,7 @@ msgid "Filename to load output profile from" msgstr "" #: ../libvips/colour/icc_transform.c:723 ../libvips/colour/icc_transform.c:909 -#: ../libvips/colour/scRGB2sRGB.c:191 ../libvips/foreign/dzsave.c:1204 +#: ../libvips/colour/scRGB2sRGB.c:191 ../libvips/foreign/dzsave.c:1215 msgid "Depth" msgstr "" @@ -739,7 +740,7 @@ msgstr "" #: ../libvips/conversion/flatten.c:382 ../libvips/conversion/join.c:266 #: ../libvips/conversion/insert.c:393 ../libvips/conversion/embed.c:591 -#: ../libvips/foreign/dzsave.c:1197 +#: ../libvips/foreign/dzsave.c:1208 msgid "Background" msgstr "" @@ -1059,14 +1060,14 @@ msgid "cache an image" msgstr "" #: ../libvips/conversion/tilecache.c:430 ../libvips/conversion/cache.c:113 -#: ../libvips/conversion/sequential.c:302 ../libvips/foreign/tiffsave.c:222 -#: ../libvips/foreign/dzsave.c:1229 +#: ../libvips/conversion/sequential.c:316 ../libvips/foreign/tiffsave.c:222 +#: ../libvips/foreign/dzsave.c:1240 msgid "Tile height" msgstr "" #: ../libvips/conversion/tilecache.c:431 ../libvips/conversion/cache.c:114 -#: ../libvips/conversion/sequential.c:303 ../libvips/foreign/tiffsave.c:223 -#: ../libvips/foreign/dzsave.c:1230 +#: ../libvips/conversion/sequential.c:317 ../libvips/foreign/tiffsave.c:223 +#: ../libvips/foreign/dzsave.c:1241 msgid "Tile height in pixels" msgstr "" @@ -1091,12 +1092,12 @@ msgid "cache an image as a set of tiles" msgstr "" #: ../libvips/conversion/tilecache.c:732 ../libvips/conversion/cache.c:106 -#: ../libvips/foreign/tiffsave.c:215 ../libvips/foreign/dzsave.c:1222 +#: ../libvips/foreign/tiffsave.c:215 ../libvips/foreign/dzsave.c:1233 msgid "Tile width" msgstr "" #: ../libvips/conversion/tilecache.c:733 ../libvips/conversion/cache.c:107 -#: ../libvips/foreign/tiffsave.c:216 ../libvips/foreign/dzsave.c:1223 +#: ../libvips/foreign/tiffsave.c:216 ../libvips/foreign/dzsave.c:1234 msgid "Tile width in pixels" msgstr "" @@ -1141,7 +1142,7 @@ msgstr "" msgid "How to generate the extra pixels" msgstr "" -#: ../libvips/conversion/embed.c:592 ../libvips/foreign/dzsave.c:1198 +#: ../libvips/conversion/embed.c:592 ../libvips/foreign/dzsave.c:1209 msgid "Colour for background pixels" msgstr "" @@ -1197,15 +1198,15 @@ msgstr "" msgid "matrix of coefficients" msgstr "" -#: ../libvips/conversion/sequential.c:285 +#: ../libvips/conversion/sequential.c:299 msgid "check sequential access" msgstr "" -#: ../libvips/conversion/sequential.c:295 +#: ../libvips/conversion/sequential.c:309 msgid "trace" msgstr "" -#: ../libvips/conversion/sequential.c:296 +#: ../libvips/conversion/sequential.c:310 msgid "trace pixel requests" msgstr "" @@ -1494,55 +1495,55 @@ msgstr "" msgid "Directory \"%s\" exists" msgstr "" -#: ../libvips/foreign/dzsave.c:1063 +#: ../libvips/foreign/dzsave.c:1074 msgid "overlap must be less than tile width and height" msgstr "" -#: ../libvips/foreign/dzsave.c:1151 +#: ../libvips/foreign/dzsave.c:1162 msgid "save image to deep zoom format" msgstr "" -#: ../libvips/foreign/dzsave.c:1161 ../libvips/foreign/dzsave.c:1215 +#: ../libvips/foreign/dzsave.c:1172 ../libvips/foreign/dzsave.c:1226 msgid "Base name" msgstr "" -#: ../libvips/foreign/dzsave.c:1162 ../libvips/foreign/dzsave.c:1216 +#: ../libvips/foreign/dzsave.c:1173 ../libvips/foreign/dzsave.c:1227 msgid "Base name to save to" msgstr "" -#: ../libvips/foreign/dzsave.c:1168 +#: ../libvips/foreign/dzsave.c:1179 msgid "Layout" msgstr "" -#: ../libvips/foreign/dzsave.c:1169 +#: ../libvips/foreign/dzsave.c:1180 msgid "Directory layout" msgstr "" -#: ../libvips/foreign/dzsave.c:1176 +#: ../libvips/foreign/dzsave.c:1187 msgid "suffix" msgstr "" -#: ../libvips/foreign/dzsave.c:1177 +#: ../libvips/foreign/dzsave.c:1188 msgid "Filename suffix for tiles" msgstr "" -#: ../libvips/foreign/dzsave.c:1183 +#: ../libvips/foreign/dzsave.c:1194 msgid "Overlap" msgstr "" -#: ../libvips/foreign/dzsave.c:1184 +#: ../libvips/foreign/dzsave.c:1195 msgid "Tile overlap in pixels" msgstr "" -#: ../libvips/foreign/dzsave.c:1190 +#: ../libvips/foreign/dzsave.c:1201 msgid "Tile size" msgstr "" -#: ../libvips/foreign/dzsave.c:1191 +#: ../libvips/foreign/dzsave.c:1202 msgid "Tile size in pixels" msgstr "" -#: ../libvips/foreign/dzsave.c:1205 +#: ../libvips/foreign/dzsave.c:1216 msgid "Pyramid depth" msgstr "" @@ -2818,13 +2819,13 @@ msgstr "" msgid "TB" msgstr "" -#: ../libvips/iofuncs/base64.c:170 +#: ../libvips/iofuncs/base64.c:168 msgid "too little data" msgstr "" #. We shouldn't really be used for large amounts of data. #. -#: ../libvips/iofuncs/base64.c:176 ../libvips/iofuncs/base64.c:241 +#: ../libvips/iofuncs/base64.c:174 ../libvips/iofuncs/base64.c:239 msgid "too much data" msgstr "" @@ -3029,16 +3030,16 @@ msgstr "" msgid "extra tokens after ')'" msgstr "" -#: ../libvips/iofuncs/threadpool.c:197 +#: ../libvips/iofuncs/threadpool.c:178 msgid "unable to create thread" msgstr "" -#: ../libvips/iofuncs/threadpool.c:330 +#: ../libvips/iofuncs/threadpool.c:311 #, c-format msgid "threads clipped to %d" msgstr "" -#: ../libvips/iofuncs/threadpool.c:394 +#: ../libvips/iofuncs/threadpool.c:375 msgid "per-thread state for vipsthreadpool" msgstr "" @@ -3665,7 +3666,7 @@ msgstr "" msgid "B-Splines with antialiasing smoothing" msgstr "" -#: ../libvips/resample/nohalo.cpp:1576 +#: ../libvips/resample/nohalo.cpp:1580 msgid "Edge sharpening resampler with halo reduction" msgstr ""