diff --git a/ChangeLog b/ChangeLog index a3a46e95..ea8080d3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,7 @@ - background render thread cleans up and quits neatly - colourspace has a source_space option - operations can be tagged as "deprecated" +- redo im_circle() as a class 22/1/14 started 7.38.3 - undeprecate VIPS_MASK_IDEAL_HIGHPASS and friends, ruby-vips was using them, diff --git a/libvips/draw/Makefile.am b/libvips/draw/Makefile.am index d43ddbce..cd480435 100644 --- a/libvips/draw/Makefile.am +++ b/libvips/draw/Makefile.am @@ -3,7 +3,7 @@ noinst_LTLIBRARIES = libdraw.la libdraw_la_SOURCES = \ circle.c \ draw.c \ - flood.c \ + im_flood.c \ im_draw_circle.c \ im_draw_image.c \ im_draw_line.c \ diff --git a/libvips/draw/circle.c b/libvips/draw/circle.c index 6c5db596..c524b60d 100644 --- a/libvips/draw/circle.c +++ b/libvips/draw/circle.c @@ -121,8 +121,7 @@ vips_circle_build( VipsObject *object ) int x, y, d; - if( VIPS_OBJECT_CLASS( vips_circle_parent_class )-> - build( object ) ) + if( VIPS_OBJECT_CLASS( vips_circle_parent_class )->build( object ) ) return( -1 ); circle->centre = VIPS_IMAGE_ADDR( draw->image, circle->cx, circle->cy ); diff --git a/libvips/draw/flood.c b/libvips/draw/flood.c index 8b77feb5..36350329 100644 --- a/libvips/draw/flood.c +++ b/libvips/draw/flood.c @@ -194,7 +194,7 @@ buffer_add( Buffer *buf, VipsFlood *flood, int x1, int x2, int y, int dir ) * pixels. */ static inline gboolean -flood_connected( VipsFlood *flood, VipsPel *tp ) +vips_flood_connected( VipsFlood *flood, VipsPel *tp ) { int j; @@ -211,7 +211,7 @@ flood_connected( VipsFlood *flood, VipsPel *tp ) * connected and unpainted. */ static void -flood_scanline( VipsFlood *flood, int x, int y, int *x1, int *x2 ) +vips_flood_scanline( VipsFlood *flood, int x, int y, int *x1, int *x2 ) { VipsDraw *draw = VIPS_DRAW( flood ); const int width = flood->test->Xsize; @@ -219,7 +219,7 @@ flood_scanline( VipsFlood *flood, int x, int y, int *x1, int *x2 ) VipsPel *tp; int i; - g_assert( flood_connected( flood, + g_assert( vips_flood_connected( flood, VIPS_IMAGE_ADDR( flood->test, x, y ) ) ); g_assert( !vips__draw_painted( draw, VIPS_IMAGE_ADDR( draw->im, x, y ) ) ); @@ -230,7 +230,7 @@ flood_scanline( VipsFlood *flood, int x, int y, int *x1, int *x2 ) */ tp = VIPS_IMAGE_ADDR( flood->test, x + 1, y ); for( i = x + 1; i < width; i++ ) { - if( !flood_connected( flood, tp ) ) + if( !vips_flood_connected( flood, tp ) ) break; tp += flood->tsize; } @@ -240,7 +240,7 @@ flood_scanline( VipsFlood *flood, int x, int y, int *x1, int *x2 ) */ tp = VIPS_IMAGE_ADDR( flood->test, x - 1, y ); for( i = x - 1; i >= 0; i-- ) { - if( !flood_connected( flood, tp ) ) + if( !vips_flood_connected( flood, tp ) ) break; tp -= flood->tsize; } @@ -262,7 +262,7 @@ flood_scanline( VipsFlood *flood, int x, int y, int *x1, int *x2 ) * line in this range looking for an edge pixel we can flood from. */ static void -flood_around( VipsFlood *flood, Scan *scan ) +vips_flood_around( VipsFlood *flood, Scan *scan ) { VipsDraw *draw = VIPS_DRAW( flood ); @@ -276,7 +276,7 @@ flood_around( VipsFlood *flood, Scan *scan ) x = scan->x1; x <= scan->x2; tp += flood->tsize, x++ ) { - if( flood_connected( flood, tp ) ) { + if( vips_flood_connected( flood, tp ) ) { int x1a; int x2a; @@ -292,7 +292,7 @@ flood_around( VipsFlood *flood, Scan *scan ) continue; } - flood_scanline( flood, x, scan->y, &x1a, &x2a ); + vips_flood_scanline( flood, x, scan->y, &x1a, &x2a ); /* Our new scanline can have up to three more * scanlines connected to it: above, below left, below @@ -317,17 +317,17 @@ flood_around( VipsFlood *flood, Scan *scan ) } static void -flood_all( Flood *flood, int x, int y ) +vips_flood_all( VipsFlood *flood, int x, int y ) { int x1, x2; /* Test start pixel ... nothing to do? */ - if( !flood_connected( flood, + if( !vips_flood_connected( flood, VIPS_IMAGE_ADDR( flood->test, x, y ) ) ) return; - flood_scanline( flood, x, y, &x1, &x2 ); + vips_flood_scanline( flood, x, y, &x1, &x2 ); flood->in = buffer_add( flood->in, flood, x1, x2, y + 1, 1 ); flood->in = buffer_add( flood->in, flood, x1, x2, y - 1, -1 ); @@ -338,7 +338,7 @@ flood_all( Flood *flood, int x, int y ) int i; for( i = 0; i < p->n; i++ ) - flood_around( flood, &p->scan[i] ); + vips_flood_around( flood, &p->scan[i] ); p->n = 0; } @@ -347,6 +347,20 @@ flood_all( Flood *flood, int x, int y ) } } +static int +vips_flood_build( VipsObject *object ) +{ + VipsDraw *draw = VIPS_DRAW( object ); + VipsFlood *flood = (VipsFlood *) object; + + int x, y, d; + + if( VIPS_OBJECT_CLASS( vips_flood_parent_class )->build( object ) ) + return( -1 ); + + return( 0 ); +} + static void flood_free( VipsFlood *flood ) { @@ -365,12 +379,12 @@ flood_free( VipsFlood *flood ) vips_free( flood ); } -static Flood * -flood_new( IMAGE *image, IMAGE *test, int x, int y, VipsPel *ink, Rect *dout ) +static VipsFlood * +vips_flood_new( VipsImage *image, VipsImage *test, int x, int y, VipsPel *ink, Rect *dout ) { - Flood *flood; + VipsFlood *flood; - if( !(flood = IM_NEW( NULL, Flood )) ) + if( !(flood = VIPS_NEW( NULL, VipsFlood )) ) return( NULL ); if( !im__draw_init( DRAW( flood ), image, ink ) ) { flood_free( flood ); @@ -382,7 +396,7 @@ flood_new( IMAGE *image, IMAGE *test, int x, int y, VipsPel *ink, Rect *dout ) flood->y = y; flood->dout = dout; flood->edge = NULL; - flood->tsize = IM_IMAGE_SIZEOF_PEL( test ); + flood->tsize = VIPS_IMAGE_SIZEOF_PEL( test ); flood->left = x; flood->top = y; flood->right = x; @@ -418,12 +432,12 @@ flood_new( IMAGE *image, IMAGE *test, int x, int y, VipsPel *ink, Rect *dout ) * Returns: 0 on success, or -1 on error. */ int -im_draw_flood( IMAGE *image, int x, int y, VipsPel *ink, Rect *dout ) +im_draw_flood( VipsImage *image, int x, int y, VipsPel *ink, Rect *dout ) { - Flood *flood; + VipsFlood *flood; if( im_check_coding_known( "im_draw_flood", image ) || - !(flood = flood_new( image, image, x, y, ink, dout )) ) + !(flood = vips_flood_new( image, image, x, y, ink, dout )) ) return( -1 ); /* Flood to != ink. @@ -431,7 +445,7 @@ im_draw_flood( IMAGE *image, int x, int y, VipsPel *ink, Rect *dout ) memcpy( flood->edge, ink, flood->tsize ); flood->equal = 0; - flood_all( flood, x, y ); + vips_flood_all( flood, x, y ); flood_free( flood ); @@ -458,18 +472,18 @@ im_draw_flood( IMAGE *image, int x, int y, VipsPel *ink, Rect *dout ) * Returns: 0 on success, or -1 on error. */ int -im_draw_flood_blob( IMAGE *image, int x, int y, VipsPel *ink, Rect *dout ) +im_draw_flood_blob( VipsImage *image, int x, int y, VipsPel *ink, Rect *dout ) { - Flood *flood; + VipsFlood *flood; int j; if( im_check_coding_known( "im_draw_flood_blob", image ) || - !(flood = flood_new( image, image, x, y, ink, dout )) ) + !(flood = vips_flood_new( image, image, x, y, ink, dout )) ) return( -1 ); /* Edge is set by colour of start pixel. */ - memcpy( flood->edge, IM_IMAGE_ADDR( image, x, y ), flood->tsize ); + memcpy( flood->edge, VIPS_IMAGE_ADDR( image, x, y ), flood->tsize ); flood->equal = 1; /* If edge == ink, we'll never stop :-( or rather, there's nothing to @@ -481,7 +495,7 @@ im_draw_flood_blob( IMAGE *image, int x, int y, VipsPel *ink, Rect *dout ) if( j == flood->tsize ) return( 0 ); - flood_all( flood, x, y ); + vips_flood_all( flood, x, y ); flood_free( flood ); @@ -510,36 +524,36 @@ im_draw_flood_blob( IMAGE *image, int x, int y, VipsPel *ink, Rect *dout ) * Returns: 0 on success, or -1 on error. */ int -im_draw_flood_other( IMAGE *image, - IMAGE *test, int x, int y, int serial, Rect *dout ) +im_draw_flood_other( VipsImage *image, + VipsImage *test, int x, int y, int serial, Rect *dout ) { int *m; - Flood *flood; + VipsFlood *flood; if( im_incheck( test ) || im_check_coding_known( "im_draw_flood_other", test ) || im_check_uncoded( "im_draw_flood_other", image ) || im_check_mono( "im_draw_flood_other", image ) || im_check_format( "im_draw_flood_other", image, - IM_BANDFMT_INT ) || + VIPS_BANDFMT_INT ) || im_check_size_same( "im_draw_flood_other", test, image ) ) return( -1 ); /* Have we done this point already? */ - m = (int *) IM_IMAGE_ADDR( image, x, y ); + m = (int *) VIPS_IMAGE_ADDR( image, x, y ); if( *m == serial ) return( 0 ); - if( !(flood = flood_new( image, test, x, y, (VipsPel *) &serial, dout )) ) + if( !(flood = vips_flood_new( image, test, x, y, (VipsPel *) &serial, dout )) ) return( -1 ); /* Edge is set by colour of start pixel. */ - memcpy( flood->edge, IM_IMAGE_ADDR( test, x, y ), flood->tsize ); + memcpy( flood->edge, VIPS_IMAGE_ADDR( test, x, y ), flood->tsize ); flood->equal = 1; - flood_all( flood, x, y ); + vips_flood_all( flood, x, y ); flood_free( flood ); diff --git a/libvips/draw/im_flood.c b/libvips/draw/im_flood.c new file mode 100644 index 00000000..247b5406 --- /dev/null +++ b/libvips/draw/im_flood.c @@ -0,0 +1,540 @@ +/* flood-fill + * + * JC 30/8/97 + * - VIPSified, cleaned up, from "John Robinson's prog to fill + * enclosed areas" + * - something Kirk gave me, so thanks John + * JC 1/10/97 + * - swapped inner memcmp/cpy for a loop ... faster for small pixels + * 13/7/02 JC + * - im_flood_blob() added + * 5/12/06 + * - im_invalidate() after paint + * 24/3/09 + * - added IM_CODING_RAD support + * 28/9/09 + * - ooops, tiny memleak + * 17/12/09 + * - use inline rather than defines, so we can add scanline fills more + * easily + * - gtk-doc comments + * 21/12/09 + * - rewrite for a scanline based fill, about 4x faster! + * - allow separate test and mark images + * 22/1/10 + * - flood_blob could loop if start point == ink + * 6/3/10 + * - don't im_invalidate() after paint, this now needs to be at a higher + * level + * 27/9/10 + * - use Draw base class + */ + +/* + + This file is part of VIPS. + + VIPS is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA + + */ + +/* + + These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk + + */ + +#ifdef HAVE_CONFIG_H +#include +#endif /*HAVE_CONFIG_H*/ +#include + +#include +#include +#include + +#include + +#include "old_draw.h" + +/* Size of a scanline buffer. We allocate a list of these to hold scanlines + * we need to visit. + */ +#define PBUFSIZE (1000) + +/* A scanline we know could contain pixels connected to us. + * + * Dir is the direction of connection: +1 means y is increasing, ie. the line + * above this one is filled. -1 if y is decreasing. + */ +typedef struct { + int x1, x2; + int y; + int dir; +} Scan; + +/* A buffer of scanlines, and how many of them have been used. If ->next is + * non-NULL, the next block could contain more of them. + * + * We keep a pair of these, then loop over one and write to the other. + */ +typedef struct _Buffer { + struct _Buffer *next; + int n; + Scan scan[PBUFSIZE]; +} Buffer; + +/* Our state. + */ +typedef struct { + Draw draw; + + /* Parameters. + */ + IMAGE *test; /* Test this image */ + int x, y; + Rect *dout; /* Write dirty here at end */ + + /* Derived stuff. + */ + VipsPel *edge; /* Boundary colour */ + int equal; /* Fill to == edge, or != edge */ + int tsize; /* sizeof( one pel in test ) */ + int left, right; /* Record bounding box of modified pixels */ + int top, bottom; + + /* Read from in, add new possibilities to out. + */ + Buffer *in; + Buffer *out; +} Flood; + +/* Alloc a new buffer. + */ +static Buffer * +buffer_build( void ) +{ + Buffer *buf; + + buf = g_new( Buffer, 1 ); + buf->next = NULL; + buf->n = 0; + + return( buf ); +} + +/* Free a chain of buffers. + */ +static void +buffer_free( Buffer *buf ) +{ + while( buf ) { + Buffer *p; + + p = buf->next; + g_free( buf ); + buf = p; + } +} + +/* Add a scanline to a buffer, prepending a new buffer if necessary. Return + * the new head buffer. + */ +static inline Buffer * +buffer_add( Buffer *buf, Flood *flood, int x1, int x2, int y, int dir ) +{ + /* Clip against image size. + */ + if( y < 0 || y >= flood->test->Ysize ) + return( buf ); + x1 = IM_CLIP( 0, x1, flood->test->Xsize - 1 ); + x2 = IM_CLIP( 0, x2, flood->test->Xsize - 1 ); + if( x2 - x1 < 0 ) + return( buf ); + + buf->scan[buf->n].x1 = x1; + buf->scan[buf->n].x2 = x2; + buf->scan[buf->n].y = y; + buf->scan[buf->n].dir = dir; + buf->n += 1; + + if( buf->n == PBUFSIZE ) { + Buffer *new; + + new = buffer_build(); + new->next = buf; + buf = new; + } + + return( buf ); +} + +/* Is p "connected"? ie. is equal to or not equal to flood->edge, depending on + * whether we are flooding to the edge boundary or flooding edge-coloured + * pixels. + */ +static inline gboolean +flood_connected( Flood *flood, VipsPel *tp ) +{ + int j; + + for( j = 0; j < flood->tsize; j++ ) + if( tp[j] != flood->edge[j] ) + break; + + /* If flood->equal, true if point == edge. + */ + return( flood->equal ^ (j < flood->tsize) ); +} + +/* Fill left and right, return the endpoints. The start point (x, y) must be + * connected and unpainted. + */ +static void +flood_scanline( Flood *flood, int x, int y, int *x1, int *x2 ) +{ + Draw *draw = DRAW( flood ); + const int width = flood->test->Xsize; + + VipsPel *tp; + int i; + + g_assert( flood_connected( flood, + IM_IMAGE_ADDR( flood->test, x, y ) ) ); + g_assert( !im__draw_painted( draw, + IM_IMAGE_ADDR( draw->im, x, y ) ) ); + + /* Search to the right for the first non-connected pixel. If the start + * pixel is unpainted, we know all the intervening pixels must be + * unpainted too. + */ + tp = IM_IMAGE_ADDR( flood->test, x + 1, y ); + for( i = x + 1; i < width; i++ ) { + if( !flood_connected( flood, tp ) ) + break; + tp += flood->tsize; + } + *x2 = i - 1; + + /* Search left. + */ + tp = IM_IMAGE_ADDR( flood->test, x - 1, y ); + for( i = x - 1; i >= 0; i-- ) { + if( !flood_connected( flood, tp ) ) + break; + tp -= flood->tsize; + } + *x1 = i + 1; + + /* Paint the range we discovered. + */ + im__draw_scanline( draw, y, *x1, *x2 ); + + if( flood->dout ) { + flood->left = IM_MIN( flood->left, *x1 ); + flood->right = IM_MAX( flood->right, *x2 ); + flood->top = IM_MIN( flood->top, y ); + flood->bottom = IM_MAX( flood->bottom, y ); + } +} + +/* We know the line below or above us is filled between x1 and x2. Search our + * line in this range looking for an edge pixel we can flood from. + */ +static void +flood_around( Flood *flood, Scan *scan ) +{ + Draw *draw = DRAW( flood ); + + VipsPel *tp; + int x; + + g_assert( scan->dir == 1 || scan->dir == -1 ); + + for( tp = IM_IMAGE_ADDR( flood->test, scan->x1, scan->y ), + x = scan->x1; + x <= scan->x2; + tp += flood->tsize, x++ ) { + if( flood_connected( flood, tp ) ) { + int x1a; + int x2a; + + /* If mark and test are different images, we also need + * to check for painted. Otherwise we can get stuck in + * connected loops. + */ + if( draw->im != flood->test ) { + VipsPel *mp = IM_IMAGE_ADDR( + draw->im, x, scan->y ); + + if( im__draw_painted( draw, mp ) ) + continue; + } + + flood_scanline( flood, x, scan->y, &x1a, &x2a ); + + /* Our new scanline can have up to three more + * scanlines connected to it: above, below left, below + * right. + */ + if( x1a < scan->x1 - 1 ) + flood->out = buffer_add( flood->out, flood, + x1a, scan->x1 - 2, + scan->y - scan->dir, -scan->dir ); + if( x2a > scan->x2 + 1 ) + flood->out = buffer_add( flood->out, flood, + scan->x2 + 2, x2a, + scan->y - scan->dir, -scan->dir ); + flood->out = buffer_add( flood->out, flood, + x1a, x2a, scan->y + scan->dir, + scan->dir ); + + x = x2a + 1; + tp = IM_IMAGE_ADDR( flood->test, x, scan->y ); + } + } +} + +static void +flood_all( Flood *flood, int x, int y ) +{ + int x1, x2; + + /* Test start pixel ... nothing to do? + */ + if( !flood_connected( flood, + IM_IMAGE_ADDR( flood->test, x, y ) ) ) + return; + + flood_scanline( flood, x, y, &x1, &x2 ); + flood->in = buffer_add( flood->in, flood, x1, x2, y + 1, 1 ); + flood->in = buffer_add( flood->in, flood, x1, x2, y - 1, -1 ); + + while( flood->in->n ) { + Buffer *p; + + for( p = flood->in; p; p = p->next ) { + int i; + + for( i = 0; i < p->n; i++ ) + flood_around( flood, &p->scan[i] ); + + p->n = 0; + } + + IM_SWAP( Buffer *, flood->in, flood->out ); + } +} + +static void +flood_free( Flood *flood ) +{ + /* Write dirty back to caller. + */ + if( flood->dout ) { + flood->dout->left = flood->left; + flood->dout->top = flood->top; + flood->dout->width = flood->right - flood->left + 1; + flood->dout->height = flood->bottom - flood->top + 1; + } + + im__draw_free( DRAW( flood ) ); + IM_FREE( flood->edge ); + IM_FREEF( buffer_free, flood->in ); + IM_FREEF( buffer_free, flood->out ); + im_free( flood ); +} + +static Flood * +flood_new( IMAGE *image, IMAGE *test, int x, int y, VipsPel *ink, Rect *dout ) +{ + Flood *flood; + + if( !(flood = IM_NEW( NULL, Flood )) ) + return( NULL ); + if( !im__draw_init( DRAW( flood ), image, ink ) ) { + flood_free( flood ); + return( NULL ); + } + + flood->test = test; + flood->x = x; + flood->y = y; + flood->dout = dout; + flood->edge = NULL; + flood->tsize = IM_IMAGE_SIZEOF_PEL( test ); + flood->left = x; + flood->top = y; + flood->right = x; + flood->bottom = y; + flood->in = buffer_build(); + flood->out = buffer_build(); + + if( !(flood->edge = (VipsPel *) im_malloc( NULL, flood->tsize )) ) { + flood_free( flood ); + return( NULL ); + } + + return( flood ); +} + +/** + * im_draw_flood: + * @image: image to fill + * @x: position to start fill + * @y: position to start fill + * @ink: colour to fill with + * @dout: output the bounding box of the filled area + * + * Flood-fill @image with @ink, starting at position @x, @y. The filled area is + * bounded by pixels that are equal to the ink colour, in other words, it + * searches for pixels enclosed by a line of @ink. + * + * The bounding box of the modified pixels is returned in @dout. @dout may be + * NULL. + * + * See also: im_draw_flood_blob(), im_draw_flood_other(). + * + * Returns: 0 on success, or -1 on error. + */ +int +im_draw_flood( IMAGE *image, int x, int y, VipsPel *ink, Rect *dout ) +{ + Flood *flood; + + if( im_check_coding_known( "im_draw_flood", image ) || + !(flood = flood_new( image, image, x, y, ink, dout )) ) + return( -1 ); + + /* Flood to != ink. + */ + memcpy( flood->edge, ink, flood->tsize ); + flood->equal = 0; + + flood_all( flood, x, y ); + + flood_free( flood ); + + return( 0 ); +} + +/** + * im_draw_flood_blob: + * @image: image to fill + * @x: position to start fill + * @y: position to start fill + * @ink: colour to fill with + * @dout: output the bounding box of the filled area + * + * Flood-fill @image with @ink, starting at position @x, @y. The filled area is + * bounded by pixels that are equal to the start pixel, in other words, it + * searches for a blob of same-coloured pixels. + * + * The bounding box of the modified pixels is returned in @dout. @dout may be + * NULL. + * + * See also: im_draw_flood(), im_draw_flood_other(), im_draw_flood_blob(). + * + * Returns: 0 on success, or -1 on error. + */ +int +im_draw_flood_blob( IMAGE *image, int x, int y, VipsPel *ink, Rect *dout ) +{ + Flood *flood; + int j; + + if( im_check_coding_known( "im_draw_flood_blob", image ) || + !(flood = flood_new( image, image, x, y, ink, dout )) ) + return( -1 ); + + /* Edge is set by colour of start pixel. + */ + memcpy( flood->edge, IM_IMAGE_ADDR( image, x, y ), flood->tsize ); + flood->equal = 1; + + /* If edge == ink, we'll never stop :-( or rather, there's nothing to + * do. + */ + for( j = 0; j < flood->tsize; j++ ) + if( flood->edge[j] != DRAW( flood )->ink[j] ) + break; + if( j == flood->tsize ) + return( 0 ); + + flood_all( flood, x, y ); + + flood_free( flood ); + + return( 0 ); +} + +/** + * im_draw_flood_other: + * @image: image to mark + * @test: image to test + * @x: position to start fill + * @y: position to start fill + * @serial: mark pixels with this number + * @dout: output the bounding box of the filled area + * + * Flood-fill @image with @serial, starting at position @x, @y. The filled + * area is bounded by pixels in @test that are equal to the start pixel, in + * other words, it searches @test for a blob of same-coloured pixels, marking + * those pixels in @image with @serial. + * + * The bounding box of the modified pixels is returned in @dout. @dout may be + * NULL. + * + * See also: im_draw_flood(), im_label_regions(), im_draw_flood_blob(). + * + * Returns: 0 on success, or -1 on error. + */ +int +im_draw_flood_other( IMAGE *image, + IMAGE *test, int x, int y, int serial, Rect *dout ) +{ + int *m; + Flood *flood; + + if( im_incheck( test ) || + im_check_coding_known( "im_draw_flood_other", test ) || + im_check_uncoded( "im_draw_flood_other", image ) || + im_check_mono( "im_draw_flood_other", image ) || + im_check_format( "im_draw_flood_other", image, + IM_BANDFMT_INT ) || + im_check_size_same( "im_draw_flood_other", test, image ) ) + return( -1 ); + + /* Have we done this point already? + */ + m = (int *) IM_IMAGE_ADDR( image, x, y ); + if( *m == serial ) + return( 0 ); + + if( !(flood = flood_new( image, test, x, y, (VipsPel *) &serial, dout )) ) + return( -1 ); + + /* Edge is set by colour of start pixel. + */ + memcpy( flood->edge, IM_IMAGE_ADDR( test, x, y ), flood->tsize ); + flood->equal = 1; + + flood_all( flood, x, y ); + + flood_free( flood ); + + return( 0 ); +} diff --git a/libvips/draw/old_draw.c b/libvips/draw/old_draw.c index bc6e8f93..591d82c1 100644 --- a/libvips/draw/old_draw.c +++ b/libvips/draw/old_draw.c @@ -42,7 +42,7 @@ #include -#include "draw.h" +#include "old_draw.h" /* Fill a scanline between points x1 and x2 inclusive. x1 < x2. */