ruby-vips 0.3.14 → 1.0.0

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.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +22 -0
  3. data/CHANGELOG.md +4 -0
  4. data/Gemfile +15 -0
  5. data/Gemfile.lock +46 -31
  6. data/{LICENSE → LICENSE.txt} +1 -1
  7. data/README.md +101 -145
  8. data/Rakefile +45 -0
  9. data/TODO +8 -32
  10. data/VERSION +1 -0
  11. data/example/annotate.rb +17 -0
  12. data/example/daltonize8.rb +75 -0
  13. data/example/example1.rb +84 -0
  14. data/example/example2.rb +31 -0
  15. data/example/example3.rb +19 -0
  16. data/example/example4.rb +18 -0
  17. data/example/example5.rb +31 -0
  18. data/example/trim8.rb +41 -0
  19. data/example/watermark.rb +44 -0
  20. data/example/wobble.rb +36 -0
  21. data/lib/vips.rb +151 -14
  22. data/lib/vips/access.rb +14 -0
  23. data/lib/vips/align.rb +11 -0
  24. data/lib/vips/angle.rb +12 -0
  25. data/lib/vips/angle45.rb +16 -0
  26. data/lib/vips/argument.rb +163 -0
  27. data/lib/vips/bandformat.rb +20 -0
  28. data/lib/vips/call.rb +302 -0
  29. data/lib/vips/coding.rb +14 -0
  30. data/lib/vips/demandstyle.rb +35 -0
  31. data/lib/vips/direction.rb +11 -0
  32. data/lib/vips/error.rb +30 -0
  33. data/lib/vips/extend.rb +22 -0
  34. data/lib/vips/foreignflags.rb +20 -0
  35. data/lib/vips/image.rb +1382 -0
  36. data/lib/vips/interpolate.rb +37 -0
  37. data/lib/vips/interpretation.rb +28 -0
  38. data/lib/vips/methods.rb +1807 -0
  39. data/lib/vips/operation.rb +19 -0
  40. data/ruby-vips8.gemspec +112 -0
  41. data/spec/image_spec.rb +515 -0
  42. data/spec/samples/balloon.v +0 -0
  43. data/spec/samples/ghost.ppm +405 -0
  44. data/spec/samples/huge.jpg +0 -0
  45. data/spec/samples/icc.jpg +0 -0
  46. data/spec/samples/lcd.icc +0 -0
  47. data/spec/samples/lion.svg +154 -0
  48. data/spec/samples/sample.csv +7 -0
  49. data/spec/samples/sample.exr +0 -0
  50. data/spec/samples/wagon.jpg +0 -0
  51. data/spec/samples/wagon.v +0 -0
  52. data/spec/spec_helper.rb +49 -0
  53. data/spec/vips_spec.rb +74 -0
  54. metadata +110 -70
  55. data/ext/extconf.rb +0 -31
  56. data/ext/header.c +0 -457
  57. data/ext/header.h +0 -9
  58. data/ext/image.c +0 -629
  59. data/ext/image.h +0 -72
  60. data/ext/image_arithmetic.c +0 -936
  61. data/ext/image_arithmetic.h +0 -38
  62. data/ext/image_boolean.c +0 -301
  63. data/ext/image_boolean.h +0 -8
  64. data/ext/image_colour.c +0 -590
  65. data/ext/image_colour.h +0 -36
  66. data/ext/image_conversion.c +0 -884
  67. data/ext/image_conversion.h +0 -38
  68. data/ext/image_convolution.c +0 -368
  69. data/ext/image_convolution.h +0 -13
  70. data/ext/image_freq_filt.c +0 -740
  71. data/ext/image_freq_filt.h +0 -27
  72. data/ext/image_histograms_lut.c +0 -643
  73. data/ext/image_histograms_lut.h +0 -28
  74. data/ext/image_morphology.c +0 -327
  75. data/ext/image_morphology.h +0 -13
  76. data/ext/image_mosaicing.c +0 -554
  77. data/ext/image_mosaicing.h +0 -15
  78. data/ext/image_relational.c +0 -384
  79. data/ext/image_relational.h +0 -8
  80. data/ext/image_resample.c +0 -249
  81. data/ext/image_resample.h +0 -9
  82. data/ext/interpolator.c +0 -106
  83. data/ext/interpolator.h +0 -7
  84. data/ext/mask.c +0 -347
  85. data/ext/mask.h +0 -18
  86. data/ext/reader.c +0 -261
  87. data/ext/reader.h +0 -2
  88. data/ext/ruby_vips.c +0 -188
  89. data/ext/ruby_vips.h +0 -72
  90. data/ext/tags +0 -450
  91. data/ext/writer.c +0 -371
  92. data/ext/writer.h +0 -2
  93. data/lib/vips/reader.rb +0 -272
  94. data/lib/vips/version.rb +0 -3
  95. data/lib/vips/writer.rb +0 -342
  96. data/ruby-vips.gemspec +0 -100
  97. data/ruby.supp +0 -134
@@ -1,28 +0,0 @@
1
- VALUE img_histgr(int, VALUE*, VALUE);
2
- VALUE img_histnd(VALUE, VALUE);
3
- VALUE img_hist_indexed(VALUE, VALUE);
4
- VALUE img_s_identity(VALUE, VALUE);
5
- VALUE img_s_identity_ushort(VALUE, VALUE, VALUE);
6
- VALUE img_s_invertlut(VALUE, VALUE, VALUE);
7
- VALUE img_s_buildlut(VALUE, VALUE);
8
- VALUE img_project(VALUE);
9
- VALUE img_histnorm(VALUE);
10
- VALUE img_histcum(VALUE);
11
- VALUE img_histeq(VALUE);
12
- VALUE img_histspec(VALUE, VALUE);
13
- VALUE img_maplut(VALUE, VALUE);
14
- VALUE img_histplot(VALUE);
15
- VALUE img_monotonic_p(VALUE);
16
- VALUE img_hist(int, VALUE*, VALUE);
17
- VALUE img_hsp(VALUE, VALUE);
18
- VALUE img_gammacorrect(VALUE, VALUE);
19
- VALUE img_mpercent_hist(VALUE, VALUE);
20
- VALUE img_mpercent(VALUE, VALUE);
21
- VALUE img_heq(int, VALUE*, VALUE);
22
- VALUE img_lhisteq(VALUE, VALUE, VALUE);
23
- VALUE img_stdif(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE);
24
- VALUE img_s_tone_build_range(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE,
25
- VALUE, VALUE, VALUE, VALUE);
26
- VALUE img_s_tone_build(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE,
27
- VALUE);
28
- VALUE img_tone_analyse(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE);
@@ -1,327 +0,0 @@
1
- #include "ruby_vips.h"
2
-
3
- /*
4
- * call-seq:
5
- * im.dilate(mask) -> image
6
- *
7
- * Dilates *self*, according to <i>mask</i>. The output image is the same size
8
- * as the input. Sets pixels in the output if *any* part of the mask matches.
9
- *
10
- * *self* must be a one channel binary image ie. with pixels that are either 0
11
- * (black) or 255 (white). This method assume that *self* contains white
12
- * objects against a black background.
13
- *
14
- * <i>mask</i> can be a two-dimensional array or a Mask object. All mask values
15
- * must be integers or this method will raise an exception.
16
- *
17
- * Mask coefficients can be either 0 (for object) or 255 (for background) or
18
- * 128 (for do not care). The mask should have odd length sides and the origin
19
- * of the mask is at location (mask_columns/2, mask_rows/2) integer division.
20
- *
21
- * Based on the book "Fundamentals of Digital Image Processing" by A. Jain,
22
- * pp 384-388, Prentice-Hall, 1989.
23
- */
24
-
25
- VALUE
26
- img_dilate(VALUE obj, VALUE mask)
27
- {
28
- INTMASK *imask;
29
-
30
- GetImg(obj, data, im);
31
- OutImg2(obj, mask, new, data_new, im_new);
32
-
33
- mask_arg2mask(mask, &imask, NULL);
34
-
35
- if (im_dilate(im, im_new, imask))
36
- vips_lib_error();
37
-
38
- return new;
39
- }
40
-
41
- /*
42
- * call-seq:
43
- * im.erode(mask) -> image
44
- *
45
- * Erodes *self*, according to <i>mask</i>. The output image is the same size
46
- * as the input. Sets pixels in the output if *all* part of the mask matches.
47
- *
48
- * *self* must be a one channel binary image ie. with pixels that are either 0
49
- * (black) or 255 (white). This method assume that *self* contains white
50
- * objects against a black background.
51
- *
52
- * <i>mask</i> can be a two-dimensional array or a Mask object. All mask values
53
- * must be integers or this method will raise an exception.
54
- *
55
- * Mask coefficients can be either 0 (for object) or 255 (for background) or
56
- * 128 (for do not care). The mask should have odd length sides and the origin
57
- * of the mask is at location (mask_columns/2, mask_rows/2) integer division.
58
- *
59
- * Based on the book "Fundamentals of Digital Image Processing" by A. Jain,
60
- * pp 384-388, Prentice-Hall, 1989.
61
- */
62
-
63
- VALUE
64
- img_erode(VALUE obj, VALUE mask)
65
- {
66
- INTMASK *imask;
67
-
68
- GetImg(obj, data, im);
69
- OutImg2(obj, mask, new, data_new, im_new);
70
-
71
- mask_arg2mask(mask, &imask, NULL);
72
-
73
- if (im_erode(im, im_new, imask))
74
- vips_lib_error();
75
-
76
- return new;
77
- }
78
-
79
- /*
80
- * call-seq:
81
- * im.rank(xsize, ysize, n) -> image
82
- *
83
- * Does rank filtering on an image. A window of size <i>xsize</i> by
84
- * <i>ysize</i> is passed over the image. At each position, the pixels inside
85
- * the window are sorted into ascending order and the pixel at the <i>n</i>th
86
- * position is output. <i>n</i> numbers from 0.
87
- *
88
- * It works for any non-complex image type, with any number of bands. The input
89
- * is expanded by copying edge pixels before performing the operation so that
90
- * the output image has the same size as *self*. Edge pixels in the output
91
- * image are therefore only approximate.
92
- */
93
-
94
- VALUE
95
- img_rank(VALUE obj, VALUE xsize, VALUE ysize, VALUE order)
96
- {
97
- GetImg(obj, data, im);
98
- OutImg(obj, new, data_new, im_new);
99
-
100
- if (im_rank(im, im_new, NUM2INT(xsize), NUM2INT(ysize), NUM2INT(order)))
101
- vips_lib_error();
102
-
103
- return new;
104
- }
105
-
106
- VALUE
107
- img_rank_image_internal(int argc, VALUE *argv, VALUE obj, int index)
108
- {
109
- vipsImg *im_t;
110
- IMAGE **ins;
111
- int i;
112
- GetImg(obj, data, im);
113
- OutImg(obj, new, data_new, im_new);
114
-
115
- ins = IM_ARRAY(im_new, argc + 1, IMAGE*);
116
- ins[0] = im;
117
-
118
- for (i = 0; i < argc; i++) {
119
- img_add_dep(data_new, argv[i]);
120
- Data_Get_Struct(argv[i], vipsImg, im_t);
121
- ins[i + 1] = im_t->in;
122
- }
123
-
124
- if (im_rank_image(ins, im_new, argc + 1, index))
125
- vips_lib_error();
126
-
127
- return new;
128
- }
129
-
130
- /*
131
- * call-seq:
132
- * im.rank_image(index, other_image, ...)
133
- *
134
- * Sorts the input images pixel-wise, then outputs an image in which each pixel
135
- * is selected from the sorted list by <i>index</i> parameter. For example, if
136
- * <i>index</i> is zero, then each output pixel will be the minimum of all the
137
- * corresponding input pixels.
138
- *
139
- * It works for any uncoded, non-complex image type. All input images must
140
- * match in size, format, and number of bands.
141
- */
142
-
143
- VALUE
144
- img_rank_image(int argc, VALUE *argv, VALUE obj)
145
- {
146
- VALUE index, *images;
147
- if (argc < 2)
148
- rb_raise(rb_eArgError, "Need an index and at least one image");
149
-
150
- index = argv[0];
151
- images = RARRAY_PTR(rb_ary_new4(argc - 1, argv + 1));
152
-
153
- return img_rank_image_internal(argc - 1, images, obj, NUM2INT(index));
154
- }
155
-
156
- /*
157
- * call-seq:
158
- * im.maxvalue(other_image, ...) -> image
159
- *
160
- * Sorts the input images pixel-wise, then outputs an image in which each pixel
161
- * is the maximum from the input pixels.
162
- *
163
- * It works for any uncoded, non-complex image type. All input images must
164
- * match in size, format, and number of bands.
165
- */
166
-
167
- VALUE
168
- img_maxvalue(int argc, VALUE *argv, VALUE obj)
169
- {
170
- return img_rank_image_internal(argc, argv, obj, argc - 1);
171
- }
172
-
173
- static VALUE
174
- img_cntlines(VALUE obj, int flag) {
175
- double nolines;
176
- GetImg(obj, data, im);
177
-
178
- if (im_cntlines(im, &nolines, flag))
179
- vips_lib_error();
180
-
181
- return DBL2NUM(nolines);
182
- }
183
-
184
- /*
185
- * call-seq:
186
- * im.cntlines_h -> number
187
- *
188
- * Calculates the number of transitions between black and white for the
189
- * horizontal direction of an image. black is < 128, and white is >= 128.
190
- *
191
- * Returns the mean of the result. Input should be binary one channel.
192
- */
193
-
194
- VALUE
195
- img_cntlines_h(VALUE obj) {
196
- return img_cntlines(obj, 0);
197
- }
198
-
199
- /*
200
- * call-seq:
201
- * im.cntlines_v -> number
202
- *
203
- * Calculates the number of transitions between black and white for the
204
- * vertical direction of an image. black is < 128, and white is >= 128.
205
- *
206
- * Returns the mean of the result. Input should be binary one channel.
207
- */
208
-
209
- VALUE
210
- img_cntlines_v(VALUE obj) {
211
- return img_cntlines(obj, 1);
212
- }
213
-
214
- static VALUE
215
- img_zerox(VALUE obj, int flag)
216
- {
217
- GetImg(obj, data, im);
218
- OutImg(obj, new, data_new, im_new);
219
-
220
- if (im_zerox(im, im_new, flag))
221
- vips_lib_error();
222
-
223
- return new;
224
- }
225
-
226
- /*
227
- * call-seq:
228
- * im.zerox_pos -> image
229
- *
230
- * Detects the +ve edges of zero crossings of *self*. Works on integer images.
231
- * The output image is byte with zero crossing set to 255 and all other values
232
- * set to zero.
233
- */
234
-
235
- VALUE
236
- img_zerox_pos(VALUE obj)
237
- {
238
- return img_zerox(obj, 1);
239
- }
240
-
241
- /*
242
- * call-seq:
243
- * im.zerox_neg -> image
244
- *
245
- * Detects the -ve edges of zero crossings of *self*. Works on integer images.
246
- * The output image is byte with zero crossing set to 255 and all other values
247
- * set to zero.
248
- */
249
-
250
- VALUE
251
- img_zerox_neg(VALUE obj)
252
- {
253
- return img_zerox(obj, -1);
254
- }
255
-
256
- static VALUE
257
- img_profile(VALUE obj, int dir)
258
- {
259
- GetImg(obj, data, im);
260
- OutImg(obj, new, data_new, im_new);
261
-
262
- if (im_profile(im, im_new, dir))
263
- vips_lib_error();
264
-
265
- return new;
266
- }
267
-
268
- /*
269
- * call-seq:
270
- * im.profile_h -> image
271
- *
272
- * For each horizontal line, find the position of the first non-zero pixel from
273
- * the left. Output is USHORT with width = 1 and height = input height.
274
- */
275
-
276
- VALUE
277
- img_profile_h(VALUE obj)
278
- {
279
- return img_profile(obj, 1);
280
- }
281
-
282
- /*
283
- * call-seq:
284
- * im.profile_v -> image
285
- *
286
- * For each vertical line, find the position of the first non-zero pixel from
287
- * the top. Output is USHORT with width = input width and height = 1.
288
- */
289
-
290
- VALUE
291
- img_profile_v(VALUE obj)
292
- {
293
- return img_profile(obj, 0);
294
- }
295
-
296
- /*
297
- * call-seq:
298
- * im.label_regions -> image, segments
299
- *
300
- * *self* is repeatedly scanned and regions of 4-connected pixels with the same
301
- * pixel value found. Every time a region is discovered, those pixels are
302
- * marked in the output image with a unique serial number. Once all pixels have
303
- * been labelled, the operation returns, returning an an image and
304
- * <i>segments</i>, the number of discrete regions which were detected.
305
- *
306
- * The output image is always a 1-band image with band format :UINT, and of the
307
- * same dimensions as *self*.
308
- *
309
- * This operation is useful for, for example, blob counting. You can use the
310
- * morphological operators to detect and isolate a series of objects, then use
311
- * this method to number them all.
312
- *
313
- * Use Image#histindexed to (for example) find blob coordinates.
314
- */
315
-
316
- VALUE
317
- img_label_regions(VALUE obj)
318
- {
319
- int segments;
320
- GetImg(obj, data, im);
321
- OutImg(obj, new, data_new, im_new);
322
-
323
- if (im_label_regions(im, im_new, &segments))
324
- vips_lib_error();
325
-
326
- return rb_ary_new3(2, new, INT2NUM(segments));
327
- }
@@ -1,13 +0,0 @@
1
- VALUE img_dilate(VALUE, VALUE);
2
- VALUE img_erode(VALUE, VALUE);
3
- VALUE img_rank(VALUE, VALUE, VALUE, VALUE);
4
- VALUE img_rank_image_internal(int, VALUE*, VALUE, int);
5
- VALUE img_rank_image(int, VALUE*, VALUE);
6
- VALUE img_maxvalue(int, VALUE*, VALUE);
7
- VALUE img_cntlines_h(VALUE);
8
- VALUE img_cntlines_v(VALUE);
9
- VALUE img_zerox_pos(VALUE);
10
- VALUE img_zerox_neg(VALUE);
11
- VALUE img_profile_h(VALUE);
12
- VALUE img_profile_v(VALUE);
13
- VALUE img_label_regions(VALUE);
@@ -1,554 +0,0 @@
1
- #include "ruby_vips.h"
2
-
3
- ID id_match_left, id_match_right, id_match_both, id_match_none;
4
-
5
- /*
6
- * call-seq:
7
- * im.lrmerge(other_image, dx, dy [,mwidth]) -> image
8
- *
9
- * Merge *self* as the reference image and <i>other_image</i> as the secondary
10
- * image according to the values <i>dx</i> and <i>dy</i>. <i>dx</i> and
11
- * <i>dy</i> give the displacement of <i>other_image</i> relative to *self*.
12
- * The result is written to the output image.
13
- *
14
- * The program carries out a smooth merge using a raised cosine function.
15
- * Works for any image type, including LABPACK.
16
- *
17
- * Pixels are treated with the value zero as "transparent", that is, zero
18
- * pixels in the overlap area do not contribute to the merge. This makes it
19
- * possible to join non-rectangular images.
20
- *
21
- * The "mwidth" parameter limits the maximum width of the blend area. If not
22
- * given, the width will be unlimited.
23
- */
24
-
25
- VALUE
26
- img_lrmerge(int argc, VALUE *argv, VALUE obj)
27
- {
28
- VALUE obj2, dx, dy, mwidth_v;
29
- int mwidth = -1;
30
-
31
- rb_scan_args(argc, argv, "31", &obj2, &dx, &dy, &mwidth_v);
32
- if (!NIL_P(mwidth_v))
33
- mwidth = NUM2INT(mwidth_v);
34
-
35
- GetImg(obj, data, im);
36
- GetImg(obj2, data2, im2);
37
- OutImg2(obj, obj2, new, data_new, im_new);
38
-
39
- if (im_lrmerge(im, im2, im_new, NUM2INT(dx), NUM2INT(dy), mwidth))
40
- vips_lib_error();
41
-
42
- return new;
43
- }
44
-
45
- /*
46
- * call-seq:
47
- * im.tbmerge(other_image, dx, dy [,mheight]) -> image
48
- *
49
- * see Image#lrmerge .
50
- */
51
-
52
- VALUE
53
- img_tbmerge(int argc, VALUE *argv, VALUE obj)
54
- {
55
- VALUE obj2, dx, dy, mwidth_v;
56
- int mwidth = -1;
57
-
58
- rb_scan_args(argc, argv, "31", &obj2, &dx, &dy, &mwidth_v);
59
- if (!NIL_P(mwidth_v))
60
- mwidth = NUM2INT(mwidth_v);
61
-
62
- GetImg(obj, data, im);
63
- GetImg(obj2, data2, im2);
64
- OutImg2(obj, obj2, new, data_new, im_new);
65
-
66
- if (im_tbmerge(im, im2, im_new, NUM2INT(dx), NUM2INT(dy), mwidth))
67
- vips_lib_error();
68
-
69
- return new;
70
- }
71
-
72
- /*
73
- * call-seq:
74
- * im.lrmerge1(other_image, xr1, yr1, xs1, ys1, xr2, yr2, xs2, ys2
75
- * [,mwidth]) -> image
76
- *
77
- * 1st order left-right merge.
78
- */
79
-
80
- VALUE
81
- img_lrmerge1(int argc, VALUE *argv, VALUE obj)
82
- {
83
- VALUE obj2, xr1, yr1, xs1, ys1, xr2, yr2, xs2, ys2, mwidth_v;
84
- int mwidth = -1;
85
-
86
- rb_scan_args(argc, argv, "91", &obj2, &xr1, &yr1, &xs1, &ys1, &xr2, &yr2,
87
- &xs2, &ys2, &mwidth_v);
88
- if (!NIL_P(mwidth_v))
89
- mwidth = NUM2INT(mwidth_v);
90
-
91
- GetImg(obj, data, im);
92
- GetImg(obj2, data2, im2);
93
- OutImg2(obj, obj2, new, data_new, im_new);
94
-
95
- if (im_lrmerge1(im, im2, im_new, NUM2INT(xr1), NUM2INT(yr1), NUM2INT(xs1),
96
- NUM2INT(ys1), NUM2INT(xr2), NUM2INT(yr2), NUM2INT(xs2), NUM2INT(ys2),
97
- mwidth))
98
- vips_lib_error();
99
-
100
- return new;
101
- }
102
-
103
- /*
104
- * call-seq:
105
- * im.tbmerge1(other_image, xr1, yr1, xs1, ys1, xr2, yr2, xs2, ys2
106
- * [,mheight]) -> image
107
- *
108
- * 1st order top-bottom merge.
109
- */
110
-
111
- VALUE
112
- img_tbmerge1(int argc, VALUE *argv, VALUE obj)
113
- {
114
- VALUE obj2, xr1, yr1, xs1, ys1, xr2, yr2, xs2, ys2, mwidth_v;
115
- int mwidth = -1;
116
-
117
- rb_scan_args(argc, argv, "91", &obj2, &xr1, &yr1, &xs1, &ys1, &xr2, &yr2,
118
- &xs2, &ys2, &mwidth_v);
119
- if (!NIL_P(mwidth_v))
120
- mwidth = NUM2INT(mwidth_v);
121
-
122
- GetImg(obj, data, im);
123
- GetImg(obj2, data2, im2);
124
- OutImg2(obj, obj2, new, data_new, im_new);
125
-
126
- if (im_tbmerge1(im, im2, im_new, NUM2INT(xr1), NUM2INT(yr1), NUM2INT(xs1),
127
- NUM2INT(ys1), NUM2INT(xr2), NUM2INT(yr2), NUM2INT(xs2), NUM2INT(ys2),
128
- mwidth))
129
- vips_lib_error();
130
-
131
- return new;
132
- }
133
-
134
- /*
135
- * call-seq:
136
- * im.lrmosaic(other_image, band, xref, yref, xsec, ysec,
137
- * halfcorrelation=5, halfarea=14 [,balancetype] [,mwidth]) -> image
138
- *
139
- * Mosaic *self* and <i>other_image</i> left-right.
140
- *
141
- * In order to carry out mosaicing, the coordinates of one tie point are
142
- * required. The tie point is expected to be in the overlapping area and has
143
- * coordinates (<i>xref</i>, <i>yref</i>) on *self*, and (<i>xsec</i>,
144
- * <i>ysec</i>) on <i>other_image</i>. The tie-point is not used as a start
145
- * point for the search, but is used to specify the overlap of the two images.
146
- *
147
- * The function splits the overlap area into three parts (top, middle and
148
- * bottom) and searches t*self* in each part for the 20 best high contrast
149
- * points. These 60 points are then searched for in <i>other_image</i>, giving
150
- * a set of 60 possible corrected vectors.
151
- *
152
- * A straight line is fitted through the 60 vectors, and points discarded which
153
- * lie a significant distance from the line. The line is then refitted to the
154
- * remaining points, and the process repeated until either all remaining points
155
- * lie on a straight line, or too many points have been discarded.
156
- *
157
- * If a good straight line fit is found, *self* and <i>other_image</i> are
158
- * joined. If no fit was found, the function fails with an error message. Note
159
- * that this function detects rotation: if the straight line found requires
160
- * <i>other_image</i> to be rotated, it also fails with an error message.
161
- *
162
- * <i>halfcorrelationsize</i> - sets the size of the fragments of *self* for
163
- * which the function searches sec. The actual window will be of size
164
- * 2 * <i>halfcorrelationsize</i> + 1. We recommend a value of 5.
165
- *
166
- * <i>halfareasize</i> - sets the size of the area of sec that is searched. The
167
- * The actual area searched will be of size 2 * <i>halfareasize</i> + 1. We
168
- * recommend a value of 14.
169
- *
170
- * <i>balancetype</i> - sets the style of the balancing the functions perform.
171
- * Balancing finds the average value of pixels in the overlap area, and scales
172
- * the left and right images so as to make the images match in average overlap.
173
- *
174
- * * :balance_none - no balancing.
175
- * * :balance_left - keep the left image unadjusted and adjust the contrast of
176
- * the right image to match the left.
177
- * * :balance_right - keep the right image unadjusted and scale the left image
178
- * to match it.
179
- * * :balance_both - adjust the contrast of both the left and right images to
180
- * bring both averages to a middle value. The middle value chosen is weighted
181
- * by the number of pixels in each image: large images will be adjusted less
182
- * than small images.
183
- *
184
- * Balancing is useful for mosaicing frames from photographic or video sources
185
- * where exact colour control is impossible and exposure varies from frame to
186
- * frame. Balancing is only allowed for uncoded uchar images.
187
- *
188
- * The <i>mwidth</i> parameter sets the maximum blend width, see Image#lrmerge.
189
- */
190
-
191
- VALUE
192
- img_lrmosaic(int argc, VALUE *argv, VALUE obj)
193
- {
194
- VALUE obj2, bandno, xref, yref, xsec, ysec, halfcorrelation_v, halfarea_v,
195
- balancetype_v, mwidth_v;
196
- ID balancetype_id;
197
- int mwidth = -1, halfcorrelation = 5, halfarea = 14, balancetype = 0;
198
-
199
- rb_scan_args(argc, argv, "64", &obj2, &bandno, &xref, &yref, &xsec, &ysec,
200
- &halfcorrelation_v, &halfarea_v, &balancetype_v, &mwidth_v);
201
-
202
- if (!NIL_P(halfcorrelation_v))
203
- halfcorrelation = NUM2INT(halfcorrelation_v);
204
-
205
- if (!NIL_P(halfarea_v))
206
- halfarea = NUM2INT(halfarea_v);
207
-
208
- if (!NIL_P(balancetype_v)) {
209
- balancetype_id = SYM2ID(balancetype_v);
210
- if (balancetype_id == id_match_none) balancetype = 0;
211
- else if (balancetype_id == id_match_left) balancetype = 1;
212
- else if (balancetype_id == id_match_right) balancetype = 2;
213
- else if (balancetype_id == id_match_both) balancetype = 3;
214
- else
215
- rb_raise(rb_eArgError, "Balance type must be nil, :match_left, :match_right, or :match_both");
216
- }
217
-
218
- if (!NIL_P(mwidth_v))
219
- mwidth = NUM2INT(mwidth_v);
220
-
221
- GetImg(obj, data, im);
222
- GetImg(obj2, data2, im2);
223
- OutImg2(obj, obj2, new, data_new, im_new);
224
-
225
- if (im_lrmosaic(im, im2, im_new, NUM2INT(bandno), NUM2INT(xref),
226
- NUM2INT(yref), NUM2INT(xsec), NUM2INT(ysec), NUM2INT(halfcorrelation),
227
- NUM2INT(halfarea), NUM2INT(balancetype), NUM2INT(mwidth)))
228
- vips_lib_error();
229
-
230
- return new;
231
- }
232
-
233
- /*
234
- * call-seq:
235
- * im.tbmosaic(other_image, band, xref, yref, xsec, ysec,
236
- * halfcorrelation=5, halfarea=14 [,balancetype] [,mheight]) -> image
237
- *
238
- * Mosaic *self* and <i>other_image</i> top-bottom.
239
- *
240
- * See Image#lrmosaic .
241
- */
242
-
243
- VALUE
244
- img_tbmosaic(int argc, VALUE *argv, VALUE obj)
245
- {
246
- VALUE obj2, bandno, xref, yref, xsec, ysec, halfcorrelation_v, halfarea_v,
247
- balancetype_v, mwidth_v;
248
- ID balancetype_id;
249
- int mwidth = -1, halfcorrelation = 5, halfarea = 14, balancetype = 0;
250
-
251
- rb_scan_args(argc, argv, "64", &obj2, &bandno, &xref, &yref, &xsec, &ysec,
252
- &halfcorrelation_v, &halfarea_v, &balancetype_v, &mwidth_v);
253
-
254
- if (!NIL_P(halfcorrelation_v))
255
- halfcorrelation = NUM2INT(halfcorrelation_v);
256
-
257
- if (!NIL_P(halfarea_v))
258
- halfarea = NUM2INT(halfarea_v);
259
-
260
- if (!NIL_P(balancetype_v)) {
261
- balancetype_id = SYM2ID(balancetype_v);
262
-
263
- if (balancetype_id == id_match_left) balancetype = 1;
264
- else if (balancetype_id == id_match_right) balancetype = 2;
265
- else if (balancetype_id == id_match_both) balancetype = 3;
266
- else
267
- rb_raise(rb_eArgError, "Balance type must be nil, :match_left, :match_right, or :match_both");
268
- }
269
-
270
- if (!NIL_P(mwidth_v))
271
- mwidth = NUM2INT(mwidth_v);
272
-
273
- GetImg(obj, data, im);
274
- GetImg(obj2, data2, im2);
275
- OutImg2(obj, obj2, new, data_new, im_new);
276
-
277
- if (im_tbmosaic(im, im2, im_new, NUM2INT(bandno), NUM2INT(xref),
278
- NUM2INT(yref), NUM2INT(xsec), NUM2INT(ysec), halfcorrelation, halfarea,
279
- balancetype, mwidth))
280
- vips_lib_error();
281
-
282
- return new;
283
- }
284
-
285
- /*
286
- * call-seq:
287
- * im.lrmosaic1(other_image, band, xr1, yr1, xs1, ys1, xr2, yr2, xs2, ys2,
288
- * halfcorrelation=5, halfarea=14 [,balancetype] [,mwidth]) -> image
289
- *
290
- * 1st order left-right mosaic.
291
- */
292
-
293
- VALUE
294
- img_lrmosaic1(int argc, VALUE *argv, VALUE obj)
295
- {
296
- VALUE obj2, bandno, xr1, yr1, xs1, ys1, xr2, yr2, xs2, ys2,
297
- halfcorrelation_v, halfarea_v, balancetype_v, mwidth_v;
298
- ID balancetype_id;
299
- int mwidth = -1, halfcorrelation = 5, halfarea = 14, balancetype = 0;
300
-
301
- rb_scan_args(argc, argv, "95", &obj2, &bandno, &xr1, &yr1, &xs1, &ys1, &xr2,
302
- &yr2, &xs2, &ys2, &halfcorrelation_v, &halfarea_v, &balancetype_v,
303
- &mwidth_v);
304
-
305
- if (argc < 10)
306
- rb_raise(rb_eArgError, "Need at least 10 arguments.");
307
-
308
- if (!NIL_P(halfcorrelation_v))
309
- halfcorrelation = NUM2INT(halfcorrelation_v);
310
-
311
- if (!NIL_P(halfarea_v))
312
- halfarea = NUM2INT(halfarea_v);
313
-
314
- if (!NIL_P(balancetype_v)) {
315
- balancetype_id = SYM2ID(balancetype_v);
316
-
317
- if (balancetype_id == id_match_left) balancetype = 1;
318
- else if (balancetype_id == id_match_right) balancetype = 2;
319
- else if (balancetype_id == id_match_both) balancetype = 3;
320
- else
321
- rb_raise(rb_eArgError, "Balance type must be nil, :match_left, :match_right, or :match_both");
322
- }
323
-
324
- if (!NIL_P(mwidth_v))
325
- mwidth = NUM2INT(mwidth_v);
326
-
327
- GetImg(obj, data, im);
328
- GetImg(obj2, data2, im2);
329
- OutImg2(obj, obj2, new, data_new, im_new);
330
-
331
- if (im_lrmosaic1(im, im2, im_new, NUM2INT(bandno), NUM2INT(xr1),
332
- NUM2INT(yr1), NUM2INT(xs1), NUM2INT(ys1), NUM2INT(xr2), NUM2INT(yr2),
333
- NUM2INT(xs2), NUM2INT(ys2), halfcorrelation, halfarea, balancetype,
334
- mwidth))
335
- vips_lib_error();
336
-
337
- return new;
338
- }
339
-
340
- /*
341
- * call-seq:
342
- * im.tbmosaic1(other_image, band, xr1, yr1, xs1, ys1, xr2, yr2, xs2, ys2,
343
- * halfcorrelation=5, halfarea=14 [,balancetype] [,mheight]) -> image
344
- *
345
- * 1st order top-bottom mosaic.
346
- */
347
-
348
- VALUE
349
- img_tbmosaic1(int argc, VALUE *argv, VALUE obj)
350
- {
351
- VALUE obj2, bandno, xr1, yr1, xs1, ys1, xr2, yr2, xs2, ys2,
352
- halfcorrelation_v, halfarea_v, balancetype_v, mwidth_v;
353
- ID balancetype_id;
354
- int mwidth = -1, halfcorrelation = 5, halfarea = 14, balancetype = 0;
355
-
356
- rb_scan_args(argc, argv, "95", &obj2, &bandno, &xr1, &yr1, &xs1, &ys1, &xr2,
357
- &yr2, &xs2, &ys2, &halfcorrelation_v, &halfarea_v, &balancetype_v,
358
- &mwidth_v);
359
-
360
- if (argc < 10)
361
- rb_raise(rb_eArgError, "Need at least 10 arguments.");
362
-
363
- if (!NIL_P(halfcorrelation_v))
364
- halfcorrelation = NUM2INT(halfcorrelation_v);
365
-
366
- if (!NIL_P(halfarea_v))
367
- halfarea = NUM2INT(halfarea_v);
368
-
369
- if (!NIL_P(balancetype_v)) {
370
- balancetype_id = SYM2ID(balancetype_v);
371
-
372
- if (balancetype_id == id_match_left) balancetype = 1;
373
- else if (balancetype_id == id_match_right) balancetype = 2;
374
- else if (balancetype_id == id_match_both) balancetype = 3;
375
- else
376
- rb_raise(rb_eArgError, "Balance type must be nil, :match_left, :match_right, or :match_both");
377
- }
378
-
379
- if (!NIL_P(mwidth_v))
380
- mwidth = NUM2INT(mwidth_v);
381
-
382
- GetImg(obj, data, im);
383
- GetImg(obj2, data2, im2);
384
- OutImg2(obj, obj2, new, data_new, im_new);
385
-
386
- if (im_tbmosaic1(im, im2, im_new, NUM2INT(bandno), NUM2INT(xr1),
387
- NUM2INT(yr1), NUM2INT(xs1), NUM2INT(ys1), NUM2INT(xr2), NUM2INT(yr2),
388
- NUM2INT(xs2), NUM2INT(ys2), halfcorrelation, halfarea, balancetype,
389
- mwidth))
390
- vips_lib_error();
391
-
392
- return new;
393
- }
394
-
395
- /*
396
- * call-seq:
397
- * im.global_balance(gamma) -> image
398
- *
399
- * Takes an image assembled with the mosaicing functions, take it apart, and
400
- * reassemble it, globally optimising the image balance. This is useful for
401
- * assembling image mosaics from sources where the exposure is uncontrolled and
402
- * may vary from tile to tile --- such as video, or photographic sources.
403
- *
404
- * The function finds a set of factors, one for each of the input images, and
405
- * scales each image by its factor before reassembling. The factors are chosen
406
- * so as to minimise the average grey-level difference between neighboring
407
- * images at their overlaps. Trivial overlaps (where the width and height of
408
- * the overlap are both less than 20 pixels) are ignored.
409
- *
410
- * The <i>gamma</i> parameter is the gamma of the image input system. It is
411
- * used during brightness adjustment. Set to 1.0 to disable gamma, to 1.6 for a
412
- * typical IR vidicon camera, or 2.3 for a typical video camera.
413
- *
414
- * It relies on information left by the mosaicing functions in ".desc" files.
415
- * If the ".desc" file of the input image has been corrupted, or is strangely
416
- * complicated, or if any of the original input images have been moved or
417
- * deleted, the function can fail.
418
- *
419
- * The function will fail for mosaics larger than about 7 by 7 frames, since it
420
- * will run out of file descriptors (UNIX sets a limit of 256 per process). To
421
- * balance larger mosaics, just assemble them in 7x7 sections, balancing and
422
- * saving each part in turn, before loading, assembling and balancing the final
423
- * image. The function can also fail if there are significant mosaicing errors.
424
- */
425
-
426
- VALUE
427
- img_global_balance(VALUE obj, VALUE gamma)
428
- {
429
- GetImg(obj, data, im);
430
- OutImg(obj, new, data_new, im_new);
431
-
432
- if (im_global_balance(im, im_new, NUM2DBL(gamma)))
433
- vips_lib_error();
434
-
435
- return new;
436
- }
437
-
438
- /*
439
- * call-seq:
440
- * im.global_balancef(gamma) -> image
441
- *
442
- * Works as Image#global_balance, but outputs a float rather than a uchar
443
- * image. This lets you adjust the range of the image manually, if the
444
- * automatically-found scales are causing burn-out.
445
- */
446
-
447
- VALUE
448
- img_global_balancef(VALUE obj, VALUE gamma)
449
- {
450
- GetImg(obj, data, im);
451
- OutImg(obj, new, data_new, im_new);
452
-
453
- if (im_global_balancef(im, im_new, NUM2DBL(gamma)))
454
- vips_lib_error();
455
-
456
- return new;
457
- }
458
-
459
- /*
460
- * call-seq:
461
- * im.correl(other_image, xref, yref, xsec, ysec, hwindowsize,
462
- * hsearchsize) -> correlation, x, y
463
- *
464
- * Find position of <i>other_image</i> within *self*. Search around point
465
- * <i>xsec</i>, <i>ysec</i> for the best match for the area around <i>xref</i>,
466
- * <i>yref</i>. Search an area of size <i>hsearchsize</i> for an of size
467
- * <i>hwindowsize</i>.
468
- *
469
- * Return a new value for xsec, ysec and the correlation at that point.
470
- */
471
-
472
- VALUE
473
- img_correl(VALUE obj, VALUE obj2, VALUE xref, VALUE yref, VALUE xsec,
474
- VALUE ysec, VALUE hwindowsize, VALUE hsearchsize)
475
- {
476
- int x, y;
477
- double correlation;
478
- GetImg(obj, data, im);
479
- GetImg(obj2, data2, im2);
480
-
481
- if (im_correl(im, im2, NUM2INT(xref), NUM2INT(yref), NUM2INT(xsec),
482
- NUM2INT(ysec), NUM2INT(hwindowsize), NUM2INT(hsearchsize), &correlation,
483
- &x, &y))
484
- vips_lib_error();
485
-
486
- return rb_ary_new3(3, DBL2NUM(correlation), INT2NUM(x), INT2NUM(y));
487
- }
488
-
489
- /*
490
- * call-seq:
491
- * im.align_bands -> image
492
- *
493
- * Brute force align the bands of an image.
494
- */
495
-
496
- VALUE
497
- img_align_bands(VALUE obj)
498
- {
499
- RUBY_VIPS_UNARY(im_align_bands);
500
- }
501
-
502
- /*
503
- * call-seq:
504
- * im.maxpos_subpel -> x, y
505
- *
506
- * This function implements "Extension of Phase Correlation to Subpixel
507
- * Registration" by H. Foroosh, from IEEE trans. Im. Proc. 11(3), 2002.
508
- *
509
- * If the best three matches in the correlation are aranged:
510
- *
511
- * 02 or 01
512
- * 1 2
513
- *
514
- * then we return a subpixel match using the ratio of correlations in the
515
- * vertical and horizontal dimension.
516
- *
517
- * ( xs[0], ys[0] ) is the best integer alignment
518
- * ( xs[ use_x ], ys[ use_x ] ) is equal in y and (+/-)1 off in x
519
- * ( xs[ use_y ], ys[ use_y ] ) is equal in x and (+/-)1 off in y
520
- *
521
- * Alternatively if the best four matches in the correlation are aranged in
522
- * a square:
523
- *
524
- * 01 or 03 or 02 or 03
525
- * 32 12 31 21
526
- *
527
- * then we return a subpixel match weighting with the sum the two on each
528
- * side over the sum of all four, but only if all four of them are very
529
- * close to the best, and the fifth is nowhere near.
530
- *
531
- * This alternative method is not described by Foroosh, but is often the
532
- * case where the match is close to n-and-a-half pixels in both dimensions.
533
- */
534
-
535
- VALUE
536
- img_maxpos_subpel(VALUE obj)
537
- {
538
- double x, y;
539
- GetImg(obj, data, im);
540
-
541
- if (im_maxpos_subpel(im, &x, &y))
542
- vips_lib_error();
543
-
544
- return rb_ary_new3(2, DBL2NUM(x), INT2NUM(y));
545
- }
546
-
547
- void
548
- init_Image_mosaicing(void)
549
- {
550
- id_match_none = rb_intern("match_none");
551
- id_match_left = rb_intern("match_left");
552
- id_match_right = rb_intern("match_right");
553
- id_match_both = rb_intern("match_both");
554
- }