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
|
- old code still there as vips_shrink2() for testing
|
||||||
- only allow [] for filename options
|
- only allow [] for filename options
|
||||||
- add memory.h to Python API .. makes tracked highwater visible
|
- 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
|
7/5/15 started 8.1.1
|
||||||
- oop, vips-8.0 wrapper script should be vips-8.1, thanks Danilo
|
- 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
|
- looks like we have a race in tiled threadcache? see
|
||||||
|
|
||||||
|
@ -24,6 +24,8 @@
|
|||||||
* - sizealike inputs
|
* - sizealike inputs
|
||||||
* 27/10/11
|
* 27/10/11
|
||||||
* - rewrite as a class
|
* - rewrite as a class
|
||||||
|
* 7/11/15
|
||||||
|
* - added bandjoin_const
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -278,5 +280,197 @@ typedef struct _VipsBandjoinConst {
|
|||||||
|
|
||||||
typedef VipsBandaryClass VipsBandjoinConstClass;
|
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_replicate_get_type( void );
|
||||||
extern GType vips_cast_get_type( void );
|
extern GType vips_cast_get_type( void );
|
||||||
extern GType vips_bandjoin_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_bandrank_get_type( void );
|
||||||
extern GType vips_black_get_type( void );
|
extern GType vips_black_get_type( void );
|
||||||
extern GType vips_rot_get_type( void );
|
extern GType vips_rot_get_type( void );
|
||||||
@ -273,6 +274,7 @@ vips_conversion_operation_init( void )
|
|||||||
vips_replicate_get_type();
|
vips_replicate_get_type();
|
||||||
vips_cast_get_type();
|
vips_cast_get_type();
|
||||||
vips_bandjoin_get_type();
|
vips_bandjoin_get_type();
|
||||||
|
vips_bandjoin_const_get_type();
|
||||||
vips_bandrank_get_type();
|
vips_bandrank_get_type();
|
||||||
vips_black_get_type();
|
vips_black_get_type();
|
||||||
vips_rot_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 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate a pixel for an image from a vec of double. Valid while im is
|
/* Make a pair of vector constants into a set of formatted pixels. bands can
|
||||||
* valid. imag can be NULL, meaning all zero for the imaginary component.
|
* 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 *
|
VipsPel *
|
||||||
vips__vector_to_ink( const char *domain,
|
vips__vector_to_pels( const char *domain,
|
||||||
VipsImage *im, double *real, double *imag, int n )
|
int bands, VipsBandFormat format, VipsCoding coding,
|
||||||
|
double *real, double *imag, int n )
|
||||||
{
|
{
|
||||||
/* Run our pipeline relative to this.
|
/* Run our pipeline relative to this.
|
||||||
*/
|
*/
|
||||||
VipsImage *context = vips_image_new();
|
VipsImage *context = vips_image_new();
|
||||||
|
|
||||||
VipsImage **t = (VipsImage **)
|
VipsImage **t = (VipsImage **)
|
||||||
vips_object_local_array( VIPS_OBJECT( context ), 6 );
|
vips_object_local_array( VIPS_OBJECT( context ), 8 );
|
||||||
|
|
||||||
VipsBandFormat format;
|
VipsImage *in;
|
||||||
int bands;
|
|
||||||
double *ones;
|
double *ones;
|
||||||
VipsPel *result;
|
VipsPel *result;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
#ifdef VIPS_DEBUG
|
#ifdef VIPS_DEBUG
|
||||||
printf( "vips__vector_to_ink: starting\n" );
|
printf( "vips__vector_to_pels: starting\n" );
|
||||||
#endif /*VIPS_DEBUG*/
|
#endif /*VIPS_DEBUG*/
|
||||||
|
|
||||||
vips_image_decode_predict( im, &bands, &format );
|
ones = VIPS_ARRAY( context, n, double );
|
||||||
ones = VIPS_ARRAY( im, n, double );
|
|
||||||
for( i = 0; i < n; i++ )
|
for( i = 0; i < n; i++ )
|
||||||
ones[i] = 1.0;
|
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 ) ||
|
if( vips_black( &t[0], 1, 1, "bands", bands, NULL ) ||
|
||||||
vips_linear( t[1], &t[2], ones, real, n, NULL ) ||
|
vips_linear( t[0], &t[1], ones, real, n, NULL ) ) {
|
||||||
vips_cast( t[2], &t[3], format, NULL ) ) {
|
|
||||||
g_object_unref( context );
|
g_object_unref( context );
|
||||||
return( NULL );
|
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 ) ||
|
if( vips_cast( in, &t[5], format, NULL ) ||
|
||||||
!(t[5] = vips_image_new_memory()) ||
|
vips_image_encode( t[5], &t[6], coding ) ) {
|
||||||
vips_image_write( t[4], t[5] ) ) {
|
|
||||||
g_object_unref( context );
|
g_object_unref( context );
|
||||||
return( NULL );
|
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 =
|
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 );
|
g_object_unref( context );
|
||||||
return( NULL );
|
return( NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
g_assert( VIPS_IMAGE_SIZEOF_PEL( t[5] ) ==
|
memcpy( result, in->data, VIPS_IMAGE_SIZEOF_PEL( in ) );
|
||||||
VIPS_IMAGE_SIZEOF_PEL( im ) );
|
|
||||||
|
|
||||||
memcpy( result, t[5]->data, VIPS_IMAGE_SIZEOF_PEL( im ) );
|
|
||||||
|
|
||||||
g_object_unref( context );
|
|
||||||
|
|
||||||
#ifdef VIPS_DEBUG
|
#ifdef VIPS_DEBUG
|
||||||
{
|
{
|
||||||
@ -278,12 +292,43 @@ vips__vector_to_ink( const char *domain,
|
|||||||
printf( "(%g, %g) ", real[i], imag ? imag[i] : 0 );
|
printf( "(%g, %g) ", real[i], imag ? imag[i] : 0 );
|
||||||
printf( "\n" );
|
printf( "\n" );
|
||||||
printf( "\tink = " );
|
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( "%d ", result[i] );
|
||||||
printf( "\n" );
|
printf( "\n" );
|
||||||
}
|
}
|
||||||
#endif /*VIPS_DEBUG*/
|
#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 );
|
return( result );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,6 +171,9 @@ int vips__bandalike( const char *domain,
|
|||||||
|
|
||||||
/* draw
|
/* 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,
|
VipsPel *vips__vector_to_ink( const char *domain,
|
||||||
VipsImage *im, double *real, double *imag, int n );
|
VipsImage *im, double *real, double *imag, int n );
|
||||||
double *vips__ink_to_vector( const char *domain,
|
double *vips__ink_to_vector( const char *domain,
|
||||||
|
Loading…
Reference in New Issue
Block a user