WiP: Add radload stream/buffer

TODO: Does streamib supports non-seekable streams?
(cherry picked from commit bc99b26b4e0326267ffea3b34d5e4a67c7866c1b)
This commit is contained in:
Kleis Auke Wolthuizen 2019-11-08 14:28:18 +01:00 committed by John Cupitt
parent cefa82bacf
commit 51ac7a6d8c
3 changed files with 251 additions and 0 deletions

View File

@ -1978,6 +1978,8 @@ void
vips_foreign_operation_init( void )
{
extern GType vips_foreign_load_rad_get_type( void );
extern GType vips_foreign_load_rad_buffer_get_type( void );
extern GType vips_foreign_load_rad_stream_get_type( void );
extern GType vips_foreign_save_rad_file_get_type( void );
extern GType vips_foreign_save_rad_buffer_get_type( void );
extern GType vips_foreign_save_rad_stream_get_type( void );
@ -2071,6 +2073,8 @@ vips_foreign_operation_init( void )
#ifdef HAVE_RADIANCE
vips_foreign_load_rad_get_type();
vips_foreign_load_rad_buffer_get_type();
vips_foreign_load_rad_stream_get_type();
vips_foreign_save_rad_file_get_type();
vips_foreign_save_rad_buffer_get_type();
vips_foreign_save_rad_stream_get_type();

View File

@ -52,6 +52,82 @@
#ifdef HAVE_RADIANCE
typedef struct _VipsForeignLoadRadStream {
VipsForeignLoad parent_object;
/* Load from a stream.
*/
VipsStreami *input;
} VipsForeignLoadRadStream;
typedef VipsForeignLoadClass VipsForeignLoadRadStreamClass;
G_DEFINE_TYPE( VipsForeignLoadRadStream, vips_foreign_load_rad_stream,
VIPS_TYPE_FOREIGN_LOAD );
static VipsForeignFlags
vips_foreign_load_rad_stream_get_flags( VipsForeignLoad *load )
{
/* The rad reader supports sequential read.
*/
return( VIPS_FOREIGN_SEQUENTIAL );
}
static int
vips_foreign_load_rad_stream_header( VipsForeignLoad *load )
{
VipsForeignLoadRadStream *stream = (VipsForeignLoadRadStream *) load;
if( vips__rad_header( stream->input, load->out ) )
return( -1 );
return( 0 );
}
static int
vips_foreign_load_rad_stream_load( VipsForeignLoad *load )
{
VipsForeignLoadRadStream *stream = (VipsForeignLoadRadStream *) load;
if( vips__rad_load( stream->input, load->real ) )
return( -1 );
return( 0 );
}
static void
vips_foreign_load_rad_stream_class_init( VipsForeignLoadRadStreamClass *class )
{
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
object_class->nickname = "radload_stream";
object_class->description = _( "load rad from stream" );
load_class->is_a_stream = vips__rad_israd;
load_class->get_flags = vips_foreign_load_rad_stream_get_flags;
load_class->header = vips_foreign_load_rad_stream_header;
load_class->load = vips_foreign_load_rad_stream_load;
VIPS_ARG_OBJECT( class, "input", 1,
_( "Input" ),
_( "Stream to load from" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadRadStream, input ),
VIPS_TYPE_STREAMI );
}
static void
vips_foreign_load_rad_stream_init( VipsForeignLoadRadStream *stream )
{
}
typedef struct _VipsForeignLoadRad {
VipsForeignLoad parent_object;
@ -172,6 +248,112 @@ vips_foreign_load_rad_init( VipsForeignLoadRad *rad )
{
}
typedef struct _VipsForeignLoadRadBuffer {
VipsForeignLoad parent_object;
/* Load from a buffer.
*/
VipsArea *buf;
} VipsForeignLoadRadBuffer;
typedef VipsForeignLoadClass VipsForeignLoadRadBufferClass;
G_DEFINE_TYPE( VipsForeignLoadRadBuffer, vips_foreign_load_rad_buffer,
VIPS_TYPE_FOREIGN_LOAD );
static gboolean
vips_foreign_load_rad_buffer_is_a_buffer( const void *buf, size_t len )
{
VipsStreami *input;
gboolean result;
if( !(input = vips_streami_new_from_memory( buf, len )) )
return( FALSE );
result = vips__rad_israd( input );
VIPS_UNREF( input );
return( result );
}
static VipsForeignFlags
vips_foreign_load_rad_buffer_get_flags( VipsForeignLoad *load )
{
/* The rad reader supports sequential read.
*/
return( VIPS_FOREIGN_SEQUENTIAL );
}
static int
vips_foreign_load_rad_buffer_header( VipsForeignLoad *load )
{
VipsForeignLoadRadBuffer *buffer = (VipsForeignLoadRadBuffer *) load;
VipsStreami *input;
if( !(input = vips_streami_new_from_memory( buffer->buf->data,
buffer->buf->length )) )
return( -1 );
if( vips__rad_header( input, load->out ) ) {
VIPS_UNREF( input );
return( -1 );
}
VIPS_UNREF( input );
return( 0 );
}
static int
vips_foreign_load_rad_buffer_load( VipsForeignLoad *load )
{
VipsForeignLoadRadBuffer *buffer = (VipsForeignLoadRadBuffer *) load;
VipsStreami *input;
if( !(input = vips_streami_new_from_memory( buffer->buf->data,
buffer->buf->length )) )
return( -1 );
if( vips__rad_load( input, load->real ) ) {
VIPS_UNREF( input );
return( -1 );
}
VIPS_UNREF( input );
return( 0 );
}
static void
vips_foreign_load_rad_buffer_class_init( VipsForeignLoadRadBufferClass *class )
{
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
object_class->nickname = "radload_buffer";
object_class->description = _( "load rad from buffer" );
load_class->is_a_buffer = vips_foreign_load_rad_buffer_is_a_buffer;
load_class->get_flags = vips_foreign_load_rad_buffer_get_flags;
load_class->header = vips_foreign_load_rad_buffer_header;
load_class->load = vips_foreign_load_rad_buffer_load;
VIPS_ARG_BOXED( class, "buffer", 1,
_( "Buffer" ),
_( "Buffer to load from" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadRadBuffer, buf ),
VIPS_TYPE_BLOB );
}
static void
vips_foreign_load_rad_buffer_init( VipsForeignLoadRadBuffer *buffer )
{
}
#endif /*HAVE_RADIANCE*/
/**
@ -211,3 +393,64 @@ vips_radload( const char *filename, VipsImage **out, ... )
return( result );
}
/**
* vips_radload_buffer:
* @buf: (array length=len) (element-type guint8): memory area to load
* @len: (type gsize): size of memory area
* @out: (out): image to write
* @...: %NULL-terminated list of optional named arguments
*
* Exactly as vips_radload(), but read from a HDR-formatted memory block.
*
* You must not free the buffer while @out is active. The
* #VipsObject::postclose signal on @out is a good place to free.
*
* See also: vips_radload().
*
* Returns: 0 on success, -1 on error.
*/
int
vips_radload_buffer( void *buf, size_t len, VipsImage **out, ... )
{
va_list ap;
VipsBlob *blob;
int result;
/* We don't take a copy of the data or free it.
*/
blob = vips_blob_new( NULL, buf, len );
va_start( ap, out );
result = vips_call_split( "radload_buffer", ap, blob, out );
va_end( ap );
vips_area_unref( VIPS_AREA( blob ) );
return( result );
}
/**
* vips_radload_stream:
* @input: stream to load from
* @out: (out): output image
* @...: %NULL-terminated list of optional named arguments
*
* Exactly as vips_radload(), but read from a stream.
*
* See also: vips_radload().
*
* Returns: 0 on success, -1 on error.
*/
int
vips_radload_stream( VipsStreami *input, VipsImage **out, ... )
{
va_list ap;
int result;
va_start( ap, out );
result = vips_call_split( "radload_stream", ap, input, out );
va_end( ap );
return( result );
}

View File

@ -570,8 +570,12 @@ int vips_ppmsave( VipsImage *in, const char *filename, ... )
int vips_matload( const char *filename, VipsImage **out, ... )
__attribute__((sentinel));
int vips_radload_stream( VipsStreami *streami, VipsImage **out, ... )
__attribute__((sentinel));
int vips_radload( const char *filename, VipsImage **out, ... )
__attribute__((sentinel));
int vips_radload_buffer( void *buf, size_t len, VipsImage **out, ... )
__attribute__((sentinel));
int vips_radsave( VipsImage *in, const char *filename, ... )
__attribute__((sentinel));
int vips_radsave_buffer( VipsImage *in, void **buf, size_t *len, ... )