From f4e970fb7270363021da2fa6286adf45613ccf8f Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Tue, 11 Feb 2014 13:28:13 +0000 Subject: [PATCH] im_draw_smudge() done --- ChangeLog | 3 +- TODO | 76 +++++---- libvips/deprecated/Makefile.am | 1 + .../{draw => deprecated}/inplace_dispatch.c | 0 libvips/deprecated/vips7compat.c | 6 + libvips/draw/Makefile.am | 5 +- libvips/draw/draw.c | 2 + .../draw/{im_draw_smudge.c => draw_smudge.c} | 144 +++++++++++++++--- libvips/draw/old_draw.c | 102 ------------- libvips/draw/old_draw.h | 92 ----------- libvips/include/vips/draw.h | 7 +- libvips/include/vips/vips7compat.h | 3 + 12 files changed, 185 insertions(+), 256 deletions(-) rename libvips/{draw => deprecated}/inplace_dispatch.c (100%) rename libvips/draw/{im_draw_smudge.c => draw_smudge.c} (58%) delete mode 100644 libvips/draw/old_draw.c delete mode 100644 libvips/draw/old_draw.h diff --git a/ChangeLog b/ChangeLog index 6e72d235..6e6ab201 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,7 +4,8 @@ - colourspace has a source_space option - operations can be tagged as "deprecated" - redo im_draw_circle(), im_draw_flood(), im_draw_line(), im_draw_mask(), - im_draw_image(), im_draw_rect(), im_draw_point(), im_read_point() as classes + im_draw_image(), im_draw_rect(), im_draw_point(), im_read_point(), + im_draw_smudge() as classes - better rounding in vips_flatten() - VipsStatistic operations are sequential diff --git a/TODO b/TODO index fde8741d..4eda420f 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,50 @@ +- need to do im_label_regions in morph + +- swap VipsArea ink for VipsArrayDouble? + +- ink to vec etc. should work for complex .. output or accept a double-length + vector + + needs to work for eg. vips_linear() as well + + if vector.len is == bands, expand to complex by setting imaginary == 0 + if vector.len == bands * 2, set imaginary from constant + if vector.len == 1, bandup with imaginary == 0 + if vector.len == 2, bandup setting imaginary from vector + + what about bands == 2? ambigious + + we must insist vector.length == 2 or bands * 2 for complex, or have the + current behaviour of imaginary == 0 always + +- try: + + $ vips draw_smudge + usage: + draw_smudge image ink left top width height + blur a rectangle on an image + where: + image - Image to draw on, input VipsImage + ink - Colour for pixels, input VipsArrayDouble + left - Rect to fill, input gint + top - Rect to fill, input gint + width - Rect to fill, input gint + height - Rect to fill, input gint + + nice if we could hide the "ink" param + + also for + + draw_image + draw_line_user + + we could either move ink to the other operations or make a new subclass of + draw containing the ink arg + + + + + - try $ vips getpoint @@ -36,11 +83,6 @@ Segmentation fault (core dumped) - - -- swap VipsArea ink for VipsArrayDouble? - - @@ -52,29 +94,7 @@ with wtc.jpg, segv if libvips is compiled with -O, OK without -- ink to vec etc. should work for complex .. output or accept a double-length - vector - - needs to work for eg. vips_linear() as well - - if vector.len is == bands, expand to complex by setting imaginary == 0 - if vector.len == bands * 2, set imaginary from constant - if vector.len == 1, bandup with imaginary == 0 - if vector.len == 2, bandup setting imaginary from vector - - what about bands == 2? ambigious - - we must insist vector.length == 2 or bands * 2 for complex, or have the - current behaviour of imaginary == 0 always - -- inplace - - can we set a region for the pixels we will modify? - - is there any point doing this? only useful on 32-bit machines, which - don't really exist any more - -- need to do mosaicing and inplace, plus im_label_regions in morph +- need to do mosaicing - now vips_linear() has uchar output, can we do something with orc? diff --git a/libvips/deprecated/Makefile.am b/libvips/deprecated/Makefile.am index 88a1dadf..c28e0d8d 100644 --- a/libvips/deprecated/Makefile.am +++ b/libvips/deprecated/Makefile.am @@ -1,6 +1,7 @@ noinst_LTLIBRARIES = libdeprecated.la libdeprecated_la_SOURCES = \ + inplace_dispatch.c \ tone.c \ freq_dispatch.c \ im_linreg.c \ diff --git a/libvips/draw/inplace_dispatch.c b/libvips/deprecated/inplace_dispatch.c similarity index 100% rename from libvips/draw/inplace_dispatch.c rename to libvips/deprecated/inplace_dispatch.c diff --git a/libvips/deprecated/vips7compat.c b/libvips/deprecated/vips7compat.c index 8951085c..2932c1a8 100644 --- a/libvips/deprecated/vips7compat.c +++ b/libvips/deprecated/vips7compat.c @@ -4603,6 +4603,12 @@ im_draw_point( VipsImage *image, int x, int y, VipsPel *ink ) return( vips_draw_point( image, vec, n, x, y, NULL ) ); } +int +im_draw_smudge( VipsImage *im, int left, int top, int width, int height ) +{ + return( vips_draw_smudge( im, left, top, width, height, NULL ) ); +} + int im_read_point( VipsImage *image, int x, int y, VipsPel *ink ) { diff --git a/libvips/draw/Makefile.am b/libvips/draw/Makefile.am index fd7fc2da..6d00e579 100644 --- a/libvips/draw/Makefile.am +++ b/libvips/draw/Makefile.am @@ -12,9 +12,6 @@ libdraw_la_SOURCES = \ draw_line.c \ draw_line_mask.c \ draw_line_user.c \ - im_draw_smudge.c \ - inplace_dispatch.c \ - old_draw.c \ - old_draw.h + draw_smudge.c AM_CPPFLAGS = -I${top_srcdir}/libvips/include @VIPS_CFLAGS@ @VIPS_INCLUDES@ diff --git a/libvips/draw/draw.c b/libvips/draw/draw.c index d49e51b4..2848d0ef 100644 --- a/libvips/draw/draw.c +++ b/libvips/draw/draw.c @@ -138,6 +138,7 @@ vips_draw_operation_init( void ) extern GType vips_draw_line_user_get_type( void ); extern GType vips_draw_circle_get_type( void ); extern GType vips_draw_flood_get_type( void ); + extern GType vips_draw_smudge_get_type( void ); vips_draw_rect_get_type(); vips_draw_image_get_type(); @@ -147,6 +148,7 @@ vips_draw_operation_init( void ) vips_draw_line_user_get_type(); vips_draw_circle_get_type(); vips_draw_flood_get_type(); + vips_draw_smudge_get_type(); } /* Fill a scanline between points x1 and x2 inclusive. x1 < x2. diff --git a/libvips/draw/im_draw_smudge.c b/libvips/draw/draw_smudge.c similarity index 58% rename from libvips/draw/im_draw_smudge.c rename to libvips/draw/draw_smudge.c index 1e1b89af..c1a5425f 100644 --- a/libvips/draw/im_draw_smudge.c +++ b/libvips/draw/draw_smudge.c @@ -18,6 +18,8 @@ * - deprecate im_smear() * 30/1/12 * - back to the custom smear, the conv one was too slow + * 11/2/14 + * - redo as a class */ /* @@ -56,32 +58,43 @@ #include #include +#include -/** - * im_draw_smudge: - * @image: image to smudge - * @left: area to smudge - * @top: area to smudge - * @width: area to smudge - * @height: area to smudge - * - * Smudge a section of @image. Each pixel in the area @left, @top, @width, - * @height is replaced by the average of the surrounding 3x3 pixels. - * - * This an inplace operation, so @image 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_draw_line(). - * - * Returns: 0 on success, or -1 on error. - */ -int -im_draw_smudge( VipsImage *im, int left, int top, int width, int height ) +#include "pdraw.h" + +typedef struct _VipsDrawSmudge { + VipsDraw parent_object; + + /* Parameters. + */ + int left; + int top; + int width; + int height; + +} VipsDrawSmudge; + +typedef struct _VipsDrawSmudgeClass { + VipsDrawClass parent_class; + +} VipsDrawSmudgeClass; + +G_DEFINE_TYPE( VipsDrawSmudge, vips_draw_smudge, VIPS_TYPE_DRAW ); + +static int +vips_draw_smudge_build( VipsObject *object ) { + VipsDraw *draw = VIPS_DRAW( object ); + VipsImage *im = draw->image; + VipsDrawSmudge *smudge = (VipsDrawSmudge *) object; + int left = smudge->left; + int top = smudge->top; + int width = smudge->width; + int height = smudge->height; + /* Double bands for complex images. */ - int bands = vips_image_get_bands( im ) * + int bands = vips_image_get_bands( draw->image ) * (vips_band_format_iscomplex( vips_image_get_format( im ) ) ? 2 : 1); int elements = bands * vips_image_get_width( im ); @@ -90,6 +103,10 @@ im_draw_smudge( VipsImage *im, int left, int top, int width, int height ) double *total; int x, y, i, j, b; + if( VIPS_OBJECT_CLASS( vips_draw_smudge_parent_class )-> + build( object ) ) + return( -1 ); + area.left = left; area.top = top; area.width = width; @@ -107,13 +124,12 @@ im_draw_smudge( VipsImage *im, int left, int top, int width, int height ) if( vips_rect_isempty( &clipped ) ) return( 0 ); - if( !(total = VIPS_ARRAY( im, bands, double )) || - im_rwcheck( im ) ) + if( !(total = VIPS_ARRAY( im, bands, double )) ) return( -1 ); /* What we do for each type. */ -#define SMUDGE(TYPE) \ +#define SMUDGE( TYPE ) \ for( y = 0; y < clipped.height; y++ ) { \ TYPE *q; \ TYPE *p; \ @@ -163,3 +179,81 @@ im_draw_smudge( VipsImage *im, int left, int top, int width, int height ) return( 0 ); } + +static void +vips_draw_smudge_class_init( VipsDrawSmudgeClass *class ) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS( class ); + VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class ); + + gobject_class->set_property = vips_object_set_property; + gobject_class->get_property = vips_object_get_property; + + vobject_class->nickname = "draw_smudge"; + vobject_class->description = _( "blur a rectangle on an image" ); + vobject_class->build = vips_draw_smudge_build; + + VIPS_ARG_INT( class, "left", 6, + _( "Left" ), + _( "Rect to fill" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsDrawSmudge, left ), + -1000000000, 1000000000, 0 ); + + VIPS_ARG_INT( class, "top", 7, + _( "top" ), + _( "Rect to fill" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsDrawSmudge, top ), + -1000000000, 1000000000, 0 ); + + VIPS_ARG_INT( class, "width", 8, + _( "width" ), + _( "Rect to fill" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsDrawSmudge, width ), + -1000000000, 1000000000, 0 ); + + VIPS_ARG_INT( class, "height", 9, + _( "height" ), + _( "Rect to fill" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsDrawSmudge, height ), + -1000000000, 1000000000, 0 ); + +} + +static void +vips_draw_smudge_init( VipsDrawSmudge *draw_smudge ) +{ +} + +/** + * vips_draw_smudge: + * @image: image to draw on + * @left: point to paint + * @top: point to paint + * @width: area to paint + * @height: area to paint + * + * Smudge a section of @image. Each pixel in the area @left, @top, @width, + * @height is replaced by the average of the surrounding 3x3 pixels. + * + * See also: vips_draw_line(). + * + * Returns: 0 on success, or -1 on error. + */ +int +vips_draw_smudge( VipsImage *image, + int left, int top, int width, int height, ... ) +{ + va_list ap; + int result; + + va_start( ap, height ); + result = vips_call_split( "draw_smudge", ap, + image, NULL, left, top, width, height ); + va_end( ap ); + + return( result ); +} diff --git a/libvips/draw/old_draw.c b/libvips/draw/old_draw.c deleted file mode 100644 index 591d82c1..00000000 --- a/libvips/draw/old_draw.c +++ /dev/null @@ -1,102 +0,0 @@ -/* base class for drawing operations - * - * 27/9/10 - * - from im_draw_circle() - * 17/11/10 - * - oops, scanline clipping was off by 1 - */ - -/* - - 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 "old_draw.h" - -/* Fill a scanline between points x1 and x2 inclusive. x1 < x2. - */ -void -im__draw_scanline( Draw *draw, int y, int x1, int x2 ) -{ - VipsPel *mp; - int i; - int len; - - g_assert( x1 <= x2 ); - - if( y < 0 || y >= draw->im->Ysize ) - return; - if( x1 < 0 && x2 < 0 ) - return; - if( x1 >= draw->im->Xsize && x2 >= draw->im->Xsize ) - return; - x1 = IM_CLIP( 0, x1, draw->im->Xsize - 1 ); - x2 = IM_CLIP( 0, x2, draw->im->Xsize - 1 ); - - mp = IM_IMAGE_ADDR( draw->im, x1, y ); - len = x2 - x1 + 1; - - for( i = 0; i < len; i++ ) { - im__draw_pel( draw, mp ); - mp += draw->psize; - } -} - -void -im__draw_free( Draw *draw ) -{ - IM_FREE( draw->ink ); -} - -Draw * -im__draw_init( Draw *draw, IMAGE *im, VipsPel *ink ) -{ - if( im_rwcheck( im ) ) - return( NULL ); - - draw->im = im; - draw->ink = NULL; - - draw->lsize = IM_IMAGE_SIZEOF_LINE( im ); - draw->psize = IM_IMAGE_SIZEOF_PEL( im ); - draw->noclip = FALSE; - - if( ink ) { - if( !(draw->ink = (VipsPel *) im_malloc( NULL, draw->psize )) ) - return( NULL ); - memcpy( draw->ink, ink, draw->psize ); - } - - return( draw ); -} diff --git a/libvips/draw/old_draw.h b/libvips/draw/old_draw.h deleted file mode 100644 index e453fb5f..00000000 --- a/libvips/draw/old_draw.h +++ /dev/null @@ -1,92 +0,0 @@ -/* base class for drawing operations - */ - -/* - - 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 - - */ - -/* Our state. - */ -typedef struct _Draw { - /* Parameters. - */ - IMAGE *im; /* Draw here */ - VipsPel *ink; /* Copy of ink param */ - - /* Derived stuff. - */ - size_t lsize; - size_t psize; - - /* If the object to draw is entirely within the image, we have a - * faster noclip path. - */ - gboolean noclip; -} Draw; - -#define DRAW(X) ((Draw *)(X)) - -static inline void -im__draw_pel( Draw *draw, VipsPel *q ) -{ - int j; - - /* Faster than memcopy() for n < about 20. - */ - for( j = 0; j < draw->psize; j++ ) - q[j] = draw->ink[j]; -} - -/* Paint, with clip. - */ -static inline void -im__draw_pel_clip( Draw *draw, int x, int y ) -{ - if( x < 0 || x >= draw->im->Xsize ) - return; - if( y < 0 || y >= draw->im->Ysize ) - return; - - im__draw_pel( draw, IM_IMAGE_ADDR( draw->im, x, y ) ); -} - -/* Is p painted? - */ -static inline gboolean -im__draw_painted( Draw *draw, VipsPel *p ) -{ - int j; - - for( j = 0; j < draw->psize; j++ ) - if( p[j] != draw->ink[j] ) - break; - - return( j == draw->psize ); -} - -void im__draw_scanline( Draw *draw, int y, int x1, int x2 ); -void im__draw_free( Draw *draw ); -Draw *im__draw_init( Draw *draw, IMAGE *im, VipsPel *ink ); diff --git a/libvips/include/vips/draw.h b/libvips/include/vips/draw.h index 847bc3f3..4c595d16 100644 --- a/libvips/include/vips/draw.h +++ b/libvips/include/vips/draw.h @@ -90,10 +90,9 @@ int vips_draw_flood( VipsImage *image, double *ink, int n, int x, int y, ... ) int vips_draw_flood1( VipsImage *image, double ink, int x, int y, ... ) __attribute__((sentinel)); - - -int im_draw_smudge( VipsImage *image, - int left, int top, int width, int height ); +int vips_draw_smudge( VipsImage *image, + int left, int top, int width, int height, ... ) + __attribute__((sentinel)); #ifdef __cplusplus } diff --git a/libvips/include/vips/vips7compat.h b/libvips/include/vips/vips7compat.h index 308dc893..9ddcbf00 100644 --- a/libvips/include/vips/vips7compat.h +++ b/libvips/include/vips/vips7compat.h @@ -1029,6 +1029,9 @@ int im_draw_flood_other( VipsImage *image, VipsImage *test, int im_draw_point( VipsImage *image, int x, int y, VipsPel *ink ); int im_read_point( VipsImage *image, int x, int y, VipsPel *ink ); +int im_draw_smudge( VipsImage *image, + int left, int top, int width, int height ); + #ifdef __cplusplus } #endif /*__cplusplus*/