add fallbacks to new_from_stream
If the stream-based loaders fail, vips_image_new_from_stream() now falls back to the old file and buffer loaders. The file and buffer loaders already try the stream loaders first.
This commit is contained in:
parent
56090c6fa7
commit
e236f19f97
@ -592,7 +592,8 @@ VImage
|
|||||||
VImage::new_from_buffer( const std::string &buf, const char *option_string,
|
VImage::new_from_buffer( const std::string &buf, const char *option_string,
|
||||||
VOption *options )
|
VOption *options )
|
||||||
{
|
{
|
||||||
return( new_from_buffer( buf.c_str(), buf.size(), option_string, options ) );
|
return( new_from_buffer( buf.c_str(), buf.size(),
|
||||||
|
option_string, options ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
VImage
|
VImage
|
||||||
|
@ -214,6 +214,7 @@ int vips_streami_decode( VipsStreami *streami );
|
|||||||
ssize_t vips_streami_read( VipsStreami *streami, void *data, size_t length );
|
ssize_t vips_streami_read( VipsStreami *streami, void *data, size_t length );
|
||||||
gboolean vips_streami_is_mappable( VipsStreami *streami );
|
gboolean vips_streami_is_mappable( VipsStreami *streami );
|
||||||
const void *vips_streami_map( VipsStreami *streami, size_t *length );
|
const void *vips_streami_map( VipsStreami *streami, size_t *length );
|
||||||
|
VipsBlob *vips_streami_map_blob( VipsStreami *streami );
|
||||||
gint64 vips_streami_seek( VipsStreami *streami, gint64 offset, int whence );
|
gint64 vips_streami_seek( VipsStreami *streami, gint64 offset, int whence );
|
||||||
int vips_streami_rewind( VipsStreami *streami );
|
int vips_streami_rewind( VipsStreami *streami );
|
||||||
size_t vips_streami_sniff_at_most( VipsStreami *streami,
|
size_t vips_streami_sniff_at_most( VipsStreami *streami,
|
||||||
|
@ -74,9 +74,12 @@ typedef struct _VipsArea {
|
|||||||
int count;
|
int count;
|
||||||
GMutex *lock;
|
GMutex *lock;
|
||||||
|
|
||||||
/* Things like ICC profiles need their own free functions.
|
/* Things like ICC profiles need their own free functions.
|
||||||
|
*
|
||||||
|
* Set client to anything you like -- VipsArea doesn't use this.
|
||||||
*/
|
*/
|
||||||
VipsCallbackFn free_fn;
|
VipsCallbackFn free_fn;
|
||||||
|
void *client;
|
||||||
|
|
||||||
/* If we are holding an array (for example, an array of double), the
|
/* If we are holding an array (for example, an array of double), the
|
||||||
* GType of the elements and their size. 0 for not known.
|
* GType of the elements and their size. 0 for not known.
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
* - better rules for hasalpha
|
* - better rules for hasalpha
|
||||||
* 9/10/18
|
* 9/10/18
|
||||||
* - fix up vips_image_dump(), it was still using ints not enums
|
* - fix up vips_image_dump(), it was still using ints not enums
|
||||||
|
* 10/12/19
|
||||||
|
* - add vips_image_new_from_stream() / vips_image_write_to_stream()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2230,6 +2232,8 @@ VipsImage *
|
|||||||
vips_image_new_from_stream( VipsStreami *streami,
|
vips_image_new_from_stream( VipsStreami *streami,
|
||||||
const char *option_string, ... )
|
const char *option_string, ... )
|
||||||
{
|
{
|
||||||
|
const char *filename = vips_stream_filename( VIPS_STREAM( streami ) );
|
||||||
|
|
||||||
const char *operation_name;
|
const char *operation_name;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
int result;
|
int result;
|
||||||
@ -2237,13 +2241,51 @@ vips_image_new_from_stream( VipsStreami *streami,
|
|||||||
|
|
||||||
vips_check_init();
|
vips_check_init();
|
||||||
|
|
||||||
if( !(operation_name = vips_foreign_find_load_stream( streami )) )
|
vips_error_freeze();
|
||||||
return( NULL );
|
operation_name = vips_foreign_find_load_stream( streami );
|
||||||
|
vips_error_thaw();
|
||||||
|
|
||||||
va_start( ap, option_string );
|
if( operation_name ) {
|
||||||
result = vips_call_split_option_string( operation_name,
|
va_start( ap, option_string );
|
||||||
option_string, ap, streami, &out );
|
result = vips_call_split_option_string( operation_name,
|
||||||
va_end( ap );
|
option_string, ap, streami, &out );
|
||||||
|
va_end( ap );
|
||||||
|
}
|
||||||
|
else if( filename ) {
|
||||||
|
/* Try with the old file-based loaders.
|
||||||
|
*/
|
||||||
|
if( !(operation_name = vips_foreign_find_load( filename )) )
|
||||||
|
return( NULL );
|
||||||
|
|
||||||
|
va_start( ap, option_string );
|
||||||
|
result = vips_call_split_option_string( operation_name,
|
||||||
|
option_string, ap, filename, &out );
|
||||||
|
va_end( ap );
|
||||||
|
}
|
||||||
|
else if( vips_streami_is_mappable( streami ) ) {
|
||||||
|
/* Try with the old buffer-based loaders.
|
||||||
|
*/
|
||||||
|
VipsBlob *blob;
|
||||||
|
const void *buf;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if( !(blob = vips_streami_map_blob( streami )) )
|
||||||
|
return( NULL );
|
||||||
|
|
||||||
|
buf = vips_blob_get( blob, &len );
|
||||||
|
if( !(operation_name =
|
||||||
|
vips_foreign_find_load_buffer( buf, len )) ) {
|
||||||
|
vips_area_unref( VIPS_AREA( blob ) );
|
||||||
|
return( NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
va_start( ap, option_string );
|
||||||
|
result = vips_call_split_option_string( operation_name,
|
||||||
|
option_string, ap, blob, &out );
|
||||||
|
va_end( ap );
|
||||||
|
|
||||||
|
vips_area_unref( VIPS_AREA( blob ) );
|
||||||
|
}
|
||||||
|
|
||||||
if( result )
|
if( result )
|
||||||
return( NULL );
|
return( NULL );
|
||||||
|
@ -873,6 +873,8 @@ vips_streami_is_mappable( VipsStreami *streami )
|
|||||||
* This operation can take a long time. Use vips_streami_is_mappable() to
|
* This operation can take a long time. Use vips_streami_is_mappable() to
|
||||||
* check if a streami can be mapped efficiently.
|
* check if a streami can be mapped efficiently.
|
||||||
*
|
*
|
||||||
|
* The pointer is valid for as long as @streami is alive.
|
||||||
|
*
|
||||||
* Returns: a pointer to the start of the file contents, or NULL on error.
|
* Returns: a pointer to the start of the file contents, or NULL on error.
|
||||||
*/
|
*/
|
||||||
const void *
|
const void *
|
||||||
@ -908,6 +910,45 @@ vips_streami_map( VipsStreami *streami, size_t *length_out )
|
|||||||
return( streami->data );
|
return( streami->data );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
vips_streami_map_cb( void *a, void *b )
|
||||||
|
{
|
||||||
|
VipsArea *area = VIPS_AREA( b );
|
||||||
|
GObject *gobject = G_OBJECT( area->client );
|
||||||
|
|
||||||
|
VIPS_UNREF( gobject );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* vips_streami_map_blob:
|
||||||
|
* @streami: input stream to operate on
|
||||||
|
*
|
||||||
|
* Just like vips_streami_map(), but return a #VipsBlob containing the
|
||||||
|
* pointer. @streami will stay alive as long as the result is alive.
|
||||||
|
*
|
||||||
|
* Returns: a new #VipsBlob containing the data, or NULL on error.
|
||||||
|
*/
|
||||||
|
VipsBlob *
|
||||||
|
vips_streami_map_blob( VipsStreami *streami )
|
||||||
|
{
|
||||||
|
const void *buf;
|
||||||
|
size_t len;
|
||||||
|
VipsBlob *blob;
|
||||||
|
|
||||||
|
if( !(buf = vips_streami_map( streami, &len )) ||
|
||||||
|
!(blob = vips_blob_new( vips_streami_map_cb, buf, len )) )
|
||||||
|
return( NULL );
|
||||||
|
|
||||||
|
/* The streami must stay alive until the blob is done.
|
||||||
|
*/
|
||||||
|
g_object_ref( streami );
|
||||||
|
VIPS_AREA( blob )->client = streami;
|
||||||
|
|
||||||
|
return( blob );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* vips_streami_seek:
|
* vips_streami_seek:
|
||||||
* @streami: input stream to operate on
|
* @streami: input stream to operate on
|
||||||
|
@ -121,8 +121,8 @@ class TestCreate:
|
|||||||
sigma = im.deviate()
|
sigma = im.deviate()
|
||||||
mean = im.avg()
|
mean = im.avg()
|
||||||
|
|
||||||
assert sigma == pytest.approx(10, abs=0.2)
|
assert sigma == pytest.approx(10, abs=0.4)
|
||||||
assert mean == pytest.approx(100, abs=0.2)
|
assert mean == pytest.approx(100, abs=0.4)
|
||||||
|
|
||||||
def test_grey(self):
|
def test_grey(self):
|
||||||
im = pyvips.Image.grey(100, 90)
|
im = pyvips.Image.grey(100, 90)
|
||||||
|
Loading…
Reference in New Issue
Block a user