ruby-vips 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md ADDED
@@ -0,0 +1,15 @@
1
+ # master
2
+
3
+ ### Changed
4
+
5
+ * Upgrade spec/* code to latest RSpec [Stanislaw Pankevich]
6
+
7
+ ### Added
8
+
9
+ * Added CHANGELOG.md file (thanks to jnicklas/capybara - using the layout of their History.txt) [Stanislaw Pankevich]
10
+ * Added Gemfile with the only 'rspec' dependency. [Stanislaw Pankevich]
11
+ * Added Jeweler Rakefile contents to release ruby-vips as a gem. [Stanislaw Pankevich]
12
+
13
+ # Before (initial unreleased version 0.1.0)
14
+
15
+ Long-long history here undocumented...
data/Gemfile.lock ADDED
@@ -0,0 +1,31 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ diff-lcs (1.1.3)
5
+ git (1.2.5)
6
+ jeweler (1.8.3)
7
+ bundler (~> 1.0)
8
+ git (>= 1.2.5)
9
+ rake
10
+ rdoc
11
+ json (1.7.3)
12
+ rake (0.9.2.2)
13
+ rdoc (3.12)
14
+ json (~> 1.4)
15
+ rspec (2.10.0)
16
+ rspec-core (~> 2.10.0)
17
+ rspec-expectations (~> 2.10.0)
18
+ rspec-mocks (~> 2.10.0)
19
+ rspec-core (2.10.1)
20
+ rspec-expectations (2.10.0)
21
+ diff-lcs (~> 1.1.3)
22
+ rspec-mocks (2.10.1)
23
+
24
+ PLATFORMS
25
+ ruby
26
+
27
+ DEPENDENCIES
28
+ bundler
29
+ jeweler (~> 1.8.3)
30
+ rdoc (~> 3.12)
31
+ rspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Timothy Elliott
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,96 @@
1
+ ## ruby-vips : A fast image processing extension for Ruby.
2
+
3
+ note: this fork aims to track the latest stable vips. There are no plans to
4
+ add more features, just to keep it working.
5
+
6
+ ruby-vips is a ruby extension for [vips](http://www.vips.ecs.soton.ac.uk). It is
7
+ extremely fast and it can process huge images without requiring the entire image
8
+ to be loaded into memory.
9
+
10
+ ruby-vips allows you to set up pipelines that don't get executed until you
11
+ output the image to disk or to a string. This means you can create,
12
+ manipulate, and pass around Image objects without incurring any memory or CPU
13
+ costs. The image is not actually processed until you write the image to memory
14
+ or to disk.
15
+
16
+ ## Requirements.
17
+
18
+ * OS X or Linux
19
+ * MRI 1.8.6, 1.8.7, 1.9.2 or Rubinius 1.0.1
20
+ * libvips 7.12.x, 7.20.x, 7.22.x, or 7.23.x
21
+
22
+ ## Installation.
23
+
24
+ ### Ubuntu Prerequisites.
25
+
26
+ $ apt-get install libvips-dev
27
+
28
+ The above installs libvips 7.20.x in Ubuntu 10.04 and 7.12.x in Ubuntu 8.04.
29
+ Though ruby-vips will work with libvips 7.12.x, many features are disabled, and
30
+ there are a few caveats.
31
+
32
+ ### OS X Prerequisites.
33
+
34
+ $ brew install vips -HEAD
35
+
36
+ The above installs libvips 7.22.x
37
+
38
+ TODO: Describe & test with macports.
39
+
40
+ ### Installing the gem.
41
+
42
+ ```bash
43
+ $ gem install ruby-vips
44
+ ```
45
+
46
+ or include it in Gemfile:
47
+
48
+ ```ruby
49
+ gem 'ruby-vips'
50
+ ```
51
+
52
+ ## Documentation.
53
+
54
+ ruby-vips has [rdoc documentation](http://rubyvips.holymonkey.com).
55
+
56
+ ## Example.
57
+
58
+ require 'rubygems'
59
+ require 'vips'
60
+ include VIPS
61
+
62
+ # Create an image object. It will not actually load the image until needed.
63
+ im = Image.jpeg('mypic.jpg')
64
+
65
+ # Shrink the jpeg by a factor of four when loading -- huge speed and CPU
66
+ # improvements on large images.
67
+ im = Image.jpeg('mypic.jpg', :shrink_factor => 4)
68
+
69
+ # Add a shrink by a factor of two to the pipeline. This will not actually be
70
+ # executed yet.
71
+ im_shrink_by_two = im.shrink(2)
72
+
73
+ # Write out the shrunk image to a PNG file. This is where the image is
74
+ # actually loaded and resized. With images that allow for random access from
75
+ # the hard drive (VIPS native format, tiled OpenEXR, ppm/pbm/pgm/pfm, tiled
76
+ # tiff, and RAW images), the entire image is never read into memory.
77
+ im_shrink_by_two.png('out.png', :interlace => true)
78
+
79
+ # All ruby-vips image commands can be chained, so the above sequence could
80
+ # be written as:
81
+ Image.jpeg('mypic.jpg', :shrink_factor => 4).shrink(2).png('out.png')
82
+
83
+ # The statement above will load the jpeg (pre-shrunk by a factor of four),
84
+ # shrink the image again by a factor of two, and then save as a png image.
85
+
86
+ # If you want to let vips determine file formats, you can use the generic
87
+ # reader and writer:
88
+ Image.new('mypic.jpg').shrink(2).write('out.png')
89
+
90
+ ## Why use ruby-vips?
91
+
92
+ - It supports over 250 low-level image and color manipulation operations.
93
+ - Operations are chainable, and do not get executed until the image is sent to
94
+ an output.
95
+ - Fastest ruby library for resizing large images. See [benchmarks at the
96
+ official libvips website](http://www.vips.ecs.soton.ac.uk/index.php?title=Speed_and_Memory_Use).
data/TODO ADDED
@@ -0,0 +1,18 @@
1
+ TODO
2
+ * Verify that all memory gets released when vips ops return errors. Namely,
3
+ make sure that the allocated IMAGEs get released via ruby's free callbacks.
4
+ * Allow for injecting ruby code into an image transformation pipeline (may be
5
+ slow to call out to ruby with every read, but may be worthwhile for fun custom
6
+ image processors).
7
+ * Tap into VIPS callback system to allow progress updates, etc.
8
+ * Allow for creating a ruby endpoint to the pipeline could be useful for
9
+ streaming.
10
+ * Image#to_a
11
+ * look into other.h, audit all libvips methods and make sure they are all
12
+ implemented
13
+ * JRuby support
14
+ * Optional extensions to core Ruby classes, allowing operations such as
15
+ [1, 2, 3] & im . This could be optionally enabled by requiring e.g.
16
+ vips/core_ext
17
+ * Put groups of image operations into modules, breaking docs into themes and
18
+ possibly allowing for selective loading of image ops.
data/ext/extconf.rb ADDED
@@ -0,0 +1,10 @@
1
+ ENV['RC_ARCHS'] = '' if RUBY_PLATFORM =~ /darwin/
2
+
3
+ require "mkmf"
4
+
5
+ File::unlink("Makefile") if (File::exist?("Makefile"))
6
+
7
+ %w{7.28 7.27 7.26 7.24 7.23 7.22 7.20}.each{|x| break if pkg_config("vips-#{x}")}
8
+
9
+ have_header('vips/vips.h')
10
+ create_makefile('vips_ext')
data/ext/header.c ADDED
@@ -0,0 +1,440 @@
1
+ #include "ruby_vips.h"
2
+ #include "image.h"
3
+ #include "header.h"
4
+
5
+ VALUE mVIPSHeader;
6
+
7
+ static ID id_notset, id_uchar, id_char, id_ushort, id_short, id_uint, id_int,
8
+ id_float, id_complex, id_double, id_dbcomplex;
9
+
10
+ ID
11
+ header_band_fmt_to_id(VipsBandFmt band_fmt)
12
+ {
13
+ switch(band_fmt) {
14
+ case IM_BANDFMT_NOTSET: return id_notset;
15
+ case IM_BANDFMT_UCHAR: return id_uchar;
16
+ case IM_BANDFMT_CHAR: return id_char;
17
+ case IM_BANDFMT_USHORT: return id_ushort;
18
+ case IM_BANDFMT_SHORT: return id_short;
19
+ case IM_BANDFMT_UINT: return id_uint;
20
+ case IM_BANDFMT_INT: return id_int;
21
+ case IM_BANDFMT_FLOAT: return id_float;
22
+ case IM_BANDFMT_COMPLEX: return id_complex; // two floats
23
+ case IM_BANDFMT_DOUBLE: return id_double;
24
+ case IM_BANDFMT_DPCOMPLEX: return id_dbcomplex; // two doubles
25
+ }
26
+ return id_notset;
27
+ }
28
+
29
+ VipsBandFmt
30
+ header_id_to_band_fmt(ID rb)
31
+ {
32
+ if(rb == id_notset) return IM_BANDFMT_NOTSET;
33
+ else if(rb == id_uchar) return IM_BANDFMT_UCHAR;
34
+ else if(rb == id_char) return IM_BANDFMT_CHAR;
35
+ else if(rb == id_ushort) return IM_BANDFMT_USHORT;
36
+ else if(rb == id_short) return IM_BANDFMT_SHORT;
37
+ else if(rb == id_uint) return IM_BANDFMT_UINT;
38
+ else if(rb == id_int) return IM_BANDFMT_INT;
39
+ else if(rb == id_float) return IM_BANDFMT_FLOAT;
40
+ else if(rb == id_complex) return IM_BANDFMT_COMPLEX;
41
+ else if(rb == id_double) return IM_BANDFMT_DOUBLE;
42
+ else if(rb == id_dbcomplex) return IM_BANDFMT_DPCOMPLEX;
43
+
44
+ return (VipsBandFmt)NULL;
45
+ }
46
+
47
+ /*
48
+ * call-seq:
49
+ * im.x_size -> number
50
+ *
51
+ * Get the width in pixels of the image.
52
+ */
53
+
54
+ static VALUE
55
+ header_x_size(VALUE obj)
56
+ {
57
+ GetImg(obj, data, im);
58
+
59
+ if (im)
60
+ return INT2FIX(im->Xsize);
61
+
62
+ return Qnil;
63
+ }
64
+
65
+ /*
66
+ * call-seq:
67
+ * im.y_size -> number
68
+ *
69
+ * Get the height in pixels of the image.
70
+ */
71
+
72
+ static VALUE
73
+ header_y_size(VALUE obj)
74
+ {
75
+ GetImg(obj, data, im);
76
+
77
+ if (im)
78
+ return INT2FIX(im->Ysize);
79
+
80
+ return Qnil;
81
+ }
82
+
83
+ /*
84
+ * call-seq:
85
+ * im.bands -> number
86
+ *
87
+ * Get the number of bands in the image.
88
+ */
89
+
90
+ static VALUE
91
+ header_bands(VALUE obj)
92
+ {
93
+ GetImg(obj, data, im);
94
+
95
+ if (im)
96
+ return INT2FIX(im->Bands);
97
+
98
+ return Qnil;
99
+ }
100
+
101
+ /*
102
+ * call-seq:
103
+ * im.band_fmt -> band_format_sym
104
+ *
105
+ * Get the band format of the image.
106
+ */
107
+
108
+ static VALUE
109
+ header_band_fmt(VALUE obj)
110
+ {
111
+ GetImg(obj, data, im);
112
+
113
+ if (im)
114
+ return ID2SYM(header_band_fmt_to_id(im->BandFmt));
115
+
116
+ return Qnil;
117
+ }
118
+
119
+ /*
120
+ * call-seq:
121
+ * im.x_res -> number
122
+ *
123
+ * Get the x-resolution of the image.
124
+ */
125
+
126
+ static VALUE
127
+ header_x_res(VALUE obj)
128
+ {
129
+ GetImg(obj, data, im);
130
+
131
+ if (im)
132
+ return rb_float_new(im->Xres);
133
+
134
+ return Qnil;
135
+ }
136
+
137
+ /*
138
+ * call-seq:
139
+ * im.y_res -> number
140
+ *
141
+ * Get the y-resolution of the image.
142
+ */
143
+
144
+ static VALUE
145
+ header_y_res(VALUE obj)
146
+ {
147
+ GetImg(obj, data, im);
148
+
149
+ if (im)
150
+ return rb_float_new(im->Yres);
151
+
152
+ return Qnil;
153
+ }
154
+
155
+ /*
156
+ * call-seq:
157
+ * im.x_offset -> number
158
+ *
159
+ * Get the x-offset of the image.
160
+ */
161
+
162
+ static VALUE
163
+ header_x_offset(VALUE obj)
164
+ {
165
+ GetImg(obj, data, im);
166
+
167
+ if (im)
168
+ return INT2FIX(im->Xoffset);
169
+
170
+ return Qnil;
171
+ }
172
+
173
+ /*
174
+ * call-seq:
175
+ * im.y_offset -> number
176
+ *
177
+ * Get the y-offset of the image.
178
+ */
179
+
180
+ static VALUE
181
+ header_y_offset(VALUE obj)
182
+ {
183
+ GetImg(obj, data, im);
184
+
185
+ if (im)
186
+ return INT2FIX(im->Yoffset);
187
+
188
+ return Qnil;
189
+ }
190
+
191
+ /* VipsImage macros with useful information */
192
+
193
+ /*
194
+ * call-seq:
195
+ * im.sizeof_element -> number
196
+ *
197
+ * Returns the size of a single image band item, in bytes.
198
+ */
199
+
200
+ static VALUE
201
+ header_sizeof_element(VALUE obj)
202
+ {
203
+ GetImg(obj, data, im);
204
+
205
+ if (im)
206
+ return INT2FIX(IM_IMAGE_SIZEOF_ELEMENT(im));
207
+
208
+ return Qnil;
209
+ }
210
+
211
+ /*
212
+ * call-seq:
213
+ * im.sizeof_pel -> number
214
+ *
215
+ * Returns the size of a pixel in the image, in bytes.
216
+ */
217
+
218
+ static VALUE
219
+ header_sizeof_pel(VALUE obj)
220
+ {
221
+ GetImg(obj, data, im);
222
+
223
+ if (im)
224
+ return INT2FIX(IM_IMAGE_SIZEOF_PEL(im));
225
+
226
+ return Qnil;
227
+ }
228
+
229
+ /*
230
+ * call-seq:
231
+ * im.sizeof_line -> number
232
+ *
233
+ * Returns the size of all pixels in the row of the image, uncompressed, in
234
+ * bytes.
235
+ */
236
+
237
+ static VALUE
238
+ header_sizeof_line(VALUE obj)
239
+ {
240
+ GetImg(obj, data, im);
241
+
242
+ if (im)
243
+ return INT2FIX(IM_IMAGE_SIZEOF_LINE(im));
244
+
245
+ return Qnil;
246
+ }
247
+
248
+ /*
249
+ * call-seq:
250
+ * im.n_elements -> number
251
+ *
252
+ * Returns the number of elements in an image row, i.e. bands * x_size.
253
+ */
254
+
255
+ static VALUE
256
+ header_n_elements(VALUE obj)
257
+ {
258
+ GetImg(obj, data, im);
259
+
260
+ if (im)
261
+ return INT2FIX(IM_IMAGE_N_ELEMENTS(im));
262
+
263
+ return Qnil;
264
+ }
265
+
266
+ static VALUE
267
+ header_meta_get(VALUE obj, const char* name)
268
+ {
269
+ GetImg(obj, data, im);
270
+
271
+ void *buf;
272
+ size_t len;
273
+
274
+ if (im_meta_get_blob(im, name, &buf, &len))
275
+ return Qnil;
276
+
277
+ return rb_tainted_str_new((char *)buf, len);
278
+ }
279
+
280
+ static VALUE
281
+ header_meta_get_string(VALUE obj, const char* name)
282
+ {
283
+ GetImg(obj, data, im);
284
+
285
+ char *str;
286
+ VALUE result;
287
+
288
+ if (vips_image_get_as_string(im, name, &str))
289
+ vips_lib_error();
290
+ result = rb_tainted_str_new(str, strlen(str));
291
+ g_free(str);
292
+
293
+ return result;
294
+ }
295
+
296
+ static void
297
+ header_meta_set_string(VALUE obj, const char* name, const char* value)
298
+ {
299
+ GetImg(obj, data, im);
300
+
301
+ vips_image_set_string(im, name, value);
302
+ }
303
+
304
+ static VALUE
305
+ header_meta_p(VALUE obj, const char* name)
306
+ {
307
+ GetImg(obj, data, im);
308
+
309
+ if (im_header_get_typeof(im, name))
310
+ return Qtrue;
311
+
312
+ return Qfalse;
313
+ }
314
+
315
+ /*
316
+ * call-seq:
317
+ * im.exif -> string
318
+ *
319
+ * Returns a binary string containing the raw exif header data.
320
+ */
321
+
322
+ static VALUE
323
+ header_exif(VALUE obj)
324
+ {
325
+ return header_meta_get(obj, IM_META_EXIF_NAME);
326
+ }
327
+
328
+ /*
329
+ * call-seq:
330
+ * im.exif? -> true or false
331
+ *
332
+ * Indicates whether the image has an exif header attached to it.
333
+ */
334
+
335
+ static VALUE
336
+ header_exif_p(VALUE obj)
337
+ {
338
+ return header_meta_p(obj, IM_META_EXIF_NAME);
339
+ }
340
+
341
+ /*
342
+ * call-seq:
343
+ * im.icc -> string
344
+ *
345
+ * Returns a binary string containing the raw icc header data.
346
+ */
347
+
348
+ static VALUE
349
+ header_icc(VALUE obj)
350
+ {
351
+ return header_meta_get(obj, IM_META_ICC_NAME);
352
+ }
353
+
354
+ /*
355
+ * call-seq:
356
+ * im.icc? -> true or false
357
+ *
358
+ * Indicates whether the image has an icc header attached to it.
359
+ */
360
+
361
+ static VALUE
362
+ header_icc_p(VALUE obj)
363
+ {
364
+ return header_meta_p(obj, IM_META_ICC_NAME);
365
+ }
366
+
367
+ /*
368
+ * call-seq:
369
+ * im.get(name) -> string
370
+ *
371
+ * Return metadata item 'name' as a string.
372
+ */
373
+
374
+ static VALUE
375
+ header_get(VALUE obj, VALUE name)
376
+ {
377
+ return header_meta_get_string(obj, StringValuePtr(name));
378
+ }
379
+
380
+ /*
381
+ * call-seq:
382
+ * im.set(name, value)
383
+ *
384
+ * Set metadata item 'name' to value.
385
+ */
386
+
387
+ static VALUE
388
+ header_set(VALUE obj, VALUE name, VALUE value)
389
+ {
390
+ header_meta_set_string(obj,
391
+ StringValuePtr(name), StringValuePtr(value));
392
+
393
+ return Qnil;
394
+ }
395
+
396
+ /*
397
+ * The header module holds image header operations that are common to readers,
398
+ * writers and image objects.
399
+ */
400
+
401
+ void
402
+ init_Header()
403
+ {
404
+ mVIPSHeader = rb_define_module_under(mVIPS, "Header");
405
+
406
+ rb_define_method(mVIPSHeader, "x_size", header_x_size, 0);
407
+ rb_define_method(mVIPSHeader, "y_size", header_y_size, 0);
408
+ rb_define_method(mVIPSHeader, "bands", header_bands, 0);
409
+ rb_define_method(mVIPSHeader, "band_fmt", header_band_fmt, 0);
410
+ rb_define_method(mVIPSHeader, "x_res", header_x_res, 0);
411
+ rb_define_method(mVIPSHeader, "y_res", header_y_res, 0);
412
+ rb_define_method(mVIPSHeader, "x_offset", header_x_offset, 0);
413
+ rb_define_method(mVIPSHeader, "y_offset", header_y_offset, 0);
414
+ rb_define_method(mVIPSHeader, "sizeof_element", header_sizeof_element, 0);
415
+ rb_define_method(mVIPSHeader, "sizeof_pel", header_sizeof_pel, 0);
416
+ rb_define_method(mVIPSHeader, "sizeof_line", header_sizeof_line, 0);
417
+ rb_define_method(mVIPSHeader, "n_elements", header_n_elements, 0);
418
+ rb_define_method(mVIPSHeader, "exif", header_exif, 0);
419
+ rb_define_method(mVIPSHeader, "exif?", header_exif_p, 0);
420
+ rb_define_method(mVIPSHeader, "icc", header_icc, 0);
421
+ rb_define_method(mVIPSHeader, "icc?", header_icc_p, 0);
422
+ rb_define_method(mVIPSHeader, "get", header_get, 1);
423
+ rb_define_method(mVIPSHeader, "set", header_set, 2);
424
+
425
+ id_notset = rb_intern("NOTSET");
426
+ id_uchar = rb_intern("UCHAR");
427
+ id_char = rb_intern("CHAR");
428
+ id_ushort = rb_intern("USHORT");
429
+ id_short = rb_intern("SHORT");
430
+ id_uint = rb_intern("UINT");
431
+ id_int = rb_intern("INT");
432
+ id_float = rb_intern("FLOAT");
433
+ id_complex = rb_intern("COMPLEX");
434
+ id_double = rb_intern("DOUBLE");
435
+ id_dbcomplex = rb_intern("DBCOMPLEX");
436
+
437
+ #if 0
438
+ VALUE mVIPS = rb_define_module("VIPS");
439
+ #endif
440
+ }