smudge / smear stuff

This commit is contained in:
John Cupitt 2010-09-30 13:36:21 +00:00
parent 64f7f58411
commit 6bcf09c1d4
10 changed files with 298 additions and 240 deletions

View File

@ -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

13
TODO
View File

@ -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

View File

@ -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 ) );
}

View File

@ -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*/

View File

@ -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
}

View File

@ -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@

View File

@ -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().

View File

@ -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 <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#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 );
}

View File

@ -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 <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#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 );
}

View File

@ -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,