diff --git a/TODO b/TODO
index 468b151b..e8841b03 100644
--- a/TODO
+++ b/TODO
@@ -1,47 +1,124 @@
-- added expat to required packages in configure.ac
+- remove libxml from configure.ac
+
+ we don't escape " inside xml attr strings, or < > inside xml content
- try moving iofuncs/vips.c to expat
+ break Buffer out into a separate class that does this? VipsDbuf, for dynamic
+ buffer? or can it be a mode for VipsBuf?
- sample XML for us to parse
+ buffer should expand by 30% on each fill to avoid lots of tiny realloc
- $ vipsheader -f getext babe.v
-
-
-
-
- jpegload
- 0
- 4294966289/169093161 (25.399999998, Rational, 1 components, 8 bytes)
- 4294966289/169093161 (25.399999998, Rational, 1 components, 8 bytes)
- 2 (Inch, Short, 1 components, 2 bytes)
- Exif Version 2.1 (Exif Version 2.1, Undefined, 4 components, 4 bytes)
- FlashPix Version 1.0 (FlashPix Version 1.0, Undefined, 4 components, 4 bytes)
- 65535 (Internal error (unknown value 65535), Short, 1 components, 2 bytes)
- in
- RXhpZgAATU0AKgAAAAgABAEaAAUAAAABAAAAPgEbAAUAAAABAAAARgEoAAMAAAABAAIAAIdpAAQA
- AAABAAAATgAAAAD///wRChQoKf///BEKFCgpAAOQAAAHAAAABDAyMTCgAAAHAAAABDAxMDCgAQAD
- AAAAAf//AAAAAAAA
-
-
-
+ use for tiffsave_buffer etc.
- currently works like this
+ have things like write-escaped-string as extra append operations
- read_xml is called on image load
- - loads extension bytes into memory
- - calls libxml to parse it to an xmlDoc
- - saves xmlDoc to VIPS_META_XML in header
+ need one that escapes ", a separate one that escapes < >
- rebuild_header called next
- - gets xmlDoc from header
- - gets "header" node
- calls rebuild_header_builtin() for every field node
- - gets "meta" field
- calls rebuild_header_meta() for every field node
+- dzsave vips.properties is currently
+
+
+
+
+ width
+ 1450
+
+
+ height
+ 2048
+
+
+ bands
+ 3
+
+
+ xoffset
+ 0
+
+
+ yoffset
+ 0
+
+
+ xres
+ 0.99999999990686772
+
+
+ yres
+ 0.99999999990686772
+
+
+ vips-loader
+ jpegload
+
+
+ jpeg-multiscan
+ 0
+
+
+ exif-data
+
+RXhpZgAASUkqAAgAAAAGABIBAwABAAAAAQAAABoBBQABAAAAVgAAABsBBQABAAAAXgAAACgBAwAB
+AAAAAgAAABMCAwABAAAAAQAAAGmHBAABAAAAZgAAAAAAAAAR/P//KSgUChH8//8pKBQKBgAAkAcA
+BAAAADAyMTABkQcABAAAAAECAwAAoAcABAAAADAxMDABoAMAAQAAAP//AAACoAQAAQAAAKoFAAAD
+oAQAAQAAAAAIAAAAAAAA
+
+
+
+ resolution-unit
+ in
+
+
+ exif-ifd0-Orientation
+ 1 (Top-left, Short, 1 components, 2 bytes)
+
+
+ exif-ifd0-XResolution
+ 4294966289/169093161 (25.399999998, Rational, 1 components, 8 bytes)
+
+
+ exif-ifd0-YResolution
+ 4294966289/169093161 (25.399999998, Rational, 1 components, 8 bytes)
+
+
+ exif-ifd0-ResolutionUnit
+ 2 (Inch, Short, 1 components, 2 bytes)
+
+
+ exif-ifd0-YCbCrPositioning
+ 1 (Centred, Short, 1 components, 2 bytes)
+
+
+ exif-ifd2-ExifVersion
+ Exif Version 2.1 (Exif Version 2.1, Undefined, 4 components, 4 bytes)
+
+
+ exif-ifd2-ComponentsConfiguration
+ Y Cb Cr - (Y Cb Cr -, Undefined, 4 components, 4 bytes)
+
+
+ exif-ifd2-FlashPixVersion
+ FlashPix Version 1.0 (FlashPix Version 1.0, Undefined, 4 components, 4 bytes)
+
+
+ exif-ifd2-ColorSpace
+ 65535 (Internal error (unknown value 65535), Short, 1 components, 2 bytes)
+
+
+ exif-ifd2-PixelXDimension
+ 1450 (1450, Long, 1 components, 4 bytes)
+
+
+ exif-ifd2-PixelYDimension
+ 2048 (2048, Long, 1 components, 4 bytes)
+
+
+ orientation
+ 1
+
+
+
+
- vips linecache has access there twice!
diff --git a/configure.ac b/configure.ac
index b7a7cd8c..d81fd6bd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -348,9 +348,8 @@ AC_CHECK_LIB(m,atan2,[AC_DEFINE(HAVE_ATAN2,1,[have atan2() in libm.])])
# have to have these
# need glib 2.6 for GOption
-PKG_CHECK_MODULES(REQUIRED, glib-2.0 >= 2.6 gmodule-2.0 gobject-2.0
- libxml-2.0 expat)
-PACKAGES_USED="$PACKAGES_USED glib-2.0 gmodule-2.0 gobject-2.0 libxml-2.0 expat"
+PKG_CHECK_MODULES(REQUIRED, glib-2.0 >= 2.6 gmodule-2.0 gobject-2.0 expat)
+PACKAGES_USED="$PACKAGES_USED glib-2.0 gmodule-2.0 gobject-2.0 expat"
# after 2.28 we have a monotonic timer
PKG_CHECK_MODULES(MONOTONIC, glib-2.0 >= 2.28,
diff --git a/libvips/foreign/dzsave.c b/libvips/foreign/dzsave.c
index 46696af2..4beeeb31 100644
--- a/libvips/foreign/dzsave.c
+++ b/libvips/foreign/dzsave.c
@@ -152,144 +152,9 @@
#include
#include
-#include
-
#include
#include
-/* Track this during property save.
- */
-typedef struct _WriteInfo {
- const char *domain;
- VipsImage *image;
- xmlNode *node;
-} WriteInfo;
-
-static int
-set_prop( WriteInfo *info,
- xmlNode *node, const char *name, const char *fmt, ... )
-{
- 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( info->domain,
- _( "unable to set property \"%s\" to value \"%s\"." ),
- name, value );
- return( -1 );
- }
-
- return( 0 );
-}
-
-static xmlNode *
-new_child( WriteInfo *info, xmlNode *parent, const char *name )
-{
- xmlNode *child;
-
- if( !(child = xmlNewChild( parent, NULL, (xmlChar *) name, NULL )) ) {
- vips_error( info->domain,
- _( "unable to set create node \"%s\"" ), name );
- return( NULL );
- }
-
- return( child );
-}
-
-static void *
-write_vips_property( VipsImage *image,
- const char *field, GValue *value, void *a )
-{
- WriteInfo *info = (WriteInfo *) a;
- 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 );
- if( !g_value_transform( value, &save_value ) )
- return( image );
-
- if( !(property = new_child( info, info->node, "property" )) )
- return( image );
-
- if( !(child = new_child( info, property, "name" )) )
- return( image );
- xmlNodeSetContent( child, (xmlChar *) field );
-
- if( !(child = new_child( info, property, "value" )) ||
- set_prop( info, child, "type", g_type_name( type ) ) )
- return( image );
- xmlNodeSetContent( child,
- (xmlChar *) vips_value_get_save_string( &save_value ) );
- }
-
- return( NULL );
-}
-
-/* Pack up all the metadata from an image as XML. This called from vips2tiff
- * as well.
- *
- * Free the result with xmlFree().
- */
-char *
-vips__make_xml_metadata( const char *domain, VipsImage *image )
-{
- xmlDoc *doc;
- GTimeVal now;
- char *date;
- WriteInfo info;
- char *dump;
- int dump_size;
-
- if( !(doc = xmlNewDoc( (xmlChar *) "1.0" )) ) {
- vips_error( domain, "%s", _( "xml save error" ) );
- return( NULL );
- }
- if( !(doc->children = xmlNewDocNode( doc, NULL,
- (xmlChar *) "image", NULL )) ) {
- vips_error( domain, "%s", _( "xml save error" ) );
- xmlFreeDoc( doc );
- return( NULL );
- }
-
- info.domain = domain;
- info.image = image;
- g_get_current_time( &now );
- date = g_time_val_to_iso8601( &now );
- if( set_prop( &info, doc->children, "xmlns",
- "http://www.vips.ecs.soton.ac.uk/dzsave" ) ||
- set_prop( &info, doc->children, "date", date ) ||
- set_prop( &info, doc->children, "version", VIPS_VERSION ) ) {
- g_free( date );
- xmlFreeDoc( doc );
- return( NULL );
- }
- g_free( date );
-
- if( !(info.node = new_child( &info, doc->children, "properties" )) ||
- vips_image_map( image, write_vips_property, &info ) ) {
- xmlFreeDoc( doc );
- return( NULL );
- }
-
- xmlDocDumpFormatMemory( doc, (xmlChar **) &dump, &dump_size, 1 );
- if( !dump ) {
- vips_error( domain, "%s", _( "xml save error" ) );
- xmlFreeDoc( doc );
- return( NULL );
- }
- xmlFreeDoc( doc );
-
- return( dump );
-}
-
#ifdef HAVE_GSF
#include
@@ -980,12 +845,11 @@ static int
write_vips_meta( VipsForeignSaveDz *dz )
{
VipsForeignSave *save = (VipsForeignSave *) dz;
- VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( dz );
char *dump;
GsfOutput *out;
- if( !(dump = vips__make_xml_metadata( class->nickname, save->ready )) )
+ if( !(dump = vips__xml_properties( save->ready )) )
return( -1 );
/* For deepzom the props must go inside the ${name}_files subdir, for
@@ -1001,7 +865,7 @@ write_vips_meta( VipsForeignSaveDz *dz )
(void) gsf_output_close( out );
g_object_unref( out );
- xmlFree( dump );
+ g_free( dump );
return( 0 );
}
diff --git a/libvips/foreign/tiff.c b/libvips/foreign/tiff.c
index dd9bdcd2..b083adc2 100644
--- a/libvips/foreign/tiff.c
+++ b/libvips/foreign/tiff.c
@@ -48,7 +48,6 @@
#include
#endif /*HAVE_UNISTD_H*/
#include
-#include
#include
#include
diff --git a/libvips/foreign/vips2tiff.c b/libvips/foreign/vips2tiff.c
index 8f344380..621e092a 100644
--- a/libvips/foreign/vips2tiff.c
+++ b/libvips/foreign/vips2tiff.c
@@ -218,7 +218,6 @@
#include
#endif /*HAVE_UNISTD_H*/
#include
-#include
#include
#include
@@ -512,10 +511,10 @@ wtiff_embed_imagedescription( Wtiff *wtiff, TIFF *tif )
if( wtiff->properties ) {
char *doc;
- if( !(doc = vips__make_xml_metadata( "vips2tiff", wtiff->im )) )
+ if( !(doc = vips__xml_properties( wtiff->im )) )
return( -1 );
TIFFSetField( tif, TIFFTAG_IMAGEDESCRIPTION, doc );
- xmlFree( doc );
+ g_free( doc );
}
else {
const char *imagedescription;
diff --git a/libvips/include/vips/internal.h b/libvips/include/vips/internal.h
index 8329cf87..858bd11a 100644
--- a/libvips/include/vips/internal.h
+++ b/libvips/include/vips/internal.h
@@ -227,7 +227,7 @@ int vips_check_bands_3ormore( const char *domain, VipsImage *im );
int vips__byteswap_bool( VipsImage *in, VipsImage **out, gboolean swap );
-char *vips__make_xml_metadata( const char *domain, VipsImage *image );
+char *vips__xml_properties( VipsImage *image );
void vips__cairo2rgba( guint32 *buf, int n );
diff --git a/libvips/iofuncs/vips.c b/libvips/iofuncs/vips.c
index 5244aa04..970be1ef 100644
--- a/libvips/iofuncs/vips.c
+++ b/libvips/iofuncs/vips.c
@@ -141,7 +141,7 @@
/* Our XML namespace.
*/
-#define NAMESPACE "http://www.vips.ecs.soton.ac.uk/vips"
+#define NAMESPACE_URI "http://www.vips.ecs.soton.ac.uk/"
/* Open for read for image files.
*/
@@ -595,7 +595,7 @@ parser_element_start_handler( void *user_data,
else if( strcmp( name, "root" ) == 0 ) {
for( p = atts; *p; p += 2 )
if( strcmp( p[0], "xmlns" ) == 0 &&
- !vips_isprefix( NAMESPACE, p[1] ) ) {
+ !vips_isprefix( NAMESPACE_URI "/vips", p[1] ) ) {
vips_error( "VipsImage", "%s",
_( "incorrect namespace in XML" ) );
vep->error = TRUE;
@@ -801,6 +801,8 @@ build_xml_meta( VipsMeta *meta, Buffer *buffer )
return( NULL );
}
+/* Make the xml we append to vips images after the pixel data.
+ */
static char *
build_xml( VipsImage *image )
{
@@ -810,8 +812,8 @@ build_xml( VipsImage *image )
buffer_init( &buffer );
buffer_appendf( &buffer, "\n" );
- buffer_appendf( &buffer, "\n",
- NAMESPACE,
+ buffer_appendf( &buffer, "\n",
+ NAMESPACE_URI,
VIPS_MAJOR_VERSION, VIPS_MINOR_VERSION, VIPS_MICRO_VERSION );
buffer_appendf( &buffer, " \n" );
@@ -836,6 +838,77 @@ build_xml( VipsImage *image )
return( buffer.data );
}
+static void *
+vips__xml_properties_meta( VipsImage *image,
+ const char *field, GValue *value, void *a )
+{
+ Buffer *buffer = (Buffer *) a;
+ GType type = G_VALUE_TYPE( value );
+
+ const char *str;
+
+ /* If we can transform to VIPS_TYPE_SAVE_STRING and back, we can save
+ * and restore.
+ */
+ if( g_value_type_transformable( type, VIPS_TYPE_SAVE_STRING ) &&
+ g_value_type_transformable( VIPS_TYPE_SAVE_STRING, type ) ) {
+ GValue save_value = { 0 };
+
+ g_value_init( &save_value, VIPS_TYPE_SAVE_STRING );
+ if( !g_value_transform( value, &save_value ) ) {
+ vips_error( "VipsImage", "%s",
+ _( "error transforming to save format" ) );
+ return( buffer );
+ }
+ str = vips_value_get_save_string( &save_value );
+ g_value_unset( &save_value );
+
+ buffer_appendf( buffer, " \n" );
+ buffer_appendf( buffer, " %s\n", field );
+ buffer_appendf( buffer, " ",
+ g_type_name( type ) );
+ buffer_append( buffer, str, strlen( str ) );
+ buffer_appendf( buffer, "\n" );
+ buffer_appendf( buffer, " \n" );
+ }
+
+ return( NULL );
+}
+
+/* Make the xml we write to vips-properties in dzsave, or to TIFF. A simple
+ * dump of all vips metadata. Free with g_free().
+ */
+char *
+vips__xml_properties( VipsImage *image )
+{
+ Buffer buffer;
+ GTimeVal now;
+ char *date;
+
+ buffer_init( &buffer );
+
+ g_get_current_time( &now );
+ date = g_time_val_to_iso8601( &now );
+ buffer_appendf( &buffer, "\n" );
+ buffer_appendf( &buffer, "\n",
+ NAMESPACE_URI,
+ date,
+ VIPS_MAJOR_VERSION, VIPS_MINOR_VERSION, VIPS_MICRO_VERSION );
+ g_free( date );
+ buffer_appendf( &buffer, " \n" );
+
+ if( vips_image_map( image, vips__xml_properties_meta, &buffer ) ) {
+ buffer_destroy( &buffer );
+ return( NULL );
+ }
+
+ buffer_appendf( &buffer, " \n" );
+ buffer_appendf( &buffer, "\n" );
+
+ return( buffer.data );
+}
+
/* Append XML to output fd.
*/
int
@@ -846,7 +919,7 @@ vips__writehist( VipsImage *image )
assert( image->dtype == VIPS_IMAGE_OPENOUT );
assert( image->fd != -1 );
- if( !(xml = build_xml( im )) )
+ if( !(xml = build_xml( image )) )
return( -1 );
if( vips__write_extension_block( image, xml, strlen( xml ) ) ) {