add dzsave_buffer
zip only ... see https://github.com/jcupitt/libvips/issues/415
This commit is contained in:
parent
c90b8be0b8
commit
156b0433d5
@ -1,6 +1,7 @@
|
|||||||
13/10/16 started 8.5.0
|
13/10/16 started 8.5.0
|
||||||
- rewritten buffer system is safer and frees memory earlier
|
- rewritten buffer system is safer and frees memory earlier
|
||||||
- added tiff save to buffer
|
- added tiff save to buffer
|
||||||
|
- added dzsave save to buffer (zip only)
|
||||||
|
|
||||||
27/9/16 started 8.4.2
|
27/9/16 started 8.4.2
|
||||||
- small doc improvements
|
- small doc improvements
|
||||||
|
@ -67,6 +67,8 @@
|
|||||||
* - more overlap changes to help gmaps mode
|
* - more overlap changes to help gmaps mode
|
||||||
* 8/9/16 Felix Bünemann
|
* 8/9/16 Felix Bünemann
|
||||||
* - move vips-properties out of subdir for gm and zoomify layouts
|
* - move vips-properties out of subdir for gm and zoomify layouts
|
||||||
|
* 15/10/16
|
||||||
|
* - add dzsave_buffer
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -557,10 +559,6 @@ struct _Layer {
|
|||||||
struct _VipsForeignSaveDz {
|
struct _VipsForeignSaveDz {
|
||||||
VipsForeignSave parent_object;
|
VipsForeignSave parent_object;
|
||||||
|
|
||||||
/* Name to write to.
|
|
||||||
*/
|
|
||||||
char *name;
|
|
||||||
|
|
||||||
char *suffix;
|
char *suffix;
|
||||||
int overlap;
|
int overlap;
|
||||||
int tile_size;
|
int tile_size;
|
||||||
@ -614,11 +612,16 @@ struct _VipsForeignSaveDz {
|
|||||||
*/
|
*/
|
||||||
VipsGsfDirectory *tree;
|
VipsGsfDirectory *tree;
|
||||||
|
|
||||||
/* @name, but without a path at the start and without a suffix.
|
/* The actual output object our zip (or whatever) is writing to.
|
||||||
|
*/
|
||||||
|
GsfOutput *out;
|
||||||
|
|
||||||
|
/* The name to save as, eg. deepzoom tiles go into ${basename}_files.
|
||||||
|
* No suffix, no path at the start.
|
||||||
*/
|
*/
|
||||||
char *basename;
|
char *basename;
|
||||||
|
|
||||||
/* @name, but just the path at the front.
|
/* The directory we write the output to, or NULL for memory output.
|
||||||
*/
|
*/
|
||||||
char *dirname;
|
char *dirname;
|
||||||
|
|
||||||
@ -650,7 +653,7 @@ struct _VipsForeignSaveDz {
|
|||||||
|
|
||||||
typedef VipsForeignSaveClass VipsForeignSaveDzClass;
|
typedef VipsForeignSaveClass VipsForeignSaveDzClass;
|
||||||
|
|
||||||
G_DEFINE_TYPE( VipsForeignSaveDz, vips_foreign_save_dz,
|
G_DEFINE_ABSTRACT_TYPE( VipsForeignSaveDz, vips_foreign_save_dz,
|
||||||
VIPS_TYPE_FOREIGN_SAVE );
|
VIPS_TYPE_FOREIGN_SAVE );
|
||||||
|
|
||||||
/* Free a pyramid.
|
/* Free a pyramid.
|
||||||
@ -672,6 +675,7 @@ vips_foreign_save_dz_dispose( GObject *gobject )
|
|||||||
|
|
||||||
VIPS_FREEF( layer_free, dz->layer );
|
VIPS_FREEF( layer_free, dz->layer );
|
||||||
VIPS_FREEF( vips_gsf_tree_free, dz->tree );
|
VIPS_FREEF( vips_gsf_tree_free, dz->tree );
|
||||||
|
VIPS_FREEF( g_object_unref, dz->out );
|
||||||
VIPS_FREE( dz->basename );
|
VIPS_FREE( dz->basename );
|
||||||
VIPS_FREE( dz->dirname );
|
VIPS_FREE( dz->dirname );
|
||||||
VIPS_FREE( dz->tempdir );
|
VIPS_FREE( dz->tempdir );
|
||||||
@ -1819,36 +1823,6 @@ vips_foreign_save_dz_build( VipsObject *object )
|
|||||||
save->ready->Xsize, save->ready->Ysize, &real_pixels )) )
|
save->ready->Xsize, save->ready->Ysize, &real_pixels )) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
/* Drop any path stuff at the start of the output name and remove the
|
|
||||||
* suffix.
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
dz->basename = g_path_get_basename( dz->name );
|
|
||||||
if( (p = (char *) vips__find_rightmost_brackets( dz->basename )) )
|
|
||||||
*p = '\0';
|
|
||||||
if( (p = strrchr( dz->basename, '.' )) ) {
|
|
||||||
/* If we're writing to thing.zip or thing.szi, default to zip
|
|
||||||
* container.
|
|
||||||
*/
|
|
||||||
if( !vips_object_argument_isset( object, "container" ) )
|
|
||||||
if( strcasecmp( p + 1, "zip" ) == 0 ||
|
|
||||||
strcasecmp( p + 1, "szi" ) == 0 )
|
|
||||||
dz->container = VIPS_FOREIGN_DZ_CONTAINER_ZIP;
|
|
||||||
|
|
||||||
/* Always remove .szi, .zip, .dz. We don't remove all suffixes
|
|
||||||
* since we might be writing to a dirname with a dot in.
|
|
||||||
*/
|
|
||||||
if( strcasecmp( p + 1, "zip" ) == 0 ||
|
|
||||||
strcasecmp( p + 1, "szi" ) == 0 ||
|
|
||||||
strcasecmp( p + 1, "dz" ) == 0 )
|
|
||||||
*p = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dz->dirname = g_path_get_dirname( dz->name );
|
|
||||||
|
|
||||||
if( dz->layout == VIPS_FOREIGN_DZ_LAYOUT_DZ )
|
if( dz->layout == VIPS_FOREIGN_DZ_LAYOUT_DZ )
|
||||||
dz->root_name = g_strdup_printf( "%s_files", dz->basename );
|
dz->root_name = g_strdup_printf( "%s_files", dz->basename );
|
||||||
else
|
else
|
||||||
@ -1869,6 +1843,7 @@ vips_foreign_save_dz_build( VipsObject *object )
|
|||||||
*/
|
*/
|
||||||
if( dz->layout == VIPS_FOREIGN_DZ_LAYOUT_DZ &&
|
if( dz->layout == VIPS_FOREIGN_DZ_LAYOUT_DZ &&
|
||||||
dz->container == VIPS_FOREIGN_DZ_CONTAINER_FS &&
|
dz->container == VIPS_FOREIGN_DZ_CONTAINER_FS &&
|
||||||
|
dz->dirname &&
|
||||||
vips_existsf( "%s/%s_files", dz->dirname, dz->basename ) ) {
|
vips_existsf( "%s/%s_files", dz->dirname, dz->basename ) ) {
|
||||||
vips_error( "dzsave",
|
vips_error( "dzsave",
|
||||||
_( "output directory %s/%s_files exists" ),
|
_( "output directory %s/%s_files exists" ),
|
||||||
@ -1934,31 +1909,30 @@ vips_foreign_save_dz_build( VipsObject *object )
|
|||||||
|
|
||||||
case VIPS_FOREIGN_DZ_CONTAINER_ZIP:
|
case VIPS_FOREIGN_DZ_CONTAINER_ZIP:
|
||||||
{
|
{
|
||||||
GsfOutput *out;
|
|
||||||
GsfOutput *zip;
|
GsfOutput *zip;
|
||||||
GsfOutput *out2;
|
GsfOutput *out2;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
char name[VIPS_PATH_MAX];
|
char name[VIPS_PATH_MAX];
|
||||||
|
|
||||||
/* This is the zip we are building.
|
/* Output to a file or memory?
|
||||||
*/
|
*/
|
||||||
vips_snprintf( name, VIPS_PATH_MAX, "%s/%s.zip",
|
if( dz->dirname ) {
|
||||||
dz->dirname, dz->basename );
|
vips_snprintf( name, VIPS_PATH_MAX, "%s/%s.zip",
|
||||||
if( !(out = gsf_output_stdio_new( name, &error )) ) {
|
dz->dirname, dz->basename );
|
||||||
vips_g_error( &error );
|
if( !(dz->out = gsf_output_stdio_new( name, &error )) ) {
|
||||||
return( -1 );
|
vips_g_error( &error );
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
dz->out = gsf_output_memory_new();
|
||||||
|
|
||||||
if( !(zip = (GsfOutput *)
|
if( !(zip = (GsfOutput *)
|
||||||
gsf_outfile_zip_new( out, &error )) ) {
|
gsf_outfile_zip_new( dz->out, &error )) ) {
|
||||||
vips_g_error( &error );
|
vips_g_error( &error );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We can unref @out since @zip has a ref to it.
|
|
||||||
*/
|
|
||||||
g_object_unref( out );
|
|
||||||
|
|
||||||
/* Make the base directory inside the zip. All stuff goes into
|
/* Make the base directory inside the zip. All stuff goes into
|
||||||
* this.
|
* this.
|
||||||
*/
|
*/
|
||||||
@ -2084,7 +2058,7 @@ vips_foreign_save_dz_class_init( VipsForeignSaveDzClass *class )
|
|||||||
gobject_class->set_property = vips_object_set_property;
|
gobject_class->set_property = vips_object_set_property;
|
||||||
gobject_class->get_property = vips_object_get_property;
|
gobject_class->get_property = vips_object_get_property;
|
||||||
|
|
||||||
object_class->nickname = "dzsave";
|
object_class->nickname = "dzsave_base";
|
||||||
object_class->description = _( "save image to deep zoom format" );
|
object_class->description = _( "save image to deep zoom format" );
|
||||||
object_class->build = vips_foreign_save_dz_build;
|
object_class->build = vips_foreign_save_dz_build;
|
||||||
|
|
||||||
@ -2094,11 +2068,11 @@ vips_foreign_save_dz_class_init( VipsForeignSaveDzClass *class )
|
|||||||
save_class->format_table = bandfmt_dz;
|
save_class->format_table = bandfmt_dz;
|
||||||
save_class->coding[VIPS_CODING_LABQ] = TRUE;
|
save_class->coding[VIPS_CODING_LABQ] = TRUE;
|
||||||
|
|
||||||
VIPS_ARG_STRING( class, "filename", 1,
|
VIPS_ARG_STRING( class, "basename", 2,
|
||||||
_( "Filename" ),
|
_( "Base name" ),
|
||||||
_( "Filename to save to" ),
|
_( "Base name to save to" ),
|
||||||
VIPS_ARGUMENT_REQUIRED_INPUT,
|
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||||
G_STRUCT_OFFSET( VipsForeignSaveDz, name ),
|
G_STRUCT_OFFSET( VipsForeignSaveDz, basename ),
|
||||||
NULL );
|
NULL );
|
||||||
|
|
||||||
VIPS_ARG_ENUM( class, "layout", 8,
|
VIPS_ARG_ENUM( class, "layout", 8,
|
||||||
@ -2178,17 +2152,10 @@ vips_foreign_save_dz_class_init( VipsForeignSaveDzClass *class )
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
VIPS_ARG_STRING( class, "dirname", 1,
|
VIPS_ARG_STRING( class, "dirname", 1,
|
||||||
_( "Base name" ),
|
_( "Directory name" ),
|
||||||
_( "Base name to save to" ),
|
_( "Directory name to save to" ),
|
||||||
VIPS_ARGUMENT_OPTIONAL_INPUT | VIPS_ARGUMENT_DEPRECATED,
|
VIPS_ARGUMENT_OPTIONAL_INPUT | VIPS_ARGUMENT_DEPRECATED,
|
||||||
G_STRUCT_OFFSET( VipsForeignSaveDz, name ),
|
G_STRUCT_OFFSET( VipsForeignSaveDz, dirname ),
|
||||||
NULL );
|
|
||||||
|
|
||||||
VIPS_ARG_STRING( class, "basename", 1,
|
|
||||||
_( "Base name" ),
|
|
||||||
_( "Base name to save to" ),
|
|
||||||
VIPS_ARGUMENT_OPTIONAL_INPUT | VIPS_ARGUMENT_DEPRECATED,
|
|
||||||
G_STRUCT_OFFSET( VipsForeignSaveDz, name ),
|
|
||||||
NULL );
|
NULL );
|
||||||
|
|
||||||
VIPS_ARG_INT( class, "tile_width", 12,
|
VIPS_ARG_INT( class, "tile_width", 12,
|
||||||
@ -2221,6 +2188,178 @@ vips_foreign_save_dz_init( VipsForeignSaveDz *dz )
|
|||||||
dz->compression = 0;
|
dz->compression = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct _VipsForeignSaveDzFile {
|
||||||
|
VipsForeignSaveDz parent_object;
|
||||||
|
|
||||||
|
/* Filename for save.
|
||||||
|
*/
|
||||||
|
char *filename;
|
||||||
|
|
||||||
|
} VipsForeignSaveDzFile;
|
||||||
|
|
||||||
|
typedef VipsForeignSaveDzClass VipsForeignSaveDzFileClass;
|
||||||
|
|
||||||
|
G_DEFINE_TYPE( VipsForeignSaveDzFile, vips_foreign_save_dz_file,
|
||||||
|
vips_foreign_save_dz_get_type() );
|
||||||
|
|
||||||
|
static int
|
||||||
|
vips_foreign_save_dz_file_build( VipsObject *object )
|
||||||
|
{
|
||||||
|
VipsForeignSaveDz *dz = (VipsForeignSaveDz *) object;
|
||||||
|
VipsForeignSaveDzFile *file = (VipsForeignSaveDzFile *) object;
|
||||||
|
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
/* Use @filename to set the default values for dirname and basename.
|
||||||
|
*/
|
||||||
|
if( !vips_object_argument_isset( object, "basename" ) )
|
||||||
|
dz->basename = g_path_get_basename( file->filename );
|
||||||
|
if( !vips_object_argument_isset( object, "dirname" ) )
|
||||||
|
dz->dirname = g_path_get_dirname( file->filename );
|
||||||
|
|
||||||
|
/* Remove any [options] from basename.
|
||||||
|
*/
|
||||||
|
if( (p = (char *) vips__find_rightmost_brackets( dz->basename )) )
|
||||||
|
*p = '\0';
|
||||||
|
|
||||||
|
/* If we're writing thing.zip or thing.szi, default to zip
|
||||||
|
* container.
|
||||||
|
*/
|
||||||
|
if( (p = strrchr( dz->basename, '.' )) ) {
|
||||||
|
if( !vips_object_argument_isset( object, "container" ) )
|
||||||
|
if( strcasecmp( p + 1, "zip" ) == 0 ||
|
||||||
|
strcasecmp( p + 1, "szi" ) == 0 )
|
||||||
|
dz->container = VIPS_FOREIGN_DZ_CONTAINER_ZIP;
|
||||||
|
|
||||||
|
/* Remove any legal suffix. We don't remove all suffixes
|
||||||
|
* since we might be writing to a dirname with a dot in.
|
||||||
|
*/
|
||||||
|
if( strcasecmp( p + 1, "zip" ) == 0 ||
|
||||||
|
strcasecmp( p + 1, "szi" ) == 0 ||
|
||||||
|
strcasecmp( p + 1, "dz" ) == 0 )
|
||||||
|
*p = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if( VIPS_OBJECT_CLASS( vips_foreign_save_dz_file_parent_class )->
|
||||||
|
build( object ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_foreign_save_dz_file_class_init( VipsForeignSaveDzFileClass *class )
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||||
|
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||||
|
|
||||||
|
gobject_class->set_property = vips_object_set_property;
|
||||||
|
gobject_class->get_property = vips_object_get_property;
|
||||||
|
|
||||||
|
object_class->nickname = "dzsave";
|
||||||
|
object_class->description = _( "save image to deepzoom file" );
|
||||||
|
object_class->build = vips_foreign_save_dz_file_build;
|
||||||
|
|
||||||
|
VIPS_ARG_STRING( class, "filename", 1,
|
||||||
|
_( "Filename" ),
|
||||||
|
_( "Filename to save to" ),
|
||||||
|
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||||
|
G_STRUCT_OFFSET( VipsForeignSaveDzFile, filename ),
|
||||||
|
NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_foreign_save_dz_file_init( VipsForeignSaveDzFile *file )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct _VipsForeignSaveDzBuffer {
|
||||||
|
VipsForeignSaveDz parent_object;
|
||||||
|
|
||||||
|
VipsArea *buf;
|
||||||
|
} VipsForeignSaveDzBuffer;
|
||||||
|
|
||||||
|
typedef VipsForeignSaveDzClass VipsForeignSaveDzBufferClass;
|
||||||
|
|
||||||
|
G_DEFINE_TYPE( VipsForeignSaveDzBuffer, vips_foreign_save_dz_buffer,
|
||||||
|
vips_foreign_save_dz_get_type() );
|
||||||
|
|
||||||
|
static int
|
||||||
|
vips_foreign_save_dz_buffer_build( VipsObject *object )
|
||||||
|
{
|
||||||
|
VipsForeignSaveDz *dz = (VipsForeignSaveDz *) object;
|
||||||
|
|
||||||
|
void *obuf;
|
||||||
|
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" );
|
||||||
|
|
||||||
|
/* Leave dirname NULL to indicate memory output.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if( VIPS_OBJECT_CLASS( vips_foreign_save_dz_buffer_parent_class )->
|
||||||
|
build( object ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
g_assert( GSF_IS_OUTPUT_MEMORY( dz->out ) );
|
||||||
|
|
||||||
|
/* Oh dear, we can't steal gsf's memory, and blob can't unref something
|
||||||
|
* or trigger a notify. We have to copy it.
|
||||||
|
*
|
||||||
|
* Don't use tracked, we want something that can be freed with g_free.
|
||||||
|
*
|
||||||
|
* FIXME ... blob (or area?) needs to support notify or unref.
|
||||||
|
*/
|
||||||
|
olen = gsf_output_size( GSF_OUTPUT( dz->out ) );
|
||||||
|
if( !(obuf = g_try_malloc( olen )) ) {
|
||||||
|
vips_error( "vips_tracked",
|
||||||
|
_( "out of memory --- size == %dMB" ),
|
||||||
|
(int) (olen / (1024.0 * 1024.0)) );
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
memcpy( obuf,
|
||||||
|
gsf_output_memory_get_bytes( GSF_OUTPUT_MEMORY( dz->out ) ),
|
||||||
|
olen );
|
||||||
|
|
||||||
|
blob = vips_blob_new( (VipsCallbackFn) g_free, obuf, olen );
|
||||||
|
g_object_set( object, "buffer", blob, NULL );
|
||||||
|
vips_area_unref( VIPS_AREA( blob ) );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_foreign_save_dz_buffer_class_init( VipsForeignSaveDzBufferClass *class )
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||||
|
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||||
|
|
||||||
|
gobject_class->set_property = vips_object_set_property;
|
||||||
|
gobject_class->get_property = vips_object_get_property;
|
||||||
|
|
||||||
|
object_class->nickname = "dzsave_buffer";
|
||||||
|
object_class->description = _( "save image to dz buffer" );
|
||||||
|
object_class->build = vips_foreign_save_dz_buffer_build;
|
||||||
|
|
||||||
|
VIPS_ARG_BOXED( class, "buffer", 1,
|
||||||
|
_( "Buffer" ),
|
||||||
|
_( "Buffer to save to" ),
|
||||||
|
VIPS_ARGUMENT_REQUIRED_OUTPUT,
|
||||||
|
G_STRUCT_OFFSET( VipsForeignSaveDzBuffer, buf ),
|
||||||
|
VIPS_TYPE_BLOB );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_foreign_save_dz_buffer_init( VipsForeignSaveDzBuffer *buffer )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
#endif /*HAVE_GSF*/
|
#endif /*HAVE_GSF*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2231,6 +2370,7 @@ vips_foreign_save_dz_init( VipsForeignSaveDz *dz )
|
|||||||
*
|
*
|
||||||
* Optional arguments:
|
* Optional arguments:
|
||||||
*
|
*
|
||||||
|
* * @basename: %gchar, base part of name
|
||||||
* * @layout: #VipsForeignDzLayout directory layout convention
|
* * @layout: #VipsForeignDzLayout directory layout convention
|
||||||
* * @suffix: suffix for tile tiles
|
* * @suffix: suffix for tile tiles
|
||||||
* * @overlap: %gint set tile overlap
|
* * @overlap: %gint set tile overlap
|
||||||
@ -2248,7 +2388,10 @@ vips_foreign_save_dz_init( VipsForeignSaveDz *dz )
|
|||||||
*
|
*
|
||||||
* vips_dzsave() creates a directory called @name to hold the tiles. If @name
|
* vips_dzsave() creates a directory called @name to hold the tiles. If @name
|
||||||
* ends `.zip`, vips_dzsave() will create a zip file called @name to hold the
|
* ends `.zip`, vips_dzsave() will create a zip file called @name to hold the
|
||||||
* tiles. You can use @container to force zip file output.
|
* tiles. You can use @container to force zip file output.
|
||||||
|
*
|
||||||
|
* Use @basename to set the name of the directory tree we are creating. The
|
||||||
|
* default value is set from @name.
|
||||||
*
|
*
|
||||||
* You can set @suffix to something like `".jpg[Q=85]"` to control the tile
|
* You can set @suffix to something like `".jpg[Q=85]"` to control the tile
|
||||||
* write options.
|
* write options.
|
||||||
@ -2292,3 +2435,66 @@ vips_dzsave( VipsImage *in, const char *name, ... )
|
|||||||
|
|
||||||
return( result );
|
return( result );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* vips_dzsave_buffer:
|
||||||
|
* @in: image to save
|
||||||
|
* @buf: return output buffer here
|
||||||
|
* @len: return output length here
|
||||||
|
* @...: %NULL-terminated list of optional named arguments
|
||||||
|
*
|
||||||
|
* Optional arguments:
|
||||||
|
*
|
||||||
|
* * @basename: %gchar, base part of name
|
||||||
|
* * @layout: #VipsForeignDzLayout directory layout convention
|
||||||
|
* * @suffix: suffix for tile tiles
|
||||||
|
* * @overlap: %gint set tile overlap
|
||||||
|
* * @tile_size: %gint set tile size
|
||||||
|
* * @background: #VipsArrayDouble background colour
|
||||||
|
* * @depth: #VipsForeignDzDepth how deep to make the pyramid
|
||||||
|
* * @centre: %gboolean centre the tiles
|
||||||
|
* * @angle: #VipsAngle rotate the image by this much
|
||||||
|
* * @container: #VipsForeignDzContainer set container type
|
||||||
|
* * @properties: %gboolean write a properties file
|
||||||
|
* * @compression: %gint zip deflate compression level
|
||||||
|
*
|
||||||
|
* As vips_dzsave(), but save to a memory buffer.
|
||||||
|
*
|
||||||
|
* Output is always in a zip container. Use @basename to set the name of the
|
||||||
|
* directory that the zip will create when unzipped.
|
||||||
|
*
|
||||||
|
* The address of the buffer is returned in @buf, the length of the buffer in
|
||||||
|
* @len. You are responsible for freeing the buffer with g_free() when you
|
||||||
|
* are done with it.
|
||||||
|
*
|
||||||
|
* See also: vips_dzsave(), vips_image_write_to_file().
|
||||||
|
*
|
||||||
|
* Returns: 0 on success, -1 on error.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
vips_dzsave_buffer( VipsImage *in, void **buf, size_t *len, ... )
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
VipsArea *area;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
area = NULL;
|
||||||
|
|
||||||
|
va_start( ap, len );
|
||||||
|
result = vips_call_split( "dzsave_buffer", ap, in, &area );
|
||||||
|
va_end( ap );
|
||||||
|
|
||||||
|
if( !result &&
|
||||||
|
area ) {
|
||||||
|
if( buf ) {
|
||||||
|
*buf = area->data;
|
||||||
|
area->free_fn = NULL;
|
||||||
|
}
|
||||||
|
if( len )
|
||||||
|
*len = area->length;
|
||||||
|
|
||||||
|
vips_area_unref( area );
|
||||||
|
}
|
||||||
|
|
||||||
|
return( result );
|
||||||
|
}
|
||||||
|
@ -1649,7 +1649,8 @@ vips_foreign_operation_init( void )
|
|||||||
extern GType vips_foreign_load_magick_buffer_get_type( void );
|
extern GType vips_foreign_load_magick_buffer_get_type( void );
|
||||||
extern GType vips_foreign_load_magick7_file_get_type( void );
|
extern GType vips_foreign_load_magick7_file_get_type( void );
|
||||||
extern GType vips_foreign_load_magick7_buffer_get_type( void );
|
extern GType vips_foreign_load_magick7_buffer_get_type( void );
|
||||||
extern GType vips_foreign_save_dz_get_type( void );
|
extern GType vips_foreign_save_dz_file_get_type( void );
|
||||||
|
extern GType vips_foreign_save_dz_buffer_get_type( void );
|
||||||
extern GType vips_foreign_load_webp_file_get_type( void );
|
extern GType vips_foreign_load_webp_file_get_type( void );
|
||||||
extern GType vips_foreign_load_webp_buffer_get_type( void );
|
extern GType vips_foreign_load_webp_buffer_get_type( void );
|
||||||
extern GType vips_foreign_save_webp_file_get_type( void );
|
extern GType vips_foreign_save_webp_file_get_type( void );
|
||||||
@ -1709,7 +1710,8 @@ vips_foreign_operation_init( void )
|
|||||||
#endif /*HAVE_GIFLIB*/
|
#endif /*HAVE_GIFLIB*/
|
||||||
|
|
||||||
#ifdef HAVE_GSF
|
#ifdef HAVE_GSF
|
||||||
vips_foreign_save_dz_get_type();
|
vips_foreign_save_dz_file_get_type();
|
||||||
|
vips_foreign_save_dz_buffer_get_type();
|
||||||
#endif /*HAVE_GSF*/
|
#endif /*HAVE_GSF*/
|
||||||
|
|
||||||
#ifdef HAVE_PNG
|
#ifdef HAVE_PNG
|
||||||
|
@ -309,10 +309,10 @@ vips_tracked_malloc( size_t size )
|
|||||||
|
|
||||||
vips_error( "vips_tracked",
|
vips_error( "vips_tracked",
|
||||||
_( "out of memory --- size == %dMB" ),
|
_( "out of memory --- size == %dMB" ),
|
||||||
(int) (size / (1024.0*1024.0)) );
|
(int) (size / (1024.0 * 1024.0)) );
|
||||||
vips_warn( "vips_tracked",
|
vips_warn( "vips_tracked",
|
||||||
_( "out of memory --- size == %dMB" ),
|
_( "out of memory --- size == %dMB" ),
|
||||||
(int) (size / (1024.0*1024.0)) );
|
(int) (size / (1024.0 * 1024.0)) );
|
||||||
|
|
||||||
return( NULL );
|
return( NULL );
|
||||||
}
|
}
|
||||||
|
@ -703,6 +703,17 @@ class TestForeign(unittest.TestCase):
|
|||||||
shutil.rmtree("test_files")
|
shutil.rmtree("test_files")
|
||||||
os.unlink("test.dzi")
|
os.unlink("test.dzi")
|
||||||
|
|
||||||
|
# test save to memory buffer
|
||||||
|
self.colour.dzsave("test-10.zip")
|
||||||
|
with open("test-10.zip", 'rb') as f:
|
||||||
|
buf1 = f.read()
|
||||||
|
os.unlink("test-10.zip")
|
||||||
|
buf2 = self.colour.dzsave_buffer(basename = "test-10")
|
||||||
|
self.assertEqual(len(buf1), len(buf2))
|
||||||
|
|
||||||
|
# we can't test the bytes are exactly equal, the timestamps will be
|
||||||
|
# different
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user