diff --git a/libvips/foreign/dzsave.c b/libvips/foreign/dzsave.c
index efc325dc..13b2ece4 100644
--- a/libvips/foreign/dzsave.c
+++ b/libvips/foreign/dzsave.c
@@ -529,11 +529,6 @@ struct _VipsForeignSaveDz {
*/
VipsPel *ink;
- /* TRUE if we are writing a .szi file. These are zips with a few
- * extra files inside.
- */
- gboolean write_szi;
-
};
typedef VipsForeignSaveClass VipsForeignSaveDzClass;
@@ -541,6 +536,21 @@ typedef VipsForeignSaveClass VipsForeignSaveDzClass;
G_DEFINE_ABSTRACT_TYPE( VipsForeignSaveDz, vips_foreign_save_dz,
VIPS_TYPE_FOREIGN_SAVE );
+/* ZIP and SZI are both written as zip files.
+ */
+static gboolean
+iszip( VipsForeignDzContainer container )
+{
+ switch( container ) {
+ case VIPS_FOREIGN_DZ_CONTAINER_ZIP:
+ case VIPS_FOREIGN_DZ_CONTAINER_SZI:
+ return( TRUE );
+
+ default:
+ return( FALSE );
+ }
+}
+
/* Free a pyramid.
*/
static void
@@ -865,20 +875,61 @@ build_scan_property( VipsDbuf *dbuf, VipsImage *image,
const char *vips_name, const char *szi_name )
{
const char *str;
+ GValue value = { 0 };
+ GValue save_value = { 0 };
+ GType type;
- if( vips_image_get_typeof( image, vips_name ) &&
- !vips_image_get_string( image, vips_name, &str ) ) {
- vips_dbuf_writef( dbuf, " \n" );
- vips_dbuf_writef( dbuf, " " );
- vips_dbuf_write_amp( dbuf, szi_name );
- vips_dbuf_writef( dbuf, "\n" );
- vips_dbuf_writef( dbuf, " " );
- vips_dbuf_write_amp( dbuf, str );
- vips_dbuf_writef( dbuf, "\n" );
- vips_dbuf_writef( dbuf, " \n" );
+ if( !vips_image_get_typeof( image, vips_name ) )
+ return;
+
+ if( vips_image_get( image, vips_name, &value ) )
+ return;
+ type = G_VALUE_TYPE( &value );
+
+ if( !g_value_type_transformable( type, VIPS_TYPE_SAVE_STRING ) ) {
+ g_value_unset( &value );
+ return;
}
+
+ g_value_init( &save_value, VIPS_TYPE_SAVE_STRING );
+ if( !g_value_transform( &value, &save_value ) ) {
+ g_value_unset( &value );
+ return;
+ }
+ g_value_unset( &value );
+
+ if( !(str = vips_value_get_save_string( &save_value )) ) {
+ g_value_unset( &save_value );
+ return;
+ }
+
+ if( !g_utf8_validate( str, -1, NULL ) ) {
+ g_value_unset( &save_value );
+ return;
+ }
+
+ vips_dbuf_writef( dbuf, " \n" );
+ vips_dbuf_writef( dbuf, " " );
+ vips_dbuf_write_amp( dbuf, szi_name );
+ vips_dbuf_writef( dbuf, "\n" );
+ vips_dbuf_writef( dbuf, " ",
+ g_type_name( type ) );
+ vips_dbuf_write_amp( dbuf, str );
+ vips_dbuf_writef( dbuf, "\n" );
+ vips_dbuf_writef( dbuf, " \n" );
+
+ g_value_unset( &save_value );
}
+static char *scan_property_names[][2] = {
+ { "openslide.vendor", "Vendor" },
+ { "openslide.objective-power", "ObjectiveMagnification" },
+ { "openslide.mpp-x", "MicronsPerPixelX" },
+ { "openslide.mpp-y", "MicronsPerPixelY" },
+ { "width", "ImageWidth" },
+ { "height", "ImageHeight" }
+};
+
/* Make the xml we write to scan-properties.xml in szi write.
* Free with g_free().
*/
@@ -888,6 +939,7 @@ build_scan_properties( VipsImage *image )
VipsDbuf dbuf;
GTimeVal now;
char *date;
+ int i;
vips_dbuf_init( &dbuf );
@@ -899,14 +951,10 @@ build_scan_properties( VipsImage *image )
g_free( date );
vips_dbuf_writef( &dbuf, " \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" );
+ for( i = 0; i < VIPS_NUMBER( scan_property_names ); i++ )
+ build_scan_property( &dbuf, image,
+ scan_property_names[i][0],
+ scan_property_names[i][1] );
vips_dbuf_writef( &dbuf, " \n" );
vips_dbuf_writef( &dbuf, "\n" );
@@ -1314,7 +1362,7 @@ strip_work( VipsThreadState *state, void *a )
}
#ifndef HAVE_GSF_ZIP64
- if( dz->container == VIPS_FOREIGN_DZ_CONTAINER_ZIP ) {
+ if( iszip( dz->container ) ) {
/* Leave 3 entry headroom for blank.png and metadata files.
*/
if( dz->tree->file_count + 3 >= (unsigned int) USHRT_MAX ) {
@@ -1930,6 +1978,7 @@ vips_foreign_save_dz_build( VipsObject *object )
break;
case VIPS_FOREIGN_DZ_CONTAINER_ZIP:
+ case VIPS_FOREIGN_DZ_CONTAINER_SZI:
{
GsfOutput *zip;
GsfOutput *out2;
@@ -1939,7 +1988,10 @@ vips_foreign_save_dz_build( VipsObject *object )
/* Output to a file or memory?
*/
if( dz->dirname ) {
- const char *suffix = dz->write_szi ? "szi" : "zip";
+ const char *suffix =
+ dz->container == VIPS_FOREIGN_DZ_CONTAINER_SZI ?
+ "szi" : "zip";
+
vips_snprintf( name, VIPS_PATH_MAX, "%s/%s.%s",
dz->dirname, dz->basename, suffix );
if( !(dz->out =
@@ -2013,7 +2065,7 @@ vips_foreign_save_dz_build( VipsObject *object )
write_vips_meta( dz ) )
return( -1 );
- if( dz->write_szi &&
+ if( dz->container == VIPS_FOREIGN_DZ_CONTAINER_SZI &&
write_scan_properties( dz ) )
return( -1 );
@@ -2057,7 +2109,7 @@ vips_foreign_save_dz_build( VipsObject *object )
/* If we are writing a zip to the filesystem, we must unref out to
* force it to disc.
*/
- if( dz->container == VIPS_FOREIGN_DZ_CONTAINER_ZIP &&
+ if( iszip( dz->container ) &&
dz->dirname != NULL )
VIPS_FREEF( g_object_unref, dz->out );
@@ -2265,14 +2317,10 @@ vips_foreign_save_dz_file_build( VipsObject *object )
*/
if( (p = strrchr( dz->basename, '.' )) ) {
if( !vips_object_argument_isset( object, "container" ) ) {
- if( strcasecmp( p + 1, "zip" ) == 0 ||
- strcasecmp( p + 1, "szi" ) == 0 )
+ if( strcasecmp( p + 1, "zip" ) == 0 )
dz->container = VIPS_FOREIGN_DZ_CONTAINER_ZIP;
-
- /* Note we are building a .szi object.
- */
if( strcasecmp( p + 1, "szi" ) == 0 )
- dz->write_szi = TRUE;
+ dz->container = VIPS_FOREIGN_DZ_CONTAINER_SZI;
}
/* Remove any legal suffix. We don't remove all suffixes
@@ -2337,10 +2385,6 @@ vips_foreign_save_dz_buffer_build( VipsObject *object )
size_t olen;
VipsBlob *blob;
- /* Memory output must always be zip.
- */
- dz->container = VIPS_FOREIGN_DZ_CONTAINER_ZIP;
-
if( !vips_object_argument_isset( object, "basename" ) )
dz->basename = g_strdup( "untitled" );
@@ -2402,6 +2446,11 @@ vips_foreign_save_dz_buffer_class_init( VipsForeignSaveDzBufferClass *class )
static void
vips_foreign_save_dz_buffer_init( VipsForeignSaveDzBuffer *buffer )
{
+ VipsForeignSaveDz *dz = (VipsForeignSaveDz *) buffer;
+
+ /* zip default for memory output.
+ */
+ dz->container = VIPS_FOREIGN_DZ_CONTAINER_ZIP;
}
#endif /*HAVE_GSF*/
diff --git a/libvips/include/vips/foreign.h b/libvips/include/vips/foreign.h
index 4a2fb418..746652e2 100644
--- a/libvips/include/vips/foreign.h
+++ b/libvips/include/vips/foreign.h
@@ -589,12 +589,14 @@ typedef enum {
* VipsForeignDzContainer:
* @VIPS_FOREIGN_DZ_CONTAINER_FS: write tiles to the filesystem
* @VIPS_FOREIGN_DZ_CONTAINER_ZIP: write tiles to a zip file
+ * @VIPS_FOREIGN_DZ_CONTAINER_SZI: write to a szi file
*
* How many pyramid layers to create.
*/
typedef enum {
VIPS_FOREIGN_DZ_CONTAINER_FS,
VIPS_FOREIGN_DZ_CONTAINER_ZIP,
+ VIPS_FOREIGN_DZ_CONTAINER_SZI,
VIPS_FOREIGN_DZ_CONTAINER_LAST
} VipsForeignDzContainer;
diff --git a/libvips/iofuncs/enumtypes.c b/libvips/iofuncs/enumtypes.c
index 805045ad..6cb186e7 100644
--- a/libvips/iofuncs/enumtypes.c
+++ b/libvips/iofuncs/enumtypes.c
@@ -238,6 +238,7 @@ vips_foreign_dz_container_get_type( void )
static const GEnumValue values[] = {
{VIPS_FOREIGN_DZ_CONTAINER_FS, "VIPS_FOREIGN_DZ_CONTAINER_FS", "fs"},
{VIPS_FOREIGN_DZ_CONTAINER_ZIP, "VIPS_FOREIGN_DZ_CONTAINER_ZIP", "zip"},
+ {VIPS_FOREIGN_DZ_CONTAINER_SZI, "VIPS_FOREIGN_DZ_CONTAINER_SZI", "szi"},
{VIPS_FOREIGN_DZ_CONTAINER_LAST, "VIPS_FOREIGN_DZ_CONTAINER_LAST", "last"},
{0, NULL, NULL}
};