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