1 /* Function dispatch tables for inplace.
2  *
3  * J. Cupitt, 8/2/95
4  */
5 
6 /*
7 
8     This file is part of VIPS.
9 
10     VIPS is free software; you can redistribute it and/or modify
11     it under the terms of the GNU Lesser General Public License as published by
12     the Free Software Foundation; either version 2 of the License, or
13     (at your option) any later version.
14 
15     This program is distributed in the hope that it will be useful,
16     but WITHOUT ANY WARRANTY; without even the implied warranty of
17     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18     GNU Lesser General Public License for more details.
19 
20     You should have received a copy of the GNU Lesser General Public License
21     along with this program; if not, write to the Free Software
22     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23     02110-1301  USA
24 
25  */
26 
27 /*
28 
29     These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
30 
31  */
32 
33 #ifdef HAVE_CONFIG_H
34 #include <config.h>
35 #endif /*HAVE_CONFIG_H*/
36 #include <vips/intl.h>
37 
38 #include <stdio.h>
39 
40 #include <vips/vips.h>
41 #include <vips/vips7compat.h>
42 
43 /* Calculate a pixel for an image from a vec of double. Valid while im is
44  * valid.
45  */
46 VipsPel *
im__vector_to_ink(const char * domain,IMAGE * im,int n,double * vec)47 im__vector_to_ink( const char *domain, IMAGE *im, int n, double *vec )
48 {
49 	IMAGE *t[3];
50 	double *zeros;
51 	int i;
52 
53 	if( im_check_vector( domain, n, im ) )
54 		return( NULL );
55 	if( im_open_local_array( im, t, 3, domain, "t" ) ||
56 		!(zeros = IM_ARRAY( im, n, double )) )
57 		return( NULL );
58 	for( i = 0; i < n; i++ )
59 		zeros[i] = 0.0;
60 
61 	if( im_black( t[0], 1, 1, im->Bands ) ||
62 		im_lintra_vec( n, zeros, t[0], vec, t[1] ) ||
63 		im_clip2fmt( t[1], t[2], im->BandFmt ) )
64 		return( NULL );
65 
66 	return( t[2]->data );
67 }
68 
69 double *
im__ink_to_vector(const char * domain,IMAGE * im,VipsPel * ink)70 im__ink_to_vector( const char *domain, IMAGE *im, VipsPel *ink )
71 {
72 	double *vec;
73 	int i;
74 
75 	if( im_check_uncoded( "im__ink_to_vector", im ) ||
76 		im_check_noncomplex( "im__ink_to_vector", im ) )
77 		return( NULL );
78 	if( !(vec = IM_ARRAY( NULL, im->Bands, double )) )
79 		return( NULL );
80 
81 #define READ( TYPE ) \
82 	vec[i] = ((TYPE *) ink)[i];
83 
84 	for( i = 0; i < im->Bands; i++ )
85 		switch( im->BandFmt ) {
86 		case IM_BANDFMT_UCHAR: 		READ( unsigned char ); break;
87 		case IM_BANDFMT_CHAR:  		READ( signed char ); break;
88 		case IM_BANDFMT_USHORT: 	READ( unsigned short ); break;
89 		case IM_BANDFMT_SHORT: 		READ( signed short ); break;
90 		case IM_BANDFMT_UINT: 		READ( unsigned int ); break;
91 		case IM_BANDFMT_INT: 		READ( signed int ); break;
92 		case IM_BANDFMT_FLOAT:  	READ( float ); break;
93 		case IM_BANDFMT_DOUBLE: 	READ( double ); break;
94 
95 		default:
96 			g_assert( 0 );
97 		}
98 
99 	return( vec );
100 }
101 
102 /* Args for im_draw_image.
103  */
104 static im_arg_desc draw_image_args[] = {
105 	IM_RW_IMAGE( "image" ),
106 	IM_INPUT_IMAGE( "sub" ),
107 	IM_INPUT_INT( "x" ),
108 	IM_INPUT_INT( "y" )
109 };
110 
111 /* Call im_draw_image via arg vector.
112  */
113 static int
draw_image_vec(im_object * argv)114 draw_image_vec( im_object *argv )
115 {
116 	int x = *((int *) argv[2]);
117 	int y = *((int *) argv[3]);
118 
119 	return( im_draw_image( argv[0], argv[1], x, y ) );
120 }
121 
122 /* Description of im_draw_image.
123  */
124 static im_function draw_image_desc = {
125 	"im_draw_image", 		/* Name */
126 	"draw image sub inside image main at position (x,y)",
127 	0,				/* Flags */
128 	draw_image_vec, 		/* Dispatch function */
129 	IM_NUMBER( draw_image_args ), 	/* Size of arg list */
130 	draw_image_args 		/* Arg list */
131 };
132 
133 /* Args for im_lineset.
134  */
135 static im_arg_desc lineset_args[] = {
136 	IM_INPUT_IMAGE( "in" ),
137 	IM_OUTPUT_IMAGE( "out" ),
138 	IM_INPUT_IMAGE( "mask" ),
139 	IM_INPUT_IMAGE( "ink" ),
140 	IM_INPUT_INTVEC( "x1" ),
141 	IM_INPUT_INTVEC( "y1" ),
142 	IM_INPUT_INTVEC( "x2" ),
143 	IM_INPUT_INTVEC( "y2" )
144 };
145 
146 /* Call im_lineset via arg vector.
147  */
148 static int
lineset_vec(im_object * argv)149 lineset_vec( im_object *argv )
150 {
151 	im_intvec_object *x1v = (im_intvec_object *) argv[4];
152 	im_intvec_object *y1v = (im_intvec_object *) argv[5];
153 	im_intvec_object *x2v = (im_intvec_object *) argv[6];
154 	im_intvec_object *y2v = (im_intvec_object *) argv[7];
155 
156 	if( x1v->n != y1v->n || x1v->n != x2v->n || x1v->n != y2v->n ) {
157 		im_error( "im_lineset", "%s", _( "vectors not same length" ) );
158 		return( -1 );
159 	}
160 
161 	return( im_lineset( argv[0], argv[1], argv[2], argv[3],
162 		x1v->n, x1v->vec, y1v->vec, x2v->vec, y2v->vec ) );
163 }
164 
165 /* Description of im_lineset.
166  */
167 static im_function lineset_desc = {
168 	"im_lineset", 		/* Name */
169 	"draw line between points (x1,y1) and (x2,y2)",
170 	0,			/* Flags */
171 	lineset_vec, 		/* Dispatch function */
172 	IM_NUMBER( lineset_args ), 	/* Size of arg list */
173 	lineset_args 		/* Arg list */
174 };
175 
176 /* Args for im_draw_mask.
177  */
178 static im_arg_desc draw_mask_args[] = {
179 	IM_RW_IMAGE( "image" ),
180 	IM_INPUT_IMAGE( "mask" ),
181 	IM_INPUT_INT( "x" ),
182 	IM_INPUT_INT( "y" ),
183 	IM_INPUT_DOUBLEVEC( "ink" )
184 };
185 
186 /* Call im_draw_mask via arg vector.
187  */
188 static int
draw_mask_vec(im_object * argv)189 draw_mask_vec( im_object *argv )
190 {
191 	IMAGE *image = argv[0];
192 	IMAGE *mask = argv[1];
193 	int x = *((int *) argv[2]);
194 	int y = *((int *) argv[3]);
195 	im_doublevec_object *dv = (im_doublevec_object *) argv[4];
196 
197 	VipsPel *ink;
198 
199 	if( !(ink = im__vector_to_ink( "im_draw_mask",
200 		image, dv->n, dv->vec )) )
201 		return( -1 );
202 
203 	return( im_draw_mask( image, mask, x, y, ink ) );
204 }
205 
206 /* Description of im_draw_mask.
207  */
208 static im_function draw_mask_desc = {
209 	"im_draw_mask", 		/* Name */
210 	"draw mask sub inside image main at position (x,y)",
211 	0,				/* Flags */
212 	draw_mask_vec, 			/* Dispatch function */
213 	IM_NUMBER( draw_mask_args ), 	/* Size of arg list */
214 	draw_mask_args 			/* Arg list */
215 };
216 
217 /* Args for im_draw_flood_blob().
218  */
219 static im_arg_desc draw_flood_blob_args[] = {
220 	IM_RW_IMAGE( "image" ),
221 	IM_INPUT_INT( "x" ),
222 	IM_INPUT_INT( "y" ),
223 	IM_INPUT_DOUBLEVEC( "ink" )
224 };
225 
226 /* Call im_draw_flood_blob() via arg vector.
227  */
228 static int
draw_flood_blob_vec(im_object * argv)229 draw_flood_blob_vec( im_object *argv )
230 {
231 	IMAGE *image = argv[0];
232 	int x = *((int *) argv[1]);
233 	int y = *((int *) argv[2]);
234 	im_doublevec_object *dv = (im_doublevec_object *) argv[3];
235 
236 	VipsPel *ink;
237 
238 	if( !(ink = im__vector_to_ink( "im_draw_flood_blob",
239 		image, dv->n, dv->vec )) )
240 		return( -1 );
241 
242 	return( im_draw_flood_blob( image, x, y, ink, NULL ) );
243 }
244 
245 /* Description of im_draw_flood_blob().
246  */
247 static im_function draw_flood_blob_desc = {
248 	"im_draw_flood_blob",	/* Name */
249 	"flood with ink from x, y while pixel == start",
250 	0,			/* Flags */
251 	draw_flood_blob_vec, 	/* Dispatch function */
252 	IM_NUMBER( draw_flood_blob_args ),/* Size of arg list */
253 	draw_flood_blob_args 	/* Arg list */
254 };
255 
256 /* Args for im_draw_flood().
257  */
258 static im_arg_desc draw_flood_args[] = {
259 	IM_RW_IMAGE( "image" ),
260 	IM_INPUT_INT( "x" ),
261 	IM_INPUT_INT( "y" ),
262 	IM_INPUT_DOUBLEVEC( "ink" )
263 };
264 
265 /* Call im_draw_flood() via arg vector.
266  */
267 static int
draw_flood_vec(im_object * argv)268 draw_flood_vec( im_object *argv )
269 {
270 	IMAGE *image = argv[0];
271 	int x = *((int *) argv[1]);
272 	int y = *((int *) argv[2]);
273 	im_doublevec_object *dv = (im_doublevec_object *) argv[3];
274 
275 	VipsPel *ink;
276 
277 	if( !(ink = im__vector_to_ink( "im_draw_flood",
278 		image, dv->n, dv->vec )) )
279 		return( -1 );
280 
281 	return( im_draw_flood( image, x, y, ink, NULL ) );
282 }
283 
284 /* Description of im_draw_flood().
285  */
286 static im_function draw_flood_desc = {
287 	"im_draw_flood",	/* Name */
288 	"flood with ink from x, y while pixel != ink",
289 	0,			/* Flags */
290 	draw_flood_vec, 	/* Dispatch function */
291 	IM_NUMBER( draw_flood_args ),/* Size of arg list */
292 	draw_flood_args 	/* Arg list */
293 };
294 
295 /* Args for im_draw_flood_other().
296  */
297 static im_arg_desc draw_flood_other_args[] = {
298 	IM_RW_IMAGE( "image" ),
299 	IM_INPUT_IMAGE( "test" ),
300 	IM_INPUT_INT( "x" ),
301 	IM_INPUT_INT( "y" ),
302 	IM_INPUT_INT( "serial" )
303 };
304 
305 /* Call im_draw_flood_other() via arg vector.
306  */
307 static int
draw_flood_other_vec(im_object * argv)308 draw_flood_other_vec( im_object *argv )
309 {
310 	IMAGE *image = argv[0];
311 	IMAGE *test = argv[1];
312 	int x = *((int *) argv[2]);
313 	int y = *((int *) argv[3]);
314 	int serial = *((int *) argv[4]);
315 
316 	return( im_draw_flood_other( image, test, x, y, serial, NULL ) );
317 }
318 
319 /* Description of im_draw_flood_other().
320  */
321 static im_function draw_flood_other_desc = {
322 	"im_draw_flood_other",	/* Name */
323 	"flood image with serial from x, y while pixel == start",
324 	0,			/* Flags */
325 	draw_flood_other_vec, 	/* Dispatch function */
326 	IM_NUMBER( draw_flood_other_args ),/* Size of arg list */
327 	draw_flood_other_args 	/* Arg list */
328 };
329 
330 /* Args for im_draw_point.
331  */
332 static im_arg_desc draw_point_args[] = {
333 	IM_RW_IMAGE( "image" ),
334 	IM_INPUT_INT( "x" ),
335 	IM_INPUT_INT( "y" ),
336 	IM_INPUT_DOUBLEVEC( "ink" )
337 };
338 
339 /* Call im_draw_point via arg vector.
340  */
341 static int
draw_point_vec(im_object * argv)342 draw_point_vec( im_object *argv )
343 {
344 	IMAGE *image = argv[0];
345 	int x = *((int *) argv[1]);
346 	int y = *((int *) argv[2]);
347 	im_doublevec_object *dv = (im_doublevec_object *) argv[3];
348 
349 	VipsPel *ink;
350 
351 	if( !(ink = im__vector_to_ink( "im_draw_point",
352 		image, dv->n, dv->vec )) )
353 		return( -1 );
354 
355 	return( im_draw_point( image, x, y, ink ) );
356 }
357 
358 /* Description of im_draw_point.
359  */
360 static im_function draw_point_desc = {
361 	"im_draw_point", 		/* Name */
362 	"draw point on image",
363 	0,				/* Flags */
364 	draw_point_vec, 		/* Dispatch function */
365 	IM_NUMBER( draw_point_args ), 	/* Size of arg list */
366 	draw_point_args 		/* Arg list */
367 };
368 
369 /* Args for im_read_point.
370  */
371 static im_arg_desc read_point_args[] = {
372 	IM_INPUT_IMAGE( "image" ),
373 	IM_INPUT_INT( "x" ),
374 	IM_INPUT_INT( "y" ),
375 	IM_OUTPUT_DOUBLEVEC( "ink" )
376 };
377 
378 /* Call im_read_point via arg vector.
379  */
380 static int
read_point_vec(im_object * argv)381 read_point_vec( im_object *argv )
382 {
383 	IMAGE *image = argv[0];
384 	int x = *((int *) argv[1]);
385 	int y = *((int *) argv[2]);
386 	im_doublevec_object *dv = (im_doublevec_object *) argv[3];
387 
388 	VipsPel *ink;
389 
390 	if( !(ink = IM_ARRAY( image, IM_IMAGE_SIZEOF_PEL( image ), VipsPel )) ||
391 		im_read_point( image, x, y, ink ) ||
392 		!(dv->vec = im__ink_to_vector( "im_read_point", image, ink )) )
393 		return( -1 );
394 	dv->n = image->Bands;
395 
396 	return( 0 );
397 }
398 
399 /* Description of im_read_point.
400  */
401 static im_function read_point_desc = {
402 	"im_read_point", 		/* Name */
403 	"read point from image",
404 	0,				/* Flags */
405 	read_point_vec, 		/* Dispatch function */
406 	IM_NUMBER( read_point_args ), 	/* Size of arg list */
407 	read_point_args 		/* Arg list */
408 };
409 
410 /* Args for im_draw_line.
411  */
412 static im_arg_desc draw_line_args[] = {
413 	IM_RW_IMAGE( "image" ),
414 	IM_INPUT_INT( "x1" ),
415 	IM_INPUT_INT( "y1" ),
416 	IM_INPUT_INT( "x2" ),
417 	IM_INPUT_INT( "y2" ),
418 	IM_INPUT_DOUBLEVEC( "ink" )
419 };
420 
421 /* Call im_draw_line via arg vector.
422  */
423 static int
draw_line_vec(im_object * argv)424 draw_line_vec( im_object *argv )
425 {
426 	IMAGE *image = argv[0];
427 	int x1 = *((int *) argv[1]);
428 	int y1 = *((int *) argv[2]);
429 	int x2 = *((int *) argv[3]);
430 	int y2 = *((int *) argv[4]);
431 	im_doublevec_object *dv = (im_doublevec_object *) argv[5];
432 
433 	VipsPel *ink;
434 
435 	if( !(ink = im__vector_to_ink( "im_draw_line",
436 		image, dv->n, dv->vec )) )
437 		return( -1 );
438 
439 	return( im_draw_line( image, x1, y1, x2, y2, ink ) );
440 }
441 
442 /* Description of im_draw_line.
443  */
444 static im_function draw_line_desc = {
445 	"im_draw_line", 		/* Name */
446 	"draw line on image",
447 	0,				/* Flags */
448 	draw_line_vec, 			/* Dispatch function */
449 	IM_NUMBER( draw_line_args ), 	/* Size of arg list */
450 	draw_line_args 			/* Arg list */
451 };
452 
453 /* Args for im_draw_smudge.
454  */
455 static im_arg_desc draw_smudge_args[] = {
456 	IM_RW_IMAGE( "image" ),
457 	IM_INPUT_INT( "left" ),
458 	IM_INPUT_INT( "top" ),
459 	IM_INPUT_INT( "width" ),
460 	IM_INPUT_INT( "height" )
461 };
462 
463 /* Call im_draw_smudge via arg vector.
464  */
465 static int
draw_smudge_vec(im_object * argv)466 draw_smudge_vec( im_object *argv )
467 {
468 	IMAGE *image = argv[0];
469 	int left = *((int *) argv[1]);
470 	int top = *((int *) argv[2]);
471 	int width = *((int *) argv[3]);
472 	int height = *((int *) argv[4]);
473 
474 	return( im_draw_smudge( image, left, top, width, height ) );
475 }
476 
477 /* Description of im_draw_smudge.
478  */
479 static im_function draw_smudge_desc = {
480 	"im_draw_smudge", 		/* Name */
481 	"smudge part of an image",
482 	0,				/* Flags */
483 	draw_smudge_vec, 		/* Dispatch function */
484 	IM_NUMBER( draw_smudge_args ), 	/* Size of arg list */
485 	draw_smudge_args 		/* Arg list */
486 };
487 
488 /* Args for im_draw_rect.
489  */
490 static im_arg_desc draw_rect_args[] = {
491 	IM_RW_IMAGE( "image" ),
492 	IM_INPUT_INT( "left" ),
493 	IM_INPUT_INT( "top" ),
494 	IM_INPUT_INT( "width" ),
495 	IM_INPUT_INT( "height" ),
496 	IM_INPUT_INT( "fill" ),
497 	IM_INPUT_DOUBLEVEC( "ink" )
498 };
499 
500 /* Call im_draw_rect via arg vector.
501  */
502 static int
draw_rect_vec(im_object * argv)503 draw_rect_vec( im_object *argv )
504 {
505 	IMAGE *image = argv[0];
506 	int left = *((int *) argv[1]);
507 	int top = *((int *) argv[2]);
508 	int width = *((int *) argv[3]);
509 	int height = *((int *) argv[4]);
510 	int fill = *((int *) argv[5]);
511 	im_doublevec_object *dv = (im_doublevec_object *) argv[6];
512 
513 	VipsPel *ink;
514 
515 	if( !(ink = im__vector_to_ink( "im_draw_rect",
516 		image, dv->n, dv->vec )) )
517 		return( -1 );
518 
519 	return( im_draw_rect( image, left, top, width, height, fill, ink ) );
520 }
521 
522 /* Description of im_draw_rect.
523  */
524 static im_function draw_rect_desc = {
525 	"im_draw_rect", 		/* Name */
526 	"draw rect on image",
527 	0,				/* Flags */
528 	draw_rect_vec, 			/* Dispatch function */
529 	IM_NUMBER( draw_rect_args ), 	/* Size of arg list */
530 	draw_rect_args 			/* Arg list */
531 };
532 
533 /* Args for im_draw_circle.
534  */
535 static im_arg_desc draw_circle_args[] = {
536 	IM_RW_IMAGE( "image" ),
537 	IM_INPUT_INT( "cx" ),
538 	IM_INPUT_INT( "cy" ),
539 	IM_INPUT_INT( "radius" ),
540 	IM_INPUT_INT( "fill" ),
541 	IM_INPUT_DOUBLEVEC( "ink" )
542 };
543 
544 /* Call im_draw_circle via arg vector.
545  */
546 static int
draw_circle_vec(im_object * argv)547 draw_circle_vec( im_object *argv )
548 {
549 	IMAGE *image = argv[0];
550 	int cx = *((int *) argv[1]);
551 	int cy = *((int *) argv[2]);
552 	int radius = *((int *) argv[3]);
553 	int fill = *((int *) argv[4]);
554 	im_doublevec_object *dv = (im_doublevec_object *) argv[5];
555 
556 	VipsPel *ink;
557 
558 	if( !(ink = im__vector_to_ink( "im_draw_circle",
559 		image, dv->n, dv->vec )) )
560 		return( -1 );
561 
562 	return( im_draw_circle( image, cx, cy, radius, fill, ink ) );
563 }
564 
565 /* Description of im_draw_circle.
566  */
567 static im_function draw_circle_desc = {
568 	"im_draw_circle", 		/* Name */
569 	"draw circle on image",
570 	0,				/* Flags */
571 	draw_circle_vec, 		/* Dispatch function */
572 	IM_NUMBER( draw_circle_args ), 	/* Size of arg list */
573 	draw_circle_args 		/* Arg list */
574 };
575 
576 /* Package up all these functions.
577  */
578 static im_function *inplace_list[] = {
579 	&draw_circle_desc,
580 	&draw_rect_desc,
581 	&draw_line_desc,
582 	&draw_point_desc,
583 	&read_point_desc,
584 	&draw_smudge_desc,
585 	&draw_flood_desc,
586 	&draw_flood_blob_desc,
587 	&draw_flood_other_desc,
588 	&draw_image_desc,
589 	&draw_mask_desc,
590 	&lineset_desc
591 };
592 
593 /* Package of functions.
594  */
595 im_package im__inplace = {
596 	"inplace",
597 	IM_NUMBER( inplace_list ),
598 	inplace_list
599 };
600