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_colour.h
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
VALUE img_lab_to_lch(VALUE);
|
2
|
+
VALUE img_lch_to_lab(VALUE);
|
3
|
+
VALUE img_labq_to_xyz(VALUE);
|
4
|
+
VALUE img_rad_to_float(VALUE);
|
5
|
+
VALUE img_float_to_rad(VALUE);
|
6
|
+
VALUE img_lch_to_ucs(VALUE);
|
7
|
+
VALUE img_lab_to_labq(VALUE);
|
8
|
+
VALUE img_lab_to_labs(VALUE);
|
9
|
+
VALUE img_lab_to_xyz(VALUE);
|
10
|
+
VALUE img_lab_to_xyz_temp(VALUE, VALUE, VALUE, VALUE);
|
11
|
+
VALUE img_lab_to_ucs(VALUE);
|
12
|
+
VALUE img_labq_to_lab(VALUE);
|
13
|
+
VALUE img_labq_to_labs(VALUE);
|
14
|
+
VALUE img_labs_to_labq(VALUE);
|
15
|
+
VALUE img_labs_to_lab(VALUE);
|
16
|
+
VALUE img_ucs_to_xyz(VALUE);
|
17
|
+
VALUE img_ucs_to_lch(VALUE);
|
18
|
+
VALUE img_ucs_to_lab(VALUE);
|
19
|
+
VALUE img_xyz_to_lab(VALUE);
|
20
|
+
VALUE img_xyz_to_lab_temp(VALUE, VALUE, VALUE, VALUE);
|
21
|
+
VALUE img_xyz_to_ucs(VALUE);
|
22
|
+
VALUE img_srgb_to_xyz(VALUE);
|
23
|
+
VALUE img_xyz_to_srgb(VALUE);
|
24
|
+
VALUE img_yxy_to_xyz(VALUE);
|
25
|
+
VALUE img_xyz_to_yxy(VALUE);
|
26
|
+
VALUE img_decmc_from_lab(VALUE, VALUE);
|
27
|
+
VALUE img_de00_from_lab(VALUE, VALUE);
|
28
|
+
VALUE img_de_from_xyz(VALUE, VALUE);
|
29
|
+
VALUE img_de_from_lab(VALUE, VALUE);
|
30
|
+
VALUE img_lab_morph(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE);
|
31
|
+
VALUE img_icc_transform(VALUE, VALUE, VALUE, VALUE);
|
32
|
+
VALUE img_icc_import(VALUE, VALUE, VALUE);
|
33
|
+
VALUE img_icc_import_embedded(VALUE, VALUE);
|
34
|
+
VALUE img_icc_export_depth(VALUE, VALUE, VALUE, VALUE);
|
35
|
+
VALUE img_icc_ac2rc(VALUE, VALUE, VALUE);
|
36
|
+
void init_Image_colour();
|
@@ -0,0 +1,863 @@
|
|
1
|
+
#include "ruby_vips.h"
|
2
|
+
#include "image.h"
|
3
|
+
#include "mask.h"
|
4
|
+
#include "header.h"
|
5
|
+
|
6
|
+
static ID id_black, id_extend, id_repeat, id_mirror, id_white;
|
7
|
+
|
8
|
+
/*
|
9
|
+
* call-seq:
|
10
|
+
* im.to_mask -> mask
|
11
|
+
*
|
12
|
+
* Make a mask from an image. All images are cast to band format :DOUBLE
|
13
|
+
* before processing. There are two cases for handling bands:
|
14
|
+
*
|
15
|
+
* If the image has a single band, Image#to_mask will write a mask the same
|
16
|
+
* size as the image.
|
17
|
+
*
|
18
|
+
* If the image has more than one band, it must be one pixel high or wide. In
|
19
|
+
* this case the output mask uses that axis to represent band values.
|
20
|
+
*/
|
21
|
+
|
22
|
+
VALUE
|
23
|
+
img_to_mask(VALUE obj)
|
24
|
+
{
|
25
|
+
vipsMask *msk;
|
26
|
+
VALUE mask = mask_alloc(cVIPSMask);
|
27
|
+
GetImg(obj, data, im);
|
28
|
+
|
29
|
+
Data_Get_Struct(mask, vipsMask, msk);
|
30
|
+
|
31
|
+
if (!(msk->dmask = im_vips2mask(im, "img_vips2mask")))
|
32
|
+
vips_lib_error();
|
33
|
+
|
34
|
+
return mask;
|
35
|
+
}
|
36
|
+
|
37
|
+
/*
|
38
|
+
* call-seq:
|
39
|
+
* im.dup -> image
|
40
|
+
*
|
41
|
+
* Create a copy of an image.
|
42
|
+
*/
|
43
|
+
|
44
|
+
VALUE
|
45
|
+
img_dup(VALUE obj)
|
46
|
+
{
|
47
|
+
RUBY_VIPS_UNARY(im_copy);
|
48
|
+
}
|
49
|
+
|
50
|
+
/*
|
51
|
+
* call-seq:
|
52
|
+
* im.copy_swap -> image
|
53
|
+
*
|
54
|
+
* Copy an image, swapping byte order between little and big endian. This
|
55
|
+
* really does change image pixels and does not just alter the header.
|
56
|
+
*/
|
57
|
+
|
58
|
+
VALUE
|
59
|
+
img_copy_swap(VALUE obj)
|
60
|
+
{
|
61
|
+
RUBY_VIPS_UNARY(im_copy_swap);
|
62
|
+
}
|
63
|
+
|
64
|
+
/*
|
65
|
+
* call-seq:
|
66
|
+
* im.copy_native -> image
|
67
|
+
*
|
68
|
+
* Copy an image to native order, that is, the order for the executing program.
|
69
|
+
*/
|
70
|
+
|
71
|
+
VALUE
|
72
|
+
img_copy_native(VALUE obj, VALUE input_msb_first)
|
73
|
+
{
|
74
|
+
#if IM_MAJOR_VERSION > 7 || IM_MINOR_VERSION >= 22
|
75
|
+
vipsImg *in, *out;
|
76
|
+
int msb_first;
|
77
|
+
|
78
|
+
VALUE new = img_spawn(obj);
|
79
|
+
|
80
|
+
Data_Get_Struct(obj, vipsImg, in);
|
81
|
+
Data_Get_Struct(new, vipsImg, out);
|
82
|
+
|
83
|
+
msb_first = input_msb_first == Qtrue ? TRUE : FALSE;
|
84
|
+
if( im_copy_native(in->in, out->in, msb_first) )
|
85
|
+
vips_lib_error();
|
86
|
+
|
87
|
+
return new;
|
88
|
+
#else
|
89
|
+
rb_raise(eVIPSError, "Your version of vips doesn't support this operation");
|
90
|
+
#endif
|
91
|
+
}
|
92
|
+
|
93
|
+
/*
|
94
|
+
* call-seq:
|
95
|
+
* im.copy_file -> image
|
96
|
+
*
|
97
|
+
* Copy an image to a disc file, then copy again to output. If the image is
|
98
|
+
* already a disc file, just copy straight through.
|
99
|
+
*
|
100
|
+
* The file is automatically deleted when <i>image</i> is closed.
|
101
|
+
*/
|
102
|
+
|
103
|
+
VALUE
|
104
|
+
img_copy_file(VALUE obj)
|
105
|
+
{
|
106
|
+
vipsImg *in, *out;
|
107
|
+
|
108
|
+
VALUE new = img_spawn(obj);
|
109
|
+
|
110
|
+
Data_Get_Struct(obj, vipsImg, in);
|
111
|
+
Data_Get_Struct(new, vipsImg, out);
|
112
|
+
|
113
|
+
if( im_copy_file(in->in, out->in) )
|
114
|
+
vips_lib_error();
|
115
|
+
|
116
|
+
return new;
|
117
|
+
}
|
118
|
+
|
119
|
+
/*
|
120
|
+
* call-seq:
|
121
|
+
* im.clip2fmt(fmt_symbol) -> image
|
122
|
+
*
|
123
|
+
* Convert the image to <i>fmt_symbol</i> format. You can convert between any
|
124
|
+
* pair of formats. Floats are truncated (not rounded). Out of range values are
|
125
|
+
* clipped.
|
126
|
+
*
|
127
|
+
* <i>fmt_symbol</i> can be any of: :NOTSET, :UCHAR, :CHAR, :USHORT, :SHORT,
|
128
|
+
* :UINT, :INT, :FLOAT, :COMPLEX, :DOUBLE, :DPCOMPLEX.
|
129
|
+
*/
|
130
|
+
|
131
|
+
VALUE
|
132
|
+
img_clip2fmt(VALUE obj, VALUE fmt)
|
133
|
+
{
|
134
|
+
GetImg(obj, data, im);
|
135
|
+
OutImg(obj, new, data_new, im_new);
|
136
|
+
|
137
|
+
if (im_clip2fmt(im, im_new, header_id_to_band_fmt(SYM2ID(fmt))))
|
138
|
+
vips_lib_error();
|
139
|
+
|
140
|
+
return new;
|
141
|
+
}
|
142
|
+
|
143
|
+
/*
|
144
|
+
* call-seq:
|
145
|
+
* im.scale -> image
|
146
|
+
*
|
147
|
+
* Search the image for the maximum and minimum value, then return the image
|
148
|
+
* as unsigned 8-bit, scaled so that the maximum value is 255 and the
|
149
|
+
* minimum is zero.
|
150
|
+
*/
|
151
|
+
|
152
|
+
VALUE
|
153
|
+
img_scale(VALUE obj)
|
154
|
+
{
|
155
|
+
RUBY_VIPS_UNARY(im_scale);
|
156
|
+
}
|
157
|
+
|
158
|
+
/*
|
159
|
+
* call-seq:
|
160
|
+
* im.msb([band]) -> image
|
161
|
+
*
|
162
|
+
* Turn any integer image to 8-bit unsigned char by discarding all but the most
|
163
|
+
* significant byte. Signed values are converted to unsigned by adding 128.
|
164
|
+
*
|
165
|
+
* This operator also works for LABQ coding.
|
166
|
+
*
|
167
|
+
* If <i>band</i> is given, this will turn any integer image to a single-band'
|
168
|
+
* 8-bit unsigned char by discarding all but the most significant byte from the
|
169
|
+
* selected band.
|
170
|
+
*/
|
171
|
+
|
172
|
+
VALUE
|
173
|
+
img_msb(int argc, VALUE *argv, VALUE obj)
|
174
|
+
{
|
175
|
+
VALUE v_num;
|
176
|
+
GetImg(obj, data, im);
|
177
|
+
OutImg(obj, new, data_new, im_new);
|
178
|
+
|
179
|
+
rb_scan_args(argc, argv, "01", &v_num);
|
180
|
+
|
181
|
+
if (NIL_P(v_num)) {
|
182
|
+
if (im_msb(im, im_new))
|
183
|
+
vips_lib_error();
|
184
|
+
} else if (im_msb_band(im, im_new, NUM2INT(v_num)))
|
185
|
+
vips_lib_error();
|
186
|
+
|
187
|
+
return new;
|
188
|
+
}
|
189
|
+
|
190
|
+
/*
|
191
|
+
* call-seq:
|
192
|
+
* im.c2amph -> image
|
193
|
+
*
|
194
|
+
* Convert a complex image from rectangular to polar coordinates. Angles are
|
195
|
+
* expressed in degrees.
|
196
|
+
*/
|
197
|
+
|
198
|
+
VALUE
|
199
|
+
img_c2amph(VALUE obj)
|
200
|
+
{
|
201
|
+
RUBY_VIPS_UNARY(im_c2amph);
|
202
|
+
}
|
203
|
+
|
204
|
+
/*
|
205
|
+
* call-seq:
|
206
|
+
* im.c2rect -> image
|
207
|
+
*
|
208
|
+
* Convert a complex image from polar to rectangular coordinates. Angles are
|
209
|
+
* expressed in degrees.
|
210
|
+
*/
|
211
|
+
|
212
|
+
VALUE
|
213
|
+
img_c2rect(VALUE obj)
|
214
|
+
{
|
215
|
+
RUBY_VIPS_UNARY(im_c2rect);
|
216
|
+
}
|
217
|
+
|
218
|
+
/*
|
219
|
+
* call-seq:
|
220
|
+
* im.ri2c(other_image) -> image
|
221
|
+
*
|
222
|
+
* Compose two real images to make a complex image. If either image has band
|
223
|
+
* format :DOUBLE, the output image is band format :DPCOMPLEX. Otherwise the
|
224
|
+
* output image is :COMPLEX.
|
225
|
+
*
|
226
|
+
* If the number of bands differs, one of the images must have one band. In
|
227
|
+
* this case, an n-band image is formed from the one-band image by joining n
|
228
|
+
* copies of the one-band image together, and then the two n-band images are
|
229
|
+
* operated upon.
|
230
|
+
*
|
231
|
+
* The two input images are cast up to the smallest common type.
|
232
|
+
*/
|
233
|
+
|
234
|
+
VALUE
|
235
|
+
img_ri2c(VALUE obj, VALUE obj2)
|
236
|
+
{
|
237
|
+
RUBY_VIPS_BINARY(im_ri2c);
|
238
|
+
}
|
239
|
+
|
240
|
+
/*
|
241
|
+
* call-seq:
|
242
|
+
* im.c2imag -> image
|
243
|
+
*
|
244
|
+
* Extract the imaginary part of a complex image.
|
245
|
+
*/
|
246
|
+
|
247
|
+
VALUE
|
248
|
+
img_c2imag(VALUE obj)
|
249
|
+
{
|
250
|
+
RUBY_VIPS_UNARY(im_c2imag);
|
251
|
+
}
|
252
|
+
|
253
|
+
/*
|
254
|
+
* call-seq:
|
255
|
+
* im.c2real -> image
|
256
|
+
*
|
257
|
+
* Extract the real part of a complex image.
|
258
|
+
*/
|
259
|
+
|
260
|
+
VALUE
|
261
|
+
img_c2real(VALUE obj)
|
262
|
+
{
|
263
|
+
RUBY_VIPS_UNARY(im_c2real);
|
264
|
+
}
|
265
|
+
|
266
|
+
/*
|
267
|
+
* call-seq:
|
268
|
+
* im.scaleps -> image
|
269
|
+
*
|
270
|
+
* Scale a power spectrum. Transform with log10(1.0 + x ** 0.25)) + 0.5,
|
271
|
+
* then scale so max == 255.
|
272
|
+
*/
|
273
|
+
|
274
|
+
VALUE
|
275
|
+
img_scaleps(VALUE obj)
|
276
|
+
{
|
277
|
+
RUBY_VIPS_UNARY(im_scaleps);
|
278
|
+
}
|
279
|
+
|
280
|
+
/*
|
281
|
+
* call-seq:
|
282
|
+
* im.falsecolour -> image
|
283
|
+
*
|
284
|
+
* Turn a 1-band 8-bit image into a 3-band 8-bit image with a false colour
|
285
|
+
* map. The map is supposed to make small differences in brightness more
|
286
|
+
* obvious.
|
287
|
+
*/
|
288
|
+
|
289
|
+
VALUE
|
290
|
+
img_falsecolour(VALUE obj)
|
291
|
+
{
|
292
|
+
RUBY_VIPS_UNARY(im_falsecolour);
|
293
|
+
}
|
294
|
+
|
295
|
+
/*
|
296
|
+
* call-seq:
|
297
|
+
* Image.gaussnoise(width, height, mean, sigma) -> image
|
298
|
+
*
|
299
|
+
* Make a one band float image of gaussian noise with the specified
|
300
|
+
* distribution. The noise distribution is created by averaging 12 random
|
301
|
+
* numbers with the appropriate weights.
|
302
|
+
*/
|
303
|
+
|
304
|
+
VALUE
|
305
|
+
img_s_gaussnoise(VALUE obj, VALUE x, VALUE y, VALUE mean, VALUE sigma)
|
306
|
+
{
|
307
|
+
OutPartial(new, data, im_new);
|
308
|
+
|
309
|
+
if (im_gaussnoise(im_new, NUM2INT(x), NUM2INT(y), NUM2DBL(mean),
|
310
|
+
NUM2DBL(sigma)))
|
311
|
+
vips_lib_error();
|
312
|
+
|
313
|
+
return new;
|
314
|
+
}
|
315
|
+
|
316
|
+
/*
|
317
|
+
* call-seq:
|
318
|
+
* Image.black(width, height, bands) -> image
|
319
|
+
*
|
320
|
+
* Make a black unsigned char image of a specified size.
|
321
|
+
*/
|
322
|
+
|
323
|
+
VALUE
|
324
|
+
img_s_black(VALUE obj, VALUE width, VALUE height, VALUE bands)
|
325
|
+
{
|
326
|
+
OutPartial(new, data, im_new);
|
327
|
+
|
328
|
+
if (im_black(im_new, NUM2INT(width), NUM2INT(height), NUM2DBL(bands)))
|
329
|
+
vips_lib_error();
|
330
|
+
|
331
|
+
return new;
|
332
|
+
}
|
333
|
+
|
334
|
+
/*
|
335
|
+
* call-seq:
|
336
|
+
* Image.text(text, font, width, alignment, dpi) -> image
|
337
|
+
*
|
338
|
+
* Draw the string <i>text</i> to an image. @out is a one-band 8-bit
|
339
|
+
* unsigned char image, with 0 for no text and 255 for text. Values inbetween
|
340
|
+
* are used for anti-aliasing.
|
341
|
+
*
|
342
|
+
* <i>text</i> is the text to render as a UTF-8 string. It can contain Pango
|
343
|
+
* markup, for example "<i>The</i>Guardian".
|
344
|
+
*
|
345
|
+
* <i>font</i> is the font to render with, selected by fontconfig. Examples
|
346
|
+
* might be "sans 12" or perhaps "bitstream charter bold 10".
|
347
|
+
*
|
348
|
+
* <i>width</i> is the maximum number of pixels across to draw within. If the
|
349
|
+
* generated text is wider than this, it will wrap to a new line. In this
|
350
|
+
* case, <i>alignment</i> can be used to set the alignment style for multi-line
|
351
|
+
* text. 0 means left-align, 1 centre, 2 right-align.
|
352
|
+
*
|
353
|
+
* <i>dpi</i> sets the resolution to render at. "sans 12" at 72 dpi draws
|
354
|
+
* characters approximately 12 pixels high.
|
355
|
+
*/
|
356
|
+
|
357
|
+
VALUE
|
358
|
+
img_s_text(VALUE obj, VALUE text, VALUE font, VALUE width,
|
359
|
+
VALUE alignment, VALUE dpi)
|
360
|
+
{
|
361
|
+
OutPartial(new, data, im_new);
|
362
|
+
|
363
|
+
if (im_text(im_new, StringValuePtr(text), StringValuePtr(font),
|
364
|
+
NUM2INT(width), NUM2INT(alignment), NUM2INT(dpi)))
|
365
|
+
vips_lib_error();
|
366
|
+
|
367
|
+
return new;
|
368
|
+
}
|
369
|
+
|
370
|
+
/*
|
371
|
+
* call-seq:
|
372
|
+
* im.extract_band(band [,num_bands]) -> image
|
373
|
+
*
|
374
|
+
* Extract the band given by <i>band</i> from the image. If <i>num_bands</i> is
|
375
|
+
* given, extract that many bands. Bands number from zero.
|
376
|
+
*
|
377
|
+
* im.extract_band(0, 2) # => new image with bands 0 & 1 from original.
|
378
|
+
*
|
379
|
+
* Extracting bands outside the input image will trigger an error.
|
380
|
+
*/
|
381
|
+
|
382
|
+
VALUE
|
383
|
+
img_extract_band(int argc, VALUE *argv, VALUE obj)
|
384
|
+
{
|
385
|
+
VALUE v_start_band, v_num_bands;
|
386
|
+
int num_bands;
|
387
|
+
GetImg(obj, data, im);
|
388
|
+
OutImg(obj, new, data_new, im_new);
|
389
|
+
|
390
|
+
rb_scan_args(argc, argv, "11", &v_start_band, &v_num_bands);
|
391
|
+
num_bands = NIL_P(v_num_bands) ? 1 : NUM2INT(v_num_bands);
|
392
|
+
|
393
|
+
if (im_extract_bands(im, im_new, NUM2INT(v_start_band), num_bands))
|
394
|
+
vips_lib_error();
|
395
|
+
|
396
|
+
return new;
|
397
|
+
}
|
398
|
+
|
399
|
+
/*
|
400
|
+
* call-seq:
|
401
|
+
* im.extract_area(left, top, width, height) -> image
|
402
|
+
* im.extract_area(left, top, width, height, band [,num_bands]) -> image
|
403
|
+
*
|
404
|
+
* The first form will extract an area from an image.
|
405
|
+
*
|
406
|
+
* The second form will extract an area and a number of bands from an image.
|
407
|
+
* Bands number from zero. Extracting outside the input image will trigger an
|
408
|
+
* error.
|
409
|
+
*/
|
410
|
+
|
411
|
+
VALUE
|
412
|
+
img_extract_area(int argc, VALUE *argv, VALUE obj)
|
413
|
+
{
|
414
|
+
VALUE v_left, v_top, v_width, v_height, v_start_band, v_num_bands;
|
415
|
+
int start_band, num_bands;
|
416
|
+
GetImg(obj, data, im);
|
417
|
+
OutImg(obj, new, data_new, im_new);
|
418
|
+
|
419
|
+
rb_scan_args(argc, argv, "42", &v_left, &v_top, &v_width, &v_height,
|
420
|
+
&v_start_band, &v_num_bands);
|
421
|
+
|
422
|
+
/* Start band defaults to the first band */
|
423
|
+
start_band = NIL_P(v_start_band) ? 0 : NUM2INT(v_start_band);
|
424
|
+
|
425
|
+
/* Number of bands defaults to all bands or the selected band.
|
426
|
+
*/
|
427
|
+
if (NIL_P(v_num_bands))
|
428
|
+
num_bands = NIL_P(v_start_band) ? im->Bands : 1;
|
429
|
+
else
|
430
|
+
num_bands = NUM2INT(v_num_bands);
|
431
|
+
|
432
|
+
if (im_extract_areabands(im, im_new, NUM2INT(v_left), NUM2INT(v_top),
|
433
|
+
NUM2INT(v_width), NUM2INT(v_height), start_band, num_bands))
|
434
|
+
vips_lib_error();
|
435
|
+
|
436
|
+
return new;
|
437
|
+
}
|
438
|
+
|
439
|
+
/*
|
440
|
+
* call-seq:
|
441
|
+
* im.embed(type_sym, x, y, width, height) -> image
|
442
|
+
*
|
443
|
+
* The opposite of Image#extract: embed an image within a larger image.
|
444
|
+
* <i>type_sym</i> controls what appears in the new pixels:
|
445
|
+
*
|
446
|
+
* * :black - black pels (all bytes == 0)
|
447
|
+
* * :extend - extend pels from image edge
|
448
|
+
* * :repeat - repeat image
|
449
|
+
* * :mirror - mirror image
|
450
|
+
* * :white - white pixels (all bytes == 255)
|
451
|
+
*/
|
452
|
+
|
453
|
+
VALUE
|
454
|
+
img_embed(VALUE obj, VALUE type_v, VALUE x, VALUE y, VALUE width, VALUE height)
|
455
|
+
{
|
456
|
+
ID type_id = SYM2ID(type_v);
|
457
|
+
int type;
|
458
|
+
GetImg(obj, data, im);
|
459
|
+
OutImg(obj, new, data_new, im_new);
|
460
|
+
|
461
|
+
if (type_id == id_black) type = 0;
|
462
|
+
else if (type_id == id_extend) type = 1;
|
463
|
+
else if (type_id == id_repeat) type = 2;
|
464
|
+
else if (type_id == id_mirror) type = 3;
|
465
|
+
else if (type_id == id_white) type = 4;
|
466
|
+
else
|
467
|
+
rb_raise(rb_eArgError, "Extend type must be :black, :extend, :repeat, :mirror, :white");
|
468
|
+
|
469
|
+
if (im_embed(im, im_new, type, NUM2INT(x), NUM2INT(y), NUM2INT(width),
|
470
|
+
NUM2INT(height)))
|
471
|
+
vips_lib_error();
|
472
|
+
|
473
|
+
return new;
|
474
|
+
}
|
475
|
+
|
476
|
+
/*
|
477
|
+
* call-seq:
|
478
|
+
* im.bandjoin(other_image, ...) -> image
|
479
|
+
*
|
480
|
+
* Join a set of images together, bandwise. If the images have n and m bands,
|
481
|
+
* then the output image will have n + m bands, with the first n coming from
|
482
|
+
* the first image and the last m from the second.
|
483
|
+
*
|
484
|
+
* The images must be the same size. The input images are cast up to the
|
485
|
+
* smallest common type.
|
486
|
+
*/
|
487
|
+
|
488
|
+
VALUE
|
489
|
+
img_bandjoin(int argc, VALUE *argv, VALUE obj)
|
490
|
+
{
|
491
|
+
vipsImg *im_t;
|
492
|
+
IMAGE **ins;
|
493
|
+
int i;
|
494
|
+
GetImg(obj, data, im);
|
495
|
+
OutImg(obj, new, data_new, im_new);
|
496
|
+
|
497
|
+
if(argc == 0)
|
498
|
+
rb_raise(rb_eArgError, "Need at least one argument");
|
499
|
+
|
500
|
+
ins = IM_ARRAY(im_new, argc + 1, IMAGE*);
|
501
|
+
ins[0] = im;
|
502
|
+
|
503
|
+
for (i = 0; i < argc; i++) {
|
504
|
+
img_add_dep(data_new, argv[i]);
|
505
|
+
Data_Get_Struct(argv[i], vipsImg, im_t);
|
506
|
+
ins[i + 1] = im_t->in;
|
507
|
+
}
|
508
|
+
|
509
|
+
if (im_gbandjoin(ins, im_new, argc + 1))
|
510
|
+
vips_lib_error();
|
511
|
+
|
512
|
+
return new;
|
513
|
+
}
|
514
|
+
|
515
|
+
/*
|
516
|
+
* call-seq:
|
517
|
+
* im.insert_noexpand(other_image, x, y) -> image
|
518
|
+
*
|
519
|
+
* Insert one image into another. <i>other_image</i> is inserted into *self* at
|
520
|
+
* position <i>x</i>, <i>y</i> relative to the top LH corner of *self*. The
|
521
|
+
* output image is the same size as *self*. <i>other_image</i> is clipped
|
522
|
+
* against the edges of *self*.
|
523
|
+
*
|
524
|
+
* If the number of bands differs, one of the images must have one band. In
|
525
|
+
* this case, an n-band image is formed from the one-band image by joining n
|
526
|
+
* copies of the one-band image together, and then the two n-band images are
|
527
|
+
* operated upon.
|
528
|
+
*
|
529
|
+
* The two input images are cast up to the smallest common type.
|
530
|
+
*/
|
531
|
+
|
532
|
+
VALUE
|
533
|
+
img_insert_noexpand(VALUE obj, VALUE obj2, VALUE x, VALUE y)
|
534
|
+
{
|
535
|
+
GetImg(obj, data, im);
|
536
|
+
GetImg(obj2, data2, im2);
|
537
|
+
OutImg2(obj, obj2, new, data_new, im_new);
|
538
|
+
|
539
|
+
if (im_insert_noexpand(im, im2, im_new, NUM2INT(x), NUM2INT(y)))
|
540
|
+
vips_lib_error();
|
541
|
+
|
542
|
+
return new;
|
543
|
+
}
|
544
|
+
|
545
|
+
static VALUE
|
546
|
+
img_insert_one(VALUE obj, VALUE obj2, VALUE x, VALUE y)
|
547
|
+
{
|
548
|
+
GetImg(obj, data, im);
|
549
|
+
GetImg(obj2, data2, im2);
|
550
|
+
OutImg2(obj, obj2, new, data_new, im_new);
|
551
|
+
|
552
|
+
if (im_insert(im, im2, im_new, NUM2INT(x), NUM2INT(y)))
|
553
|
+
vips_lib_error();
|
554
|
+
|
555
|
+
return new;
|
556
|
+
}
|
557
|
+
|
558
|
+
static VALUE
|
559
|
+
img_insertset(int argc, VALUE *argv, VALUE obj, VALUE obj2)
|
560
|
+
{
|
561
|
+
int i, *x, *y;
|
562
|
+
GetImg(obj, data, im);
|
563
|
+
GetImg(obj2, data2, im2);
|
564
|
+
OutImg2(obj, obj2, new, data_new, im_new);
|
565
|
+
|
566
|
+
x = IM_ARRAY(im_new, argc - 1, int);
|
567
|
+
y = IM_ARRAY(im_new, argc - 1, int);
|
568
|
+
|
569
|
+
for(i = 1; i < argc; i++) {
|
570
|
+
x[i] = NUM2INT(RARRAY_PTR(argv[i])[0]);
|
571
|
+
y[i] = NUM2INT(RARRAY_PTR(argv[i])[1]);
|
572
|
+
}
|
573
|
+
|
574
|
+
if( im_insertset(im, im2, im_new, argc - 1, x, y) )
|
575
|
+
vips_lib_error();
|
576
|
+
|
577
|
+
return new;
|
578
|
+
}
|
579
|
+
|
580
|
+
/*
|
581
|
+
* call-seq:
|
582
|
+
* im.insert(other_image, x, y) -> image
|
583
|
+
* im.insert(other_image, coordinates, ...) -> image
|
584
|
+
*
|
585
|
+
* Insert <i>other_image</i> repeatedly into *self* at the positions listed in
|
586
|
+
* the <i>coordinates</i> arrays. These arrays should contain x and y
|
587
|
+
* coordinates:
|
588
|
+
*
|
589
|
+
* im.insert(other_image, 100, 100) # => other_image inserted once at 100, 100
|
590
|
+
* im.insert(other_image, [12, 20], [32, 22]) # => inserted twice at given coordinates
|
591
|
+
* The output image is the same size as *self*. <i>other_image</i> is clipped
|
592
|
+
* against the edges of *self*.
|
593
|
+
*
|
594
|
+
* This operation is fast for large @n, but will use a memory buffer the size
|
595
|
+
* of the output image. It's useful for things like making scatter plots.
|
596
|
+
*
|
597
|
+
* If the number of bands differs, one of the images must have one band. In
|
598
|
+
* this case, an n-band image is formed from the one-band image by joining n
|
599
|
+
* copies of the one-band image together, and then the two n-band images are
|
600
|
+
* operated upon.
|
601
|
+
*
|
602
|
+
* The two input images are cast up to the smallest common type.
|
603
|
+
*/
|
604
|
+
|
605
|
+
VALUE
|
606
|
+
img_insert(int argc, VALUE *argv, VALUE obj)
|
607
|
+
{
|
608
|
+
VALUE obj2, x_or_ary, y_or_arys;
|
609
|
+
|
610
|
+
rb_scan_args(argc, argv, "2*", &obj2, &x_or_ary, &y_or_arys);
|
611
|
+
|
612
|
+
if (TYPE(x_or_ary) == T_ARRAY) {
|
613
|
+
if (!NIL_P(y_or_arys))
|
614
|
+
rb_ary_unshift(y_or_arys, x_or_ary);
|
615
|
+
|
616
|
+
return img_insertset(RARRAY_LEN(y_or_arys), RARRAY_PTR(y_or_arys), obj,
|
617
|
+
obj2);
|
618
|
+
}
|
619
|
+
|
620
|
+
if (RARRAY_LEN(y_or_arys) != 1)
|
621
|
+
rb_raise(rb_eArgError,
|
622
|
+
"Need two coordinates or an array of coordinates");
|
623
|
+
|
624
|
+
return img_insert_one(obj, obj2, x_or_ary, RARRAY_PTR(y_or_arys)[0]);
|
625
|
+
}
|
626
|
+
|
627
|
+
/*
|
628
|
+
* call-seq:
|
629
|
+
* im.lrjoin(other_image) -> image
|
630
|
+
*
|
631
|
+
* Join *self* and <i>other_image</i> together, left-right. If one is taller
|
632
|
+
* than the other, the output image will be as high as the smaller image.
|
633
|
+
*
|
634
|
+
* If the number of bands differs, one of the images must have one band. In
|
635
|
+
* this case, an n-band image is formed from the one-band image by joining n
|
636
|
+
* copies of the one-band image together, and then the two n-band images are
|
637
|
+
* operated upon.
|
638
|
+
*
|
639
|
+
* The two input images are cast up to the smallest common type.
|
640
|
+
*/
|
641
|
+
|
642
|
+
VALUE
|
643
|
+
img_lrjoin(VALUE obj, VALUE obj2)
|
644
|
+
{
|
645
|
+
RUBY_VIPS_BINARY(im_lrjoin);
|
646
|
+
}
|
647
|
+
|
648
|
+
/*
|
649
|
+
* call-seq:
|
650
|
+
* im.tbjoin(other_image) -> image
|
651
|
+
*
|
652
|
+
* Join *self* and <i>other_image</i> together, top-bottom. If one is taller
|
653
|
+
* than the other, the output image will be as high as the smaller image.
|
654
|
+
*
|
655
|
+
* If the number of bands differs, one of the images must have one band. In
|
656
|
+
* this case, an n-band image is formed from the one-band image by joining n
|
657
|
+
* copies of the one-band image together, and then the two n-band images are
|
658
|
+
* operated upon.
|
659
|
+
*
|
660
|
+
* The two input images are cast up to the smallest common type.
|
661
|
+
*/
|
662
|
+
|
663
|
+
VALUE
|
664
|
+
img_tbjoin(VALUE obj, VALUE obj2)
|
665
|
+
{
|
666
|
+
RUBY_VIPS_BINARY(im_tbjoin);
|
667
|
+
}
|
668
|
+
|
669
|
+
/*
|
670
|
+
* call-seq:
|
671
|
+
* im.replicate(across, down) -> image
|
672
|
+
*
|
673
|
+
* Replicate an image <i>across</i> times horizontally <i>down</i> times
|
674
|
+
* vertically.
|
675
|
+
*/
|
676
|
+
|
677
|
+
VALUE
|
678
|
+
img_replicate(VALUE obj, VALUE across, VALUE down)
|
679
|
+
{
|
680
|
+
GetImg(obj, data, im);
|
681
|
+
OutImg(obj, new, data_new, im_new);
|
682
|
+
|
683
|
+
if (im_replicate(im, im_new, NUM2INT(across), NUM2INT(down)))
|
684
|
+
vips_lib_error();
|
685
|
+
|
686
|
+
return new;
|
687
|
+
}
|
688
|
+
|
689
|
+
/*
|
690
|
+
* call-seq:
|
691
|
+
* im.grid(tile_height, across, down) -> image
|
692
|
+
*
|
693
|
+
* Chop a tall thin image up into a set of tiles, lay the tiles out in a grid.
|
694
|
+
*
|
695
|
+
* *self* should be a very tall, thin image containing a list of smaller
|
696
|
+
* images. Volumetric or time-sequence images are often laid out like this.
|
697
|
+
* This image is chopped into a series of tiles, each <i>tile_height</i> pixels'
|
698
|
+
* high and the width of *self*. The tiles are then rearranged into a grid
|
699
|
+
* <i>across</i> tiles across and <i>down</i> tiles down in row-major order.
|
700
|
+
*/
|
701
|
+
|
702
|
+
VALUE
|
703
|
+
img_grid(VALUE obj, VALUE tile_height, VALUE across, VALUE down)
|
704
|
+
{
|
705
|
+
GetImg(obj, data, im);
|
706
|
+
OutImg(obj, new, data_new, im_new);
|
707
|
+
|
708
|
+
if (im_grid(im, im_new, NUM2INT(tile_height), NUM2INT(across),
|
709
|
+
NUM2INT(down)))
|
710
|
+
vips_lib_error();
|
711
|
+
|
712
|
+
return new;
|
713
|
+
}
|
714
|
+
|
715
|
+
/*
|
716
|
+
* call-seq:
|
717
|
+
* im.wrap(x, y) -> image
|
718
|
+
*
|
719
|
+
* Slice an image up and move the segments about so that the pixel that was
|
720
|
+
* at 0, 0 is now at <i>x</i>, <i>y</i>.
|
721
|
+
*/
|
722
|
+
|
723
|
+
VALUE
|
724
|
+
img_wrap(VALUE obj, VALUE x, VALUE y)
|
725
|
+
{
|
726
|
+
GetImg(obj, data, im);
|
727
|
+
OutImg(obj, new, data_new, im_new);
|
728
|
+
|
729
|
+
if (im_wrap(im, im_new, NUM2INT(x), NUM2INT(y)))
|
730
|
+
vips_lib_error();
|
731
|
+
|
732
|
+
return new;
|
733
|
+
}
|
734
|
+
|
735
|
+
/*
|
736
|
+
* call-seq:
|
737
|
+
* im.fliphor -> image
|
738
|
+
*
|
739
|
+
* Flips an image left-right.
|
740
|
+
*/
|
741
|
+
|
742
|
+
VALUE
|
743
|
+
img_fliphor(VALUE obj)
|
744
|
+
{
|
745
|
+
RUBY_VIPS_UNARY(im_fliphor);
|
746
|
+
}
|
747
|
+
|
748
|
+
/*
|
749
|
+
* call-seq:
|
750
|
+
* im.flipver -> image
|
751
|
+
*
|
752
|
+
* Flips an image top-bottom.
|
753
|
+
*/
|
754
|
+
|
755
|
+
VALUE
|
756
|
+
img_flipver(VALUE obj)
|
757
|
+
{
|
758
|
+
RUBY_VIPS_UNARY(im_flipver);
|
759
|
+
}
|
760
|
+
|
761
|
+
/*
|
762
|
+
* call-seq:
|
763
|
+
* im.rot90 -> image
|
764
|
+
*
|
765
|
+
* Rotate an image 90 degrees.
|
766
|
+
*/
|
767
|
+
|
768
|
+
VALUE
|
769
|
+
img_rot90(VALUE obj)
|
770
|
+
{
|
771
|
+
RUBY_VIPS_UNARY(im_rot90);
|
772
|
+
}
|
773
|
+
|
774
|
+
/*
|
775
|
+
* call-seq:
|
776
|
+
* im.rot180 -> image
|
777
|
+
*
|
778
|
+
* Rotate an image 180 degrees.
|
779
|
+
*/
|
780
|
+
|
781
|
+
VALUE
|
782
|
+
img_rot180(VALUE obj)
|
783
|
+
{
|
784
|
+
RUBY_VIPS_UNARY(im_rot180);
|
785
|
+
}
|
786
|
+
|
787
|
+
/*
|
788
|
+
* call-seq:
|
789
|
+
* im.rot270 -> image
|
790
|
+
*
|
791
|
+
* Rotate an image 270 degrees.
|
792
|
+
*/
|
793
|
+
|
794
|
+
VALUE
|
795
|
+
img_rot270(VALUE obj)
|
796
|
+
{
|
797
|
+
RUBY_VIPS_UNARY(im_rot270);
|
798
|
+
}
|
799
|
+
|
800
|
+
/*
|
801
|
+
* call-seq:
|
802
|
+
* im.subsample(x [,y]) -> image
|
803
|
+
*
|
804
|
+
* Subsample an image by an integer fraction. This is fast nearest-neighbour
|
805
|
+
* shrink.
|
806
|
+
*
|
807
|
+
* If only one integer is given the width and height are subsampled equally.
|
808
|
+
*/
|
809
|
+
|
810
|
+
VALUE
|
811
|
+
img_subsample(int argc, VALUE *argv, VALUE obj)
|
812
|
+
{
|
813
|
+
VALUE x, y;
|
814
|
+
GetImg(obj, data, im);
|
815
|
+
OutImg(obj, new, data_new, im_new);
|
816
|
+
|
817
|
+
rb_scan_args(argc, argv, "11", &x, &y);
|
818
|
+
if (NIL_P(y))
|
819
|
+
y = x;
|
820
|
+
|
821
|
+
if (im_subsample(im, im_new, NUM2INT(x), NUM2INT(y)))
|
822
|
+
vips_lib_error();
|
823
|
+
|
824
|
+
return new;
|
825
|
+
}
|
826
|
+
|
827
|
+
/*
|
828
|
+
* call-seq:
|
829
|
+
* im.zoom(x [,y]) -> image
|
830
|
+
*
|
831
|
+
* Zoom an image by repeating pixels. This is fast nearest-neighbour
|
832
|
+
* zoom.
|
833
|
+
*
|
834
|
+
* If only one integer is given the width and height are zoomed equally.
|
835
|
+
*/
|
836
|
+
|
837
|
+
VALUE
|
838
|
+
img_zoom(int argc, VALUE *argv, VALUE obj)
|
839
|
+
{
|
840
|
+
VALUE x, y;
|
841
|
+
GetImg(obj, data, im);
|
842
|
+
OutImg(obj, new, data_new, im_new);
|
843
|
+
|
844
|
+
rb_scan_args(argc, argv, "11", &x, &y);
|
845
|
+
if (NIL_P(y))
|
846
|
+
y = x;
|
847
|
+
|
848
|
+
if (im_zoom(im, im_new, NUM2INT(x), NUM2INT(y)))
|
849
|
+
vips_lib_error();
|
850
|
+
|
851
|
+
return new;
|
852
|
+
}
|
853
|
+
|
854
|
+
void
|
855
|
+
init_Image_conversion()
|
856
|
+
{
|
857
|
+
id_black = rb_intern("black");
|
858
|
+
id_extend = rb_intern("extend");
|
859
|
+
id_repeat = rb_intern("repeat");
|
860
|
+
id_mirror = rb_intern("mirror");
|
861
|
+
id_white = rb_intern("white");
|
862
|
+
}
|
863
|
+
|