ruby-vips 0.3.14 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
- }