Merge branch 'dzsave-gsf'
This commit is contained in:
commit
ff71a69827
8
TODO
8
TODO
@ -1,12 +1,4 @@
|
|||||||
|
|
||||||
- how do we keep compat with old behaviour? gsf won't let us write to "."
|
|
||||||
|
|
||||||
looks like we need to break compatibility :-(
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- auto-enable zip output?
|
|
||||||
|
|
||||||
- try
|
- try
|
||||||
|
|
||||||
vips vips
|
vips vips
|
||||||
|
@ -41,28 +41,6 @@
|
|||||||
* filesystem
|
* filesystem
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
TODO
|
|
||||||
|
|
||||||
- need some way to pass save options to the jpeg tile writer
|
|
||||||
|
|
||||||
- and to pick a tile writer!
|
|
||||||
|
|
||||||
- need some way to select a container format
|
|
||||||
|
|
||||||
- are the rules for naming objects correct? eg.
|
|
||||||
|
|
||||||
vips dzsave fred.tif /my/output/file.zip
|
|
||||||
|
|
||||||
will create file.zip containing
|
|
||||||
|
|
||||||
file.zip:file_files
|
|
||||||
file.zip:file_files/0/0_0.jpg
|
|
||||||
file.zip:file.dzi
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
This file is part of VIPS.
|
This file is part of VIPS.
|
||||||
@ -176,6 +154,10 @@ typedef struct _VipsGsfDirectory {
|
|||||||
*/
|
*/
|
||||||
gboolean no_compression;
|
gboolean no_compression;
|
||||||
|
|
||||||
|
/* The root node holds the enclosing zip file or FS root ... finish
|
||||||
|
* this on cleanup.
|
||||||
|
*/
|
||||||
|
GsfOutput *container;
|
||||||
} VipsGsfDirectory;
|
} VipsGsfDirectory;
|
||||||
|
|
||||||
/* Close all dirs, non-NULL on error.
|
/* Close all dirs, non-NULL on error.
|
||||||
@ -185,12 +167,19 @@ vips_gsf_tree_close( VipsGsfDirectory *tree )
|
|||||||
{
|
{
|
||||||
vips_slist_map2( tree->children,
|
vips_slist_map2( tree->children,
|
||||||
(VipsSListMap2Fn) vips_gsf_tree_close, NULL, NULL );
|
(VipsSListMap2Fn) vips_gsf_tree_close, NULL, NULL );
|
||||||
|
|
||||||
if( tree->out &&
|
if( tree->out &&
|
||||||
!gsf_output_is_closed( tree->out ) &&
|
!gsf_output_is_closed( tree->out ) &&
|
||||||
!gsf_output_close( tree->out ) ) {
|
!gsf_output_close( tree->out ) ) {
|
||||||
vips_error( "vips_gsf", "%s", _( "unable to close stream" ) );
|
vips_error( "vips_gsf", "%s", _( "unable to close stream" ) );
|
||||||
return( tree );
|
return( tree );
|
||||||
}
|
}
|
||||||
|
if( tree->container &&
|
||||||
|
!gsf_output_is_closed( tree->container ) &&
|
||||||
|
!gsf_output_close( tree->container ) ) {
|
||||||
|
vips_error( "vips_gsf", "%s", _( "unable to close stream" ) );
|
||||||
|
return( tree );
|
||||||
|
}
|
||||||
|
|
||||||
return( NULL );
|
return( NULL );
|
||||||
}
|
}
|
||||||
@ -205,11 +194,19 @@ vips_gsf_tree_free( VipsGsfDirectory *tree )
|
|||||||
(VipsSListMap2Fn) vips_gsf_tree_free, NULL, NULL );
|
(VipsSListMap2Fn) vips_gsf_tree_free, NULL, NULL );
|
||||||
g_slist_free( tree->children );
|
g_slist_free( tree->children );
|
||||||
g_free( (char *) tree->name );
|
g_free( (char *) tree->name );
|
||||||
|
|
||||||
if( tree->out ) {
|
if( tree->out ) {
|
||||||
if( !gsf_output_is_closed( tree->out ) )
|
if( !gsf_output_is_closed( tree->out ) )
|
||||||
(void) gsf_output_close( tree->out );
|
(void) gsf_output_close( tree->out );
|
||||||
g_object_unref( tree->out );
|
g_object_unref( tree->out );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( tree->container ) {
|
||||||
|
if( !gsf_output_is_closed( tree->container ) )
|
||||||
|
(void) gsf_output_close( tree->container );
|
||||||
|
g_object_unref( tree->container );
|
||||||
|
}
|
||||||
|
|
||||||
g_free( tree );
|
g_free( tree );
|
||||||
|
|
||||||
return( NULL );
|
return( NULL );
|
||||||
@ -227,6 +224,7 @@ vips_gsf_tree_new( GsfOutput *out, gboolean no_compression )
|
|||||||
tree->children = NULL;
|
tree->children = NULL;
|
||||||
tree->out = out;
|
tree->out = out;
|
||||||
tree->no_compression = no_compression;
|
tree->no_compression = no_compression;
|
||||||
|
tree->container = NULL;
|
||||||
|
|
||||||
return( tree );
|
return( tree );
|
||||||
}
|
}
|
||||||
@ -263,6 +261,7 @@ vips_gsf_dir_new( VipsGsfDirectory *parent, const char *name )
|
|||||||
dir->name = g_strdup( name );
|
dir->name = g_strdup( name );
|
||||||
dir->children = NULL;
|
dir->children = NULL;
|
||||||
dir->no_compression = parent->no_compression;
|
dir->no_compression = parent->no_compression;
|
||||||
|
dir->container = NULL;
|
||||||
|
|
||||||
if( dir->no_compression )
|
if( dir->no_compression )
|
||||||
dir->out = gsf_outfile_new_child_full(
|
dir->out = gsf_outfile_new_child_full(
|
||||||
@ -404,8 +403,8 @@ struct _VipsForeignSaveDz {
|
|||||||
*/
|
*/
|
||||||
char *dirname;
|
char *dirname;
|
||||||
|
|
||||||
/* The root directory name ... used to form
|
/* The root directory name ... $basename with perhaps some extra
|
||||||
* $(root_name)_files, $(root_name), etc.
|
* stuff, eg. $(basename)_files, etc.
|
||||||
*/
|
*/
|
||||||
char *root_name;
|
char *root_name;
|
||||||
};
|
};
|
||||||
@ -588,7 +587,7 @@ write_dzi( VipsForeignSaveDz *dz )
|
|||||||
char buf[VIPS_PATH_MAX];
|
char buf[VIPS_PATH_MAX];
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
vips_snprintf( buf, VIPS_PATH_MAX, "%s.dzi", dz->name );
|
vips_snprintf( buf, VIPS_PATH_MAX, "%s.dzi", dz->basename );
|
||||||
out = vips_gsf_path( dz->tree, buf, NULL );
|
out = vips_gsf_path( dz->tree, buf, NULL );
|
||||||
|
|
||||||
vips_snprintf( buf, VIPS_PATH_MAX, "%s", dz->suffix + 1 );
|
vips_snprintf( buf, VIPS_PATH_MAX, "%s", dz->suffix + 1 );
|
||||||
@ -675,7 +674,7 @@ write_blank( VipsForeignSaveDz *dz )
|
|||||||
}
|
}
|
||||||
g_object_unref( x );
|
g_object_unref( x );
|
||||||
|
|
||||||
out = vips_gsf_path( dz->tree, "blank.png", dz->root_name, NULL );
|
out = vips_gsf_path( dz->tree, "blank.png", NULL );
|
||||||
gsf_output_write( out, len, buf );
|
gsf_output_write( out, len, buf );
|
||||||
gsf_output_close( out );
|
gsf_output_close( out );
|
||||||
g_object_unref( out );
|
g_object_unref( out );
|
||||||
@ -955,8 +954,7 @@ tile_name( Layer *layer, int x, int y )
|
|||||||
*/
|
*/
|
||||||
dz->tile_count += 1;
|
dz->tile_count += 1;
|
||||||
|
|
||||||
out = vips_gsf_path( dz->tree, name,
|
out = vips_gsf_path( dz->tree, name, dirname, NULL );
|
||||||
dz->root_name, dirname, NULL );
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -965,8 +963,7 @@ tile_name( Layer *layer, int x, int y )
|
|||||||
vips_snprintf( dirname2, VIPS_PATH_MAX, "%d", y );
|
vips_snprintf( dirname2, VIPS_PATH_MAX, "%d", y );
|
||||||
vips_snprintf( name, VIPS_PATH_MAX, "%d%s", x, dz->suffix );
|
vips_snprintf( name, VIPS_PATH_MAX, "%d%s", x, dz->suffix );
|
||||||
|
|
||||||
out = vips_gsf_path( dz->tree, name,
|
out = vips_gsf_path( dz->tree, name, dirname, dirname2, NULL );
|
||||||
dz->root_name, dirname, dirname2, NULL );
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1490,10 +1487,17 @@ vips_foreign_save_dz_build( VipsObject *object )
|
|||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
dz->basename = g_path_get_basename( dz->name );
|
dz->basename = g_path_get_basename( dz->name );
|
||||||
if( (p = (char *) vips__find_rightmost_brackets( dz->name )) )
|
if( (p = (char *) vips__find_rightmost_brackets( dz->basename )) )
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
if( (p = strrchr( dz->name, '.' )) )
|
if( (p = strrchr( dz->basename, '.' )) ) {
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
|
|
||||||
|
/* If we're writing to thing.zip, default to zip container.
|
||||||
|
*/
|
||||||
|
if( strcasecmp( p + 1, "zip" ) == 0 &&
|
||||||
|
!vips_object_argument_isset( object, "container" ) )
|
||||||
|
dz->container = VIPS_FOREIGN_DZ_CONTAINER_ZIP;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dz->dirname = g_path_get_dirname( dz->name );
|
dz->dirname = g_path_get_dirname( dz->name );
|
||||||
@ -1528,6 +1532,7 @@ vips_foreign_save_dz_build( VipsObject *object )
|
|||||||
{
|
{
|
||||||
GsfOutput *out;
|
GsfOutput *out;
|
||||||
GsfOutput *zip;
|
GsfOutput *zip;
|
||||||
|
GsfOutput *out2;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
|
||||||
/* This is the zip we are building.
|
/* This is the zip we are building.
|
||||||
@ -1547,7 +1552,19 @@ vips_foreign_save_dz_build( VipsObject *object )
|
|||||||
*/
|
*/
|
||||||
g_object_unref( out );
|
g_object_unref( out );
|
||||||
|
|
||||||
dz->tree = vips_gsf_tree_new( zip, TRUE );
|
/* Make the base directory inside the zip. All stuff goes into
|
||||||
|
* this.
|
||||||
|
*/
|
||||||
|
out2 = gsf_outfile_new_child_full( (GsfOutfile *) zip,
|
||||||
|
dz->basename, TRUE,
|
||||||
|
"compression-level", 0,
|
||||||
|
NULL );
|
||||||
|
|
||||||
|
dz->tree = vips_gsf_tree_new( out2, TRUE );
|
||||||
|
|
||||||
|
/* Note the thing that will need closing up on exit.
|
||||||
|
*/
|
||||||
|
dz->tree->container = zip;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1763,21 +1780,14 @@ vips_foreign_save_dz_init( VipsForeignSaveDz *dz )
|
|||||||
* @depth: how deep to make the pyramid
|
* @depth: how deep to make the pyramid
|
||||||
* @centre: centre the tiles
|
* @centre: centre the tiles
|
||||||
* @angle: rotate the image by this much
|
* @angle: rotate the image by this much
|
||||||
* @container: container format
|
* @container: set container type
|
||||||
*
|
*
|
||||||
* Save an image as a set of tiles at various resolutions. By default dzsave
|
* Save an image as a set of tiles at various resolutions. By default dzsave
|
||||||
* uses DeepZoom layout -- use @layout to pick other conventions.
|
* uses DeepZoom layout -- use @layout to pick other conventions.
|
||||||
*
|
*
|
||||||
* @name is split into three parts: $(dirname) (everything before the
|
* vips_dzsave() creates a directory called @name to hold the tiles. If @name
|
||||||
* last '/'), $(basename) (everything after the last '/') and $(rootname)
|
* ends ".zip", vips_dzsave() will create a zip file called @name to hold the
|
||||||
* ($(basename) minus any extensions).
|
* tiles. You can use @container to force zip file output.
|
||||||
*
|
|
||||||
* In DeepZoom layout a directory in $(dirname) called
|
|
||||||
* "$(basename)_files" is created to hold the tiles, and an XML file called
|
|
||||||
* "$(basename).dzi" is written with the image metadata,
|
|
||||||
*
|
|
||||||
* In Zoomify and Google layout, a directory called @name is created to
|
|
||||||
* hold the tile structure.
|
|
||||||
*
|
*
|
||||||
* You can set @suffix to something like ".jpg[Q=85]" to control the tile write
|
* You can set @suffix to something like ".jpg[Q=85]" to control the tile write
|
||||||
* options.
|
* options.
|
||||||
@ -1793,13 +1803,6 @@ vips_foreign_save_dz_init( VipsForeignSaveDz *dz )
|
|||||||
* Use @depth to control how low the pyramid goes. This defaults to the
|
* Use @depth to control how low the pyramid goes. This defaults to the
|
||||||
* correct setting for the @layout you select.
|
* correct setting for the @layout you select.
|
||||||
*
|
*
|
||||||
* Use @container to set where to write the zoom structure. By default it
|
|
||||||
* writes to the filesystem, but set this to #VIPS_FOREIGN_DZ_CONTAINER_ZIP
|
|
||||||
* and dzsave will create a zip file called @name to hold the pyramid.
|
|
||||||
*
|
|
||||||
* Using #VIPS_FOREIGN_DZ_CONTAINER_ZIP can save a separate zip stage,
|
|
||||||
* which will be very slow on some platforms.
|
|
||||||
*
|
|
||||||
* See also: vips_tiffsave().
|
* See also: vips_tiffsave().
|
||||||
*
|
*
|
||||||
* Returns: 0 on success, -1 on error.
|
* Returns: 0 on success, -1 on error.
|
||||||
|
Loading…
Reference in New Issue
Block a user