now compiles with new add.c
compiles, but not tested
This commit is contained in:
parent
370641d25b
commit
ce03da8c71
@ -27,6 +27,7 @@ libarithmetic_la_SOURCES = \
|
||||
math.c \
|
||||
arithmetic.c \
|
||||
binary.c \
|
||||
add.c \
|
||||
power.c \
|
||||
round.c
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif /*HAVE_CONFIG_H*/
|
||||
#include <vips8/intl.h>
|
||||
#include <vips/intl.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -73,33 +73,33 @@ typedef VipsBinaryClass VipsAddClass;
|
||||
G_DEFINE_TYPE( VipsAdd, vips_add, VIPS_TYPE_BINARY );
|
||||
|
||||
#define LOOP( IN, OUT ) { \
|
||||
IN *p1 = (IN *) in[0]; \
|
||||
IN *p2 = (IN *) in[1]; \
|
||||
IN *p1 = (IN *) left; \
|
||||
IN *p2 = (IN *) right; \
|
||||
OUT *q = (OUT *) out; \
|
||||
\
|
||||
for( x = 0; x < sz; x++ ) \
|
||||
q[x] = p1[x] + p2[x]; \
|
||||
}
|
||||
|
||||
static VipsVector *add_vectors[VIPS_FORMAT_LAST] = { NULL };
|
||||
|
||||
static void
|
||||
add_buffer( PEL **in, PEL *out, int width, IMAGE *im )
|
||||
add_buffer( VipsBinary *binary, PEL *out, PEL *left, PEL *right, int width )
|
||||
{
|
||||
VipsArithmeticClass *class = VIPS_ARITHMETIC_GET_CLASS( binary );
|
||||
VipsImage *im = binary->left_processed;
|
||||
|
||||
/* Complex just doubles the size.
|
||||
*/
|
||||
const int sz = width * im->Bands *
|
||||
(vips_bandfmt_iscomplex( im->BandFmt ) ? 2 : 1);
|
||||
(vips_band_format_iscomplex( im->BandFmt ) ? 2 : 1);
|
||||
|
||||
if( vips_vector_get_enabled() &&
|
||||
add_vectors[im->BandFmt] ) {
|
||||
VipsVector *vector = add_vectors[im->BandFmt];
|
||||
VipsVector *v;
|
||||
|
||||
if( (v = vips_arithmetic_get_vector( class, im->BandFmt )) ) {
|
||||
VipsExecutor ex;
|
||||
|
||||
vips_executor_set_program( &ex, vector, sz );
|
||||
vips_executor_set_array( &ex, vector->s[0], in[0] );
|
||||
vips_executor_set_array( &ex, vector->s[1], in[1] );
|
||||
vips_executor_set_program( &ex, v, sz );
|
||||
vips_executor_set_array( &ex, v->s[0], left );
|
||||
vips_executor_set_array( &ex, v->s[1], right );
|
||||
vips_executor_set_destination( &ex, out );
|
||||
|
||||
vips_executor_run( &ex );
|
||||
@ -151,47 +151,6 @@ add_buffer( PEL **in, PEL *out, int width, IMAGE *im )
|
||||
#define D IM_BANDFMT_DOUBLE
|
||||
#define DX IM_BANDFMT_DPCOMPLEX
|
||||
|
||||
VipsVector *
|
||||
im__init_program( VipsVector *vectors[IM_BANDFMT_LAST],
|
||||
VipsBandFmt format_table[IM_BANDFMT_LAST], VipsBandFmt fmt )
|
||||
{
|
||||
int isize = im__sizeof_bandfmt[fmt];
|
||||
int osize = im__sizeof_bandfmt[format_table[fmt]];
|
||||
|
||||
VipsVector *v;
|
||||
|
||||
v = vips_vector_new( "binary arith", osize );
|
||||
|
||||
vips_vector_source_name( v, "s1", isize );
|
||||
vips_vector_source_name( v, "s2", isize );
|
||||
vips_vector_temporary( v, "t1", osize );
|
||||
vips_vector_temporary( v, "t2", osize );
|
||||
|
||||
vectors[fmt] = v;
|
||||
|
||||
return( v );
|
||||
}
|
||||
|
||||
void
|
||||
im__compile_programs( VipsVector *vectors[IM_BANDFMT_LAST] )
|
||||
{
|
||||
int fmt;
|
||||
|
||||
for( fmt = 0; fmt < IM_BANDFMT_LAST; fmt++ ) {
|
||||
if( vectors[fmt] &&
|
||||
!vips_vector_compile( vectors[fmt] ) )
|
||||
IM_FREEF( vips_vector_free, vectors[fmt] );
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf( "im__compile_programs: " );
|
||||
for( fmt = 0; fmt < IM_BANDFMT_LAST; fmt++ )
|
||||
if( vectors[fmt] )
|
||||
printf( "%s ", im_BandFmt2char( fmt ) );
|
||||
printf( "\n" );
|
||||
#endif /*DEBUG*/
|
||||
}
|
||||
|
||||
/* Type promotion for addition. Sign and value preserving. Make sure these
|
||||
* match the case statement in add_buffer() above.
|
||||
*/
|
||||
@ -201,32 +160,30 @@ static int bandfmt_add[10] = {
|
||||
};
|
||||
|
||||
static void
|
||||
build_programs( void )
|
||||
vips_add_class_init( VipsAddClass *class )
|
||||
{
|
||||
static gboolean done = FALSE;
|
||||
|
||||
VipsArithmeticClass *aclass = VIPS_ARITHMETIC_CLASS( class );
|
||||
VipsBinaryClass *bclass = VIPS_BINARY_CLASS( class );
|
||||
VipsVector *v;
|
||||
|
||||
if( done )
|
||||
return;
|
||||
done = TRUE;
|
||||
vips_arithmetic_set_format_table( aclass, bandfmt_add );
|
||||
|
||||
v = im__init_program( add_vectors, bandfmt_add, IM_BANDFMT_UCHAR );
|
||||
v = vips_arithmetic_get_program( aclass, VIPS_FORMAT_UCHAR );
|
||||
vips_vector_asm2( v, "convubw", "t1", "s1" );
|
||||
vips_vector_asm2( v, "convubw", "t2", "s2" );
|
||||
vips_vector_asm3( v, "addw", "d1", "t1", "t2" );
|
||||
|
||||
v = im__init_program( add_vectors, bandfmt_add, IM_BANDFMT_CHAR );
|
||||
v = vips_arithmetic_get_program( aclass, VIPS_FORMAT_CHAR );
|
||||
vips_vector_asm2( v, "convsbw", "t1", "s1" );
|
||||
vips_vector_asm2( v, "convsbw", "t2", "s2" );
|
||||
vips_vector_asm3( v, "addw", "d1", "t1", "t2" );
|
||||
|
||||
v = im__init_program( add_vectors, bandfmt_add, IM_BANDFMT_USHORT );
|
||||
v = vips_arithmetic_get_program( aclass, VIPS_FORMAT_USHORT );
|
||||
vips_vector_asm2( v, "convuwl", "t1", "s1" );
|
||||
vips_vector_asm2( v, "convuwl", "t2", "s2" );
|
||||
vips_vector_asm3( v, "addl", "d1", "t1", "t2" );
|
||||
|
||||
v = im__init_program( add_vectors, bandfmt_add, IM_BANDFMT_SHORT );
|
||||
v = vips_arithmetic_get_program( aclass, VIPS_FORMAT_SHORT );
|
||||
vips_vector_asm2( v, "convswl", "t1", "s1" );
|
||||
vips_vector_asm2( v, "convswl", "t2", "s2" );
|
||||
vips_vector_asm3( v, "addl", "d1", "t1", "t2" );
|
||||
@ -237,14 +194,20 @@ build_programs( void )
|
||||
|
||||
float/double/complex are not handled well
|
||||
|
||||
v = im__init_program( add_vectors, IM_BANDFMT_UINT );
|
||||
v = vips_arithmetic_get_vector( aclass, VIPS_FORMAT_UINT );
|
||||
vips_vector_asm3( v, "addl", "d1", "s1", "s2" );
|
||||
|
||||
v = im__init_program( add_vectors, IM_BANDFMT_INT );
|
||||
v = vips_arithmetic_get_vector( aclass, VIPS_FORMAT_INT );
|
||||
vips_vector_asm3( v, "addl", "d1", "s1", "s2" );
|
||||
|
||||
*/
|
||||
|
||||
im__compile_programs( add_vectors );
|
||||
vips_arithmetic_compile( aclass );
|
||||
|
||||
bclass->process_line = add_buffer;
|
||||
}
|
||||
|
||||
static void
|
||||
vips_add_init( VipsAdd *add )
|
||||
{
|
||||
}
|
||||
|
@ -43,7 +43,7 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif /*HAVE_CONFIG_H*/
|
||||
#include <vips8/intl.h>
|
||||
#include <vips/intl.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -69,8 +69,6 @@ G_DEFINE_ABSTRACT_TYPE( VipsArithmetic, vips_arithmetic, VIPS_TYPE_OPERATION );
|
||||
static int
|
||||
vips_arithmetic_build( VipsObject *object )
|
||||
{
|
||||
VipsArithmetic *arithmetic = VIPS_ARITHMETIC (object);
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_arithmetic_parent_class )->build( object ) )
|
||||
return( -1 );
|
||||
|
||||
@ -110,6 +108,85 @@ vips_arithmetic_init( VipsArithmetic *arithmetic )
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
vips_arithmetic_set_format_table( VipsArithmeticClass *class,
|
||||
VipsBandFormat *format_table )
|
||||
{
|
||||
int i;
|
||||
|
||||
g_assert( !class->format_table );
|
||||
|
||||
class->format_table = format_table;
|
||||
|
||||
for( i = 0; i < VIPS_FORMAT_LAST; i++ ) {
|
||||
int isize = vips_format_sizeof( i );
|
||||
int osize = vips_format_sizeof( (int) format_table[i] );
|
||||
|
||||
VipsVector *v;
|
||||
|
||||
v = vips_vector_new( "arithmetic", osize );
|
||||
|
||||
vips_vector_source_name( v, "s1", isize );
|
||||
vips_vector_source_name( v, "s2", isize );
|
||||
vips_vector_temporary( v, "t1", osize );
|
||||
vips_vector_temporary( v, "t2", osize );
|
||||
|
||||
class->vectors[i] = v;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the stub for this program ... use _get_vector() to get the compiled
|
||||
* code.
|
||||
*/
|
||||
VipsVector *
|
||||
vips_arithmetic_get_program( VipsArithmeticClass *class, VipsBandFormat fmt )
|
||||
{
|
||||
g_assert( (int) fmt >= 0 && (int) fmt < VIPS_FORMAT_LAST );
|
||||
g_assert( !class->vector_program[fmt] );
|
||||
|
||||
class->vector_program[fmt] = TRUE;
|
||||
|
||||
return( class->vectors[fmt] );
|
||||
}
|
||||
|
||||
/* Get the compiled code for this type, if available.
|
||||
*/
|
||||
VipsVector *
|
||||
vips_arithmetic_get_vector( VipsArithmeticClass *class, VipsBandFormat fmt )
|
||||
{
|
||||
g_assert( fmt >= 0 && fmt < VIPS_FORMAT_LAST );
|
||||
|
||||
if( !vips_vector_get_enabled() ||
|
||||
!class->vector_program[fmt] )
|
||||
return( NULL );
|
||||
|
||||
return( class->vectors[fmt] );
|
||||
}
|
||||
|
||||
void
|
||||
vips_arithmetic_compile( VipsArithmeticClass *class )
|
||||
{
|
||||
int i;
|
||||
|
||||
g_assert( class->format_table );
|
||||
|
||||
for( i = 0; i < VIPS_FORMAT_LAST; i++ )
|
||||
if( class->vector_program[i] &&
|
||||
!vips_vector_compile( class->vectors[i] ) )
|
||||
/* If compilation fails, turn off the vector for this
|
||||
* type.
|
||||
*/
|
||||
class->vector_program[i] = FALSE;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf( "vips_arithmetic_compile: " );
|
||||
for( i = 0; i < IM_BANDFMT_LAST; i++ )
|
||||
if( class->vector_program[i] )
|
||||
printf( "%s ", VIPS_ENUM_NICK( VIPS_TYPE_FORMAT, i ) );
|
||||
printf( "\n" );
|
||||
#endif /*DEBUG*/
|
||||
}
|
||||
|
||||
/* Called from iofuncs to init all operations in this dir. Use a plugin system
|
||||
* instead?
|
||||
*/
|
||||
@ -120,3 +197,4 @@ vips_arithmetic_operation_init( void )
|
||||
|
||||
vips_add_get_type();
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,8 @@
|
||||
extern "C" {
|
||||
#endif /*__cplusplus*/
|
||||
|
||||
#include <vips/vector.h>
|
||||
|
||||
#define VIPS_TYPE_ARITHMETIC (vips_arithmetic_get_type())
|
||||
#define VIPS_ARITHMETIC( obj ) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST( (obj), \
|
||||
@ -56,19 +58,35 @@ typedef struct _VipsArithmetic {
|
||||
*/
|
||||
VipsImage *output;
|
||||
|
||||
/* For each input format, what output format. Used for arithmetic
|
||||
* too, since we cast inputs to match.
|
||||
*/
|
||||
VipsFormat *cast_table;
|
||||
} VipsArithmetic;
|
||||
|
||||
typedef struct _VipsArithmeticClass {
|
||||
VipsOperationClass parent_class;
|
||||
|
||||
/* For each input format, what output format. Used for arithmetic
|
||||
* too, since we cast inputs to match.
|
||||
*/
|
||||
VipsBandFormat *format_table;
|
||||
|
||||
/* A vector program for each input type.
|
||||
*/
|
||||
VipsVector *vectors[VIPS_FORMAT_LAST];
|
||||
|
||||
/* ... and if we've set a program for this format.
|
||||
*/
|
||||
gboolean vector_program[VIPS_FORMAT_LAST];
|
||||
} VipsArithmeticClass;
|
||||
|
||||
GType vips_arithmetic_get_type( void );
|
||||
|
||||
void vips_arithmetic_set_format_table( VipsArithmeticClass *klass,
|
||||
VipsBandFormat *format_table );
|
||||
VipsVector *vips_arithmetic_get_vector( VipsArithmeticClass *klass,
|
||||
VipsBandFormat fmt );
|
||||
void vips_arithmetic_compile( VipsArithmeticClass *klass );
|
||||
VipsVector *vips_arithmetic_get_program( VipsArithmeticClass *klass,
|
||||
VipsBandFormat fmt );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /*__cplusplus*/
|
||||
|
@ -34,7 +34,7 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif /*HAVE_CONFIG_H*/
|
||||
#include <vips8/intl.h>
|
||||
#include <vips/intl.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -75,7 +75,7 @@ G_DEFINE_ABSTRACT_TYPE( VipsBinary, vips_binary, VIPS_TYPE_ARITHMETIC );
|
||||
/* For two integer types, the "largest", ie. one which can represent the
|
||||
* full range of both.
|
||||
*/
|
||||
static VipsFormat format_largest[6][6] = {
|
||||
static VipsBandFormat format_largest[6][6] = {
|
||||
/* UC C US S UI I */
|
||||
/* UC */ { UC, S, US, S, UI, I },
|
||||
/* C */ { S, C, I, S, I, I },
|
||||
@ -87,11 +87,11 @@ static VipsFormat format_largest[6][6] = {
|
||||
|
||||
/* For two formats, find one which can represent the full range of both.
|
||||
*/
|
||||
static VipsFormat
|
||||
vips_format_common( VipsFormat a, VipsFormat b )
|
||||
static VipsBandFormat
|
||||
vips_format_common( VipsBandFormat a, VipsBandFormat b )
|
||||
{
|
||||
if( vips_format_iscomplex( a ) ||
|
||||
vips_format_iscomplex( b ) ) {
|
||||
if( vips_band_format_iscomplex( a ) ||
|
||||
vips_band_format_iscomplex( b ) ) {
|
||||
if( a == VIPS_FORMAT_DPCOMPLEX ||
|
||||
b == VIPS_FORMAT_DPCOMPLEX )
|
||||
return( VIPS_FORMAT_DPCOMPLEX );
|
||||
@ -99,8 +99,8 @@ vips_format_common( VipsFormat a, VipsFormat b )
|
||||
return( VIPS_FORMAT_COMPLEX );
|
||||
|
||||
}
|
||||
else if( vips_format_isfloat( a ) ||
|
||||
vips_format_isfloat( b ) ) {
|
||||
else if( vips_band_format_isfloat( a ) ||
|
||||
vips_band_format_isfloat( b ) ) {
|
||||
if( a == VIPS_FORMAT_DOUBLE ||
|
||||
b == VIPS_FORMAT_DOUBLE )
|
||||
return( VIPS_FORMAT_DOUBLE );
|
||||
@ -115,13 +115,13 @@ int
|
||||
vips__formatalike_vec( VipsImage **in, VipsImage **out, int n )
|
||||
{
|
||||
int i;
|
||||
VipsFormat format;
|
||||
VipsBandFormat format;
|
||||
|
||||
g_assert( n >= 1 );
|
||||
|
||||
format = in[0]->BandFmt;
|
||||
for( i = 1; i < n; i++ )
|
||||
fmt = vips_format_common( format, in[i]->BandFmt );
|
||||
format = vips_format_common( format, in[i]->BandFmt );
|
||||
|
||||
for( i = 0; i < n; i++ )
|
||||
if( im_clip2fmt( in[i], out[i], format ) )
|
||||
@ -219,6 +219,7 @@ vips_binary_process_region( VipsRegion *or, void *seq, void *a, void *b )
|
||||
{
|
||||
VipsRegion **ir = (VipsRegion **) seq;
|
||||
VipsBinary *binary = VIPS_BINARY( b );
|
||||
VipsBinaryClass *class = VIPS_BINARY_GET_CLASS( binary );
|
||||
|
||||
PEL *p[MAX_INPUT_IMAGES], *q;
|
||||
int i, y;
|
||||
@ -237,7 +238,7 @@ vips_binary_process_region( VipsRegion *or, void *seq, void *a, void *b )
|
||||
for( y = 0; y < or->valid.height; y++ ) {
|
||||
/* Bizarre double-cast stops a bogus gcc 4.1 compiler warning.
|
||||
*/
|
||||
binary->process_line( binary, q, p[0], p[1], or->valid.width );
|
||||
class->process_line( binary, q, p[0], p[1], or->valid.width );
|
||||
|
||||
for( i = 0; ir[i]; i++ )
|
||||
p[i] += VIPS_REGION_LSKIP( ir[i] );
|
||||
@ -253,6 +254,7 @@ vips_binary_build( VipsObject *object )
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||
const char *domain = class->description;
|
||||
VipsArithmetic *arithmetic = VIPS_ARITHMETIC( object );
|
||||
VipsArithmeticClass *aclass = VIPS_ARITHMETIC_GET_CLASS( arithmetic );
|
||||
VipsBinary *binary = VIPS_BINARY( object );
|
||||
|
||||
VipsImage *t[5];
|
||||
@ -284,15 +286,15 @@ vips_binary_build( VipsObject *object )
|
||||
/* Hint demand style. Being a buffer processor, we are happiest with
|
||||
* thin strips.
|
||||
*/
|
||||
if( vips_demand_hint_array( binary->output,
|
||||
if( vips_demand_hint_array( arithmetic->output,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, t + 2 ) ||
|
||||
vips_image_copy_fields_array( binary->output, t + 2 ) )
|
||||
vips_image_copy_fields_array( arithmetic->output, t + 2 ) )
|
||||
return( -1 );
|
||||
|
||||
binary->output->Bands = t[2]->Bands;
|
||||
binary->output->BandFmt = arithmetic->cast_table[t[2]->BandFmt];
|
||||
arithmetic->output->Bands = t[2]->Bands;
|
||||
arithmetic->output->BandFmt = aclass->format_table[t[2]->BandFmt];
|
||||
|
||||
if( vips_image_generate( binary->output,
|
||||
if( vips_image_generate( arithmetic->output,
|
||||
vips_start_many, vips_binary_process_region,
|
||||
vips_stop_many,
|
||||
t + 2, binary ) )
|
||||
|
@ -46,8 +46,9 @@ extern "C" {
|
||||
#define VIPS_BINARY_GET_CLASS( obj ) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS( (obj), VIPS_TYPE_BINARY, VipsBinaryClass ))
|
||||
|
||||
typedef void (*VipsBinaryProcessFn)( VipsBinary *binary,
|
||||
void *out, void *left, void *right, int width );
|
||||
struct _VipsBinary;
|
||||
typedef void (*VipsBinaryProcessFn)( struct _VipsBinary *binary,
|
||||
PEL *out, PEL *left, PEL *right, int width );
|
||||
|
||||
typedef struct _VipsBinary {
|
||||
VipsArithmetic parent_instance;
|
||||
@ -66,9 +67,8 @@ typedef struct _VipsBinary {
|
||||
VipsImage *left_processed;
|
||||
VipsImage *right_processed;
|
||||
|
||||
/* The line processor, plus some client data.
|
||||
/* Some client data for the line processor, if it wants it.
|
||||
*/
|
||||
VipsBinaryProcessFn process_line;
|
||||
void *a;
|
||||
void *b;
|
||||
} VipsBinary;
|
||||
@ -76,6 +76,10 @@ typedef struct _VipsBinary {
|
||||
typedef struct _VipsBinaryClass {
|
||||
VipsArithmeticClass parent_class;
|
||||
|
||||
/* The line processor.
|
||||
*/
|
||||
VipsBinaryProcessFn process_line;
|
||||
|
||||
} VipsBinaryClass;
|
||||
|
||||
GType vips_binary_get_type( void );
|
||||
|
Loading…
Reference in New Issue
Block a user