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 );
|
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
|
static int
|
||||||
vips_bandary_stop( void *vseq, void *a, void *b )
|
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->p );
|
||||||
|
VIPS_FREE( seq->pixels );
|
||||||
|
|
||||||
VIPS_FREE( seq );
|
VIPS_FREE( seq );
|
||||||
|
|
||||||
@ -129,6 +115,7 @@ vips_bandary_start( VipsImage *out, void *a, void *b )
|
|||||||
seq->bandary = bandary;
|
seq->bandary = bandary;
|
||||||
seq->ir = NULL;
|
seq->ir = NULL;
|
||||||
seq->p = NULL;
|
seq->p = NULL;
|
||||||
|
seq->pixels = NULL;
|
||||||
|
|
||||||
/* How many images?
|
/* How many images?
|
||||||
*/
|
*/
|
||||||
@ -158,6 +145,14 @@ vips_bandary_start( VipsImage *out, void *a, void *b )
|
|||||||
return( NULL );
|
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 );
|
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" );
|
VIPS_GATE_START( "vips_bandary_gen: work" );
|
||||||
|
|
||||||
for( y = 0; y < r->height; y++ ) {
|
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++ )
|
for( i = 0; i < bandary->n; i++ )
|
||||||
seq->p[i] += VIPS_REGION_LSKIP( seq->ir[i] );
|
seq->p[i] += VIPS_REGION_LSKIP( seq->ir[i] );
|
||||||
|
@ -53,7 +53,27 @@ extern "C" {
|
|||||||
VIPS_TYPE_BANDARY, VipsBandaryClass ))
|
VIPS_TYPE_BANDARY, VipsBandaryClass ))
|
||||||
|
|
||||||
struct _VipsBandary;
|
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 );
|
VipsPel *out, VipsPel **in, int width );
|
||||||
|
|
||||||
typedef struct _VipsBandary {
|
typedef struct _VipsBandary {
|
||||||
|
@ -146,9 +146,10 @@ vips_bandbool_build( VipsObject *object )
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vips_bandbool_buffer( VipsBandary *bandary,
|
vips_bandbool_buffer( VipsBandarySequence *seq,
|
||||||
VipsPel *out, VipsPel **in, int width )
|
VipsPel *out, VipsPel **in, int width )
|
||||||
{
|
{
|
||||||
|
VipsBandary *bandary = seq->bandary;
|
||||||
VipsBandbool *bandbool = (VipsBandbool *) bandary;
|
VipsBandbool *bandbool = (VipsBandbool *) bandary;
|
||||||
VipsImage *im = bandary->ready[0];
|
VipsImage *im = bandary->ready[0];
|
||||||
int bands = im->Bands;
|
int bands = im->Bands;
|
||||||
|
@ -88,8 +88,10 @@ typedef VipsBandaryClass VipsBandjoinClass;
|
|||||||
G_DEFINE_TYPE( VipsBandjoin, vips_bandjoin, VIPS_TYPE_BANDARY );
|
G_DEFINE_TYPE( VipsBandjoin, vips_bandjoin, VIPS_TYPE_BANDARY );
|
||||||
|
|
||||||
static void
|
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;
|
VipsConversion *conversion = (VipsConversion *) bandary;
|
||||||
VipsImage **in = bandary->ready;
|
VipsImage **in = bandary->ready;
|
||||||
|
|
||||||
@ -296,9 +298,10 @@ vips_bandjoin_const_finalize( GObject *object )
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vips_bandjoin_const_buffer( VipsBandary *bandary,
|
vips_bandjoin_const_buffer( VipsBandarySequence *seq,
|
||||||
VipsPel *q, VipsPel **p, int width )
|
VipsPel *q, VipsPel **p, int width )
|
||||||
{
|
{
|
||||||
|
VipsBandary *bandary = seq->bandary;
|
||||||
VipsConversion *conversion = (VipsConversion *) bandary;
|
VipsConversion *conversion = (VipsConversion *) bandary;
|
||||||
VipsBandjoinConst *bandjoin = (VipsBandjoinConst *) bandary;
|
VipsBandjoinConst *bandjoin = (VipsBandjoinConst *) bandary;
|
||||||
VipsImage *in = bandary->ready[0];
|
VipsImage *in = bandary->ready[0];
|
||||||
|
@ -120,9 +120,10 @@ G_DEFINE_TYPE( VipsBandmean, vips_bandmean, VIPS_TYPE_BANDARY );
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vips_bandmean_buffer( VipsBandary *bandary,
|
vips_bandmean_buffer( VipsBandarySequence *seq,
|
||||||
VipsPel *out, VipsPel **in, int width )
|
VipsPel *out, VipsPel **in, int width )
|
||||||
{
|
{
|
||||||
|
VipsBandary *bandary = seq->bandary;
|
||||||
VipsImage *im = bandary->ready[0];
|
VipsImage *im = bandary->ready[0];
|
||||||
const int bands = im->Bands;
|
const int bands = im->Bands;
|
||||||
const int sz = width *
|
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
|
/* Sort input band elements in the stack. Needs to be big enough for
|
||||||
* sizeof(band-element) * number-of-images.
|
* sizeof(band-element) * number-of-images.
|
||||||
*/
|
*/
|
||||||
#define SORT_BUFFER (1024)
|
|
||||||
|
|
||||||
static void
|
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;
|
VipsBandrank *bandrank = (VipsBandrank *) bandary;
|
||||||
VipsImage **in = bandary->ready;
|
VipsImage **in = bandary->ready;
|
||||||
int sz = width * in[0]->Bands;
|
int sz = width * in[0]->Bands;
|
||||||
|
VipsPel *sort_buffer = seq->pixels;
|
||||||
|
|
||||||
int i, j, k;
|
int i, j, k;
|
||||||
int x;
|
int x;
|
||||||
VipsPel sort_buffer[SORT_BUFFER];
|
|
||||||
|
|
||||||
/* Special-case max and min.
|
/* Special-case max and min.
|
||||||
*/
|
*/
|
||||||
@ -196,15 +196,6 @@ vips_bandrank_build( VipsObject *object )
|
|||||||
return( vips_bandary_copy( bandary ) );
|
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 ) )
|
if( vips__bandalike_vec( class->nickname, in, band, n, 0 ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
|
@ -337,9 +337,10 @@ typedef VipsBandaryClass VipsExtractBandClass;
|
|||||||
G_DEFINE_TYPE( VipsExtractBand, vips_extract_band, VIPS_TYPE_BANDARY );
|
G_DEFINE_TYPE( VipsExtractBand, vips_extract_band, VIPS_TYPE_BANDARY );
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vips_extract_band_buffer( VipsBandary *bandary,
|
vips_extract_band_buffer( VipsBandarySequence *seq,
|
||||||
VipsPel *out, VipsPel **in, int width )
|
VipsPel *out, VipsPel **in, int width )
|
||||||
{
|
{
|
||||||
|
VipsBandary *bandary = seq->bandary;
|
||||||
VipsConversion *conversion = (VipsConversion *) bandary;
|
VipsConversion *conversion = (VipsConversion *) bandary;
|
||||||
VipsExtractBand *extract = (VipsExtractBand *) bandary;
|
VipsExtractBand *extract = (VipsExtractBand *) bandary;
|
||||||
VipsImage *im = bandary->ready[0];
|
VipsImage *im = bandary->ready[0];
|
||||||
|
Loading…
Reference in New Issue
Block a user