ruby-vips 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.md +15 -0
- data/Gemfile.lock +31 -0
- data/LICENSE +20 -0
- data/README.md +96 -0
- data/TODO +18 -0
- data/ext/extconf.rb +10 -0
- data/ext/header.c +440 -0
- data/ext/header.h +8 -0
- data/ext/image.c +639 -0
- data/ext/image.h +71 -0
- data/ext/image_arithmetic.c +940 -0
- data/ext/image_arithmetic.h +38 -0
- data/ext/image_boolean.c +302 -0
- data/ext/image_boolean.h +8 -0
- data/ext/image_colour.c +593 -0
- data/ext/image_colour.h +36 -0
- data/ext/image_conversion.c +863 -0
- data/ext/image_conversion.h +37 -0
- data/ext/image_convolution.c +371 -0
- data/ext/image_convolution.h +13 -0
- data/ext/image_freq_filt.c +742 -0
- data/ext/image_freq_filt.h +27 -0
- data/ext/image_histograms_lut.c +646 -0
- data/ext/image_histograms_lut.h +28 -0
- data/ext/image_morphology.c +330 -0
- data/ext/image_morphology.h +13 -0
- data/ext/image_mosaicing.c +556 -0
- data/ext/image_mosaicing.h +14 -0
- data/ext/image_relational.c +386 -0
- data/ext/image_relational.h +8 -0
- data/ext/image_resample.c +253 -0
- data/ext/image_resample.h +9 -0
- data/ext/interpolator.c +106 -0
- data/ext/interpolator.h +6 -0
- data/ext/mask.c +349 -0
- data/ext/mask.h +17 -0
- data/ext/reader.c +315 -0
- data/ext/ruby_vips.c +131 -0
- data/ext/ruby_vips.h +26 -0
- data/ext/writer.c +346 -0
- data/lib/vips.rb +7 -0
- data/lib/vips/reader.rb +183 -0
- data/lib/vips/version.rb +3 -0
- data/lib/vips/writer.rb +275 -0
- data/ruby-vips.gemspec +93 -0
- metadata +163 -0
data/ext/image.h
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
#ifndef RUBY_VIPS_IMAGE_H
|
2
|
+
#define RUBY_VIPS_IMAGE_H
|
3
|
+
|
4
|
+
#include "ruby_vips.h"
|
5
|
+
|
6
|
+
extern VALUE cVIPSImage;
|
7
|
+
|
8
|
+
struct _vipsImg {
|
9
|
+
VipsImage *in;
|
10
|
+
VALUE *deps;
|
11
|
+
int deps_len;
|
12
|
+
};
|
13
|
+
typedef struct _vipsImg vipsImg;
|
14
|
+
|
15
|
+
void img_add_dep(vipsImg*, VALUE);
|
16
|
+
VALUE img_spawn(VALUE);
|
17
|
+
VALUE img_spawn2(VALUE, VALUE);
|
18
|
+
VALUE img_spawn3(VALUE, VALUE, VALUE);
|
19
|
+
VALUE img_alloc(VALUE);
|
20
|
+
VALUE img_init(VALUE, VipsImage*);
|
21
|
+
VALUE img_init_partial();
|
22
|
+
VALUE img_init_partial_anyclass(VALUE);
|
23
|
+
VipsBandFmt img_id_to_band_fmt(VALUE);
|
24
|
+
|
25
|
+
#define GetImg(obj, data, im) \
|
26
|
+
vipsImg *data; \
|
27
|
+
VipsImage *im; \
|
28
|
+
Data_Get_Struct(obj, vipsImg, data); \
|
29
|
+
im = data->in;
|
30
|
+
|
31
|
+
#define OutImg(obj, new, data_new, im_new) \
|
32
|
+
VALUE new = img_spawn(obj); \
|
33
|
+
GetImg(new, data_new, im_new);
|
34
|
+
|
35
|
+
#define OutImg2(obj, obj2, new, data_new, im_new) \
|
36
|
+
VALUE new = img_spawn2(obj, obj2); \
|
37
|
+
GetImg(new, data_new, im_new);
|
38
|
+
|
39
|
+
#define OutImg3(obj, obj2, obj3, new, data_new, im_new) \
|
40
|
+
VALUE new = img_spawn3(obj, obj2, obj3); \
|
41
|
+
GetImg(new, data_new, im_new);
|
42
|
+
|
43
|
+
#define OutPartial(new, data_new, im_new) \
|
44
|
+
VALUE new = img_init_partial(); \
|
45
|
+
GetImg(new, data_new, im_new);
|
46
|
+
|
47
|
+
#define RUBY_VIPS_UNARY(VIPS_METHOD) \
|
48
|
+
do { \
|
49
|
+
GetImg(obj, data, im); \
|
50
|
+
OutImg(obj, new, data_new, im_new); \
|
51
|
+
\
|
52
|
+
if (VIPS_METHOD(im, im_new)) \
|
53
|
+
vips_lib_error(); \
|
54
|
+
\
|
55
|
+
return new; \
|
56
|
+
} while(0)
|
57
|
+
|
58
|
+
#define RUBY_VIPS_BINARY(VIPS_METHOD) \
|
59
|
+
do { \
|
60
|
+
GetImg(obj, data, im); \
|
61
|
+
GetImg(obj2, data2, im2); \
|
62
|
+
OutImg2(obj, obj2, new, data_new, im_new); \
|
63
|
+
\
|
64
|
+
if (VIPS_METHOD(im, im2, im_new)) \
|
65
|
+
vips_lib_error(); \
|
66
|
+
\
|
67
|
+
return new; \
|
68
|
+
} while(0)
|
69
|
+
|
70
|
+
#endif
|
71
|
+
|
@@ -0,0 +1,940 @@
|
|
1
|
+
#include "ruby_vips.h"
|
2
|
+
#include "image.h"
|
3
|
+
#include "mask.h"
|
4
|
+
#include "interpolator.h"
|
5
|
+
|
6
|
+
/*
|
7
|
+
* call-seq:
|
8
|
+
* im.measure_area(left, top, width, height, h, v, sel) -> array
|
9
|
+
*
|
10
|
+
* Analyse a grid of colour patches, producing an array of averages.
|
11
|
+
* Pass a box defined by <i>left</i>, <i>top</i>, <i>width</i>, and
|
12
|
+
* <i>height</i>, the number of horizontal and vertical patches <i>h</i> and
|
13
|
+
* <i>v</i>, an array giving the numbers of the patches to measure <i>sel</i>
|
14
|
+
* (patches are numbered left-to-right, top-to-bottom, starting with 1). Return
|
15
|
+
* an array in which rows are patches and columns are bands. Only the central
|
16
|
+
* 50% of each patch is averaged.
|
17
|
+
*/
|
18
|
+
|
19
|
+
VALUE
|
20
|
+
img_measure_area(VALUE obj, VALUE left, VALUE top, VALUE width, VALUE height,
|
21
|
+
VALUE h, VALUE v, VALUE sel)
|
22
|
+
{
|
23
|
+
DOUBLEMASK *ret;
|
24
|
+
VALUE results;
|
25
|
+
int *a, i, len = RARRAY_LENINT(sel);
|
26
|
+
GetImg(obj, data, im);
|
27
|
+
|
28
|
+
a = ALLOC_N(int, len);
|
29
|
+
for (i = 0; i < len; i++)
|
30
|
+
a[i] = NUM2INT(RARRAY_PTR(sel)[i]);
|
31
|
+
|
32
|
+
ret = im_measure_area(im, NUM2INT(left), NUM2INT(top), NUM2INT(width),
|
33
|
+
NUM2INT(height), NUM2INT(h), NUM2INT(v), a, len, "img_measure_area");
|
34
|
+
|
35
|
+
xfree(a);
|
36
|
+
|
37
|
+
return dmask2rb(ret);
|
38
|
+
}
|
39
|
+
|
40
|
+
/*
|
41
|
+
* call-seq:
|
42
|
+
* im.stats -> array
|
43
|
+
*
|
44
|
+
* Find many image statistics in a single pass through the pixels. Returns an
|
45
|
+
* array of 6 columns by n+1 (where n is number of bands in the image) rows.
|
46
|
+
* Columns are statistics, and are, in order: minimum, maximum, sum, sum of
|
47
|
+
* squares, mean, standard deviation. Row 0 has statistics for all bands
|
48
|
+
* together, row 1 has stats for band 1, and so on.
|
49
|
+
*/
|
50
|
+
|
51
|
+
VALUE
|
52
|
+
img_stats(VALUE obj)
|
53
|
+
{
|
54
|
+
DOUBLEMASK *ret;
|
55
|
+
GetImg(obj, data, im);
|
56
|
+
|
57
|
+
if (!(ret = im_stats(im)))
|
58
|
+
vips_lib_error();
|
59
|
+
|
60
|
+
return dmask2rb(ret);
|
61
|
+
}
|
62
|
+
|
63
|
+
/*
|
64
|
+
* call-seq:
|
65
|
+
* im.max -> number
|
66
|
+
*
|
67
|
+
* Finds the the maximum value of *self*. If input is complex, the max modulus
|
68
|
+
* is returned. Finds the maximum of all bands: if you want to find the maximum
|
69
|
+
* of each band separately, use Image#stats.
|
70
|
+
*/
|
71
|
+
|
72
|
+
VALUE
|
73
|
+
img_max(VALUE obj) {
|
74
|
+
double out;
|
75
|
+
GetImg(obj, data, im);
|
76
|
+
|
77
|
+
if (im_max(im, &out))
|
78
|
+
vips_lib_error();
|
79
|
+
|
80
|
+
return DBL2NUM(out);
|
81
|
+
}
|
82
|
+
|
83
|
+
/*
|
84
|
+
* call-seq:
|
85
|
+
* im.min -> number
|
86
|
+
*
|
87
|
+
* Finds the the minimum value of the image. If input is complex, the min
|
88
|
+
* modulus is returned. Finds the minimum of all bands: if you want to find the
|
89
|
+
* minimum of each band separately, use Image#stats.
|
90
|
+
*/
|
91
|
+
|
92
|
+
VALUE
|
93
|
+
img_min(VALUE obj) {
|
94
|
+
double out;
|
95
|
+
GetImg(obj, data, im);
|
96
|
+
|
97
|
+
if (im_min(im, &out))
|
98
|
+
vips_lib_error();
|
99
|
+
|
100
|
+
return DBL2NUM(out);
|
101
|
+
}
|
102
|
+
|
103
|
+
/*
|
104
|
+
* call-seq:
|
105
|
+
* im.avg -> number
|
106
|
+
*
|
107
|
+
* Finds the average of an image. Works on any non-complex image format.
|
108
|
+
*/
|
109
|
+
|
110
|
+
VALUE
|
111
|
+
img_avg(VALUE obj) {
|
112
|
+
double out;
|
113
|
+
GetImg(obj, data, im);
|
114
|
+
|
115
|
+
if (im_avg(im, &out))
|
116
|
+
vips_lib_error();
|
117
|
+
|
118
|
+
return DBL2NUM(out);
|
119
|
+
}
|
120
|
+
|
121
|
+
/*
|
122
|
+
* call-seq:
|
123
|
+
* im.deviate -> number
|
124
|
+
*
|
125
|
+
* This operation finds the standard deviation of all pixels in the image. It
|
126
|
+
* operates on all bands of the input image: use Image#stats if you need to
|
127
|
+
* calculate an average for each band.
|
128
|
+
*
|
129
|
+
* Non-complex images only.
|
130
|
+
*/
|
131
|
+
|
132
|
+
VALUE
|
133
|
+
img_deviate(VALUE obj) {
|
134
|
+
double out;
|
135
|
+
GetImg(obj, data, im);
|
136
|
+
|
137
|
+
if (im_deviate(im, &out))
|
138
|
+
vips_lib_error();
|
139
|
+
|
140
|
+
return DBL2NUM(out);
|
141
|
+
}
|
142
|
+
|
143
|
+
/*
|
144
|
+
* call-seq:
|
145
|
+
* im.maxpos_avg -> [ x, y, value ]
|
146
|
+
*
|
147
|
+
* Function to find the maximum of an image. In the event of a draw, returns
|
148
|
+
* average of all drawing coords.
|
149
|
+
*/
|
150
|
+
|
151
|
+
VALUE
|
152
|
+
img_maxpos_avg(VALUE obj) {
|
153
|
+
double x, y, out;
|
154
|
+
GetImg(obj, data, im);
|
155
|
+
|
156
|
+
if (im_maxpos_avg(im, &x, &y, &out))
|
157
|
+
vips_lib_error();
|
158
|
+
|
159
|
+
return rb_ary_new3(3, DBL2NUM(x), DBL2NUM(y), DBL2NUM(out));
|
160
|
+
}
|
161
|
+
|
162
|
+
static VALUE
|
163
|
+
img_maxpos_single(VALUE obj) {
|
164
|
+
double out;
|
165
|
+
int x, y;
|
166
|
+
GetImg(obj, data, im);
|
167
|
+
|
168
|
+
if (im_maxpos(im, &x, &y, &out))
|
169
|
+
vips_lib_error();
|
170
|
+
|
171
|
+
return rb_ary_new3(3, INT2NUM(x), INT2NUM(y), DBL2NUM(out));
|
172
|
+
}
|
173
|
+
|
174
|
+
static VALUE
|
175
|
+
img_maxpos_n(VALUE obj, int len) {
|
176
|
+
double *out;
|
177
|
+
int im_return, i, *x, *y;
|
178
|
+
VALUE t, ary;
|
179
|
+
GetImg(obj, data, im);
|
180
|
+
|
181
|
+
ary = rb_ary_new2(len);
|
182
|
+
|
183
|
+
x = ALLOC_N(int, len);
|
184
|
+
y = ALLOC_N(int, len);
|
185
|
+
out = ALLOC_N(double, len);
|
186
|
+
|
187
|
+
if (!(im_return = im_maxpos_vec(im, x, y, out, len))) {
|
188
|
+
for (i = 0; i < len; i++) {
|
189
|
+
t = rb_ary_new3(3, INT2NUM(x[i]), INT2NUM(y[i]), DBL2NUM(out[i]));
|
190
|
+
rb_ary_push(ary, t);
|
191
|
+
}
|
192
|
+
}
|
193
|
+
|
194
|
+
xfree(x);
|
195
|
+
xfree(y);
|
196
|
+
xfree(out);
|
197
|
+
|
198
|
+
if(im_return)
|
199
|
+
vips_lib_error();
|
200
|
+
|
201
|
+
return ary;
|
202
|
+
}
|
203
|
+
|
204
|
+
/*
|
205
|
+
* call-seq:
|
206
|
+
* im.maxpos -> x, y, value
|
207
|
+
* im.maxpos(n, ...) -> [ x, y, value ], ...
|
208
|
+
*
|
209
|
+
* Function to find the maximum of an image. Works for any image type. Returns
|
210
|
+
* an array with the x and y coordinates of the maximum value and the
|
211
|
+
* corresponding value. If <i>n</i> is given, returns the <i>n</i> largest
|
212
|
+
* values. For complex images, finds the pixel with the highest modulus.
|
213
|
+
*/
|
214
|
+
|
215
|
+
VALUE
|
216
|
+
img_maxpos(int argc, VALUE *argv, VALUE obj) {
|
217
|
+
VALUE v_num;
|
218
|
+
|
219
|
+
rb_scan_args(argc, argv, "01", &v_num);
|
220
|
+
if (NIL_P(v_num))
|
221
|
+
return img_maxpos_single(obj);
|
222
|
+
else
|
223
|
+
return img_maxpos_n(obj, NUM2INT(v_num));
|
224
|
+
}
|
225
|
+
|
226
|
+
static VALUE
|
227
|
+
img_minpos_single(VALUE obj) {
|
228
|
+
double out;
|
229
|
+
int x, y;
|
230
|
+
GetImg(obj, data, im);
|
231
|
+
|
232
|
+
if (im_minpos(im, &x, &y, &out))
|
233
|
+
vips_lib_error();
|
234
|
+
|
235
|
+
return rb_ary_new3(3, INT2NUM(x), INT2NUM(y), DBL2NUM(out));
|
236
|
+
}
|
237
|
+
|
238
|
+
static VALUE
|
239
|
+
img_minpos_n(VALUE obj, int len) {
|
240
|
+
double *out;
|
241
|
+
int im_return, i, *x, *y;
|
242
|
+
VALUE t, ary;
|
243
|
+
GetImg(obj, data, im);
|
244
|
+
|
245
|
+
ary = rb_ary_new2(len);
|
246
|
+
|
247
|
+
x = ALLOC_N(int, len);
|
248
|
+
y = ALLOC_N(int, len);
|
249
|
+
out = ALLOC_N(double, len);
|
250
|
+
|
251
|
+
if (!(im_return = im_minpos_vec(im, x, y, out, len))) {
|
252
|
+
for (i = 0; i < len; i++) {
|
253
|
+
t = rb_ary_new3(3, INT2NUM(x[i]), INT2NUM(y[i]), DBL2NUM(out[i]));
|
254
|
+
rb_ary_push(ary, t);
|
255
|
+
}
|
256
|
+
}
|
257
|
+
|
258
|
+
xfree(x);
|
259
|
+
xfree(y);
|
260
|
+
xfree(out);
|
261
|
+
|
262
|
+
if(im_return)
|
263
|
+
vips_lib_error();
|
264
|
+
|
265
|
+
return ary;
|
266
|
+
}
|
267
|
+
|
268
|
+
/*
|
269
|
+
* call-seq:
|
270
|
+
* im.minpos -> x, y, value
|
271
|
+
* im.minpos(n) -> [ x, y, value ], ...
|
272
|
+
*
|
273
|
+
* Function to find the minimum of an image. Works for any image type. Returns
|
274
|
+
* an array with the x and y coordinates of the minimum value and the
|
275
|
+
* corresponding value. If <i>n</i> is given, returns the <i>n</i> lowest
|
276
|
+
* values. For complex images, finds the pixel with the lowest modulus.
|
277
|
+
*/
|
278
|
+
|
279
|
+
VALUE
|
280
|
+
img_minpos(int argc, VALUE *argv, VALUE obj) {
|
281
|
+
VALUE v_num;
|
282
|
+
|
283
|
+
rb_scan_args(argc, argv, "01", &v_num);
|
284
|
+
if (NIL_P(v_num))
|
285
|
+
return img_minpos_single(obj);
|
286
|
+
else
|
287
|
+
return img_minpos_n(obj, NUM2INT(v_num));
|
288
|
+
}
|
289
|
+
|
290
|
+
/*
|
291
|
+
* call-seq:
|
292
|
+
* im.bandmean -> image
|
293
|
+
*
|
294
|
+
* Creates a one-band image where each pixel is the average of the bands for
|
295
|
+
* that pixel in the input image. The output band format is the same as the
|
296
|
+
* input band format. Integer types use round-to-nearest averaging.
|
297
|
+
*
|
298
|
+
*/
|
299
|
+
|
300
|
+
VALUE
|
301
|
+
img_bandmean(VALUE obj)
|
302
|
+
{
|
303
|
+
RUBY_VIPS_UNARY(im_bandmean);
|
304
|
+
}
|
305
|
+
|
306
|
+
/*
|
307
|
+
* call-seq:
|
308
|
+
* im.add(other_image) -> image
|
309
|
+
* im + other_image -> image
|
310
|
+
*
|
311
|
+
* This operation calculates im + <i>other_image</i> and writes the result to
|
312
|
+
* a new image. The images must be the same size. They may have any format.
|
313
|
+
*
|
314
|
+
* If the number of bands differs, one of the images must have one band. In
|
315
|
+
* this case, an n-band image is formed from the one-band image by joining n
|
316
|
+
* copies of the one-band image together, and then the two n-band images are
|
317
|
+
* operated upon.
|
318
|
+
*
|
319
|
+
* The two input images are cast up to the smallest common type.
|
320
|
+
*/
|
321
|
+
|
322
|
+
VALUE
|
323
|
+
img_add(VALUE obj, VALUE obj2)
|
324
|
+
{
|
325
|
+
RUBY_VIPS_BINARY(im_add);
|
326
|
+
}
|
327
|
+
|
328
|
+
/*
|
329
|
+
* call-seq:
|
330
|
+
* im.subtract(other_image) -> image
|
331
|
+
* im - other_image -> image
|
332
|
+
*
|
333
|
+
* This operation calculates im - <i>image</i> and writes the result to a new
|
334
|
+
* image. The images must be the same size. They may have any format.
|
335
|
+
*
|
336
|
+
* If the number of bands differs, one of the images must have one band. In this
|
337
|
+
* case, an n-band image is formed from the one-band image by joining n copies
|
338
|
+
* of the one-band image together, and then the two n-band images are operated
|
339
|
+
* upon.
|
340
|
+
*
|
341
|
+
* The two input images are cast up to the smallest common type.
|
342
|
+
*/
|
343
|
+
|
344
|
+
VALUE
|
345
|
+
img_subtract(VALUE obj, VALUE obj2)
|
346
|
+
{
|
347
|
+
RUBY_VIPS_BINARY(im_subtract);
|
348
|
+
}
|
349
|
+
|
350
|
+
/*
|
351
|
+
* call-seq:
|
352
|
+
* im.invert -> image
|
353
|
+
*
|
354
|
+
* This operation calculates (255 - im). The operation works on uchar images
|
355
|
+
* only. The input can have any no of channels.
|
356
|
+
*
|
357
|
+
* See Image#exptra for a function which can process any input image type.
|
358
|
+
*/
|
359
|
+
|
360
|
+
VALUE
|
361
|
+
img_invert(VALUE obj)
|
362
|
+
{
|
363
|
+
RUBY_VIPS_UNARY(im_invert);
|
364
|
+
}
|
365
|
+
|
366
|
+
static VALUE
|
367
|
+
img_lin_mult(int argc, VALUE *argv_a, VALUE *argv_b, VALUE obj)
|
368
|
+
{
|
369
|
+
double *a, *b;
|
370
|
+
int i;
|
371
|
+
|
372
|
+
GetImg(obj, data, im);
|
373
|
+
OutImg(obj, new, data_new, im_new);
|
374
|
+
|
375
|
+
a = IM_ARRAY(im_new, argc, double);
|
376
|
+
b = IM_ARRAY(im_new, argc, double);
|
377
|
+
|
378
|
+
for (i = 0; i < argc; i++) {
|
379
|
+
a[i] = NUM2DBL(argv_a[i]);
|
380
|
+
b[i] = NUM2DBL(argv_b[i]);
|
381
|
+
}
|
382
|
+
|
383
|
+
if (im_lintra_vec(argc, a, im, b, im_new))
|
384
|
+
vips_lib_error();
|
385
|
+
|
386
|
+
return new;
|
387
|
+
}
|
388
|
+
|
389
|
+
/*
|
390
|
+
* call-seq:
|
391
|
+
* im.lin(a, b) -> image
|
392
|
+
* im.lin([a1, a2, a3], [b1, b2, b3]) -> image
|
393
|
+
*
|
394
|
+
* Pass an image through a linear transform - ie. im * <i>a</i> + <i>b</i>.
|
395
|
+
* Output is always float for integer input, double for double input, complex
|
396
|
+
* for complex input and double complex for double complex input.
|
397
|
+
*
|
398
|
+
* If the arrays are passed in and they have the same number of elements as
|
399
|
+
* there are bands in the image, then one array element is used for each band.
|
400
|
+
* If the arrays have more than one element and the image only has a single
|
401
|
+
* band, the result is a many-band image where each band corresponds to one
|
402
|
+
* array element.
|
403
|
+
*/
|
404
|
+
|
405
|
+
VALUE
|
406
|
+
img_lin(VALUE obj, VALUE a, VALUE b)
|
407
|
+
{
|
408
|
+
int len = 1;
|
409
|
+
VALUE *a_v = &a;
|
410
|
+
VALUE *b_v = &b;
|
411
|
+
|
412
|
+
if (TYPE(a) == T_ARRAY) {
|
413
|
+
len = RARRAY_LEN(a);
|
414
|
+
|
415
|
+
if (len < 1 || len != RARRAY_LEN(b))
|
416
|
+
rb_raise(rb_eArgError, "argument arrays must be of equal length with at least one element");
|
417
|
+
|
418
|
+
a_v = RARRAY_PTR(a);
|
419
|
+
b_v = RARRAY_PTR(b);
|
420
|
+
}
|
421
|
+
|
422
|
+
return img_lin_mult(len, a_v, b_v, obj);
|
423
|
+
}
|
424
|
+
|
425
|
+
/*
|
426
|
+
* call-seq:
|
427
|
+
* im.multiply(other_image) -> image
|
428
|
+
* im * other_image -> image
|
429
|
+
*
|
430
|
+
* This operation calculates im * <i>other_image</i>. The images must be the
|
431
|
+
* same size. They may have any format.
|
432
|
+
*
|
433
|
+
* If the number of bands differs, one of the images must have one band. In
|
434
|
+
* this case, an n-band image is formed from the one-band image by joining n
|
435
|
+
* copies of the one-band image together, and then the two n-band images are
|
436
|
+
* operated upon.
|
437
|
+
*
|
438
|
+
* The two input images are cast up to the smallest common type.
|
439
|
+
*/
|
440
|
+
|
441
|
+
VALUE
|
442
|
+
img_multiply(VALUE obj, VALUE obj2)
|
443
|
+
{
|
444
|
+
RUBY_VIPS_BINARY(im_multiply);
|
445
|
+
}
|
446
|
+
|
447
|
+
static VALUE
|
448
|
+
img_remainder_img(VALUE obj, VALUE obj2)
|
449
|
+
{
|
450
|
+
RUBY_VIPS_BINARY(im_remainder);
|
451
|
+
}
|
452
|
+
|
453
|
+
static VALUE
|
454
|
+
img_remainder_const(int argc, VALUE *argv, VALUE obj)
|
455
|
+
{
|
456
|
+
int i;
|
457
|
+
double *c;
|
458
|
+
|
459
|
+
GetImg(obj, data, im);
|
460
|
+
OutImg(obj, new, data_new, im_new);
|
461
|
+
|
462
|
+
c = IM_ARRAY(im_new, argc, double);
|
463
|
+
for (i = 0; i < argc; i++)
|
464
|
+
c[i] = NUM2DBL(argv[i]);
|
465
|
+
|
466
|
+
if (im_remainder_vec(im, im_new, argc, c))
|
467
|
+
vips_lib_error();
|
468
|
+
|
469
|
+
return new;
|
470
|
+
}
|
471
|
+
|
472
|
+
/*
|
473
|
+
* call-seq:
|
474
|
+
* im % other_image -> image
|
475
|
+
* im % c -> image
|
476
|
+
* im % [c, ...] -> image
|
477
|
+
*
|
478
|
+
* im.remainder(other_image) -> image
|
479
|
+
* im.remainder(c) -> image
|
480
|
+
* im.remainder(c, ...) -> image
|
481
|
+
*
|
482
|
+
* The first form calculates im % <i>other_image</i> (remainder after
|
483
|
+
* division). The images must be the same size. They may have any non-complex
|
484
|
+
* format. For float formats, it calculates im - <i>other_image</i> * floor (im
|
485
|
+
* / <i>other_image</i>).
|
486
|
+
*
|
487
|
+
* If the number of bands differs, one of the images must have one band. In
|
488
|
+
* this case, an n-band image is formed from the one-band image by joining n
|
489
|
+
* copies of the one-band image together, and then the two n-band images are
|
490
|
+
* operated upon.
|
491
|
+
*
|
492
|
+
* The two input images are cast up to the smallest common type.
|
493
|
+
*
|
494
|
+
* The second and third form calculates im % <i>c</i> (remainder after division
|
495
|
+
* by constant). The image may have any non-complex format. For float formats,
|
496
|
+
* calculates im - <i>c</i> * floor (im / <i>c</i>).
|
497
|
+
*
|
498
|
+
* If the number of image bands and constants differs, then the image must have
|
499
|
+
* one band or there must only one constant. Either the image is up-banded by
|
500
|
+
* joining n copies of the one-band image together, or the same constant is
|
501
|
+
* used for all image bands.
|
502
|
+
*/
|
503
|
+
|
504
|
+
VALUE
|
505
|
+
img_remainder(int argc, VALUE *argv, VALUE obj)
|
506
|
+
{
|
507
|
+
if (argc < 1)
|
508
|
+
rb_raise(rb_eArgError, "Expected at least one constant");
|
509
|
+
else if (argc == 1 && CLASS_OF(argv[0]) == cVIPSImage)
|
510
|
+
return img_remainder_img(obj, argv[0]);
|
511
|
+
else
|
512
|
+
return img_remainder_const(argc, argv, obj);
|
513
|
+
}
|
514
|
+
|
515
|
+
VALUE
|
516
|
+
img_remainder_binop(VALUE obj, VALUE arg)
|
517
|
+
{
|
518
|
+
int argc = 1;
|
519
|
+
VALUE *argv = &arg;
|
520
|
+
|
521
|
+
if (TYPE(arg) == T_ARRAY) {
|
522
|
+
argc = RARRAY_LEN(arg);
|
523
|
+
argv = RARRAY_PTR(arg);
|
524
|
+
}
|
525
|
+
|
526
|
+
return img_remainder(argc, argv, obj);
|
527
|
+
}
|
528
|
+
|
529
|
+
/*
|
530
|
+
* call-seq:
|
531
|
+
* im.divide(other_image) -> image
|
532
|
+
* im / other_image -> image
|
533
|
+
*
|
534
|
+
* This operation calculates im / <i>other_image</i>. The images must be the
|
535
|
+
* same size. They may have any format.
|
536
|
+
*
|
537
|
+
* If the number of bands differs, one of the images must have one band. In
|
538
|
+
* this case, an n-band image is formed from the one-band image by joining n
|
539
|
+
* copies of the one-band image together, and then the two n-band images are
|
540
|
+
* operated upon.
|
541
|
+
*
|
542
|
+
* The two input images are cast up to the smallest common type.
|
543
|
+
*/
|
544
|
+
|
545
|
+
VALUE
|
546
|
+
img_divide(VALUE obj, VALUE obj2)
|
547
|
+
{
|
548
|
+
RUBY_VIPS_BINARY(im_divide);
|
549
|
+
}
|
550
|
+
|
551
|
+
/*
|
552
|
+
* call-seq:
|
553
|
+
* im.recomb(array) -> image
|
554
|
+
*
|
555
|
+
* This operation recombines an image's bands. Each pixel in im is treated as
|
556
|
+
* an n-element vector, where n is the number of bands in im, and multipled by
|
557
|
+
* the n x m matrix <i>array</i> to produce the m-band output image.
|
558
|
+
*
|
559
|
+
* The output image is always float, unless im is double, in which case it is
|
560
|
+
* double too. No complex images allowed.
|
561
|
+
*
|
562
|
+
* It's useful for various sorts of colour space conversions.
|
563
|
+
*/
|
564
|
+
|
565
|
+
VALUE
|
566
|
+
img_recomb(VALUE obj, VALUE recomb)
|
567
|
+
{
|
568
|
+
DOUBLEMASK *dmask;
|
569
|
+
|
570
|
+
GetImg(obj, data, im);
|
571
|
+
OutImg(obj, new, data_new, im_new);
|
572
|
+
|
573
|
+
mask_arg2mask(recomb, NULL, &dmask);
|
574
|
+
|
575
|
+
if (im_recomb(im, im_new, dmask))
|
576
|
+
vips_lib_error();
|
577
|
+
|
578
|
+
return new;
|
579
|
+
}
|
580
|
+
|
581
|
+
/*
|
582
|
+
* call-seq:
|
583
|
+
* im.sign -> image
|
584
|
+
*
|
585
|
+
* Finds the unit vector in the direction of the pixel value. For non-complex
|
586
|
+
* images, it returns a signed char image with values -1, 0, and 1 for
|
587
|
+
* negative, zero and positive pixels. For complex images, it returns a complex
|
588
|
+
* normalised to length 1.
|
589
|
+
*/
|
590
|
+
|
591
|
+
VALUE
|
592
|
+
img_sign(VALUE obj)
|
593
|
+
{
|
594
|
+
RUBY_VIPS_UNARY(im_sign);
|
595
|
+
}
|
596
|
+
|
597
|
+
/*
|
598
|
+
* call-seq:
|
599
|
+
* im.abs -> image
|
600
|
+
*
|
601
|
+
* This operation finds the absolute value of an image. It does a copy for
|
602
|
+
* unsigned integer types, negate for negative values in signed integer types,
|
603
|
+
* fabs(3) for float types, and calculate modulus for complex types.
|
604
|
+
*/
|
605
|
+
|
606
|
+
VALUE
|
607
|
+
img_abs(VALUE obj)
|
608
|
+
{
|
609
|
+
RUBY_VIPS_UNARY(im_abs);
|
610
|
+
}
|
611
|
+
|
612
|
+
/*
|
613
|
+
* call-seq:
|
614
|
+
* im.floor -> image
|
615
|
+
*
|
616
|
+
* For each pixel, find the largest integral value not less than. Copy for
|
617
|
+
* integer types. Output type == input type.
|
618
|
+
*/
|
619
|
+
|
620
|
+
VALUE
|
621
|
+
img_floor(VALUE obj)
|
622
|
+
{
|
623
|
+
RUBY_VIPS_UNARY(im_floor);
|
624
|
+
}
|
625
|
+
|
626
|
+
/*
|
627
|
+
* call-seq:
|
628
|
+
* im.rint -> image
|
629
|
+
*
|
630
|
+
* Finds the nearest integral value. Copy for integer types. Output type ==
|
631
|
+
* input type.
|
632
|
+
*/
|
633
|
+
|
634
|
+
VALUE
|
635
|
+
img_rint(VALUE obj)
|
636
|
+
{
|
637
|
+
RUBY_VIPS_UNARY(im_rint);
|
638
|
+
}
|
639
|
+
|
640
|
+
/*
|
641
|
+
* call-seq:
|
642
|
+
* im.ceil -> image
|
643
|
+
*
|
644
|
+
* For each pixel, find the smallest integral value not less than. Copy for
|
645
|
+
* integer types. Output type == input type.
|
646
|
+
*/
|
647
|
+
|
648
|
+
VALUE
|
649
|
+
img_ceil(VALUE obj)
|
650
|
+
{
|
651
|
+
RUBY_VIPS_UNARY(im_ceil);
|
652
|
+
}
|
653
|
+
|
654
|
+
/*
|
655
|
+
* call-seq:
|
656
|
+
* linreg(x) -> image
|
657
|
+
* linreg(*args) -> image
|
658
|
+
*
|
659
|
+
* Function to find perform pixelwise linear regression on an array of
|
660
|
+
* single band images. The output is a seven-band double image.
|
661
|
+
*
|
662
|
+
* <i>x</i> is the position of each image (pixel value is Y).
|
663
|
+
*/
|
664
|
+
|
665
|
+
VALUE
|
666
|
+
img_s_linreg(int argc, VALUE *argv, VALUE obj)
|
667
|
+
{
|
668
|
+
vipsImg *in;
|
669
|
+
IMAGE **ins;
|
670
|
+
double *vips_xs;
|
671
|
+
VALUE cur_img;
|
672
|
+
int i;
|
673
|
+
OutPartial(new, data_new, im_new);
|
674
|
+
|
675
|
+
vips_xs = IM_ARRAY(im_new, argc, double);
|
676
|
+
ins = IM_ARRAY(im_new, argc + 1, IMAGE*);
|
677
|
+
|
678
|
+
ins[argc] = NULL; /* takes a NULL terminated array of IMAGE pointers */
|
679
|
+
|
680
|
+
for (i = 0; i < argc; i++) {
|
681
|
+
cur_img = RARRAY_PTR(argv[i])[0];
|
682
|
+
img_add_dep(data_new, cur_img);
|
683
|
+
|
684
|
+
Data_Get_Struct(cur_img, vipsImg, in);
|
685
|
+
ins[i] = in->in;
|
686
|
+
|
687
|
+
vips_xs[i] = NUM2DBL(RARRAY_PTR(argv[i])[1]);
|
688
|
+
}
|
689
|
+
|
690
|
+
if (im_linreg(ins, im_new, vips_xs))
|
691
|
+
vips_lib_error();
|
692
|
+
|
693
|
+
return new;
|
694
|
+
}
|
695
|
+
|
696
|
+
/*
|
697
|
+
* call-seq:
|
698
|
+
* im.point(interpolator_sym, x, y, band) -> number
|
699
|
+
*
|
700
|
+
* Find the value at (@x, @y) in given band of image.
|
701
|
+
* Non-integral values are calculated using the supplied interpolator, e.g.
|
702
|
+
* :bilinear.
|
703
|
+
*
|
704
|
+
* To get a list of available interpolators, look at
|
705
|
+
* VIPS::Interpolator::INTERPOLATORS.keys
|
706
|
+
*/
|
707
|
+
|
708
|
+
VALUE
|
709
|
+
img_point(VALUE obj, VALUE itrp_sym, VALUE x, VALUE y, VALUE band)
|
710
|
+
{
|
711
|
+
double out;
|
712
|
+
VipsInterpolate *itrp_vips = interp_lookup(itrp_sym);
|
713
|
+
GetImg(obj, data, im);
|
714
|
+
|
715
|
+
if (im_point(im, itrp_vips, NUM2DBL(x), NUM2DBL(y), NUM2INT(band), &out))
|
716
|
+
vips_lib_error();
|
717
|
+
|
718
|
+
return DBL2NUM(out);
|
719
|
+
}
|
720
|
+
|
721
|
+
/*
|
722
|
+
* call-seq:
|
723
|
+
* im.pow(c, ...) -> image
|
724
|
+
*
|
725
|
+
* im ** c -> image
|
726
|
+
* im ** [c, ...] -> image
|
727
|
+
*
|
728
|
+
* Tansforms each pixel value in the input image to value ** <i>c</i> in the
|
729
|
+
* output image. It detects division by zero, setting those pixels to zero in
|
730
|
+
* the output. Beware: it does this silently!
|
731
|
+
*
|
732
|
+
* If one constant <i>c</i> is given, that constant is used for each image
|
733
|
+
* band. If more than one value is given, it must have the same number of
|
734
|
+
* elements as there are bands in the image, and one element is used for each
|
735
|
+
* band.
|
736
|
+
*/
|
737
|
+
|
738
|
+
VALUE
|
739
|
+
img_pow(int argc, VALUE *argv, VALUE obj)
|
740
|
+
{
|
741
|
+
double *c;
|
742
|
+
int i;
|
743
|
+
|
744
|
+
if (argc < 1)
|
745
|
+
rb_raise(rb_eArgError, "Expected at least one constant");
|
746
|
+
|
747
|
+
GetImg(obj, data, im);
|
748
|
+
OutImg(obj, new, data_new, im_new);
|
749
|
+
|
750
|
+
c = IM_ARRAY(im_new, argc, double);
|
751
|
+
|
752
|
+
for (i = 0; i < argc; i++)
|
753
|
+
c[i] = NUM2DBL(argv[i]);
|
754
|
+
|
755
|
+
if (im_powtra_vec(im, im_new, argc, c))
|
756
|
+
vips_lib_error();
|
757
|
+
|
758
|
+
return new;
|
759
|
+
}
|
760
|
+
|
761
|
+
VALUE
|
762
|
+
img_pow_binop(VALUE obj, VALUE arg)
|
763
|
+
{
|
764
|
+
int argc = 1;
|
765
|
+
VALUE *argv = &arg;
|
766
|
+
|
767
|
+
if (TYPE(arg) == T_ARRAY) {
|
768
|
+
argc = RARRAY_LEN(arg);
|
769
|
+
argv = RARRAY_PTR(arg);
|
770
|
+
}
|
771
|
+
|
772
|
+
return img_pow(argc, argv, obj);
|
773
|
+
}
|
774
|
+
|
775
|
+
/*
|
776
|
+
* call-seq:
|
777
|
+
* im.expn(c, ...) -> image
|
778
|
+
*
|
779
|
+
* Transforms each pixel value of the input image to <i>c</i> ** value in the
|
780
|
+
* output image. It detects division by zero, setting those pixels to zero in
|
781
|
+
* the output. Beware: it does this silently!
|
782
|
+
*
|
783
|
+
* If one constant <i>c</i> is given, that constant is used for each image
|
784
|
+
* band. If more than one value is given, it must have the same number of
|
785
|
+
* elements as there are bands in the image, and one element is used for each
|
786
|
+
* band.
|
787
|
+
*/
|
788
|
+
|
789
|
+
VALUE
|
790
|
+
img_expn(int argc, VALUE *argv, VALUE obj)
|
791
|
+
{
|
792
|
+
double *c;
|
793
|
+
int i;
|
794
|
+
GetImg(obj, data, im);
|
795
|
+
OutImg(obj, new, data_new, im_new);
|
796
|
+
|
797
|
+
c = IM_ARRAY(im_new, argc, double);
|
798
|
+
|
799
|
+
for (i = 0; i < argc; i++)
|
800
|
+
c[i] = NUM2DBL(argv[i]);
|
801
|
+
|
802
|
+
if (im_expntra_vec(im, im_new, argc, c))
|
803
|
+
vips_lib_error();
|
804
|
+
|
805
|
+
return new;
|
806
|
+
}
|
807
|
+
|
808
|
+
/*
|
809
|
+
* call-seq:
|
810
|
+
* im.log -> image
|
811
|
+
*
|
812
|
+
* For each pixel, calculate the natural logarithm. The output type is float,
|
813
|
+
* unless the input is double, in which case the output is double. Non-complex
|
814
|
+
* images only.
|
815
|
+
*/
|
816
|
+
|
817
|
+
VALUE
|
818
|
+
img_log(VALUE obj)
|
819
|
+
{
|
820
|
+
RUBY_VIPS_UNARY(im_logtra);
|
821
|
+
}
|
822
|
+
|
823
|
+
/*
|
824
|
+
* call-seq:
|
825
|
+
* im.log10 -> image
|
826
|
+
*
|
827
|
+
* For each pixel, calculate the base 10 logarithm. The output type is float,
|
828
|
+
* unless the input is double, in which case the output is double. Non-complex
|
829
|
+
* images only.
|
830
|
+
*/
|
831
|
+
|
832
|
+
VALUE
|
833
|
+
img_log10(VALUE obj)
|
834
|
+
{
|
835
|
+
RUBY_VIPS_UNARY(im_log10tra);
|
836
|
+
}
|
837
|
+
|
838
|
+
/*
|
839
|
+
* call-seq:
|
840
|
+
* im.sin -> image
|
841
|
+
*
|
842
|
+
* For each pixel, calculate the sine. Angles are expressed in degrees. The
|
843
|
+
* output type is float, unless the input is double, in which case the output
|
844
|
+
* is double. Non-complex images only.
|
845
|
+
*/
|
846
|
+
|
847
|
+
VALUE
|
848
|
+
img_sin(VALUE obj)
|
849
|
+
{
|
850
|
+
RUBY_VIPS_UNARY(im_sintra);
|
851
|
+
}
|
852
|
+
|
853
|
+
/*
|
854
|
+
* call-seq:
|
855
|
+
* im.cos -> image
|
856
|
+
*
|
857
|
+
* For each pixel, calculate the cosine. Angles are expressed in degrees. The
|
858
|
+
* output type is float, unless the input is double, in which case the output
|
859
|
+
* is double. Non-complex images only.
|
860
|
+
*/
|
861
|
+
|
862
|
+
VALUE
|
863
|
+
img_cos(VALUE obj)
|
864
|
+
{
|
865
|
+
RUBY_VIPS_UNARY(im_costra);
|
866
|
+
}
|
867
|
+
|
868
|
+
/*
|
869
|
+
* call-seq:
|
870
|
+
* im.tan -> image
|
871
|
+
*
|
872
|
+
* For each pixel, calculate the tangent. Angles are expressed in degrees. The
|
873
|
+
* output type is float, unless the input is double, in which case the output
|
874
|
+
* is double. Non-complex images only.
|
875
|
+
*/
|
876
|
+
|
877
|
+
VALUE
|
878
|
+
img_tan(VALUE obj)
|
879
|
+
{
|
880
|
+
RUBY_VIPS_UNARY(im_tantra);
|
881
|
+
}
|
882
|
+
|
883
|
+
/*
|
884
|
+
* call-seq:
|
885
|
+
* im.asin -> image
|
886
|
+
*
|
887
|
+
* For each pixel, calculate the arc or inverse sine. Angles are expressed in
|
888
|
+
* degrees. The output type is float, unless the input is double, in which case
|
889
|
+
* the output is double. Non-complex images only.
|
890
|
+
*/
|
891
|
+
|
892
|
+
VALUE
|
893
|
+
img_asin(VALUE obj)
|
894
|
+
{
|
895
|
+
RUBY_VIPS_UNARY(im_asintra);
|
896
|
+
}
|
897
|
+
|
898
|
+
/*
|
899
|
+
* call-seq:
|
900
|
+
* im.acos -> image
|
901
|
+
*
|
902
|
+
* For each pixel, calculate the arc or inverse cosine. Angles are expressed in
|
903
|
+
* degrees. The output type is float, unless the input is double, in which case
|
904
|
+
* the output is double. Non-complex images only.
|
905
|
+
*/
|
906
|
+
|
907
|
+
VALUE
|
908
|
+
img_acos(VALUE obj)
|
909
|
+
{
|
910
|
+
RUBY_VIPS_UNARY(im_acostra);
|
911
|
+
}
|
912
|
+
|
913
|
+
/*
|
914
|
+
* call-seq:
|
915
|
+
* im.atan -> image
|
916
|
+
*
|
917
|
+
* For each pixel, calculate the arc or inverse tangent. Angles are expressed
|
918
|
+
* in degrees. The output type is float, unless the input is double, in which
|
919
|
+
* case the output is double. Non-complex images only.
|
920
|
+
*/
|
921
|
+
|
922
|
+
VALUE
|
923
|
+
img_atan(VALUE obj)
|
924
|
+
{
|
925
|
+
RUBY_VIPS_UNARY(im_atantra);
|
926
|
+
}
|
927
|
+
|
928
|
+
/*
|
929
|
+
* call-seq:
|
930
|
+
* im.cross_phase(other_image) -> image
|
931
|
+
*
|
932
|
+
* Find the phase of the cross power spectrum of two complex images, expressed
|
933
|
+
* as a complex image where the modulus of each pixel is one.
|
934
|
+
*/
|
935
|
+
|
936
|
+
VALUE
|
937
|
+
img_cross_phase(VALUE obj, VALUE obj2)
|
938
|
+
{
|
939
|
+
RUBY_VIPS_BINARY(im_cross_phase);
|
940
|
+
}
|