1 /* base class for all arithmetic operations
2  *
3  * properties:
4  * 	- one output image, one or more inputs
5  * 	- cast input images to match
6  * 	- output is large enough to hold output values (value preserving)
7  * 	- point-to-point operations (ie. each pixel depends only on the
8  * 	  corresponding pixel in the input)
9  * 	- LUT-able: ie. arithmetic (image) can be exactly replaced by
10  * 	  maplut (image, arithmetic (lut)) for 8/16 bit int images
11  */
12 
13 /*
14 
15     Copyright (C) 1991-2005 The National Gallery
16 
17     This library is free software; you can redistribute it and/or
18     modify it under the terms of the GNU Lesser General Public
19     License as published by the Free Software Foundation; either
20     version 2.1 of the License, or (at your option) any later version.
21 
22     This library is distributed in the hope that it will be useful,
23     but WITHOUT ANY WARRANTY; without even the implied warranty of
24     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25     Lesser General Public License for more details.
26 
27     You should have received a copy of the GNU Lesser General Public
28     License along with this library; if not, write to the Free Software
29     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
30     02110-1301  USA
31 
32  */
33 
34 /*
35 
36     These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
37 
38  */
39 
40 /*
41 #define DEBUG
42  */
43 
44 #ifdef HAVE_CONFIG_H
45 #include <config.h>
46 #endif /*HAVE_CONFIG_H*/
47 #include <vips/intl.h>
48 
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <math.h>
52 
53 #include <vips/vips.h>
54 #include <vips/internal.h>
55 
56 #include "parithmetic.h"
57 
58 /**
59  * SECTION: arithmetic
60  * @short_description: operations which perform pixel arithmetic, trig, log, statistics
61  * @stability: Stable
62  * @include: vips/vips.h
63  *
64  * These operations perform pixel arithmetic, that is, they perform an
65  * arithmetic operation, such as addition, on every pixel in an image or a
66  * pair of images. All (except in a few cases noted below) will work with
67  * images of any type or any mixture of types, of any size and of any number
68  * of bands.
69  *
70  * For binary operations, if the number of bands differs, one of the images
71  * must have one band. In this case, an n-band image is formed from the
72  * one-band image by joining n copies of the one-band image together, and then
73  * the two n-band images are operated upon.
74  *
75  * In the same way, for operations that take an array constant, such as
76  * vips_remainder_const(), you can mix single-element arrays or single-band
77  * images freely.
78  *
79  * Arithmetic operations try to preserve precision by increasing the number of
80  * bits in the output image when necessary. Generally, this follows the ANSI C
81  * conventions for type promotion, so multiplying two
82  * #VIPS_FORMAT_UCHAR images together, for example, produces a
83  * #VIPS_FORMAT_USHORT image, and taking the vips_cos() of a
84  * #VIPS_FORMAT_USHORT image produces #VIPS_FORMAT_FLOAT image.
85  *
86  * For binary arithmetic operations, type promotion occurs in two stages.
87  * First, the two input images are cast up to the smallest common format,
88  * that is, the type with the smallest range that can represent the full
89  * range of both inputs. This conversion can be represented as a table:
90  *
91  * <table>
92  *   <title>Smallest common format</title>
93  *   <tgroup cols='10' align='left' colsep='1' rowsep='1'>
94  *     <thead>
95  *       <row>
96  *         <entry>@in2/@in1</entry>
97  *         <entry>uchar</entry>
98  *         <entry>char</entry>
99  *         <entry>ushort</entry>
100  *         <entry>short</entry>
101  *         <entry>uint</entry>
102  *         <entry>int</entry>
103  *         <entry>float</entry>
104  *         <entry>double</entry>
105  *         <entry>complex</entry>
106  *         <entry>double complex</entry>
107  *       </row>
108  *     </thead>
109  *     <tbody>
110  *       <row>
111  *         <entry>uchar</entry>
112  *         <entry>ushort</entry>
113  *         <entry>short</entry>
114  *         <entry>ushort</entry>
115  *         <entry>short</entry>
116  *         <entry>uint</entry>
117  *         <entry>int</entry>
118  *         <entry>float</entry>
119  *         <entry>double</entry>
120  *         <entry>complex</entry>
121  *         <entry>double complex</entry>
122  *       </row>
123  *       <row>
124  *         <entry>char</entry>
125  *         <entry>short</entry>
126  *         <entry>short</entry>
127  *         <entry>short</entry>
128  *         <entry>short</entry>
129  *         <entry>int</entry>
130  *         <entry>int</entry>
131  *         <entry>float</entry>
132  *         <entry>double</entry>
133  *         <entry>complex</entry>
134  *         <entry>double complex</entry>
135  *       </row>
136  *       <row>
137  *         <entry>ushort</entry>
138  *         <entry>ushort</entry>
139  *         <entry>short</entry>
140  *         <entry>ushort</entry>
141  *         <entry>short</entry>
142  *         <entry>uint</entry>
143  *         <entry>int</entry>
144  *         <entry>float</entry>
145  *         <entry>double</entry>
146  *         <entry>complex</entry>
147  *         <entry>double complex</entry>
148  *       </row>
149  *       <row>
150  *         <entry>short</entry>
151  *         <entry>short</entry>
152  *         <entry>short</entry>
153  *         <entry>short</entry>
154  *         <entry>short</entry>
155  *         <entry>int</entry>
156  *         <entry>int</entry>
157  *         <entry>float</entry>
158  *         <entry>double</entry>
159  *         <entry>complex</entry>
160  *         <entry>double complex</entry>
161  *       </row>
162  *       <row>
163  *         <entry>uint</entry>
164  *         <entry>uint</entry>
165  *         <entry>int</entry>
166  *         <entry>uint</entry>
167  *         <entry>int</entry>
168  *         <entry>uint</entry>
169  *         <entry>int</entry>
170  *         <entry>float</entry>
171  *         <entry>double</entry>
172  *         <entry>complex</entry>
173  *         <entry>double complex</entry>
174  *       </row>
175  *       <row>
176  *         <entry>int</entry>
177  *         <entry>int</entry>
178  *         <entry>int</entry>
179  *         <entry>int</entry>
180  *         <entry>int</entry>
181  *         <entry>int</entry>
182  *         <entry>int</entry>
183  *         <entry>float</entry>
184  *         <entry>double</entry>
185  *         <entry>complex</entry>
186  *         <entry>double complex</entry>
187  *       </row>
188  *       <row>
189  *         <entry>float</entry>
190  *         <entry>float</entry>
191  *         <entry>float</entry>
192  *         <entry>float</entry>
193  *         <entry>float</entry>
194  *         <entry>float</entry>
195  *         <entry>float</entry>
196  *         <entry>float</entry>
197  *         <entry>double</entry>
198  *         <entry>complex</entry>
199  *         <entry>double complex</entry>
200  *       </row>
201  *       <row>
202  *         <entry>double</entry>
203  *         <entry>double</entry>
204  *         <entry>double</entry>
205  *         <entry>double</entry>
206  *         <entry>double</entry>
207  *         <entry>double</entry>
208  *         <entry>double</entry>
209  *         <entry>double</entry>
210  *         <entry>double</entry>
211  *         <entry>double complex</entry>
212  *         <entry>double complex</entry>
213  *       </row>
214  *       <row>
215  *         <entry>complex</entry>
216  *         <entry>complex</entry>
217  *         <entry>complex</entry>
218  *         <entry>complex</entry>
219  *         <entry>complex</entry>
220  *         <entry>complex</entry>
221  *         <entry>complex</entry>
222  *         <entry>complex</entry>
223  *         <entry>double complex</entry>
224  *         <entry>complex</entry>
225  *         <entry>double complex</entry>
226  *       </row>
227  *       <row>
228  *         <entry>double complex</entry>
229  *         <entry>double complex</entry>
230  *         <entry>double complex</entry>
231  *         <entry>double complex</entry>
232  *         <entry>double complex</entry>
233  *         <entry>double complex</entry>
234  *         <entry>double complex</entry>
235  *         <entry>double complex</entry>
236  *         <entry>double complex</entry>
237  *         <entry>double complex</entry>
238  *         <entry>double complex</entry>
239  *       </row>
240  *     </tbody>
241  *   </tgroup>
242  * </table>
243  *
244  * In the second stage, the operation is performed between the two identical
245  * types to form the output. The details vary between operations, but
246  * generally the principle is that the output type should be large enough to
247  * represent the whole range of possible values, except that int never becomes
248  * float.
249  */
250 
251 G_DEFINE_ABSTRACT_TYPE( VipsArithmetic, vips_arithmetic, VIPS_TYPE_OPERATION );
252 
253 /* Save a bit of typing.
254  */
255 #define UC VIPS_FORMAT_UCHAR
256 #define C VIPS_FORMAT_CHAR
257 #define US VIPS_FORMAT_USHORT
258 #define S VIPS_FORMAT_SHORT
259 #define UI VIPS_FORMAT_UINT
260 #define I VIPS_FORMAT_INT
261 #define F VIPS_FORMAT_FLOAT
262 #define X VIPS_FORMAT_COMPLEX
263 #define D VIPS_FORMAT_DOUBLE
264 #define DX VIPS_FORMAT_DPCOMPLEX
265 
266 /* For two integer types, the "largest", ie. one which can represent the
267  * full range of both.
268  */
269 static VipsBandFormat format_largest[6][6] = {
270         /* UC  C   US  S   UI  I */
271 /* UC */ { UC, S,  US, S,  UI, I },
272 /* C */  { S,  C,  I,  S,  I,  I },
273 /* US */ { US, I,  US, I,  UI, I },
274 /* S */  { S,  S,  I,  S,  I,  I },
275 /* UI */ { UI, I,  UI, I,  UI, I },
276 /* I */  { I,  I,  I,  I,  I,  I }
277 };
278 
279 /* For two formats, find one which can represent the full range of both.
280  */
281 static VipsBandFormat
vips_format_common(VipsBandFormat a,VipsBandFormat b)282 vips_format_common( VipsBandFormat a, VipsBandFormat b )
283 {
284 	if( vips_band_format_iscomplex( a ) ||
285 		vips_band_format_iscomplex( b ) ) {
286 		if( a == VIPS_FORMAT_DPCOMPLEX ||
287 			b == VIPS_FORMAT_DPCOMPLEX )
288 			return( VIPS_FORMAT_DPCOMPLEX );
289 		else
290 			return( VIPS_FORMAT_COMPLEX );
291 
292 	}
293 	else if( vips_band_format_isfloat( a ) ||
294 		vips_band_format_isfloat( b ) ) {
295 		if( a == VIPS_FORMAT_DOUBLE ||
296 			b == VIPS_FORMAT_DOUBLE )
297 			return( VIPS_FORMAT_DOUBLE );
298 		else
299 			return( VIPS_FORMAT_FLOAT );
300 	}
301 	else
302 		return( format_largest[a][b] );
303 }
304 
305 int
vips__formatalike_vec(VipsImage ** in,VipsImage ** out,int n)306 vips__formatalike_vec( VipsImage **in, VipsImage **out, int n )
307 {
308 	int i;
309 	VipsBandFormat format;
310 
311 	g_assert( n >= 1 );
312 
313 	format = in[0]->BandFmt;
314 	for( i = 1; i < n; i++ )
315 		format = vips_format_common( format, in[i]->BandFmt );
316 
317 	for( i = 0; i < n; i++ )
318 		if( in[i]->BandFmt == format ) {
319 			/* Already in the right format ... just copy the image
320 			 * pointer and add a ref.
321 			 */
322 			out[i] = in[i];
323 			g_object_ref( in[i] );
324 		}
325 		else {
326 			if( vips_cast( in[i], &out[i], format, NULL ) )
327 				return( -1 );
328 		}
329 
330 	return( 0 );
331 }
332 
333 int
vips__sizealike_vec(VipsImage ** in,VipsImage ** out,int n)334 vips__sizealike_vec( VipsImage **in, VipsImage **out, int n )
335 {
336 	int i;
337 	int width_max;
338 	int height_max;
339 
340 	g_assert( n >= 1 );
341 
342 	width_max = in[0]->Xsize;
343 	height_max = in[0]->Ysize;
344 	for( i = 1; i < n; i++ ) {
345 		width_max = VIPS_MAX( width_max, in[i]->Xsize );
346 		height_max = VIPS_MAX( height_max, in[i]->Ysize );
347 	}
348 
349 	for( i = 0; i < n; i++ )
350 		if( in[i]->Xsize == width_max &&
351 			in[i]->Ysize == height_max ) {
352 			/* Already the right size ... just copy the image
353 			 * pointer and add a ref.
354 			 */
355 			out[i] = in[i];
356 			g_object_ref( in[i] );
357 		}
358 		else {
359 			if( vips_embed( in[i], &out[i],
360 				0, 0, width_max, height_max, NULL ) )
361 				return( -1 );
362 		}
363 
364 	return( 0 );
365 }
366 
367 /* Make an n-band image. Input 1 or n bands.
368  */
369 int
vips__bandup(const char * domain,VipsImage * in,VipsImage ** out,int n)370 vips__bandup( const char *domain, VipsImage *in, VipsImage **out, int n )
371 {
372 	VipsImage **bands;
373 	int i;
374 	int result;
375 
376 	if( in->Bands == n )
377 		return( vips_copy( in, out, NULL ) );
378 	if( in->Bands != 1 ) {
379 		vips_error( domain, _( "not one band or %d bands" ), n );
380 		return( -1 );
381 	}
382 	if( n > VIPS_MAX_COORD ||
383 		n < 1 ) {
384 		vips_error( domain, "%s", _( "bad bands" ) );
385 		return( -1 );
386 	}
387 
388 	if( !(bands = VIPS_ARRAY( NULL, n, VipsImage * )) )
389 		return( -1 );
390 	for( i = 0; i < n; i++ )
391 		bands[i] = in;
392 	result = vips_bandjoin( bands, out, n, NULL );
393 	VIPS_FREE( bands );
394 
395 	return( result );
396 }
397 
398 /* base_bands is the default minimum.
399  *
400  * Handy for example, if you have VipsLinear with
401  * a 3-element vector of constants and a 1-band input image, you need to cast
402  * the image up to three bands.
403  */
404 int
vips__bandalike_vec(const char * domain,VipsImage ** in,VipsImage ** out,int n,int base_bands)405 vips__bandalike_vec( const char *domain,
406 	VipsImage **in, VipsImage **out, int n, int base_bands )
407 {
408 	int i;
409 	int max_bands;
410 	VipsInterpretation interpretation;
411 
412 	g_assert( n >= 1 );
413 
414 	/* We try to set the interpretation of the output images from the
415 	 * interpretation of the n-band input. For example, if we are matching
416 	 * a set of BW images to an RGB image, we want the BW images to be
417 	 * tagged as RGB.
418 	 */
419 	max_bands = base_bands;
420 	interpretation = VIPS_INTERPRETATION_ERROR;
421 	for( i = 0; i < n; i++ ) {
422 		/* >= so we can pick up interpretation if base_bands is equal
423 		 * to the number of bands of the largest image.
424 		 */
425 		if( in[i]->Bands >= max_bands ) {
426 			max_bands = in[i]->Bands;
427 			interpretation = in[i]->Type;
428 		}
429 	}
430 
431 	for( i = 0; i < n; i++ )
432 		if( in[i]->Bands == max_bands ) {
433 			/* Already the right number of bands ... just copy the
434 			 * image pointer and add a ref.
435 			 */
436 			out[i] = in[i];
437 			g_object_ref( in[i] );
438 		}
439 		else {
440 			if( vips__bandup( domain, in[i], &out[i], max_bands ) )
441 				return( -1 );
442 
443 			if( interpretation != VIPS_INTERPRETATION_ERROR )
444 				out[i]->Type = interpretation;
445 		}
446 
447 	return( 0 );
448 }
449 
450 int
vips__formatalike(VipsImage * in1,VipsImage * in2,VipsImage ** out1,VipsImage ** out2)451 vips__formatalike( VipsImage *in1, VipsImage *in2,
452 	VipsImage **out1, VipsImage **out2 )
453 {
454 	VipsImage *in[2];
455 	VipsImage *out[2];
456 
457 	in[0] = in1;
458 	in[1] = in2;
459 
460 	if( vips__formatalike_vec( in, out, 2 ) )
461 		return( -1 );
462 
463 	*out1 = out[0];
464 	*out2 = out[1];
465 
466 	return( 0 );
467 }
468 
469 int
vips__sizealike(VipsImage * in1,VipsImage * in2,VipsImage ** out1,VipsImage ** out2)470 vips__sizealike( VipsImage *in1, VipsImage *in2,
471 	VipsImage **out1, VipsImage **out2 )
472 {
473 	VipsImage *in[2];
474 	VipsImage *out[2];
475 
476 	in[0] = in1;
477 	in[1] = in2;
478 
479 	if( vips__sizealike_vec( in, out, 2 ) )
480 		return( -1 );
481 
482 	*out1 = out[0];
483 	*out2 = out[1];
484 
485 	return( 0 );
486 }
487 
488 int
vips__bandalike(const char * domain,VipsImage * in1,VipsImage * in2,VipsImage ** out1,VipsImage ** out2)489 vips__bandalike( const char *domain,
490 	VipsImage *in1, VipsImage *in2, VipsImage **out1, VipsImage **out2 )
491 {
492 	VipsImage *in[2];
493 	VipsImage *out[2];
494 
495 	in[0] = in1;
496 	in[1] = in2;
497 
498 	if( vips__bandalike_vec( domain, in, out, 2, 1 ) )
499 		return( -1 );
500 
501 	*out1 = out[0];
502 	*out2 = out[1];
503 
504 	return( 0 );
505 }
506 
507 /* Our sequence value.
508  */
509 typedef struct {
510 	VipsArithmetic *arithmetic;
511 
512 	/* Set of input regions.
513 	 */
514 	VipsRegion **ir;
515 
516 	/* For each input, an input pointer.
517 	 */
518 	VipsPel **p;
519 
520 } VipsArithmeticSequence;
521 
522 static int
vips_arithmetic_stop(void * vseq,void * a,void * b)523 vips_arithmetic_stop( void *vseq, void *a, void *b )
524 {
525 	VipsArithmeticSequence *seq = (VipsArithmeticSequence *) vseq;
526 
527         if( seq->ir ) {
528 		int i;
529 
530 		for( i = 0; seq->ir[i]; i++ )
531 			VIPS_UNREF( seq->ir[i] );
532 		VIPS_FREE( seq->ir );
533 	}
534 
535 	VIPS_FREE( seq->p );
536 
537 	VIPS_FREE( seq );
538 
539 	return( 0 );
540 }
541 
542 static void *
vips_arithmetic_start(VipsImage * out,void * a,void * b)543 vips_arithmetic_start( VipsImage *out, void *a, void *b )
544 {
545 	VipsImage **in = (VipsImage **) a;
546 	VipsArithmetic *arithmetic = (VipsArithmetic *) b;
547 
548 	VipsArithmeticSequence *seq;
549 	int i, n;
550 
551 	if( !(seq = VIPS_NEW( NULL, VipsArithmeticSequence )) )
552 		return( NULL );
553 
554 	seq->arithmetic = arithmetic;
555 	seq->ir = NULL;
556 	seq->p = NULL;
557 
558 	/* How many images?
559 	 */
560 	for( n = 0; in[n]; n++ )
561 		;
562 
563 	/* Alocate space for region array.
564 	 */
565 	if( !(seq->ir = VIPS_ARRAY( NULL, n + 1, VipsRegion * )) ) {
566 		vips_arithmetic_stop( seq, NULL, NULL );
567 		return( NULL );
568 	}
569 
570 	/* Create a set of regions.
571 	 */
572 	for( i = 0; i < n; i++ )
573 		if( !(seq->ir[i] = vips_region_new( in[i] )) ) {
574 			vips_arithmetic_stop( seq, NULL, NULL );
575 			return( NULL );
576 		}
577 	seq->ir[n] = NULL;
578 
579 	/* Input pointers.
580 	 */
581 	if( !(seq->p = VIPS_ARRAY( NULL, n + 1, VipsPel * )) ) {
582 		vips_arithmetic_stop( seq, NULL, NULL );
583 		return( NULL );
584 	}
585 
586 	return( seq );
587 }
588 
589 static int
vips_arithmetic_gen(VipsRegion * or,void * vseq,void * a,void * b,gboolean * stop)590 vips_arithmetic_gen( VipsRegion *or,
591 	void *vseq, void *a, void *b, gboolean *stop )
592 {
593 	VipsArithmeticSequence *seq = (VipsArithmeticSequence *) vseq;
594 	VipsRegion **ir = seq->ir;
595 	VipsArithmetic *arithmetic = VIPS_ARITHMETIC( b );
596 	VipsArithmeticClass *class = VIPS_ARITHMETIC_GET_CLASS( arithmetic );
597 	VipsRect *r = &or->valid;
598 
599 	VipsPel *q;
600 	int i, y;
601 
602 	/* Prepare all input regions and make buffer pointers.
603 	 */
604 	if( vips_reorder_prepare_many( or->im, ir, r ) )
605 		return( -1 );
606 	for( i = 0; ir[i]; i++ )
607 		seq->p[i] = (VipsPel *)
608 			VIPS_REGION_ADDR( ir[i], r->left, r->top );
609 	seq->p[i] = NULL;
610 	q = (VipsPel *) VIPS_REGION_ADDR( or, r->left, r->top );
611 
612 	VIPS_GATE_START( "vips_arithmetic_gen: work" );
613 
614 	for( y = 0; y < r->height; y++ ) {
615 		class->process_line( arithmetic, q, seq->p, r->width );
616 
617 		for( i = 0; ir[i]; i++ )
618 			seq->p[i] += VIPS_REGION_LSKIP( ir[i] );
619 		q += VIPS_REGION_LSKIP( or );
620 	}
621 
622 	VIPS_GATE_STOP( "vips_arithmetic_gen: work" );
623 
624 	VIPS_COUNT_PIXELS( or, VIPS_OBJECT_CLASS( class )->nickname );
625 
626 	return( 0 );
627 }
628 
629 static int
vips_arithmetic_build(VipsObject * object)630 vips_arithmetic_build( VipsObject *object )
631 {
632 	VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
633 	VipsArithmetic *arithmetic = VIPS_ARITHMETIC( object );
634 	VipsArithmeticClass *aclass = VIPS_ARITHMETIC_GET_CLASS( arithmetic );
635 
636 	VipsImage **decode;
637 	VipsImage **format;
638 	VipsImage **band;
639 	VipsImage **size;
640 	int i;
641 
642 #ifdef DEBUG
643 	printf( "vips_arithmetic_build: " );
644 	vips_object_print_name( object );
645 	printf( "\n" );
646 #endif /*DEBUG*/
647 
648 	if( VIPS_OBJECT_CLASS( vips_arithmetic_parent_class )->
649 		build( object ) )
650 		return( -1 );
651 
652 	g_object_set( arithmetic, "out", vips_image_new(), NULL );
653 
654 	decode = (VipsImage **)
655 		vips_object_local_array( object, arithmetic->n );
656 	format = (VipsImage **)
657 		vips_object_local_array( object, arithmetic->n );
658 	band = (VipsImage **)
659 		vips_object_local_array( object, arithmetic->n );
660 	size = (VipsImage **)
661 		vips_object_local_array( object, arithmetic->n );
662 
663 	/* Decode RAD/LABQ etc.
664 	 */
665 	for( i = 0; i < arithmetic->n; i++ )
666 		if( vips_image_decode( arithmetic->in[i], &decode[i] ) )
667 			return( -1 );
668 
669 	/* Cast our input images up to a common format, bands and size.
670 	 */
671 	if( vips__formatalike_vec( decode, format, arithmetic->n ) ||
672 		vips__bandalike_vec( class->nickname,
673 			format, band, arithmetic->n, arithmetic->base_bands ) ||
674 		vips__sizealike_vec( band, size, arithmetic->n ) )
675 		return( -1 );
676 
677 	/* Keep a copy of the processed images here for subclasses.
678 	 */
679 	arithmetic->ready = size;
680 
681 	if( vips_image_pipeline_array( arithmetic->out,
682 		VIPS_DEMAND_STYLE_THINSTRIP, arithmetic->ready ) )
683 		return( -1 );
684 
685 	arithmetic->out->Bands = arithmetic->ready[0]->Bands;
686 	if( arithmetic->format != VIPS_FORMAT_NOTSET )
687 		arithmetic->out->BandFmt = arithmetic->format;
688 	else
689 		arithmetic->out->BandFmt =
690 			aclass->format_table[arithmetic->ready[0]->BandFmt];
691 
692 	if( vips_image_generate( arithmetic->out,
693 		vips_arithmetic_start,
694 		vips_arithmetic_gen,
695 		vips_arithmetic_stop,
696 		arithmetic->ready, arithmetic ) )
697 		return( -1 );
698 
699 	return( 0 );
700 }
701 
702 static void
vips_arithmetic_class_init(VipsArithmeticClass * class)703 vips_arithmetic_class_init( VipsArithmeticClass *class )
704 {
705 	GObjectClass *gobject_class = G_OBJECT_CLASS( class );
706 	VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
707 	VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
708 
709 	gobject_class->set_property = vips_object_set_property;
710 	gobject_class->get_property = vips_object_get_property;
711 
712 	vobject_class->nickname = "arithmetic";
713 	vobject_class->description = _( "arithmetic operations" );
714 	vobject_class->build = vips_arithmetic_build;
715 
716 	operation_class->flags = VIPS_OPERATION_SEQUENTIAL;
717 
718 	VIPS_ARG_IMAGE( class, "out", 100,
719 		_( "Output" ),
720 		_( "Output image" ),
721 		VIPS_ARGUMENT_REQUIRED_OUTPUT,
722 		G_STRUCT_OFFSET( VipsArithmetic, out ) );
723 }
724 
725 static void
vips_arithmetic_init(VipsArithmetic * arithmetic)726 vips_arithmetic_init( VipsArithmetic *arithmetic )
727 {
728 	arithmetic->base_bands = 1;
729 	arithmetic->format = VIPS_FORMAT_NOTSET;
730 }
731 
732 void
vips_arithmetic_set_format_table(VipsArithmeticClass * class,const VipsBandFormat * format_table)733 vips_arithmetic_set_format_table( VipsArithmeticClass *class,
734 	const VipsBandFormat *format_table )
735 {
736 	g_assert( !class->format_table );
737 
738 	class->format_table = format_table;
739 }
740 
741 void
vips_arithmetic_set_vector(VipsArithmeticClass * class)742 vips_arithmetic_set_vector( VipsArithmeticClass *class )
743 {
744 	int i;
745 
746 	g_assert( class->format_table );
747 
748 	for( i = 0; i < VIPS_FORMAT_LAST; i++ ) {
749 		int isize = vips_format_sizeof( i );
750 		int osize = vips_format_sizeof( (int) class->format_table[i] );
751 
752 		VipsVector *v;
753 
754 		v = vips_vector_new( "arithmetic", osize );
755 
756 		vips_vector_source_name( v, "s1", isize );
757 		vips_vector_source_name( v, "s2", isize );
758 		vips_vector_temporary( v, "t1", osize );
759 		vips_vector_temporary( v, "t2", osize );
760 
761 		class->vectors[i] = v;
762 	}
763 }
764 
765 /* Get the stub for this program ... use _get_vector() to get the compiled
766  * code.
767  */
768 VipsVector *
vips_arithmetic_get_program(VipsArithmeticClass * class,VipsBandFormat fmt)769 vips_arithmetic_get_program( VipsArithmeticClass *class, VipsBandFormat fmt )
770 {
771 	g_assert( (int) fmt >= 0 && (int) fmt < VIPS_FORMAT_LAST );
772 	g_assert( !class->vector_program[fmt] );
773 
774 	class->vector_program[fmt] = TRUE;
775 
776 	return( class->vectors[fmt] );
777 }
778 
779 /* Get the compiled code for this type, if available.
780  */
781 VipsVector *
vips_arithmetic_get_vector(VipsArithmeticClass * class,VipsBandFormat fmt)782 vips_arithmetic_get_vector( VipsArithmeticClass *class, VipsBandFormat fmt )
783 {
784 	g_assert( fmt >= 0 && fmt < VIPS_FORMAT_LAST );
785 
786 	if( !vips_vector_isenabled() ||
787 		!class->vector_program[fmt] )
788 		return( NULL );
789 
790 	return( class->vectors[fmt] );
791 }
792 
793 void
vips_arithmetic_compile(VipsArithmeticClass * class)794 vips_arithmetic_compile( VipsArithmeticClass *class )
795 {
796 	int i;
797 
798 	g_assert( class->format_table );
799 
800 	for( i = 0; i < VIPS_FORMAT_LAST; i++ )
801 		if( class->vector_program[i] &&
802 			!vips_vector_compile( class->vectors[i] ) )
803 			/* If compilation fails, turn off the vector for this
804 			 * type.
805 			 */
806 			class->vector_program[i] = FALSE;
807 
808 #ifdef DEBUG
809 	printf( "vips_arithmetic_compile: " );
810 	for( i = 0; i < VIPS_FORMAT_LAST; i++ )
811 		if( class->vector_program[i] )
812 			printf( "%s ",
813 				vips_enum_nick( VIPS_TYPE_BAND_FORMAT, i ) );
814 	printf( "\n" );
815 #endif /*DEBUG*/
816 }
817 
818 /* Called from iofuncs to init all operations in this dir. Use a plugin system
819  * instead?
820  */
821 void
vips_arithmetic_operation_init(void)822 vips_arithmetic_operation_init( void )
823 {
824 	extern GType vips_add_get_type( void );
825 	extern GType vips_sum_get_type( void );
826 	extern GType vips_subtract_get_type( void );
827 	extern GType vips_multiply_get_type( void );
828 	extern GType vips_divide_get_type( void );
829 	extern GType vips_invert_get_type( void );
830 	extern GType vips_avg_get_type( void );
831 	extern GType vips_min_get_type( void );
832 	extern GType vips_max_get_type( void );
833 	extern GType vips_deviate_get_type( void );
834 	extern GType vips_linear_get_type( void );
835 	extern GType vips_math_get_type( void );
836 	extern GType vips_abs_get_type( void );
837 	extern GType vips_sign_get_type( void );
838 	extern GType vips_stats_get_type( void );
839 	extern GType vips_hist_find_get_type( void );
840 	extern GType vips_hist_find_ndim_get_type( void );
841 	extern GType vips_hist_find_indexed_get_type( void );
842 	extern GType vips_hough_line_get_type( void );
843 	extern GType vips_hough_circle_get_type( void );
844 	extern GType vips_project_get_type( void );
845 	extern GType vips_profile_get_type( void );
846 	extern GType vips_measure_get_type( void );
847 	extern GType vips_getpoint_get_type( void );
848 	extern GType vips_round_get_type( void );
849 	extern GType vips_relational_get_type( void );
850 	extern GType vips_relational_const_get_type( void );
851 	extern GType vips_remainder_get_type( void );
852 	extern GType vips_remainder_const_get_type( void );
853 	extern GType vips_boolean_get_type( void );
854 	extern GType vips_boolean_const_get_type( void );
855 	extern GType vips_math2_get_type( void );
856 	extern GType vips_math2_const_get_type( void );
857 	extern GType vips_complex_get_type( void );
858 	extern GType vips_complex2_get_type( void );
859 	extern GType vips_complexget_get_type( void );
860 	extern GType vips_complexform_get_type( void );
861 	extern GType vips_find_trim_get_type( void );
862 
863 	vips_add_get_type();
864 	vips_sum_get_type();
865 	vips_subtract_get_type();
866 	vips_multiply_get_type();
867 	vips_divide_get_type();
868 	vips_invert_get_type();
869 	vips_avg_get_type();
870 	vips_min_get_type();
871 	vips_max_get_type();
872 	vips_deviate_get_type();
873 	vips_linear_get_type();
874 	vips_math_get_type();
875 	vips_abs_get_type();
876 	vips_sign_get_type();
877 	vips_stats_get_type();
878 	vips_hist_find_get_type();
879 	vips_hist_find_ndim_get_type();
880 	vips_hist_find_indexed_get_type();
881 	vips_hough_line_get_type();
882 	vips_hough_circle_get_type();
883 	vips_project_get_type();
884 	vips_profile_get_type();
885 	vips_measure_get_type();
886 	vips_getpoint_get_type();
887 	vips_round_get_type();
888 	vips_relational_get_type();
889 	vips_relational_const_get_type();
890 	vips_remainder_get_type();
891 	vips_remainder_const_get_type();
892 	vips_boolean_get_type();
893 	vips_boolean_const_get_type();
894 	vips_math2_get_type();
895 	vips_math2_const_get_type();
896 	vips_complex_get_type();
897 	vips_complex2_get_type();
898 	vips_complexget_get_type();
899 	vips_complexform_get_type();
900 	vips_find_trim_get_type();
901 }
902