| /* Function dispatch tables for inplace. |
| * |
| * J. Cupitt, 8/2/95 |
| */ |
| |
| /* |
| |
| 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 <vips/vips.h> |
| |
| #ifdef WITH_DMALLOC |
| #include <dmalloc.h> |
| #endif /*WITH_DMALLOC*/ |
| |
| /** |
| * SECTION: inplace |
| * @short_description: in-place paintbox operations: flood, paste, line, |
| * circle |
| * @stability: Stable |
| * @include: vips/vips.h |
| * |
| * These operations modify the input image. You can't easily use them in |
| * pipelines, but they are useful for paintbox-style programs. |
| * |
| */ |
| |
| /* 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[] = { |
| IM_RW_IMAGE( "main" ), |
| IM_INPUT_IMAGE( "sub" ), |
| IM_INPUT_INT( "x" ), |
| IM_INPUT_INT( "y" ) |
| }; |
| |
| /* Call im_insertplace via arg vector. |
| */ |
| static int |
| insertplace_vec( im_object *argv ) |
| { |
| int x = *((int *) argv[2]); |
| int y = *((int *) argv[3]); |
| |
| return( im_insertplace( argv[0], argv[1], x, y ) ); |
| } |
| |
| /* Description of im_insertplace. |
| */ |
| static im_function insertplace_desc = { |
| "im_insertplace", /* Name */ |
| "draw image sub inside image main at position (x,y)", |
| 0, /* Flags */ |
| insertplace_vec, /* Dispatch function */ |
| IM_NUMBER( insertplace_args ), /* Size of arg list */ |
| insertplace_args /* Arg list */ |
| }; |
| |
| /* Args for im_lineset. |
| */ |
| static im_arg_desc lineset_args[] = { |
| IM_INPUT_IMAGE( "in" ), |
| IM_OUTPUT_IMAGE( "out" ), |
| IM_INPUT_IMAGE( "mask" ), |
| IM_INPUT_IMAGE( "ink" ), |
| IM_INPUT_INTVEC( "x1" ), |
| IM_INPUT_INTVEC( "y1" ), |
| IM_INPUT_INTVEC( "x2" ), |
| IM_INPUT_INTVEC( "y2" ) |
| }; |
| |
| /* Call im_lineset via arg vector. |
| */ |
| static int |
| lineset_vec( im_object *argv ) |
| { |
| im_intvec_object *x1v = (im_intvec_object *) argv[4]; |
| im_intvec_object *y1v = (im_intvec_object *) argv[5]; |
| im_intvec_object *x2v = (im_intvec_object *) argv[6]; |
| im_intvec_object *y2v = (im_intvec_object *) argv[7]; |
| |
| if( x1v->n != y1v->n || x1v->n != x2v->n || x1v->n != y2v->n ) { |
| im_error( "im_lineset", "%s", _( "vectors not same length" ) ); |
| return( -1 ); |
| } |
| |
| return( im_lineset( argv[0], argv[1], argv[2], argv[3], |
| x1v->n, x1v->vec, y1v->vec, x2v->vec, y2v->vec ) ); |
| } |
| |
| /* Description of im_lineset. |
| */ |
| static im_function lineset_desc = { |
| "im_lineset", /* Name */ |
| "draw line between points (x1,y1) and (x2,y2)", |
| 0, /* Flags */ |
| lineset_vec, /* Dispatch function */ |
| IM_NUMBER( lineset_args ), /* Size of arg list */ |
| lineset_args /* Arg list */ |
| }; |
| |
| /* Calculate a pixel for an image from a vec of double. Valid while im is |
| * valid. |
| */ |
| static PEL * |
| vector_to_ink( IMAGE *im, double *vec ) |
| { |
| const int n = im->Bands; |
| |
| IMAGE *t[3]; |
| double *zeros; |
| int i; |
| |
| if( im_open_local_array( im, t, 3, "vector_to_ink", "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, n ) || |
| 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_flood_blob_copy(). |
| */ |
| static im_arg_desc flood_blob_copy_args[] = { |
| IM_INPUT_IMAGE( "in" ), |
| IM_OUTPUT_IMAGE( "out" ), |
| IM_INPUT_INT( "start_x" ), |
| IM_INPUT_INT( "start_y" ), |
| IM_INPUT_DOUBLEVEC( "ink" ) |
| }; |
| |
| /* Call im_flood_blob_copy() via arg vector. |
| */ |
| static int |
| flood_blob_copy_vec( im_object *argv ) |
| { |
| IMAGE *in = argv[0]; |
| IMAGE *out = argv[1]; |
| int start_x = *((int *) argv[2]); |
| int start_y = *((int *) argv[3]); |
| im_doublevec_object *dv = (im_doublevec_object *) argv[4]; |
| |
| PEL *ink; |
| |
| if( dv->n != in->Bands ) { |
| im_error( "im_flood_blob_copy", |
| "%s", _( "bad vector length" ) ); |
| return( -1 ); |
| } |
| if( !(ink = vector_to_ink( in, dv->vec )) ) |
| return( -1 ); |
| |
| return( im_flood_blob_copy( in, out, start_x, start_y, ink ) ); |
| } |
| |
| /* Description of im_flood_blob_copy(). |
| */ |
| static im_function flood_blob_copy_desc = { |
| "im_flood_blob_copy", /* Name */ |
| "flood with ink from start_x, start_y while pixel == start pixel", |
| 0, /* Flags */ |
| flood_blob_copy_vec, /* Dispatch function */ |
| IM_NUMBER( flood_blob_copy_args ),/* Size of arg list */ |
| flood_blob_copy_args /* Arg list */ |
| }; |
| |
| /* Args for im_flood_copy(). |
| */ |
| static im_arg_desc flood_copy_args[] = { |
| IM_INPUT_IMAGE( "in" ), |
| IM_OUTPUT_IMAGE( "out" ), |
| IM_INPUT_INT( "start_x" ), |
| IM_INPUT_INT( "start_y" ), |
| IM_INPUT_DOUBLEVEC( "ink" ) |
| }; |
| |
| /* Call im_flood_copy() via arg vector. |
| */ |
| static int |
| flood_copy_vec( im_object *argv ) |
| { |
| IMAGE *in = argv[0]; |
| IMAGE *out = argv[1]; |
| int start_x = *((int *) argv[2]); |
| int start_y = *((int *) argv[3]); |
| im_doublevec_object *dv = (im_doublevec_object *) argv[4]; |
| |
| PEL *ink; |
| |
| if( dv->n != in->Bands ) { |
| im_error( "im_flood_copy", |
| "%s", _( "bad vector length" ) ); |
| return( -1 ); |
| } |
| if( !(ink = vector_to_ink( in, dv->vec )) ) |
| return( -1 ); |
| |
| return( im_flood_copy( in, out, start_x, start_y, ink ) ); |
| } |
| |
| /* Description of im_flood_copy(). |
| */ |
| static im_function flood_copy_desc = { |
| "im_flood_copy", /* Name */ |
| "flood with ink from start_x, start_y while pixel == start pixel", |
| 0, /* Flags */ |
| flood_copy_vec, /* Dispatch function */ |
| IM_NUMBER( flood_copy_args ),/* Size of arg list */ |
| flood_copy_args /* Arg list */ |
| }; |
| |
| /* Args for im_flood_other_copy(). |
| */ |
| static im_arg_desc flood_other_copy_args[] = { |
| IM_INPUT_IMAGE( "test" ), |
| IM_INPUT_IMAGE( "mark" ), |
| IM_OUTPUT_IMAGE( "out" ), |
| IM_INPUT_INT( "start_x" ), |
| IM_INPUT_INT( "start_y" ), |
| IM_INPUT_INT( "serial" ) |
| }; |
| |
| /* Call im_flood_other_copy() via arg vector. |
| */ |
| static int |
| flood_other_copy_vec( im_object *argv ) |
| { |
| IMAGE *test = argv[0]; |
| IMAGE *mark = argv[1]; |
| IMAGE *out = argv[2]; |
| int start_x = *((int *) argv[3]); |
| int start_y = *((int *) argv[4]); |
| int serial = *((int *) argv[5]); |
| |
| return( im_flood_other_copy( test, mark, out, |
| start_x, start_y, serial ) ); |
| } |
| |
| /* Description of im_flood_other_copy(). |
| */ |
| static im_function flood_other_copy_desc = { |
| "im_flood_other_copy", /* Name */ |
| "flood mark with serial from start_x, start_y while pixel == start pixel", |
| 0, /* Flags */ |
| flood_other_copy_vec, /* Dispatch function */ |
| IM_NUMBER( flood_other_copy_args ),/* Size of arg list */ |
| flood_other_copy_args /* Arg list */ |
| }; |
| |
| /* To do: |
| * these all need some kind of pel type |
| * |
| im_flood.c |
| im_paintrect.c |
| im_plotmask.c |
| line_draw.c |
| plot_point.c |
| smudge_area.c |
| * |
| */ |
| |
| /* Package up all these functions. |
| */ |
| static im_function *inplace_list[] = { |
| &circle_desc, |
| &flood_copy_desc, |
| &flood_blob_copy_desc, |
| &flood_other_copy_desc, |
| &insertplace_desc, |
| &lineset_desc |
| }; |
| |
| /* Package of functions. |
| */ |
| im_package im__inplace = { |
| "inplace", |
| IM_NUMBER( inplace_list ), |
| inplace_list |
| }; |