From 3277e26e657ea60d386309c96aa66c00f7d58576 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Fri, 14 Feb 2014 10:29:09 +0000 Subject: [PATCH] add a direct path to flood for labelregions --- TODO | 7 ++++ libvips/draw/draw_flood.c | 62 +++++++++++++++++++++++++++++++ libvips/include/vips/internal.h | 7 ++-- libvips/morphology/labelregions.c | 6 +++ 4 files changed, 79 insertions(+), 3 deletions(-) diff --git a/TODO b/TODO index 6745781d..4cb16877 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,10 @@ +- add a direct route to flood for label_regions, delay speeding up operation + dispatch for now, seems like a large job + + a direct path can also avoid things like vector_to_ink, which involve + running a pipeline to generate a single pixel + + almost working - it was quick .. diff --git a/libvips/draw/draw_flood.c b/libvips/draw/draw_flood.c index f265904b..c9cf97e5 100644 --- a/libvips/draw/draw_flood.c +++ b/libvips/draw/draw_flood.c @@ -518,6 +518,68 @@ vips_draw_flood_init( VipsDrawFlood *draw_flood ) { } +/* Direct path to flood for vips_labelregions(). We need to avoid the function + * dispatch system for speed. + * + * Equivalent to: + * + * vips_draw_flood1( image, serial, x, y, + * "test", test, + * "equal", TRUE, + * NULL ) + * + * image must be 1-band int. + */ +int +vips__draw_flood_direct( VipsImage *image, VipsImage *test, + int serial, int x, int y ) +{ + VipsDrawFlood *flood = (VipsDrawFlood *) + vips_operation_new( "draw_flood" ); + VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( flood ); + + if( vips_check_format( class->nickname, image, VIPS_FORMAT_INT ) || + vips_check_mono( class->nickname, image ) || + vips_check_coding_known( class->nickname, test ) || + vips_check_size_same( class->nickname, test, image ) || + vips_image_wio_input( test ) ) { + g_object_unref( flood ); + return( -1 ); + } + + ((VipsDraw *) flood)->image = image; + + if( !(((VipsDrawink *) flood)->pixel_ink = VIPS_ARRAY( flood, + VIPS_IMAGE_SIZEOF_PEL( image ), VipsPel )) ) { + g_object_unref( flood ); + return( -1 ); + } + *((int *) (((VipsDrawink *) flood)->pixel_ink)) = serial; + + flood->test = test; + flood->tsize = VIPS_IMAGE_SIZEOF_PEL( test ); + flood->left = flood->x; + flood->top = flood->y; + flood->right = flood->x; + flood->bottom = flood->y; + flood->in = buffer_build(); + flood->out = buffer_build(); + + if( !(flood->edge = + (VipsPel *) im_malloc( flood, flood->tsize )) ) { + g_object_unref( flood ); + return( -1 ); + } + memcpy( flood->edge, + VIPS_IMAGE_ADDR( test, x, y ), flood->tsize ); + + vips_draw_flood_all( flood ); + + g_object_unref( flood ); + + return( 0 ); +} + static int vips_draw_floodv( VipsImage *image, double *ink, int n, int x, int y, va_list ap ) diff --git a/libvips/include/vips/internal.h b/libvips/include/vips/internal.h index 5b7b2c1a..5f7e9bd9 100644 --- a/libvips/include/vips/internal.h +++ b/libvips/include/vips/internal.h @@ -259,7 +259,7 @@ int *im_offsets45( int size ); int im_conv_f_raw( VipsImage *in, VipsImage *out, DOUBLEMASK *mask ); int im_convsep_f_raw( VipsImage *in, VipsImage *out, DOUBLEMASK *mask ); -/* inplace +/* draw */ VipsPel *vips__vector_to_ink( const char *domain, @@ -269,8 +269,9 @@ double *vips__ink_to_vector( const char *domain, VipsPel *im__vector_to_ink( const char *domain, VipsImage *im, int n, double *vec ); -VipsImage *im__inplace_base( const char *domain, - VipsImage *main, VipsImage *sub, VipsImage *out ); + +int vips__draw_flood_direct( VipsImage *image, VipsImage *test, + int serial, int x, int y ); /* Register base vips interpolators, called during startup. */ diff --git a/libvips/morphology/labelregions.c b/libvips/morphology/labelregions.c index 08d8c3a2..e70be565 100644 --- a/libvips/morphology/labelregions.c +++ b/libvips/morphology/labelregions.c @@ -41,6 +41,7 @@ #include #include +#include #include "pmorphology.h" @@ -87,11 +88,16 @@ vips_labelregions_build( VipsObject *object ) for( y = 0; y < t[1]->Ysize; y++ ) { for( x = 0; x < t[1]->Xsize; x++ ) { if( !m[x] ) { + /* if( vips_draw_flood1( t[1], serial, x, y, "test", in, "equal", TRUE, NULL ) ) return( -1 ); + */ + if( vips__draw_flood_direct( t[1], in, + serial, x, y ) ) + return( -1 ); serial += 1; }