new im_aconv() compiles

compiled and linked in, needs testing though
This commit is contained in:
John Cupitt 2011-06-08 13:37:03 +01:00
parent 2d717ec578
commit 69331fab9f
5 changed files with 160 additions and 199 deletions

View File

@ -4,6 +4,7 @@ libconvolution_la_SOURCES = \
convol_dispatch.c \ convol_dispatch.c \
im_addgnoise.c \ im_addgnoise.c \
im_compass.c \ im_compass.c \
im_aconv.c \
im_aconvsep.c \ im_aconvsep.c \
im_conv.c \ im_conv.c \
im_conv_f.c \ im_conv_f.c \

View File

@ -426,6 +426,39 @@ static im_function spcor_desc = {
two_in_one_out /* Arg list */ two_in_one_out /* Arg list */
}; };
/* Args for im_aconv().
*/
static im_arg_desc aconv_args[] = {
IM_INPUT_IMAGE( "in" ),
IM_OUTPUT_IMAGE( "out" ),
IM_INPUT_DMASK( "matrix" ),
IM_INPUT_INT( "n_layers" ),
IM_INPUT_INT( "cluster" )
};
/* Call im_aconv via arg vector.
*/
static int
aconv_vec( im_object *argv )
{
im_mask_object *mo = argv[2];
int n_layers = *((int *) argv[3]);
int cluster = *((int *) argv[4]);
return( im_aconv( argv[0], argv[1], mo->mask, n_layers, cluster ) );
}
/* Description of im_aconv.
*/
static im_function aconv_desc = {
"im_aconv", /* Name */
"approximate convolution",
IM_FN_TRANSFORM | IM_FN_PIO, /* Flags */
aconv_vec, /* Dispatch function */
IM_NUMBER( aconv_args ), /* Size of arg list */
aconv_args /* Arg list */
};
/* Args for im_aconvsep(). /* Args for im_aconvsep().
*/ */
static im_arg_desc aconvsep_args[] = { static im_arg_desc aconvsep_args[] = {
@ -450,7 +483,7 @@ aconvsep_vec( im_object *argv )
*/ */
static im_function aconvsep_desc = { static im_function aconvsep_desc = {
"im_aconvsep", /* Name */ "im_aconvsep", /* Name */
"approximate convolution", "approximate separable convolution",
IM_FN_TRANSFORM | IM_FN_PIO, /* Flags */ IM_FN_TRANSFORM | IM_FN_PIO, /* Flags */
aconvsep_vec, /* Dispatch function */ aconvsep_vec, /* Dispatch function */
IM_NUMBER( aconvsep_args ), /* Size of arg list */ IM_NUMBER( aconvsep_args ), /* Size of arg list */
@ -461,6 +494,7 @@ static im_function aconvsep_desc = {
*/ */
static im_function *convol_list[] = { static im_function *convol_list[] = {
&aconvsep_desc, &aconvsep_desc,
&aconv_desc,
&addgnoise_desc, &addgnoise_desc,
&compass_desc, &compass_desc,
&contrast_surface_desc, &contrast_surface_desc,

View File

@ -52,8 +52,6 @@
- are we handling mask offset correctly? - are we handling mask offset correctly?
- just done boxes_new()
*/ */
/* Show sample pixels as they are transformed. /* Show sample pixels as they are transformed.
@ -151,7 +149,7 @@ boxes_start( Boxes *boxes, int x )
} }
static int static int
boxes_end( Boxes *lines, int x, int y, int factor ) boxes_end( Boxes *boxes, int x, int y, int factor )
{ {
boxes->end[boxes->n_hlines] = x; boxes->end[boxes->n_hlines] = x;
@ -209,7 +207,7 @@ boxes_merge( Boxes *boxes, int a, int b )
if( boxes->band[i] == b ) if( boxes->band[i] == b )
boxes->band[i] = a; boxes->band[i] = a;
/* Delete b. /* Mark b to be deleted.
*/ */
boxes->weight[b] = 0; boxes->weight[b] = 0;
} }
@ -230,13 +228,13 @@ boxes_cluster( Boxes *boxes, int cluster )
if( boxes->weight[i] == 0 ) if( boxes->weight[i] == 0 )
continue; continue;
for( j = i + 1; j < lines->n_lines; j++ ) { for( j = i + 1; j < boxes->n_hlines; j++ ) {
int d; int d;
if( boxes->weight[j] == 0 ) if( boxes->weight[j] == 0 )
continue; continue;
d = lines_distance( lines, i, j ); d = boxes_distance( boxes, i, j );
if( d < best ) { if( d < best ) {
best = d; best = d;
a = i; a = i;
@ -344,7 +342,6 @@ boxes_new( IMAGE *in, IMAGE *out, DOUBLEMASK *mask, int n_layers, int cluster )
/* For each layer, generate a set of lines which are inside the /* For each layer, generate a set of lines which are inside the
* perimeter. Work down from the top. * perimeter. Work down from the top.
*/ */
band_offset = 0;
for( z = 0; z < n_layers; z++ ) { for( z = 0; z < n_layers; z++ ) {
/* How deep we are into the mask, as a double we can test /* How deep we are into the mask, as a double we can test
* against. Add half the layer depth so we can easily find >50% * against. Add half the layer depth so we can easily find >50%
@ -371,25 +368,25 @@ boxes_new( IMAGE *in, IMAGE *out, DOUBLEMASK *mask, int n_layers, int cluster )
* inside. Is our current square (x, y) part * inside. Is our current square (x, y) part
* of that line? * of that line?
*/ */
if( (y_positive && coeff >= y_ph) || if( (z_positive && coeff >= z_ph) ||
(!y_positive && coeff <= y_ph) ) { (!z_positive && coeff <= z_ph) ) {
if( !inside ) { if( !inside ) {
boxes_start( lines, x ); boxes_start( boxes, x );
inside = 1; inside = 1;
} }
} }
else { else {
if( inside ) { if( inside ) {
boxes_end( lines, x, y, boxes_end( boxes, x, y,
y_positive ? 1 : -1 ); z_positive ? 1 : -1 );
inside = 0; inside = 0;
} }
} }
} }
if( inside && if( inside &&
boxes_end( lines, mask->xsize, y, boxes_end( boxes, mask->xsize, y,
y_positive ? 1 : -1 ) ) z_positive ? 1 : -1 ) )
return( NULL ); return( NULL );
} }
} }
@ -422,7 +419,7 @@ boxes_new( IMAGE *in, IMAGE *out, DOUBLEMASK *mask, int n_layers, int cluster )
x = boxes->factor[0]; x = boxes->factor[0];
for( y = 1; y < boxes->n_vlines; y++ ) for( y = 1; y < boxes->n_vlines; y++ )
x = gcd( x, boxes->factor[y] ); x = gcd( x, boxes->factor[y] );
for( y = 0; y < boxes->n_lines; y++ ) for( y = 0; y < boxes->n_vlines; y++ )
boxes->factor[y] /= x; boxes->factor[y] /= x;
boxes->area *= x; boxes->area *= x;
@ -441,7 +438,7 @@ boxes_new( IMAGE *in, IMAGE *out, DOUBLEMASK *mask, int n_layers, int cluster )
for( y = 0; y < boxes->n_vlines; y++ ) { for( y = 0; y < boxes->n_vlines; y++ ) {
printf( "%3d - %2d x ", y, boxes->factor[z] ); printf( "%3d - %2d x ", y, boxes->factor[z] );
for( x = 0; x < 55; x++ ) { for( x = 0; x < 55; x++ ) {
int rx = x * (width + 1) / 55; int rx = x * (mask->xsize + 1) / 55;
int b = boxes->band[y]; int b = boxes->band[y];
if( rx >= boxes->start[b] && rx < boxes->end[b] ) if( rx >= boxes->start[b] && rx < boxes->end[b] )
@ -461,13 +458,17 @@ boxes_new( IMAGE *in, IMAGE *out, DOUBLEMASK *mask, int n_layers, int cluster )
*/ */
typedef struct { typedef struct {
Boxes *boxes; Boxes *boxes;
REGION *ir; /* Input region */ REGION *ir; /* Input region */
int *start; /* Offsets for start and stop */ /* For the horizontal pass, offsets for start and stop. For the
* vertical pass, just use just start to get the offsets to sum.
*/
int *start;
int *end; int *end;
/* The sums for each line. int for integer types, double for floating /* For the horizontal pass, the rolling sums. int for integer types,
* point types. * double for floating point types.
*/ */
void *sum; void *sum;
@ -492,7 +493,7 @@ static void *
aconv_start( IMAGE *out, void *a, void *b ) aconv_start( IMAGE *out, void *a, void *b )
{ {
IMAGE *in = (IMAGE *) a; IMAGE *in = (IMAGE *) a;
Lines *lines = (Lines *) b; Boxes *boxes = (Boxes *) b;
AConvSequence *seq; AConvSequence *seq;
@ -501,18 +502,25 @@ aconv_start( IMAGE *out, void *a, void *b )
/* Init! /* Init!
*/ */
seq->lines = lines; seq->boxes = boxes;
seq->ir = im_region_create( in ); seq->ir = im_region_create( in );
seq->start = IM_ARRAY( out, lines->n_lines, int );
seq->end = IM_ARRAY( out, lines->n_lines, int ); /* There will always be more vlines than hlines, so make the arrays
* vlines big and we'll have room for both.
*/
g_assert( boxes->n_vlines > boxes->n_hlines );
seq->start = IM_ARRAY( out, boxes->n_vlines, int );
seq->end = IM_ARRAY( out, boxes->n_vlines, int );
if( vips_band_format_isint( out->BandFmt ) ) if( vips_band_format_isint( out->BandFmt ) )
seq->sum = IM_ARRAY( out, lines->n_lines, int ); seq->sum = IM_ARRAY( out, boxes->n_vlines, int );
else else
seq->sum = IM_ARRAY( out, lines->n_lines, double ); seq->sum = IM_ARRAY( out, boxes->n_vlines, double );
seq->last_stride = -1; seq->last_stride = -1;
if( !seq->ir || !seq->start || !seq->end || !seq->sum ) { if( !seq->ir || !seq->start || !seq->end || !seq->sum ) {
aconv_stop( seq, in, lines ); aconv_stop( seq, in, boxes );
return( NULL ); return( NULL );
} }
@ -557,82 +565,6 @@ G_STMT_START { \
* them separate for easy debugging. * them separate for easy debugging.
*/ */
#define HCONV_INT( TYPE, CLIP ) { \
for( i = 0; i < bands; i++ ) { \
int *seq_sum = (int *) seq->sum; \
\
TYPE *q; \
TYPE *p; \
int sum; \
\
p = i + (TYPE *) IM_REGION_ADDR( ir, r->left, r->top + y ); \
q = i + (TYPE *) IM_REGION_ADDR( or, r->left, r->top + y ); \
\
sum = 0; \
for( z = 0; z < lines->n_lines; z++ ) { \
seq_sum[z] = 0; \
for( x = lines->start[z]; x < lines->end[z]; x++ ) \
seq_sum[z] += p[x * istride]; \
sum += lines->factor[z] * seq_sum[z]; \
} \
sum = (sum + lines->rounding) / lines->area; \
CLIP( sum ); \
*q = sum; \
q += ostride; \
\
for( x = 1; x < r->width; x++ ) { \
sum = 0; \
for( z = 0; z < lines->n_lines; z++ ) { \
seq_sum[z] += p[seq->end[z]]; \
seq_sum[z] -= p[seq->start[z]]; \
sum += lines->factor[z] * seq_sum[z]; \
} \
p += istride; \
sum = (sum + lines->rounding) / lines->area; \
CLIP( sum ); \
*q = sum; \
q += ostride; \
} \
} \
}
#define HCONV_FLOAT( TYPE ) { \
for( i = 0; i < bands; i++ ) { \
double *seq_sum = (double *) seq->sum; \
\
TYPE *q; \
TYPE *p; \
double sum; \
\
p = i + (TYPE *) IM_REGION_ADDR( ir, r->left, r->top + y ); \
q = i + (TYPE *) IM_REGION_ADDR( or, r->left, r->top + y ); \
\
sum = 0; \
for( z = 0; z < lines->n_lines; z++ ) { \
seq_sum[z] = 0; \
for( x = lines->start[z]; x < lines->end[z]; x++ ) \
seq_sum[z] += p[x * istride]; \
sum += lines->factor[z] * seq_sum[z]; \
} \
sum = sum / lines->area + mask->offset; \
*q = sum; \
q += ostride; \
\
for( x = 1; x < r->width; x++ ) { \
sum = 0; \
for( z = 0; z < lines->n_lines; z++ ) { \
seq_sum[z] += p[seq->end[z]]; \
seq_sum[z] -= p[seq->start[z]]; \
sum += lines->factor[z] * seq_sum[z]; \
} \
p += istride; \
sum = sum / lines->area + mask->offset; \
*q = sum; \
q += ostride; \
} \
} \
}
/* Do horizontal masks ... we scan the mask along scanlines. /* Do horizontal masks ... we scan the mask along scanlines.
*/ */
static int static int
@ -640,11 +572,11 @@ aconv_hgenerate( REGION *or, void *vseq, void *a, void *b )
{ {
AConvSequence *seq = (AConvSequence *) vseq; AConvSequence *seq = (AConvSequence *) vseq;
IMAGE *in = (IMAGE *) a; IMAGE *in = (IMAGE *) a;
Lines *lines = (Lines *) b; Boxes *boxes = (Boxes *) b;
REGION *ir = seq->ir; REGION *ir = seq->ir;
const int n_lines = lines->n_lines; const int n_hlines = boxes->n_hlines;
DOUBLEMASK *mask = lines->mask; DOUBLEMASK *mask = boxes->mask;
Rect *r = &or->valid; Rect *r = &or->valid;
/* Double the bands (notionally) for complex. /* Double the bands (notionally) for complex.
@ -671,23 +603,61 @@ aconv_hgenerate( REGION *or, void *vseq, void *a, void *b )
*/ */
istride = IM_IMAGE_SIZEOF_PEL( in ) / istride = IM_IMAGE_SIZEOF_PEL( in ) /
IM_IMAGE_SIZEOF_ELEMENT( in ); IM_IMAGE_SIZEOF_ELEMENT( in );
ostride = IM_IMAGE_SIZEOF_PEL( lines->out ) / ostride = IM_IMAGE_SIZEOF_PEL( boxes->out ) /
IM_IMAGE_SIZEOF_ELEMENT( lines->out ); IM_IMAGE_SIZEOF_ELEMENT( boxes->out );
/* Init offset array. /* Init offset array.
*/ */
if( seq->last_stride != istride ) { if( seq->last_stride != istride ) {
seq->last_stride = istride; seq->last_stride = istride;
for( z = 0; z < n_lines; z++ ) { for( z = 0; z < n_hlines; z++ ) {
seq->start[z] = lines->start[z] * istride; seq->start[z] = boxes->start[z] * istride;
seq->end[z] = lines->end[z] * istride; seq->end[z] = boxes->end[z] * istride;
} }
} }
for( y = 0; y < r->height; y++ ) { for( y = 0; y < r->height; y++ ) {
switch( in->BandFmt ) { switch( in->BandFmt ) {
case IM_BANDFMT_UCHAR: case IM_BANDFMT_UCHAR:
for( i = 0; i < bands; i++ ) {
int *seq_sum = (int *) seq->sum;
PEL *p;
int *q;
int sum;
p = i + (PEL *) IM_REGION_ADDR( ir, r->left, r->top + y );
q = i + (int *) IM_REGION_ADDR( or, r->left, r->top + y );
sum = 0;
for( z = 0; z < n_hlines; z++ ) {
seq_sum[z] = 0;
for( x = boxes->start[z]; x < boxes->end[z]; x++ )
seq_sum[z] += p[x * istride];
sum += boxes->factor[z] * seq_sum[z];
}
*q = sum;
q += ostride;
for( x = 1; x < r->width; x++ ) {
sum = 0;
for( z = 0; z < n_hlines; z++ ) {
seq_sum[z] += p[seq->end[z]];
seq_sum[z] -= p[seq->start[z]];
sum += seq_sum[z];
}
p += istride;
*q = sum;
q += ostride;
}
}
break;
/*
case IM_BANDFMT_UCHAR:
HCONV_INT( unsigned char, CLIP_UCHAR ); HCONV_INT( unsigned char, CLIP_UCHAR );
break; break;
@ -726,6 +696,7 @@ aconv_hgenerate( REGION *or, void *vseq, void *a, void *b )
case IM_BANDFMT_DPCOMPLEX: case IM_BANDFMT_DPCOMPLEX:
HCONV_FLOAT( double ); HCONV_FLOAT( double );
break; break;
*/
default: default:
g_assert( 0 ); g_assert( 0 );
@ -750,6 +721,8 @@ aconv_horizontal( Boxes *boxes, IMAGE *in, IMAGE *out )
return( -1 ); return( -1 );
} }
out->Bands *= boxes->n_hlines; out->Bands *= boxes->n_hlines;
out->BandFmt = vips_band_format_isfloat( in->BandFmt ) ?
VIPS_FORMAT_DOUBLE : VIPS_FORMAT_INT;
if( im_demand_hint( out, IM_SMALLTILE, in, NULL ) || if( im_demand_hint( out, IM_SMALLTILE, in, NULL ) ||
im_generate( out, im_generate( out,
@ -762,82 +735,6 @@ aconv_horizontal( Boxes *boxes, IMAGE *in, IMAGE *out )
return( 0 ); return( 0 );
} }
#define VCONV_INT( TYPE, CLIP ) { \
for( x = 0; x < sz; x++ ) { \
int *seq_sum = (int *) seq->sum; \
\
TYPE *q; \
TYPE *p; \
int sum; \
\
p = x + (TYPE *) IM_REGION_ADDR( ir, r->left, r->top ); \
q = x + (TYPE *) IM_REGION_ADDR( or, r->left, r->top ); \
\
sum = 0; \
for( z = 0; z < lines->n_lines; z++ ) { \
seq_sum[z] = 0; \
for( y = lines->start[z]; y < lines->end[z]; y++ ) \
seq_sum[z] += p[y * istride]; \
sum += lines->factor[z] * seq_sum[z]; \
} \
sum = (sum + lines->rounding) / lines->area; \
CLIP( sum ); \
*q = sum; \
q += ostride; \
\
for( y = 1; y < r->height; y++ ) { \
sum = 0; \
for( z = 0; z < lines->n_lines; z++ ) { \
seq_sum[z] += p[seq->end[z]]; \
seq_sum[z] -= p[seq->start[z]]; \
sum += lines->factor[z] * seq_sum[z]; \
} \
p += istride; \
sum = (sum + lines->rounding) / lines->area; \
CLIP( sum ); \
*q = sum; \
q += ostride; \
} \
} \
}
#define VCONV_FLOAT( TYPE ) { \
for( x = 0; x < sz; x++ ) { \
double *seq_sum = (double *) seq->sum; \
\
TYPE *q; \
TYPE *p; \
double sum; \
\
p = x + (TYPE *) IM_REGION_ADDR( ir, r->left, r->top ); \
q = x + (TYPE *) IM_REGION_ADDR( or, r->left, r->top ); \
\
sum = 0; \
for( z = 0; z < lines->n_lines; z++ ) { \
seq_sum[z] = 0; \
for( y = lines->start[z]; y < lines->end[z]; y++ ) \
seq_sum[z] += p[y * istride]; \
sum += lines->factor[z] * seq_sum[z]; \
} \
sum = sum / lines->area + mask->offset; \
*q = sum; \
q += ostride; \
\
for( y = 1; y < r->height; y++ ) { \
sum = 0; \
for( z = 0; z < lines->n_lines; z++ ) { \
seq_sum[z] += p[seq->end[z]]; \
seq_sum[z] -= p[seq->start[z]]; \
sum += lines->factor[z] * seq_sum[z]; \
} \
p += istride; \
sum = sum / lines->area + mask->offset; \
*q = sum; \
q += ostride; \
} \
} \
}
/* Do vertical masks ... we scan the mask down columns of pixels. Copy-paste /* Do vertical masks ... we scan the mask down columns of pixels. Copy-paste
* from above with small changes. * from above with small changes.
*/ */
@ -846,11 +743,11 @@ aconv_vgenerate( REGION *or, void *vseq, void *a, void *b )
{ {
AConvSequence *seq = (AConvSequence *) vseq; AConvSequence *seq = (AConvSequence *) vseq;
IMAGE *in = (IMAGE *) a; IMAGE *in = (IMAGE *) a;
Lines *lines = (Lines *) b; Boxes *boxes = (Boxes *) b;
REGION *ir = seq->ir; REGION *ir = seq->ir;
const int n_lines = lines->n_lines; const int n_vlines = boxes->n_vlines;
DOUBLEMASK *mask = lines->mask; DOUBLEMASK *mask = boxes->mask;
Rect *r = &or->valid; Rect *r = &or->valid;
/* Double the width (notionally) for complex. /* Double the width (notionally) for complex.
@ -876,22 +773,47 @@ aconv_vgenerate( REGION *or, void *vseq, void *a, void *b )
* ease of direction change. * ease of direction change.
*/ */
istride = IM_REGION_LSKIP( ir ) / istride = IM_REGION_LSKIP( ir ) /
IM_IMAGE_SIZEOF_ELEMENT( lines->in ); IM_IMAGE_SIZEOF_ELEMENT( boxes->in );
ostride = IM_REGION_LSKIP( or ) / ostride = IM_REGION_LSKIP( or ) /
IM_IMAGE_SIZEOF_ELEMENT( lines->out ); IM_IMAGE_SIZEOF_ELEMENT( boxes->out );
/* Init offset array. /* Init offset array.
*/ */
if( seq->last_stride != istride ) { if( seq->last_stride != istride ) {
seq->last_stride = istride; seq->last_stride = istride;
for( z = 0; z < n_lines; z++ ) { for( z = 0; z < n_vlines; z++ )
seq->start[z] = lines->start[z] * istride; seq->start[z] = boxes->band[z] +
seq->end[z] = lines->end[z] * istride; boxes->row[z] * istride;
}
} }
switch( in->BandFmt ) { switch( in->BandFmt ) {
case IM_BANDFMT_UCHAR:
for( x = 0; x < sz; x++ ) {
int *p;
PEL *q;
int sum;
p = x * boxes->n_hlines +
(int *) IM_REGION_ADDR( ir, r->left, r->top );
q = x + (PEL *) IM_REGION_ADDR( or, r->left, r->top );
for( y = 0; y < r->height; y++ ) {
sum = 0;
for( z = 0; z < n_vlines; z++ )
sum += boxes->factor[z] * p[seq->start[z]];
p += istride;
sum = (sum + boxes->rounding) / boxes->area;
CLIP_UCHAR( sum );
*q = sum;
q += ostride;
}
}
break;
/*
case IM_BANDFMT_UCHAR: case IM_BANDFMT_UCHAR:
VCONV_INT( unsigned char, CLIP_UCHAR ); VCONV_INT( unsigned char, CLIP_UCHAR );
break; break;
@ -931,6 +853,7 @@ aconv_vgenerate( REGION *or, void *vseq, void *a, void *b )
case IM_BANDFMT_DPCOMPLEX: case IM_BANDFMT_DPCOMPLEX:
VCONV_FLOAT( double ); VCONV_FLOAT( double );
break; break;
*/
default: default:
g_assert( 0 ); g_assert( 0 );
@ -953,7 +876,8 @@ aconv_vertical( Boxes *boxes, IMAGE *in, IMAGE *out )
im_error( "im_aconv", "%s", _( "image too small for mask" ) ); im_error( "im_aconv", "%s", _( "image too small for mask" ) );
return( -1 ); return( -1 );
} }
out->Bands /= boxes->n_hlines; out->Bands = boxes->in->Bands;
out->BandFmt = boxes->in->BandFmt;
if( im_demand_hint( out, IM_SMALLTILE, in, NULL ) || if( im_demand_hint( out, IM_SMALLTILE, in, NULL ) ||
im_generate( out, im_generate( out,

View File

@ -435,7 +435,7 @@ G_STMT_START { \
q = i + (TYPE *) IM_REGION_ADDR( or, r->left, r->top + y ); \ q = i + (TYPE *) IM_REGION_ADDR( or, r->left, r->top + y ); \
\ \
sum = 0; \ sum = 0; \
for( z = 0; z < lines->n_lines; z++ ) { \ for( z = 0; z < n_lines; z++ ) { \
seq_sum[z] = 0; \ seq_sum[z] = 0; \
for( x = lines->start[z]; x < lines->end[z]; x++ ) \ for( x = lines->start[z]; x < lines->end[z]; x++ ) \
seq_sum[z] += p[x * istride]; \ seq_sum[z] += p[x * istride]; \
@ -448,7 +448,7 @@ G_STMT_START { \
\ \
for( x = 1; x < r->width; x++ ) { \ for( x = 1; x < r->width; x++ ) { \
sum = 0; \ sum = 0; \
for( z = 0; z < lines->n_lines; z++ ) { \ for( z = 0; z < n_lines; z++ ) { \
seq_sum[z] += p[seq->end[z]]; \ seq_sum[z] += p[seq->end[z]]; \
seq_sum[z] -= p[seq->start[z]]; \ seq_sum[z] -= p[seq->start[z]]; \
sum += lines->factor[z] * seq_sum[z]; \ sum += lines->factor[z] * seq_sum[z]; \

View File

@ -39,6 +39,8 @@ extern "C" {
int im_aconvsep( VipsImage *in, VipsImage *out, int im_aconvsep( VipsImage *in, VipsImage *out,
DOUBLEMASK *mask, int n_layers ); DOUBLEMASK *mask, int n_layers );
int im_aconv( VipsImage *in, VipsImage *out,
DOUBLEMASK *mask, int n_layers, int cluster );
int im_conv( VipsImage *in, VipsImage *out, INTMASK *mask ); int im_conv( VipsImage *in, VipsImage *out, INTMASK *mask );
int im_conv_f( VipsImage *in, VipsImage *out, DOUBLEMASK *mask ); int im_conv_f( VipsImage *in, VipsImage *out, DOUBLEMASK *mask );
int im_convsep( VipsImage *in, VipsImage *out, INTMASK *mask ); int im_convsep( VipsImage *in, VipsImage *out, INTMASK *mask );