async-ruby-vips 1.2.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.
@@ -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
+ }