1 /* compat stuff for vips7
2 *
3 * 4/3/11
4 * - hacked up
5 */
6
7 /*
8
9 This file is part of VIPS.
10
11 VIPS is free software; you can redistribute it and/or modify
12 it under the terms of the GNU Lesser General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU Lesser General Public License for more details.
20
21 You should have received a copy of the GNU Lesser General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 02110-1301 USA
25
26 */
27
28 /*
29
30 These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
31
32 */
33
34 /*
35 #define VIPS_DEBUG
36 */
37
38 #ifdef HAVE_CONFIG_H
39 #include <config.h>
40 #endif /*HAVE_CONFIG_H*/
41 #include <vips/intl.h>
42
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <ctype.h>
47
48 #include <vips/vips.h>
49 #include <vips/vips7compat.h>
50 #include <vips/internal.h>
51 #include <vips/debug.h>
52 #include <vips/vector.h>
53 #include <vips/transform.h>
54
55 /* Split filename into name / mode components. name and mode should both be
56 * FILENAME_MAX chars.
57 *
58 * We look for the ':' splitting the name and mode by searching for the
59 * rightmost occurrence of the regexp "\.[A-Za-z0-9]+:". The initial dot can
60 * be missing if there's a dirsep or start of string, meaning this is a
61 * filename without an extension.
62 *
63 * Examples:
64 *
65 * c:\silly:dir:name\fr:ed.tif:jpeg:95,,,,c:\icc\srgb.icc
66 * -> c:\silly:dir:name\fr:ed.tif jpeg:95,,,,c:\icc\srgb.icc
67 * I180:
68 * -> I180 ""
69 * c:\silly:
70 * -> c:\silly ""
71 * c:\silly
72 * -> c:\silly ""
73 * C:\fixtures\2569067123_aca715a2ee_o.jpg
74 * -> C:\fixtures\2569067123_aca715a2ee_o.jpg ""
75 *
76 * vips8 handles this in a much better way :(
77 */
78 void
im_filename_split(const char * path,char * name,char * mode)79 im_filename_split( const char *path, char *name, char *mode )
80 {
81 char *p;
82 size_t len;
83
84 vips_strncpy( name, path, FILENAME_MAX );
85 strcpy( mode, "" );
86
87 if( (len = strlen( name )) == 0 )
88 return;
89
90 /* Search backwards towards start, stopping at each ':' char.
91 */
92 for( p = name + len - 1; p > name; p -= 1 )
93 if( *p == ':' ) {
94 char *q;
95
96 /* We are skipping back over the file extension,
97 * isalnum() is probably sufficient.
98 */
99 for( q = p - 1; isalnum( *q ) && q > name; q -= 1 )
100 ;
101
102 if( *q == '.' ) {
103 break;
104 }
105
106 /* All the way back to the start? We probably have a
107 * filename with no extension, eg. "I180:"
108 */
109 if( q == name )
110 break;
111
112 /* .. or we could hit a dirsep. Allow win or nix
113 * separators.
114 */
115 if( *q == '/' ||
116 *q == '\\' )
117 break;
118 }
119
120 /* Ignore a ':' in column 1, it's probably a drive letter on a
121 * Windows path.
122 */
123 if( *p == ':' &&
124 p - name != 1 ) {
125 vips_strncpy( mode, p + 1, FILENAME_MAX );
126 *p = '\0';
127 }
128 }
129
130 /**
131 * vips_path_filename7:
132 * @path: path to split
133 *
134 * Return the filename part of a vips7 path. For testing only.
135 */
136 char *
vips_path_filename7(const char * path)137 vips_path_filename7( const char *path )
138 {
139 char name[FILENAME_MAX];
140 char mode[FILENAME_MAX];
141
142 im_filename_split( path, name, mode );
143
144 return( g_strdup( name ) );
145 }
146
147 /**
148 * vips_path_mode7:
149 * @path: path to split
150 *
151 * Return the mode part of a vips7 path. For testing only.
152 */
153 char *
vips_path_mode7(const char * path)154 vips_path_mode7( const char *path )
155 {
156 char name[FILENAME_MAX];
157 char mode[FILENAME_MAX];
158
159 im_filename_split( path, name, mode );
160
161 return( g_strdup( mode ) );
162 }
163
164 /* Skip any leading path stuff. Horrible: if this is a filename which came
165 * from win32 and we're a *nix machine, it'll have '\\' not '/' as the
166 * separator :-(
167 *
168 * Try to fudge this ... if the file doesn't contain any of our native
169 * separators, look for the opposite one as well. If there are none of those
170 * either, just return the filename.
171 */
172 const char *
im_skip_dir(const char * path)173 im_skip_dir( const char *path )
174 {
175 char name[FILENAME_MAX];
176 char mode[FILENAME_MAX];
177 const char *p;
178 const char *q;
179
180 const char native_dir_sep = G_DIR_SEPARATOR;
181 const char non_native_dir_sep = native_dir_sep == '/' ? '\\' : '/';
182
183 /* Remove any trailing save modifiers: we don't want '/' or '\' in the
184 * modifier confusing us.
185 */
186 im_filename_split( path, name, mode );
187
188 /* The '\0' char at the end of the string.
189 */
190 p = name + strlen( name );
191
192 /* Search back for the first native dir sep, or failing that, the first
193 * non-native dir sep.
194 */
195 for( q = p; q > name && q[-1] != native_dir_sep; q-- )
196 ;
197 if( q == name )
198 for( q = p; q > name && q[-1] != non_native_dir_sep; q-- )
199 ;
200
201 return( path + (q - name) );
202 }
203
204 /* Extract suffix from filename, ignoring any mode string. Suffix should be
205 * FILENAME_MAX chars. Include the "." character, if any.
206 */
207 void
im_filename_suffix(const char * path,char * suffix)208 im_filename_suffix( const char *path, char *suffix )
209 {
210 char name[FILENAME_MAX];
211 char mode[FILENAME_MAX];
212 char *p;
213
214 im_filename_split( path, name, mode );
215 if( (p = strrchr( name, '.' )) )
216 strcpy( suffix, p );
217 else
218 strcpy( suffix, "" );
219 }
220
221 /* Does a filename have one of a set of suffixes. Ignore case.
222 */
223 int
im_filename_suffix_match(const char * path,const char * suffixes[])224 im_filename_suffix_match( const char *path, const char *suffixes[] )
225 {
226 char suffix[FILENAME_MAX];
227 const char **p;
228
229 im_filename_suffix( path, suffix );
230 for( p = suffixes; *p; p++ )
231 if( g_ascii_strcasecmp( suffix, *p ) == 0 )
232 return( 1 );
233
234 return( 0 );
235 }
236
237 /* p points to the start of a buffer ... move it on through the buffer (ready
238 * for the next call), and return the current option (or NULL for option
239 * missing). ',' characters inside options can be escaped with a '\'.
240 */
241 char *
im_getnextoption(char ** in)242 im_getnextoption( char **in )
243 {
244 char *p;
245 char *q;
246
247 p = *in;
248 q = p;
249
250 if( !p || !*p )
251 return( NULL );
252
253 /* Find the next ',' not prefixed with a '\'. If the first character
254 * of p is ',', there can't be a previous escape character.
255 */
256 for(;;) {
257 if( !(p = strchr( p, ',' )) )
258 break;
259 if( p == q )
260 break;
261 if( p[-1] != '\\' )
262 break;
263
264 p += 1;
265 }
266
267 if( p ) {
268 /* Another option follows this one .. set up to pick that out
269 * next time.
270 */
271 *p = '\0';
272 *in = p + 1;
273 }
274 else {
275 /* This is the last one.
276 */
277 *in = NULL;
278 }
279
280 if( strlen( q ) > 0 )
281 return( q );
282 else
283 return( NULL );
284 }
285
286 /* Get a suboption string, or NULL.
287 */
288 char *
im_getsuboption(const char * buf)289 im_getsuboption( const char *buf )
290 {
291 char *p, *q, *r;
292
293 if( !(p = strchr( buf, ':' )) )
294 /* No suboption.
295 */
296 return( NULL );
297
298 /* Step over the ':'.
299 */
300 p += 1;
301
302 /* Need to unescape any \, pairs. Shift stuff down one if we find one.
303 */
304 for( q = p; *q; q++ )
305 if( q[0] == '\\' && q[1] == ',' )
306 for( r = q; *r; r++ )
307 r[0] = r[1];
308
309 return( p );
310 }
311
312 VipsImage *
im_open(const char * filename,const char * mode)313 im_open( const char *filename, const char *mode )
314 {
315 VipsImage *image;
316
317 vips_check_init();
318
319 /* We have to go via the old VipsFormat system so we can support the
320 * "filename:option" syntax.
321 *
322 * Use "rs" to turn on seq mode.
323 */
324 if( strcmp( mode, "r" ) == 0 ||
325 strcmp( mode, "rd" ) == 0 ) {
326 if( !(image = vips__deprecated_open_read( filename, FALSE )) )
327 return( NULL );
328 }
329 else if( strcmp( mode, "rs" ) == 0 ) {
330 if( !(image = vips__deprecated_open_read( filename, TRUE )) )
331 return( NULL );
332 }
333 else if( strcmp( mode, "w" ) == 0 ) {
334 if( !(image = vips__deprecated_open_write( filename )) )
335 return( NULL );
336 }
337 else {
338 if( !(image = vips_image_new_mode( filename, mode )) )
339 return( NULL );
340 }
341
342 return( image );
343 }
344
345 /* Just for compatibility. New code should use vips_object_local() directly.
346 */
347 VipsImage *
im_open_local(VipsImage * parent,const char * filename,const char * mode)348 im_open_local( VipsImage *parent,
349 const char *filename, const char *mode )
350 {
351 VipsImage *image;
352
353 if( !(image = im_open( filename, mode )) )
354 return( NULL );
355 vips_object_local( parent, image );
356
357 return( image );
358 }
359
360 /* Just for compatibility. New code should use vips_object_local_array().
361 */
362 int
im_open_local_array(VipsImage * parent,VipsImage ** images,int n,const char * filename,const char * mode)363 im_open_local_array( VipsImage *parent,
364 VipsImage **images, int n,
365 const char *filename, const char *mode )
366 {
367 int i;
368
369 for( i = 0; i < n; i++ )
370 if( !(images[i] = im_open_local( parent, filename, mode )) )
371 return( -1 );
372
373 return( 0 );
374 }
375
376 typedef struct {
377 im_callback_fn fn;
378 void *a;
379 void *b;
380 } Callback;
381
382 static void
im_add_callback_cb(VipsImage * im,Callback * callback)383 im_add_callback_cb( VipsImage *im, Callback *callback )
384 {
385 if( callback->fn( callback->a, callback->b ) )
386 vips_image_set_kill( im, TRUE );
387 }
388
389 int
im_add_callback(VipsImage * im,const char * name,im_callback_fn fn,void * a,void * b)390 im_add_callback( VipsImage *im,
391 const char *name, im_callback_fn fn, void *a, void *b )
392 {
393 Callback *callback;
394
395 callback = VIPS_NEW( VIPS_OBJECT( im ), Callback );
396 callback->fn = fn;
397 callback->a = a;
398 callback->b = b;
399 g_signal_connect( im, name,
400 G_CALLBACK( im_add_callback_cb ), callback );
401
402 return( 0 );
403 }
404
405 static void
im_add_callback_cb1(VipsImage * im,void * x,Callback * callback)406 im_add_callback_cb1( VipsImage *im, void *x, Callback *callback )
407 {
408 if( callback->fn( callback->a, callback->b ) )
409 vips_image_set_kill( im, TRUE );
410 }
411
412 int
im_add_callback1(VipsImage * im,const char * name,im_callback_fn fn,void * a,void * b)413 im_add_callback1( VipsImage *im,
414 const char *name, im_callback_fn fn, void *a, void *b )
415 {
416 Callback *callback;
417
418 callback = VIPS_NEW( VIPS_OBJECT( im ), Callback );
419 callback->fn = fn;
420 callback->a = a;
421 callback->b = b;
422 g_signal_connect( im, name,
423 G_CALLBACK( im_add_callback_cb1 ), callback );
424
425 return( 0 );
426 }
427
428 /* Make something local to an image descriptor ... pass in a constructor
429 * and a destructor, plus three args.
430 */
431 void *
im_local(IMAGE * im,im_construct_fn cons,im_callback_fn dest,void * a,void * b,void * c)432 im_local( IMAGE *im,
433 im_construct_fn cons, im_callback_fn dest, void *a, void *b, void *c )
434 {
435 void *obj;
436
437 if( !im ) {
438 im_error( "im_local", "%s", _( "NULL image descriptor" ) );
439 return( NULL );
440 }
441
442 if( !(obj = cons( a, b, c )) )
443 return( NULL );
444 if( im_add_close_callback( im, (im_callback_fn) dest, obj, a ) ) {
445 dest( obj, a );
446 return( NULL );
447 }
448
449 return( obj );
450 }
451
452 /* Make an array of things local to a descriptor ... eg. make 6 local temp
453 * images.
454 */
455 int
im_local_array(IMAGE * im,void ** out,int n,im_construct_fn cons,im_callback_fn dest,void * a,void * b,void * c)456 im_local_array( IMAGE *im, void **out, int n,
457 im_construct_fn cons, im_callback_fn dest, void *a, void *b, void *c )
458 {
459 int i;
460
461 for( i = 0; i < n; i++ )
462 if( !(out[i] = im_local( im, cons, dest, a, b, c )) )
463 return( -1 );
464
465 return( 0 );
466 }
467
468 int
im_close(VipsImage * im)469 im_close( VipsImage *im )
470 {
471 g_object_unref( im );
472
473 return( 0 );
474 }
475
476 /* edvips.c needs this
477 */
478 VipsImage *
im_init(const char * filename)479 im_init( const char *filename )
480 {
481 VipsImage *image;
482
483 image = vips_image_new();
484 IM_SETSTR( image->filename, filename );
485
486 return( image );
487 }
488
489 /* We can't do this with a rename macro since the C++ interface needs
490 * this entrypoint, see VImage.h.
491 *
492 * As a result our fancy ABI check will not work with the vips7 interface.
493 */
494 int
im_init_world(const char * argv0)495 im_init_world( const char *argv0 )
496 {
497 return( vips_init( argv0 ) );
498 }
499
500 /* Prettyprint various header fields. Just for vips7 compat, use
501 * vips_enum_value() instead.
502 */
im_Type2char(VipsInterpretation type)503 const char *im_Type2char( VipsInterpretation type )
504 { return( vips_enum_string( VIPS_TYPE_INTERPRETATION, type ) ); }
im_BandFmt2char(VipsBandFormat format)505 const char *im_BandFmt2char( VipsBandFormat format )
506 { return( vips_enum_string( VIPS_TYPE_BAND_FORMAT, format ) ); }
im_Coding2char(VipsCoding coding)507 const char *im_Coding2char( VipsCoding coding )
508 { return( vips_enum_string( VIPS_TYPE_CODING, coding ) ); }
im_dtype2char(VipsImageType n)509 const char *im_dtype2char( VipsImageType n )
510 { return( vips_enum_string( VIPS_TYPE_IMAGE_TYPE, n ) ); }
im_dhint2char(VipsDemandStyle style)511 const char *im_dhint2char( VipsDemandStyle style )
512 { return( vips_enum_string( VIPS_TYPE_DEMAND_STYLE, style ) ); }
513
514 /* Old names for enums, for compat.
515 */
516 static const char *im_Type[] = {
517 "IM_TYPE_MULTIBAND", /* 0 */
518 "IM_TYPE_B_W", /* 1 */
519 "LUMINACE", /* 2 */
520 "XRAY", /* 3 */
521 "IR", /* 4 */
522 "YUV", /* 5 */
523 "RED_ONLY", /* 6 */
524 "GREEN_ONLY", /* 7 */
525 "BLUE_ONLY", /* 8 */
526 "POWER_SPECTRUM", /* 9 */
527 "IM_TYPE_HISTOGRAM", /* 10 */
528 "LUT", /* 11 */
529 "IM_TYPE_XYZ", /* 12 */
530 "IM_TYPE_LAB", /* 13 */
531 "CMC", /* 14 */
532 "IM_TYPE_CMYK", /* 15 */
533 "IM_TYPE_LABQ", /* 15 */
534 "IM_TYPE_RGB", /* 17 */
535 "IM_TYPE_UCS", /* 18 */
536 "IM_TYPE_LCH", /* 19 */
537 "IM_TYPE_LABS", /* 20 */
538 "<unknown>", /* 21 */
539 "IM_TYPE_sRGB", /* 22 */
540 "IM_TYPE_YXY", /* 23 */
541 "IM_TYPE_FOURIER", /* 24 */
542 "IM_TYPE_RGB16", /* 25 */
543 "IM_TYPE_GREY16", /* 26 */
544 NULL
545 };
546
547 static const char *im_BandFmt[] = {
548 "IM_BANDFMT_UCHAR",
549 "IM_BANDFMT_CHAR",
550 "IM_BANDFMT_USHORT",
551 "IM_BANDFMT_SHORT",
552 "IM_BANDFMT_UINT",
553 "IM_BANDFMT_INT",
554 "IM_BANDFMT_FLOAT",
555 "IM_BANDFMT_COMPLEX",
556 "IM_BANDFMT_DOUBLE",
557 "IM_BANDFMT_DPCOMPLEX",
558 NULL
559 };
560
561 static const char *im_Coding[] = {
562 "IM_CODING_NONE",
563 "COLQUANT8",
564 "IM_CODING_LABQ",
565 "IM_CODING_LABQ_COMPRESSED",
566 "RGB_COMPRESSED",
567 "LUM_COMPRESSED",
568 "IM_CODING_RAD",
569 NULL
570 };
571
572 static const char *im_dtype[] = {
573 "IM_NONE",
574 "IM_SETBUF",
575 "IM_SETBUF_FOREIGN",
576 "IM_OPENIN",
577 "IM_MMAPIN",
578 "IM_MMAPINRW",
579 "IM_OPENOUT",
580 "IM_PARTIAL",
581 NULL
582 };
583
584 static const char *im_dhint[] = {
585 "IM_SMALLTILE",
586 "IM_FATSTRIP",
587 "IM_THINSTRIP",
588 "IM_ANY",
589 NULL
590 };
591
592 /* enum string to int, try the GEnum first, then use a compat *char[] for old
593 * names.
594 */
595 static int
lookup_enum(GType type,const char * names[],const char * name)596 lookup_enum( GType type, const char *names[], const char *name )
597 {
598 GEnumClass *class;
599 GEnumValue *value;
600 int i;
601
602 class = g_type_class_ref( type );
603 if( (value = g_enum_get_value_by_nick( class, name )) )
604 return( value->value );
605 if( (value = g_enum_get_value_by_name( class, name )) )
606 return( value->value );
607
608 for( i = 0; names[i]; i++ )
609 if( g_ascii_strcasecmp( names[i], name ) == 0 )
610 return( i );
611
612 return( -1 );
613 }
614
im_char2Type(const char * str)615 VipsInterpretation im_char2Type( const char *str )
616 { return( lookup_enum( VIPS_TYPE_INTERPRETATION, im_Type, str ) ); }
im_char2BandFmt(const char * str)617 VipsBandFormat im_char2BandFmt( const char *str )
618 { return( lookup_enum( VIPS_TYPE_BAND_FORMAT, im_BandFmt, str ) ); }
im_char2Coding(const char * str)619 VipsCoding im_char2Coding( const char *str )
620 { return( lookup_enum( VIPS_TYPE_CODING, im_Coding, str ) ); }
im_char2dtype(const char * str)621 VipsImageType im_char2dtype( const char *str )
622 { return( lookup_enum( VIPS_TYPE_IMAGE_TYPE, im_dtype, str ) ); }
im_char2dhint(const char * str)623 VipsDemandStyle im_char2dhint( const char *str )
624 { return( lookup_enum( VIPS_TYPE_DEMAND_STYLE, im_dhint, str ) ); }
625
626 /* Totally useless now.
627 */
im_Compression2char(int n)628 const char *im_Compression2char( int n ) { return( "NONE" ); }
im_char2Compression(const char * str)629 int im_char2Compression( const char *str ) { return( -1 ); }
630
631 /* Wrap one / many is being replaced by a class thing.
632 */
633
634 typedef struct {
635 im_wrapmany_fn fn; /* Function we call */
636 void *a, *b; /* User values for function */
637 } Bundle;
638
639 /* Maximum number of input images -- why not?
640 */
641 #define MAX_INPUT_IMAGES (64)
642
643 /* Convert a VipsRegion.
644 */
645 static int
process_region(VipsRegion * or,void * seq,void * a,void * b)646 process_region( VipsRegion *or, void *seq, void *a, void *b )
647 {
648 VipsRegion **ir = (VipsRegion **) seq;
649 Bundle *bun = (Bundle *) b;
650
651 PEL *p[MAX_INPUT_IMAGES], *q;
652 int i, y;
653
654 /* Prepare all input regions and make buffer pointers.
655 */
656 if( vips_reorder_prepare_many( or->im, ir, &or->valid ) )
657 return( -1 );
658 for( i = 0; ir[i]; i++ )
659 p[i] = (PEL *) VIPS_REGION_ADDR( ir[i],
660 or->valid.left, or->valid.top );
661 p[i] = NULL;
662 q = (PEL *) VIPS_REGION_ADDR( or, or->valid.left, or->valid.top );
663
664 /* Convert linewise.
665 */
666 for( y = 0; y < or->valid.height; y++ ) {
667 PEL *p1[MAX_INPUT_IMAGES];
668
669 /* Make a copy of p[] which the buffer function can mess up if
670 * it wants.
671 */
672 for( i = 0; ir[i]; i++ )
673 p1[i] = p[i];
674
675 /* Bizarre double-cast stops a bogus gcc 4.1 compiler warning.
676 */
677 bun->fn( (void **) ((void *)p1), q,
678 or->valid.width, bun->a, bun->b );
679
680 /* Move pointers on.
681 */
682 for( i = 0; ir[i]; i++ )
683 p[i] += VIPS_REGION_LSKIP( ir[i] );
684 q += VIPS_REGION_LSKIP( or );
685 }
686
687 return( 0 );
688 }
689
690 /* Make a copy of an array of input images.
691 */
692 static IMAGE **
dupims(IMAGE * out,IMAGE ** in)693 dupims( IMAGE *out, IMAGE **in )
694 {
695 IMAGE **new;
696 int i, n;
697
698 for( n = 0; in[n]; n++ )
699 ;
700 new = VIPS_ARRAY( VIPS_OBJECT( out ), n + 1, IMAGE * );
701 for( i = 0; i < n; i++ )
702 new[i] = in[i];
703 new[n] = NULL;
704
705 return( new );
706 }
707
708 int
im_wrapmany(IMAGE ** in,IMAGE * out,im_wrapmany_fn fn,void * a,void * b)709 im_wrapmany( IMAGE **in, IMAGE *out, im_wrapmany_fn fn, void *a, void *b )
710 {
711 Bundle *bun;
712 int i, n;
713
714 /* Count input images.
715 */
716 for( n = 0; in[n]; n++ )
717 ;
718 if( n >= MAX_INPUT_IMAGES - 1 ) {
719 vips_error( "im_wrapmany", "%s", _( "too many input images" ) );
720 return( -1 );
721 }
722
723 /* Save args.
724 */
725 bun = VIPS_NEW( VIPS_OBJECT( out ), Bundle );
726 if( !(in = dupims( out, in )) )
727 return( -1 );
728 bun->fn = fn;
729 bun->a = a;
730 bun->b = b;
731
732 /* Check descriptors --- make sure that our caller has done this
733 * correctly.
734 */
735 for( i = 0; i < n; i++ ) {
736 if( in[i]->Xsize != out->Xsize || in[i]->Ysize != out->Ysize ) {
737 vips_error( "im_wrapmany",
738 "%s", _( "descriptors differ in size" ) );
739 return( -1 );
740 }
741
742 /* Check io style.
743 */
744 if( vips_image_pio_input( in[i] ) )
745 return( -1 );
746 }
747
748 /* Don't call vips_image_pipeline_array(), we don't want to copy
749 * fields.
750 */
751 vips__demand_hint_array( out, VIPS_DEMAND_STYLE_THINSTRIP, in );
752 if( vips__reorder_set_input( out, in ) )
753 return( -1 );
754
755 /* Generate!
756 */
757 if( vips_image_generate( out,
758 vips_start_many, (VipsGenerateFn) process_region,
759 vips_stop_many, in, bun ) )
760 return( -1 );
761
762 return( 0 );
763 }
764
765 static void
wrapone_gen(void ** ins,void * out,int width,Bundle * bun,void * dummy)766 wrapone_gen( void **ins, void *out, int width, Bundle *bun, void *dummy )
767 {
768 ((im_wrapone_fn) (bun->fn)) (ins[0], out, width, bun->a, bun->b );
769 }
770
771 int
im_wrapone(IMAGE * in,IMAGE * out,im_wrapone_fn fn,void * a,void * b)772 im_wrapone( IMAGE *in, IMAGE *out, im_wrapone_fn fn, void *a, void *b )
773 {
774 Bundle *bun;
775 IMAGE *invec[2];
776
777 /* Heh, yuk. We cast back above.
778 */
779 bun = VIPS_NEW( VIPS_OBJECT( out ), Bundle );
780 bun->fn = (im_wrapmany_fn) fn;
781 bun->a = a;
782 bun->b = b;
783 invec[0] = in; invec[1] = NULL;
784
785 return( im_wrapmany( invec, out,
786 (im_wrapmany_fn) wrapone_gen, bun, NULL ) );
787 }
788
789 static void
wraptwo_gen(void ** ins,void * out,int width,Bundle * bun,void * dummy)790 wraptwo_gen( void **ins, void *out, int width, Bundle *bun, void *dummy )
791 {
792 ((im_wraptwo_fn) (bun->fn)) (ins[0], ins[1], out,
793 width, bun->a, bun->b );
794 }
795
796 int
im_wraptwo(IMAGE * in1,IMAGE * in2,IMAGE * out,im_wraptwo_fn fn,void * a,void * b)797 im_wraptwo( IMAGE *in1, IMAGE *in2, IMAGE *out,
798 im_wraptwo_fn fn, void *a, void *b )
799 {
800 Bundle *bun;
801 IMAGE *invec[3];
802
803 bun = VIPS_NEW( VIPS_OBJECT( out ), Bundle );
804 bun->fn = (im_wrapmany_fn) fn;
805 bun->a = a;
806 bun->b = b;
807 invec[0] = in1; invec[1] = in2; invec[2] = NULL;
808
809 return( im_wrapmany( invec, out,
810 (im_wrapmany_fn) wraptwo_gen, bun, NULL ) );
811 }
812
813 /* Save a bit of typing.
814 */
815 #define UC IM_BANDFMT_UCHAR
816 #define C IM_BANDFMT_CHAR
817 #define US IM_BANDFMT_USHORT
818 #define S IM_BANDFMT_SHORT
819 #define UI IM_BANDFMT_UINT
820 #define I IM_BANDFMT_INT
821 #define F IM_BANDFMT_FLOAT
822 #define X IM_BANDFMT_COMPLEX
823 #define D IM_BANDFMT_DOUBLE
824 #define DX IM_BANDFMT_DPCOMPLEX
825
826 /* For two integer types, the "largest", ie. one which can represent the
827 * full range of both.
828 */
829 static int bandfmt_largest[6][6] = {
830 /* UC C US S UI I */
831 /* UC */ { UC, S, US, S, UI, I },
832 /* C */ { S, C, I, S, I, I },
833 /* US */ { US, I, US, I, UI, I },
834 /* S */ { S, S, I, S, I, I },
835 /* UI */ { UI, I, UI, I, UI, I },
836 /* I */ { I, I, I, I, I, I }
837 };
838
839 /* For two formats, find one which can represent the full range of both.
840 */
841 static VipsBandFmt
im__format_common(VipsBandFmt in1,VipsBandFmt in2)842 im__format_common( VipsBandFmt in1, VipsBandFmt in2 )
843 {
844 if( vips_band_format_iscomplex( in1 ) ||
845 vips_band_format_iscomplex( in2 ) ) {
846 /* What kind of complex?
847 */
848 if( in1 == IM_BANDFMT_DPCOMPLEX || in2 == IM_BANDFMT_DPCOMPLEX )
849 /* Output will be DPCOMPLEX.
850 */
851 return( IM_BANDFMT_DPCOMPLEX );
852 else
853 return( IM_BANDFMT_COMPLEX );
854
855 }
856 else if( vips_bandfmt_isfloat( in1 ) ||
857 vips_bandfmt_isfloat( in2 ) ) {
858 /* What kind of float?
859 */
860 if( in1 == IM_BANDFMT_DOUBLE || in2 == IM_BANDFMT_DOUBLE )
861 return( IM_BANDFMT_DOUBLE );
862 else
863 return( IM_BANDFMT_FLOAT );
864 }
865 else
866 /* Must be int+int -> int.
867 */
868 return( bandfmt_largest[in1][in2] );
869 }
870
871 int
im__formatalike_vec(IMAGE ** in,IMAGE ** out,int n)872 im__formatalike_vec( IMAGE **in, IMAGE **out, int n )
873 {
874 int i;
875 VipsBandFmt fmt;
876
877 g_assert( n >= 1 );
878
879 fmt = in[0]->BandFmt;
880 for( i = 1; i < n; i++ )
881 fmt = im__format_common( fmt, in[i]->BandFmt );
882
883 for( i = 0; i < n; i++ )
884 if( im_clip2fmt( in[i], out[i], fmt ) )
885 return( -1 );
886
887 return( 0 );
888 }
889
890 int
im__formatalike(IMAGE * in1,IMAGE * in2,IMAGE * out1,IMAGE * out2)891 im__formatalike( IMAGE *in1, IMAGE *in2, IMAGE *out1, IMAGE *out2 )
892 {
893 IMAGE *in[2];
894 IMAGE *out[2];
895
896 in[0] = in1;
897 in[1] = in2;
898 out[0] = out1;
899 out[1] = out2;
900
901 return( im__formatalike_vec( in, out, 2 ) );
902 }
903
904 /* Make an n-band image. Input 1 or n bands.
905 */
906 int
im__bandup(const char * domain,IMAGE * in,IMAGE * out,int n)907 im__bandup( const char *domain, IMAGE *in, IMAGE *out, int n )
908 {
909 IMAGE *bands[256];
910 int i;
911
912 if( in->Bands == n )
913 return( vips_image_write( in, out ) );
914 if( in->Bands != 1 ) {
915 im_error( domain, _( "not one band or %d bands" ), n );
916 return( -1 );
917 }
918 if( n > 256 || n < 1 ) {
919 im_error( domain, "%s", _( "bad bands" ) );
920 return( -1 );
921 }
922
923 for( i = 0; i < n; i++ )
924 bands[i] = in;
925
926 return( im_gbandjoin( bands, out, n ) );
927 }
928
929 int
im__bandalike_vec(const char * domain,IMAGE ** in,IMAGE ** out,int n)930 im__bandalike_vec( const char *domain, IMAGE **in, IMAGE **out, int n )
931 {
932 int i;
933 int max_bands;
934
935 g_assert( n >= 1 );
936
937 max_bands = in[0]->Bands;
938 for( i = 1; i < n; i++ )
939 max_bands = IM_MAX( max_bands, in[i]->Bands );
940 for( i = 0; i < n; i++ )
941 if( im__bandup( domain, in[i], out[i], max_bands ) )
942 return( -1 );
943
944 return( 0 );
945 }
946
947 int
im__bandalike(const char * domain,IMAGE * in1,IMAGE * in2,IMAGE * out1,IMAGE * out2)948 im__bandalike( const char *domain,
949 IMAGE *in1, IMAGE *in2, IMAGE *out1, IMAGE *out2 )
950 {
951 IMAGE *in[2];
952 IMAGE *out[2];
953
954 in[0] = in1;
955 in[1] = in2;
956 out[0] = out1;
957 out[1] = out2;
958 if( im__bandalike_vec( domain, in, out, 2 ) )
959 return( -1 );
960
961 return( 0 );
962 }
963
964 VipsVector *
im__init_program(VipsVector * vectors[IM_BANDFMT_LAST],VipsBandFmt format_table[IM_BANDFMT_LAST],VipsBandFmt fmt)965 im__init_program( VipsVector *vectors[IM_BANDFMT_LAST],
966 VipsBandFmt format_table[IM_BANDFMT_LAST], VipsBandFmt fmt )
967 {
968 int isize = im__sizeof_bandfmt[fmt];
969 int osize = im__sizeof_bandfmt[format_table[fmt]];
970
971 VipsVector *v;
972
973 v = vips_vector_new( "binary arith", osize );
974
975 vips_vector_source_name( v, "s1", isize );
976 vips_vector_source_name( v, "s2", isize );
977 vips_vector_temporary( v, "t1", osize );
978 vips_vector_temporary( v, "t2", osize );
979
980 vectors[fmt] = v;
981
982 return( v );
983 }
984
985 void
im__compile_programs(VipsVector * vectors[IM_BANDFMT_LAST])986 im__compile_programs( VipsVector *vectors[IM_BANDFMT_LAST] )
987 {
988 int fmt;
989
990 for( fmt = 0; fmt < IM_BANDFMT_LAST; fmt++ ) {
991 if( vectors[fmt] &&
992 !vips_vector_compile( vectors[fmt] ) )
993 IM_FREEF( vips_vector_free, vectors[fmt] );
994 }
995
996 #ifdef DEBUG
997 printf( "im__compile_programs: " );
998 for( fmt = 0; fmt < IM_BANDFMT_LAST; fmt++ )
999 if( vectors[fmt] )
1000 printf( "%s ", im_BandFmt2char( fmt ) );
1001 printf( "\n" );
1002 #endif /*DEBUG*/
1003 }
1004
1005 int
im_add(IMAGE * in1,IMAGE * in2,IMAGE * out)1006 im_add( IMAGE *in1, IMAGE *in2, IMAGE *out )
1007 {
1008 VipsImage *x;
1009
1010 if( vips_call( "add", in1, in2, &x, NULL ) )
1011 return( -1 );
1012 if( vips_image_write( x, out ) ) {
1013 g_object_unref( x );
1014 return( -1 );
1015 }
1016 g_object_unref( x );
1017
1018 return( 0 );
1019 }
1020
1021 int
im_subtract(IMAGE * in1,IMAGE * in2,IMAGE * out)1022 im_subtract( IMAGE *in1, IMAGE *in2, IMAGE *out )
1023 {
1024 VipsImage *x;
1025
1026 if( vips_call( "subtract", in1, in2, &x, NULL ) )
1027 return( -1 );
1028 if( vips_image_write( x, out ) ) {
1029 g_object_unref( x );
1030 return( -1 );
1031 }
1032 g_object_unref( x );
1033
1034 return( 0 );
1035 }
1036
1037 int
im_multiply(IMAGE * in1,IMAGE * in2,IMAGE * out)1038 im_multiply( IMAGE *in1, IMAGE *in2, IMAGE *out )
1039 {
1040 VipsImage *x;
1041
1042 if( vips_call( "multiply", in1, in2, &x, NULL ) )
1043 return( -1 );
1044 if( vips_image_write( x, out ) ) {
1045 g_object_unref( x );
1046 return( -1 );
1047 }
1048 g_object_unref( x );
1049
1050 return( 0 );
1051 }
1052
1053 int
im_divide(IMAGE * in1,IMAGE * in2,IMAGE * out)1054 im_divide( IMAGE *in1, IMAGE *in2, IMAGE *out )
1055 {
1056 VipsImage *x;
1057
1058 if( vips_call( "divide", in1, in2, &x, NULL ) )
1059 return( -1 );
1060 if( vips_image_write( x, out ) ) {
1061 g_object_unref( x );
1062 return( -1 );
1063 }
1064 g_object_unref( x );
1065
1066 return( 0 );
1067 }
1068
1069 int
im_avg(IMAGE * in,double * out)1070 im_avg( IMAGE *in, double *out )
1071 {
1072 return( vips_avg( in, out, NULL ) );
1073 }
1074
1075 int
im_deviate(IMAGE * in,double * out)1076 im_deviate( IMAGE *in, double *out )
1077 {
1078 return( vips_deviate( in, out, NULL ) );
1079 }
1080
im_generate(VipsImage * im,im_start_fn start,im_generate_fn generate,im_stop_fn stop,void * a,void * b)1081 int im_generate( VipsImage *im,
1082 im_start_fn start, im_generate_fn generate, im_stop_fn stop,
1083 void *a, void *b )
1084 {
1085 return( vips_image_generate( im,
1086 start, (VipsGenerateFn) generate, stop, a, b ) );
1087 }
1088
1089 int
im_minpos(IMAGE * in,int * xpos,int * ypos,double * out)1090 im_minpos( IMAGE *in, int *xpos, int *ypos, double *out )
1091 {
1092 return( vips_min( in, out, "x", xpos, "y", ypos, NULL ) );
1093 }
1094
1095 int
im_min(IMAGE * in,double * out)1096 im_min( IMAGE *in, double *out )
1097 {
1098 return( im_minpos( in, NULL, NULL, out ) );
1099 }
1100
1101 int
im_maxpos(IMAGE * in,int * xpos,int * ypos,double * out)1102 im_maxpos( IMAGE *in, int *xpos, int *ypos, double *out )
1103 {
1104 return( vips_max( in, out, "x", xpos, "y", ypos, NULL ) );
1105 }
1106
1107 int
im_max(IMAGE * in,double * out)1108 im_max( IMAGE *in, double *out )
1109 {
1110 return( im_maxpos( in, NULL, NULL, out ) );
1111 }
1112
1113 #define MAX_IMAGES 100
1114 int
im_demand_hint(IMAGE * im,VipsDemandStyle hint,...)1115 im_demand_hint (IMAGE * im, VipsDemandStyle hint, ...)
1116 {
1117 va_list ap;
1118 int i;
1119 IMAGE *ar[MAX_IMAGES];
1120
1121 va_start (ap, hint);
1122 for (i = 0; i < MAX_IMAGES && (ar[i] = va_arg (ap, IMAGE *)); i++)
1123 ;
1124 va_end (ap);
1125 if (i == MAX_IMAGES)
1126 {
1127 im_error ("im_demand_hint", "%s", _("too many images"));
1128 return (-1);
1129 }
1130
1131 vips__demand_hint_array (im, hint, ar);
1132
1133 return (0);
1134 }
1135
1136 int
im_cp_descv(IMAGE * im,...)1137 im_cp_descv (IMAGE * im, ...)
1138 {
1139 va_list ap;
1140 int i;
1141 IMAGE *ar[MAX_IMAGES];
1142
1143 va_start (ap, im);
1144 for (i = 0; i < MAX_IMAGES && (ar[i] = va_arg (ap, IMAGE *)); i++)
1145 ;
1146 va_end (ap);
1147 if (i == MAX_IMAGES)
1148 {
1149 im_error ("im_cp_descv", "%s", _("too many images"));
1150 return (-1);
1151 }
1152
1153 return (vips__image_copy_fields_array (im, ar));
1154 }
1155
1156 int
im_cp_desc(IMAGE * out,IMAGE * in)1157 im_cp_desc(IMAGE *out, IMAGE *in )
1158 {
1159 return( im_cp_descv( out, in, NULL));
1160 }
1161
1162 int
im_copy_set(IMAGE * in,IMAGE * out,VipsType type,float xres,float yres,int xoffset,int yoffset)1163 im_copy_set( IMAGE *in, IMAGE *out,
1164 VipsType type, float xres, float yres, int xoffset, int yoffset )
1165 {
1166 VipsImage *x;
1167
1168 if( vips_copy( in, &x,
1169 "interpretation", type,
1170 "xres", xres,
1171 "yres", yres,
1172 "xoffset", xoffset,
1173 "yoffset", yoffset,
1174 NULL ) )
1175 return( -1 );
1176 if( vips_image_write( x, out ) ) {
1177 g_object_unref( x );
1178 return( -1 );
1179 }
1180 g_object_unref( x );
1181
1182 return( 0 );
1183 }
1184
1185 int
im_copy_morph(IMAGE * in,IMAGE * out,int bands,VipsBandFmt bandfmt,VipsCoding coding)1186 im_copy_morph( IMAGE *in, IMAGE *out,
1187 int bands, VipsBandFmt bandfmt, VipsCoding coding )
1188 {
1189 VipsImage *x;
1190
1191 if( vips_copy( in, &x,
1192 "bands", bands,
1193 "format", bandfmt,
1194 "coding", coding,
1195 NULL ) )
1196 return( -1 );
1197 if( vips_image_write( x, out ) ) {
1198 g_object_unref( x );
1199 return( -1 );
1200 }
1201 g_object_unref( x );
1202
1203 return( 0 );
1204 }
1205
1206 int
im_copy(IMAGE * in,IMAGE * out)1207 im_copy( IMAGE *in, IMAGE *out )
1208 {
1209 return( vips_image_write( in, out ) );
1210 }
1211
1212 int
im_copy_swap(IMAGE * in,IMAGE * out)1213 im_copy_swap( IMAGE *in, IMAGE *out )
1214 {
1215 VipsImage *x;
1216
1217 if( vips_byteswap( in, &x, NULL ) )
1218 return( -1 );
1219 if( vips_image_write( x, out ) ) {
1220 g_object_unref( x );
1221 return( -1 );
1222 }
1223 g_object_unref( x );
1224
1225 return( 0 );
1226 }
1227
1228 int
im_copy_set_meta(IMAGE * in,IMAGE * out,const char * field,GValue * value)1229 im_copy_set_meta( IMAGE *in, IMAGE *out, const char *field, GValue *value )
1230 {
1231 if( vips_image_write( in, out ) )
1232 return( -1 );
1233 (void) im_meta_set( out, field, value );
1234
1235 return( 0 );
1236 }
1237
1238 int
im_copy_native(IMAGE * in,IMAGE * out,gboolean is_msb_first)1239 im_copy_native( IMAGE *in, IMAGE *out, gboolean is_msb_first )
1240 {
1241 if( is_msb_first != im_amiMSBfirst() )
1242 return( im_copy_swap( in, out ) );
1243 else
1244 return( vips_image_write( in, out ) );
1245 }
1246
1247 int
im_embed(IMAGE * in,IMAGE * out,int type,int x,int y,int width,int height)1248 im_embed( IMAGE *in, IMAGE *out, int type, int x, int y, int width, int height )
1249 {
1250 VipsImage *t;
1251
1252 if( vips_embed( in, &t, x, y, width, height,
1253 "extend", type,
1254 NULL ) )
1255 return( -1 );
1256 if( vips_image_write( t, out ) ) {
1257 g_object_unref( t );
1258 return( -1 );
1259 }
1260 g_object_unref( t );
1261
1262 return( 0 );
1263 }
1264
1265 int
im_fliphor(IMAGE * in,IMAGE * out)1266 im_fliphor( IMAGE *in, IMAGE *out )
1267 {
1268 VipsImage *t;
1269
1270 if( vips_flip( in, &t, VIPS_DIRECTION_HORIZONTAL, NULL ) )
1271 return( -1 );
1272 if( vips_image_write( t, out ) ) {
1273 g_object_unref( t );
1274 return( -1 );
1275 }
1276 g_object_unref( t );
1277
1278 return( 0 );
1279 }
1280
1281 int
im_rot90(IMAGE * in,IMAGE * out)1282 im_rot90( IMAGE *in, IMAGE *out )
1283 {
1284 VipsImage *t;
1285
1286 if( vips_rot( in, &t, VIPS_ANGLE_D90, NULL ) )
1287 return( -1 );
1288 if( vips_image_write( t, out ) ) {
1289 g_object_unref( t );
1290 return( -1 );
1291 }
1292 g_object_unref( t );
1293
1294 return( 0 );
1295 }
1296
1297 int
im_rot180(IMAGE * in,IMAGE * out)1298 im_rot180( IMAGE *in, IMAGE *out )
1299 {
1300 VipsImage *t;
1301
1302 if( vips_rot( in, &t, VIPS_ANGLE_D180, NULL ) )
1303 return( -1 );
1304 if( vips_image_write( t, out ) ) {
1305 g_object_unref( t );
1306 return( -1 );
1307 }
1308 g_object_unref( t );
1309
1310 return( 0 );
1311 }
1312
1313 int
im_rot270(IMAGE * in,IMAGE * out)1314 im_rot270( IMAGE *in, IMAGE *out )
1315 {
1316 VipsImage *t;
1317
1318 if( vips_rot( in, &t, VIPS_ANGLE_D270, NULL ) )
1319 return( -1 );
1320 if( vips_image_write( t, out ) ) {
1321 g_object_unref( t );
1322 return( -1 );
1323 }
1324 g_object_unref( t );
1325
1326 return( 0 );
1327 }
1328
1329 int
im_flipver(IMAGE * in,IMAGE * out)1330 im_flipver( IMAGE *in, IMAGE *out )
1331 {
1332 VipsImage *t;
1333
1334 if( vips_flip( in, &t, VIPS_DIRECTION_VERTICAL, NULL ) )
1335 return( -1 );
1336 if( vips_image_write( t, out ) ) {
1337 g_object_unref( t );
1338 return( -1 );
1339 }
1340 g_object_unref( t );
1341
1342 return( 0 );
1343 }
1344
1345 int
im_insert(IMAGE * main,IMAGE * sub,IMAGE * out,int x,int y)1346 im_insert( IMAGE *main, IMAGE *sub, IMAGE *out, int x, int y )
1347 {
1348 VipsImage *t;
1349
1350 if( vips_insert( main, sub, &t, x, y,
1351 "expand", TRUE,
1352 NULL ) )
1353 return( -1 );
1354 if( vips_image_write( t, out ) ) {
1355 g_object_unref( t );
1356 return( -1 );
1357 }
1358 g_object_unref( t );
1359
1360 return( 0 );
1361 }
1362
1363 int
im_insert_noexpand(IMAGE * main,IMAGE * sub,IMAGE * out,int x,int y)1364 im_insert_noexpand( IMAGE *main, IMAGE *sub, IMAGE *out, int x, int y )
1365 {
1366 VipsImage *t;
1367
1368 if( vips_insert( main, sub, &t, x, y, NULL ) )
1369 return( -1 );
1370 if( vips_image_write( t, out ) ) {
1371 g_object_unref( t );
1372 return( -1 );
1373 }
1374 g_object_unref( t );
1375
1376 return( 0 );
1377 }
1378
1379 int
im_lrjoin(IMAGE * left,IMAGE * right,IMAGE * out)1380 im_lrjoin( IMAGE *left, IMAGE *right, IMAGE *out )
1381 {
1382 VipsImage *t;
1383
1384 if( vips_join( left, right, &t, VIPS_DIRECTION_HORIZONTAL,
1385 NULL ) )
1386 return( -1 );
1387 if( vips_image_write( t, out ) ) {
1388 g_object_unref( t );
1389 return( -1 );
1390 }
1391 g_object_unref( t );
1392
1393 return( 0 );
1394 }
1395
1396 int
im_tbjoin(IMAGE * left,IMAGE * right,IMAGE * out)1397 im_tbjoin( IMAGE *left, IMAGE *right, IMAGE *out )
1398 {
1399 VipsImage *t;
1400
1401 if( vips_join( left, right, &t, VIPS_DIRECTION_VERTICAL,
1402 NULL ) )
1403 return( -1 );
1404 if( vips_image_write( t, out ) ) {
1405 g_object_unref( t );
1406 return( -1 );
1407 }
1408 g_object_unref( t );
1409
1410 return( 0 );
1411 }
1412
1413 int
im_extract_area(IMAGE * in,IMAGE * out,int left,int top,int width,int height)1414 im_extract_area( IMAGE *in, IMAGE *out,
1415 int left, int top, int width, int height )
1416 {
1417 VipsImage *t;
1418
1419 if( vips_extract_area( in, &t, left, top, width, height,
1420 NULL ) )
1421 return( -1 );
1422 if( vips_image_write( t, out ) ) {
1423 g_object_unref( t );
1424 return( -1 );
1425 }
1426 g_object_unref( t );
1427
1428 return( 0 );
1429 }
1430
1431 int
im_extract_bands(IMAGE * in,IMAGE * out,int band,int nbands)1432 im_extract_bands( IMAGE *in, IMAGE *out, int band, int nbands )
1433 {
1434 VipsImage *t;
1435
1436 if( vips_extract_band( in, &t, band,
1437 "n", nbands,
1438 NULL ) )
1439 return( -1 );
1440 if( vips_image_write( t, out ) ) {
1441 g_object_unref( t );
1442 return( -1 );
1443 }
1444 g_object_unref( t );
1445
1446 return( 0 );
1447 }
1448
1449 int
im_extract_band(IMAGE * in,IMAGE * out,int band)1450 im_extract_band( IMAGE *in, IMAGE *out, int band )
1451 {
1452 return( im_extract_bands( in, out, band, 1 ) );
1453 }
1454
1455 int
im_extract_areabands(IMAGE * in,IMAGE * out,int left,int top,int width,int height,int band,int nbands)1456 im_extract_areabands( IMAGE *in, IMAGE *out,
1457 int left, int top, int width, int height, int band, int nbands )
1458 {
1459 VipsImage *t1, *t2;
1460
1461 if( vips_extract_area( in, &t1, left, top, width, height,
1462 NULL ) )
1463 return( -1 );
1464
1465 if( vips_extract_band( t1, &t2, band,
1466 "n", nbands,
1467 NULL ) ) {
1468 g_object_unref( t1 );
1469 return( -1 );
1470 }
1471 g_object_unref( t1 );
1472
1473 if( vips_image_write( t2, out ) ) {
1474 g_object_unref( t2 );
1475 return( -1 );
1476 }
1477 g_object_unref( t2 );
1478
1479 return( 0 );
1480 }
1481
1482 int
im_replicate(IMAGE * in,IMAGE * out,int across,int down)1483 im_replicate( IMAGE *in, IMAGE *out, int across, int down )
1484 {
1485 VipsImage *t;
1486
1487 if( vips_replicate( in, &t, across, down,
1488 NULL ) )
1489 return( -1 );
1490 if( vips_image_write( t, out ) ) {
1491 g_object_unref( t );
1492 return( -1 );
1493 }
1494 g_object_unref( t );
1495
1496 return( 0 );
1497 }
1498
1499 int
im_clip2fmt(IMAGE * in,IMAGE * out,VipsBandFmt fmt)1500 im_clip2fmt( IMAGE *in, IMAGE *out, VipsBandFmt fmt )
1501 {
1502 VipsImage *t;
1503
1504 if( vips_cast( in, &t, fmt,
1505 NULL ) )
1506 return( -1 );
1507 if( vips_image_write( t, out ) ) {
1508 g_object_unref( t );
1509 return( -1 );
1510 }
1511 g_object_unref( t );
1512
1513 return( 0 );
1514 }
1515
1516 size_t
im_ref_string_get_length(const GValue * value)1517 im_ref_string_get_length( const GValue *value )
1518 {
1519 size_t length;
1520
1521 (void) vips_value_get_ref_string( value, &length );
1522
1523 return( length );
1524 }
1525
1526 int
im_bandjoin(VipsImage * in1,VipsImage * in2,VipsImage * out)1527 im_bandjoin( VipsImage *in1, VipsImage *in2, VipsImage *out )
1528 {
1529 VipsImage *t;
1530
1531 if( vips_bandjoin2( in1, in2, &t,
1532 NULL ) )
1533 return( -1 );
1534 if( vips_image_write( t, out ) ) {
1535 g_object_unref( t );
1536 return( -1 );
1537 }
1538 g_object_unref( t );
1539
1540 return( 0 );
1541 }
1542
1543 int
im_gbandjoin(VipsImage ** in,VipsImage * out,int n)1544 im_gbandjoin( VipsImage **in, VipsImage *out, int n )
1545 {
1546 VipsImage *t;
1547
1548 if( vips_bandjoin( in, &t, n,
1549 NULL ) )
1550 return( -1 );
1551 if( vips_image_write( t, out ) ) {
1552 g_object_unref( t );
1553 return( -1 );
1554 }
1555 g_object_unref( t );
1556
1557 return( 0 );
1558 }
1559
1560 int
im_rank_image(VipsImage ** in,VipsImage * out,int n,int index)1561 im_rank_image( VipsImage **in, VipsImage *out, int n, int index )
1562 {
1563 VipsImage *t;
1564
1565 if( vips_bandrank( in, &t, n,
1566 "index", index,
1567 NULL ) )
1568 return( -1 );
1569 if( vips_image_write( t, out ) ) {
1570 g_object_unref( t );
1571 return( -1 );
1572 }
1573 g_object_unref( t );
1574
1575 return( 0 );
1576 }
1577
1578 int
im_maxvalue(IMAGE ** in,IMAGE * out,int n)1579 im_maxvalue( IMAGE **in, IMAGE *out, int n )
1580 {
1581 return( im_rank_image( in, out, n, n - 1 ) );
1582 }
1583
1584 int
im_invert(IMAGE * in,IMAGE * out)1585 im_invert( IMAGE *in, IMAGE *out )
1586 {
1587 VipsImage *t;
1588
1589 if( vips_invert( in, &t,
1590 NULL ) )
1591 return( -1 );
1592 if( vips_image_write( t, out ) ) {
1593 g_object_unref( t );
1594 return( -1 );
1595 }
1596 g_object_unref( t );
1597
1598 return( 0 );
1599 }
1600
1601 int
im_sign(IMAGE * in,IMAGE * out)1602 im_sign( IMAGE *in, IMAGE *out )
1603 {
1604 VipsImage *t;
1605
1606 if( vips_sign( in, &t,
1607 NULL ) )
1608 return( -1 );
1609 if( vips_image_write( t, out ) ) {
1610 g_object_unref( t );
1611 return( -1 );
1612 }
1613 g_object_unref( t );
1614
1615 return( 0 );
1616 }
1617
1618 int
im_abs(IMAGE * in,IMAGE * out)1619 im_abs( IMAGE *in, IMAGE *out )
1620 {
1621 VipsImage *t;
1622
1623 if( vips_abs( in, &t,
1624 NULL ) )
1625 return( -1 );
1626 if( vips_image_write( t, out ) ) {
1627 g_object_unref( t );
1628 return( -1 );
1629 }
1630 g_object_unref( t );
1631
1632 return( 0 );
1633 }
1634
1635 int
im_bandmean(IMAGE * in,IMAGE * out)1636 im_bandmean( IMAGE *in, IMAGE *out )
1637 {
1638 VipsImage *t;
1639
1640 if( vips_bandmean( in, &t,
1641 NULL ) )
1642 return( -1 );
1643 if( vips_image_write( t, out ) ) {
1644 g_object_unref( t );
1645 return( -1 );
1646 }
1647 g_object_unref( t );
1648
1649 return( 0 );
1650 }
1651
1652 int
im_lintra(double a,IMAGE * in,double b,IMAGE * out)1653 im_lintra( double a, IMAGE *in, double b, IMAGE *out )
1654 {
1655 VipsImage *t;
1656
1657 if( vips_linear1( in, &t, a, b,
1658 NULL ) )
1659 return( -1 );
1660 if( vips_image_write( t, out ) ) {
1661 g_object_unref( t );
1662 return( -1 );
1663 }
1664 g_object_unref( t );
1665
1666 return( 0 );
1667 }
1668
1669 int
im_lintra_vec(int n,double * a,IMAGE * in,double * b,IMAGE * out)1670 im_lintra_vec( int n, double *a, IMAGE *in, double *b, IMAGE *out )
1671 {
1672 VipsImage *t;
1673
1674 if( vips_linear( in, &t, a, b, n,
1675 NULL ) )
1676 return( -1 );
1677 if( vips_image_write( t, out ) ) {
1678 g_object_unref( t );
1679 return( -1 );
1680 }
1681 g_object_unref( t );
1682
1683 return( 0 );
1684 }
1685
1686 int
im_black(IMAGE * out,int x,int y,int bands)1687 im_black( IMAGE *out, int x, int y, int bands )
1688 {
1689 VipsImage *t;
1690
1691 if( vips_black( &t, x, y,
1692 "bands", bands,
1693 NULL ) )
1694 return( -1 );
1695 if( vips_image_write( t, out ) ) {
1696 g_object_unref( t );
1697 return( -1 );
1698 }
1699 g_object_unref( t );
1700
1701 return( 0 );
1702 }
1703
1704 int
im_identity_ushort(VipsImage * lut,int bands,int sz)1705 im_identity_ushort( VipsImage *lut, int bands, int sz )
1706 {
1707 VipsImage *t;
1708
1709 if( vips_identity( &t,
1710 "bands", bands,
1711 "ushort", TRUE,
1712 "size", sz,
1713 NULL ) )
1714 return( -1 );
1715 if( vips_image_write( t, lut ) ) {
1716 g_object_unref( t );
1717 return( -1 );
1718 }
1719 g_object_unref( t );
1720
1721 return( 0 );
1722 }
1723
1724 int
im_identity(VipsImage * lut,int bands)1725 im_identity( VipsImage *lut, int bands )
1726 {
1727 VipsImage *t;
1728
1729 if( vips_identity( &t,
1730 "bands", bands,
1731 NULL ) )
1732 return( -1 );
1733 if( vips_image_write( t, lut ) ) {
1734 g_object_unref( t );
1735 return( -1 );
1736 }
1737 g_object_unref( t );
1738
1739 return( 0 );
1740 }
1741
1742 int
im_gaussnoise(VipsImage * out,int x,int y,double mean,double sigma)1743 im_gaussnoise( VipsImage *out, int x, int y, double mean, double sigma )
1744 {
1745 VipsImage *t;
1746
1747 if( vips_gaussnoise( &t, x, y,
1748 "mean", mean,
1749 "sigma", sigma,
1750 NULL ) )
1751 return( -1 );
1752 if( vips_image_write( t, out ) ) {
1753 g_object_unref( t );
1754 return( -1 );
1755 }
1756 g_object_unref( t );
1757
1758 return( 0 );
1759 }
1760
1761 int
im_grid(VipsImage * in,VipsImage * out,int tile_height,int across,int down)1762 im_grid( VipsImage *in, VipsImage *out, int tile_height, int across, int down )
1763 {
1764 VipsImage *t;
1765
1766 if( vips_grid( in, &t, tile_height, across, down, NULL ) )
1767 return( -1 );
1768 if( vips_image_write( t, out ) ) {
1769 g_object_unref( t );
1770 return( -1 );
1771 }
1772 g_object_unref( t );
1773
1774 return( 0 );
1775 }
1776
1777 int
im_scale(VipsImage * in,VipsImage * out)1778 im_scale( VipsImage *in, VipsImage *out )
1779 {
1780 VipsImage *t;
1781
1782 if( vips_scale( in, &t, NULL ) )
1783 return( -1 );
1784 if( vips_image_write( t, out ) ) {
1785 g_object_unref( t );
1786 return( -1 );
1787 }
1788 g_object_unref( t );
1789
1790 return( 0 );
1791 }
1792
1793 int
im_msb(VipsImage * in,VipsImage * out)1794 im_msb( VipsImage *in, VipsImage *out )
1795 {
1796 VipsImage *t;
1797
1798 if( vips_msb( in, &t, NULL ) )
1799 return( -1 );
1800 if( vips_image_write( t, out ) ) {
1801 g_object_unref( t );
1802 return( -1 );
1803 }
1804 g_object_unref( t );
1805
1806 return( 0 );
1807 }
1808
1809 int
im_msb_band(VipsImage * in,VipsImage * out,int band)1810 im_msb_band( VipsImage *in, VipsImage *out, int band )
1811 {
1812 VipsImage *t;
1813
1814 if( vips_msb( in, &t, "band", band, NULL ) )
1815 return( -1 );
1816 if( vips_image_write( t, out ) ) {
1817 g_object_unref( t );
1818 return( -1 );
1819 }
1820 g_object_unref( t );
1821
1822 return( 0 );
1823 }
1824
1825 int
im_make_xy(IMAGE * out,const int xsize,const int ysize)1826 im_make_xy( IMAGE *out, const int xsize, const int ysize )
1827 {
1828 VipsImage *t;
1829
1830 if( vips_xyz( &t, xsize, ysize, NULL ) )
1831 return( -1 );
1832 if( vips_image_write( t, out ) ) {
1833 g_object_unref( t );
1834 return( -1 );
1835 }
1836 g_object_unref( t );
1837
1838 return( 0 );
1839 }
1840
1841 int
im_zone(IMAGE * out,int size)1842 im_zone( IMAGE *out, int size )
1843 {
1844 VipsImage *t;
1845
1846 if( vips_zone( &t, size, size,
1847 "uchar", TRUE,
1848 NULL ) )
1849 return( -1 );
1850 if( vips_image_write( t, out ) ) {
1851 g_object_unref( t );
1852 return( -1 );
1853 }
1854 g_object_unref( t );
1855
1856 return( 0 );
1857 }
1858
1859 int
im_fzone(IMAGE * out,int size)1860 im_fzone( IMAGE *out, int size )
1861 {
1862 VipsImage *t;
1863
1864 if( vips_zone( &t, size, size, NULL ) )
1865 return( -1 );
1866 if( vips_image_write( t, out ) ) {
1867 g_object_unref( t );
1868 return( -1 );
1869 }
1870 g_object_unref( t );
1871
1872 return( 0 );
1873 }
1874
1875 int
im_sines(IMAGE * out,int xsize,int ysize,double horfreq,double verfreq)1876 im_sines( IMAGE *out, int xsize, int ysize, double horfreq, double verfreq )
1877 {
1878 VipsImage *t;
1879
1880 if( vips_sines( &t, xsize, ysize,
1881 "hfreq", horfreq,
1882 "vfreq", verfreq,
1883 NULL ) )
1884 return( -1 );
1885 if( vips_image_write( t, out ) ) {
1886 g_object_unref( t );
1887 return( -1 );
1888 }
1889 g_object_unref( t );
1890
1891 return( 0 );
1892 }
1893
1894 int
im_text(IMAGE * out,const char * text,const char * font,int width,int align,int dpi)1895 im_text( IMAGE *out, const char *text, const char *font,
1896 int width, int align, int dpi )
1897 {
1898 VipsImage *t;
1899
1900 if( vips_text( &t, text,
1901 "font", font,
1902 "width", width,
1903 "align", align,
1904 "dpi", dpi,
1905 NULL ) )
1906 return( -1 );
1907 if( vips_image_write( t, out ) ) {
1908 g_object_unref( t );
1909 return( -1 );
1910 }
1911 g_object_unref( t );
1912
1913 return( 0 );
1914 }
1915
1916 int
im_system(VipsImage * im,const char * cmd,char ** out)1917 im_system( VipsImage *im, const char *cmd, char **out )
1918 {
1919 VipsArea *area;
1920 VipsImage **array;
1921 char *str;
1922
1923 area = vips_area_new_array_object( 1 );
1924 array = (VipsImage **) area->data;
1925 array[0] = im;
1926
1927 if( vips_system( cmd,
1928 "in", area,
1929 "in_format", "%s.v",
1930 "log", &str,
1931 NULL ) ) {
1932 vips_area_unref( area );
1933 return( -1 );
1934 }
1935
1936 vips_area_unref( area );
1937
1938 if( out )
1939 *out = str;
1940
1941 return( 0 );
1942 }
1943
1944 VipsImage *
im_system_image(VipsImage * im,const char * in_format,const char * out_format,const char * cmd_format,char ** log)1945 im_system_image( VipsImage *im,
1946 const char *in_format, const char *out_format, const char *cmd_format,
1947 char **log )
1948 {
1949 VipsArrayImage *array;
1950 char *str;
1951 VipsImage *out;
1952
1953 array = vips_array_image_newv( 1, im );
1954
1955 /* im will be unreffed when area is unreffed.
1956 */
1957 g_object_ref( im );
1958
1959 if( vips_system( cmd_format,
1960 "in", array,
1961 "out", &out,
1962 "in_format", in_format,
1963 "out_format", out_format,
1964 "log", &str,
1965 NULL ) ) {
1966 vips_area_unref( VIPS_AREA( array ) );
1967 return( NULL );
1968 }
1969
1970 vips_area_unref( VIPS_AREA( array ) );
1971
1972 if( log )
1973 *log = str;
1974 else
1975 g_free( str );
1976
1977 return( out );
1978 }
1979
1980 int
im_wrap(IMAGE * in,IMAGE * out,int x,int y)1981 im_wrap( IMAGE *in, IMAGE *out, int x, int y )
1982 {
1983 VipsImage *t;
1984
1985 if( vips_wrap( in, &t, "x", x, "y", y, NULL ) )
1986 return( -1 );
1987 if( vips_image_write( t, out ) ) {
1988 g_object_unref( t );
1989 return( -1 );
1990 }
1991 g_object_unref( t );
1992
1993 return( 0 );
1994 }
1995
1996 int
im_rotquad(IMAGE * in,IMAGE * out)1997 im_rotquad( IMAGE *in, IMAGE *out )
1998 {
1999 return( im_wrap( in, out, in->Xsize / 2, in->Ysize / 2 ) );
2000 }
2001
2002 int
im_scaleps(VipsImage * in,VipsImage * out)2003 im_scaleps( VipsImage *in, VipsImage *out )
2004 {
2005 VipsImage *t;
2006
2007 if( vips_scale( in, &t, "log", TRUE, NULL ) )
2008 return( -1 );
2009 if( vips_image_write( t, out ) ) {
2010 g_object_unref( t );
2011 return( -1 );
2012 }
2013 g_object_unref( t );
2014
2015 return( 0 );
2016 }
2017
2018 int
im_zoom(VipsImage * in,VipsImage * out,int xfac,int yfac)2019 im_zoom( VipsImage *in, VipsImage *out, int xfac, int yfac )
2020 {
2021 VipsImage *t;
2022
2023 if( vips_zoom( in, &t, xfac, yfac, NULL ) )
2024 return( -1 );
2025 if( vips_image_write( t, out ) ) {
2026 g_object_unref( t );
2027 return( -1 );
2028 }
2029 g_object_unref( t );
2030
2031 return( 0 );
2032 }
2033
2034 int
im_subsample(VipsImage * in,VipsImage * out,int xfac,int yfac)2035 im_subsample( VipsImage *in, VipsImage *out, int xfac, int yfac )
2036 {
2037 VipsImage *t;
2038
2039 if( vips_subsample( in, &t, xfac, yfac, NULL ) )
2040 return( -1 );
2041 if( vips_image_write( t, out ) ) {
2042 g_object_unref( t );
2043 return( -1 );
2044 }
2045 g_object_unref( t );
2046
2047 return( 0 );
2048 }
2049
2050 static int
vips__math(VipsImage * in,VipsImage * out,VipsOperationMath math)2051 vips__math( VipsImage *in, VipsImage *out, VipsOperationMath math )
2052 {
2053 VipsImage *t;
2054
2055 if( vips_math( in, &t, math,
2056 NULL ) )
2057 return( -1 );
2058 if( vips_image_write( t, out ) ) {
2059 g_object_unref( t );
2060 return( -1 );
2061 }
2062 g_object_unref( t );
2063
2064 return( 0 );
2065 }
2066
2067 int
im_sintra(IMAGE * in,IMAGE * out)2068 im_sintra( IMAGE *in, IMAGE *out )
2069 {
2070 return( vips__math( in, out, VIPS_OPERATION_MATH_SIN ) );
2071 }
2072
2073 int
im_costra(IMAGE * in,IMAGE * out)2074 im_costra( IMAGE *in, IMAGE *out )
2075 {
2076 return( vips__math( in, out, VIPS_OPERATION_MATH_COS ) );
2077 }
2078
2079 int
im_tantra(IMAGE * in,IMAGE * out)2080 im_tantra( IMAGE *in, IMAGE *out )
2081 {
2082 return( vips__math( in, out, VIPS_OPERATION_MATH_TAN ) );
2083 }
2084
2085 int
im_asintra(IMAGE * in,IMAGE * out)2086 im_asintra( IMAGE *in, IMAGE *out )
2087 {
2088 return( vips__math( in, out, VIPS_OPERATION_MATH_ASIN ) );
2089 }
2090
2091 int
im_acostra(IMAGE * in,IMAGE * out)2092 im_acostra( IMAGE *in, IMAGE *out )
2093 {
2094 return( vips__math( in, out, VIPS_OPERATION_MATH_ACOS ) );
2095 }
2096
2097 int
im_atantra(IMAGE * in,IMAGE * out)2098 im_atantra( IMAGE *in, IMAGE *out )
2099 {
2100 return( vips__math( in, out, VIPS_OPERATION_MATH_ATAN ) );
2101 }
2102
2103 int
im_logtra(IMAGE * in,IMAGE * out)2104 im_logtra( IMAGE *in, IMAGE *out )
2105 {
2106 return( vips__math( in, out, VIPS_OPERATION_MATH_LOG ) );
2107 }
2108
2109 int
im_log10tra(IMAGE * in,IMAGE * out)2110 im_log10tra( IMAGE *in, IMAGE *out )
2111 {
2112 return( vips__math( in, out, VIPS_OPERATION_MATH_LOG10 ) );
2113 }
2114
2115 int
im_exptra(IMAGE * in,IMAGE * out)2116 im_exptra( IMAGE *in, IMAGE *out )
2117 {
2118 return( vips__math( in, out, VIPS_OPERATION_MATH_EXP ) );
2119 }
2120
2121 int
im_exp10tra(IMAGE * in,IMAGE * out)2122 im_exp10tra( IMAGE *in, IMAGE *out )
2123 {
2124 return( vips__math( in, out, VIPS_OPERATION_MATH_EXP10 ) );
2125 }
2126
2127 DOUBLEMASK *
im_stats(VipsImage * in)2128 im_stats( VipsImage *in )
2129 {
2130 VipsImage *t;
2131 DOUBLEMASK *msk;
2132
2133 if( vips_stats( in, &t,
2134 NULL ) )
2135 return( NULL );
2136 if( !(msk = im_vips2mask( t, "im_stats" )) ) {
2137 g_object_unref( t );
2138 return( NULL );
2139 }
2140 g_object_unref( t );
2141
2142 return( msk );
2143 }
2144
2145 DOUBLEMASK *
im_gauss_dmask(const char * filename,double sigma,double min_ampl)2146 im_gauss_dmask( const char *filename, double sigma, double min_ampl )
2147 {
2148 VipsImage *t;
2149 DOUBLEMASK *msk;
2150
2151 if( vips_gaussmat( &t, sigma, min_ampl,
2152 "precision", VIPS_PRECISION_FLOAT,
2153 NULL ) )
2154 return( NULL );
2155 if( !(msk = im_vips2mask( t, filename )) ) {
2156 g_object_unref( t );
2157 return( NULL );
2158 }
2159 g_object_unref( t );
2160
2161 return( msk );
2162 }
2163
2164 DOUBLEMASK *
im_gauss_dmask_sep(const char * filename,double sigma,double min_ampl)2165 im_gauss_dmask_sep( const char *filename, double sigma, double min_ampl )
2166 {
2167 VipsImage *t;
2168 DOUBLEMASK *msk;
2169
2170 if( vips_gaussmat( &t, sigma, min_ampl,
2171 "precision", VIPS_PRECISION_FLOAT,
2172 "separable", TRUE,
2173 NULL ) )
2174 return( NULL );
2175 if( !(msk = im_vips2mask( t, filename )) ) {
2176 g_object_unref( t );
2177 return( NULL );
2178 }
2179 g_object_unref( t );
2180
2181 return( msk );
2182 }
2183
2184 INTMASK *
im_gauss_imask(const char * filename,double sigma,double min_ampl)2185 im_gauss_imask( const char *filename, double sigma, double min_ampl )
2186 {
2187 VipsImage *t;
2188 INTMASK *msk;
2189
2190 if( vips_gaussmat( &t, sigma, min_ampl, NULL ) )
2191 return( NULL );
2192 if( !(msk = im_vips2imask( t, filename )) ) {
2193 g_object_unref( t );
2194 return( NULL );
2195 }
2196 g_object_unref( t );
2197
2198 return( msk );
2199 }
2200
2201 INTMASK *
im_gauss_imask_sep(const char * filename,double sigma,double min_ampl)2202 im_gauss_imask_sep( const char *filename, double sigma, double min_ampl )
2203 {
2204 VipsImage *t;
2205 INTMASK *msk;
2206
2207 if( vips_gaussmat( &t, sigma, min_ampl,
2208 "separable", TRUE,
2209 NULL ) )
2210 return( NULL );
2211 if( !(msk = im_vips2imask( t, filename )) ) {
2212 g_object_unref( t );
2213 return( NULL );
2214 }
2215 g_object_unref( t );
2216
2217 return( msk );
2218 }
2219
2220 INTMASK *
im_log_imask(const char * filename,double sigma,double min_ampl)2221 im_log_imask( const char *filename, double sigma, double min_ampl )
2222 {
2223 VipsImage *t;
2224 INTMASK *msk;
2225
2226 if( vips_logmat( &t, sigma, min_ampl, NULL ) )
2227 return( NULL );
2228 if( !(msk = im_vips2imask( t, filename )) ) {
2229 g_object_unref( t );
2230 return( NULL );
2231 }
2232 g_object_unref( t );
2233
2234 return( msk );
2235 }
2236
2237 DOUBLEMASK *
im_log_dmask(const char * filename,double sigma,double min_ampl)2238 im_log_dmask( const char *filename, double sigma, double min_ampl )
2239 {
2240 VipsImage *t;
2241 DOUBLEMASK *msk;
2242
2243 if( vips_logmat( &t, sigma, min_ampl,
2244 "precision", VIPS_PRECISION_FLOAT,
2245 NULL ) )
2246 return( NULL );
2247 if( !(msk = im_vips2mask( t, filename )) ) {
2248 g_object_unref( t );
2249 return( NULL );
2250 }
2251 g_object_unref( t );
2252
2253 return( msk );
2254 }
2255
2256 int
im_recomb(IMAGE * in,IMAGE * out,DOUBLEMASK * recomb)2257 im_recomb( IMAGE *in, IMAGE *out, DOUBLEMASK *recomb )
2258 {
2259 VipsImage *t1, *t2;
2260
2261 if( !(t1 = vips_image_new()) ||
2262 im_mask2vips( recomb, t1 ) )
2263 return( -1 );
2264 if( vips_recomb( in, &t2, t1,
2265 NULL ) ) {
2266 g_object_unref( t1 );
2267 return( -1 );
2268 }
2269 g_object_unref( t1 );
2270 if( vips_image_write( t2, out ) ) {
2271 g_object_unref( t2 );
2272 return( -1 );
2273 }
2274 g_object_unref( t2 );
2275
2276 return( 0 );
2277 }
2278
2279 int
im_compass(VipsImage * in,VipsImage * out,INTMASK * mask)2280 im_compass( VipsImage *in, VipsImage *out, INTMASK *mask )
2281 {
2282 VipsImage *t1, *t2;
2283
2284 if( !(t1 = vips_image_new()) ||
2285 im_imask2vips( mask, t1 ) )
2286 return( -1 );
2287 if( vips_compass( in, &t2, t1,
2288 "times", 8,
2289 "angle", VIPS_ANGLE45_D45,
2290 "precision", VIPS_PRECISION_INTEGER,
2291 NULL ) ) {
2292 g_object_unref( t1 );
2293 return( -1 );
2294 }
2295 g_object_unref( t1 );
2296 if( vips_image_write( t2, out ) ) {
2297 g_object_unref( t2 );
2298 return( -1 );
2299 }
2300 g_object_unref( t2 );
2301
2302 return( 0 );
2303 }
2304
2305 int
im_lindetect(IMAGE * in,IMAGE * out,INTMASK * mask)2306 im_lindetect( IMAGE *in, IMAGE *out, INTMASK *mask )
2307 {
2308 VipsImage *t1, *t2;
2309
2310 if( !(t1 = vips_image_new()) ||
2311 im_imask2vips( mask, t1 ) )
2312 return( -1 );
2313 if( vips_compass( in, &t2, t1,
2314 "times", 4,
2315 "angle", VIPS_ANGLE45_D45,
2316 "precision", VIPS_PRECISION_INTEGER,
2317 NULL ) ) {
2318 g_object_unref( t1 );
2319 return( -1 );
2320 }
2321 g_object_unref( t1 );
2322 if( vips_image_write( t2, out ) ) {
2323 g_object_unref( t2 );
2324 return( -1 );
2325 }
2326 g_object_unref( t2 );
2327
2328 return( 0 );
2329 }
2330
2331 int
im_gradient(IMAGE * in,IMAGE * out,INTMASK * mask)2332 im_gradient( IMAGE *in, IMAGE *out, INTMASK *mask )
2333 {
2334 VipsImage *t1, *t2;
2335
2336 if( !(t1 = vips_image_new()) ||
2337 im_imask2vips( mask, t1 ) )
2338 return( -1 );
2339 if( vips_compass( in, &t2, t1,
2340 "times", 2,
2341 "angle", VIPS_ANGLE45_D90,
2342 "combine", VIPS_COMBINE_SUM,
2343 "precision", VIPS_PRECISION_INTEGER,
2344 NULL ) ) {
2345 g_object_unref( t1 );
2346 return( -1 );
2347 }
2348 g_object_unref( t1 );
2349 if( vips_image_write( t2, out ) ) {
2350 g_object_unref( t2 );
2351 return( -1 );
2352 }
2353 g_object_unref( t2 );
2354
2355 return( 0 );
2356 }
2357
2358 int
im_convsep_raw(IMAGE * in,IMAGE * out,INTMASK * mask)2359 im_convsep_raw( IMAGE *in, IMAGE *out, INTMASK *mask )
2360 {
2361 im_error( "im_convsep_raw", "no compat function" );
2362 return( -1 );
2363 }
2364
2365 int
im_convsep(IMAGE * in,IMAGE * out,INTMASK * mask)2366 im_convsep( IMAGE *in, IMAGE *out, INTMASK *mask )
2367 {
2368 VipsImage *t1, *t2;
2369
2370 if( !(t1 = vips_image_new()) ||
2371 im_imask2vips( mask, t1 ) )
2372 return( -1 );
2373 if( vips_convsep( in, &t2, t1,
2374 "precision", VIPS_PRECISION_INTEGER,
2375 NULL ) ) {
2376 g_object_unref( t1 );
2377 return( -1 );
2378 }
2379 g_object_unref( t1 );
2380 if( vips_image_write( t2, out ) ) {
2381 g_object_unref( t2 );
2382 return( -1 );
2383 }
2384 g_object_unref( t2 );
2385
2386 return( 0 );
2387 }
2388
2389 int
im_convsep_f_raw(IMAGE * in,IMAGE * out,DOUBLEMASK * mask)2390 im_convsep_f_raw( IMAGE *in, IMAGE *out, DOUBLEMASK *mask )
2391 {
2392 im_error( "im_convsep_raw", "no compat function" );
2393 return( -1 );
2394 }
2395
2396 int
im_convsep_f(IMAGE * in,IMAGE * out,DOUBLEMASK * mask)2397 im_convsep_f( IMAGE *in, IMAGE *out, DOUBLEMASK *mask )
2398 {
2399 VipsImage *t1, *t2;
2400
2401 if( !(t1 = vips_image_new()) ||
2402 im_mask2vips( mask, t1 ) )
2403 return( -1 );
2404 if( vips_convsep( in, &t2, t1, NULL ) ) {
2405 g_object_unref( t1 );
2406 return( -1 );
2407 }
2408 g_object_unref( t1 );
2409 if( vips_image_write( t2, out ) ) {
2410 g_object_unref( t2 );
2411 return( -1 );
2412 }
2413 g_object_unref( t2 );
2414
2415 return( 0 );
2416 }
2417
2418 int
im_conv(VipsImage * in,VipsImage * out,INTMASK * mask)2419 im_conv( VipsImage *in, VipsImage *out, INTMASK *mask )
2420 {
2421 VipsImage *t1, *t2;
2422
2423 if( !(t1 = vips_image_new()) ||
2424 im_imask2vips( mask, t1 ) )
2425 return( -1 );
2426 if( vips_convi( in, &t2, t1,
2427 NULL ) ) {
2428 g_object_unref( t1 );
2429 return( -1 );
2430 }
2431 g_object_unref( t1 );
2432 if( vips_image_write( t2, out ) ) {
2433 g_object_unref( t2 );
2434 return( -1 );
2435 }
2436 g_object_unref( t2 );
2437
2438 return( 0 );
2439 }
2440
2441 int
im_conv_raw(VipsImage * in,VipsImage * out,INTMASK * mask)2442 im_conv_raw( VipsImage *in, VipsImage *out, INTMASK *mask )
2443 {
2444 im_error( "im_conv_raw", "no compat function" );
2445 return( -1 );
2446 }
2447
2448 int
im_conv_f(VipsImage * in,VipsImage * out,DOUBLEMASK * mask)2449 im_conv_f( VipsImage *in, VipsImage *out, DOUBLEMASK *mask )
2450 {
2451 VipsImage *t1, *t2;
2452
2453 if( !(t1 = vips_image_new()) ||
2454 im_mask2vips( mask, t1 ) )
2455 return( -1 );
2456 if( vips_convf( in, &t2, t1,
2457 NULL ) ) {
2458 g_object_unref( t1 );
2459 return( -1 );
2460 }
2461 g_object_unref( t1 );
2462 if( vips_image_write( t2, out ) ) {
2463 g_object_unref( t2 );
2464 return( -1 );
2465 }
2466 g_object_unref( t2 );
2467
2468 return( 0 );
2469 }
2470
2471 int
im_aconvsep(VipsImage * in,VipsImage * out,DOUBLEMASK * mask,int n_layers)2472 im_aconvsep( VipsImage *in, VipsImage *out, DOUBLEMASK *mask, int n_layers )
2473 {
2474 VipsImage *t1, *t2;
2475
2476 if( !(t1 = vips_image_new()) ||
2477 im_mask2vips( mask, t1 ) )
2478 return( -1 );
2479 if( vips_convasep( in, &t2, t1,
2480 "layers", n_layers,
2481 NULL ) ) {
2482 g_object_unref( t1 );
2483 return( -1 );
2484 }
2485 g_object_unref( t1 );
2486 if( vips_image_write( t2, out ) ) {
2487 g_object_unref( t2 );
2488 return( -1 );
2489 }
2490 g_object_unref( t2 );
2491
2492 return( 0 );
2493 }
2494
2495 int
im_aconv(VipsImage * in,VipsImage * out,DOUBLEMASK * mask,int n_layers,int cluster)2496 im_aconv( VipsImage *in, VipsImage *out,
2497 DOUBLEMASK *mask, int n_layers, int cluster )
2498 {
2499 VipsImage *t1, *t2;
2500
2501 if( !(t1 = vips_image_new()) ||
2502 im_mask2vips( mask, t1 ) )
2503 return( -1 );
2504 if( vips_conva( in, &t2, t1,
2505 "layers", n_layers,
2506 "cluster", cluster,
2507 NULL ) ) {
2508 g_object_unref( t1 );
2509 return( -1 );
2510 }
2511 g_object_unref( t1 );
2512 if( vips_image_write( t2, out ) ) {
2513 g_object_unref( t2 );
2514 return( -1 );
2515 }
2516 g_object_unref( t2 );
2517
2518 return( 0 );
2519 }
2520
2521 int
im_conv_f_raw(VipsImage * in,VipsImage * out,DOUBLEMASK * mask)2522 im_conv_f_raw( VipsImage *in, VipsImage *out, DOUBLEMASK *mask )
2523 {
2524 im_error( "im_conv_f_raw", "no compat function" );
2525 return( -1 );
2526 }
2527
2528 int
im_addgnoise(IMAGE * in,IMAGE * out,double sigma)2529 im_addgnoise( IMAGE *in, IMAGE *out, double sigma )
2530 {
2531 IMAGE *t;
2532
2533 if( !(t = im_open_local( out, "im_addgnoise", "p" )) ||
2534 im_gaussnoise( t, in->Xsize, in->Ysize, 0, sigma ) ||
2535 im_add( in, t, out ) )
2536 return( -1 );
2537
2538 return( 0 );
2539 }
2540
2541 int
im_contrast_surface_raw(IMAGE * in,IMAGE * out,int half_win_size,int spacing)2542 im_contrast_surface_raw( IMAGE *in, IMAGE *out, int half_win_size, int spacing )
2543 {
2544 im_error( "im_contrast_surface_raw", "no compat function" );
2545 return( -1 );
2546 }
2547
2548 /* This replaces some custom code in 7.36 and earlier. The hand-made one was
2549 * slower for spacing == 1, though faster for large values of spacing.
2550 *
2551 * Not worth maintaining a special operator for.
2552 */
2553 int
im_contrast_surface(IMAGE * in,IMAGE * out,int half_win_size,int spacing)2554 im_contrast_surface( IMAGE *in, IMAGE *out, int half_win_size, int spacing )
2555 {
2556 VipsImage **t = (VipsImage **)
2557 vips_object_local_array( VIPS_OBJECT( out ), 10 );
2558 int size = half_win_size * 2;
2559
2560 int x, y;
2561
2562 t[0] = vips_image_new_matrixv( 1, 2, -1.0, 1.0 );
2563 t[1] = vips_image_new_matrixv( 2, 1, -1.0, 1.0 );
2564 t[8] = vips_image_new_matrix( size, size );
2565
2566 for( y = 0; y < size; y++ )
2567 for( x = 0; x < size; x++ )
2568 *VIPS_MATRIX( t[8], x, y ) = 1.0;
2569
2570 if( vips_conv( in, &t[2], t[0],
2571 "precision", VIPS_PRECISION_INTEGER,
2572 NULL ) ||
2573 vips_conv( in, &t[3], t[1],
2574 "precision", VIPS_PRECISION_INTEGER,
2575 NULL ) ||
2576 vips_abs( t[2], &t[4], NULL ) ||
2577 vips_abs( t[3], &t[5], NULL ) ||
2578 vips_add( t[4], t[5], &t[6], NULL ) ||
2579 vips_conv( t[6], &t[7], t[8],
2580 "precision", VIPS_PRECISION_INTEGER,
2581 NULL ) ||
2582 vips_subsample( t[7], &t[9], spacing, spacing, NULL ) ||
2583 vips_image_write( t[9], out ) )
2584 return( -1 );
2585
2586 return( 0 );
2587 }
2588
2589 int
im_spcor_raw(IMAGE * in,IMAGE * ref,IMAGE * out)2590 im_spcor_raw( IMAGE *in, IMAGE *ref, IMAGE *out )
2591 {
2592 im_error( "im_spcor_raw", "no compat function" );
2593 return( -1 );
2594 }
2595
2596 int
im_spcor(IMAGE * in,IMAGE * ref,IMAGE * out)2597 im_spcor( IMAGE *in, IMAGE *ref, IMAGE *out )
2598 {
2599 VipsImage *x;
2600
2601 if( vips_call( "spcor", in, ref, &x, NULL ) )
2602 return( -1 );
2603 if( vips_image_write( x, out ) ) {
2604 g_object_unref( x );
2605 return( -1 );
2606 }
2607 g_object_unref( x );
2608
2609 return( 0 );
2610 }
2611
2612 int
im_fastcor_raw(IMAGE * in,IMAGE * ref,IMAGE * out)2613 im_fastcor_raw( IMAGE *in, IMAGE *ref, IMAGE *out )
2614 {
2615 im_error( "im_fastcor_raw", "no compat function" );
2616 return( -1 );
2617 }
2618
2619 int
im_fastcor(IMAGE * in,IMAGE * ref,IMAGE * out)2620 im_fastcor( IMAGE *in, IMAGE *ref, IMAGE *out )
2621 {
2622 VipsImage *x;
2623
2624 if( vips_call( "fastcor", in, ref, &x, NULL ) )
2625 return( -1 );
2626 if( vips_image_write( x, out ) ) {
2627 g_object_unref( x );
2628 return( -1 );
2629 }
2630 g_object_unref( x );
2631
2632 return( 0 );
2633 }
2634
2635 int
im_sharpen(IMAGE * in,IMAGE * out,int mask_size,double x1,double y2,double y3,double m1,double m2)2636 im_sharpen( IMAGE *in, IMAGE *out,
2637 int mask_size,
2638 double x1, double y2, double y3,
2639 double m1, double m2 )
2640 {
2641 VipsImage **t = (VipsImage **)
2642 vips_object_local_array( VIPS_OBJECT( out ), 2 );
2643
2644 /* im_sharpen() always recoded as labq and im_benchmark() depends
2645 * upon this behaviour.
2646 */
2647 if( vips_call( "sharpen", in, &t[0],
2648 "sigma", mask_size / 4.0,
2649 "x1", x1,
2650 "y2", y2,
2651 "y3", y3,
2652 "m1", m1,
2653 "m2", m2,
2654 NULL ) ||
2655 vips_colourspace( t[0], &t[1],
2656 VIPS_INTERPRETATION_LABQ, NULL ) ||
2657 vips_image_write( t[1], out ) )
2658 return( -1 );
2659
2660 return( 0 );
2661 }
2662
2663 static int
vips__round(VipsImage * in,VipsImage * out,VipsOperationRound round)2664 vips__round( VipsImage *in, VipsImage *out, VipsOperationRound round )
2665 {
2666 VipsImage *t;
2667
2668 if( vips_round( in, &t, round,
2669 NULL ) )
2670 return( -1 );
2671 if( vips_image_write( t, out ) ) {
2672 g_object_unref( t );
2673 return( -1 );
2674 }
2675 g_object_unref( t );
2676
2677 return( 0 );
2678 }
2679
2680 int
im_rint(IMAGE * in,IMAGE * out)2681 im_rint( IMAGE *in, IMAGE *out )
2682 {
2683 return( vips__round( in, out, VIPS_OPERATION_ROUND_RINT ) );
2684 }
2685
2686 int
im_floor(IMAGE * in,IMAGE * out)2687 im_floor( IMAGE *in, IMAGE *out )
2688 {
2689 return( vips__round( in, out, VIPS_OPERATION_ROUND_FLOOR ) );
2690 }
2691
2692 int
im_ceil(IMAGE * in,IMAGE * out)2693 im_ceil( IMAGE *in, IMAGE *out )
2694 {
2695 return( vips__round( in, out, VIPS_OPERATION_ROUND_CEIL ) );
2696 }
2697
2698 static int
vips__relational(IMAGE * in1,IMAGE * in2,IMAGE * out,VipsOperationRelational relational)2699 vips__relational( IMAGE *in1, IMAGE *in2, IMAGE *out,
2700 VipsOperationRelational relational )
2701 {
2702 VipsImage *t;
2703
2704 if( vips_relational( in1, in2, &t, relational,
2705 NULL ) )
2706 return( -1 );
2707 if( vips_image_write( t, out ) ) {
2708 g_object_unref( t );
2709 return( -1 );
2710 }
2711 g_object_unref( t );
2712
2713 return( 0 );
2714 }
2715
2716 int
im_equal(IMAGE * in1,IMAGE * in2,IMAGE * out)2717 im_equal( IMAGE *in1, IMAGE *in2, IMAGE *out )
2718 {
2719 return( vips__relational( in1, in2, out,
2720 VIPS_OPERATION_RELATIONAL_EQUAL ) );
2721 }
2722
2723 int
im_notequal(IMAGE * in1,IMAGE * in2,IMAGE * out)2724 im_notequal( IMAGE *in1, IMAGE *in2, IMAGE *out )
2725 {
2726 return( vips__relational( in1, in2, out,
2727 VIPS_OPERATION_RELATIONAL_NOTEQ ) );
2728 }
2729
2730 int
im_less(IMAGE * in1,IMAGE * in2,IMAGE * out)2731 im_less( IMAGE *in1, IMAGE *in2, IMAGE *out )
2732 {
2733 return( vips__relational( in1, in2, out,
2734 VIPS_OPERATION_RELATIONAL_LESS ) );
2735 }
2736
2737 int
im_lesseq(IMAGE * in1,IMAGE * in2,IMAGE * out)2738 im_lesseq( IMAGE *in1, IMAGE *in2, IMAGE *out )
2739 {
2740 return( vips__relational( in1, in2, out,
2741 VIPS_OPERATION_RELATIONAL_LESSEQ ) );
2742 }
2743
2744 int
im_more(IMAGE * in1,IMAGE * in2,IMAGE * out)2745 im_more( IMAGE *in1, IMAGE *in2, IMAGE *out )
2746 {
2747 return( vips__relational( in1, in2, out,
2748 VIPS_OPERATION_RELATIONAL_MORE ) );
2749 }
2750
2751 int
im_moreeq(IMAGE * in1,IMAGE * in2,IMAGE * out)2752 im_moreeq( IMAGE *in1, IMAGE *in2, IMAGE *out )
2753 {
2754 return( vips__relational( in1, in2, out,
2755 VIPS_OPERATION_RELATIONAL_MOREEQ ) );
2756 }
2757
2758 static int
vips__relational_vec(IMAGE * in,IMAGE * out,VipsOperationRelational relational,double * c,int n)2759 vips__relational_vec( IMAGE *in, IMAGE *out,
2760 VipsOperationRelational relational, double *c, int n )
2761 {
2762 VipsImage *t;
2763
2764 if( vips_relational_const( in, &t, relational, c, n,
2765 NULL ) )
2766 return( -1 );
2767 if( vips_image_write( t, out ) ) {
2768 g_object_unref( t );
2769 return( -1 );
2770 }
2771 g_object_unref( t );
2772
2773 return( 0 );
2774 }
2775
2776 int
im_equal_vec(VipsImage * in,VipsImage * out,int n,double * c)2777 im_equal_vec( VipsImage *in, VipsImage *out, int n, double *c )
2778 {
2779 return( vips__relational_vec( in, out,
2780 VIPS_OPERATION_RELATIONAL_EQUAL, c, n ) );
2781 }
2782
2783 int
im_notequal_vec(VipsImage * in,VipsImage * out,int n,double * c)2784 im_notequal_vec( VipsImage *in, VipsImage *out, int n, double *c )
2785 {
2786 return( vips__relational_vec( in, out,
2787 VIPS_OPERATION_RELATIONAL_NOTEQ, c, n ) );
2788 }
2789
2790 int
im_less_vec(VipsImage * in,VipsImage * out,int n,double * c)2791 im_less_vec( VipsImage *in, VipsImage *out, int n, double *c )
2792 {
2793 return( vips__relational_vec( in, out,
2794 VIPS_OPERATION_RELATIONAL_LESS, c, n ) );
2795 }
2796
2797 int
im_lesseq_vec(VipsImage * in,VipsImage * out,int n,double * c)2798 im_lesseq_vec( VipsImage *in, VipsImage *out, int n, double *c )
2799 {
2800 return( vips__relational_vec( in, out,
2801 VIPS_OPERATION_RELATIONAL_LESSEQ, c, n ) );
2802 }
2803
2804 int
im_more_vec(VipsImage * in,VipsImage * out,int n,double * c)2805 im_more_vec( VipsImage *in, VipsImage *out, int n, double *c )
2806 {
2807 return( vips__relational_vec( in, out,
2808 VIPS_OPERATION_RELATIONAL_MORE, c, n ) );
2809 }
2810
2811 int
im_moreeq_vec(VipsImage * in,VipsImage * out,int n,double * c)2812 im_moreeq_vec( VipsImage *in, VipsImage *out, int n, double *c )
2813 {
2814 return( vips__relational_vec( in, out,
2815 VIPS_OPERATION_RELATIONAL_MOREEQ, c, n ) );
2816 }
2817
2818 int
im_equalconst(IMAGE * in,IMAGE * out,double c)2819 im_equalconst( IMAGE *in, IMAGE *out, double c )
2820 {
2821 return( im_equal_vec( in, out, 1, &c ) );
2822 }
2823
2824 int
im_notequalconst(IMAGE * in,IMAGE * out,double c)2825 im_notequalconst( IMAGE *in, IMAGE *out, double c )
2826 {
2827 return( im_notequal_vec( in, out, 1, &c ) );
2828 }
2829
2830 int
im_lessconst(IMAGE * in,IMAGE * out,double c)2831 im_lessconst( IMAGE *in, IMAGE *out, double c )
2832 {
2833 return( im_less_vec( in, out, 1, &c ) );
2834 }
2835
2836 int
im_lesseqconst(IMAGE * in,IMAGE * out,double c)2837 im_lesseqconst( IMAGE *in, IMAGE *out, double c )
2838 {
2839 return( im_lesseq_vec( in, out, 1, &c ) );
2840 }
2841
2842 int
im_moreconst(IMAGE * in,IMAGE * out,double c)2843 im_moreconst( IMAGE *in, IMAGE *out, double c )
2844 {
2845 return( im_more_vec( in, out, 1, &c ) );
2846 }
2847
2848 int
im_moreeqconst(IMAGE * in,IMAGE * out,double c)2849 im_moreeqconst( IMAGE *in, IMAGE *out, double c )
2850 {
2851 return( im_moreeq_vec( in, out, 1, &c ) );
2852 }
2853
2854 int
im_remainder(IMAGE * in1,IMAGE * in2,IMAGE * out)2855 im_remainder( IMAGE *in1, IMAGE *in2, IMAGE *out )
2856 {
2857 VipsImage *t;
2858
2859 if( vips_remainder( in1, in2, &t,
2860 NULL ) )
2861 return( -1 );
2862 if( vips_image_write( t, out ) ) {
2863 g_object_unref( t );
2864 return( -1 );
2865 }
2866 g_object_unref( t );
2867
2868 return( 0 );
2869 }
2870
2871 int
im_remainder_vec(IMAGE * in,IMAGE * out,int n,double * c)2872 im_remainder_vec( IMAGE *in, IMAGE *out, int n, double *c )
2873 {
2874 VipsImage *t;
2875
2876 if( vips_remainder_const( in, &t, c, n,
2877 NULL ) )
2878 return( -1 );
2879 if( vips_image_write( t, out ) ) {
2880 g_object_unref( t );
2881 return( -1 );
2882 }
2883 g_object_unref( t );
2884
2885 return( 0 );
2886 }
2887
2888 int
im_remainderconst(IMAGE * in,IMAGE * out,double c)2889 im_remainderconst( IMAGE *in, IMAGE *out, double c )
2890 {
2891 return( im_remainder_vec( in, out, 1, &c ) );
2892 }
2893
2894 static int
vips__boolean(IMAGE * in1,IMAGE * in2,IMAGE * out,VipsOperationBoolean boolean)2895 vips__boolean( IMAGE *in1, IMAGE *in2, IMAGE *out,
2896 VipsOperationBoolean boolean )
2897 {
2898 VipsImage *t;
2899
2900 if( vips_boolean( in1, in2, &t, boolean,
2901 NULL ) )
2902 return( -1 );
2903 if( vips_image_write( t, out ) ) {
2904 g_object_unref( t );
2905 return( -1 );
2906 }
2907 g_object_unref( t );
2908
2909 return( 0 );
2910 }
2911
2912 int
im_andimage(VipsImage * in1,VipsImage * in2,VipsImage * out)2913 im_andimage( VipsImage *in1, VipsImage *in2, VipsImage *out )
2914 {
2915 return( vips__boolean( in1, in2, out, VIPS_OPERATION_BOOLEAN_AND ) );
2916 }
2917
2918 int
im_orimage(VipsImage * in1,VipsImage * in2,VipsImage * out)2919 im_orimage( VipsImage *in1, VipsImage *in2, VipsImage *out )
2920 {
2921 return( vips__boolean( in1, in2, out, VIPS_OPERATION_BOOLEAN_OR ) );
2922 }
2923
2924 int
im_eorimage(VipsImage * in1,VipsImage * in2,VipsImage * out)2925 im_eorimage( VipsImage *in1, VipsImage *in2, VipsImage *out )
2926 {
2927 return( vips__boolean( in1, in2, out, VIPS_OPERATION_BOOLEAN_EOR ) );
2928 }
2929
2930 static int
vips__boolean_vec(IMAGE * in,IMAGE * out,VipsOperationBoolean boolean,double * c,int n)2931 vips__boolean_vec( IMAGE *in, IMAGE *out,
2932 VipsOperationBoolean boolean, double *c, int n )
2933 {
2934 VipsImage *t;
2935
2936 if( vips_boolean_const( in, &t, boolean, c, n,
2937 NULL ) )
2938 return( -1 );
2939 if( vips_image_write( t, out ) ) {
2940 g_object_unref( t );
2941 return( -1 );
2942 }
2943 g_object_unref( t );
2944
2945 return( 0 );
2946 }
2947
2948 int
im_andimage_vec(VipsImage * in,VipsImage * out,int n,double * c)2949 im_andimage_vec( VipsImage *in, VipsImage *out, int n, double *c )
2950 {
2951 return( vips__boolean_vec( in, out,
2952 VIPS_OPERATION_BOOLEAN_AND, c, n ) );
2953 }
2954
2955 int
im_orimage_vec(VipsImage * in,VipsImage * out,int n,double * c)2956 im_orimage_vec( VipsImage *in, VipsImage *out, int n, double *c )
2957 {
2958 return( vips__boolean_vec( in, out,
2959 VIPS_OPERATION_BOOLEAN_OR, c, n ) );
2960 }
2961
2962 int
im_eorimage_vec(VipsImage * in,VipsImage * out,int n,double * c)2963 im_eorimage_vec( VipsImage *in, VipsImage *out, int n, double *c )
2964 {
2965 return( vips__boolean_vec( in, out,
2966 VIPS_OPERATION_BOOLEAN_EOR, c, n ) );
2967 }
2968
2969 int
im_shiftleft_vec(IMAGE * in,IMAGE * out,int n,double * c)2970 im_shiftleft_vec( IMAGE *in, IMAGE *out, int n, double *c )
2971 {
2972 return( vips__boolean_vec( in, out,
2973 VIPS_OPERATION_BOOLEAN_LSHIFT, c, n ) );
2974 }
2975
2976 int
im_shiftright_vec(IMAGE * in,IMAGE * out,int n,double * c)2977 im_shiftright_vec( IMAGE *in, IMAGE *out, int n, double *c )
2978 {
2979 return( vips__boolean_vec( in, out,
2980 VIPS_OPERATION_BOOLEAN_RSHIFT, c, n ) );
2981 }
2982
2983 int
im_andimageconst(IMAGE * in,IMAGE * out,double c)2984 im_andimageconst( IMAGE *in, IMAGE *out, double c )
2985 {
2986 return( im_andimage_vec( in, out, 1, &c ) );
2987 }
2988
2989 int
im_orimageconst(IMAGE * in,IMAGE * out,double c)2990 im_orimageconst( IMAGE *in, IMAGE *out, double c )
2991 {
2992 return( im_orimage_vec( in, out, 1, &c ) );
2993 }
2994
2995 int
im_eorimageconst(IMAGE * in,IMAGE * out,double c)2996 im_eorimageconst( IMAGE *in, IMAGE *out, double c )
2997 {
2998 return( im_eorimage_vec( in, out, 1, &c ) );
2999 }
3000
3001 int
im_shiftleft(IMAGE * in,IMAGE * out,int n)3002 im_shiftleft( IMAGE *in, IMAGE *out, int n )
3003 {
3004 double c = n;
3005
3006 return( im_shiftleft_vec( in, out, 1, &c ) );
3007 }
3008
3009 int
im_shiftright(IMAGE * in,IMAGE * out,int n)3010 im_shiftright( IMAGE *in, IMAGE *out, int n )
3011 {
3012 double c = n;
3013
3014 return( im_shiftright_vec( in, out, 1, &c ) );
3015 }
3016
3017 static int
vips__math2_vec(IMAGE * in,IMAGE * out,VipsOperationMath2 math2,double * c,int n)3018 vips__math2_vec( IMAGE *in, IMAGE *out,
3019 VipsOperationMath2 math2, double *c, int n )
3020 {
3021 VipsImage *t;
3022
3023 if( vips_math2_const( in, &t, math2, c, n,
3024 NULL ) )
3025 return( -1 );
3026 if( vips_image_write( t, out ) ) {
3027 g_object_unref( t );
3028 return( -1 );
3029 }
3030 g_object_unref( t );
3031
3032 return( 0 );
3033 }
3034
3035 int
im_powtra_vec(VipsImage * in,VipsImage * out,int n,double * c)3036 im_powtra_vec( VipsImage *in, VipsImage *out, int n, double *c )
3037 {
3038 return( vips__math2_vec( in, out, VIPS_OPERATION_MATH2_POW, c, n ) );
3039 }
3040
3041 int
im_powtra(IMAGE * in,IMAGE * out,double c)3042 im_powtra( IMAGE *in, IMAGE *out, double c )
3043 {
3044 return( im_powtra_vec( in, out, 1, &c ) );
3045 }
3046
3047 int
im_expntra_vec(IMAGE * in,IMAGE * out,int n,double * c)3048 im_expntra_vec( IMAGE *in, IMAGE *out, int n, double *c )
3049 {
3050 return( vips__math2_vec( in, out, VIPS_OPERATION_MATH2_WOP, c, n ) );
3051 }
3052
3053 int
im_expntra(IMAGE * in,IMAGE * out,double c)3054 im_expntra( IMAGE *in, IMAGE *out, double c )
3055 {
3056 return( im_expntra_vec( in, out, 1, &c ) );
3057 }
3058
3059 int
im_ifthenelse(VipsImage * c,VipsImage * a,VipsImage * b,VipsImage * out)3060 im_ifthenelse( VipsImage *c, VipsImage *a, VipsImage *b, VipsImage *out )
3061 {
3062 VipsImage *t;
3063
3064 if( vips_ifthenelse( c, a, b, &t,
3065 NULL ) )
3066 return( -1 );
3067 if( vips_image_write( t, out ) ) {
3068 g_object_unref( t );
3069 return( -1 );
3070 }
3071 g_object_unref( t );
3072
3073 return( 0 );
3074 }
3075
3076 int
im_blend(VipsImage * c,VipsImage * a,VipsImage * b,VipsImage * out)3077 im_blend( VipsImage *c, VipsImage *a, VipsImage *b, VipsImage *out )
3078 {
3079 VipsImage *t;
3080
3081 if( vips_ifthenelse( c, a, b, &t,
3082 "blend", TRUE,
3083 NULL ) )
3084 return( -1 );
3085 if( vips_image_write( t, out ) ) {
3086 g_object_unref( t );
3087 return( -1 );
3088 }
3089 g_object_unref( t );
3090
3091 return( 0 );
3092 }
3093
3094 static int
vips__complex(VipsImage * in,VipsImage * out,VipsOperationComplex cmplx)3095 vips__complex( VipsImage *in, VipsImage *out, VipsOperationComplex cmplx )
3096 {
3097 VipsImage *t;
3098
3099 if( vips_complex( in, &t, cmplx,
3100 NULL ) )
3101 return( -1 );
3102 if( vips_image_write( t, out ) ) {
3103 g_object_unref( t );
3104 return( -1 );
3105 }
3106 g_object_unref( t );
3107
3108 return( 0 );
3109 }
3110
3111 int
im_c2amph(IMAGE * in,IMAGE * out)3112 im_c2amph( IMAGE *in, IMAGE *out )
3113 {
3114 return( vips__complex( in, out, VIPS_OPERATION_COMPLEX_POLAR ) );
3115 }
3116
3117 int
im_c2rect(IMAGE * in,IMAGE * out)3118 im_c2rect( IMAGE *in, IMAGE *out )
3119 {
3120 return( vips__complex( in, out, VIPS_OPERATION_COMPLEX_RECT ) );
3121 }
3122
3123 static int
vips__complexget(VipsImage * in,VipsImage * out,VipsOperationComplexget get)3124 vips__complexget( VipsImage *in, VipsImage *out, VipsOperationComplexget get )
3125 {
3126 VipsImage *t;
3127
3128 if( vips_complexget( in, &t, get,
3129 NULL ) )
3130 return( -1 );
3131 if( vips_image_write( t, out ) ) {
3132 g_object_unref( t );
3133 return( -1 );
3134 }
3135 g_object_unref( t );
3136
3137 return( 0 );
3138 }
3139
3140 int
im_c2real(IMAGE * in,IMAGE * out)3141 im_c2real( IMAGE *in, IMAGE *out )
3142 {
3143 return( vips__complexget( in, out, VIPS_OPERATION_COMPLEXGET_REAL ) );
3144 }
3145
3146 int
im_c2imag(IMAGE * in,IMAGE * out)3147 im_c2imag( IMAGE *in, IMAGE *out )
3148 {
3149 return( vips__complexget( in, out, VIPS_OPERATION_COMPLEXGET_IMAG ) );
3150 }
3151
3152 int
im_ri2c(IMAGE * in1,IMAGE * in2,IMAGE * out)3153 im_ri2c( IMAGE *in1, IMAGE *in2, IMAGE *out )
3154 {
3155 VipsImage *x;
3156
3157 if( vips_call( "complexform", in1, in2, &x, NULL ) )
3158 return( -1 );
3159 if( vips_image_write( x, out ) ) {
3160 g_object_unref( x );
3161 return( -1 );
3162 }
3163 g_object_unref( x );
3164
3165 return( 0 );
3166 }
3167
3168 int
im_cache(VipsImage * in,VipsImage * out,int width,int height,int max)3169 im_cache( VipsImage *in, VipsImage *out,
3170 int width, int height, int max )
3171 {
3172 return( vips_sink_screen( in, out, NULL,
3173 width, height, max, 0, NULL, NULL ) );
3174 }
3175
3176 int
im_argb2rgba(VipsImage * in,VipsImage * out)3177 im_argb2rgba( VipsImage *in, VipsImage *out )
3178 {
3179 /* No longer exists, just a null op.
3180 */
3181 return( vips_image_write( in, out ) );
3182 }
3183
3184 int
im_shrink(VipsImage * in,VipsImage * out,double xshrink,double yshrink)3185 im_shrink( VipsImage *in, VipsImage *out, double xshrink, double yshrink )
3186 {
3187 VipsImage *x;
3188
3189 if( vips_shrink( in, &x, xshrink, yshrink, NULL ) )
3190 return( -1 );
3191 if( vips_image_write( x, out ) ) {
3192 g_object_unref( x );
3193 return( -1 );
3194 }
3195 g_object_unref( x );
3196
3197 return( 0 );
3198 }
3199
3200 int
im_eye(IMAGE * out,const int xsize,const int ysize,const double factor)3201 im_eye( IMAGE *out, const int xsize, const int ysize, const double factor )
3202 {
3203 VipsImage *x;
3204
3205 if( vips_eye( &x, xsize, ysize,
3206 "factor", factor,
3207 "uchar", TRUE,
3208 NULL ) )
3209 return( -1 );
3210 if( vips_image_write( x, out ) ) {
3211 g_object_unref( x );
3212 return( -1 );
3213 }
3214 g_object_unref( x );
3215
3216 return( 0 );
3217 }
3218
3219 int
im_feye(IMAGE * out,const int xsize,const int ysize,const double factor)3220 im_feye( IMAGE *out, const int xsize, const int ysize, const double factor )
3221 {
3222 VipsImage *x;
3223
3224 if( vips_eye( &x, xsize, ysize,
3225 "factor", factor,
3226 NULL ) )
3227 return( -1 );
3228 if( vips_image_write( x, out ) ) {
3229 g_object_unref( x );
3230 return( -1 );
3231 }
3232 g_object_unref( x );
3233
3234 return( 0 );
3235 }
3236
3237 int
im_grey(IMAGE * out,const int xsize,const int ysize)3238 im_grey( IMAGE *out, const int xsize, const int ysize )
3239 {
3240 VipsImage *x;
3241
3242 if( vips_grey( &x, xsize, ysize,
3243 "uchar", TRUE,
3244 NULL ) )
3245 return( -1 );
3246 if( vips_image_write( x, out ) ) {
3247 g_object_unref( x );
3248 return( -1 );
3249 }
3250 g_object_unref( x );
3251
3252 return( 0 );
3253 }
3254
3255 int
im_fgrey(IMAGE * out,const int xsize,const int ysize)3256 im_fgrey( IMAGE *out, const int xsize, const int ysize )
3257 {
3258 VipsImage *x;
3259
3260 if( vips_grey( &x, xsize, ysize,
3261 NULL ) )
3262 return( -1 );
3263 if( vips_image_write( x, out ) ) {
3264 g_object_unref( x );
3265 return( -1 );
3266 }
3267 g_object_unref( x );
3268
3269 return( 0 );
3270 }
3271
3272 int
im_buildlut(DOUBLEMASK * input,VipsImage * out)3273 im_buildlut( DOUBLEMASK *input, VipsImage *out )
3274 {
3275 VipsImage *mat;
3276 VipsImage *x;
3277
3278 mat = vips_image_new();
3279 if( im_mask2vips( input, mat ) )
3280 return( -1 );
3281 if( vips_buildlut( mat, &x,
3282 NULL ) ) {
3283 g_object_unref( mat );
3284 return( -1 );
3285 }
3286 g_object_unref( mat );
3287 if( vips_image_write( x, out ) ) {
3288 g_object_unref( x );
3289 return( -1 );
3290 }
3291 g_object_unref( x );
3292
3293 return( 0 );
3294 }
3295
3296 int
im_invertlut(DOUBLEMASK * input,VipsImage * out,int size)3297 im_invertlut( DOUBLEMASK *input, VipsImage *out, int size )
3298 {
3299 VipsImage *mat;
3300 VipsImage *x;
3301
3302 mat = vips_image_new();
3303 if( im_mask2vips( input, mat ) )
3304 return( -1 );
3305 if( vips_invertlut( mat, &x,
3306 "size", size,
3307 NULL ) ) {
3308 g_object_unref( mat );
3309 return( -1 );
3310 }
3311 g_object_unref( mat );
3312 if( vips_image_write( x, out ) ) {
3313 g_object_unref( x );
3314 return( -1 );
3315 }
3316 g_object_unref( x );
3317
3318 return( 0 );
3319 }
3320
3321 int
im_tone_build_range(IMAGE * out,int in_max,int out_max,double Lb,double Lw,double Ps,double Pm,double Ph,double S,double M,double H)3322 im_tone_build_range( IMAGE *out,
3323 int in_max, int out_max,
3324 double Lb, double Lw,
3325 double Ps, double Pm, double Ph,
3326 double S, double M, double H )
3327 {
3328 VipsImage *t;
3329
3330 if( vips_tonelut( &t,
3331 "in_max", in_max,
3332 "out_max", out_max,
3333 "Lb", Lb,
3334 "Lw", Lw,
3335 "Ps", Ps,
3336 "Pm", Pm,
3337 "Ph", Ph,
3338 "S", S,
3339 "M", M,
3340 "H", H,
3341 NULL ) )
3342 return( -1 );
3343 if( vips_image_write( t, out ) ) {
3344 g_object_unref( t );
3345 return( -1 );
3346 }
3347 g_object_unref( t );
3348
3349 return( 0 );
3350 }
3351
3352 int
im_tone_build(IMAGE * out,double Lb,double Lw,double Ps,double Pm,double Ph,double S,double M,double H)3353 im_tone_build( IMAGE *out,
3354 double Lb, double Lw,
3355 double Ps, double Pm, double Ph,
3356 double S, double M, double H )
3357 {
3358 IMAGE *t1;
3359
3360 if( !(t1 = im_open_local( out, "im_tone_build", "p" )) ||
3361 im_tone_build_range( t1, 32767, 32767,
3362 Lb, Lw, Ps, Pm, Ph, S, M, H ) ||
3363 im_clip2fmt( t1, out, IM_BANDFMT_SHORT ) )
3364 return( -1 );
3365
3366 return( 0 );
3367 }
3368
3369 int
im_rightshift_size(IMAGE * in,IMAGE * out,int xshift,int yshift,int band_fmt)3370 im_rightshift_size( IMAGE *in, IMAGE *out,
3371 int xshift, int yshift, int band_fmt )
3372 {
3373 VipsImage **t = (VipsImage **)
3374 vips_object_local_array( VIPS_OBJECT( out ), 2 );
3375
3376 if( vips_shrink( in, &t[0], 1 << xshift, 1 << yshift, NULL ) ||
3377 vips_cast( t[0], &t[1], band_fmt, NULL ) ||
3378 vips_image_write( t[1], out ) )
3379 return( -1 );
3380
3381 return( 0 );
3382 }
3383
3384 int
im_Lab2XYZ_temp(IMAGE * in,IMAGE * out,double X0,double Y0,double Z0)3385 im_Lab2XYZ_temp( IMAGE *in, IMAGE *out, double X0, double Y0, double Z0 )
3386 {
3387 VipsArea *temp;
3388 VipsImage *x;
3389
3390 temp = VIPS_AREA( vips_array_double_newv( 3, X0, Y0, Z0 ) );
3391 if( vips_Lab2XYZ( in, &x, "temp", temp, NULL ) ) {
3392 vips_area_unref( temp );
3393 return( -1 );
3394 }
3395 vips_area_unref( temp );
3396
3397 if( vips_image_write( x, out ) ) {
3398 g_object_unref( x );
3399 return( -1 );
3400 }
3401 g_object_unref( x );
3402
3403 return( 0 );
3404 }
3405
3406 int
im_Lab2XYZ(IMAGE * in,IMAGE * out)3407 im_Lab2XYZ( IMAGE *in, IMAGE *out )
3408 {
3409 VipsImage *x;
3410
3411 if( vips_Lab2XYZ( in, &x, NULL ) )
3412 return( -1 );
3413 if( vips_image_write( x, out ) ) {
3414 g_object_unref( x );
3415 return( -1 );
3416 }
3417 g_object_unref( x );
3418
3419 return( 0 );
3420 }
3421
3422 int
im_XYZ2Lab_temp(IMAGE * in,IMAGE * out,double X0,double Y0,double Z0)3423 im_XYZ2Lab_temp( IMAGE *in, IMAGE *out, double X0, double Y0, double Z0 )
3424 {
3425 double ary[3];
3426 VipsArea *temp;
3427 VipsImage *x;
3428
3429 ary[0] = X0;
3430 ary[1] = Y0;
3431 ary[2] = Z0;
3432 temp = VIPS_AREA( vips_array_double_new( ary, 3 ) );
3433 if( vips_XYZ2Lab( in, &x, "temp", temp, NULL ) ) {
3434 vips_area_unref( temp );
3435 return( -1 );
3436 }
3437 vips_area_unref( temp );
3438
3439 if( vips_image_write( x, out ) ) {
3440 g_object_unref( x );
3441 return( -1 );
3442 }
3443 g_object_unref( x );
3444
3445 return( 0 );
3446 }
3447
3448 int
im_XYZ2Lab(IMAGE * in,IMAGE * out)3449 im_XYZ2Lab( IMAGE *in, IMAGE *out )
3450 {
3451 VipsImage *x;
3452
3453 if( vips_XYZ2Lab( in, &x, NULL ) )
3454 return( -1 );
3455 if( vips_image_write( x, out ) ) {
3456 g_object_unref( x );
3457 return( -1 );
3458 }
3459 g_object_unref( x );
3460
3461 return( 0 );
3462 }
3463
3464 int
im_Lab2LCh(IMAGE * in,IMAGE * out)3465 im_Lab2LCh( IMAGE *in, IMAGE *out )
3466 {
3467 VipsImage *x;
3468
3469 if( vips_Lab2LCh( in, &x, NULL ) )
3470 return( -1 );
3471 if( vips_image_write( x, out ) ) {
3472 g_object_unref( x );
3473 return( -1 );
3474 }
3475 g_object_unref( x );
3476
3477 return( 0 );
3478 }
3479
3480 int
im_LCh2Lab(IMAGE * in,IMAGE * out)3481 im_LCh2Lab( IMAGE *in, IMAGE *out )
3482 {
3483 VipsImage *x;
3484
3485 if( vips_LCh2Lab( in, &x, NULL ) )
3486 return( -1 );
3487 if( vips_image_write( x, out ) ) {
3488 g_object_unref( x );
3489 return( -1 );
3490 }
3491 g_object_unref( x );
3492
3493 return( 0 );
3494 }
3495
3496 int
im_LCh2UCS(IMAGE * in,IMAGE * out)3497 im_LCh2UCS( IMAGE *in, IMAGE *out )
3498 {
3499 VipsImage *x;
3500
3501 if( vips_LCh2CMC( in, &x, NULL ) )
3502 return( -1 );
3503 if( vips_image_write( x, out ) ) {
3504 g_object_unref( x );
3505 return( -1 );
3506 }
3507 g_object_unref( x );
3508
3509 return( 0 );
3510 }
3511
3512 int
im_UCS2LCh(IMAGE * in,IMAGE * out)3513 im_UCS2LCh( IMAGE *in, IMAGE *out )
3514 {
3515 VipsImage *x;
3516
3517 if( vips_CMC2LCh( in, &x, NULL ) )
3518 return( -1 );
3519 if( vips_image_write( x, out ) ) {
3520 g_object_unref( x );
3521 return( -1 );
3522 }
3523 g_object_unref( x );
3524
3525 return( 0 );
3526 }
3527
3528 int
im_XYZ2Yxy(IMAGE * in,IMAGE * out)3529 im_XYZ2Yxy( IMAGE *in, IMAGE *out )
3530 {
3531 VipsImage *x;
3532
3533 if( vips_XYZ2Yxy( in, &x, NULL ) )
3534 return( -1 );
3535 if( vips_image_write( x, out ) ) {
3536 g_object_unref( x );
3537 return( -1 );
3538 }
3539 g_object_unref( x );
3540
3541 return( 0 );
3542 }
3543
3544 int
im_Yxy2XYZ(IMAGE * in,IMAGE * out)3545 im_Yxy2XYZ( IMAGE *in, IMAGE *out )
3546 {
3547 VipsImage *x;
3548
3549 if( vips_Yxy2XYZ( in, &x, NULL ) )
3550 return( -1 );
3551 if( vips_image_write( x, out ) ) {
3552 g_object_unref( x );
3553 return( -1 );
3554 }
3555 g_object_unref( x );
3556
3557 return( 0 );
3558 }
3559
3560 int
im_float2rad(IMAGE * in,IMAGE * out)3561 im_float2rad( IMAGE *in, IMAGE *out )
3562 {
3563 VipsImage *x;
3564
3565 if( vips_float2rad( in, &x, NULL ) )
3566 return( -1 );
3567 if( vips_image_write( x, out ) ) {
3568 g_object_unref( x );
3569 return( -1 );
3570 }
3571 g_object_unref( x );
3572
3573 return( 0 );
3574 }
3575
3576 int
im_rad2float(IMAGE * in,IMAGE * out)3577 im_rad2float( IMAGE *in, IMAGE *out )
3578 {
3579 VipsImage *x;
3580
3581 if( vips_rad2float( in, &x, NULL ) )
3582 return( -1 );
3583 if( vips_image_write( x, out ) ) {
3584 g_object_unref( x );
3585 return( -1 );
3586 }
3587 g_object_unref( x );
3588
3589 return( 0 );
3590 }
3591
3592 int
im_Lab2LabQ(IMAGE * in,IMAGE * out)3593 im_Lab2LabQ( IMAGE *in, IMAGE *out )
3594 {
3595 VipsImage *x;
3596
3597 if( vips_Lab2LabQ( in, &x, NULL ) )
3598 return( -1 );
3599 if( vips_image_write( x, out ) ) {
3600 g_object_unref( x );
3601 return( -1 );
3602 }
3603 g_object_unref( x );
3604
3605 return( 0 );
3606 }
3607
3608 int
im_LabQ2Lab(IMAGE * in,IMAGE * out)3609 im_LabQ2Lab( IMAGE *in, IMAGE *out )
3610 {
3611 VipsImage *x;
3612
3613 if( vips_LabQ2Lab( in, &x, NULL ) )
3614 return( -1 );
3615 if( vips_image_write( x, out ) ) {
3616 g_object_unref( x );
3617 return( -1 );
3618 }
3619 g_object_unref( x );
3620
3621 return( 0 );
3622 }
3623
3624 int
im_Lab2LabS(IMAGE * in,IMAGE * out)3625 im_Lab2LabS( IMAGE *in, IMAGE *out )
3626 {
3627 VipsImage *x;
3628
3629 if( vips_Lab2LabS( in, &x, NULL ) )
3630 return( -1 );
3631 if( vips_image_write( x, out ) ) {
3632 g_object_unref( x );
3633 return( -1 );
3634 }
3635 g_object_unref( x );
3636
3637 return( 0 );
3638 }
3639
3640 int
im_LabS2Lab(IMAGE * in,IMAGE * out)3641 im_LabS2Lab( IMAGE *in, IMAGE *out )
3642 {
3643 VipsImage *x;
3644
3645 if( vips_LabS2Lab( in, &x, NULL ) )
3646 return( -1 );
3647 if( vips_image_write( x, out ) ) {
3648 g_object_unref( x );
3649 return( -1 );
3650 }
3651 g_object_unref( x );
3652
3653 return( 0 );
3654 }
3655
3656 int
im_LabQ2LabS(IMAGE * in,IMAGE * out)3657 im_LabQ2LabS( IMAGE *in, IMAGE *out )
3658 {
3659 VipsImage *x;
3660
3661 if( vips_LabQ2LabS( in, &x, NULL ) )
3662 return( -1 );
3663 if( vips_image_write( x, out ) ) {
3664 g_object_unref( x );
3665 return( -1 );
3666 }
3667 g_object_unref( x );
3668
3669 return( 0 );
3670 }
3671
3672 int
im_LabS2LabQ(IMAGE * in,IMAGE * out)3673 im_LabS2LabQ( IMAGE *in, IMAGE *out )
3674 {
3675 VipsImage *x;
3676
3677 if( vips_LabS2LabQ( in, &x, NULL ) )
3678 return( -1 );
3679 if( vips_image_write( x, out ) ) {
3680 g_object_unref( x );
3681 return( -1 );
3682 }
3683 g_object_unref( x );
3684
3685 return( 0 );
3686 }
3687
3688 int
im_Lab2disp(IMAGE * in,IMAGE * out,struct im_col_display * disp)3689 im_Lab2disp( IMAGE *in, IMAGE *out, struct im_col_display *disp )
3690 {
3691 IMAGE *t[1];
3692
3693 if( im_open_local_array( out, t, 1, "im_Lab2disp:1", "p" ) ||
3694 im_Lab2XYZ( in, t[0] ) ||
3695 im_XYZ2disp( t[0], out, disp ) )
3696 return( -1 );
3697
3698 return( 0 );
3699 }
3700
3701 int
im_dECMC_fromdisp(IMAGE * im1,IMAGE * im2,IMAGE * out,struct im_col_display * d)3702 im_dECMC_fromdisp( IMAGE *im1, IMAGE *im2,
3703 IMAGE *out, struct im_col_display *d )
3704 {
3705 IMAGE *t[4];
3706
3707 if( im_open_local_array( out, t, 4, "im_dECMC_fromdisp:1", "p" ) ||
3708 im_disp2XYZ( im1, t[0], d ) ||
3709 im_XYZ2Lab( t[0], t[1] ) ||
3710 im_disp2XYZ( im2, t[2], d ) ||
3711 im_XYZ2Lab( t[2], t[3] ) ||
3712 im_dECMC_fromLab( t[1], t[3], out ) )
3713 return( -1 );
3714
3715 return( 0 );
3716 }
3717
3718 int
im_dE_fromdisp(IMAGE * im1,IMAGE * im2,IMAGE * out,struct im_col_display * d)3719 im_dE_fromdisp( IMAGE *im1, IMAGE *im2, IMAGE *out, struct im_col_display *d )
3720 {
3721 IMAGE *t[2];
3722
3723 if( im_open_local_array( out, t, 2, "im_dE_fromdisp:1", "p" ) ||
3724 im_disp2XYZ( im1, t[0], d ) ||
3725 im_disp2XYZ( im2, t[1], d ) ||
3726 im_dE_fromXYZ( t[0], t[1], out ) )
3727 return( -1 );
3728
3729 return( 0 );
3730 }
3731
3732 int
im_disp2Lab(IMAGE * in,IMAGE * out,struct im_col_display * d)3733 im_disp2Lab( IMAGE *in, IMAGE *out, struct im_col_display *d )
3734 {
3735 VipsImage *t[1];
3736
3737 if( im_open_local_array( out, t, 1, "im_disp2Lab:1", "p" ) ||
3738 im_disp2XYZ( in, t[0], d ) ||
3739 im_XYZ2Lab( t[0], out ) )
3740 return( -1 );
3741
3742 return( 0 );
3743 }
3744
3745 int
im_sRGB2XYZ(IMAGE * in,IMAGE * out)3746 im_sRGB2XYZ( IMAGE *in, IMAGE *out )
3747 {
3748 VipsImage **t = (VipsImage **)
3749 vips_object_local_array( (VipsObject *) out, 2 );
3750
3751 if( vips_sRGB2scRGB( in, &t[0], NULL ) ||
3752 vips_scRGB2XYZ( t[0], &t[1], NULL ) ||
3753 vips_image_write( t[1], out ) )
3754 return( -1 );
3755
3756 return( 0 );
3757 }
3758
3759 int
im_XYZ2sRGB(IMAGE * in,IMAGE * out)3760 im_XYZ2sRGB( IMAGE *in, IMAGE *out )
3761 {
3762 VipsImage **t = (VipsImage **)
3763 vips_object_local_array( (VipsObject *) out, 2 );
3764
3765 if( vips_XYZ2scRGB( in, &t[0], NULL ) ||
3766 vips_scRGB2sRGB( t[0], &t[1], NULL ) ||
3767 vips_image_write( t[1], out ) )
3768 return( -1 );
3769
3770 return( 0 );
3771 }
3772
3773 int
im_LabQ2sRGB(IMAGE * in,IMAGE * out)3774 im_LabQ2sRGB( IMAGE *in, IMAGE *out )
3775 {
3776 VipsImage *x;
3777
3778 if( vips_LabQ2sRGB( in, &x, NULL ) )
3779 return( -1 );
3780 if( vips_image_write( x, out ) ) {
3781 g_object_unref( x );
3782 return( -1 );
3783 }
3784 g_object_unref( x );
3785
3786 return( 0 );
3787 }
3788
3789 int
im_icc_transform(VipsImage * in,VipsImage * out,const char * input_profile_filename,const char * output_profile_filename,VipsIntent intent)3790 im_icc_transform( VipsImage *in, VipsImage *out,
3791 const char *input_profile_filename,
3792 const char *output_profile_filename,
3793 VipsIntent intent )
3794 {
3795 VipsImage *x;
3796
3797 if( vips_icc_transform( in, &x, output_profile_filename,
3798 "input_profile", input_profile_filename,
3799 "intent", intent,
3800 NULL ) )
3801 return( -1 );
3802 if( vips_image_write( x, out ) ) {
3803 g_object_unref( x );
3804 return( -1 );
3805 }
3806 g_object_unref( x );
3807
3808 return( 0 );
3809 }
3810
3811 int
im_icc_import(VipsImage * in,VipsImage * out,const char * input_profile_filename,VipsIntent intent)3812 im_icc_import( VipsImage *in, VipsImage *out,
3813 const char *input_profile_filename, VipsIntent intent )
3814 {
3815 VipsImage *x;
3816
3817 if( vips_icc_import( in, &x,
3818 "input_profile", input_profile_filename,
3819 "intent", intent,
3820 NULL ) )
3821 return( -1 );
3822 if( vips_image_write( x, out ) ) {
3823 g_object_unref( x );
3824 return( -1 );
3825 }
3826 g_object_unref( x );
3827
3828 return( 0 );
3829 }
3830
3831 int
im_icc_import_embedded(VipsImage * in,VipsImage * out,VipsIntent intent)3832 im_icc_import_embedded( VipsImage *in, VipsImage *out, VipsIntent intent )
3833 {
3834 VipsImage *x;
3835
3836 if( vips_icc_import( in, &x,
3837 "embedded", TRUE,
3838 "intent", intent,
3839 NULL ) )
3840 return( -1 );
3841 if( vips_image_write( x, out ) ) {
3842 g_object_unref( x );
3843 return( -1 );
3844 }
3845 g_object_unref( x );
3846
3847 return( 0 );
3848 }
3849
3850 int
im_icc_export_depth(VipsImage * in,VipsImage * out,int depth,const char * output_profile_filename,VipsIntent intent)3851 im_icc_export_depth( VipsImage *in, VipsImage *out, int depth,
3852 const char *output_profile_filename, VipsIntent intent )
3853 {
3854 VipsImage *x;
3855
3856 if( vips_icc_export( in, &x,
3857 "output_profile", output_profile_filename,
3858 "depth", depth,
3859 "intent", intent,
3860 NULL ) )
3861 return( -1 );
3862 if( vips_image_write( x, out ) ) {
3863 g_object_unref( x );
3864 return( -1 );
3865 }
3866 g_object_unref( x );
3867
3868 return( 0 );
3869 }
3870
3871 /**
3872 * im_LabQ2XYZ:
3873 * @in: input image
3874 * @out: output image
3875 *
3876 * Convert an image from LabQ (Coding == IM_CODING_LABQ) to XYZ.
3877 *
3878 * Returns: 0 on success, -1 on error.
3879 */
3880 int
im_LabQ2XYZ(IMAGE * in,IMAGE * out)3881 im_LabQ2XYZ( IMAGE *in, IMAGE *out )
3882 {
3883 IMAGE *t[1];
3884
3885 if( im_open_local_array( out, t, 1, "im_LabQ2XYZ:1", "p" ) ||
3886 im_LabQ2Lab( in, t[0] ) ||
3887 im_Lab2XYZ( t[0], out ) )
3888 return( -1 );
3889
3890 return( 0 );
3891 }
3892
3893 int
im_Lab2UCS(IMAGE * in,IMAGE * out)3894 im_Lab2UCS( IMAGE *in, IMAGE *out )
3895 {
3896 IMAGE *t[1];
3897
3898 if( im_open_local_array( out, t, 1, "im_Lab2UCS:1", "p" ) ||
3899 im_Lab2LCh( in, t[0] ) ||
3900 im_LCh2UCS( t[0], out ) )
3901 return( -1 );
3902
3903 return( 0 );
3904 }
3905
3906 int
im_UCS2Lab(IMAGE * in,IMAGE * out)3907 im_UCS2Lab( IMAGE *in, IMAGE *out )
3908 {
3909 IMAGE *t[1];
3910
3911 if( im_open_local_array( out, t, 1, "im_UCS2Lab:1", "p" ) ||
3912 im_UCS2LCh( in, t[0] ) ||
3913 im_LCh2Lab( t[0], out ) )
3914 return( -1 );
3915
3916 return( 0 );
3917 }
3918
3919 int
im_UCS2XYZ(IMAGE * in,IMAGE * out)3920 im_UCS2XYZ( IMAGE *in, IMAGE *out )
3921 {
3922 IMAGE *t[1];
3923
3924 if( im_open_local_array( out, t, 1, "im_UCS2XYZ:1", "p" ) ||
3925 im_UCS2Lab( in, t[0] ) ||
3926 im_Lab2XYZ( t[0], out ) )
3927 return( -1 );
3928
3929 return( 0 );
3930 }
3931
3932 int
im_XYZ2UCS(IMAGE * in,IMAGE * out)3933 im_XYZ2UCS( IMAGE *in, IMAGE *out )
3934 {
3935 IMAGE *t[1];
3936
3937 if( im_open_local_array( out, t, 1, "im_XYZ2UCS:1", "p" ) ||
3938 im_XYZ2Lab( in, t[0] ) ||
3939 im_Lab2UCS( t[0], out ) )
3940 return( -1 );
3941
3942 return( 0 );
3943 }
3944
3945 int
im_dE_fromXYZ(IMAGE * in1,IMAGE * in2,IMAGE * out)3946 im_dE_fromXYZ( IMAGE *in1, IMAGE *in2, IMAGE *out )
3947 {
3948 IMAGE *t[2];
3949
3950 if( im_open_local_array( out, t, 2, "im_dE_fromXYZ:1", "p" ) ||
3951 im_XYZ2Lab( in1, t[0] ) ||
3952 im_XYZ2Lab( in2, t[1] ) ||
3953 im_dE_fromLab( t[0], t[1], out ) )
3954 return( -1 );
3955
3956 return( 0 );
3957 }
3958
3959 int
im_dE_fromLab(IMAGE * in1,IMAGE * in2,IMAGE * out)3960 im_dE_fromLab( IMAGE *in1, IMAGE *in2, IMAGE *out )
3961 {
3962 VipsImage *x;
3963
3964 if( vips_dE76( in1, in2, &x,
3965 NULL ) )
3966 return( -1 );
3967 if( vips_image_write( x, out ) ) {
3968 g_object_unref( x );
3969 return( -1 );
3970 }
3971 g_object_unref( x );
3972
3973 return( 0 );
3974 }
3975
3976 int
im_dECMC_fromLab(IMAGE * in1,IMAGE * in2,IMAGE * out)3977 im_dECMC_fromLab( IMAGE *in1, IMAGE *in2, IMAGE *out )
3978 {
3979 VipsImage *x;
3980
3981 if( vips_dECMC( in1, in2, &x,
3982 NULL ) )
3983 return( -1 );
3984 if( vips_image_write( x, out ) ) {
3985 g_object_unref( x );
3986 return( -1 );
3987 }
3988 g_object_unref( x );
3989
3990 return( 0 );
3991 }
3992
3993 int
im_dE00_fromLab(IMAGE * in1,IMAGE * in2,IMAGE * out)3994 im_dE00_fromLab( IMAGE *in1, IMAGE *in2, IMAGE *out )
3995 {
3996 VipsImage *x;
3997
3998 if( vips_dE00( in1, in2, &x,
3999 NULL ) )
4000 return( -1 );
4001 if( vips_image_write( x, out ) ) {
4002 g_object_unref( x );
4003 return( -1 );
4004 }
4005 g_object_unref( x );
4006
4007 return( 0 );
4008 }
4009
4010 int
im_icc_ac2rc(VipsImage * in,VipsImage * out,const char * profile_filename)4011 im_icc_ac2rc( VipsImage *in, VipsImage *out, const char *profile_filename )
4012 {
4013 VipsImage *x;
4014
4015 if( vips_icc_ac2rc( in, &x, profile_filename ) )
4016 return( -1 );
4017 if( vips_image_write( x, out ) ) {
4018 g_object_unref( x );
4019 return( -1 );
4020 }
4021 g_object_unref( x );
4022
4023 return( 0 );
4024 }
4025
4026 int
im_quadratic(IMAGE * in,IMAGE * out,IMAGE * coeff)4027 im_quadratic( IMAGE *in, IMAGE *out, IMAGE *coeff )
4028 {
4029 VipsImage *x;
4030
4031 if( vips_quadratic( in, &x, coeff,
4032 NULL ) )
4033 return( -1 );
4034 if( vips_image_write( x, out ) ) {
4035 g_object_unref( x );
4036 return( -1 );
4037 }
4038 g_object_unref( x );
4039
4040 return( 0 );
4041 }
4042
4043 int
im_maxpos_vec(VipsImage * im,int * xpos,int * ypos,double * maxima,int n)4044 im_maxpos_vec( VipsImage *im, int *xpos, int *ypos, double *maxima, int n )
4045 {
4046 double max;
4047 VipsArrayDouble *out_array;
4048 VipsArrayInt *x_array;
4049 VipsArrayInt *y_array;
4050
4051 if( vips_max( im, &max,
4052 "size", n,
4053 "out_array", &out_array,
4054 "x_array", &x_array,
4055 "y_array", &y_array,
4056 NULL ) )
4057 return( -1 );
4058
4059 memcpy( xpos, VIPS_ARRAY_ADDR( x_array, 0 ), n * sizeof( int ) );
4060 memcpy( ypos, VIPS_ARRAY_ADDR( y_array, 0 ), n * sizeof( int ) );
4061 memcpy( maxima, VIPS_ARRAY_ADDR( out_array, 0 ), n * sizeof( double ) );
4062
4063 vips_area_unref( VIPS_AREA( out_array ) );
4064 vips_area_unref( VIPS_AREA( x_array ) );
4065 vips_area_unref( VIPS_AREA( y_array ) );
4066
4067 return( 0 );
4068 }
4069
4070 int
im_minpos_vec(VipsImage * im,int * xpos,int * ypos,double * minima,int n)4071 im_minpos_vec( VipsImage *im, int *xpos, int *ypos, double *minima, int n )
4072 {
4073 double min;
4074 VipsArrayDouble *out_array;
4075 VipsArrayInt *x_array;
4076 VipsArrayInt *y_array;
4077
4078 if( vips_min( im, &min,
4079 "size", n,
4080 "out_array", &out_array,
4081 "x_array", &x_array,
4082 "y_array", &y_array,
4083 NULL ) )
4084 return( -1 );
4085
4086 memcpy( xpos, VIPS_ARRAY_ADDR( x_array, 0 ), n * sizeof( int ) );
4087 memcpy( ypos, VIPS_ARRAY_ADDR( y_array, 0 ), n * sizeof( int ) );
4088 memcpy( minima, VIPS_ARRAY_ADDR( out_array, 0 ), n * sizeof( double ) );
4089
4090 vips_area_unref( VIPS_AREA( out_array ) );
4091 vips_area_unref( VIPS_AREA( x_array ) );
4092 vips_area_unref( VIPS_AREA( y_array ) );
4093
4094 return( 0 );
4095 }
4096
4097 int
im_cross_phase(IMAGE * in1,IMAGE * in2,IMAGE * out)4098 im_cross_phase( IMAGE *in1, IMAGE *in2, IMAGE *out )
4099 {
4100 VipsImage *x;
4101
4102 if( vips_call( "cross_phase", in1, in2, &x, NULL ) )
4103 return( -1 );
4104
4105 if( vips_image_write( x, out ) ) {
4106 g_object_unref( x );
4107 return( -1 );
4108 }
4109 g_object_unref( x );
4110
4111 return( 0 );
4112 }
4113
4114 int
im_maplut(IMAGE * in,IMAGE * out,IMAGE * lut)4115 im_maplut( IMAGE *in, IMAGE *out, IMAGE *lut )
4116 {
4117 VipsImage *x;
4118
4119 if( vips_maplut( in, &x, lut, NULL ) )
4120 return( -1 );
4121
4122 if( vips_image_write( x, out ) ) {
4123 g_object_unref( x );
4124 return( -1 );
4125 }
4126 g_object_unref( x );
4127
4128 return( 0 );
4129 }
4130
4131 int
im_ismonotonic(IMAGE * lut,int * out)4132 im_ismonotonic( IMAGE *lut, int *out )
4133 {
4134 gboolean monotonic;
4135
4136 if( vips_hist_ismonotonic( lut, &monotonic, NULL ) )
4137 return( -1 );
4138
4139 *out = monotonic ? 255 : 0;
4140
4141 return( 0 );
4142 }
4143
4144 int
im_histcum(IMAGE * in,IMAGE * out)4145 im_histcum( IMAGE *in, IMAGE *out )
4146 {
4147 VipsImage *x;
4148
4149 if( vips_hist_cum( in, &x, NULL ) )
4150 return( -1 );
4151
4152 if( vips_image_write( x, out ) ) {
4153 g_object_unref( x );
4154 return( -1 );
4155 }
4156 g_object_unref( x );
4157
4158 return( 0 );
4159 }
4160
4161 int
im_histnorm(IMAGE * in,IMAGE * out)4162 im_histnorm( IMAGE *in, IMAGE *out )
4163 {
4164 VipsImage *x;
4165
4166 if( vips_hist_norm( in, &x, NULL ) )
4167 return( -1 );
4168
4169 if( vips_image_write( x, out ) ) {
4170 g_object_unref( x );
4171 return( -1 );
4172 }
4173 g_object_unref( x );
4174
4175 return( 0 );
4176 }
4177
4178 int
im_histeq(IMAGE * in,IMAGE * out)4179 im_histeq( IMAGE *in, IMAGE *out )
4180 {
4181 IMAGE *t1;
4182
4183 if( !(t1 = im_open_local( out, "im_histeq", "p" )) ||
4184 im_histcum( in, t1 ) ||
4185 im_histnorm( t1, out ) )
4186 return( -1 );
4187
4188 return( 0 );
4189 }
4190
4191 int
im_heq(VipsImage * in,VipsImage * out,int bandno)4192 im_heq( VipsImage *in, VipsImage *out, int bandno )
4193 {
4194 VipsImage *x;
4195
4196 if( vips_hist_equal( in, &x, "band", bandno, NULL ) )
4197 return( -1 );
4198
4199 if( vips_image_write( x, out ) ) {
4200 g_object_unref( x );
4201 return( -1 );
4202 }
4203 g_object_unref( x );
4204
4205 return( 0 );
4206 }
4207
4208 int
im_hist(IMAGE * in,IMAGE * out,int bandno)4209 im_hist( IMAGE *in, IMAGE *out, int bandno )
4210 {
4211 IMAGE *hist;
4212
4213 if( !(hist = im_open_local( out, "im_hist", "p" )) ||
4214 im_histgr( in, hist, bandno ) ||
4215 im_histplot( hist, out ) )
4216 return( -1 );
4217
4218 return( 0 );
4219 }
4220
4221 int
im_histgr(IMAGE * in,IMAGE * out,int bandno)4222 im_histgr( IMAGE *in, IMAGE *out, int bandno )
4223 {
4224 VipsImage *x;
4225
4226 if( vips_hist_find( in, &x,
4227 "band", bandno,
4228 NULL ) )
4229 return( -1 );
4230
4231 if( vips_image_write( x, out ) ) {
4232 g_object_unref( x );
4233 return( -1 );
4234 }
4235 g_object_unref( x );
4236
4237 return( 0 );
4238 }
4239
4240 int
im_stdif(IMAGE * in,IMAGE * out,double a,double m0,double b,double s0,int width,int height)4241 im_stdif( IMAGE *in, IMAGE *out,
4242 double a, double m0, double b, double s0,
4243 int width, int height )
4244 {
4245 VipsImage *x;
4246
4247 if( vips_stdif( in, &x, width, height,
4248 "a", a,
4249 "b", b,
4250 "m0", m0,
4251 "s0", s0,
4252 NULL ) )
4253 return( -1 );
4254
4255 if( vips_image_write( x, out ) ) {
4256 g_object_unref( x );
4257 return( -1 );
4258 }
4259 g_object_unref( x );
4260
4261 return( 0 );
4262 }
4263
4264 int
im_lhisteq(VipsImage * in,VipsImage * out,int width,int height)4265 im_lhisteq( VipsImage *in, VipsImage *out, int width, int height )
4266 {
4267 VipsImage *x;
4268
4269 if( vips_hist_local( in, &x, width, height, NULL ) )
4270 return( -1 );
4271
4272 if( vips_image_write( x, out ) ) {
4273 g_object_unref( x );
4274 return( -1 );
4275 }
4276 g_object_unref( x );
4277
4278 return( 0 );
4279 }
4280
4281 int
im_histnD(VipsImage * in,VipsImage * out,int bins)4282 im_histnD( VipsImage *in, VipsImage *out, int bins )
4283 {
4284 VipsImage *x;
4285
4286 if( vips_hist_find_ndim( in, &x,
4287 "bins", bins,
4288 NULL ) )
4289 return( -1 );
4290
4291 if( vips_image_write( x, out ) ) {
4292 g_object_unref( x );
4293 return( -1 );
4294 }
4295 g_object_unref( x );
4296
4297 return( 0 );
4298 }
4299
4300 int
im_hist_indexed(VipsImage * index,VipsImage * value,VipsImage * out)4301 im_hist_indexed( VipsImage *index, VipsImage *value, VipsImage *out )
4302 {
4303 VipsImage *x;
4304
4305 if( vips_hist_find_indexed( value, index, &x, NULL ) )
4306 return( -1 );
4307
4308 if( vips_image_write( x, out ) ) {
4309 g_object_unref( x );
4310 return( -1 );
4311 }
4312 g_object_unref( x );
4313
4314 return( 0 );
4315 }
4316
4317 int
im_project(IMAGE * in,IMAGE * hout,IMAGE * vout)4318 im_project( IMAGE *in, IMAGE *hout, IMAGE *vout )
4319 {
4320 VipsImage *x, *y;
4321
4322 if( vips_project( in, &x, &y, NULL ) )
4323 return( -1 );
4324
4325 if( vips_image_write( x, hout ) ) {
4326 g_object_unref( x );
4327 g_object_unref( y );
4328 return( -1 );
4329 }
4330 g_object_unref( x );
4331
4332 if( vips_image_write( y, vout ) ) {
4333 g_object_unref( y );
4334 return( -1 );
4335 }
4336 g_object_unref( y );
4337
4338 return( 0 );
4339 }
4340
4341 int
im_profile(IMAGE * in,IMAGE * out,int dir)4342 im_profile( IMAGE *in, IMAGE *out, int dir )
4343 {
4344 VipsImage *columns, *rows;
4345 VipsImage *t1, *t2;
4346
4347 if( vips_profile( in, &columns, &rows, NULL ) )
4348 return( -1 );
4349 if( dir == 0 ) {
4350 t1 = columns;
4351 g_object_unref( rows );
4352 }
4353 else {
4354 t1 = rows;
4355 g_object_unref( columns );
4356 }
4357
4358 if( vips_cast( t1, &t2, VIPS_FORMAT_USHORT, NULL ) ) {
4359 g_object_unref( t1 );
4360 return( -1 );
4361 }
4362 g_object_unref( t1 );
4363
4364 if( vips_image_write( t2, out ) ) {
4365 g_object_unref( t2 );
4366 return( -1 );
4367 }
4368 g_object_unref( t2 );
4369
4370 return( 0 );
4371 }
4372
4373 int
im_erode(IMAGE * in,IMAGE * out,INTMASK * mask)4374 im_erode( IMAGE *in, IMAGE *out, INTMASK *mask )
4375 {
4376 VipsImage *t1, *t2;
4377
4378 if( !(t1 = vips_image_new()) ||
4379 im_imask2vips( mask, t1 ) )
4380 return( -1 );
4381
4382 if( vips_morph( in, &t2, t1, VIPS_OPERATION_MORPHOLOGY_ERODE,
4383 NULL ) ) {
4384 g_object_unref( t1 );
4385 return( -1 );
4386 }
4387 g_object_unref( t1 );
4388
4389 if( vips_image_write( t2, out ) ) {
4390 g_object_unref( t2 );
4391 return( -1 );
4392 }
4393 g_object_unref( t2 );
4394
4395 return( 0 );
4396 }
4397
4398 int
im_erode_raw(IMAGE * in,IMAGE * out,INTMASK * m)4399 im_erode_raw( IMAGE *in, IMAGE *out, INTMASK *m )
4400 {
4401 return( im_erode( in, out, m ) );
4402 }
4403
4404 int
im_dilate(IMAGE * in,IMAGE * out,INTMASK * mask)4405 im_dilate( IMAGE *in, IMAGE *out, INTMASK *mask )
4406 {
4407 VipsImage *t1, *t2;
4408
4409 if( !(t1 = vips_image_new()) ||
4410 im_imask2vips( mask, t1 ) )
4411 return( -1 );
4412
4413 if( vips_morph( in, &t2, t1, VIPS_OPERATION_MORPHOLOGY_DILATE,
4414 NULL ) ) {
4415 g_object_unref( t1 );
4416 return( -1 );
4417 }
4418 g_object_unref( t1 );
4419
4420 if( vips_image_write( t2, out ) ) {
4421 g_object_unref( t2 );
4422 return( -1 );
4423 }
4424 g_object_unref( t2 );
4425
4426 return( 0 );
4427 }
4428
4429 int
im_dilate_raw(IMAGE * in,IMAGE * out,INTMASK * m)4430 im_dilate_raw( IMAGE *in, IMAGE *out, INTMASK *m )
4431 {
4432 return( im_dilate( in, out, m ) );
4433 }
4434
4435 int
im_mpercent(IMAGE * in,double percent,int * out)4436 im_mpercent( IMAGE *in, double percent, int *out )
4437 {
4438 if( vips_percent( in, percent * 100.0, out, NULL ) )
4439 return( -1 );
4440
4441 return( 0 );
4442 }
4443
4444 int
im_mpercent_hist(IMAGE * in,double percent,int * out)4445 im_mpercent_hist( IMAGE *in, double percent, int *out )
4446 {
4447 /* Hard to do this in a wrapper.
4448 */
4449 vips_error( "im_mpercent_hist", "%s", _( "no compat implemented" ) );
4450
4451 return( -1 );
4452 }
4453
4454 int
im_hsp(IMAGE * in,IMAGE * ref,IMAGE * out)4455 im_hsp( IMAGE *in, IMAGE *ref, IMAGE *out )
4456 {
4457 IMAGE *t[3];
4458
4459 if( im_open_local_array( out, t, 3, "im_hsp", "p" ) ||
4460 im_histgr( in, t[0], -1 ) ||
4461 im_histgr( ref, t[1], -1 ) ||
4462 im_histspec( t[0], t[1], t[2] ) ||
4463 im_maplut( in, out, t[2] ) )
4464 return( -1 );
4465
4466 return( 0 );
4467 }
4468
4469 static int
match(VipsImage * in,VipsImage * ref,VipsImage * out)4470 match( VipsImage *in, VipsImage *ref, VipsImage *out )
4471 {
4472 VipsImage *x;
4473
4474 if( vips_hist_match( in, ref, &x, NULL ) )
4475 return( -1 );
4476
4477 if( vips_image_write( x, out ) ) {
4478 g_object_unref( x );
4479 return( -1 );
4480 }
4481 g_object_unref( x );
4482
4483 return( 0 );
4484 }
4485
4486 int
im_histspec(IMAGE * in,IMAGE * ref,IMAGE * out)4487 im_histspec( IMAGE *in, IMAGE *ref, IMAGE *out )
4488 {
4489 IMAGE *t[5];
4490 guint64 px;
4491 int fmt;
4492
4493 if( im_check_uint( "im_histspec", in ) ||
4494 im_check_uint( "im_histspec", ref ) )
4495 return( -1 );
4496
4497 if( im_open_local_array( out, t, 5, "im_histspec", "p" ) ||
4498 im_histeq( in, t[0] ) ||
4499 im_histeq( ref, t[2] ) ||
4500 match( t[0], t[2], t[4] ) )
4501 return( -1 );
4502
4503 px = VIPS_IMAGE_N_PELS( t[4] );
4504 if( px <= 256 )
4505 fmt = IM_BANDFMT_UCHAR;
4506 else if( px <= 65536 )
4507 fmt = IM_BANDFMT_USHORT;
4508 else
4509 fmt = IM_BANDFMT_UINT;
4510
4511 if( im_clip2fmt( t[4], out, fmt ) )
4512 return( -1 );
4513
4514 return( 0 );
4515 }
4516
4517 int
im_falsecolour(IMAGE * in,IMAGE * out)4518 im_falsecolour( IMAGE *in, IMAGE *out )
4519 {
4520 VipsImage *x;
4521
4522 if( vips_falsecolour( in, &x, NULL ) )
4523 return( -1 );
4524
4525 if( vips_image_write( x, out ) ) {
4526 g_object_unref( x );
4527 return( -1 );
4528 }
4529 g_object_unref( x );
4530
4531 return( 0 );
4532 }
4533
4534 int
im_gammacorrect(IMAGE * in,IMAGE * out,double exponent)4535 im_gammacorrect( IMAGE *in, IMAGE *out, double exponent )
4536 {
4537 VipsImage *x;
4538
4539 if( vips_gamma( in, &x,
4540 "exponent", 1.0 / exponent,
4541 NULL ) )
4542 return( -1 );
4543
4544 if( vips_image_write( x, out ) ) {
4545 g_object_unref( x );
4546 return( -1 );
4547 }
4548 g_object_unref( x );
4549
4550 return( 0 );
4551 }
4552
4553 /* This is used by the carrierwave shrinker to cache the
4554 * output of shrink before doing the final affine.
4555 *
4556 * We use the vips8 threaded tilecache to avoid a deadlock: suppose thread1,
4557 * evaluating the top block of the output is delayed, and thread2, evaluating
4558 * the second block gets here first (this can happen on a heavily-loaded
4559 * system).
4560 *
4561 * With an unthreaded tilecache (as we had before), thread2 will get
4562 * the cache lock and start evaling the second block of the shrink. When it
4563 * reaches the png reader it will stall until the first block has been used ...
4564 * but it never will, since thread1 will block on this cache lock.
4565 *
4566 * This function is only used in this place (I think), so it's OK to
4567 * hard-wire this to be a sequential threaded cache.
4568 */
4569 int
im_tile_cache(IMAGE * in,IMAGE * out,int tile_width,int tile_height,int max_tiles)4570 im_tile_cache( IMAGE *in, IMAGE *out,
4571 int tile_width, int tile_height, int max_tiles )
4572 {
4573 VipsImage *x;
4574
4575 if( vips_tilecache( in, &x,
4576 "tile_width", tile_width,
4577 "tile_height", tile_height,
4578 "max_tiles", max_tiles,
4579 "access", VIPS_ACCESS_SEQUENTIAL,
4580 "threaded", TRUE,
4581 NULL ) )
4582 return( -1 );
4583
4584 if( vips_image_write( x, out ) ) {
4585 g_object_unref( x );
4586 return( -1 );
4587 }
4588 g_object_unref( x );
4589
4590 return( 0 );
4591 }
4592
4593 /* This is the one used by nip2's menu for caching images. Random access and
4594 * persistent.
4595 */
4596 int
im_tile_cache_random(IMAGE * in,IMAGE * out,int tile_width,int tile_height,int max_tiles)4597 im_tile_cache_random( IMAGE *in, IMAGE *out,
4598 int tile_width, int tile_height, int max_tiles )
4599 {
4600 VipsImage *x;
4601
4602 if( vips_tilecache( in, &x,
4603 "tile_width", tile_width,
4604 "tile_height", tile_height,
4605 "max_tiles", max_tiles,
4606 "access", VIPS_ACCESS_RANDOM,
4607 "persistent", TRUE,
4608 "threaded", TRUE,
4609 NULL ) )
4610 return( -1 );
4611
4612 if( vips_image_write( x, out ) ) {
4613 g_object_unref( x );
4614 return( -1 );
4615 }
4616 g_object_unref( x );
4617
4618 return( 0 );
4619 }
4620
4621 static int
im__affinei(VipsImage * in,VipsImage * out,VipsInterpolate * interpolate,VipsTransformation * trn)4622 im__affinei( VipsImage *in, VipsImage *out,
4623 VipsInterpolate *interpolate, VipsTransformation *trn )
4624 {
4625 VipsImage **t = (VipsImage **)
4626 vips_object_local_array( VIPS_OBJECT( out ), 2 );
4627
4628 VipsArea *oarea;
4629 gboolean repack;
4630
4631 oarea = VIPS_AREA( vips_array_int_newv( 4,
4632 trn->oarea.left, trn->oarea.top,
4633 trn->oarea.width, trn->oarea.height ) );
4634
4635 /* vips7 affine would repack labq and im_benchmark() depends upon
4636 * this.
4637 */
4638 repack = in->Coding == IM_CODING_LABQ;
4639
4640 if( vips_affine( in, &t[0],
4641 trn->a, trn->b, trn->c, trn->d,
4642 "interpolate", interpolate,
4643 "oarea", oarea,
4644 "odx", trn->odx,
4645 "ody", trn->ody,
4646 NULL ) ) {
4647 vips_area_unref( oarea );
4648 return( -1 );
4649 }
4650 vips_area_unref( oarea );
4651 in = t[0];
4652
4653 if( repack ) {
4654 if( vips_colourspace( in, &t[1],
4655 VIPS_INTERPRETATION_LABQ, NULL ) )
4656 return( -1 );
4657 in = t[1];
4658 }
4659
4660 if( vips_image_write( in, out ) )
4661 return( -1 );
4662
4663 return( 0 );
4664 }
4665
4666 int
im_affinei(VipsImage * in,VipsImage * out,VipsInterpolate * interpolate,double a,double b,double c,double d,double odx,double ody,int ox,int oy,int ow,int oh)4667 im_affinei( VipsImage *in, VipsImage *out, VipsInterpolate *interpolate,
4668 double a, double b, double c, double d, double odx, double ody,
4669 int ox, int oy, int ow, int oh )
4670 {
4671 VipsTransformation trn;
4672
4673 trn.iarea.left = 0;
4674 trn.iarea.top = 0;
4675 trn.iarea.width = in->Xsize;
4676 trn.iarea.height = in->Ysize;
4677
4678 trn.oarea.left = ox;
4679 trn.oarea.top = oy;
4680 trn.oarea.width = ow;
4681 trn.oarea.height = oh;
4682
4683 trn.a = a;
4684 trn.b = b;
4685 trn.c = c;
4686 trn.d = d;
4687 trn.idx = 0;
4688 trn.idy = 0;
4689 trn.odx = odx;
4690 trn.ody = ody;
4691
4692 return( im__affinei( in, out, interpolate, &trn ) );
4693 }
4694
4695 int
im_affinei_all(VipsImage * in,VipsImage * out,VipsInterpolate * interpolate,double a,double b,double c,double d,double odx,double ody)4696 im_affinei_all( VipsImage *in, VipsImage *out, VipsInterpolate *interpolate,
4697 double a, double b, double c, double d, double odx, double ody )
4698 {
4699 VipsTransformation trn;
4700
4701 trn.iarea.left = 0;
4702 trn.iarea.top = 0;
4703 trn.iarea.width = in->Xsize;
4704 trn.iarea.height = in->Ysize;
4705 trn.a = a;
4706 trn.b = b;
4707 trn.c = c;
4708 trn.d = d;
4709 trn.idx = 0;
4710 trn.idy = 0;
4711 trn.odx = odx;
4712 trn.ody = ody;
4713
4714 vips__transform_set_area( &trn );
4715
4716 return( im__affinei( in, out, interpolate, &trn ) );
4717 }
4718
4719 /* Still needed by some parts of mosaic.
4720 */
4721 int
vips__affine(VipsImage * in,VipsImage * out,VipsTransformation * trn)4722 vips__affine( VipsImage *in, VipsImage *out, VipsTransformation *trn )
4723 {
4724 return( im__affinei( in, out,
4725 vips_interpolate_bilinear_static(), trn ) );
4726 }
4727
4728 int
im_copy_file(IMAGE * in,IMAGE * out)4729 im_copy_file( IMAGE *in, IMAGE *out )
4730 {
4731 VipsImage *x;
4732
4733 if( vips_copy_file( in, &x, NULL ) )
4734 return( -1 );
4735 if( vips_image_write( x, out ) ) {
4736 g_object_unref( x );
4737 return( -1 );
4738 }
4739 g_object_unref( x );
4740
4741 return( 0 );
4742 }
4743
4744 int
im_video_v4l1(IMAGE * im,const char * device,int channel,int brightness,int colour,int contrast,int hue,int ngrabs)4745 im_video_v4l1( IMAGE *im, const char *device,
4746 int channel, int brightness, int colour, int contrast, int hue,
4747 int ngrabs )
4748 {
4749 im_error( "im_video_v4l1",
4750 "%s", _( "compiled without im_video_v4l1 support" ) );
4751 return( -1 );
4752 }
4753
4754 int
im_fwfft(IMAGE * in,IMAGE * out)4755 im_fwfft( IMAGE *in, IMAGE *out )
4756 {
4757 VipsImage *x;
4758
4759 if( vips_fwfft( in, &x, NULL ) )
4760 return( -1 );
4761
4762 if( vips_image_write( x, out ) ) {
4763 g_object_unref( x );
4764 return( -1 );
4765 }
4766 g_object_unref( x );
4767
4768 return( 0 );
4769 }
4770
4771 int
im_invfft(IMAGE * in,IMAGE * out)4772 im_invfft( IMAGE *in, IMAGE *out )
4773 {
4774 VipsImage *x;
4775
4776 if( vips_invfft( in, &x, NULL ) )
4777 return( -1 );
4778
4779 if( vips_image_write( x, out ) ) {
4780 g_object_unref( x );
4781 return( -1 );
4782 }
4783 g_object_unref( x );
4784
4785 return( 0 );
4786 }
4787
4788 int
im_invfftr(IMAGE * in,IMAGE * out)4789 im_invfftr( IMAGE *in, IMAGE *out )
4790 {
4791 VipsImage *x;
4792
4793 if( vips_invfft( in, &x,
4794 "real", TRUE,
4795 NULL ) )
4796 return( -1 );
4797
4798 if( vips_image_write( x, out ) ) {
4799 g_object_unref( x );
4800 return( -1 );
4801 }
4802 g_object_unref( x );
4803
4804 return( 0 );
4805 }
4806
4807 int
im_freqflt(IMAGE * in,IMAGE * mask,IMAGE * out)4808 im_freqflt( IMAGE *in, IMAGE *mask, IMAGE *out )
4809 {
4810 VipsImage *x;
4811
4812 if( vips_freqmult( in, mask, &x, NULL ) )
4813 return( -1 );
4814
4815 if( vips_image_write( x, out ) ) {
4816 g_object_unref( x );
4817 return( -1 );
4818 }
4819 g_object_unref( x );
4820
4821 return( 0 );
4822 }
4823
4824 int
im_disp_ps(IMAGE * in,IMAGE * out)4825 im_disp_ps( IMAGE *in, IMAGE *out )
4826 {
4827 VipsImage *t;
4828
4829 if( vips_spectrum( in, &t, NULL ) )
4830 return( -1 );
4831 if( vips_image_write( t, out ) ) {
4832 g_object_unref( t );
4833 return( -1 );
4834 }
4835 g_object_unref( t );
4836
4837 return( 0 );
4838 }
4839
4840 int
im_fractsurf(IMAGE * out,int size,double frd)4841 im_fractsurf( IMAGE *out, int size, double frd )
4842 {
4843 VipsImage *t;
4844
4845 if( vips_fractsurf( &t, size, size, frd, NULL ) )
4846 return( -1 );
4847 if( vips_image_write( t, out ) ) {
4848 g_object_unref( t );
4849 return( -1 );
4850 }
4851 g_object_unref( t );
4852
4853 return( 0 );
4854 }
4855
4856 int
im_phasecor_fft(IMAGE * in1,IMAGE * in2,IMAGE * out)4857 im_phasecor_fft( IMAGE *in1, IMAGE *in2, IMAGE *out )
4858 {
4859 VipsImage *x;
4860
4861 if( vips_phasecor( in1, in2, &x, NULL ) )
4862 return( -1 );
4863
4864 if( vips_image_write( x, out ) ) {
4865 g_object_unref( x );
4866 return( -1 );
4867 }
4868 g_object_unref( x );
4869
4870 return( 0 );
4871 }
4872
4873 int
im_cntlines(VipsImage * im,double * nolines,int flag)4874 im_cntlines( VipsImage *im, double *nolines, int flag )
4875 {
4876 return( vips_countlines( im, nolines,
4877 flag == 0 ?
4878 VIPS_DIRECTION_HORIZONTAL : VIPS_DIRECTION_VERTICAL,
4879 NULL ) );
4880 }
4881
4882 int
im_label_regions(IMAGE * test,IMAGE * mask,int * segments)4883 im_label_regions( IMAGE *test, IMAGE *mask, int *segments )
4884 {
4885 VipsImage *x;
4886
4887 if( vips_labelregions( test, &x, "segments", segments, NULL ) )
4888 return( -1 );
4889
4890 if( vips_image_write( x, mask ) ) {
4891 g_object_unref( x );
4892 return( -1 );
4893 }
4894 g_object_unref( x );
4895
4896 return( 0 );
4897 }
4898
4899 int
im_rank(IMAGE * in,IMAGE * out,int width,int height,int index)4900 im_rank( IMAGE *in, IMAGE *out, int width, int height, int index )
4901 {
4902 VipsImage *x;
4903
4904 if( vips_rank( in, &x, width, height, index, NULL ) )
4905 return( -1 );
4906
4907 if( vips_image_write( x, out ) ) {
4908 g_object_unref( x );
4909 return( -1 );
4910 }
4911 g_object_unref( x );
4912
4913 return( 0 );
4914 }
4915
4916 int
im_rank_raw(IMAGE * in,IMAGE * out,int width,int height,int index)4917 im_rank_raw( IMAGE *in, IMAGE *out, int width, int height, int index )
4918 {
4919 im_error( "im_rank_raw", "no compat function" );
4920 return( -1 );
4921 }
4922
4923 int
im_draw_circle(VipsImage * image,int x,int y,int radius,gboolean fill,VipsPel * ink)4924 im_draw_circle( VipsImage *image,
4925 int x, int y, int radius, gboolean fill, VipsPel *ink )
4926 {
4927 double *vec;
4928 int n;
4929
4930 if( !(vec = vips__ink_to_vector( "im_draw_circle", image, ink, &n )) )
4931 return( -1 );
4932
4933 return( vips_draw_circle( image, vec, n, x, y, radius,
4934 "fill", fill,
4935 NULL ) );
4936 }
4937
4938 int
im_draw_line(VipsImage * image,int x1,int y1,int x2,int y2,VipsPel * ink)4939 im_draw_line( VipsImage *image, int x1, int y1, int x2, int y2, VipsPel *ink )
4940 {
4941 double *vec;
4942 int n;
4943
4944 if( !(vec = vips__ink_to_vector( "im_draw_line", image, ink, &n )) )
4945 return( -1 );
4946
4947 return( vips_draw_line( image, vec, n, x1, y1, x2, y2, NULL ) );
4948 }
4949
4950 typedef struct _Line {
4951 VipsPlotFn plot;
4952 void *a;
4953 void *b;
4954 void *c;
4955 } Line;
4956
4957 static void
draw_line_wrapper(VipsImage * image,int x,int y,void * client)4958 draw_line_wrapper( VipsImage *image, int x, int y, void *client )
4959 {
4960 Line *line = (Line *) client;
4961
4962 line->plot( image, x, y, line->a, line->b, line->c );
4963 }
4964
4965 int
im_draw_line_user(VipsImage * image,int x1,int y1,int x2,int y2,VipsPlotFn plot,void * a,void * b,void * c)4966 im_draw_line_user( VipsImage *image,
4967 int x1, int y1, int x2, int y2,
4968 VipsPlotFn plot, void *a, void *b, void *c )
4969 {
4970 Line line;
4971
4972 line.plot = plot;
4973 line.a = a;
4974 line.b = b;
4975 line.c = c;
4976
4977 vips__draw_line_direct( image, x1, y1, x2, y2,
4978 draw_line_wrapper, &line );
4979
4980 return( 0 );
4981 }
4982
4983 int
im_draw_mask(VipsImage * image,VipsImage * mask,int x,int y,VipsPel * ink)4984 im_draw_mask( VipsImage *image, VipsImage *mask, int x, int y, VipsPel *ink )
4985 {
4986 /* Direct call, since this has to be very quick.
4987 */
4988 return( vips__draw_mask_direct( image, mask, ink, x, y ) );
4989 }
4990
4991 int
im_draw_image(VipsImage * image,VipsImage * sub,int x,int y)4992 im_draw_image( VipsImage *image, VipsImage *sub, int x, int y )
4993 {
4994 return( vips_draw_image( image, sub, x, y, NULL ) );
4995 }
4996
4997 int
im_draw_rect(IMAGE * image,int left,int top,int width,int height,int fill,VipsPel * ink)4998 im_draw_rect( IMAGE *image,
4999 int left, int top, int width, int height, int fill, VipsPel *ink )
5000 {
5001 double *vec;
5002 int n;
5003
5004 if( !(vec = vips__ink_to_vector( "im_draw_rect", image, ink, &n )) )
5005 return( -1 );
5006
5007 return( vips_draw_rect( image, vec, n, left, top, width, height,
5008 "fill", fill,
5009 NULL ) );
5010 }
5011
5012 int
im_draw_point(VipsImage * image,int x,int y,VipsPel * ink)5013 im_draw_point( VipsImage *image, int x, int y, VipsPel *ink )
5014 {
5015 double *vec;
5016 int n;
5017
5018 if( !(vec = vips__ink_to_vector( "im_draw_rect", image, ink, &n )) )
5019 return( -1 );
5020
5021 return( vips_draw_point( image, vec, n, x, y, NULL ) );
5022 }
5023
5024 int
im_draw_smudge(VipsImage * im,int left,int top,int width,int height)5025 im_draw_smudge( VipsImage *im, int left, int top, int width, int height )
5026 {
5027 return( vips_draw_smudge( im, left, top, width, height, NULL ) );
5028 }
5029
5030 int
im_read_point(VipsImage * image,int x,int y,VipsPel * ink)5031 im_read_point( VipsImage *image, int x, int y, VipsPel *ink )
5032 {
5033 double *vector;
5034 int n;
5035 VipsPel *pixel_vector;
5036
5037 if( vips_getpoint( image, &vector, &n, x, y, NULL ) )
5038 return( -1 );
5039
5040 if( !(pixel_vector = vips__vector_to_ink( "im_read_point",
5041 image, vector, NULL, n )) ) {
5042 g_free( vector );
5043 return( -1 );
5044 }
5045
5046 memcpy( ink, pixel_vector, VIPS_IMAGE_SIZEOF_PEL( image ) );
5047
5048 g_free( vector );
5049
5050 return( 0 );
5051 }
5052
5053 int
im_draw_flood(IMAGE * image,int x,int y,VipsPel * ink,Rect * dout)5054 im_draw_flood( IMAGE *image, int x, int y, VipsPel *ink, Rect *dout )
5055 {
5056 double *vec;
5057 int n;
5058 int left;
5059 int top;
5060 int width;
5061 int height;
5062
5063 if( !(vec = vips__ink_to_vector( "im_draw_flood", image, ink, &n )) )
5064 return( -1 );
5065
5066 if( vips_draw_flood( image, vec, n, x, y,
5067 "left", &left,
5068 "top", &top,
5069 "width", &width,
5070 "height", &height,
5071 NULL ) )
5072 return( -1 );
5073
5074 if( dout ) {
5075 dout->left = left;
5076 dout->top = top;
5077 dout->width = width;
5078 dout->height = height;
5079 }
5080
5081 return( 0 );
5082 }
5083
5084 int
im_draw_flood_blob(IMAGE * image,int x,int y,VipsPel * ink,Rect * dout)5085 im_draw_flood_blob( IMAGE *image, int x, int y, VipsPel *ink, Rect *dout )
5086 {
5087 double *vec;
5088 int n;
5089 int left;
5090 int top;
5091 int width;
5092 int height;
5093
5094 if( !(vec = vips__ink_to_vector( "im_draw_flood", image, ink, &n )) )
5095 return( -1 );
5096
5097 if( vips_draw_flood( image, vec, n, x, y,
5098 "equal", TRUE,
5099 "left", &left,
5100 "top", &top,
5101 "width", &width,
5102 "height", &height,
5103 NULL ) )
5104 return( -1 );
5105
5106 if( dout ) {
5107 dout->left = left;
5108 dout->top = top;
5109 dout->width = width;
5110 dout->height = height;
5111 }
5112
5113 return( 0 );
5114 }
5115
5116 int
im_draw_flood_other(IMAGE * image,IMAGE * test,int x,int y,int serial,Rect * dout)5117 im_draw_flood_other( IMAGE *image,
5118 IMAGE *test, int x, int y, int serial, Rect *dout )
5119 {
5120 int left;
5121 int top;
5122 int width;
5123 int height;
5124
5125 if( vips_draw_flood1( image, serial, x, y,
5126 "test", test,
5127 "equal", TRUE,
5128 "left", &left,
5129 "top", &top,
5130 "width", &width,
5131 "height", &height,
5132 NULL ) )
5133 return( -1 );
5134
5135 if( dout ) {
5136 dout->left = left;
5137 dout->top = top;
5138 dout->width = width;
5139 dout->height = height;
5140 }
5141
5142 return( 0 );
5143 }
5144
5145 int
im_lineset(IMAGE * in,IMAGE * out,IMAGE * mask,IMAGE * ink,int n,int * x1v,int * y1v,int * x2v,int * y2v)5146 im_lineset( IMAGE *in, IMAGE *out, IMAGE *mask, IMAGE *ink,
5147 int n, int *x1v, int *y1v, int *x2v, int *y2v )
5148 {
5149 Rect mask_rect;
5150 int i;
5151
5152 if( mask->Bands != 1 || mask->BandFmt != IM_BANDFMT_UCHAR ||
5153 mask->Coding != IM_CODING_NONE ) {
5154 im_error( "im_lineset",
5155 "%s", _( "mask image not 1 band 8 bit uncoded" ) );
5156 return( -1 );
5157 }
5158 if( ink->Bands != in->Bands || ink->BandFmt != in->BandFmt ||
5159 ink->Coding != in->Coding ) {
5160 im_error( "im_lineset",
5161 "%s", _( "ink image does not match in image" ) );
5162 return( -1 );
5163 }
5164 if( ink->Xsize != 1 || ink->Ysize != 1 ) {
5165 im_error( "im_lineset", "%s", _( "ink image not 1x1 pixels" ) );
5166 return( -1 );
5167 }
5168
5169 /* Copy the image then fastline to it ... this will render to a "t"
5170 * usually.
5171 */
5172 if( vips_image_write( in, out ) )
5173 return( -1 );
5174
5175 mask_rect.left = mask->Xsize / 2;
5176 mask_rect.top = mask->Ysize / 2;
5177 mask_rect.width = mask->Xsize;
5178 mask_rect.height = mask->Ysize;
5179
5180 if( im_incheck( ink ) ||
5181 im_incheck( mask ) )
5182 return( -1 );
5183
5184 for( i = 0; i < n; i++ ) {
5185 if( im_fastlineuser( out, x1v[i], y1v[i], x2v[i], y2v[i],
5186 (VipsPlotFn) im_plotmask, ink->data, mask->data, &mask_rect ) )
5187 return( -1 );
5188 }
5189
5190 return( 0 );
5191 }
5192
5193 int
im_match_linear_search(IMAGE * ref,IMAGE * sec,IMAGE * out,int xr1,int yr1,int xs1,int ys1,int xr2,int yr2,int xs2,int ys2,int hwindowsize,int hsearchsize)5194 im_match_linear_search( IMAGE *ref, IMAGE *sec, IMAGE *out,
5195 int xr1, int yr1, int xs1, int ys1,
5196 int xr2, int yr2, int xs2, int ys2,
5197 int hwindowsize, int hsearchsize )
5198 {
5199 VipsImage *x;
5200
5201 if( vips_match( ref, sec, &x,
5202 xr1, yr1, xs1, ys1, xr2, yr2, xs2, ys2,
5203 "search", TRUE,
5204 "hwindow", hwindowsize,
5205 "harea", hsearchsize,
5206 NULL ) )
5207 return( -1 );
5208
5209 if( vips_image_write( x, out ) ) {
5210 g_object_unref( x );
5211 return( -1 );
5212 }
5213 g_object_unref( x );
5214
5215 return( 0 );
5216 }
5217
5218 int
im_match_linear(IMAGE * ref,IMAGE * sec,IMAGE * out,int xr1,int yr1,int xs1,int ys1,int xr2,int yr2,int xs2,int ys2)5219 im_match_linear( IMAGE *ref, IMAGE *sec, IMAGE *out,
5220 int xr1, int yr1, int xs1, int ys1,
5221 int xr2, int yr2, int xs2, int ys2 )
5222 {
5223 VipsImage *x;
5224
5225 if( vips_match( ref, sec, &x,
5226 xr1, yr1, xs1, ys1, xr2, yr2, xs2, ys2,
5227 NULL ) )
5228 return( -1 );
5229
5230 if( vips_image_write( x, out ) ) {
5231 g_object_unref( x );
5232 return( -1 );
5233 }
5234 g_object_unref( x );
5235
5236 return( 0 );
5237 }
5238
5239 int
im_global_balance(IMAGE * in,IMAGE * out,double gamma)5240 im_global_balance( IMAGE *in, IMAGE *out, double gamma )
5241 {
5242 VipsImage *x;
5243
5244 if( vips_globalbalance( in, &x,
5245 "gamma", gamma,
5246 "int_output", TRUE,
5247 NULL ) )
5248 return( -1 );
5249
5250 if( vips_image_write( x, out ) ) {
5251 g_object_unref( x );
5252 return( -1 );
5253 }
5254 g_object_unref( x );
5255
5256 return( 0 );
5257 }
5258
5259 int
im_histplot(IMAGE * in,IMAGE * out)5260 im_histplot( IMAGE *in, IMAGE *out )
5261 {
5262 VipsImage *x;
5263
5264 if( vips_hist_plot( in, &x, NULL ) )
5265 return( -1 );
5266
5267 if( vips_image_write( x, out ) ) {
5268 g_object_unref( x );
5269 return( -1 );
5270 }
5271 g_object_unref( x );
5272
5273 return( 0 );
5274 }
5275
5276 int
im_global_balancef(IMAGE * in,IMAGE * out,double gamma)5277 im_global_balancef( IMAGE *in, IMAGE *out, double gamma )
5278 {
5279 VipsImage *x;
5280
5281 if( vips_globalbalance( in, &x,
5282 "gamma", gamma,
5283 NULL ) )
5284 return( -1 );
5285
5286 if( vips_image_write( x, out ) ) {
5287 g_object_unref( x );
5288 return( -1 );
5289 }
5290 g_object_unref( x );
5291
5292 return( 0 );
5293 }
5294
5295 int
im_remosaic(IMAGE * in,IMAGE * out,const char * old_str,const char * new_str)5296 im_remosaic( IMAGE *in, IMAGE *out, const char *old_str, const char *new_str )
5297 {
5298 VipsImage *x;
5299
5300 if( vips_remosaic( in, &x, old_str, new_str, NULL ) )
5301 return( -1 );
5302
5303 if( vips_image_write( x, out ) ) {
5304 g_object_unref( x );
5305 return( -1 );
5306 }
5307 g_object_unref( x );
5308
5309 return( 0 );
5310 }
5311
5312 int
im_lrmosaic(IMAGE * ref,IMAGE * sec,IMAGE * out,int bandno,int xref,int yref,int xsec,int ysec,int hwindowsize,int hsearchsize,int balancetype,int mwidth)5313 im_lrmosaic( IMAGE *ref, IMAGE *sec, IMAGE *out,
5314 int bandno,
5315 int xref, int yref, int xsec, int ysec,
5316 int hwindowsize, int hsearchsize,
5317 int balancetype,
5318 int mwidth )
5319 {
5320 VipsImage *x;
5321
5322 if( vips_mosaic( ref, sec, &x, VIPS_DIRECTION_HORIZONTAL,
5323 xref, yref, xsec, ysec,
5324 "hwindow", hwindowsize,
5325 "harea", hsearchsize,
5326 "mblend", mwidth,
5327 NULL ) )
5328 return( -1 );
5329 if( vips_image_write( x, out ) ) {
5330 g_object_unref( x );
5331 return( -1 );
5332 }
5333 g_object_unref( x );
5334
5335 return( 0 );
5336 }
5337
5338 int
im_lrmosaic1(IMAGE * ref,IMAGE * sec,IMAGE * out,int bandno,int xr1,int yr1,int xs1,int ys1,int xr2,int yr2,int xs2,int ys2,int hwindowsize,int hsearchsize,int balancetype,int mwidth)5339 im_lrmosaic1( IMAGE *ref, IMAGE *sec, IMAGE *out,
5340 int bandno,
5341 int xr1, int yr1, int xs1, int ys1,
5342 int xr2, int yr2, int xs2, int ys2,
5343 int hwindowsize, int hsearchsize,
5344 int balancetype,
5345 int mwidth )
5346 {
5347 VipsImage *x;
5348
5349 if( vips_mosaic1( ref, sec, &x, VIPS_DIRECTION_HORIZONTAL,
5350 xr1, yr1, xs1, ys1, xr2, yr2, xs2, ys2,
5351 "search", TRUE,
5352 "bandno", bandno,
5353 "hwindow", hwindowsize,
5354 "harea", hsearchsize,
5355 "mblend", mwidth,
5356 NULL ) )
5357 return( -1 );
5358 if( vips_image_write( x, out ) ) {
5359 g_object_unref( x );
5360 return( -1 );
5361 }
5362 g_object_unref( x );
5363
5364 return( 0 );
5365 }
5366
5367 int
im_tbmosaic(IMAGE * ref,IMAGE * sec,IMAGE * out,int bandno,int xref,int yref,int xsec,int ysec,int hwindowsize,int hsearchsize,int balancetype,int mwidth)5368 im_tbmosaic( IMAGE *ref, IMAGE *sec, IMAGE *out,
5369 int bandno,
5370 int xref, int yref, int xsec, int ysec,
5371 int hwindowsize, int hsearchsize,
5372 int balancetype,
5373 int mwidth )
5374 {
5375 VipsImage *x;
5376
5377 if( vips_mosaic( ref, sec, &x, VIPS_DIRECTION_VERTICAL,
5378 xref, yref, xsec, ysec,
5379 "hwindow", hwindowsize,
5380 "harea", hsearchsize,
5381 "mblend", mwidth,
5382 NULL ) )
5383 return( -1 );
5384 if( vips_image_write( x, out ) ) {
5385 g_object_unref( x );
5386 return( -1 );
5387 }
5388 g_object_unref( x );
5389
5390 return( 0 );
5391 }
5392
5393 int
im_tbmosaic1(IMAGE * ref,IMAGE * sec,IMAGE * out,int bandno,int xr1,int yr1,int xs1,int ys1,int xr2,int yr2,int xs2,int ys2,int hwindowsize,int hsearchsize,int balancetype,int mwidth)5394 im_tbmosaic1( IMAGE *ref, IMAGE *sec, IMAGE *out,
5395 int bandno,
5396 int xr1, int yr1, int xs1, int ys1,
5397 int xr2, int yr2, int xs2, int ys2,
5398 int hwindowsize, int hsearchsize,
5399 int balancetype,
5400 int mwidth )
5401 {
5402 VipsImage *x;
5403
5404 if( vips_mosaic1( ref, sec, &x, VIPS_DIRECTION_VERTICAL,
5405 xr1, yr1, xs1, ys1, xr2, yr2, xs2, ys2,
5406 "search", TRUE,
5407 "bandno", bandno,
5408 "hwindow", hwindowsize,
5409 "harea", hsearchsize,
5410 "mblend", mwidth,
5411 NULL ) )
5412 return( -1 );
5413 if( vips_image_write( x, out ) ) {
5414 g_object_unref( x );
5415 return( -1 );
5416 }
5417 g_object_unref( x );
5418
5419 return( 0 );
5420 }
5421
5422 int
im_correl(VipsImage * ref,VipsImage * sec,int xref,int yref,int xsec,int ysec,int hwindowsize,int hsearchsize,double * correlation,int * x,int * y)5423 im_correl( VipsImage *ref, VipsImage *sec,
5424 int xref, int yref, int xsec, int ysec,
5425 int hwindowsize, int hsearchsize,
5426 double *correlation, int *x, int *y )
5427 {
5428 return( vips__correl( ref, sec, xref, yref, xsec, ysec,
5429 hwindowsize, hsearchsize, correlation, x, y ) );
5430 }
5431
5432 int
im_lrmerge(IMAGE * ref,IMAGE * sec,IMAGE * out,int dx,int dy,int mwidth)5433 im_lrmerge( IMAGE *ref, IMAGE *sec, IMAGE *out,
5434 int dx, int dy, int mwidth )
5435 {
5436 VipsImage *x;
5437
5438 if( vips_merge( ref, sec, &x, VIPS_DIRECTION_HORIZONTAL, dx, dy,
5439 "mblend", mwidth,
5440 NULL ) )
5441 return( -1 );
5442 if( vips_image_write( x, out ) ) {
5443 g_object_unref( x );
5444 return( -1 );
5445 }
5446 g_object_unref( x );
5447
5448 return( 0 );
5449 }
5450
5451 int
im_lrmerge1(IMAGE * ref,IMAGE * sec,IMAGE * out,int xr1,int yr1,int xs1,int ys1,int xr2,int yr2,int xs2,int ys2,int mwidth)5452 im_lrmerge1( IMAGE *ref, IMAGE *sec, IMAGE *out,
5453 int xr1, int yr1, int xs1, int ys1,
5454 int xr2, int yr2, int xs2, int ys2,
5455 int mwidth )
5456 {
5457 VipsImage *x;
5458
5459 if( vips_mosaic1( ref, sec, &x, VIPS_DIRECTION_HORIZONTAL,
5460 xr1, yr1, xs1, ys1, xr2, yr2, xs2, ys2,
5461 "mblend", mwidth,
5462 NULL ) )
5463 return( -1 );
5464 if( vips_image_write( x, out ) ) {
5465 g_object_unref( x );
5466 return( -1 );
5467 }
5468 g_object_unref( x );
5469
5470 return( 0 );
5471 }
5472
5473 int
im_tbmerge(IMAGE * ref,IMAGE * sec,IMAGE * out,int dx,int dy,int mwidth)5474 im_tbmerge( IMAGE *ref, IMAGE *sec, IMAGE *out,
5475 int dx, int dy, int mwidth )
5476 {
5477 VipsImage *x;
5478
5479 if( vips_merge( ref, sec, &x, VIPS_DIRECTION_VERTICAL, dx, dy,
5480 "mblend", mwidth,
5481 NULL ) )
5482 return( -1 );
5483 if( vips_image_write( x, out ) ) {
5484 g_object_unref( x );
5485 return( -1 );
5486 }
5487 g_object_unref( x );
5488
5489 return( 0 );
5490 }
5491
5492 int
im_tbmerge1(IMAGE * ref,IMAGE * sec,IMAGE * out,int xr1,int yr1,int xs1,int ys1,int xr2,int yr2,int xs2,int ys2,int mwidth)5493 im_tbmerge1( IMAGE *ref, IMAGE *sec, IMAGE *out,
5494 int xr1, int yr1, int xs1, int ys1,
5495 int xr2, int yr2, int xs2, int ys2,
5496 int mwidth )
5497 {
5498 VipsImage *x;
5499
5500 if( vips_mosaic1( ref, sec, &x, VIPS_DIRECTION_VERTICAL,
5501 xr1, yr1, xs1, ys1, xr2, yr2, xs2, ys2,
5502 "mblend", mwidth,
5503 NULL ) )
5504 return( -1 );
5505 if( vips_image_write( x, out ) ) {
5506 g_object_unref( x );
5507 return( -1 );
5508 }
5509 g_object_unref( x );
5510
5511 return( 0 );
5512 }
5513
5514 /* The common part of most binary conversion
5515 * operators. We:
5516 *
5517 * - check in and out
5518 * - cast in1 and in2 up to a common format
5519 * - equalise bands
5520 * - make an input array
5521 * - return the matched images in vec[0] and vec[1]
5522 *
5523 * A left-over, remove soon.
5524 */
5525 IMAGE **
im__insert_base(const char * domain,IMAGE * in1,IMAGE * in2,IMAGE * out)5526 im__insert_base( const char *domain,
5527 IMAGE *in1, IMAGE *in2, IMAGE *out )
5528 {
5529 IMAGE *t[4];
5530 IMAGE **vec;
5531
5532 if( im_piocheck( in1, out ) ||
5533 im_pincheck( in2 ) ||
5534 im_check_bands_1orn( domain, in1, in2 ) ||
5535 im_check_coding_known( domain, in1 ) ||
5536 im_check_coding_same( domain, in1, in2 ) )
5537 return( NULL );
5538
5539 /* Cast our input images up to a common format and bands.
5540 */
5541 if( im_open_local_array( out, t, 4, domain, "p" ) ||
5542 im__formatalike( in1, in2, t[0], t[1] ) ||
5543 im__bandalike( domain, t[0], t[1], t[2], t[3] ) ||
5544 !(vec = im_allocate_input_array( out, t[2], t[3], NULL )) )
5545 return( NULL );
5546
5547 /* Generate the output.
5548 */
5549 if( im_cp_descv( out, vec[0], vec[1], NULL ) ||
5550 im_demand_hint_array( out, IM_SMALLTILE, vec ) )
5551 return( NULL );
5552
5553 return( vec );
5554 }
5555
5556 /**
5557 * im_insertset:
5558 * @main: big image
5559 * @sub: small image
5560 * @out: output image
5561 * @n: number of positions
5562 * @x: left positions of @sub
5563 * @y: top positions of @sub
5564 *
5565 * Insert @sub repeatedly into @main at the positions listed in the arrays @x,
5566 * @y of length @n. @out is the same
5567 * size as @main. @sub is clipped against the edges of @main.
5568 *
5569 * This operation is fast for large @n, but will use a memory buffer the size
5570 * of @out. It's useful for things like making scatter plots.
5571 *
5572 * If the number of bands differs, one of the images
5573 * must have one band. In this case, an n-band image is formed from the
5574 * one-band image by joining n copies of the one-band image together, and then
5575 * the two n-band images are operated upon.
5576 *
5577 * The two input images are cast up to the smallest common type (see table
5578 * Smallest common format in
5579 * <link linkend="VIPS-arithmetic">arithmetic</link>).
5580 *
5581 * See also: im_insert(), im_lrjoin().
5582 *
5583 * Returns: 0 on success, -1 on error
5584 */
5585 int
im_insertset(IMAGE * main,IMAGE * sub,IMAGE * out,int n,int * x,int * y)5586 im_insertset( IMAGE *main, IMAGE *sub, IMAGE *out, int n, int *x, int *y )
5587 {
5588 IMAGE **vec;
5589 IMAGE *t;
5590 int i;
5591
5592 if( !(vec = im__insert_base( "im_insert", main, sub, out )) )
5593 return( -1 );
5594
5595 /* Copy to a memory image, zap that, then copy to out.
5596 */
5597 if( !(t = im_open_local( out, "im_insertset", "t" )) ||
5598 im_copy( vec[0], t ) )
5599 return( -1 );
5600
5601 for( i = 0; i < n; i++ )
5602 if( im_insertplace( t, vec[1], x[i], y[i] ) )
5603 return( -1 );
5604
5605 if( im_copy( t, out ) )
5606 return( -1 );
5607
5608 return( 0 );
5609 }
5610
5611 /* We had this entry point in earlier libvipses, hilariously.
5612 */
5613 int
vips__init(const char * argv0)5614 vips__init( const char *argv0 )
5615 {
5616 return( vips_init( argv0 ) );
5617 }
5618
5619 int
im_greyc_mask(IMAGE * in,IMAGE * out,IMAGE * mask,int iterations,float amplitude,float sharpness,float anisotropy,float alpha,float sigma,float dl,float da,float gauss_prec,int interpolation,int fast_approx)5620 im_greyc_mask( IMAGE *in, IMAGE *out, IMAGE *mask,
5621 int iterations,
5622 float amplitude, float sharpness, float anisotropy,
5623 float alpha, float sigma,
5624 float dl, float da, float gauss_prec,
5625 int interpolation, int fast_approx )
5626 {
5627 vips_error( "im_greyc_mask",
5628 "This function is no longer in the core library" );
5629
5630 return( -1 );
5631 }
5632
5633 int
vips_check_imask(const char * domain,INTMASK * mask)5634 vips_check_imask( const char *domain, INTMASK *mask )
5635 {
5636 if( !mask ||
5637 mask->xsize > 1000 ||
5638 mask->ysize > 1000 ||
5639 mask->xsize <= 0 ||
5640 mask->ysize <= 0 ||
5641 mask->scale == 0 ||
5642 !mask->coeff ) {
5643 vips_error( domain, "%s", _( "nonsense mask parameters" ) );
5644 return( -1 );
5645 }
5646
5647 return( 0 );
5648 }
5649
5650 int
vips_check_dmask(const char * domain,DOUBLEMASK * mask)5651 vips_check_dmask( const char *domain, DOUBLEMASK *mask )
5652 {
5653 if( !mask ||
5654 mask->xsize > 1000 ||
5655 mask->ysize > 1000 ||
5656 mask->xsize <= 0 ||
5657 mask->ysize <= 0 ||
5658 mask->scale == 0 ||
5659 !mask->coeff ) {
5660 vips_error( domain, "%s", _( "nonsense mask parameters" ) );
5661 return( -1 );
5662 }
5663
5664 return( 0 );
5665 }
5666
5667 int
vips_check_dmask_1d(const char * domain,DOUBLEMASK * mask)5668 vips_check_dmask_1d( const char *domain, DOUBLEMASK *mask )
5669 {
5670 if( vips_check_dmask( domain, mask ) )
5671 return( -1 );
5672 if( mask->xsize != 1 &&
5673 mask->ysize != 1 ) {
5674 vips_error( domain, "%s", _( "mask must be 1D" ) );
5675 return( -1 );
5676 }
5677
5678 return( 0 );
5679 }
5680
5681 GOptionGroup *
vips_get_option_group(void)5682 vips_get_option_group( void )
5683 {
5684 static GOptionGroup *option_group = NULL;
5685
5686 if( !option_group ) {
5687 option_group = g_option_group_new( "vips",
5688 _( "VIPS Options" ), _( "Show VIPS options" ),
5689 NULL, NULL );
5690 vips_add_option_entries( option_group );
5691 }
5692
5693 return( option_group );
5694 }
5695
5696 /* We used to use this for system() back in the day. But it's awkward to make
5697 * it work properly on win32, so this is now deprecated.
5698 */
5699 FILE *
vips_popenf(const char * fmt,const char * mode,...)5700 vips_popenf( const char *fmt, const char *mode, ... )
5701 {
5702 vips_error( "popenf", "%s", _( "deprecated" ) );
5703 return( NULL );
5704 }
5705
5706 /* We used to use this for getpoint(), but since it was the only caller in
5707 * vips8 it's now deprecated.
5708 */
5709 double *
vips__ink_to_vector(const char * domain,VipsImage * im,VipsPel * ink,int * n)5710 vips__ink_to_vector( const char *domain, VipsImage *im, VipsPel *ink, int *n )
5711 {
5712 VipsImage **t = (VipsImage **)
5713 vips_object_local_array( VIPS_OBJECT( im ), 6 );
5714
5715 double *result;
5716
5717 #ifdef VIPS_DEBUG
5718 printf( "vips__ink_to_vector: starting\n" );
5719 #endif /*VIPS_DEBUG*/
5720
5721 /* Wrap a VipsImage around ink.
5722 */
5723 t[0] = vips_image_new_from_memory( ink, VIPS_IMAGE_SIZEOF_PEL( im ),
5724 1, 1, VIPS_IMAGE_SIZEOF_PEL( im ), VIPS_FORMAT_UCHAR );
5725 if( vips_copy( t[0], &t[1],
5726 "bands", im->Bands,
5727 "format", im->BandFmt,
5728 "coding", im->Coding,
5729 "interpretation", im->Type,
5730 NULL ) )
5731 return( NULL );
5732
5733 /* The image may be coded .. unpack to double.
5734 */
5735 if( vips_image_decode( t[1], &t[2] ) ||
5736 vips_cast( t[2], &t[3], VIPS_FORMAT_DOUBLE, NULL ) )
5737 return( NULL );
5738
5739 /* To a mem buffer, then copy to out.
5740 */
5741 if( !(t[4] = vips_image_new_memory()) ||
5742 vips_image_write( t[3], t[4] ) )
5743 return( NULL );
5744
5745 if( !(result = VIPS_ARRAY( im, t[4]->Bands, double )) )
5746 return( NULL );
5747 memcpy( result, t[4]->data, VIPS_IMAGE_SIZEOF_PEL( t[4] ) );
5748 *n = t[4]->Bands;
5749
5750 #ifdef VIPS_DEBUG
5751 {
5752 int i;
5753
5754 printf( "vips__ink_to_vector:\n" );
5755 printf( "\tink = " );
5756 for( i = 0; i < n; i++ )
5757 printf( "%d ", ink[i] );
5758 printf( "\n" );
5759
5760 printf( "\tvec = " );
5761 for( i = 0; i < *n; i++ )
5762 printf( "%g ", result[i] );
5763 printf( "\n" );
5764 }
5765 #endif /*VIPS_DEBUG*/
5766
5767 return( result );
5768 }
5769
5770