make bandrank work with many input images

400+ tested and seems to work

see https://github.com/jcupitt/libvips/issues/822
This commit is contained in:
John Cupitt 2017-12-15 14:47:56 +00:00
parent f4f9667406
commit 1be4267492
7 changed files with 47 additions and 35 deletions

View File

@ -79,21 +79,6 @@
G_DEFINE_ABSTRACT_TYPE( VipsBandary, vips_bandary, VIPS_TYPE_CONVERSION );
/* Our sequence value.
*/
typedef struct {
VipsBandary *bandary;
/* Set of input regions.
*/
VipsRegion **ir;
/* For each input, an input pointer.
*/
VipsPel **p;
} VipsBandarySequence;
static int
vips_bandary_stop( void *vseq, void *a, void *b )
{
@ -108,6 +93,7 @@ vips_bandary_stop( void *vseq, void *a, void *b )
}
VIPS_FREE( seq->p );
VIPS_FREE( seq->pixels );
VIPS_FREE( seq );
@ -129,6 +115,7 @@ vips_bandary_start( VipsImage *out, void *a, void *b )
seq->bandary = bandary;
seq->ir = NULL;
seq->p = NULL;
seq->pixels = NULL;
/* How many images?
*/
@ -158,6 +145,14 @@ vips_bandary_start( VipsImage *out, void *a, void *b )
return( NULL );
}
/* Pixel buffer. This is used as working space by some subclasses.
*/
if( !(seq->pixels = VIPS_ARRAY( NULL,
n * VIPS_IMAGE_SIZEOF_PEL( bandary->ready[0] ), VipsPel )) ) {
vips_bandary_stop( seq, NULL, NULL );
return( NULL );
}
return( seq );
}
@ -182,7 +177,7 @@ vips_bandary_gen( VipsRegion *or, void *vseq, void *a, void *b, gboolean *stop )
VIPS_GATE_START( "vips_bandary_gen: work" );
for( y = 0; y < r->height; y++ ) {
class->process_line( bandary, q, seq->p, r->width );
class->process_line( seq, q, seq->p, r->width );
for( i = 0; i < bandary->n; i++ )
seq->p[i] += VIPS_REGION_LSKIP( seq->ir[i] );

View File

@ -53,7 +53,27 @@ extern "C" {
VIPS_TYPE_BANDARY, VipsBandaryClass ))
struct _VipsBandary;
typedef void (*VipsBandaryProcessFn)( struct _VipsBandary *bandary,
/* Our sequence value.
*/
typedef struct {
struct _VipsBandary *bandary;
/* Set of input regions.
*/
VipsRegion **ir;
/* For each input, an input pointer.
*/
VipsPel **p;
/* A memory area large enough to hold one pixel from each input image.
*/
VipsPel *pixels;
} VipsBandarySequence;
typedef void (*VipsBandaryProcessFn)( VipsBandarySequence *seq,
VipsPel *out, VipsPel **in, int width );
typedef struct _VipsBandary {

View File

@ -146,9 +146,10 @@ vips_bandbool_build( VipsObject *object )
}
static void
vips_bandbool_buffer( VipsBandary *bandary,
vips_bandbool_buffer( VipsBandarySequence *seq,
VipsPel *out, VipsPel **in, int width )
{
VipsBandary *bandary = seq->bandary;
VipsBandbool *bandbool = (VipsBandbool *) bandary;
VipsImage *im = bandary->ready[0];
int bands = im->Bands;

View File

@ -88,8 +88,10 @@ typedef VipsBandaryClass VipsBandjoinClass;
G_DEFINE_TYPE( VipsBandjoin, vips_bandjoin, VIPS_TYPE_BANDARY );
static void
vips_bandjoin_buffer( VipsBandary *bandary, VipsPel *q, VipsPel **p, int width )
vips_bandjoin_buffer( VipsBandarySequence *seq,
VipsPel *q, VipsPel **p, int width )
{
VipsBandary *bandary = seq->bandary;
VipsConversion *conversion = (VipsConversion *) bandary;
VipsImage **in = bandary->ready;
@ -296,9 +298,10 @@ vips_bandjoin_const_finalize( GObject *object )
}
static void
vips_bandjoin_const_buffer( VipsBandary *bandary,
vips_bandjoin_const_buffer( VipsBandarySequence *seq,
VipsPel *q, VipsPel **p, int width )
{
VipsBandary *bandary = seq->bandary;
VipsConversion *conversion = (VipsConversion *) bandary;
VipsBandjoinConst *bandjoin = (VipsBandjoinConst *) bandary;
VipsImage *in = bandary->ready[0];

View File

@ -120,9 +120,10 @@ G_DEFINE_TYPE( VipsBandmean, vips_bandmean, VIPS_TYPE_BANDARY );
}
static void
vips_bandmean_buffer( VipsBandary *bandary,
vips_bandmean_buffer( VipsBandarySequence *seq,
VipsPel *out, VipsPel **in, int width )
{
VipsBandary *bandary = seq->bandary;
VipsImage *im = bandary->ready[0];
const int bands = im->Bands;
const int sz = width *

View File

@ -147,18 +147,18 @@ G_DEFINE_TYPE( VipsBandrank, vips_bandrank, VIPS_TYPE_BANDARY );
/* Sort input band elements in the stack. Needs to be big enough for
* sizeof(band-element) * number-of-images.
*/
#define SORT_BUFFER (1024)
static void
vips_bandrank_buffer( VipsBandary *bandary, VipsPel *q, VipsPel **p, int width )
vips_bandrank_buffer( VipsBandarySequence *seq,
VipsPel *q, VipsPel **p, int width )
{
VipsBandary *bandary = seq->bandary;
VipsBandrank *bandrank = (VipsBandrank *) bandary;
VipsImage **in = bandary->ready;
int sz = width * in[0]->Bands;
VipsPel *sort_buffer = seq->pixels;
int i, j, k;
int x;
VipsPel sort_buffer[SORT_BUFFER];
/* Special-case max and min.
*/
@ -196,15 +196,6 @@ vips_bandrank_build( VipsObject *object )
return( vips_bandary_copy( bandary ) );
}
/* We need to keep one band element for every input image
* on the stack.
*/
if( sizeof( double ) * n > SORT_BUFFER ) {
vips_error( class->nickname,
"%s", _( "too many input images" ) );
return( -1 );
}
if( vips__bandalike_vec( class->nickname, in, band, n, 0 ) )
return( -1 );

View File

@ -337,9 +337,10 @@ typedef VipsBandaryClass VipsExtractBandClass;
G_DEFINE_TYPE( VipsExtractBand, vips_extract_band, VIPS_TYPE_BANDARY );
static void
vips_extract_band_buffer( VipsBandary *bandary,
vips_extract_band_buffer( VipsBandarySequence *seq,
VipsPel *out, VipsPel **in, int width )
{
VipsBandary *bandary = seq->bandary;
VipsConversion *conversion = (VipsConversion *) bandary;
VipsExtractBand *extract = (VipsExtractBand *) bandary;
VipsImage *im = bandary->ready[0];