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
@@ -0,0 +1,9 @@
|
|
1
|
+
VALUE img_affinei(int, VALUE*, VALUE);
|
2
|
+
VALUE img_affinei_resize(int, VALUE*, VALUE);
|
3
|
+
VALUE img_stretch3(int, VALUE*, VALUE);
|
4
|
+
VALUE img_shrink(int, VALUE*, VALUE);
|
5
|
+
VALUE img_rightshift_size(VALUE, VALUE, VALUE, VALUE);
|
6
|
+
VALUE img_match_linear(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE,
|
7
|
+
VALUE, VALUE);
|
8
|
+
VALUE img_match_linear_search(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE,
|
9
|
+
VALUE, VALUE, VALUE, VALUE, VALUE);
|
data/ext/interpolator.c
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
#include "ruby_vips.h"
|
2
|
+
|
3
|
+
static VALUE cVIPSInterpolator;
|
4
|
+
static ID id_INTERPOLATORS;
|
5
|
+
|
6
|
+
VipsInterpolate*
|
7
|
+
interp_lookup(VALUE itrp_sym)
|
8
|
+
{
|
9
|
+
VALUE rb_interp;
|
10
|
+
VipsInterpolate *itrp;
|
11
|
+
VALUE hVIPSInterpolators = rb_const_get(cVIPSInterpolator,
|
12
|
+
id_INTERPOLATORS);
|
13
|
+
|
14
|
+
rb_interp = rb_hash_aref(hVIPSInterpolators, itrp_sym);
|
15
|
+
Data_Get_Struct(rb_interp, VipsInterpolate, itrp);
|
16
|
+
|
17
|
+
return itrp;
|
18
|
+
}
|
19
|
+
|
20
|
+
static void*
|
21
|
+
interp_register(VipsInterpolateClass *itrp, void *hash)
|
22
|
+
{
|
23
|
+
VipsInterpolate *inst;
|
24
|
+
VipsObjectClass *klass = (VipsObjectClass*) itrp;;
|
25
|
+
VALUE obj, hVIPSInterpolators = (VALUE)hash;
|
26
|
+
|
27
|
+
inst = vips_interpolate_new(klass->nickname);
|
28
|
+
obj = Data_Wrap_Struct(cVIPSInterpolator, 0, 0, inst);
|
29
|
+
|
30
|
+
rb_hash_aset(hVIPSInterpolators, ID2SYM(rb_intern(klass->nickname)), obj);
|
31
|
+
|
32
|
+
return NULL;
|
33
|
+
}
|
34
|
+
|
35
|
+
static void
|
36
|
+
interp_register_builtin()
|
37
|
+
{
|
38
|
+
VALUE hVIPSInterpolators = rb_hash_new();
|
39
|
+
|
40
|
+
/* Hash of available interpolators. Keys are the symbols, and values are
|
41
|
+
* interpolator objects.
|
42
|
+
*/
|
43
|
+
rb_define_const(cVIPSInterpolator, "INTERPOLATORS", hVIPSInterpolators);
|
44
|
+
|
45
|
+
vips_class_map_concrete_all(
|
46
|
+
g_type_from_name( "VipsInterpolate" ),
|
47
|
+
(void *) interp_register,
|
48
|
+
(void *) hVIPSInterpolators
|
49
|
+
);
|
50
|
+
}
|
51
|
+
|
52
|
+
|
53
|
+
/*
|
54
|
+
* call-seq:
|
55
|
+
* interp.nickname -> string
|
56
|
+
*
|
57
|
+
* Retrieve the internally used nickname of the interpolator.
|
58
|
+
*/
|
59
|
+
|
60
|
+
static VALUE
|
61
|
+
interp_nickname(VALUE obj)
|
62
|
+
{
|
63
|
+
VipsObject *v_obj;
|
64
|
+
Data_Get_Struct(obj, VipsObject, v_obj);
|
65
|
+
return rb_str_new2(v_obj->nickname);
|
66
|
+
}
|
67
|
+
|
68
|
+
/*
|
69
|
+
* call-seq:
|
70
|
+
* interp.description -> string
|
71
|
+
*
|
72
|
+
* Retrieve the description of the interpolator.
|
73
|
+
*/
|
74
|
+
|
75
|
+
static VALUE
|
76
|
+
interp_description(VALUE obj)
|
77
|
+
{
|
78
|
+
VipsObject *v_obj;
|
79
|
+
Data_Get_Struct(obj, VipsObject, v_obj);
|
80
|
+
return rb_str_new2(v_obj->description);
|
81
|
+
}
|
82
|
+
|
83
|
+
/*
|
84
|
+
* VIPS Interpolators determine how color values will be estimated when an
|
85
|
+
* image is modified.
|
86
|
+
*
|
87
|
+
* This class provides information on which interpolators are available to
|
88
|
+
* VIPS.
|
89
|
+
*/
|
90
|
+
|
91
|
+
void
|
92
|
+
init_Interpolator()
|
93
|
+
{
|
94
|
+
cVIPSInterpolator = rb_define_class_under(mVIPS, "Interpolator", rb_cObject);
|
95
|
+
|
96
|
+
rb_define_method(cVIPSInterpolator, "nickname", interp_nickname, 0);
|
97
|
+
rb_define_method(cVIPSInterpolator, "description", interp_description, 0);
|
98
|
+
|
99
|
+
id_INTERPOLATORS = rb_intern("INTERPOLATORS");
|
100
|
+
|
101
|
+
interp_register_builtin();
|
102
|
+
|
103
|
+
#if 0
|
104
|
+
VALUE mVIPS = rb_define_module("VIPS");
|
105
|
+
#endif
|
106
|
+
}
|
data/ext/interpolator.h
ADDED
data/ext/mask.c
ADDED
@@ -0,0 +1,349 @@
|
|
1
|
+
#include "ruby_vips.h"
|
2
|
+
#include "mask.h"
|
3
|
+
#include "image.h"
|
4
|
+
|
5
|
+
VALUE cVIPSMask;
|
6
|
+
|
7
|
+
static void
|
8
|
+
mask_free(vipsMask *msk)
|
9
|
+
{
|
10
|
+
if(msk->dmask)
|
11
|
+
im_free_dmask(msk->dmask);
|
12
|
+
|
13
|
+
if(msk->imask)
|
14
|
+
im_free_imask(msk->imask);
|
15
|
+
|
16
|
+
xfree(msk);
|
17
|
+
}
|
18
|
+
|
19
|
+
VALUE
|
20
|
+
mask_alloc(VALUE klass)
|
21
|
+
{
|
22
|
+
vipsMask *msk;
|
23
|
+
VALUE new = Data_Make_Struct(klass, vipsMask, 0, mask_free, msk);
|
24
|
+
msk->imask = NULL;
|
25
|
+
msk->dmask = NULL;
|
26
|
+
|
27
|
+
return new;
|
28
|
+
}
|
29
|
+
|
30
|
+
static int
|
31
|
+
ary_is_int_2d(VALUE ary)
|
32
|
+
{
|
33
|
+
Check_Type(ary, T_ARRAY);
|
34
|
+
|
35
|
+
VALUE *row, *rows = RARRAY_PTR(ary);
|
36
|
+
int i, j;
|
37
|
+
for(i = 0; i < RARRAY_LEN(ary); i++) {
|
38
|
+
Check_Type(rows[i], T_ARRAY);
|
39
|
+
for(j = 0; j < RARRAY_LEN(rows[i]); j++) {
|
40
|
+
row = RARRAY_PTR(rows[i]);
|
41
|
+
if(TYPE(row[j]) != T_FIXNUM)
|
42
|
+
return 0;
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
return 1;
|
47
|
+
}
|
48
|
+
|
49
|
+
/* initialize an INTMASK from a ruby array */
|
50
|
+
|
51
|
+
static INTMASK*
|
52
|
+
mask_ary2imask(VALUE coeffs)
|
53
|
+
{
|
54
|
+
INTMASK *msk;
|
55
|
+
VALUE row, *rows = RARRAY_PTR(coeffs);
|
56
|
+
int i, j, num_cols, num_rows = RARRAY_LEN(coeffs);
|
57
|
+
|
58
|
+
num_cols = RARRAY_LEN(rows[0]);
|
59
|
+
if( !(msk = im_create_imask("mask_initialize_imask", num_cols, num_rows)) )
|
60
|
+
vips_lib_error();
|
61
|
+
|
62
|
+
for(i = 0; i < num_rows; i++) {
|
63
|
+
row = rows[i];
|
64
|
+
for(j = 0; j < RARRAY_LEN(row) && j < num_cols; j++)
|
65
|
+
msk->coeff[i * num_cols + j] = NUM2INT(RARRAY_PTR(row)[j]);
|
66
|
+
}
|
67
|
+
|
68
|
+
return msk;
|
69
|
+
}
|
70
|
+
|
71
|
+
static DOUBLEMASK*
|
72
|
+
mask_ary2dmask(VALUE coeffs)
|
73
|
+
{
|
74
|
+
DOUBLEMASK *msk;
|
75
|
+
VALUE row, *rows = RARRAY_PTR(coeffs);
|
76
|
+
int i, j, num_cols, num_rows = RARRAY_LEN(coeffs);
|
77
|
+
|
78
|
+
num_cols = RARRAY_LEN(rows[0]);
|
79
|
+
if (!(msk = im_create_dmask("mask_ary2dmask", num_cols, num_rows)))
|
80
|
+
vips_lib_error();
|
81
|
+
|
82
|
+
for(i = 0; i < num_rows; i++) {
|
83
|
+
row = rows[i];
|
84
|
+
for(j = 0; j < RARRAY_LEN(row) && j < num_cols; j++)
|
85
|
+
msk->coeff[i * num_cols + j] = NUM2DBL(RARRAY_PTR(row)[j]);
|
86
|
+
}
|
87
|
+
|
88
|
+
return msk;
|
89
|
+
}
|
90
|
+
|
91
|
+
/*
|
92
|
+
* call-seq:
|
93
|
+
* Mask.new(coeffs, scale=1, offset=0) -> mask
|
94
|
+
*
|
95
|
+
* Create a new Mask object. <i>coeffs</i> is a two-dimensional array where
|
96
|
+
* every row must have the same length. Note that some methods require a mask
|
97
|
+
* where all values in <i>coeffs</i> are whole integers.
|
98
|
+
*/
|
99
|
+
static VALUE
|
100
|
+
mask_initialize(int argc, VALUE *argv, VALUE obj)
|
101
|
+
{
|
102
|
+
VALUE coeffs, scale, offset;
|
103
|
+
vipsMask *msk;
|
104
|
+
Data_Get_Struct(obj, vipsMask, msk);
|
105
|
+
|
106
|
+
rb_scan_args(argc, argv, "12", &coeffs, &scale, &offset);
|
107
|
+
|
108
|
+
if (NIL_P(scale))
|
109
|
+
scale = INT2NUM(1);
|
110
|
+
|
111
|
+
if (NIL_P(offset))
|
112
|
+
offset = INT2NUM(0);
|
113
|
+
|
114
|
+
if(TYPE(scale) == T_FIXNUM && TYPE(offset) == T_FIXNUM &&
|
115
|
+
ary_is_int_2d(coeffs)) {
|
116
|
+
msk->imask = mask_ary2imask(coeffs);
|
117
|
+
msk->imask->scale = NUM2INT(scale);
|
118
|
+
msk->imask->offset = NUM2INT(offset);
|
119
|
+
}
|
120
|
+
|
121
|
+
msk->dmask = mask_ary2dmask(coeffs);
|
122
|
+
msk->dmask->scale = NUM2DBL(scale);
|
123
|
+
msk->dmask->offset = NUM2DBL(offset);
|
124
|
+
|
125
|
+
return obj;
|
126
|
+
}
|
127
|
+
|
128
|
+
/*
|
129
|
+
* call-seq:
|
130
|
+
* msk.xsize -> number
|
131
|
+
*
|
132
|
+
* Retrieve the number of columns in the mask.
|
133
|
+
*/
|
134
|
+
|
135
|
+
static VALUE
|
136
|
+
mask_xsize(VALUE obj)
|
137
|
+
{
|
138
|
+
vipsMask *msk;
|
139
|
+
Data_Get_Struct(obj, vipsMask, msk);
|
140
|
+
return INT2FIX(msk->dmask->xsize);
|
141
|
+
}
|
142
|
+
|
143
|
+
/*
|
144
|
+
* call-seq:
|
145
|
+
* msk.ysize -> number
|
146
|
+
*
|
147
|
+
* Retrieve the number of rows in the mask.
|
148
|
+
*/
|
149
|
+
|
150
|
+
static VALUE
|
151
|
+
mask_ysize(VALUE obj)
|
152
|
+
{
|
153
|
+
vipsMask *msk;
|
154
|
+
Data_Get_Struct(obj, vipsMask, msk);
|
155
|
+
return INT2FIX(msk->dmask->ysize);
|
156
|
+
}
|
157
|
+
|
158
|
+
/*
|
159
|
+
* call-seq:
|
160
|
+
* msk.scale -> number
|
161
|
+
*
|
162
|
+
* Retrieve the scale of the mask.
|
163
|
+
*/
|
164
|
+
|
165
|
+
static VALUE
|
166
|
+
mask_scale(VALUE obj)
|
167
|
+
{
|
168
|
+
vipsMask *msk;
|
169
|
+
Data_Get_Struct(obj, vipsMask, msk);
|
170
|
+
return msk->imask ? INT2FIX(msk->imask->scale) : DBL2NUM(msk->dmask->scale);
|
171
|
+
}
|
172
|
+
|
173
|
+
/*
|
174
|
+
* call-seq:
|
175
|
+
* msk.offset -> number
|
176
|
+
*
|
177
|
+
* Retrieve the offset of the mask.
|
178
|
+
*/
|
179
|
+
|
180
|
+
static VALUE
|
181
|
+
mask_offset(VALUE obj)
|
182
|
+
{
|
183
|
+
vipsMask *msk;
|
184
|
+
Data_Get_Struct(obj, vipsMask, msk);
|
185
|
+
return msk->imask ? INT2FIX(msk->imask->offset) : DBL2NUM(msk->dmask->offset);
|
186
|
+
}
|
187
|
+
|
188
|
+
VALUE
|
189
|
+
imask2rb(INTMASK *msk)
|
190
|
+
{
|
191
|
+
int i, j;
|
192
|
+
VALUE row, rows = rb_ary_new2(msk->ysize);
|
193
|
+
|
194
|
+
for(i = 0; i < msk->ysize; i++) {
|
195
|
+
row = rb_ary_new2(msk->xsize);
|
196
|
+
rb_ary_push(rows, row);
|
197
|
+
for(j = 0; j < msk->xsize; j++) {
|
198
|
+
rb_ary_push(row, INT2FIX(msk->coeff[i * msk->xsize + j]));
|
199
|
+
}
|
200
|
+
}
|
201
|
+
|
202
|
+
return rows;
|
203
|
+
}
|
204
|
+
|
205
|
+
VALUE
|
206
|
+
dmask2rb(DOUBLEMASK *msk)
|
207
|
+
{
|
208
|
+
int i, j;
|
209
|
+
VALUE row, rows = rb_ary_new2(msk->ysize);
|
210
|
+
|
211
|
+
for(i = 0; i < msk->ysize; i++) {
|
212
|
+
row = rb_ary_new2(msk->xsize);
|
213
|
+
rb_ary_push(rows, row);
|
214
|
+
for(j = 0; j < msk->xsize; j++) {
|
215
|
+
rb_ary_push(row, DBL2NUM(msk->coeff[i * msk->xsize + j]));
|
216
|
+
}
|
217
|
+
}
|
218
|
+
|
219
|
+
return rows;
|
220
|
+
}
|
221
|
+
|
222
|
+
/*
|
223
|
+
* call-seq:
|
224
|
+
* msk.coeff -> array
|
225
|
+
*
|
226
|
+
* Retrieve the two-dimensional array of coefficients for the mask.
|
227
|
+
*/
|
228
|
+
|
229
|
+
static VALUE
|
230
|
+
mask_coeff(VALUE obj)
|
231
|
+
{
|
232
|
+
vipsMask *msk;
|
233
|
+
Data_Get_Struct(obj, vipsMask, msk);
|
234
|
+
if(msk->imask)
|
235
|
+
return imask2rb(msk->imask);
|
236
|
+
else
|
237
|
+
return dmask2rb(msk->dmask);
|
238
|
+
}
|
239
|
+
|
240
|
+
/*
|
241
|
+
* call-seq:
|
242
|
+
* msk.int? -> true or false
|
243
|
+
*
|
244
|
+
* Indicate whether all coefficients, the scale and the offset in the mask are
|
245
|
+
* integers. Some methods require an all-integer mask.
|
246
|
+
*/
|
247
|
+
|
248
|
+
static VALUE
|
249
|
+
mask_int_p(VALUE obj)
|
250
|
+
{
|
251
|
+
vipsMask *msk;
|
252
|
+
Data_Get_Struct(obj, vipsMask, msk);
|
253
|
+
if(msk->imask)
|
254
|
+
return Qtrue;
|
255
|
+
|
256
|
+
return Qfalse;
|
257
|
+
}
|
258
|
+
|
259
|
+
void
|
260
|
+
mask_arg2mask(VALUE arg, INTMASK **imask, DOUBLEMASK **dmask)
|
261
|
+
{
|
262
|
+
INTMASK *imask_t = NULL;
|
263
|
+
DOUBLEMASK *dmask_t = NULL;
|
264
|
+
vipsMask *data;
|
265
|
+
const char *errstr;
|
266
|
+
|
267
|
+
if (TYPE(arg) == T_ARRAY) {
|
268
|
+
if (imask && ary_is_int_2d(arg))
|
269
|
+
imask_t = mask_ary2imask(arg);
|
270
|
+
else if (dmask)
|
271
|
+
dmask_t = mask_ary2dmask(arg);
|
272
|
+
} else if (CLASS_OF(arg) == cVIPSMask) {
|
273
|
+
Data_Get_Struct(arg, vipsMask, data);
|
274
|
+
|
275
|
+
if (imask)
|
276
|
+
imask_t = data->imask;
|
277
|
+
if (dmask)
|
278
|
+
dmask_t = data->dmask;
|
279
|
+
}
|
280
|
+
|
281
|
+
if (!imask_t && !dmask_t) {
|
282
|
+
if (imask && dmask)
|
283
|
+
errstr = "Expected an array or a Mask";
|
284
|
+
else
|
285
|
+
errstr = "Expected an int array or an int Mask";
|
286
|
+
|
287
|
+
rb_raise(rb_eArgError, errstr);
|
288
|
+
}
|
289
|
+
|
290
|
+
if (imask)
|
291
|
+
*imask = imask_t;
|
292
|
+
|
293
|
+
if (dmask)
|
294
|
+
*dmask = dmask_t;
|
295
|
+
}
|
296
|
+
|
297
|
+
/*
|
298
|
+
* call-seq:
|
299
|
+
* msk.int? -> true or false
|
300
|
+
*
|
301
|
+
* Create a one-band, band format :DOUBLE image based on mask *self*.
|
302
|
+
*/
|
303
|
+
|
304
|
+
static VALUE
|
305
|
+
mask_to_image(VALUE obj)
|
306
|
+
{
|
307
|
+
vipsMask *msk;
|
308
|
+
|
309
|
+
OutImg(obj, new, data, im);
|
310
|
+
Data_Get_Struct(obj, vipsMask, msk);
|
311
|
+
|
312
|
+
if (im_mask2vips(msk->dmask, im))
|
313
|
+
vips_lib_error();
|
314
|
+
|
315
|
+
return new;
|
316
|
+
}
|
317
|
+
|
318
|
+
/*
|
319
|
+
* VIPS uses masks for various operations. A vips mask is a two-dimensional
|
320
|
+
* array with a scale and an offset.
|
321
|
+
*
|
322
|
+
* All operations that accept a Mask object also accept an array, in which case
|
323
|
+
* scale defaults to 1 and offset to zero.
|
324
|
+
*
|
325
|
+
* Some vips operations require that all values in the mask are integer values.
|
326
|
+
* These operations will raise an exception if given a mask that contains
|
327
|
+
* any float values.
|
328
|
+
*/
|
329
|
+
|
330
|
+
void
|
331
|
+
init_Mask()
|
332
|
+
{
|
333
|
+
cVIPSMask = rb_define_class_under(mVIPS, "Mask", rb_cObject);
|
334
|
+
|
335
|
+
rb_define_alloc_func(cVIPSMask, mask_alloc);
|
336
|
+
rb_define_method(cVIPSMask, "initialize", mask_initialize, -1);
|
337
|
+
rb_define_method(cVIPSMask, "xsize", mask_xsize, 0);
|
338
|
+
rb_define_method(cVIPSMask, "ysize", mask_ysize, 0);
|
339
|
+
rb_define_method(cVIPSMask, "scale", mask_scale, 0);
|
340
|
+
rb_define_method(cVIPSMask, "offset", mask_offset, 0);
|
341
|
+
rb_define_method(cVIPSMask, "coeff", mask_coeff, 0);
|
342
|
+
rb_define_method(cVIPSMask, "int?", mask_int_p, 0);
|
343
|
+
rb_define_method(cVIPSMask, "to_image", mask_to_image, 0);
|
344
|
+
|
345
|
+
#if 0
|
346
|
+
VALUE mVIPS = rb_define_module("VIPS");
|
347
|
+
#endif
|
348
|
+
}
|
349
|
+
|