diff --git a/ChangeLog b/ChangeLog index e9740a9c..0797b30c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -13,6 +13,7 @@ - revise window_offset / window_size, again - fix a mixup with ANY hints that caused performance problems on the main benchmark +- rewritten im_circle as im_draw_circle, im_circle moved to almostdeprecated 12/5/10 started 7.22.2 - the conditional image of ifthenelse can be any format, a (!=0) is added if diff --git a/TODO b/TODO index d88853c9..94f2f5bd 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,7 @@ -- im__print_all() should work even without DEBUG +- rename most of the inplace ops as im_draw_line() etc. - use a hash for im__open_images + nip2 should be able to call RW image ops by copying them, see + im_draw_circle_copy() - use D65 in cmsCreateLab4Profile() ? not sure diff --git a/libvips/deprecated/deprecated_dispatch.c b/libvips/deprecated/deprecated_dispatch.c index adb4734b..0a66305f 100644 --- a/libvips/deprecated/deprecated_dispatch.c +++ b/libvips/deprecated/deprecated_dispatch.c @@ -1217,6 +1217,40 @@ static im_function convf_desc = { conv_dmask /* Arg list */ }; +/* Args for im_circle. + */ +static im_arg_desc circle_args[] = { + IM_RW_IMAGE( "image" ), + IM_INPUT_INT( "cx" ), + IM_INPUT_INT( "cy" ), + IM_INPUT_INT( "radius" ), + IM_INPUT_INT( "intensity" ) +}; + +/* Call im_circle via arg vector. + */ +static int +circle_vec( im_object *argv ) +{ + int cx = *((int *) argv[1]); + int cy = *((int *) argv[2]); + int radius = *((int *) argv[3]); + int intensity = *((int *) argv[4]); + + return( im_circle( argv[0], cx, cy, radius, intensity ) ); +} + +/* Description of im_circle. + */ +static im_function circle_desc = { + "im_circle", /* Name */ + "plot circle on image", + 0, /* Flags */ + circle_vec, /* Dispatch function */ + IM_NUMBER( circle_args ), /* Size of arg list */ + circle_args /* Arg list */ +}; + /* Package up all these functions. */ static im_function *deprecated_list[] = { @@ -1262,7 +1296,8 @@ static im_function *deprecated_list[] = { &dilate_raw_desc, &erode_raw_desc, &similarity_area_desc, - &similarity_desc + &similarity_desc, + &circle_desc }; /* Package of functions. diff --git a/libvips/deprecated/rename.c b/libvips/deprecated/rename.c index d6640ca2..205c0675 100644 --- a/libvips/deprecated/rename.c +++ b/libvips/deprecated/rename.c @@ -424,3 +424,37 @@ im_cache( IMAGE *in, IMAGE *out, int width, int height, int max ) 0, NULL, NULL ) ); } + +/** + * im_circle: + * @im: image to draw on + * @cx: centre of circle + * @cy: centre of circle + * @radius: circle radius + * @intensity: value to draw + * + * Draws a circle on a 1-band 8-bit image. + * + * This an inplace operation, so @im is changed. It does not thread and will + * not work well as part of a pipeline. On 32-bit machines it will be limited + * to 2GB images. + * + * See also: im_fastline(). + * + * Returns: 0 on success, or -1 on error. + */ +int +im_circle( IMAGE *im, int cx, int cy, int radius, int intensity ) +{ + PEL ink[1]; + + if( im_rwcheck( im ) || + im_check_uncoded( "im_circle", im ) || + im_check_mono( "im_circle", im ) || + im_check_format( "im_circle", im, IM_BANDFMT_UCHAR ) ) + return( -1 ); + + ink[0] = intensity; + + return( im_draw_circle( im, cx, cy, radius, FALSE, ink ) ); +} diff --git a/libvips/include/vips/almostdeprecated.h b/libvips/include/vips/almostdeprecated.h index 35a63212..1b522549 100644 --- a/libvips/include/vips/almostdeprecated.h +++ b/libvips/include/vips/almostdeprecated.h @@ -206,9 +206,6 @@ int im_bernd( const char *tiffname, int x, int y, int w, int h ); int im_resize_linear( IMAGE *, IMAGE *, int, int ); -int im_line( IMAGE *, int, int, int, int, int ); -int im_segment( IMAGE *test, IMAGE *mask, int *segments ); - int im_convf( IMAGE *in, IMAGE *out, DOUBLEMASK *mask ); int im_convsepf( IMAGE *in, IMAGE *out, DOUBLEMASK *mask ); int im_conv_raw( IMAGE *in, IMAGE *out, INTMASK *mask ); @@ -229,6 +226,12 @@ int im_erode_raw( IMAGE *in, IMAGE *out, INTMASK *m ); int im_dilate_raw( IMAGE *in, IMAGE *out, INTMASK *m ); int im_rank_raw( IMAGE *in, IMAGE *out, int xsize, int ysize, int order ); +/* inplace + */ +int im_circle( IMAGE *im, int cx, int cy, int radius, int intensity ); +int im_line( IMAGE *, int, int, int, int, int ); +int im_segment( IMAGE *test, IMAGE *mask, int *segments ); + #ifdef __cplusplus } #endif /*__cplusplus*/ diff --git a/libvips/include/vips/inplace.h b/libvips/include/vips/inplace.h index de32208f..a156ef32 100644 --- a/libvips/include/vips/inplace.h +++ b/libvips/include/vips/inplace.h @@ -41,7 +41,10 @@ int im_plotmask( IMAGE *im, int ix, int iy, PEL *ink, PEL *mask, Rect *r ); int im_smear( IMAGE *im, int ix, int iy, Rect *r ); int im_smudge( IMAGE *im, int ix, int iy, Rect *r ); int im_paintrect( IMAGE *im, Rect *r, PEL *ink ); -int im_circle( IMAGE *im, int cx, int cy, int radius, int intensity ); +int im_draw_circle( IMAGE *im, + int cx, int cy, int radius, gboolean fill, PEL *ink ); +int im_draw_circle_copy( IMAGE *in, IMAGE *out, + int cx, int cy, int radius, gboolean fill, PEL *ink ); int im_insertplace( IMAGE *main, IMAGE *sub, int x, int y ); int im_fastline( IMAGE *im, int x1, int y1, int x2, int y2, PEL *pel ); int im_fastlineuser( IMAGE *im, diff --git a/libvips/inplace/flood.c b/libvips/inplace/flood.c index eb55db96..24dc93ed 100644 --- a/libvips/inplace/flood.c +++ b/libvips/inplace/flood.c @@ -246,12 +246,10 @@ flood_scanline( Flood *flood, int x, int y, int *x1, int *x2 ) int i; int len; - /* g_assert( flood_connected( flood, (PEL *) IM_IMAGE_ADDR( flood->test, x, y ) ) ); g_assert( !flood_painted( flood, (PEL *) IM_IMAGE_ADDR( flood->mark, 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 @@ -398,11 +396,11 @@ flood_free( Flood *flood ) } static Flood * -flood_build( IMAGE *test, IMAGE *mark, int x, int y, PEL *ink, Rect *dout ) +flood_new( IMAGE *test, IMAGE *mark, int x, int y, PEL *ink, Rect *dout ) { - Flood *flood = IM_NEW( NULL, Flood ); + Flood *flood; - if( !flood ) + if( !(flood = IM_NEW( NULL, Flood )) ) return( NULL ); flood->test = test; flood->mark = mark; @@ -445,7 +443,8 @@ flood_build( IMAGE *test, IMAGE *mark, int x, int y, PEL *ink, Rect *dout ) * 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. + * The bounding box of the modified pixels is returned in @dout. @dout may be + * NULL. * * This an inplace operation, so @im is changed. It does not thread and will * not work well as part of a pipeline. On 32-bit machines, it will be limited @@ -463,7 +462,7 @@ im_flood( IMAGE *im, int x, int y, PEL *ink, Rect *dout ) if( im_rwcheck( im ) || im_check_coding_known( "im_flood", im ) ) return( -1 ); - if( !(flood = flood_build( im, im, x, y, ink, dout )) ) + if( !(flood = flood_new( im, im, x, y, ink, dout )) ) return( -1 ); /* Flood to != ink. @@ -490,7 +489,8 @@ im_flood( IMAGE *im, int x, int y, PEL *ink, Rect *dout ) * 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. + * The bounding box of the modified pixels is returned in @dout. @dout may be + * NULL. * * This an inplace operation, so @im is changed. It does not thread and will * not work well as part of a pipeline. On 32-bit machines, it will be limited @@ -509,7 +509,7 @@ im_flood_blob( IMAGE *im, int x, int y, PEL *ink, Rect *dout ) if( im_rwcheck( im ) || im_check_coding_known( "im_flood", im ) ) return( -1 ); - if( !(flood = flood_build( im, im, x, y, ink, dout )) ) + if( !(flood = flood_new( im, im, x, y, ink, dout )) ) return( -1 ); /* Edge is set by colour of start pixel. @@ -547,7 +547,8 @@ im_flood_blob( IMAGE *im, int x, int y, PEL *ink, Rect *dout ) * other words, it searches @test for a blob of same-coloured pixels, marking * those pixels in @mark with @serial. * - * The bounding box of the modified pixels is returned in @dout. + * The bounding box of the modified pixels is returned in @dout. @dout may be + * NULL. * * This an inplace operation, so @mark is changed. It does not thread and will * not work well as part of a pipeline. On 32-bit machines, it will be limited @@ -578,7 +579,7 @@ im_flood_other( IMAGE *test, IMAGE *mark, int x, int y, int serial, Rect *dout ) if( *m == serial ) return( 0 ); - if( !(flood = flood_build( test, mark, x, y, (PEL *) &serial, dout )) ) + if( !(flood = flood_new( test, mark, x, y, (PEL *) &serial, dout )) ) return( -1 ); /* Edge is set by colour of start pixel. diff --git a/libvips/inplace/im_circle.c b/libvips/inplace/im_circle.c index e5a83c93..075f5c48 100644 --- a/libvips/inplace/im_circle.c +++ b/libvips/inplace/im_circle.c @@ -1,13 +1,4 @@ -/* @(#) writes a circle in a vasari file - * @(#) The circle is centred in the middle of the file (xsize/2, ysize/2) - * @(#) im must be a valid image - * @(#) int im_circle(pim, cx, cy, radius, intensity) - * @(#) IMAGE *pim; - * @(#) int cx, cy, radius, intensity; - * @(#) - * @(#) Return -1 on error 0 on sucess. - * - * Copyright 1990, N. Dessipris. +/* draw a circle on an image * * Author N. Dessipris * Written on 30/05/1990 @@ -21,6 +12,9 @@ * 6/3/10 * - don't im_invalidate() after paint, this now needs to be at a higher * level + * 18/8/10 + * - gtkdoc + * - rewritten: clips, fills, any bands, any format */ /* @@ -54,8 +48,6 @@ #endif /*HAVE_CONFIG_H*/ #include -#include -#include #include #include @@ -64,72 +56,243 @@ #include #endif /*WITH_DMALLOC*/ -int -im_circle( IMAGE *im, int cx, int cy, int radius, int intensity ) -{ - PEL *start; - int size = 0; - int x, y, d, offset; +/* Our state. + */ +typedef struct { + /* Parameters. + */ + IMAGE *im; /* Test this image */ + int cx, cy; + int radius; + gboolean fill; + PEL *ink; /* Copy of ink param */ - if( im_rwcheck( im ) ) + /* Derived stuff. + */ + size_t lsize; + size_t psize; + PEL *centre; + + /* If the circle is entirely within the image, we have a faster + * noclip path. + */ + gboolean noclip; +} Circle; + +/* Faster than memcpy for n < about 20. + */ +static inline void +circle_paint_pel( Circle *circle, PEL *q ) +{ + int j; + + for( j = 0; j < circle->psize; j++ ) + q[j] = circle->ink[j]; +} + +/* Paint, with clip. + */ +static void +circle_paint_pel_clip( Circle *circle, int x, int y ) +{ + if( x < 0 || x >= circle->im->Xsize ) + return; + if( y < 0 || y >= circle->im->Ysize ) + return; + + circle_paint_pel( circle, (PEL *) IM_IMAGE_ADDR( circle->im, x, y ) ); +} + +/* Fill a scanline between points x1 and x2 inclusive. x1 < x2. + */ +static void +circle_paint_scanline( Circle *circle, int y, int x1, int x2 ) +{ + PEL *mp; + int i; + int len; + + g_assert( x1 <= x2 ); + + if( y < 0 || y > circle->im->Ysize ) + return; + if( x1 < 0 && x2 < 0 ) + return; + if( x1 > circle->im->Xsize && x2 > circle->im->Xsize ) + return; + x1 = IM_CLIP( 0, x1, circle->im->Xsize - 1 ); + x2 = IM_CLIP( 0, x2, circle->im->Xsize - 1 ); + + mp = (PEL *) IM_IMAGE_ADDR( circle->im, x1, y ); + len = x2 - x1 + 1; + + for( i = 0; i < len; i++ ) { + circle_paint_pel( circle, mp ); + mp += circle->psize; + } +} + +static void +circle_octants( Circle *circle, int x, int y ) +{ + if( circle->fill ) { + const int cx = circle->cx; + const int cy = circle->cy; + + circle_paint_scanline( circle, cy + y, cx - x, cx + x ); + circle_paint_scanline( circle, cy - y, cx - x, cx + x ); + circle_paint_scanline( circle, cy + x, cx - y, cx + y ); + circle_paint_scanline( circle, cy - x, cx - y, cx + y ); + } + else if( circle->noclip ) { + const size_t lsize = circle->lsize; + const size_t psize = circle->psize; + PEL *centre = circle->centre; + + circle_paint_pel( circle, centre + lsize * y - psize * x ); + circle_paint_pel( circle, centre + lsize * y + psize * x ); + circle_paint_pel( circle, centre - lsize * y - psize * x ); + circle_paint_pel( circle, centre - lsize * y + psize * x ); + circle_paint_pel( circle, centre + lsize * x - psize * y ); + circle_paint_pel( circle, centre + lsize * x + psize * y ); + circle_paint_pel( circle, centre - lsize * x - psize * y ); + circle_paint_pel( circle, centre - lsize * x + psize * y ); + } + else { + const int cx = circle->cx; + const int cy = circle->cy; + + circle_paint_pel_clip( circle, cx + y, cy - x ); + circle_paint_pel_clip( circle, cx + y, cy + x ); + circle_paint_pel_clip( circle, cx - y, cy - x ); + circle_paint_pel_clip( circle, cx - y, cy + x ); + circle_paint_pel_clip( circle, cx + x, cy - y ); + circle_paint_pel_clip( circle, cx + x, cy + y ); + circle_paint_pel_clip( circle, cx - x, cy - y ); + circle_paint_pel_clip( circle, cx - x, cy + y ); + } +} + +static void +circle_free( Circle *circle ) +{ + IM_FREE( circle->ink ); + im_free( circle ); +} + +static Circle * +circle_new( IMAGE *im, int cx, int cy, int radius, gboolean fill, PEL *ink ) +{ + Circle *circle; + + if( !(circle = IM_NEW( NULL, Circle )) ) + return( NULL ); + circle->im = im; + circle->cx = cx; + circle->cy = cy; + circle->radius = radius; + circle->fill = fill; + circle->ink = NULL; + + circle->lsize = IM_IMAGE_SIZEOF_LINE( im ); + circle->psize = IM_IMAGE_SIZEOF_PEL( im ); + circle->centre = (PEL *) IM_IMAGE_ADDR( im, cx, cy ); + circle->noclip = FALSE; + + if( !(circle->ink = (PEL *) im_malloc( NULL, circle->psize )) ) { + circle_free( circle ); + return( NULL ); + } + memcpy( circle->ink, ink, circle->psize ); + + if( cx - radius >= 0 && cx + radius < im->Xsize && + cy - radius >= 0 && cy + radius < im->Ysize ) + circle->noclip = TRUE; + + return( circle ); +} + +static void +circle_paint( Circle *circle ) +{ + int x, y, d; + + y = circle->radius; + d = 3 - 2 * circle->radius; + + for( x = 0; x < y; x++ ) { + circle_octants( circle, x, y ); + + if( d < 0 ) + d += 4 * x + 6; + else { + d += 4 * (x - y) + 10; + y--; + } + } + + if( x == y ) + circle_octants( circle, x, y ); +} + +/** + * im_draw_circle: + * @im: image to draw on + * @cx: centre of circle + * @cy: centre of circle + * @radius: circle radius + * @fill: fill the circle + * @ink: value to draw + * + * Draws a circle on an image. If @fill is %TRUE then the circle is filled, + * otherwise a 1-pixel-wide perimeter is drawn. + * + * @ink is an array of bytes containing a valid pixel for the image's format. + * It must have at least IM_IMAGE_SIZEOF_PEL( @im ) bytes. + * + * This an inplace operation, so @im is changed. It does not thread and will + * not work well as part of a pipeline. On 32-bit machines it will be limited + * to 2GB images. + * + * See also: im_fastline(). + * + * Returns: 0 on success, or -1 on error. + */ +int +im_draw_circle( IMAGE *im, int cx, int cy, int radius, gboolean fill, PEL *ink ) +{ + Circle *circle; + + if( cx + radius < 0 || cx - radius >= im->Xsize || + cy + radius < 0 || cy - radius >= im->Ysize ) + return( 0 ); + + if( im_rwcheck( im ) || + im_check_coding_known( "im_draw_circle", im ) || + !(circle = circle_new( im, cx, cy, radius, fill, ink )) ) + return( -1 ); + circle_paint( circle ); + circle_free( circle ); + + return( 0 ); +} + + +/* One we can call from nip. Grr! Should be a way to wrap these + * automatically. Maybe nip could do it if it sees a RW image argument? + */ + +int +im_draw_circle_copy( IMAGE *in, IMAGE *out, + int cx, int cy, int radius, gboolean fill, PEL *ink ) +{ + IMAGE *t; + + if( !(t = im_open_local( out, "im_flood_blob_copy", "t" )) || + im_copy( in, t ) || + im_draw_circle( t, cx, cy, radius, fill, ink ) || + im_copy( t, out ) ) return( -1 ); -/* Check args */ - if ( (im->data == NULL)||(im->BandFmt != IM_BANDFMT_UCHAR)|| - (im->Bands != 1)) - { - im_error("im_circle: ", "%s", _( "able to write input image") ); - return(-1); - } - if ((intensity > 255)||(intensity <= 0)) - { - im_error( "im_circle", "%s", _( "intensity between 0 and 255") ); - return(-1); - } -/* Check if circle fits into image */ - if ( ((radius+cy)> im->Ysize - 1) || ((cy-radius)< 0 ) || - ((radius+cx)> im->Xsize - 1) || ((cx-radius) < 0 ) ) - { - im_error( "im_circle", "%s", _( "The circle does not fit in image") ); - return(-1); - } -/* Draw the circle */ - size = im->Xsize; - start = (PEL*)im->data; - offset = cy * im->Xsize + cx; /* point at the center of the circle */ - x = 0; - y = radius; - d = 3 - 2 * radius; - while ( x < y ) - { - *(start + offset + size * y + x) = (PEL)intensity; - *(start + offset + size * x + y) = (PEL)intensity; - *(start + offset + size * y - x) = (PEL)intensity; - *(start + offset + size * x - y) = (PEL)intensity; - *(start + offset - size * y - x) = (PEL)intensity; - *(start + offset - size * x - y) = (PEL)intensity; - *(start + offset - size * y + x) = (PEL)intensity; - *(start + offset - size * x + y) = (PEL)intensity; - if (d < 0 ) - d += ( 4 * x + 6 ); - else - { - d += ( 4 * ( x - y ) + 10 ); - y--; - } - x++; - } - if ( x== y ) - { - *(start + offset + size * y + x) = (PEL)intensity; - *(start + offset + size * x + y) = (PEL)intensity; - *(start + offset + size * y - x) = (PEL)intensity; - *(start + offset + size * x - y) = (PEL)intensity; - *(start + offset - size * y - x) = (PEL)intensity; - *(start + offset - size * x - y) = (PEL)intensity; - *(start + offset - size * y + x) = (PEL)intensity; - *(start + offset - size * x + y) = (PEL)intensity; - } - - return(0); + return( 0 ); } diff --git a/libvips/inplace/inplace_dispatch.c b/libvips/inplace/inplace_dispatch.c index 39adfa32..31f9e73e 100644 --- a/libvips/inplace/inplace_dispatch.c +++ b/libvips/inplace/inplace_dispatch.c @@ -54,40 +54,6 @@ * */ -/* Args for im_circle. - */ -static im_arg_desc circle_args[] = { - IM_RW_IMAGE( "image" ), - IM_INPUT_INT( "cx" ), - IM_INPUT_INT( "cy" ), - IM_INPUT_INT( "radius" ), - IM_INPUT_INT( "intensity" ) -}; - -/* Call im_circle via arg vector. - */ -static int -circle_vec( im_object *argv ) -{ - int cx = *((int *) argv[1]); - int cy = *((int *) argv[2]); - int radius = *((int *) argv[3]); - int intensity = *((int *) argv[4]); - - return( im_circle( argv[0], cx, cy, radius, intensity ) ); -} - -/* Description of im_circle. - */ -static im_function circle_desc = { - "im_circle", /* Name */ - "plot circle on image", - 0, /* Flags */ - circle_vec, /* Dispatch function */ - IM_NUMBER( circle_args ), /* Size of arg list */ - circle_args /* Arg list */ -}; - /* Args for im_insertplace. */ static im_arg_desc insertplace_args[] = { @@ -316,6 +282,92 @@ static im_function flood_other_copy_desc = { flood_other_copy_args /* Arg list */ }; +/* Args for im_draw_circle. + */ +static im_arg_desc draw_circle_args[] = { + IM_RW_IMAGE( "image" ), + IM_INPUT_INT( "cx" ), + IM_INPUT_INT( "cy" ), + IM_INPUT_INT( "radius" ), + IM_INPUT_INT( "fill" ), + IM_INPUT_DOUBLEVEC( "ink" ) +}; + +/* Call im_draw_circle via arg vector. + */ +static int +draw_circle_vec( im_object *argv ) +{ + IMAGE *in = argv[0]; + int cx = *((int *) argv[1]); + int cy = *((int *) argv[2]); + int radius = *((int *) argv[3]); + int fill = *((int *) argv[4]); + im_doublevec_object *dv = (im_doublevec_object *) argv[5]; + + PEL *ink; + + if( !(ink = vector_to_ink( in, dv->vec )) ) + return( -1 ); + + return( im_draw_circle( in, cx, cy, radius, fill, ink ) ); +} + +/* Description of im_draw_circle. + */ +static im_function draw_circle_desc = { + "im_draw_circle", /* Name */ + "draw circle on image", + 0, /* Flags */ + draw_circle_vec, /* Dispatch function */ + IM_NUMBER( draw_circle_args ), /* Size of arg list */ + draw_circle_args /* Arg list */ +}; + +/* Args for im_draw_circle_copy. + */ +static im_arg_desc draw_circle_copy_args[] = { + IM_INPUT_IMAGE( "in" ), + IM_OUTPUT_IMAGE( "out" ), + IM_INPUT_INT( "cx" ), + IM_INPUT_INT( "cy" ), + IM_INPUT_INT( "radius" ), + IM_INPUT_INT( "fill" ), + IM_INPUT_DOUBLEVEC( "ink" ) +}; + +/* Call im_draw_circle_copy via arg vector. + */ +static int +draw_circle_copy_vec( im_object *argv ) +{ + IMAGE *in = argv[0]; + IMAGE *out = argv[1]; + int cx = *((int *) argv[2]); + int cy = *((int *) argv[3]); + int radius = *((int *) argv[4]); + int fill = *((int *) argv[5]); + im_doublevec_object *dv = (im_doublevec_object *) argv[6]; + + PEL *ink; + + if( !(ink = vector_to_ink( in, dv->vec )) ) + return( -1 ); + + return( im_draw_circle_copy( in, out, cx, cy, radius, fill, ink ) ); +} + +/* Description of im_draw_circle_copy. + */ +static im_function draw_circle_copy_desc = { + "im_draw_circle_copy", /* Name */ + "draw circle on image", + 0, /* Flags */ + draw_circle_copy_vec, /* Dispatch function */ + IM_NUMBER( draw_circle_copy_args ), /* Size of arg list */ + draw_circle_copy_args /* Arg list */ +}; + /* To do: * these all need some kind of pel type * @@ -331,7 +383,8 @@ static im_function flood_other_copy_desc = { /* Package up all these functions. */ static im_function *inplace_list[] = { - &circle_desc, + &draw_circle_desc, + &draw_circle_copy_desc, &flood_copy_desc, &flood_blob_copy_desc, &flood_other_copy_desc,