diff --git a/ChangeLog b/ChangeLog index 6ee1fd09..bd9ce73a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -29,6 +29,7 @@ - added im_draw_mask(), now wrappable, moved im_plotmask() to deprecated - added im_draw_point(), moved im_plotpoint() to deprecated - added im_read_point(), now partial, moved im_readpoint() to deprecated +- added im_draw_smudge(), moved im_smudge() / im_smear() to deprecated 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 4a177cef..dc3487c2 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,15 @@ -- wrap im_read_point: output OUBLEVEC? +- wrap im_read_point: output DOUBLEVEC? -- smudge_area, then check gtk-doc output +- check gtk-doc output + +- convsep / conv need to be able to do COMPLEX + + just double the bands + +- test im_read_point() + +- maybe im_draw_smudge() is too slow :-( also, we had a sanity failure with + it, argh diff --git a/libvips/deprecated/rename.c b/libvips/deprecated/rename.c index c8305c4d..b1cbe1c0 100644 --- a/libvips/deprecated/rename.c +++ b/libvips/deprecated/rename.c @@ -541,14 +541,10 @@ im_plotmask( IMAGE *im, int ix, int iy, PEL *ink, PEL *mask, Rect *r ) { IMAGE *mask_im; - if( !(mask_im = im_open( "im_plotmask", "t" )) ) + if( !(mask_im = im_image( mask, + r->width, r->height, 1, IM_BANDFMT_UCHAR )) ) return( -1 ); - if( im_black( mask_im, r->width, r->height, 1 ) ) { - im_close( mask_im ); - return( -1 ); - } - memcpy( mask_im->data, mask, r->width * r->height ); - if( im_draw_mask( im, mask_im, ix - r->left, iy - r->top, ink ) ) { + if( im_draw_mask( im, mask_im, ix + r->left, iy + r->top, ink ) ) { im_close( mask_im ); return( -1 ); } @@ -692,3 +688,10 @@ im_smear( IMAGE *im, int ix, int iy, Rect *r ) return( 0 ); } + +int +im_smudge( VipsImage *image, int ix, int iy, Rect *r ) +{ + return( im_draw_smudge( image, + r->left + ix, r->top + iy, r->width, r->height ) ); +} diff --git a/libvips/include/vips/almostdeprecated.h b/libvips/include/vips/almostdeprecated.h index 79930752..129261b0 100644 --- a/libvips/include/vips/almostdeprecated.h +++ b/libvips/include/vips/almostdeprecated.h @@ -248,6 +248,9 @@ int im_plotmask( IMAGE *im, int ix, int iy, PEL *ink, PEL *mask, Rect *r ); int im_readpoint( IMAGE *im, int x, int y, PEL *pel ); int im_plotpoint( IMAGE *im, int x, int y, PEL *pel ); +int im_smudge( IMAGE *image, int ix, int iy, Rect *r ); +int im_smear( IMAGE *im, int ix, int iy, Rect *r ); + #ifdef __cplusplus } #endif /*__cplusplus*/ diff --git a/libvips/include/vips/inplace.h b/libvips/include/vips/inplace.h index 4276a53e..d509abd8 100644 --- a/libvips/include/vips/inplace.h +++ b/libvips/include/vips/inplace.h @@ -64,8 +64,8 @@ int im_draw_mask( VipsImage *image, int im_draw_point( VipsImage *image, int x, int y, PEL *ink ); int im_read_point( VipsImage *image, int x, int y, PEL *ink ); -int im_smear( VipsImage *im, int ix, int iy, Rect *r ); -int im_smudge( VipsImage *im, int ix, int iy, Rect *r ); +int im_draw_smudge( VipsImage *image, + int left, int top, int width, int height ); #ifdef __cplusplus } diff --git a/libvips/inplace/Makefile.am b/libvips/inplace/Makefile.am index 771a562c..64d9420f 100644 --- a/libvips/inplace/Makefile.am +++ b/libvips/inplace/Makefile.am @@ -10,7 +10,7 @@ libinplace_la_SOURCES = \ im_draw_rect.c \ im_draw_mask.c \ im_draw_point.c \ - im_smudge_area.c \ + im_draw_smudge.c \ inplace_dispatch.c INCLUDES = -I${top_srcdir}/libvips/include @VIPS_CFLAGS@ @VIPS_INCLUDES@ diff --git a/libvips/inplace/im_draw_image.c b/libvips/inplace/im_draw_image.c index 8f86ba80..b63d0bdc 100644 --- a/libvips/inplace/im_draw_image.c +++ b/libvips/inplace/im_draw_image.c @@ -98,18 +98,18 @@ im__inplace_base( const char *domain, /** * im_draw_image: - * @main: image to draw on + * @image: image to draw on * @sub: image to draw * @x: position to insert * @y: position to insert * - * Draw @sub on top of @main at position @x, @y. The two images must have the + * 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 @main. @sub will be converted to @main's format, see + * number of bands in @image. @sub will be converted to @image's format, see * im_clip2fmt(). * - * This an inplace operation, so @main is changed. It does not thread and will + * This an inplace operation, so @image is changed. It does not thread and will * not work well as part of a pipeline. * * See also: im_insert(). diff --git a/libvips/inplace/im_draw_smudge.c b/libvips/inplace/im_draw_smudge.c new file mode 100644 index 00000000..49a67611 --- /dev/null +++ b/libvips/inplace/im_draw_smudge.c @@ -0,0 +1,121 @@ +/* Smudge a piece of image. + * + * Copyright: J. Cupitt + * Written: 15/06/1992 + * 22/7/93 JC + * - im_incheck() added + * 16/8/94 JC + * - im_incheck() changed to im_makerw() + * ? JC + * - im_makerw() changed to im_rwcheck() + * 5/12/06 + * - im_invalidate() after paint + * 6/3/10 + * - don't im_invalidate() after paint, this now needs to be at a higher + * level + * 30/9/10 + * - gtk-doc + * - deprecate im_smear() + */ + +/* + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 + +#ifdef WITH_DMALLOC +#include +#endif /*WITH_DMALLOC*/ + +/* The mask we use for blurring. + */ +static INTMASK *blur = NULL; + +/** + * 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 ) +{ + Rect area, image, clipped; + IMAGE *t[2]; + + area.left = left; + area.top = top; + area.width = width; + area.height = height; + image.left = 0; + image.top = 0; + image.width = im->Xsize; + image.height = im->Ysize; + im_rect_intersectrect( &area, &image, &clipped ); + if( im_rect_isempty( &clipped ) ) + return( 0 ); + + if( !blur ) { + blur = im_create_imaskv( "im_draw_smudge", 3, 1, 1, 1, 1 ); + blur->scale = 3; + } + + if( !(t[0] = im_open( "im_draw_smudge", "p" )) ) + return( -1 ); + if( !(t[1] = im_open_local( t[0], "im_draw_smudge", "p" )) || + im_convsep( im, t[0], blur ) || + im_extract_area( t[0], t[1], + clipped.left, clipped.top, + clipped.width, clipped.height ) || + im_draw_image( im, t[1], clipped.left, clipped.top ) ) { + im_close( t[0] ); + return( -1 ); + } + im_close( t[0] ); + + return( 0 ); +} diff --git a/libvips/inplace/im_smudge_area.c b/libvips/inplace/im_smudge_area.c deleted file mode 100644 index f5780c32..00000000 --- a/libvips/inplace/im_smudge_area.c +++ /dev/null @@ -1,182 +0,0 @@ -/* Smudge a piece of image. - * - * Copyright: J. Cupitt - * Written: 15/06/1992 - * 22/7/93 JC - * - im_incheck() added - * 16/8/94 JC - * - im_incheck() changed to im_makerw() - * ? JC - * - im_makerw() changed to im_rwcheck() - * 5/12/06 - * - im_invalidate() after paint - * 6/3/10 - * - don't im_invalidate() after paint, this now needs to be at a higher - * level - */ - -/* - - 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 - -#ifdef WITH_DMALLOC -#include -#endif /*WITH_DMALLOC*/ - -/* Smudge a section of an IMAGE. Smudge area r offset by x, y. Take average - * of pixels in 3x3 area surrounding current pixel for every pixel in r. We do - * not change the outermost pixels in the image, although we do read them. - */ -int -im_smudge( IMAGE *im, int ix, int iy, Rect *r ) -{ - int x, y, a, b, c; - int ba = im->Bands; - int el = ba * im->Xsize; - Rect area, image, clipped; - double total[ 256 ]; - - if( im_rwcheck( im ) ) - return( -1 ); - - /* Don't do the margins. - */ - area = *r; - area.left += ix; - area.top += iy; - image.left = 0; - image.top = 0; - image.width = im->Xsize; - image.height = im->Ysize; - im_rect_marginadjust( &image, -1 ); - im_rect_intersectrect( &area, &image, &clipped ); - - /* Any left? - */ - if( im_rect_isempty( &clipped ) ) - return( 0 ); - -/* What we do for each type. - */ -#define SMUDGE(TYPE) \ - for( y = clipped.top; y < clipped.top + clipped.height; y++ ) \ - for( x = clipped.left; \ - x < clipped.left + clipped.width; x++ ) { \ - TYPE *to = (TYPE *) im->data + x * ba + y * el; \ - TYPE *from = to - el - ba; \ - TYPE *f; \ - \ - for( a = 0; a < ba; a++ ) \ - total[a] = 0.0; \ - \ - for( a = 0; a < 3; a++ ) { \ - f = from; \ - for( b = 0; b < 3; b++ ) \ - for( c = 0; c < ba; c++ ) \ - total[c] += *f++; \ - from += el; \ - } \ - \ - for( a = 0; a < ba; a++ ) \ - to[a] = (16 * (double) to[a] + total[a]) \ - / 25.0; \ - } - - /* Loop through the remaining pixels. - */ - switch( im->BandFmt ) { - case IM_BANDFMT_UCHAR: - SMUDGE(unsigned char); - break; - - case IM_BANDFMT_CHAR: - SMUDGE(char); - break; - - case IM_BANDFMT_USHORT: - SMUDGE(unsigned short); - break; - - case IM_BANDFMT_SHORT: - SMUDGE(short); - break; - - case IM_BANDFMT_UINT: - SMUDGE(unsigned int); - break; - - case IM_BANDFMT_INT: - SMUDGE(int); - break; - - case IM_BANDFMT_FLOAT: - SMUDGE(float); - break; - - case IM_BANDFMT_DOUBLE: - SMUDGE(double); - break; - - /* Do complex types too. Just treat as float and double, but with - * twice the number of bands. - */ - case IM_BANDFMT_COMPLEX: - /* Twice number of bands: double size and bands. - */ - ba *= 2; - el *= 2; - - SMUDGE(float); - - break; - - case IM_BANDFMT_DPCOMPLEX: - /* Twice number of bands: double size and bands. - */ - ba *= 2; - el *= 2; - - SMUDGE(double); - - break; - - default: - im_error( "im_smudge", "%s", _( "unknown band format" ) ); - return( -1 ); - - } - - return( 0 ); -} diff --git a/libvips/inplace/inplace_dispatch.c b/libvips/inplace/inplace_dispatch.c index 93338e01..6236d26d 100644 --- a/libvips/inplace/inplace_dispatch.c +++ b/libvips/inplace/inplace_dispatch.c @@ -58,6 +58,65 @@ * */ +/* Calculate a pixel for an image from a vec of double. Valid while im is + * valid. + */ +PEL * +im__vector_to_ink( const char *domain, IMAGE *im, int n, double *vec ) +{ + IMAGE *t[3]; + double *zeros; + int i; + + if( im_check_vector( domain, n, im ) ) + return( NULL ); + if( im_open_local_array( im, t, 3, domain, "t" ) || + !(zeros = IM_ARRAY( im, n, double )) ) + return( NULL ); + for( i = 0; i < n; i++ ) + zeros[i] = 0.0; + + if( im_black( t[0], 1, 1, im->Bands ) || + im_lintra_vec( n, zeros, t[0], vec, t[1] ) || + im_clip2fmt( t[1], t[2], im->BandFmt ) ) + return( NULL ); + + return( (PEL *) t[2]->data ); +} + +double * +im__ink_to_vector( const char *domain, IMAGE *im, PEL *ink ) +{ + double *vec; + int i; + + if( im_check_uncoded( "im__ink_to_vector", im ) || + im_check_noncomplex( "im__ink_to_vector", im ) ) + return( NULL ); + if( !(vec = IM_ARRAY( NULL, im->Bands, double )) ) + return( NULL ); + +#define READ( TYPE ) \ + vec[i] = ((TYPE *) ink)[i]; + + for( i = 0; i < im->Bands; i++ ) + switch( im->BandFmt ) { + case IM_BANDFMT_UCHAR: READ( unsigned char ); break; + case IM_BANDFMT_CHAR: READ( signed char ); break; + case IM_BANDFMT_USHORT: READ( unsigned short ); break; + case IM_BANDFMT_SHORT: READ( signed short ); break; + case IM_BANDFMT_UINT: READ( unsigned int ); break; + case IM_BANDFMT_INT: READ( signed int ); break; + case IM_BANDFMT_FLOAT: READ( float ); break; + case IM_BANDFMT_DOUBLE: READ( double ); break; + + default: + g_assert( 0 ); + } + + return( vec ); +} + /* Args for im_draw_image. */ static im_arg_desc draw_image_args[] = { @@ -132,32 +191,6 @@ static im_function lineset_desc = { lineset_args /* Arg list */ }; -/* Calculate a pixel for an image from a vec of double. Valid while im is - * valid. - */ -PEL * -im__vector_to_ink( const char *domain, IMAGE *im, int n, double *vec ) -{ - IMAGE *t[3]; - double *zeros; - int i; - - if( im_check_vector( domain, n, im ) ) - return( NULL ); - if( im_open_local_array( im, t, 3, domain, "t" ) || - !(zeros = IM_ARRAY( im, n, double )) ) - return( NULL ); - for( i = 0; i < n; i++ ) - zeros[i] = 0.0; - - if( im_black( t[0], 1, 1, im->Bands ) || - im_lintra_vec( n, zeros, t[0], vec, t[1] ) || - im_clip2fmt( t[1], t[2], im->BandFmt ) ) - return( NULL ); - - return( (PEL *) t[2]->data ); -} - /* Args for im_draw_mask. */ static im_arg_desc draw_mask_args[] = { @@ -350,6 +383,47 @@ static im_function draw_point_desc = { draw_point_args /* Arg list */ }; +/* Args for im_read_point. + */ +static im_arg_desc read_point_args[] = { + IM_RW_IMAGE( "image" ), + IM_INPUT_INT( "x" ), + IM_INPUT_INT( "y" ), + IM_OUTPUT_DOUBLEVEC( "ink" ) +}; + +/* Call im_read_point via arg vector. + */ +static int +read_point_vec( im_object *argv ) +{ + IMAGE *image = argv[0]; + int x = *((int *) argv[1]); + int y = *((int *) argv[2]); + im_doublevec_object *dv = (im_doublevec_object *) argv[3]; + + PEL *ink; + + if( !(ink = IM_ARRAY( image, IM_IMAGE_SIZEOF_PEL( image ), PEL )) || + im_read_point( image, x, y, ink ) || + !(dv->vec = im__ink_to_vector( "im_read_point", image, ink )) ) + return( -1 ); + dv->n = image->Bands; + + return( 0 ); +} + +/* Description of im_read_point. + */ +static im_function read_point_desc = { + "im_read_point", /* Name */ + "read point from image", + 0, /* Flags */ + read_point_vec, /* Dispatch function */ + IM_NUMBER( read_point_args ), /* Size of arg list */ + read_point_args /* Arg list */ +}; + /* Args for im_draw_line. */ static im_arg_desc draw_line_args[] = { @@ -385,12 +459,47 @@ draw_line_vec( im_object *argv ) /* Description of im_draw_line. */ static im_function draw_line_desc = { - "im_draw_line", /* Name */ + "im_draw_line", /* Name */ "draw line on image", - 0, /* Flags */ - draw_line_vec, /* Dispatch function */ + 0, /* Flags */ + draw_line_vec, /* Dispatch function */ IM_NUMBER( draw_line_args ), /* Size of arg list */ - draw_line_args /* Arg list */ + draw_line_args /* Arg list */ +}; + +/* Args for im_draw_smudge. + */ +static im_arg_desc draw_smudge_args[] = { + IM_RW_IMAGE( "image" ), + IM_INPUT_INT( "left" ), + IM_INPUT_INT( "top" ), + IM_INPUT_INT( "width" ), + IM_INPUT_INT( "height" ) +}; + +/* Call im_draw_smudge via arg vector. + */ +static int +draw_smudge_vec( im_object *argv ) +{ + IMAGE *image = argv[0]; + int left = *((int *) argv[1]); + int top = *((int *) argv[2]); + int width = *((int *) argv[3]); + int height = *((int *) argv[4]); + + return( im_draw_smudge( image, left, top, width, height ) ); +} + +/* Description of im_draw_smudge. + */ +static im_function draw_smudge_desc = { + "im_draw_smudge", /* Name */ + "smudge part of an image", + 0, /* Flags */ + draw_smudge_vec, /* Dispatch function */ + IM_NUMBER( draw_smudge_args ), /* Size of arg list */ + draw_smudge_args /* Arg list */ }; /* Args for im_draw_rect. @@ -430,12 +539,12 @@ draw_rect_vec( im_object *argv ) /* Description of im_draw_rect. */ static im_function draw_rect_desc = { - "im_draw_rect", /* Name */ + "im_draw_rect", /* Name */ "draw rect on image", - 0, /* Flags */ - draw_rect_vec, /* Dispatch function */ + 0, /* Flags */ + draw_rect_vec, /* Dispatch function */ IM_NUMBER( draw_rect_args ), /* Size of arg list */ - draw_rect_args /* Arg list */ + draw_rect_args /* Arg list */ }; /* Args for im_draw_circle. @@ -481,14 +590,6 @@ static im_function draw_circle_desc = { draw_circle_args /* Arg list */ }; -/* To do: - * these all need some kind of pel type - * - plot_point.c - smudge_area.c - * - */ - /* Package up all these functions. */ static im_function *inplace_list[] = { @@ -496,6 +597,8 @@ static im_function *inplace_list[] = { &draw_rect_desc, &draw_line_desc, &draw_point_desc, + &read_point_desc, + &draw_smudge_desc, &flood_desc, &flood_blob_desc, &flood_other_desc,