remove libxml from xml save
just some printfs now
This commit is contained in:
parent
e87654fcd9
commit
5614330cc4
149
TODO
149
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
|
||||
<?xml version="1.0"?>
|
||||
<root xmlns="http://www.vips.ecs.soton.ac.uk/vips/7.39.0">
|
||||
<header>
|
||||
<field type="VipsRefString" name="Hist"/>
|
||||
</header>
|
||||
<meta>
|
||||
<field type="VipsRefString" name="vips-loader">jpegload</field>
|
||||
<field type="gint" name="jpeg-multiscan">0</field>
|
||||
<field type="VipsRefString" name="exif-ifd0-X-Resolution">4294966289/169093161 (25.399999998, Rational, 1 components, 8 bytes)</field>
|
||||
<field type="VipsRefString" name="exif-ifd0-Y-Resolution">4294966289/169093161 (25.399999998, Rational, 1 components, 8 bytes)</field>
|
||||
<field type="VipsRefString" name="exif-ifd0-Resolution Unit">2 (Inch, Short, 1 components, 2 bytes)</field>
|
||||
<field type="VipsRefString" name="exif-ifd2-Exif Version">Exif Version 2.1 (Exif Version 2.1, Undefined, 4 components, 4 bytes)</field>
|
||||
<field type="VipsRefString" name="exif-ifd2-FlashPixVersion">FlashPix Version 1.0 (FlashPix Version 1.0, Undefined, 4 components, 4 bytes)</field>
|
||||
<field type="VipsRefString" name="exif-ifd2-Colour Space">65535 (Internal error (unknown value 65535), Short, 1 components, 2 bytes)</field>
|
||||
<field type="VipsRefString" name="resolution-unit">in</field><field type="VipsBlob" name="exif-data">
|
||||
RXhpZgAATU0AKgAAAAgABAEaAAUAAAABAAAAPgEbAAUAAAABAAAARgEoAAMAAAABAAIAAIdpAAQA
|
||||
AAABAAAATgAAAAD///wRChQoKf///BEKFCgpAAOQAAAHAAAABDAyMTCgAAAHAAAABDAxMDCgAQAD
|
||||
AAAAAf//AAAAAAAA
|
||||
</field>
|
||||
</meta>
|
||||
</root>
|
||||
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
|
||||
|
||||
|
||||
<?xml version="1.0"?>
|
||||
<image xmlns="http://www.vips.ecs.soton.ac.uk/dzsave" date="2017-02-25T17:32:07.565137Z" version="8.5.0">
|
||||
<properties>
|
||||
<property>
|
||||
<name>width</name>
|
||||
<value type="gint">1450</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>height</name>
|
||||
<value type="gint">2048</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>bands</name>
|
||||
<value type="gint">3</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>xoffset</name>
|
||||
<value type="gint">0</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>yoffset</name>
|
||||
<value type="gint">0</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>xres</name>
|
||||
<value type="gdouble">0.99999999990686772</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>yres</name>
|
||||
<value type="gdouble">0.99999999990686772</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>vips-loader</name>
|
||||
<value type="VipsRefString">jpegload</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>jpeg-multiscan</name>
|
||||
<value type="gint">0</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>exif-data</name>
|
||||
<value type="VipsBlob">
|
||||
RXhpZgAASUkqAAgAAAAGABIBAwABAAAAAQAAABoBBQABAAAAVgAAABsBBQABAAAAXgAAACgBAwAB
|
||||
AAAAAgAAABMCAwABAAAAAQAAAGmHBAABAAAAZgAAAAAAAAAR/P//KSgUChH8//8pKBQKBgAAkAcA
|
||||
BAAAADAyMTABkQcABAAAAAECAwAAoAcABAAAADAxMDABoAMAAQAAAP//AAACoAQAAQAAAKoFAAAD
|
||||
oAQAAQAAAAAIAAAAAAAA
|
||||
</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>resolution-unit</name>
|
||||
<value type="VipsRefString">in</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>exif-ifd0-Orientation</name>
|
||||
<value type="VipsRefString">1 (Top-left, Short, 1 components, 2 bytes)</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>exif-ifd0-XResolution</name>
|
||||
<value type="VipsRefString">4294966289/169093161 (25.399999998, Rational, 1 components, 8 bytes)</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>exif-ifd0-YResolution</name>
|
||||
<value type="VipsRefString">4294966289/169093161 (25.399999998, Rational, 1 components, 8 bytes)</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>exif-ifd0-ResolutionUnit</name>
|
||||
<value type="VipsRefString">2 (Inch, Short, 1 components, 2 bytes)</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>exif-ifd0-YCbCrPositioning</name>
|
||||
<value type="VipsRefString">1 (Centred, Short, 1 components, 2 bytes)</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>exif-ifd2-ExifVersion</name>
|
||||
<value type="VipsRefString">Exif Version 2.1 (Exif Version 2.1, Undefined, 4 components, 4 bytes)</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>exif-ifd2-ComponentsConfiguration</name>
|
||||
<value type="VipsRefString">Y Cb Cr - (Y Cb Cr -, Undefined, 4 components, 4 bytes)</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>exif-ifd2-FlashPixVersion</name>
|
||||
<value type="VipsRefString">FlashPix Version 1.0 (FlashPix Version 1.0, Undefined, 4 components, 4 bytes)</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>exif-ifd2-ColorSpace</name>
|
||||
<value type="VipsRefString">65535 (Internal error (unknown value 65535), Short, 1 components, 2 bytes)</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>exif-ifd2-PixelXDimension</name>
|
||||
<value type="VipsRefString">1450 (1450, Long, 1 components, 4 bytes)</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>exif-ifd2-PixelYDimension</name>
|
||||
<value type="VipsRefString">2048 (2048, Long, 1 components, 4 bytes)</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>orientation</name>
|
||||
<value type="gint">1</value>
|
||||
</property>
|
||||
</properties>
|
||||
</image>
|
||||
|
||||
|
||||
|
||||
- vips linecache has access there twice!
|
||||
|
@ -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,
|
||||
|
@ -152,144 +152,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <libxml/parser.h>
|
||||
|
||||
#include <vips/vips.h>
|
||||
#include <vips/internal.h>
|
||||
|
||||
/* 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 <gsf/gsf.h>
|
||||
@ -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 );
|
||||
}
|
||||
|
@ -48,7 +48,6 @@
|
||||
#include <unistd.h>
|
||||
#endif /*HAVE_UNISTD_H*/
|
||||
#include <string.h>
|
||||
#include <libxml/parser.h>
|
||||
|
||||
#include <vips/vips.h>
|
||||
#include <vips/internal.h>
|
||||
|
@ -218,7 +218,6 @@
|
||||
#include <unistd.h>
|
||||
#endif /*HAVE_UNISTD_H*/
|
||||
#include <string.h>
|
||||
#include <libxml/parser.h>
|
||||
|
||||
#include <vips/vips.h>
|
||||
#include <vips/internal.h>
|
||||
@ -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;
|
||||
|
@ -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 );
|
||||
|
||||
|
@ -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, "<?xml version=\"1.0\"?>\n" );
|
||||
buffer_appendf( &buffer, "<root xmlns=\"%s/%d.%d.%d\">\n",
|
||||
NAMESPACE,
|
||||
buffer_appendf( &buffer, "<root xmlns=\"%s/vips/%d.%d.%d\">\n",
|
||||
NAMESPACE_URI,
|
||||
VIPS_MAJOR_VERSION, VIPS_MINOR_VERSION, VIPS_MICRO_VERSION );
|
||||
buffer_appendf( &buffer, " <header>\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, " <property>\n" );
|
||||
buffer_appendf( buffer, " <name>%s</name>\n", field );
|
||||
buffer_appendf( buffer, " <value type=\"%s\">",
|
||||
g_type_name( type ) );
|
||||
buffer_append( buffer, str, strlen( str ) );
|
||||
buffer_appendf( buffer, "</value>\n" );
|
||||
buffer_appendf( buffer, " </property>\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, "<?xml version=\"1.0\"?>\n" );
|
||||
buffer_appendf( &buffer, "<image xmlns=\"%s/dzsave\" "
|
||||
"date=\"%s\" version=\"%d.%d.%d\">\n",
|
||||
NAMESPACE_URI,
|
||||
date,
|
||||
VIPS_MAJOR_VERSION, VIPS_MINOR_VERSION, VIPS_MICRO_VERSION );
|
||||
g_free( date );
|
||||
buffer_appendf( &buffer, " <properties>\n" );
|
||||
|
||||
if( vips_image_map( image, vips__xml_properties_meta, &buffer ) ) {
|
||||
buffer_destroy( &buffer );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
buffer_appendf( &buffer, " </properties>\n" );
|
||||
buffer_appendf( &buffer, "</image>\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 ) ) ) {
|
||||
|
Loading…
Reference in New Issue
Block a user