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