now works woo
python interface plus test and benchmark to go update c++ too I guess oh docs as well sigh
This commit is contained in:
parent
3ed0904fab
commit
9cb2674a77
@ -6,6 +6,7 @@
|
||||
- old code still there as vips_shrink2() for testing
|
||||
- only allow [] for filename options
|
||||
- add memory.h to Python API .. makes tracked highwater visible
|
||||
- added bandjoin_const to add constant bands to an image
|
||||
|
||||
7/5/15 started 8.1.1
|
||||
- oop, vips-8.0 wrapper script should be vips-8.1, thanks Danilo
|
||||
|
6
TODO
6
TODO
@ -1,6 +1,8 @@
|
||||
- started bandjoinconst
|
||||
- pyvips should use bandjoin_const when possible
|
||||
|
||||
see also unaryconst.c
|
||||
benchmark, maybe not worthwhile
|
||||
|
||||
- test suite is broken, float->int mask I guess
|
||||
|
||||
- looks like we have a race in tiled threadcache? see
|
||||
|
||||
|
@ -24,6 +24,8 @@
|
||||
* - sizealike inputs
|
||||
* 27/10/11
|
||||
* - rewrite as a class
|
||||
* 7/11/15
|
||||
* - added bandjoin_const
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -278,5 +280,197 @@ typedef struct _VipsBandjoinConst {
|
||||
|
||||
typedef VipsBandaryClass VipsBandjoinConstClass;
|
||||
|
||||
//G_DEFINE_TYPE( VipsBandjoinConst, vips_bandjoin_const, VIPS_TYPE_BANDARY );
|
||||
G_DEFINE_TYPE( VipsBandjoinConst, vips_bandjoin_const, VIPS_TYPE_BANDARY );
|
||||
|
||||
static void
|
||||
vips_bandjoin_const_finalize( GObject *object )
|
||||
{
|
||||
VipsBandjoinConst *bandjoin = (VipsBandjoinConst *) object;
|
||||
|
||||
VIPS_FREE( bandjoin->c_ready );
|
||||
|
||||
G_OBJECT_CLASS( vips_bandjoin_const_parent_class )->finalize( object );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_bandjoin_const_buffer( VipsBandary *bandary,
|
||||
VipsPel *q, VipsPel **p, int width )
|
||||
{
|
||||
VipsConversion *conversion = (VipsConversion *) bandary;
|
||||
VipsBandjoinConst *bandjoin = (VipsBandjoinConst *) bandary;
|
||||
VipsImage *in = bandary->ready[0];
|
||||
|
||||
/* Output pel size.
|
||||
*/
|
||||
const int ops = VIPS_IMAGE_SIZEOF_PEL( conversion->out );
|
||||
|
||||
/* Input pel size.
|
||||
*/
|
||||
const int ips = VIPS_IMAGE_SIZEOF_PEL( in );
|
||||
|
||||
/* Extra bands size.
|
||||
*/
|
||||
const int ebs = ops - ips;
|
||||
|
||||
VipsPel * restrict p1;
|
||||
VipsPel * restrict q1;
|
||||
int x, z;
|
||||
|
||||
q1 = q;
|
||||
p1 = p[0];
|
||||
|
||||
for( x = 0; x < width; x++ ) {
|
||||
for( z = 0; z < ips; z++ )
|
||||
q1[z] = p1[z];
|
||||
|
||||
p1 += ips;
|
||||
q1 += ips;
|
||||
|
||||
for( z = 0; z < ebs; z++ )
|
||||
q1[z] = bandjoin->c_ready[z];
|
||||
|
||||
q1 += ebs;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
vips_bandjoin_const_build( VipsObject *object )
|
||||
{
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||
VipsBandary *bandary = (VipsBandary *) object;
|
||||
VipsBandjoinConst *bandjoin = (VipsBandjoinConst *) object;
|
||||
|
||||
if( bandjoin->c &&
|
||||
bandjoin->in ) {
|
||||
double *c;
|
||||
int n;
|
||||
|
||||
c = vips_array_double_get( bandjoin->c, &n );
|
||||
|
||||
if( n == 0 )
|
||||
return( vips_bandary_copy( bandary ) );
|
||||
else
|
||||
bandary->out_bands = bandjoin->in->Bands + n;
|
||||
|
||||
bandary->n = 1;
|
||||
bandary->in = &bandjoin->in;
|
||||
|
||||
if( !(bandjoin->c_ready = vips__vector_to_pels( class->nickname,
|
||||
n, bandjoin->in->BandFmt, bandjoin->in->Coding,
|
||||
c, NULL, n )) )
|
||||
return( -1 );
|
||||
|
||||
}
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_bandjoin_const_parent_class )->
|
||||
build( object ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_bandjoin_const_class_init( VipsBandjoinConstClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
|
||||
VipsBandaryClass *bandary_class = VIPS_BANDARY_CLASS( class );
|
||||
|
||||
VIPS_DEBUG_MSG( "vips_bandjoin_const_class_init\n" );
|
||||
|
||||
gobject_class->finalize = vips_bandjoin_const_finalize;
|
||||
gobject_class->set_property = vips_object_set_property;
|
||||
gobject_class->get_property = vips_object_get_property;
|
||||
|
||||
vobject_class->nickname = "bandjoin_const";
|
||||
vobject_class->description = _( "append a constant band to an image" );
|
||||
vobject_class->build = vips_bandjoin_const_build;
|
||||
|
||||
bandary_class->process_line = vips_bandjoin_const_buffer;
|
||||
|
||||
VIPS_ARG_IMAGE( class, "in", 0,
|
||||
_( "Input" ),
|
||||
_( "Input image" ),
|
||||
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||
G_STRUCT_OFFSET( VipsBandjoinConst, in ) );
|
||||
|
||||
VIPS_ARG_BOXED( class, "c", 12,
|
||||
_( "Constants" ),
|
||||
_( "Array of constants to add" ),
|
||||
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||
G_STRUCT_OFFSET( VipsBandjoinConst, c ),
|
||||
VIPS_TYPE_ARRAY_DOUBLE );
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
vips_bandjoin_const_init( VipsBandjoinConst *bandjoin )
|
||||
{
|
||||
/* Init our instance fields.
|
||||
*/
|
||||
}
|
||||
|
||||
static int
|
||||
vips_bandjoin_constv( VipsImage *in, VipsImage **out,
|
||||
double *c, int n, va_list ap )
|
||||
{
|
||||
VipsArrayDouble *array;
|
||||
int result;
|
||||
|
||||
array = vips_array_double_new( c, n );
|
||||
result = vips_call_split( "bandjoin_const", ap, in, out, array );
|
||||
vips_area_unref( VIPS_AREA( array ) );
|
||||
|
||||
return( result );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_bandjoin_const:
|
||||
* @in: (array length=n) (transfer none): array of input images
|
||||
* @out: output image
|
||||
* @c: (array length=n): array of constants to append
|
||||
* @n: number of constants
|
||||
* @...: %NULL-terminated list of optional named arguments
|
||||
*
|
||||
* Append a set of constant bands to an image.
|
||||
*
|
||||
* See also: vips_bandjoin().
|
||||
*
|
||||
* Returns: 0 on success, -1 on error
|
||||
*/
|
||||
int
|
||||
vips_bandjoin_const( VipsImage *in, VipsImage **out, double *c, int n, ... )
|
||||
{
|
||||
va_list ap;
|
||||
int result;
|
||||
|
||||
va_start( ap, n );
|
||||
result = vips_bandjoin_constv( in, out, c, n, ap );
|
||||
va_end( ap );
|
||||
|
||||
return( result );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_bandjoin_const1:
|
||||
* @in: input image
|
||||
* @out: output image
|
||||
* @c: constant to append
|
||||
* @...: %NULL-terminated list of optional named arguments
|
||||
*
|
||||
* Append a single constant band to an image.
|
||||
*
|
||||
* Returns: 0 on success, -1 on error
|
||||
*/
|
||||
int
|
||||
vips_bandjoin_const1( VipsImage *in, VipsImage **out, double c, ... )
|
||||
{
|
||||
va_list ap;
|
||||
int result;
|
||||
|
||||
va_start( ap, c );
|
||||
result = vips_bandjoin_constv( in, out, &c, 1, ap );
|
||||
va_end( ap );
|
||||
|
||||
return( result );
|
||||
}
|
||||
|
@ -229,6 +229,7 @@ vips_conversion_operation_init( void )
|
||||
extern GType vips_replicate_get_type( void );
|
||||
extern GType vips_cast_get_type( void );
|
||||
extern GType vips_bandjoin_get_type( void );
|
||||
extern GType vips_bandjoin_const_get_type( void );
|
||||
extern GType vips_bandrank_get_type( void );
|
||||
extern GType vips_black_get_type( void );
|
||||
extern GType vips_rot_get_type( void );
|
||||
@ -273,6 +274,7 @@ vips_conversion_operation_init( void )
|
||||
vips_replicate_get_type();
|
||||
vips_cast_get_type();
|
||||
vips_bandjoin_get_type();
|
||||
vips_bandjoin_const_get_type();
|
||||
vips_bandrank_get_type();
|
||||
vips_black_get_type();
|
||||
vips_rot_get_type();
|
||||
|
@ -208,65 +208,79 @@ vips_insert_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* Calculate a pixel for an image from a vec of double. Valid while im is
|
||||
* valid. imag can be NULL, meaning all zero for the imaginary component.
|
||||
/* Make a pair of vector constants into a set of formatted pixels. bands can
|
||||
* be 3 while n is 1, meaning expand the constant to the number of bands.
|
||||
* imag can be NULL, meaning all zero for the imaginary component.
|
||||
*/
|
||||
VipsPel *
|
||||
vips__vector_to_ink( const char *domain,
|
||||
VipsImage *im, double *real, double *imag, int n )
|
||||
vips__vector_to_pels( const char *domain,
|
||||
int bands, VipsBandFormat format, VipsCoding coding,
|
||||
double *real, double *imag, int n )
|
||||
{
|
||||
/* Run our pipeline relative to this.
|
||||
*/
|
||||
VipsImage *context = vips_image_new();
|
||||
|
||||
VipsImage **t = (VipsImage **)
|
||||
vips_object_local_array( VIPS_OBJECT( context ), 6 );
|
||||
vips_object_local_array( VIPS_OBJECT( context ), 8 );
|
||||
|
||||
VipsBandFormat format;
|
||||
int bands;
|
||||
VipsImage *in;
|
||||
double *ones;
|
||||
VipsPel *result;
|
||||
int i;
|
||||
|
||||
#ifdef VIPS_DEBUG
|
||||
printf( "vips__vector_to_ink: starting\n" );
|
||||
printf( "vips__vector_to_pels: starting\n" );
|
||||
#endif /*VIPS_DEBUG*/
|
||||
|
||||
vips_image_decode_predict( im, &bands, &format );
|
||||
ones = VIPS_ARRAY( im, n, double );
|
||||
ones = VIPS_ARRAY( context, n, double );
|
||||
for( i = 0; i < n; i++ )
|
||||
ones[i] = 1.0;
|
||||
|
||||
/* Cast vec to match the decoded image.
|
||||
/* Make the real and imaginary parts.
|
||||
*/
|
||||
if( vips_black( &t[1], 1, 1, "bands", bands, NULL ) ||
|
||||
vips_linear( t[1], &t[2], ones, real, n, NULL ) ||
|
||||
vips_cast( t[2], &t[3], format, NULL ) ) {
|
||||
if( vips_black( &t[0], 1, 1, "bands", bands, NULL ) ||
|
||||
vips_linear( t[0], &t[1], ones, real, n, NULL ) ) {
|
||||
g_object_unref( context );
|
||||
return( NULL );
|
||||
}
|
||||
in = t[1];
|
||||
|
||||
if( imag ) {
|
||||
if( vips_black( &t[2], 1, 1, "bands", bands, NULL ) ||
|
||||
vips_linear( t[2], &t[3], ones, imag, n, NULL ) ||
|
||||
vips_complexform( in, t[3], &t[4], NULL ) ) {
|
||||
g_object_unref( context );
|
||||
return( NULL );
|
||||
}
|
||||
in = t[4];
|
||||
}
|
||||
|
||||
/* And now recode the vec to match the original im.
|
||||
/* Cast to the output type and coding.
|
||||
*/
|
||||
if( vips_image_encode( t[3], &t[4], im->Coding ) ||
|
||||
!(t[5] = vips_image_new_memory()) ||
|
||||
vips_image_write( t[4], t[5] ) ) {
|
||||
if( vips_cast( in, &t[5], format, NULL ) ||
|
||||
vips_image_encode( t[5], &t[6], coding ) ) {
|
||||
g_object_unref( context );
|
||||
return( NULL );
|
||||
}
|
||||
in = t[6];
|
||||
|
||||
/* Write to memory, copy to output buffer.
|
||||
*/
|
||||
if( !(t[7] = vips_image_new_memory()) ||
|
||||
vips_image_write( in, t[7] ) ) {
|
||||
g_object_unref( context );
|
||||
return( NULL );
|
||||
}
|
||||
in = t[7];
|
||||
|
||||
if( !(result =
|
||||
VIPS_ARRAY( im, VIPS_IMAGE_SIZEOF_PEL( t[5] ), VipsPel )) ) {
|
||||
VIPS_ARRAY( NULL, VIPS_IMAGE_SIZEOF_PEL( in ), VipsPel )) ) {
|
||||
g_object_unref( context );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
g_assert( VIPS_IMAGE_SIZEOF_PEL( t[5] ) ==
|
||||
VIPS_IMAGE_SIZEOF_PEL( im ) );
|
||||
|
||||
memcpy( result, t[5]->data, VIPS_IMAGE_SIZEOF_PEL( im ) );
|
||||
|
||||
g_object_unref( context );
|
||||
memcpy( result, in->data, VIPS_IMAGE_SIZEOF_PEL( in ) );
|
||||
|
||||
#ifdef VIPS_DEBUG
|
||||
{
|
||||
@ -278,12 +292,43 @@ vips__vector_to_ink( const char *domain,
|
||||
printf( "(%g, %g) ", real[i], imag ? imag[i] : 0 );
|
||||
printf( "\n" );
|
||||
printf( "\tink = " );
|
||||
for( i = 0; i < VIPS_IMAGE_SIZEOF_PEL( im ); i++ )
|
||||
for( i = 0; i < VIPS_IMAGE_SIZEOF_PEL( in ); i++ )
|
||||
printf( "%d ", result[i] );
|
||||
printf( "\n" );
|
||||
}
|
||||
#endif /*VIPS_DEBUG*/
|
||||
|
||||
g_object_unref( context );
|
||||
|
||||
return( result );
|
||||
}
|
||||
|
||||
static void
|
||||
vips__vector_to_ink_cb( VipsObject *object, char *buf )
|
||||
{
|
||||
g_free( buf );
|
||||
}
|
||||
|
||||
/* Calculate a pixel for an image from a vec of double. Valid while im is
|
||||
* valid.
|
||||
*/
|
||||
VipsPel *
|
||||
vips__vector_to_ink( const char *domain,
|
||||
VipsImage *im, double *real, double *imag, int n )
|
||||
{
|
||||
int bands;
|
||||
VipsBandFormat format;
|
||||
VipsPel *result;
|
||||
|
||||
vips_image_decode_predict( im, &bands, &format );
|
||||
|
||||
if( !(result = vips__vector_to_pels( domain,
|
||||
bands, format, im->Coding, real, imag, n )) )
|
||||
return( NULL );
|
||||
|
||||
g_signal_connect( im, "postclose",
|
||||
G_CALLBACK( vips__vector_to_ink_cb ), result );
|
||||
|
||||
return( result );
|
||||
}
|
||||
|
||||
|
@ -171,6 +171,9 @@ int vips__bandalike( const char *domain,
|
||||
|
||||
/* draw
|
||||
*/
|
||||
VipsPel *vips__vector_to_pels( const char *domain,
|
||||
int bands, VipsBandFormat format, VipsCoding coding,
|
||||
double *real, double *imag, int n );
|
||||
VipsPel *vips__vector_to_ink( const char *domain,
|
||||
VipsImage *im, double *real, double *imag, int n );
|
||||
double *vips__ink_to_vector( const char *domain,
|
||||
|
Loading…
Reference in New Issue
Block a user