From 495a6c7af174d9e068ce12678f6ac3e835c1748a Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Sun, 9 Feb 2014 19:38:53 +0000 Subject: [PATCH] im_draw_image() is a class --- ChangeLog | 4 +- TODO | 7 +- libvips/deprecated/vips7compat.c | 5 + libvips/draw/Makefile.am | 2 +- libvips/draw/draw.c | 2 + libvips/draw/im_draw_image.c | 151 ------------------- libvips/draw/paintimage.c | 227 +++++++++++++++++++++++++++++ libvips/include/vips/draw.h | 4 +- libvips/include/vips/vips7compat.h | 1 + 9 files changed, 244 insertions(+), 159 deletions(-) delete mode 100644 libvips/draw/im_draw_image.c create mode 100644 libvips/draw/paintimage.c diff --git a/ChangeLog b/ChangeLog index 23798fa9..f74fe7d0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,8 +3,8 @@ - background render thread cleans up and quits neatly - 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() as - classes +- redo im_draw_circle(), im_draw_flood(), im_draw_line(), im_draw_mask(), + im_draw_image() as classes - better rounding in vips_flatten() - VipsStatistic operations are sequential diff --git a/TODO b/TODO index dec2d3f7..cd469caa 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,6 @@ -- we will need a fastlineuser, or have to modify nip2 + + + - try: @@ -13,9 +15,6 @@ needs to work for eg. vips_linear() as well -- test circle / flood compat wrappers - - - inplace can we set a region for the pixels we will modify? diff --git a/libvips/deprecated/vips7compat.c b/libvips/deprecated/vips7compat.c index 7cd076e0..bab5bfd3 100644 --- a/libvips/deprecated/vips7compat.c +++ b/libvips/deprecated/vips7compat.c @@ -4570,6 +4570,11 @@ im_draw_mask( VipsImage *image, VipsImage *mask_im, int x, int y, VipsPel *ink ) return( vips_paintmask( image, vec, n, mask_im, x, y, NULL ) ); } +int +im_draw_image( VipsImage *image, VipsImage *sub, int x, int y ) +{ + return( vips_paintimage( image, sub, x, y, NULL ) ); +} int im_draw_flood( IMAGE *image, int x, int y, VipsPel *ink, Rect *dout ) { diff --git a/libvips/draw/Makefile.am b/libvips/draw/Makefile.am index 9ab16276..b3d80a43 100644 --- a/libvips/draw/Makefile.am +++ b/libvips/draw/Makefile.am @@ -7,9 +7,9 @@ libdraw_la_SOURCES = \ draw.c \ flood.c \ paintmask.c \ + paintimage.c \ linemask.c \ lineuser.c \ - im_draw_image.c \ im_draw_point.c \ im_draw_rect.c \ im_draw_smudge.c \ diff --git a/libvips/draw/draw.c b/libvips/draw/draw.c index 3534e89e..d644406b 100644 --- a/libvips/draw/draw.c +++ b/libvips/draw/draw.c @@ -131,6 +131,7 @@ void vips_draw_operation_init( void ) { extern GType vips_paintmask_get_type( void ); + extern GType vips_paintimage_get_type( void ); extern GType vips_line_get_type( void ); extern GType vips_line_mask_get_type( void ); extern GType vips_line_user_get_type( void ); @@ -138,6 +139,7 @@ vips_draw_operation_init( void ) extern GType vips_flood_get_type( void ); vips_paintmask_get_type(); + vips_paintimage_get_type(); vips_line_get_type(); vips_line_mask_get_type(); vips_line_user_get_type(); diff --git a/libvips/draw/im_draw_image.c b/libvips/draw/im_draw_image.c deleted file mode 100644 index f997e846..00000000 --- a/libvips/draw/im_draw_image.c +++ /dev/null @@ -1,151 +0,0 @@ -/* in-place insert - * - * Copyright: J. Cupitt - * Written: 15/06/1992 - * 22/7/93 JC - * - im_incheck() added - * 16/8/94 JC - * - im_incheck() changed to im_makerw() - * 1/9/04 JC - * - checks bands/types/etc match (thanks Matt) - * - smarter pixel size calculations - * 5/12/06 - * - im_invalidate() after paint - * 24/3/09 - * - added IM_CODING_RAD support - * 21/10/09 - * - allow sub to be outside main - * - gtkdoc - * 6/3/10 - * - don't im_invalidate() after paint, this now needs to be at a higher - * level - * 25/8/10 - * - cast and bandalike sub to main - * 22/9/10 - * - rename to im_draw_image() - * - gtk-doc - */ - -/* - - 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 - -/* The common part of most binary inplace operators. - * - * Unlike im__formatalike() and friends, we can only change one of the images, - * since the other is being updated. - */ -VipsImage * -im__inplace_base( const char *domain, - VipsImage *main, VipsImage *sub, VipsImage *out ) -{ - VipsImage *t[2]; - - if( im_rwcheck( main ) || - im_pincheck( sub ) || - im_check_coding_known( domain, main ) || - im_check_coding_same( domain, main, sub ) || - im_check_bands_1orn_unary( domain, sub, main->Bands ) ) - return( NULL ); - - /* Cast sub to match main in bands and format. - */ - if( im_open_local_array( out, t, 2, domain, "p" ) || - im__bandup( domain, sub, t[0], main->Bands ) || - im_clip2fmt( t[0], t[1], main->BandFmt ) ) - return( NULL ); - - return( t[1] ); -} - -/** - * im_draw_image: - * @image: image to draw on - * @sub: image to draw - * @x: position to insert - * @y: position to insert - * - * Draw @sub on top of @image at position @x, @y. The two images must have the - * same - * Coding. If @sub has 1 band, the bands will be duplicated to match the - * number of bands in @image. @sub will be converted to @image's format, see - * im_clip2fmt(). - * - * See also: im_insert(). - * - * Returns: 0 on success, or -1 on error. - */ -int -im_draw_image( VipsImage *image, VipsImage *sub, int x, int y ) -{ - Rect br, sr, clip; - VipsPel *p, *q; - int z; - - /* Make rects for main and sub and clip. - */ - br.left = 0; - br.top = 0; - br.width = image->Xsize; - br.height = image->Ysize; - sr.left = x; - sr.top = y; - sr.width = sub->Xsize; - sr.height = sub->Ysize; - im_rect_intersectrect( &br, &sr, &clip ); - if( im_rect_isempty( &clip ) ) - return( 0 ); - - if( !(sub = im__inplace_base( "im_draw_image", image, sub, image )) || - im_rwcheck( image ) || - im_incheck( sub ) ) - return( -1 ); - - /* Loop, memcpying sub to main. - */ - p = IM_IMAGE_ADDR( sub, clip.left - x, clip.top - y ); - q = IM_IMAGE_ADDR( image, clip.left, clip.top ); - for( z = 0; z < clip.height; z++ ) { - memcpy( (char *) q, (char *) p, - clip.width * IM_IMAGE_SIZEOF_PEL( sub ) ); - p += IM_IMAGE_SIZEOF_LINE( sub ); - q += IM_IMAGE_SIZEOF_LINE( image ); - } - - return( 0 ); -} diff --git a/libvips/draw/paintimage.c b/libvips/draw/paintimage.c new file mode 100644 index 00000000..8a1fb9f5 --- /dev/null +++ b/libvips/draw/paintimage.c @@ -0,0 +1,227 @@ +/* in-place insert + * + * Copyright: J. Cupitt + * Written: 15/06/1992 + * 22/7/93 JC + * - im_incheck() added + * 16/8/94 JC + * - im_incheck() changed to im_makerw() + * 1/9/04 JC + * - checks bands/types/etc match (thanks Matt) + * - smarter pixel size calculations + * 5/12/06 + * - im_invalidate() after paint + * 24/3/09 + * - added IM_CODING_RAD support + * 21/10/09 + * - allow sub to be outside main + * - gtkdoc + * 6/3/10 + * - don't im_invalidate() after paint, this now needs to be at a higher + * level + * 25/8/10 + * - cast and bandalike sub to main + * 22/9/10 + * - rename to im_draw_image() + * - gtk-doc + * 9/2/14 + * - redo as a class, based on paintimage + */ + +/* + + 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 + +#include "pdraw.h" + +typedef struct _VipsPaintimage { + VipsDraw parent_object; + + /* Parameters. + */ + VipsImage *sub; + int x; + int y; + +} VipsPaintimage; + +typedef struct _VipsPaintimageClass { + VipsDrawClass parent_class; + +} VipsPaintimageClass; + +G_DEFINE_TYPE( VipsPaintimage, vips_paintimage, VIPS_TYPE_DRAW ); + +static int +vips_paintimage_build( VipsObject *object ) +{ + VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object ); + VipsDraw *draw = VIPS_DRAW( object ); + VipsPaintimage *paintimage = (VipsPaintimage *) object; + VipsImage **t = (VipsImage **) vips_object_local_array( object, 3 ); + + VipsImage *im; + VipsRect image; + VipsRect sub; + VipsRect clip; + + if( VIPS_OBJECT_CLASS( vips_paintimage_parent_class )->build( object ) ) + return( -1 ); + + if( vips_check_coding_known( class->nickname, draw->image ) || + vips_check_coding_same( class->nickname, + draw->image, paintimage->sub ) || + vips_check_bands_1orn_unary( class->nickname, + paintimage->sub, draw->image->Bands ) ) + return( -1 ); + + /* Cast sub to match main in bands and format. + */ + im = paintimage->sub; + if( im->Coding == VIPS_CODING_NONE ) { + if( vips__bandup( class->nickname, + im, &t[0], draw->image->Bands ) || + vips_cast( t[0], &t[1], draw->image->BandFmt, NULL ) ) + return( -1 ); + + im = t[1]; + } + + /* Make rects for main and sub and clip. + */ + image.left = 0; + image.top = 0; + image.width = draw->image->Xsize; + image.height = draw->image->Ysize; + sub.left = paintimage->x; + sub.top = paintimage->y; + sub.width = im->Xsize; + sub.height = im->Ysize; + vips_rect_intersectrect( &image, &sub, &clip ); + + if( !vips_rect_isempty( &clip ) ) { + VipsPel *p, *q; + int y; + + if( vips_image_wio_input( im ) ) + return( -1 ); + + p = VIPS_IMAGE_ADDR( im, + clip.left - paintimage->x, clip.top - paintimage->y ); + q = VIPS_IMAGE_ADDR( draw->image, clip.left, clip.top ); + for( y = 0; y < clip.height; y++ ) { + memcpy( (char *) q, (char *) p, + clip.width * VIPS_IMAGE_SIZEOF_PEL( im ) ); + p += VIPS_IMAGE_SIZEOF_LINE( im ); + q += VIPS_IMAGE_SIZEOF_LINE( draw->image ); + } + } + + return( 0 ); +} + +static void +vips_paintimage_class_init( VipsPaintimageClass *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 = "paintimage"; + vobject_class->description = _( "paint an image into another image" ); + vobject_class->build = vips_paintimage_build; + + VIPS_ARG_IMAGE( class, "sub", 5, + _( "Sub-image" ), + _( "Sub-image to insert into main image" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsPaintimage, sub ) ); + + VIPS_ARG_INT( class, "x", 6, + _( "x" ), + _( "Draw image here" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsPaintimage, x ), + -1000000000, 1000000000, 0 ); + + VIPS_ARG_INT( class, "y", 7, + _( "y" ), + _( "Draw image here" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsPaintimage, y ), + -1000000000, 1000000000, 0 ); + +} + +static void +vips_paintimage_init( VipsPaintimage *paintimage ) +{ +} + +/** + * vips_paintimage1: + * @image: image to draw on + * @sub: image to paint + * @x: draw @sub here + * @y: draw @sub here + * + * Draw @sub on top of @image at position @x, @y. The two images must have the + * same + * Coding. If @sub has 1 band, the bands will be duplicated to match the + * number of bands in @image. @sub will be converted to @image's format, see + * vips_cast(). + * + * See also: vips_paintmask(), vips_insert(). + * + * Returns: 0 on success, or -1 on error. + */ +int +vips_paintimage( VipsImage *image, VipsImage *sub, int x, int y, ... ) +{ + va_list ap; + int result; + + va_start( ap, y ); + result = vips_call_split( "paintimage", ap, + image, NULL, sub, x, y ); + va_end( ap ); + + return( result ); +} diff --git a/libvips/include/vips/draw.h b/libvips/include/vips/draw.h index 1ed06eab..83374fab 100644 --- a/libvips/include/vips/draw.h +++ b/libvips/include/vips/draw.h @@ -45,6 +45,9 @@ int vips_paintmask1( VipsImage *image, double ink, VipsImage *mask, int x, int y, ... ) __attribute__((sentinel)); +int vips_paintimage( VipsImage *image, VipsImage *sub, int x, int y, ... ) + __attribute__((sentinel)); + int vips_line( VipsImage *image, double *ink, int n, int x1, int y1, int x2, int y2, ... ) __attribute__((sentinel)); @@ -81,7 +84,6 @@ int vips_flood1( VipsImage *image, double ink, int x, int y, ... ) int im_draw_rect( VipsImage *image, int left, int top, int width, int height, int fill, VipsPel *ink ); -int im_draw_image( VipsImage *image, VipsImage *sub, int x, int y ); int im_draw_point( VipsImage *image, int x, int y, VipsPel *ink ); int im_read_point( VipsImage *image, int x, int y, VipsPel *ink ); diff --git a/libvips/include/vips/vips7compat.h b/libvips/include/vips/vips7compat.h index d67a9304..9b5c39bf 100644 --- a/libvips/include/vips/vips7compat.h +++ b/libvips/include/vips/vips7compat.h @@ -1008,6 +1008,7 @@ typedef int (*VipsPlotFn)( VipsImage *, int, int, void *, void *, void * ); int im_draw_mask( VipsImage *image, VipsImage *mask_im, int x, int y, VipsPel *ink ); +int im_draw_image( VipsImage *image, VipsImage *sub, int x, int y ); int im_draw_line_user( VipsImage *image, int x1, int y1, int x2, int y2,