async-ruby-vips 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2fd9bfe82936faf9228063b50fd6b2b77c6941c8
4
+ data.tar.gz: 73b4f797dd51f56737bdbc5eede0e8a21f730890
5
+ SHA512:
6
+ metadata.gz: 69c7e4a80904bd8b2b74daedc1270c59d933fecca2a1ace15d49e6e53932ff5226b8e34ce6cfe648e156f460d0ce29bae04f79e252b66c2c32edcb672ecc30d3
7
+ data.tar.gz: 605dd6ae731af3ade945dcbb47983c9351bd89569d3b5d7e8aa529fe1da9083c54611b951d615f8e736782723547471a39963d06a3a1a166499cb57d9f5f068b
@@ -0,0 +1,63 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ addressable (2.3.5)
5
+ builder (3.2.2)
6
+ diff-lcs (1.2.5)
7
+ faraday (0.8.8)
8
+ multipart-post (~> 1.2.0)
9
+ git (1.2.6)
10
+ github_api (0.10.1)
11
+ addressable
12
+ faraday (~> 0.8.1)
13
+ hashie (>= 1.2)
14
+ multi_json (~> 1.4)
15
+ nokogiri (~> 1.5.2)
16
+ oauth2
17
+ hashie (2.0.5)
18
+ highline (1.6.20)
19
+ httpauth (0.2.0)
20
+ jeweler (1.8.8)
21
+ builder
22
+ bundler (~> 1.0)
23
+ git (>= 1.2.5)
24
+ github_api (= 0.10.1)
25
+ highline (>= 1.6.15)
26
+ nokogiri (= 1.5.10)
27
+ rake
28
+ rdoc
29
+ json (1.8.1)
30
+ jwt (0.1.8)
31
+ multi_json (>= 1.5)
32
+ multi_json (1.8.2)
33
+ multi_xml (0.5.5)
34
+ multipart-post (1.2.0)
35
+ nokogiri (1.5.10)
36
+ oauth2 (0.9.2)
37
+ faraday (~> 0.8)
38
+ httpauth (~> 0.2)
39
+ jwt (~> 0.1.4)
40
+ multi_json (~> 1.0)
41
+ multi_xml (~> 0.5)
42
+ rack (~> 1.2)
43
+ rack (1.5.2)
44
+ rake (10.1.1)
45
+ rdoc (3.12.2)
46
+ json (~> 1.4)
47
+ rspec (2.14.1)
48
+ rspec-core (~> 2.14.0)
49
+ rspec-expectations (~> 2.14.0)
50
+ rspec-mocks (~> 2.14.0)
51
+ rspec-core (2.14.7)
52
+ rspec-expectations (2.14.4)
53
+ diff-lcs (>= 1.1.3, < 2.0)
54
+ rspec-mocks (2.14.4)
55
+
56
+ PLATFORMS
57
+ ruby
58
+
59
+ DEPENDENCIES
60
+ bundler (~> 1.5)
61
+ jeweler (~> 1.8)
62
+ rdoc (~> 3.12)
63
+ rspec (~> 2.14)
@@ -0,0 +1,101 @@
1
+ async-ruby-vips
2
+ ===============
3
+
4
+ Non-blocking transformation and image writing in Ruby, powered by VIPS
5
+
6
+ ## Requirements
7
+
8
+ * OS X or Linux
9
+ * MRI >= 1.9.2
10
+ * libvips 7.28.x
11
+ * libexif
12
+
13
+ ## Prerequisites
14
+ * On Ubuntu, `apt-get install libvips-dev`, or follow the guidelines at: https://github.com/jcupitt/libvips
15
+
16
+ If you installed it from source, make sure:
17
+ * /usr/local/lib is on your LD_LIBRARY_PATH
18
+ * /usr/local/bin is on PATH
19
+ * /usr/local/lib/pkgconfig is on PKG_CONFIG_PATH
20
+
21
+
22
+ ## Building
23
+ * bundle install # to install dependencies
24
+ * rake gemspec # to generate gemspec file
25
+ * rake build # to build the gem
26
+ * rake install # to install the gem
27
+
28
+ ## Example
29
+
30
+ ```ruby
31
+ require 'rubygems'
32
+ require 'async_vips'
33
+ include AsyncVips
34
+
35
+
36
+ # Non-blocking scaling of an image:
37
+ # Allowed symbols are: :load, :scale_x, :scale_y, :save
38
+ # Wneh called, a function is invoked on a separate native thread.
39
+ # The callback-proc is invoked on a separate Ruby thread on completion.
40
+ AsyncVips.transform(:load => srcfile, :scale_x => 800, :save => dstfile) do |img|
41
+ if(img.error != nil)
42
+ puts img.error
43
+ end
44
+ end
45
+
46
+ # Set the number of operations cached by VIPS:
47
+ AsyncVips.set_cache(100)
48
+
49
+ # Get image information:
50
+ # Allowed symbols are: :load
51
+ AsyncVips.info(:load => srcfile) do |img|
52
+ puts img.src # image filepath
53
+ puts img.width # image width
54
+ puts img.height # image height
55
+ puts img.size # image size in bytes
56
+ end
57
+
58
+
59
+ ## Using event machine
60
+
61
+ require 'rubygems'
62
+ require 'async_vips'
63
+ require 'eventmachine'
64
+ include AsyncVips
65
+
66
+ #puts AsyncVips::VERSION
67
+ #puts AsyncVips::LIB_VERSION
68
+ AsyncVips.set_cache(0) # sets the number of operations cached by VIPS
69
+
70
+ EM.run do
71
+
72
+ EM.add_timer(3) do
73
+ source = './images/*.JPG'
74
+ files = Dir[source]
75
+ files.each do |srcfile|
76
+ dstfile = './output/'+File.basename(srcfile)
77
+
78
+ AsyncVips.transform(:load => srcfile, :scale_x => 800, :save => dstfile) do |img|
79
+ puts img.src
80
+ if(img.error != nil)
81
+ puts img.error
82
+ end
83
+ end
84
+
85
+ end
86
+ end
87
+
88
+ EM.add_periodic_timer(1) do
89
+ puts "#{Time.now}"
90
+ end
91
+ end
92
+
93
+
94
+ ```ruby
95
+
96
+
97
+ ## Version history
98
+
99
+ ### 1.2.1 - added support for natural_orientation flag
100
+ ### 1.1.0 - shrink operation
101
+ ### 1.0.0 - initial release
@@ -0,0 +1,74 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+ # stub: async-ruby-vips 1.2.1 ruby lib
6
+ # stub: ext/extconf.rb
7
+
8
+ Gem::Specification.new do |s|
9
+ s.name = "async-ruby-vips"
10
+ s.version = "1.2.1"
11
+
12
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
13
+ s.require_paths = ["lib"]
14
+ s.authors = ["Grigoriy Chudnov"]
15
+ s.date = "2014-01-27"
16
+ s.description = "Non-blocking transformation and image writing in Ruby, powered by VIPS."
17
+ s.email = "g.chudnov@gmail.com"
18
+ s.extensions = ["ext/extconf.rb"]
19
+ s.extra_rdoc_files = [
20
+ "README.md"
21
+ ]
22
+ s.files = [
23
+ "Gemfile.lock",
24
+ "README.md",
25
+ "async-ruby-vips.gemspec",
26
+ "ext/LICENSE",
27
+ "ext/async_vips.c",
28
+ "ext/async_vips.h",
29
+ "ext/callback.c",
30
+ "ext/callback.h",
31
+ "ext/details.c",
32
+ "ext/details.h",
33
+ "ext/extconf.rb",
34
+ "ext/image.c",
35
+ "ext/image.h",
36
+ "ext/info.c",
37
+ "ext/info.h",
38
+ "ext/transform.c",
39
+ "ext/transform.h",
40
+ "ext/transform_data.c",
41
+ "ext/transform_data.h",
42
+ "ext/transform_data_fwd.h",
43
+ "ext/writer.c",
44
+ "ext/writer.h",
45
+ "lib/async_vips.rb",
46
+ "lib/async_vips/version.rb"
47
+ ]
48
+ s.homepage = "https://github.com/gchudnov/async-ruby-vips"
49
+ s.licenses = ["MIT"]
50
+ s.rubygems_version = "2.2.1"
51
+ s.summary = "async-ruby-vips is a ruby extension for vips that transforms images asynchronously."
52
+
53
+ if s.respond_to? :specification_version then
54
+ s.specification_version = 4
55
+
56
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
57
+ s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
58
+ s.add_development_dependency(%q<bundler>, ["~> 1.5"])
59
+ s.add_development_dependency(%q<jeweler>, ["~> 1.8"])
60
+ s.add_development_dependency(%q<rspec>, ["~> 2.14"])
61
+ else
62
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
63
+ s.add_dependency(%q<bundler>, ["~> 1.5"])
64
+ s.add_dependency(%q<jeweler>, ["~> 1.8"])
65
+ s.add_dependency(%q<rspec>, ["~> 2.14"])
66
+ end
67
+ else
68
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
69
+ s.add_dependency(%q<bundler>, ["~> 1.5"])
70
+ s.add_dependency(%q<jeweler>, ["~> 1.8"])
71
+ s.add_dependency(%q<rspec>, ["~> 2.14"])
72
+ end
73
+ end
74
+
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 Grigoriy Chudnov
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.
@@ -0,0 +1,73 @@
1
+ #include "async_vips.h"
2
+ #include "transform.h"
3
+ #include "writer.h"
4
+ #include "callback.h"
5
+ #include "image.h"
6
+ #include "info.h"
7
+
8
+ VALUE mAsyncVips, eVipsError;
9
+
10
+ /* Initialize VIPS library */
11
+ void av_init()
12
+ {
13
+ VALUE argv_0 = rb_gv_get("0");
14
+
15
+ if(NIL_P(argv_0))
16
+ vips_init("");
17
+ else
18
+ vips_init(RSTRING_PTR(argv_0));
19
+ }
20
+
21
+ /* Print internal debugging information from VIPS, including memory allocation information. */
22
+ static VALUE av_debug_info(VALUE self)
23
+ {
24
+ vips_object_print_all();
25
+ return Qnil;
26
+ }
27
+
28
+ /* Set the max number of operations to keep in cache. */
29
+ static VALUE av_set_cache(VALUE self, VALUE val)
30
+ {
31
+ vips_cache_set_max(NUM2INT(val));
32
+ return Qnil;
33
+ }
34
+
35
+ /* Get the version string */
36
+ static VALUE av_version_string()
37
+ {
38
+ return rb_str_new2(vips_version_string());
39
+ }
40
+
41
+ /* Copy error from vips */
42
+ char* copy_vips_error(void)
43
+ {
44
+ char* result = NULL;
45
+ const char* err_str = vips_error_buffer();
46
+ if(err_str && strlen(err_str) > 0)
47
+ {
48
+ result = malloc(strlen(err_str) + 1);
49
+ strcpy(result, err_str);
50
+ im_error_clear();
51
+ }
52
+
53
+ return result;
54
+ }
55
+
56
+ /* Initialize extension */
57
+ void Init_async_vips_ext()
58
+ {
59
+ av_init();
60
+
61
+ mAsyncVips = rb_define_module("AsyncVips");
62
+ eVipsError = rb_define_class_under(mAsyncVips, "Error", rb_eStandardError);
63
+
64
+ rb_define_singleton_method(mAsyncVips, "debug_info", av_debug_info, 0);
65
+ rb_define_singleton_method(mAsyncVips, "set_cache", av_set_cache, 1);
66
+ rb_define_const(mAsyncVips, "LIB_VERSION", av_version_string());
67
+
68
+ //
69
+ init_async_vips_transform();
70
+ init_async_vips_image();
71
+ init_async_vips_info();
72
+ init_async_vips_event_thread();
73
+ }
@@ -0,0 +1,11 @@
1
+ #ifndef ASYNC_VIPS_H
2
+ #define ASYNC_VIPS_H
3
+
4
+ #include "ruby.h"
5
+ #include "vips/vips.h"
6
+
7
+ extern VALUE mAsyncVips, eVipsError;
8
+
9
+ char* copy_vips_error(void);
10
+
11
+ #endif
@@ -0,0 +1,119 @@
1
+ #include "callback.h"
2
+ #include "async_vips.h"
3
+ #include "image.h"
4
+ #include "transform_data.h"
5
+ #include <pthread.h>
6
+
7
+
8
+ typedef struct _tdata_wait_t
9
+ {
10
+ transform_data_t* tdata;
11
+ int abort;
12
+ } tdata_wait_t;
13
+
14
+
15
+ /* Queue of callbacks; each one invoked on a ruby thread */
16
+ pthread_mutex_t av_proc_mutex = PTHREAD_MUTEX_INITIALIZER;
17
+ pthread_cond_t av_proc_cond = PTHREAD_COND_INITIALIZER;
18
+ transform_data_t* av_proc_queue = NULL;
19
+
20
+ /* Push new callback to front of the queue */
21
+ static void av_proc_queue_push(transform_data_t* tdata)
22
+ {
23
+ tdata->next = av_proc_queue;
24
+ av_proc_queue = tdata;
25
+ }
26
+
27
+ /* Pop next callback from the queue; Returns NULL, when the queue is empty */
28
+ static transform_data_t* av_proc_queue_pop(void)
29
+ {
30
+ transform_data_t* tdata = av_proc_queue;
31
+ if(tdata)
32
+ {
33
+ av_proc_queue = tdata->next;
34
+ }
35
+
36
+ return tdata;
37
+ }
38
+
39
+ /* Callback executed by Ruby Thread */
40
+ static VALUE av_handle_proc(void *d)
41
+ {
42
+ transform_data_t* tdata = (transform_data_t*)d;
43
+
44
+ // Invoke callback with task argument
45
+ VALUE proc = (VALUE)tdata->proc;
46
+ VALUE img = rb_class_new_instance(0, NULL, cImage);
47
+
48
+ av_image_init(img, tdata);
49
+ rb_funcall2(proc, rb_intern("call"), 1, &img);
50
+ rb_gc_unregister_address(&tdata->proc);
51
+
52
+ av_free_transform_data(tdata);
53
+
54
+ return Qnil;
55
+ }
56
+
57
+
58
+ /* Wait until we have some callbacks to process */
59
+ static VALUE av_wait_for_tdata(void* w)
60
+ {
61
+ tdata_wait_t* waiter = (tdata_wait_t*)w;
62
+
63
+ pthread_mutex_lock(&av_proc_mutex);
64
+ while (!waiter->abort && (waiter->tdata = av_proc_queue_pop()) == NULL)
65
+ {
66
+ pthread_cond_wait(&av_proc_cond, &av_proc_mutex);
67
+ }
68
+ pthread_mutex_unlock(&av_proc_mutex);
69
+
70
+ return Qnil;
71
+ }
72
+
73
+ /* Stop waiting for callbacks */
74
+ static void av_stop_waiting_for_tdata(void* w)
75
+ {
76
+ tdata_wait_t* waiter = (tdata_wait_t*)w;
77
+
78
+ pthread_mutex_lock(&av_proc_mutex);
79
+ waiter->abort = 1;
80
+ pthread_mutex_unlock(&av_proc_mutex);
81
+ pthread_cond_signal(&av_proc_cond);
82
+ }
83
+
84
+
85
+ /* ruby event thread, waiting for processed transformations (invokes callbacks) */
86
+ static VALUE av_event_thread(void *unused)
87
+ {
88
+ tdata_wait_t waiter = { .tdata = NULL, .abort = 0 };
89
+ while (!waiter.abort)
90
+ {
91
+ rb_thread_blocking_region(av_wait_for_tdata, &waiter, av_stop_waiting_for_tdata, &waiter);
92
+ if (waiter.tdata)
93
+ {
94
+ rb_thread_create(av_handle_proc, waiter.tdata);
95
+ }
96
+ }
97
+
98
+ return Qnil;
99
+ }
100
+
101
+ /* Initialize Ruby Event Thread for invokation of user-provider callbacks */
102
+ static void av_create_event_thread(void)
103
+ {
104
+ rb_thread_create(av_event_thread, NULL);
105
+ }
106
+
107
+ /* Add the transform data to the event queue */
108
+ void av_add_to_event_queue(transform_data_t* tdata)
109
+ {
110
+ pthread_mutex_lock(&av_proc_mutex);
111
+ av_proc_queue_push(tdata);
112
+ pthread_mutex_unlock(&av_proc_mutex);
113
+ pthread_cond_signal(&av_proc_cond);
114
+ }
115
+
116
+ void init_async_vips_event_thread(void)
117
+ {
118
+ av_create_event_thread();
119
+ }