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:
parent
f4f9667406
commit
1be4267492
@ -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] );
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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];
|
||||
|
@ -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 *
|
||||
|
@ -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 );
|
||||
|
||||
|
@ -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];
|
||||
|
Loading…
Reference in New Issue
Block a user