add SZI container type
and improve the scan-properties file a bit
This commit is contained in:
parent
00d8517203
commit
605d93c92f
@ -529,11 +529,6 @@ struct _VipsForeignSaveDz {
|
|||||||
*/
|
*/
|
||||||
VipsPel *ink;
|
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;
|
typedef VipsForeignSaveClass VipsForeignSaveDzClass;
|
||||||
@ -541,6 +536,21 @@ typedef VipsForeignSaveClass VipsForeignSaveDzClass;
|
|||||||
G_DEFINE_ABSTRACT_TYPE( VipsForeignSaveDz, vips_foreign_save_dz,
|
G_DEFINE_ABSTRACT_TYPE( VipsForeignSaveDz, vips_foreign_save_dz,
|
||||||
VIPS_TYPE_FOREIGN_SAVE );
|
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.
|
/* Free a pyramid.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
@ -865,20 +875,61 @@ build_scan_property( VipsDbuf *dbuf, VipsImage *image,
|
|||||||
const char *vips_name, const char *szi_name )
|
const char *vips_name, const char *szi_name )
|
||||||
{
|
{
|
||||||
const char *str;
|
const char *str;
|
||||||
|
GValue value = { 0 };
|
||||||
|
GValue save_value = { 0 };
|
||||||
|
GType type;
|
||||||
|
|
||||||
if( vips_image_get_typeof( image, vips_name ) &&
|
if( !vips_image_get_typeof( image, vips_name ) )
|
||||||
!vips_image_get_string( image, vips_name, &str ) ) {
|
return;
|
||||||
vips_dbuf_writef( dbuf, " <property>\n" );
|
|
||||||
vips_dbuf_writef( dbuf, " <name>" );
|
if( vips_image_get( image, vips_name, &value ) )
|
||||||
vips_dbuf_write_amp( dbuf, szi_name );
|
return;
|
||||||
vips_dbuf_writef( dbuf, "</name>\n" );
|
type = G_VALUE_TYPE( &value );
|
||||||
vips_dbuf_writef( dbuf, " <value type=\"str\">" );
|
|
||||||
vips_dbuf_write_amp( dbuf, str );
|
if( !g_value_type_transformable( type, VIPS_TYPE_SAVE_STRING ) ) {
|
||||||
vips_dbuf_writef( dbuf, "</value>\n" );
|
g_value_unset( &value );
|
||||||
vips_dbuf_writef( dbuf, " </property>\n" );
|
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, " <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=\"%s\">",
|
||||||
|
g_type_name( type ) );
|
||||||
|
vips_dbuf_write_amp( dbuf, str );
|
||||||
|
vips_dbuf_writef( dbuf, "</value>\n" );
|
||||||
|
vips_dbuf_writef( dbuf, " </property>\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.
|
/* Make the xml we write to scan-properties.xml in szi write.
|
||||||
* Free with g_free().
|
* Free with g_free().
|
||||||
*/
|
*/
|
||||||
@ -888,6 +939,7 @@ build_scan_properties( VipsImage *image )
|
|||||||
VipsDbuf dbuf;
|
VipsDbuf dbuf;
|
||||||
GTimeVal now;
|
GTimeVal now;
|
||||||
char *date;
|
char *date;
|
||||||
|
int i;
|
||||||
|
|
||||||
vips_dbuf_init( &dbuf );
|
vips_dbuf_init( &dbuf );
|
||||||
|
|
||||||
@ -899,14 +951,10 @@ build_scan_properties( VipsImage *image )
|
|||||||
g_free( date );
|
g_free( date );
|
||||||
vips_dbuf_writef( &dbuf, " <properties>\n" );
|
vips_dbuf_writef( &dbuf, " <properties>\n" );
|
||||||
|
|
||||||
build_scan_property( &dbuf, image,
|
for( i = 0; i < VIPS_NUMBER( scan_property_names ); i++ )
|
||||||
"openslide.vendor", "Vendor" );
|
build_scan_property( &dbuf, image,
|
||||||
build_scan_property( &dbuf, image,
|
scan_property_names[i][0],
|
||||||
"openslide.objective-power", "ObjectiveMagnification" );
|
scan_property_names[i][1] );
|
||||||
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, " </properties>\n" );
|
||||||
vips_dbuf_writef( &dbuf, "</image>\n" );
|
vips_dbuf_writef( &dbuf, "</image>\n" );
|
||||||
@ -1314,7 +1362,7 @@ strip_work( VipsThreadState *state, void *a )
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef HAVE_GSF_ZIP64
|
#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.
|
/* Leave 3 entry headroom for blank.png and metadata files.
|
||||||
*/
|
*/
|
||||||
if( dz->tree->file_count + 3 >= (unsigned int) USHRT_MAX ) {
|
if( dz->tree->file_count + 3 >= (unsigned int) USHRT_MAX ) {
|
||||||
@ -1930,6 +1978,7 @@ vips_foreign_save_dz_build( VipsObject *object )
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case VIPS_FOREIGN_DZ_CONTAINER_ZIP:
|
case VIPS_FOREIGN_DZ_CONTAINER_ZIP:
|
||||||
|
case VIPS_FOREIGN_DZ_CONTAINER_SZI:
|
||||||
{
|
{
|
||||||
GsfOutput *zip;
|
GsfOutput *zip;
|
||||||
GsfOutput *out2;
|
GsfOutput *out2;
|
||||||
@ -1939,7 +1988,10 @@ vips_foreign_save_dz_build( VipsObject *object )
|
|||||||
/* Output to a file or memory?
|
/* Output to a file or memory?
|
||||||
*/
|
*/
|
||||||
if( dz->dirname ) {
|
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",
|
vips_snprintf( name, VIPS_PATH_MAX, "%s/%s.%s",
|
||||||
dz->dirname, dz->basename, suffix );
|
dz->dirname, dz->basename, suffix );
|
||||||
if( !(dz->out =
|
if( !(dz->out =
|
||||||
@ -2013,7 +2065,7 @@ vips_foreign_save_dz_build( VipsObject *object )
|
|||||||
write_vips_meta( dz ) )
|
write_vips_meta( dz ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
if( dz->write_szi &&
|
if( dz->container == VIPS_FOREIGN_DZ_CONTAINER_SZI &&
|
||||||
write_scan_properties( dz ) )
|
write_scan_properties( dz ) )
|
||||||
return( -1 );
|
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
|
/* If we are writing a zip to the filesystem, we must unref out to
|
||||||
* force it to disc.
|
* force it to disc.
|
||||||
*/
|
*/
|
||||||
if( dz->container == VIPS_FOREIGN_DZ_CONTAINER_ZIP &&
|
if( iszip( dz->container ) &&
|
||||||
dz->dirname != NULL )
|
dz->dirname != NULL )
|
||||||
VIPS_FREEF( g_object_unref, dz->out );
|
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( (p = strrchr( dz->basename, '.' )) ) {
|
||||||
if( !vips_object_argument_isset( object, "container" ) ) {
|
if( !vips_object_argument_isset( object, "container" ) ) {
|
||||||
if( strcasecmp( p + 1, "zip" ) == 0 ||
|
if( strcasecmp( p + 1, "zip" ) == 0 )
|
||||||
strcasecmp( p + 1, "szi" ) == 0 )
|
|
||||||
dz->container = VIPS_FOREIGN_DZ_CONTAINER_ZIP;
|
dz->container = VIPS_FOREIGN_DZ_CONTAINER_ZIP;
|
||||||
|
|
||||||
/* Note we are building a .szi object.
|
|
||||||
*/
|
|
||||||
if( strcasecmp( p + 1, "szi" ) == 0 )
|
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
|
/* 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;
|
size_t olen;
|
||||||
VipsBlob *blob;
|
VipsBlob *blob;
|
||||||
|
|
||||||
/* Memory output must always be zip.
|
|
||||||
*/
|
|
||||||
dz->container = VIPS_FOREIGN_DZ_CONTAINER_ZIP;
|
|
||||||
|
|
||||||
if( !vips_object_argument_isset( object, "basename" ) )
|
if( !vips_object_argument_isset( object, "basename" ) )
|
||||||
dz->basename = g_strdup( "untitled" );
|
dz->basename = g_strdup( "untitled" );
|
||||||
|
|
||||||
@ -2402,6 +2446,11 @@ vips_foreign_save_dz_buffer_class_init( VipsForeignSaveDzBufferClass *class )
|
|||||||
static void
|
static void
|
||||||
vips_foreign_save_dz_buffer_init( VipsForeignSaveDzBuffer *buffer )
|
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*/
|
#endif /*HAVE_GSF*/
|
||||||
|
@ -589,12 +589,14 @@ typedef enum {
|
|||||||
* VipsForeignDzContainer:
|
* VipsForeignDzContainer:
|
||||||
* @VIPS_FOREIGN_DZ_CONTAINER_FS: write tiles to the filesystem
|
* @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_ZIP: write tiles to a zip file
|
||||||
|
* @VIPS_FOREIGN_DZ_CONTAINER_SZI: write to a szi file
|
||||||
*
|
*
|
||||||
* How many pyramid layers to create.
|
* How many pyramid layers to create.
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
VIPS_FOREIGN_DZ_CONTAINER_FS,
|
VIPS_FOREIGN_DZ_CONTAINER_FS,
|
||||||
VIPS_FOREIGN_DZ_CONTAINER_ZIP,
|
VIPS_FOREIGN_DZ_CONTAINER_ZIP,
|
||||||
|
VIPS_FOREIGN_DZ_CONTAINER_SZI,
|
||||||
VIPS_FOREIGN_DZ_CONTAINER_LAST
|
VIPS_FOREIGN_DZ_CONTAINER_LAST
|
||||||
} VipsForeignDzContainer;
|
} VipsForeignDzContainer;
|
||||||
|
|
||||||
|
@ -238,6 +238,7 @@ vips_foreign_dz_container_get_type( void )
|
|||||||
static const GEnumValue values[] = {
|
static const GEnumValue values[] = {
|
||||||
{VIPS_FOREIGN_DZ_CONTAINER_FS, "VIPS_FOREIGN_DZ_CONTAINER_FS", "fs"},
|
{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_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"},
|
{VIPS_FOREIGN_DZ_CONTAINER_LAST, "VIPS_FOREIGN_DZ_CONTAINER_LAST", "last"},
|
||||||
{0, NULL, NULL}
|
{0, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user