1 /* remainder.c
2 *
3 * 2/8/99 JC
4 * - im_divide adapted to make im_remainder
5 * 8/5/02 JC
6 * - im_remainderconst added
7 * - im_remainderconst_vec added
8 * 27/9/04
9 * - updated for 1 band $op n band image -> n band image case
10 * 26/2/07
11 * - oop, broken for _vec case :-(
12 * 14/5/08
13 * - better /0 test
14 * 27/8/08
15 * - revise upcasting system
16 * - add gtkdoc comments
17 * 23/6/10
18 * - constant ops clip to target range
19 * 12/11/11
20 * - redone as a class
21 */
22
23 /*
24
25 Copyright (C) 1991-2005 The National Gallery
26
27 This library is free software; you can redistribute it and/or
28 modify it under the terms of the GNU Lesser General Public
29 License as published by the Free Software Foundation; either
30 version 2.1 of the License, or (at your option) any later version.
31
32 This library is distributed in the hope that it will be useful,
33 but WITHOUT ANY WARRANTY; without even the implied warranty of
34 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
35 Lesser General Public License for more details.
36
37 You should have received a copy of the GNU Lesser General Public
38 License along with this library; if not, write to the Free Software
39 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
40 02110-1301 USA
41
42 */
43
44 /*
45
46 These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
47
48 */
49
50 /*
51 #define DEBUG
52 */
53
54 #ifdef HAVE_CONFIG_H
55 #include <config.h>
56 #endif /*HAVE_CONFIG_H*/
57 #include <vips/intl.h>
58
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <math.h>
62
63 #include <vips/vips.h>
64
65 #include "binary.h"
66 #include "unaryconst.h"
67
68 typedef VipsBinary VipsRemainder;
69 typedef VipsBinaryClass VipsRemainderClass;
70
71 G_DEFINE_TYPE( VipsRemainder, vips_remainder, VIPS_TYPE_BINARY );
72
73 static int
vips_remainder_build(VipsObject * object)74 vips_remainder_build( VipsObject *object )
75 {
76 VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
77 VipsBinary *binary = (VipsBinary *) object;
78
79 if( binary->left &&
80 vips_check_noncomplex( class->nickname, binary->left ) )
81 return( -1 );
82 if( binary->right &&
83 vips_check_noncomplex( class->nickname, binary->right ) )
84 return( -1 );
85
86 if( VIPS_OBJECT_CLASS( vips_remainder_parent_class )->build( object ) )
87 return( -1 );
88
89 return( 0 );
90 }
91
92 /* Integer remainder-after-division.
93 */
94 #define IREMAINDER( TYPE ) { \
95 TYPE * restrict p1 = (TYPE *) in[0]; \
96 TYPE * restrict p2 = (TYPE *) in[1]; \
97 TYPE * restrict q = (TYPE *) out; \
98 \
99 for( x = 0; x < sz; x++ ) \
100 q[x] = p2[x] ? p1[x] % p2[x] : -1; \
101 }
102
103 /* Float remainder-after-division.
104 */
105 #define FREMAINDER( TYPE ) { \
106 TYPE * restrict p1 = (TYPE *) in[0]; \
107 TYPE * restrict p2 = (TYPE *) in[1]; \
108 TYPE * restrict q = (TYPE *) out; \
109 \
110 for( x = 0; x < sz; x++ ) { \
111 double a = p1[x]; \
112 double b = p2[x]; \
113 \
114 q[x] = b ? a - b * VIPS_FLOOR (a / b) : -1; \
115 } \
116 }
117
118 static void
vips_remainder_buffer(VipsArithmetic * arithmetic,VipsPel * out,VipsPel ** in,int width)119 vips_remainder_buffer( VipsArithmetic *arithmetic,
120 VipsPel *out, VipsPel **in, int width )
121 {
122 VipsImage *im = arithmetic->ready[0];
123 const int sz = width * vips_image_get_bands( im );
124
125 int x;
126
127 switch( vips_image_get_format( im ) ) {
128 case VIPS_FORMAT_CHAR: IREMAINDER( signed char ); break;
129 case VIPS_FORMAT_UCHAR: IREMAINDER( unsigned char ); break;
130 case VIPS_FORMAT_SHORT: IREMAINDER( signed short ); break;
131 case VIPS_FORMAT_USHORT:IREMAINDER( unsigned short ); break;
132 case VIPS_FORMAT_INT: IREMAINDER( signed int ); break;
133 case VIPS_FORMAT_UINT: IREMAINDER( unsigned int ); break;
134 case VIPS_FORMAT_FLOAT: FREMAINDER( float ); break;
135 case VIPS_FORMAT_DOUBLE:FREMAINDER( double ); break;
136
137 default:
138 g_assert_not_reached();
139 }
140 }
141
142 /* Save a bit of typing.
143 */
144 #define UC VIPS_FORMAT_UCHAR
145 #define C VIPS_FORMAT_CHAR
146 #define US VIPS_FORMAT_USHORT
147 #define S VIPS_FORMAT_SHORT
148 #define UI VIPS_FORMAT_UINT
149 #define I VIPS_FORMAT_INT
150 #define F VIPS_FORMAT_FLOAT
151 #define X VIPS_FORMAT_COMPLEX
152 #define D VIPS_FORMAT_DOUBLE
153 #define DX VIPS_FORMAT_DPCOMPLEX
154
155 /* Type promotion for remainder. Keep in sync with remainder_buffer() above.
156 */
157 static int vips_remainder_format_table[10] = {
158 /* UC C US S UI I F X D DX */
159 UC, C, US, S, UI, I, F, X, D, DX
160 };
161
162 static void
vips_remainder_class_init(VipsRemainderClass * class)163 vips_remainder_class_init( VipsRemainderClass *class )
164 {
165 GObjectClass *gobject_class = G_OBJECT_CLASS( class );
166 VipsObjectClass *object_class = (VipsObjectClass *) class;
167 VipsArithmeticClass *aclass = VIPS_ARITHMETIC_CLASS( class );
168
169 gobject_class->set_property = vips_object_set_property;
170 gobject_class->get_property = vips_object_get_property;
171
172 object_class->nickname = "remainder";
173 object_class->description =
174 _( "remainder after integer division of two images" );
175 object_class->build = vips_remainder_build;
176
177 aclass->process_line = vips_remainder_buffer;
178
179 vips_arithmetic_set_format_table( aclass,
180 vips_remainder_format_table );
181 }
182
183 static void
vips_remainder_init(VipsRemainder * remainder)184 vips_remainder_init( VipsRemainder *remainder )
185 {
186 }
187
188 /**
189 * vips_remainder:
190 * @left: left-hand input #VipsImage
191 * @right: right-hand input #VipsImage
192 * @out: (out): output #VipsImage
193 * @...: %NULL-terminated list of optional named arguments
194 *
195 * This operation calculates @left % @right (remainder after integer division)
196 * and writes the result to @out. The images may have any
197 * non-complex format. For float formats, vips_remainder() calculates @in1 -
198 * @in2 * floor (@in1 / @in2).
199 *
200 * If the images differ in size, the smaller image is enlarged to match the
201 * larger by adding zero pixels along the bottom and right.
202 *
203 * If the number of bands differs, one of the images
204 * must have one band. In this case, an n-band image is formed from the
205 * one-band image by joining n copies of the one-band image together, and then
206 * the two n-band images are operated upon.
207 *
208 * The two input images are cast up to the smallest common format (see table
209 * Smallest common format in
210 * <link linkend="libvips-arithmetic">arithmetic</link>), and that format is the
211 * result type.
212 *
213 * See also: vips_remainder_const(), vips_divide(), vips_round().
214 *
215 * Returns: 0 on success, -1 on error
216 */
217 int
vips_remainder(VipsImage * left,VipsImage * right,VipsImage ** out,...)218 vips_remainder( VipsImage *left, VipsImage *right, VipsImage **out, ... )
219 {
220 va_list ap;
221 int result;
222
223 va_start( ap, out );
224 result = vips_call_split( "remainder", ap, left, right, out );
225 va_end( ap );
226
227 return( result );
228 }
229
230 typedef VipsUnaryConst VipsRemainderConst;
231 typedef VipsUnaryConstClass VipsRemainderConstClass;
232
233 G_DEFINE_TYPE( VipsRemainderConst,
234 vips_remainder_const, VIPS_TYPE_UNARY_CONST );
235
236 static int
vips_remainder_const_build(VipsObject * object)237 vips_remainder_const_build( VipsObject *object )
238 {
239 VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
240 VipsUnary *unary = (VipsUnary *) object;
241
242 if( unary->in &&
243 vips_check_noncomplex( class->nickname, unary->in ) )
244 return( -1 );
245
246 if( VIPS_OBJECT_CLASS( vips_remainder_const_parent_class )->
247 build( object ) )
248 return( -1 );
249
250 return( 0 );
251 }
252
253 /* Integer remainder-after-divide, per-band constant.
254 */
255 #define IREMAINDERCONST( TYPE ) { \
256 TYPE * restrict p = (TYPE *) in[0]; \
257 TYPE * restrict q = (TYPE *) out; \
258 int * restrict c = uconst->c_int; \
259 \
260 for( i = 0, x = 0; x < width; x++ ) \
261 for( b = 0; b < bands; b++, i++ ) \
262 q[i] = p[i] % c[b]; \
263 }
264
265 /* Float remainder-after-divide, per-band constant.
266 */
267 #define FREMAINDERCONST( TYPE ) { \
268 TYPE * restrict p = (TYPE *) in[0]; \
269 TYPE * restrict q = (TYPE *) out; \
270 int * restrict c = uconst->c_int; \
271 \
272 for( i = 0, x = 0; x < width; x++ ) \
273 for( b = 0; b < bands; b++, i++ ) { \
274 double left = p[i]; \
275 double right = c[b]; \
276 \
277 q[i] = right ? \
278 left - right * floor( left / right ) : \
279 -1; \
280 } \
281 }
282
283 static void
vips_remainder_const_buffer(VipsArithmetic * arithmetic,VipsPel * out,VipsPel ** in,int width)284 vips_remainder_const_buffer( VipsArithmetic *arithmetic,
285 VipsPel *out, VipsPel **in, int width )
286 {
287 VipsUnaryConst *uconst = (VipsUnaryConst *) arithmetic;
288 VipsImage *im = arithmetic->ready[0];
289 int bands = im->Bands;
290
291 int i, x, b;
292
293 switch( vips_image_get_format( im ) ) {
294 case VIPS_FORMAT_CHAR: IREMAINDERCONST( signed char ); break;
295 case VIPS_FORMAT_UCHAR: IREMAINDERCONST( unsigned char ); break;
296 case VIPS_FORMAT_SHORT: IREMAINDERCONST( signed short ); break;
297 case VIPS_FORMAT_USHORT:IREMAINDERCONST( unsigned short ); break;
298 case VIPS_FORMAT_INT: IREMAINDERCONST( signed int ); break;
299 case VIPS_FORMAT_UINT: IREMAINDERCONST( unsigned int ); break;
300 case VIPS_FORMAT_FLOAT: FREMAINDERCONST( float ); break;
301 case VIPS_FORMAT_DOUBLE:FREMAINDERCONST( double ); break;
302
303 default:
304 g_assert_not_reached();
305 }
306 }
307
308 static void
vips_remainder_const_class_init(VipsRemainderConstClass * class)309 vips_remainder_const_class_init( VipsRemainderConstClass *class )
310 {
311 GObjectClass *gobject_class = G_OBJECT_CLASS( class );
312 VipsObjectClass *object_class = (VipsObjectClass *) class;
313 VipsArithmeticClass *aclass = VIPS_ARITHMETIC_CLASS( class );
314
315 gobject_class->set_property = vips_object_set_property;
316 gobject_class->get_property = vips_object_get_property;
317
318 object_class->nickname = "remainder_const";
319 object_class->description =
320 _( "remainder after integer division of an image "
321 "and a constant" );
322 object_class->build = vips_remainder_const_build;
323
324 aclass->process_line = vips_remainder_const_buffer;
325
326 vips_arithmetic_set_format_table( aclass, vips_remainder_format_table );
327 }
328
329 static void
vips_remainder_const_init(VipsRemainderConst * remainder_const)330 vips_remainder_const_init( VipsRemainderConst *remainder_const )
331 {
332 }
333
334 static int
vips_remainder_constv(VipsImage * in,VipsImage ** out,const double * c,int n,va_list ap)335 vips_remainder_constv( VipsImage *in, VipsImage **out,
336 const double *c, int n, va_list ap )
337 {
338 VipsArea *area_c;
339 double *array;
340 int result;
341 int i;
342
343 area_c = vips_area_new_array( G_TYPE_DOUBLE, sizeof( double ), n );
344 array = (double *) area_c->data;
345 for( i = 0; i < n; i++ )
346 array[i] = c[i];
347
348 result = vips_call_split( "remainder_const", ap, in, out, area_c );
349
350 vips_area_unref( area_c );
351
352 return( result );
353 }
354
355 /**
356 * vips_remainder_const: (method)
357 * @in: input image
358 * @out: (out): output image
359 * @c: (array length=n): array of constants
360 * @n: number of constants in @c
361 * @...: %NULL-terminated list of optional named arguments
362 *
363 * This operation calculates @in % @c (remainder after division by an
364 * array of constants)
365 * and writes the result to @out.
366 * The image may have any
367 * non-complex format. For float formats, vips_remainder_const() calculates
368 * @in - @c * floor (@in / @c).
369 *
370 * If the array of constants has just one element, that constant is used for
371 * all image bands. If the array has more than one element and they have
372 * the same number of elements as there are bands in the image, then
373 * one array element is used for each band. If the arrays have more than one
374 * element and the image only has a single band, the result is a many-band
375 * image where each band corresponds to one array element.
376 *
377 * See also: vips_remainder(), vips_divide(), vips_round().
378 *
379 * Returns: 0 on success, -1 on error
380 */
381 int
vips_remainder_const(VipsImage * in,VipsImage ** out,const double * c,int n,...)382 vips_remainder_const( VipsImage *in, VipsImage **out,
383 const double *c, int n, ... )
384 {
385 va_list ap;
386 int result;
387
388 va_start( ap, n );
389 result = vips_remainder_constv( in, out, c, n, ap );
390 va_end( ap );
391
392 return( result );
393 }
394
395 /**
396 * vips_remainder_const1: (method)
397 * @in: input image
398 * @out: (out): output image
399 * @c: constant
400 * @...: %NULL-terminated list of optional named arguments
401 *
402 * This operation calculates @in % @c (remainder after division by a
403 * constant)
404 * and writes the result to @out.
405 * The image may have any
406 * non-complex format. For float formats, vips_remainder_const() calculates
407 * @in - @c * floor (@in / @c).
408 *
409 * If the array of constants has just one element, that constant is used for
410 * all image bands. If the array has more than one element and they have
411 * the same number of elements as there are bands in the image, then
412 * one array element is used for each band. If the arrays have more than one
413 * element and the image only has a single band, the result is a many-band
414 * image where each band corresponds to one array element.
415 *
416 * See also: vips_remainder(), vips_divide(), vips_round().
417 *
418 * Returns: 0 on success, -1 on error
419 */
420 int
vips_remainder_const1(VipsImage * in,VipsImage ** out,double c,...)421 vips_remainder_const1( VipsImage *in, VipsImage **out, double c, ... )
422 {
423 va_list ap;
424 int result;
425
426 va_start( ap, c );
427 result = vips_remainder_constv( in, out, &c, 1, ap );
428 va_end( ap );
429
430 return( result );
431 }
432
433