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,
|
||||
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
|
||||
|
|
|
@ -214,6 +214,7 @@ int vips_streami_decode( VipsStreami *streami );
|
|||
ssize_t vips_streami_read( VipsStreami *streami, void *data, size_t length );
|
||||
gboolean vips_streami_is_mappable( VipsStreami *streami );
|
||||
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 );
|
||||
int vips_streami_rewind( VipsStreami *streami );
|
||||
size_t vips_streami_sniff_at_most( VipsStreami *streami,
|
||||
|
|
|
@ -74,9 +74,12 @@ typedef struct _VipsArea {
|
|||
int count;
|
||||
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;
|
||||
void *client;
|
||||
|
||||
/* If we are holding an array (for example, an array of double), the
|
||||
* GType of the elements and their size. 0 for not known.
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
* - better rules for hasalpha
|
||||
* 9/10/18
|
||||
* - 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,
|
||||
const char *option_string, ... )
|
||||
{
|
||||
const char *filename = vips_stream_filename( VIPS_STREAM( streami ) );
|
||||
|
||||
const char *operation_name;
|
||||
va_list ap;
|
||||
int result;
|
||||
|
@ -2237,13 +2241,51 @@ vips_image_new_from_stream( VipsStreami *streami,
|
|||
|
||||
vips_check_init();
|
||||
|
||||
if( !(operation_name = vips_foreign_find_load_stream( streami )) )
|
||||
return( NULL );
|
||||
vips_error_freeze();
|
||||
operation_name = vips_foreign_find_load_stream( streami );
|
||||
vips_error_thaw();
|
||||
|
||||
va_start( ap, option_string );
|
||||
result = vips_call_split_option_string( operation_name,
|
||||
option_string, ap, streami, &out );
|
||||
va_end( ap );
|
||||
if( operation_name ) {
|
||||
va_start( ap, option_string );
|
||||
result = vips_call_split_option_string( operation_name,
|
||||
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 )
|
||||
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
|
||||
* 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.
|
||||
*/
|
||||
const void *
|
||||
|
@ -908,6 +910,45 @@ vips_streami_map( VipsStreami *streami, size_t *length_out )
|
|||
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:
|
||||
* @streami: input stream to operate on
|
||||
|
|
|
@ -121,8 +121,8 @@ class TestCreate:
|
|||
sigma = im.deviate()
|
||||
mean = im.avg()
|
||||
|
||||
assert sigma == pytest.approx(10, abs=0.2)
|
||||
assert mean == pytest.approx(100, abs=0.2)
|
||||
assert sigma == pytest.approx(10, abs=0.4)
|
||||
assert mean == pytest.approx(100, abs=0.4)
|
||||
|
||||
def test_grey(self):
|
||||
im = pyvips.Image.grey(100, 90)
|
||||
|
|
Loading…
Reference in New Issue