write scan-properties.xml to szi
see https://github.com/jcupitt/libvips/issues/853
This commit is contained in:
parent
c46f4b15e0
commit
21e1e68771
@ -1,6 +1,7 @@
|
||||
23/12/17 started 8.7.0
|
||||
- add magicksave, save image with libMagick [dlemstra]
|
||||
- dzsave to szi sets suffix correctly [martinweihrauch]
|
||||
- dzsave szi writes "scan-properties.xml"
|
||||
|
||||
5/1/18 started 8.6.2
|
||||
- vips_sink_screen() keeps a ref to the input image ... stops a rare race
|
||||
|
@ -76,6 +76,8 @@
|
||||
* 24/11/17
|
||||
* - output overlap-only tiles on edges for better deepzoom spec
|
||||
* compliance
|
||||
* 6/1/18
|
||||
* - add scan-properties.xml for szi output
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -858,6 +860,81 @@ write_vips_meta( VipsForeignSaveDz *dz )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static void
|
||||
build_scan_property( VipsDbuf *dbuf, VipsImage *image,
|
||||
const char *vips_name, const char *szi_name )
|
||||
{
|
||||
const char *str;
|
||||
|
||||
if( vips_image_get_typeof( image, vips_name ) &&
|
||||
!vips_image_get_string( image, vips_name, &str ) ) {
|
||||
vips_dbuf_writef( dbuf, " <property>\n" );
|
||||
vips_dbuf_writef( dbuf, " <name>" );
|
||||
vips_dbuf_write_amp( dbuf, szi_name );
|
||||
vips_dbuf_writef( dbuf, "</name>\n" );
|
||||
vips_dbuf_writef( dbuf, " <value type=\"str\">" );
|
||||
vips_dbuf_write_amp( dbuf, str );
|
||||
vips_dbuf_writef( dbuf, "</value>\n" );
|
||||
vips_dbuf_writef( dbuf, " </property>\n" );
|
||||
}
|
||||
}
|
||||
|
||||
/* Make the xml we write to scan-properties.xml in szi write.
|
||||
* Free with g_free().
|
||||
*/
|
||||
char *
|
||||
build_scan_properties( VipsImage *image )
|
||||
{
|
||||
VipsDbuf dbuf;
|
||||
GTimeVal now;
|
||||
char *date;
|
||||
|
||||
vips_dbuf_init( &dbuf );
|
||||
|
||||
g_get_current_time( &now );
|
||||
date = g_time_val_to_iso8601( &now );
|
||||
vips_dbuf_writef( &dbuf, "<?xml version=\"1.0\"?>\n" );
|
||||
vips_dbuf_writef( &dbuf, "<image xmlns=\"http://www.pathozoom.com/szi\""
|
||||
" date=\"%s\" version=\"1.0\">\n", date );
|
||||
g_free( date );
|
||||
vips_dbuf_writef( &dbuf, " <properties>\n" );
|
||||
|
||||
build_scan_property( &dbuf, image,
|
||||
"openslide.vendor", "Vendor" );
|
||||
build_scan_property( &dbuf, image,
|
||||
"openslide.objective-power", "ObjectiveMagnification" );
|
||||
build_scan_property( &dbuf, image,
|
||||
"openslide.mpp-x", "MicronsPerPixelX" );
|
||||
build_scan_property( &dbuf, image,
|
||||
"openslide.mpp-y", "MicronsPerPixelY" );
|
||||
|
||||
vips_dbuf_writef( &dbuf, " </properties>\n" );
|
||||
vips_dbuf_writef( &dbuf, "</image>\n" );
|
||||
|
||||
return( (char *) vips_dbuf_steal( &dbuf, NULL ) );
|
||||
}
|
||||
|
||||
static int
|
||||
write_scan_properties( VipsForeignSaveDz *dz )
|
||||
{
|
||||
VipsForeignSave *save = (VipsForeignSave *) dz;
|
||||
|
||||
char *dump;
|
||||
GsfOutput *out;
|
||||
|
||||
if( !(dump = build_scan_properties( save->ready )) )
|
||||
return( -1 );
|
||||
|
||||
out = vips_gsf_path( dz->tree, "scan-properties.xml", NULL );
|
||||
gsf_output_write( out, strlen( dump ), (guchar *) dump );
|
||||
(void) gsf_output_close( out );
|
||||
g_object_unref( out );
|
||||
|
||||
g_free( dump );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* Our state during a threaded write of a strip.
|
||||
*/
|
||||
typedef struct _Strip {
|
||||
@ -1936,6 +2013,10 @@ vips_foreign_save_dz_build( VipsObject *object )
|
||||
write_vips_meta( dz ) )
|
||||
return( -1 );
|
||||
|
||||
if( dz->write_szi &&
|
||||
write_scan_properties( dz ) )
|
||||
return( -1 );
|
||||
|
||||
/* This is so ugly. In earlier versions of dzsave, we wrote x.dzi and
|
||||
* x_files. Now we write x/x.dzi and x/x_files to make it possible to
|
||||
* create zip files.
|
||||
|
@ -69,6 +69,7 @@ unsigned char *vips_dbuf_get_write( VipsDbuf *dbuf, size_t *size );
|
||||
gboolean vips_dbuf_write( VipsDbuf *dbuf,
|
||||
const unsigned char *data, size_t size );
|
||||
gboolean vips_dbuf_writef( VipsDbuf *dbuf, const char *fmt, ... );
|
||||
gboolean vips_dbuf_write_amp( VipsDbuf *dbuf, const char *str );
|
||||
void vips_dbuf_reset( VipsDbuf *dbuf );
|
||||
void vips_dbuf_destroy( VipsDbuf *dbuf );
|
||||
gboolean vips_dbuf_seek( VipsDbuf *dbuf, off_t offset, int whence );
|
||||
|
@ -206,6 +206,52 @@ vips_dbuf_writef( VipsDbuf *dbuf, const char *fmt, ... )
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_dbuf_write_amp:
|
||||
* @dbuf: the buffer
|
||||
* @str: string to write
|
||||
*
|
||||
* Write @str to @dbuf, but escape <>&.
|
||||
*
|
||||
* Returns: %FALSE on out of memory, %TRUE otherwise.
|
||||
*/
|
||||
gboolean
|
||||
vips_dbuf_write_amp( VipsDbuf *dbuf, const char *str )
|
||||
{
|
||||
const char *p;
|
||||
size_t len;
|
||||
|
||||
for( p = str; *p; p += len ) {
|
||||
len = strcspn( p, "&<>" );
|
||||
|
||||
vips_dbuf_write( dbuf, (unsigned char *) p, len );
|
||||
switch( p[len] ) {
|
||||
case '&':
|
||||
if( vips_dbuf_writef( dbuf, "&" ) )
|
||||
return( FALSE );
|
||||
len += 1;
|
||||
break;
|
||||
|
||||
case '<':
|
||||
if( vips_dbuf_writef( dbuf, "<" ) )
|
||||
return( FALSE );
|
||||
len += 1;
|
||||
break;
|
||||
|
||||
case '>':
|
||||
if( vips_dbuf_writef( dbuf, ">" ) )
|
||||
return( FALSE );
|
||||
len += 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_dbuf_reset:
|
||||
* @dbuf: the buffer
|
||||
|
@ -743,40 +743,6 @@ dbuf_write_quotes( VipsDbuf *dbuf, const char *str )
|
||||
}
|
||||
}
|
||||
|
||||
/* Append a string to a buffer, but escape &<>.
|
||||
*/
|
||||
static void
|
||||
dbuf_write_amp( VipsDbuf *dbuf, const char *str )
|
||||
{
|
||||
const char *p;
|
||||
size_t len;
|
||||
|
||||
for( p = str; *p; p += len ) {
|
||||
len = strcspn( p, "&<>" );
|
||||
|
||||
vips_dbuf_write( dbuf, (unsigned char *) p, len );
|
||||
switch( p[len] ) {
|
||||
case '&':
|
||||
vips_dbuf_writef( dbuf, "&" );
|
||||
len += 1;
|
||||
break;
|
||||
|
||||
case '<':
|
||||
vips_dbuf_writef( dbuf, "<" );
|
||||
len += 1;
|
||||
break;
|
||||
|
||||
case '>':
|
||||
vips_dbuf_writef( dbuf, ">" );
|
||||
len += 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void *
|
||||
build_xml_meta( VipsMeta *meta, VipsDbuf *dbuf )
|
||||
{
|
||||
@ -808,7 +774,7 @@ build_xml_meta( VipsMeta *meta, VipsDbuf *dbuf )
|
||||
g_type_name( type ) );
|
||||
dbuf_write_quotes( dbuf, meta->name );
|
||||
vips_dbuf_writef( dbuf, "\">" );
|
||||
dbuf_write_amp( dbuf, str );
|
||||
vips_dbuf_write_amp( dbuf, str );
|
||||
vips_dbuf_writef( dbuf, "</field>\n" );
|
||||
}
|
||||
|
||||
@ -839,7 +805,7 @@ build_xml( VipsImage *image )
|
||||
vips_dbuf_writef( &dbuf,
|
||||
" <field type=\"%s\" name=\"Hist\">",
|
||||
g_type_name( VIPS_TYPE_REF_STRING ) );
|
||||
dbuf_write_amp( &dbuf, str );
|
||||
vips_dbuf_write_amp( &dbuf, str );
|
||||
vips_dbuf_writef( &dbuf, "</field>\n" );
|
||||
}
|
||||
|
||||
@ -884,11 +850,11 @@ vips__xml_properties_meta( VipsImage *image,
|
||||
|
||||
vips_dbuf_writef( dbuf, " <property>\n" );
|
||||
vips_dbuf_writef( dbuf, " <name>" );
|
||||
dbuf_write_amp( dbuf, field );
|
||||
vips_dbuf_write_amp( dbuf, field );
|
||||
vips_dbuf_writef( dbuf, "</name>\n" );
|
||||
vips_dbuf_writef( dbuf, " <value type=\"%s\">",
|
||||
g_type_name( type ) );
|
||||
dbuf_write_amp( dbuf, str );
|
||||
vips_dbuf_write_amp( dbuf, str );
|
||||
vips_dbuf_writef( dbuf, "</value>\n" );
|
||||
vips_dbuf_writef( dbuf, " </property>\n" );
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user