From e9a0acfa9b8c6edb9993e81e77cdadb9798a9166 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Wed, 25 Jun 2014 11:26:05 +0100 Subject: [PATCH 01/11] save openslide metadata to .dzi files see https://github.com/jcupitt/libvips/issues/137 todo: - save to zoomify ImageProperties.xml as well? - any other useful fields? --- libvips/foreign/dzsave.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/libvips/foreign/dzsave.c b/libvips/foreign/dzsave.c index 6b9ece9d..86194881 100644 --- a/libvips/foreign/dzsave.c +++ b/libvips/foreign/dzsave.c @@ -42,6 +42,9 @@ * 8/5/14 * - set Type on strips so we can convert for save correctly, thanks * philipgiuliani + * 25/6/14 + * - save openslide metadata to .dzi, see + * https://github.com/jcupitt/libvips/issues/137 */ /* @@ -591,9 +594,30 @@ pyramid_build( VipsForeignSaveDz *dz, Layer *above, return( layer ); } +static void * +write_dzi_field( VipsImage *image, const char *field, GValue *value, void *a ) +{ + GsfOutput *out = (GsfOutput *) a; + + if( vips_isprefix( "openslide.", field ) && + !vips_isprefix( "openslide.level", field ) ) { + char *str_value; + + str_value = g_strdup_value_contents( value ); + gsf_output_printf( out, " %s=\"%s\"\n", + field + 10, str_value ); + g_free( str_value ); + + } + + return( NULL ); +} + static int write_dzi( VipsForeignSaveDz *dz ) { + VipsForeignSave *save = (VipsForeignSave *) dz; + GsfOutput *out; char buf[VIPS_PATH_MAX]; char *p; @@ -616,6 +640,9 @@ write_dzi( VipsForeignSaveDz *dz ) gsf_output_printf( out, " Height=\"%d\"\n", dz->layer->height ); gsf_output_printf( out, " Width=\"%d\"\n", dz->layer->width ); gsf_output_printf( out, " />\n" ); + gsf_output_printf( out, " ready, write_dzi_field, out ); + gsf_output_printf( out, " />\n" ); gsf_output_printf( out, "\n" ); (void) gsf_output_close( out ); From 94f92fc0145fa18ae1cf4029a544f23169d1af01 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 26 Jun 2014 09:30:36 +0100 Subject: [PATCH 02/11] write props to a separate file and dump all vips props --- libvips/foreign/dzsave.c | 66 +++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 24 deletions(-) diff --git a/libvips/foreign/dzsave.c b/libvips/foreign/dzsave.c index 86194881..a322b92b 100644 --- a/libvips/foreign/dzsave.c +++ b/libvips/foreign/dzsave.c @@ -594,30 +594,9 @@ pyramid_build( VipsForeignSaveDz *dz, Layer *above, return( layer ); } -static void * -write_dzi_field( VipsImage *image, const char *field, GValue *value, void *a ) -{ - GsfOutput *out = (GsfOutput *) a; - - if( vips_isprefix( "openslide.", field ) && - !vips_isprefix( "openslide.level", field ) ) { - char *str_value; - - str_value = g_strdup_value_contents( value ); - gsf_output_printf( out, " %s=\"%s\"\n", - field + 10, str_value ); - g_free( str_value ); - - } - - return( NULL ); -} - static int write_dzi( VipsForeignSaveDz *dz ) { - VipsForeignSave *save = (VipsForeignSave *) dz; - GsfOutput *out; char buf[VIPS_PATH_MAX]; char *p; @@ -640,9 +619,6 @@ write_dzi( VipsForeignSaveDz *dz ) gsf_output_printf( out, " Height=\"%d\"\n", dz->layer->height ); gsf_output_printf( out, " Width=\"%d\"\n", dz->layer->width ); gsf_output_printf( out, " />\n" ); - gsf_output_printf( out, " ready, write_dzi_field, out ); - gsf_output_printf( out, " />\n" ); gsf_output_printf( out, "\n" ); (void) gsf_output_close( out ); @@ -722,6 +698,45 @@ write_blank( VipsForeignSaveDz *dz ) return( 0 ); } +static void * +write_vips_property( VipsImage *image, + const char *field, GValue *value, void *a ) +{ + GsfOutput *out = (GsfOutput *) a; + char *str_value; + + str_value = g_strdup_value_contents( value ); + gsf_output_printf( out, " %s\n", field ); + gsf_output_printf( out, " %s\n", str_value ); + g_free( str_value ); + + return( NULL ); +} + +static int +write_vips_properties( VipsForeignSaveDz *dz ) +{ + VipsForeignSave *save = (VipsForeignSave *) dz; + + GsfOutput *out; + + out = vips_gsf_path( dz->tree, + "vips-properties.xml", dz->root_name, NULL ); + + gsf_output_printf( out, + "\n" ); + gsf_output_printf( out, "\n" ); + gsf_output_printf( out, " \n" ); + (void) vips_image_map( save->ready, write_vips_property, out ); + gsf_output_printf( out, " \n" ); + gsf_output_printf( out, "\n" ); + + (void) gsf_output_close( out ); + g_object_unref( out ); + + return( 0 ); +} + /* Generate area @target in @to using pixels in @from. VIPS_CODING_LABQ only. */ static void @@ -1651,6 +1666,9 @@ vips_foreign_save_dz_build( VipsObject *object ) return( -1 ); } + if( write_vips_properties( dz ) ) + return( -1 ); + if( vips_gsf_tree_close( dz->tree ) ) return( -1 ); From 58bfb69b07e03c45b55a9f7e9a30d68311cd4d48 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 26 Jun 2014 10:54:07 +0100 Subject: [PATCH 03/11] wrap props in another element --- libvips/foreign/dzsave.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libvips/foreign/dzsave.c b/libvips/foreign/dzsave.c index a322b92b..b55cb1f7 100644 --- a/libvips/foreign/dzsave.c +++ b/libvips/foreign/dzsave.c @@ -706,8 +706,10 @@ write_vips_property( VipsImage *image, char *str_value; str_value = g_strdup_value_contents( value ); - gsf_output_printf( out, " %s\n", field ); - gsf_output_printf( out, " %s\n", str_value ); + gsf_output_printf( out, " \n" ); + gsf_output_printf( out, " %s\n", field ); + gsf_output_printf( out, " %s\n", str_value ); + gsf_output_printf( out, " \n" ); g_free( str_value ); return( NULL ); From d9ddf0287eaeb9a9d66ba7ade9bf8aa96f1f0d3d Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 26 Jun 2014 11:08:00 +0100 Subject: [PATCH 04/11] note date and version in dzprops --- libvips/foreign/dzsave.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/libvips/foreign/dzsave.c b/libvips/foreign/dzsave.c index b55cb1f7..6c362f42 100644 --- a/libvips/foreign/dzsave.c +++ b/libvips/foreign/dzsave.c @@ -720,15 +720,29 @@ write_vips_properties( VipsForeignSaveDz *dz ) { VipsForeignSave *save = (VipsForeignSave *) dz; + time_t timebuf; + char time_string[30]; GsfOutput *out; + time( &timebuf ); + ctime_r( &timebuf, time_string ); + + /* Remove the trailing \n. + */ + if( strlen( time_string ) > 0 && + time_string[strlen( time_string ) - 1] == '\n' ) + time_string[strlen( time_string ) - 1] = '\0'; + out = vips_gsf_path( dz->tree, "vips-properties.xml", dz->root_name, NULL ); gsf_output_printf( out, "\n" ); gsf_output_printf( out, "\n" ); - gsf_output_printf( out, " \n" ); + gsf_output_printf( out, " \n" ); (void) vips_image_map( save->ready, write_vips_property, out ); gsf_output_printf( out, " \n" ); gsf_output_printf( out, "\n" ); From 40e34664820290c47cdd71bc68f8bf734afba7fa Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 26 Jun 2014 17:18:24 +0100 Subject: [PATCH 05/11] fix a bash-ism in configure.ac helps freebsd --- ChangeLog | 3 +++ configure.ac | 22 +++++++++++++++++----- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 354b9f2b..b4b0d9a1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +26/6/14 started 7.40.2 +- fixes to help freebsd + 24/6/14 started 7.40.1 - revise man.1 pages - fix vips_guess_prefix() diff --git a/configure.ac b/configure.ac index ef6da63d..5e7a3e5c 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # also update the version number in the m4 macros below -AC_INIT([vips], [7.40.1], [vipsip@jiscmail.ac.uk]) +AC_INIT([vips], [7.40.2], [vipsip@jiscmail.ac.uk]) # required for gobject-introspection AC_PREREQ(2.62) @@ -18,7 +18,7 @@ AC_CONFIG_MACRO_DIR([m4]) # user-visible library versioning m4_define([vips_major_version], [7]) m4_define([vips_minor_version], [40]) -m4_define([vips_micro_version], [1]) +m4_define([vips_micro_version], [2]) m4_define([vips_version], [vips_major_version.vips_minor_version.vips_micro_version]) @@ -63,13 +63,25 @@ GOBJECT_INTROSPECTION_CHECK([1.30.0]) introspection_sources=$(cd libvips ; find . -name "*.c") filter_list="deprecated " +# contains(string, substring) +# +# Returns 0 if the specified string contains the specified substring, +# otherwise returns 1. +contains() { + string="$1" + substring="$2" + if test "${string#*$substring}" != "$string"; then + return 0 # $substring is in $string + else + return 1 # $substring is not in $string + fi +} + introspection_sources2= for name in $introspection_sources; do found=0 for filter in $filter_list; do - # FIXME .. argh a bash-ism :( not sure of a nice, portable way to do - # regexp matching - if [[[ $name == *${filter}* ]]]; then + if contains $name ${filter}; then found=1 fi done From c5fbe6daa642b522c54b6912b22649f59c8d237f Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Mon, 30 Jun 2014 12:58:57 +0100 Subject: [PATCH 06/11] more tweaks to dzsave props add docs too --- ChangeLog | 1 + libvips/foreign/dzsave.c | 48 ++++++++++++++++++++++++++-------------- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index 616a33c9..31f38483 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ 30/6/14 started 7.40.3 - fix interlaced thumbnails in vipsthumbnail, thanks lovell +- add --properties argument to dzsave, thanks bgilbert 25/6/14 started 7.40.2 - dzsave write to zip stops at 4gb, thanks bgilbert diff --git a/libvips/foreign/dzsave.c b/libvips/foreign/dzsave.c index e38c9a7a..a10fb8b8 100644 --- a/libvips/foreign/dzsave.c +++ b/libvips/foreign/dzsave.c @@ -44,7 +44,7 @@ * philipgiuliani * 25/6/14 * - stop on zip write >4gb, thanks bgilbert - * - save openslide metadata to .dzi, see + * - save metadata to .dzi, see * https://github.com/jcupitt/libvips/issues/137 */ @@ -391,6 +391,7 @@ struct _VipsForeignSaveDz { VipsArrayDouble *background; VipsForeignDzDepth depth; gboolean centre; + gboolean properties; VipsAngle angle; VipsForeignDzContainer container; @@ -727,29 +728,27 @@ write_vips_properties( VipsForeignSaveDz *dz ) { VipsForeignSave *save = (VipsForeignSave *) dz; - time_t timebuf; - char time_string[30]; + time_t now; + char time_string[50]; GsfOutput *out; - time( &timebuf ); - ctime_r( &timebuf, time_string ); - - /* Remove the trailing \n. - */ - if( strlen( time_string ) > 0 && - time_string[strlen( time_string ) - 1] == '\n' ) - time_string[strlen( time_string ) - 1] = '\0'; + time( &now ); + strftime( time_string, sizeof( time_string ), + "%FT%TZ", gmtime( &now ) ); out = vips_gsf_path( dz->tree, "vips-properties.xml", dz->root_name, NULL ); gsf_output_printf( out, "\n" ); - gsf_output_printf( out, "\n" ); - gsf_output_printf( out, " \n" ); + gsf_output_printf( out, " \n" ); (void) vips_image_map( save->ready, write_vips_property, out ); gsf_output_printf( out, " \n" ); gsf_output_printf( out, "\n" ); @@ -1714,7 +1713,8 @@ vips_foreign_save_dz_build( VipsObject *object ) return( -1 ); } - if( write_vips_properties( dz ) ) + if( dz->properties && + write_vips_properties( dz ) ) return( -1 ); if( vips_gsf_tree_close( dz->tree ) ) @@ -1869,6 +1869,13 @@ vips_foreign_save_dz_class_init( VipsForeignSaveDzClass *class ) VIPS_TYPE_FOREIGN_DZ_CONTAINER, VIPS_FOREIGN_DZ_CONTAINER_FS ); + VIPS_ARG_BOOL( class, "properties", 16, + _( "Properties" ), + _( "Write a properties file to the output directory" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsForeignSaveDz, properties ), + FALSE ); + /* How annoying. We stupidly had these in earlier versions. */ @@ -1934,16 +1941,17 @@ vips_foreign_save_dz_init( VipsForeignSaveDz *dz ) * @centre: centre the tiles * @angle: rotate the image by this much * @container: set container type + * @properties: write a properties file * * Save an image as a set of tiles at various resolutions. By default dzsave * uses DeepZoom layout -- use @layout to pick other conventions. * * vips_dzsave() creates a directory called @name to hold the tiles. If @name - * ends ".zip", vips_dzsave() will create a zip file called @name to hold the + * ends `.zip`, vips_dzsave() will create a zip file called @name to hold the * tiles. You can use @container to force zip file output. * - * You can set @suffix to something like ".jpg[Q=85]" to control the tile write - * options. + * You can set @suffix to something like `".jpg[Q=85]"` to control the tile + * write options. * * 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 @@ -1956,6 +1964,12 @@ vips_foreign_save_dz_init( VipsForeignSaveDz *dz ) * Use @depth to control how low the pyramid goes. This defaults to the * correct setting for the @layout you select. * + * If @properties is %TRUE, vips_dzsave() will write a file called + * `vips-properties.xml` to the output directory. This file lists all of the + * metadata attached to @in in an obvious manner. It can be useful for viewing + * programs which wish to use fields from source files loaded via + * vips_openslideload(). + * * See also: vips_tiffsave(). * * Returns: 0 on success, -1 on error. From 5d1fa07a4058738fa09f6902dcfe30784e5eb813 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Tue, 1 Jul 2014 09:26:10 +0100 Subject: [PATCH 07/11] more dzsave props tweaks * don't version xmlns * escape <> in field names and values * set a type on each value --- libvips/foreign/dzsave.c | 49 ++++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/libvips/foreign/dzsave.c b/libvips/foreign/dzsave.c index a10fb8b8..db817130 100644 --- a/libvips/foreign/dzsave.c +++ b/libvips/foreign/dzsave.c @@ -706,19 +706,49 @@ write_blank( VipsForeignSaveDz *dz ) return( 0 ); } +static void +print_escape( GsfOutput *out, const char *str ) +{ + const char *p; + + for( p = str; *p; p++ ) + switch( *p ) { + case '<': + gsf_output_printf( out, "<" ); + break; + case '>': + gsf_output_printf( out, ">" ); + break; + default: + gsf_output_printf( out, "%c", *p ); + break; + } +} + static void * write_vips_property( VipsImage *image, const char *field, GValue *value, void *a ) { GsfOutput *out = (GsfOutput *) a; - char *str_value; + GType type = G_VALUE_TYPE( value ); - str_value = g_strdup_value_contents( value ); - gsf_output_printf( out, " \n" ); - gsf_output_printf( out, " %s\n", field ); - gsf_output_printf( out, " %s\n", str_value ); - gsf_output_printf( out, " \n" ); - g_free( str_value ); + if( g_value_type_transformable( type, VIPS_TYPE_SAVE_STRING ) ) { + GValue save_value = { 0 }; + + g_value_init( &save_value, VIPS_TYPE_SAVE_STRING ); + g_value_transform( value, &save_value ); + + gsf_output_printf( out, " \n" ); + gsf_output_printf( out, " " ); + print_escape( out, field ); + gsf_output_printf( out, "\n" ); + gsf_output_printf( out, " ", + g_type_name( type ) ); + print_escape( out, vips_value_get_save_string( &save_value ) ); + gsf_output_printf( out, "\n" ); + gsf_output_printf( out, " \n" ); + g_value_unset( &save_value ); + } return( NULL ); } @@ -742,11 +772,10 @@ write_vips_properties( VipsForeignSaveDz *dz ) gsf_output_printf( out, "\n" ); gsf_output_printf( out, "\n" ); gsf_output_printf( out, " \n" ); (void) vips_image_map( save->ready, write_vips_property, out ); From 98e156301cbca45d0be0107993094807413ed10f Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Tue, 1 Jul 2014 12:07:31 +0100 Subject: [PATCH 08/11] use libxml2 to write props don't write xml ourselves, get libxml2 to do the encoding --- libvips/foreign/dzsave.c | 161 ++++++++++++++++++++++++++++----------- 1 file changed, 117 insertions(+), 44 deletions(-) diff --git a/libvips/foreign/dzsave.c b/libvips/foreign/dzsave.c index db817130..fa3229bd 100644 --- a/libvips/foreign/dzsave.c +++ b/libvips/foreign/dzsave.c @@ -44,8 +44,7 @@ * philipgiuliani * 25/6/14 * - stop on zip write >4gb, thanks bgilbert - * - save metadata to .dzi, see - * https://github.com/jcupitt/libvips/issues/137 + * - save metadata, see https://github.com/jcupitt/libvips/issues/137 */ /* @@ -706,85 +705,159 @@ write_blank( VipsForeignSaveDz *dz ) return( 0 ); } -static void -print_escape( GsfOutput *out, const char *str ) +static int +set_prop( VipsForeignSaveDz *dz, + xmlNode *node, const char *name, const char *fmt, ... ) { - const char *p; + VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( dz ); - for( p = str; *p; p++ ) - switch( *p ) { - case '<': - gsf_output_printf( out, "<" ); - break; - case '>': - gsf_output_printf( out, ">" ); - break; - default: - gsf_output_printf( out, "%c", *p ); - break; - } + va_list ap; + char value[1024]; + + va_start( ap, fmt ); + (void) vips_vsnprintf( value, 1024, fmt, ap ); + va_end( ap ); + + if( !xmlSetProp( node, (xmlChar *) name, (xmlChar *) value ) ) { + vips_error( class->nickname, + _( "unable to set property \"%s\" to value \"%s\"." ), + name, value ); + return( -1 ); + } + + return( 0 ); } +static xmlNode * +new_child( VipsForeignSaveDz *dz, xmlNode *parent, const char *name ) +{ + VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( dz ); + + xmlNode *child; + + if( !(child = xmlNewChild( parent, NULL, + (xmlChar *) name, NULL )) ) { + vips_error( class->nickname, + _( "unable to set create node \"%s\"" ), + name ); + return( NULL ); + } + + return( child ); +} + +/* Track this during a property save. + */ +typedef struct _WriteInfo { + VipsForeignSaveDz *dz; + xmlNode *node; +} WriteInfo; + static void * write_vips_property( VipsImage *image, const char *field, GValue *value, void *a ) { - GsfOutput *out = (GsfOutput *) a; + WriteInfo *info = (WriteInfo *) a; + VipsForeignSaveDz *dz = info->dz; GType type = G_VALUE_TYPE( value ); if( g_value_type_transformable( type, VIPS_TYPE_SAVE_STRING ) ) { GValue save_value = { 0 }; + xmlNode *property; + xmlNode *child; g_value_init( &save_value, VIPS_TYPE_SAVE_STRING ); g_value_transform( value, &save_value ); - gsf_output_printf( out, " \n" ); - gsf_output_printf( out, " " ); - print_escape( out, field ); - gsf_output_printf( out, "\n" ); - gsf_output_printf( out, " ", - g_type_name( type ) ); - print_escape( out, vips_value_get_save_string( &save_value ) ); - gsf_output_printf( out, "\n" ); - gsf_output_printf( out, " \n" ); - g_value_unset( &save_value ); + if( !(property = new_child( dz, info->node, "property" )) ) + return( image ); + + if( !(child = new_child( dz, property, "name" )) || + set_prop( dz, child, "type", g_type_name( type ) ) ) + return( image ); + xmlNodeSetContent( child, (xmlChar *) field ); + + if( !(child = new_child( dz, property, "value" )) ) + return( image ); + xmlNodeSetContent( child, + (xmlChar *) vips_value_get_save_string( &save_value ) ); } return( NULL ); } static int -write_vips_properties( VipsForeignSaveDz *dz ) +write_vips_properties( VipsForeignSaveDz *dz, xmlNode *node ) { VipsForeignSave *save = (VipsForeignSave *) dz; + xmlNode *this; + WriteInfo info; + + if( !(this = new_child( dz, node, "properties" )) ) + return( -1 ); + info.dz = dz; + info.node = this; + if( vips_image_map( save->ready, write_vips_property, &info ) ) + return( -1 ); + + return( 0 ); +} + +static int +write_vips_meta( VipsForeignSaveDz *dz ) +{ + VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( dz ); + time_t now; char time_string[50]; + xmlDoc *doc; + char *dump; + int dump_size; GsfOutput *out; time( &now ); strftime( time_string, sizeof( time_string ), "%FT%TZ", gmtime( &now ) ); + if( !(doc = xmlNewDoc( (xmlChar *) "1.0" )) ) { + vips_error( class->nickname, "%s", _( "xml save error" ) ); + return( -1 ); + } + if( !(doc->children = xmlNewDocNode( doc, NULL, + (xmlChar *) "image", NULL )) ) { + vips_error( class->nickname, "%s", _( "xml save error" ) ); + xmlFreeDoc( doc ); + return( -1 ); + } + if( set_prop( dz, doc->children, "xmlns", + "http://www.vips.ecs.soton.ac.uk/dzsave" ) || + set_prop( dz, doc->children, "date", time_string ) || + set_prop( dz, doc->children, "version", VIPS_VERSION ) || + write_vips_properties( dz, doc->children ) ) { + xmlFreeDoc( doc ); + return( -1 ); + } + + /* Double-cast stops a bogus gcc 4.1 compiler warning. + xmlDocDumpMemory( doc, (xmlChar **) ((char *) &dump), &dump_size ); + */ + xmlDocDumpMemory( doc, (xmlChar **) &dump, &dump_size ); + if( !dump ) { + vips_error( class->nickname, "%s", _( "xml save error" ) ); + xmlFreeDoc( doc ); + return( -1 ); + } + xmlFreeDoc( doc ); + out = vips_gsf_path( dz->tree, "vips-properties.xml", dz->root_name, NULL ); - - gsf_output_printf( out, - "\n" ); - gsf_output_printf( out, "\n" ); - gsf_output_printf( out, " \n" ); - (void) vips_image_map( save->ready, write_vips_property, out ); - gsf_output_printf( out, " \n" ); - gsf_output_printf( out, "\n" ); - + gsf_output_write( out, dump_size, (guchar *) dump ); (void) gsf_output_close( out ); g_object_unref( out ); + xmlFree( dump ); + return( 0 ); } @@ -1743,7 +1816,7 @@ vips_foreign_save_dz_build( VipsObject *object ) } if( dz->properties && - write_vips_properties( dz ) ) + write_vips_meta( dz ) ) return( -1 ); if( vips_gsf_tree_close( dz->tree ) ) From 3913ef5c89fce962b9d4162eb541a373c92a6bae Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Wed, 2 Jul 2014 09:01:26 +0100 Subject: [PATCH 09/11] pretty-print dzsave xml output --- libvips/foreign/dzsave.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/libvips/foreign/dzsave.c b/libvips/foreign/dzsave.c index fa3229bd..432beab1 100644 --- a/libvips/foreign/dzsave.c +++ b/libvips/foreign/dzsave.c @@ -839,10 +839,7 @@ write_vips_meta( VipsForeignSaveDz *dz ) return( -1 ); } - /* Double-cast stops a bogus gcc 4.1 compiler warning. - xmlDocDumpMemory( doc, (xmlChar **) ((char *) &dump), &dump_size ); - */ - xmlDocDumpMemory( doc, (xmlChar **) &dump, &dump_size ); + xmlDocDumpFormatMemory( doc, (xmlChar **) &dump, &dump_size, 1 ); if( !dump ) { vips_error( class->nickname, "%s", _( "xml save error" ) ); xmlFreeDoc( doc ); From 80f0b7cedd46e1ef02aca4748332404991b48e2a Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 3 Jul 2014 09:12:06 +0100 Subject: [PATCH 10/11] put type on the value, not the field name --- libvips/foreign/dzsave.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libvips/foreign/dzsave.c b/libvips/foreign/dzsave.c index 432beab1..65078e77 100644 --- a/libvips/foreign/dzsave.c +++ b/libvips/foreign/dzsave.c @@ -772,12 +772,12 @@ write_vips_property( VipsImage *image, if( !(property = new_child( dz, info->node, "property" )) ) return( image ); - if( !(child = new_child( dz, property, "name" )) || - set_prop( dz, child, "type", g_type_name( type ) ) ) + if( !(child = new_child( dz, property, "name" )) ) return( image ); xmlNodeSetContent( child, (xmlChar *) field ); - if( !(child = new_child( dz, property, "value" )) ) + if( !(child = new_child( dz, property, "value" )) || + set_prop( dz, child, "type", g_type_name( type ) ) ) return( image ); xmlNodeSetContent( child, (xmlChar *) vips_value_get_save_string( &save_value ) ); From f562dfdd5ba47fb7d12155edbaaebd68d89532fd Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 3 Jul 2014 09:13:01 +0100 Subject: [PATCH 11/11] oops --- ChangeLog | 5 ----- 1 file changed, 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9c805abc..31f38483 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,3 @@ -<<<<<<< HEAD -26/6/14 started 7.40.2 -- fixes to help freebsd -======= 30/6/14 started 7.40.3 - fix interlaced thumbnails in vipsthumbnail, thanks lovell - add --properties argument to dzsave, thanks bgilbert @@ -12,7 +8,6 @@ - added --enable-docs configure option to help freebsd - removed a bash-ism from configure to help freebsd - don't assume GType fits in an int to help freebsd ->>>>>>> c5fbe6daa642b522c54b6912b22649f59c8d237f 24/6/14 started 7.40.1 - revise man.1 pages