ruby-vips 1.0.6 → 2.0.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 614489c8022d27d06892f9980c0df0cca00d7598
4
- data.tar.gz: 9c0332039d753a99a4eb526f6b424d6a432c4b6b
3
+ metadata.gz: 294dcea3bbc7b03ef6652be00b29732722bde853
4
+ data.tar.gz: 407c694bb0080bd7bdca1469e3db50f58c5c0daf
5
5
  SHA512:
6
- metadata.gz: c9f73109c2116d56f607e9cee9a01b8bce41d380b223f0e734576a4066184cab9162e514759fcbf36750c6adc30df86467ed1755b9904b6469c66063efee1542
7
- data.tar.gz: 12f7e4f9e3af5ead044a1fd9e46a2e080f0e612b34216fe26966c734501dd2633a66417a25144644b96e00440970345939e591503ca660fa76837b6ff365f85d
6
+ metadata.gz: a36160fc23f5953312f4e3e4fb44db4c45bf4f024586e72f397b7c88457284d4a1e2e0705ca83d2c993b04500d5347ea226b3af3889b91d81396ea432e1e4664
7
+ data.tar.gz: 83e9faa1e666f2d503a9d93f8a249b49c03bf4cda7a5b83bbc60df98e4dde0f51fd73086108749266b752dc887047a02e0ddad49b2f4f0a94b02815a3b2bd884
@@ -5,27 +5,22 @@ env:
5
5
  - NOKOGIRI_USE_SYSTEM_LIBRARIES=true
6
6
  - VIPS_VERSION_MAJOR=8
7
7
  - VIPS_VERSION_MINOR=5
8
- - VIPS_VERSION_MICRO=3
8
+ - VIPS_VERSION_MICRO=7
9
9
  - PATH=$HOME/vips/bin:$PATH
10
10
  - LD_LIBRARY_PATH=$HOME/vips/lib:$LD_LIBRARY_PATH
11
11
  - PKG_CONFIG_PATH=$HOME/vips/lib/pkgconfig:$PKG_CONFIG_PATH
12
- - PYTHONPATH=$HOME/vips/lib/python2.7/site-packages:$PYTHONPATH
13
- - GI_TYPELIB_PATH=$HOME/vips/lib/girepository-1.0:$GI_TYPELIB_PATH
14
12
 
15
13
  dist: trusty
16
14
 
17
15
  addons:
18
16
  apt:
19
17
  packages:
20
- - libxml2-dev
18
+ - libexpat1-dev
21
19
  - gettext
22
- - python-dev
23
- - liblcms1-dev
20
+ - liblcms2-dev
24
21
  - libmagickwand-dev
25
22
  - libopenexr-dev
26
23
  - libcfitsio3-dev
27
- - gobject-introspection
28
- - libgirepository1.0-dev
29
24
  - libgif-dev
30
25
  - libgs-dev
31
26
  - libgsf-1-dev
@@ -34,18 +29,20 @@ addons:
34
29
  - liborc-0.4-dev
35
30
  - libpango1.0-dev
36
31
  - libpoppler-glib-dev
32
+ - librsvg2-dev
37
33
  - libwebp-dev
34
+ # missing on trusty, unfortunately
35
+ # - libwebpmux2
36
+ - libfftw3-dev
38
37
  - libglib2.0-dev
39
38
 
40
39
  cache:
41
40
  directories:
42
41
  - $HOME/vips
43
42
 
44
- # gobject-introspection 3.1 declares itself as 2.1 minimum, so we can't test
45
- # 2.0 ... in fact it seems to work if you force it, but I don't think we can do
46
- # that on travis
47
43
  language: ruby
48
44
  rvm:
45
+ - 2.0
49
46
  - 2.1
50
47
  - 2.2
51
48
  - 2.3
@@ -58,4 +55,4 @@ gemfile:
58
55
 
59
56
  before_install:
60
57
  - uname -a
61
- - bash install-vips.sh
58
+ - bash install-vips.sh --without-python
@@ -1,8 +1,12 @@
1
1
  # master
2
2
 
3
+ # Version 2.0.0
4
+
5
+ * rewrite on top of 'ffi' [John Cupitt, Kleis Auke Wolthuizen]
6
+
3
7
  # Version 1.0.6
4
8
 
5
- * remove lazy load, fixing a race with fork() [felixbuenemann]
9
+ * remove lazy load, fixing a race with multi-threading [felixbuenemann]
6
10
  * make `Image#to_a` much faster [John Cupitt]
7
11
  * remove the `at_exit` handler [John Cupitt]
8
12
 
data/README.md CHANGED
@@ -3,12 +3,7 @@
3
3
  [![Gem Version](https://badge.fury.io/rb/ruby-vips.svg)](https://badge.fury.io/rb/ruby-vips)
4
4
  [![Build Status](https://travis-ci.org/jcupitt/ruby-vips.svg?branch=master)](https://travis-ci.org/jcupitt/ruby-vips)
5
5
 
6
- *API break:* version 1.0 of this gem is an API break, see below for some notes
7
- on why there is a break and how to update your code.
8
- The older `ruby-vips` is still here and still maintained in branch
9
- `0.3-stable`.
10
-
11
- This gem provides a Ruby binding for the [vips image processing
6
+ This gem provides a Ruby binding for the [libvips image processing
12
7
  library](https://jcupitt.github.io/libvips).
13
8
 
14
9
  Programs that use `ruby-vips` don't
@@ -17,25 +12,22 @@ operations building on a source image. When the end of the pipe is connected
17
12
  to a destination, the whole pipeline executes at once, streaming the image
18
13
  in parallel from source to destination a section at a time.
19
14
 
20
- Because `ruby-vips` is very parallel, it's quick, and because it doesn't need
21
- to keep entire images in memory, it's light.
22
- For example, the benchmark at
23
- [vips-benchmarks](https://github.com/stanislaw/vips-benchmarks) loads a large
24
- image, crops, shrinks, sharpens and saves again, and repeats 10 times.
15
+ Because `ruby-vips` is parallel, it's quick, and because it doesn't need to
16
+ keep entire images in memory, it's light. For example, the benchmark at
17
+ [vips-benchmarks](https://github.com/jcupitt/vips-benchmarks) loads a
18
+ large image, crops, shrinks, sharpens and saves again, and repeats 10 times.
25
19
 
26
20
  ```text
27
21
  real time in seconds, fastest of three runs
28
- benchmark tiff jpeg
29
- ruby-vips.rb 2.97 3.29
30
- image-magick 8.18 9.71
31
- rmagick.rb 9.22 10.06
32
- image_sci.rb 9.39 7.20
22
+ benchmark tiff jpeg
23
+ ruby-vips.rb 0.66 0.44
24
+ image-magick 1.10 1.50
25
+ rmagick.rb 1.63 2.16
33
26
 
34
27
  peak memory use in bytes
35
28
  benchmark peak RSS
36
- ruby-vips.rb 117604
37
- image_sci.rb 146536
38
- rmagick.rb 3352020
29
+ ruby-vips.rb 58696
30
+ rmagick.rb 787564
39
31
  ```
40
32
 
41
33
  See also [benchmarks at the official libvips
@@ -46,50 +38,32 @@ which gives some more background.
46
38
 
47
39
  ## Requirements
48
40
 
49
- * OS X or Linux
50
- * libvips 8.2 and later
41
+ * macOS, Linux, and Windows tested
51
42
 
52
- ## Installation prerequisites
43
+ * libvips 8.2 or later, see the [libvips install instructions](https://jcupitt.github.io/libvips/install.html)
53
44
 
54
- ### OS X
45
+ * [ruby-ffi](https://github.com/ffi/ffi) 1.9 or later
55
46
 
56
- Install [homebrew](http://mxcl.github.com/homebrew) and enter:
47
+ * Ruby 2.0+, JRuby should work
57
48
 
58
- ```bash
59
- $ brew install homebrew/science/vips
60
- ```
49
+ ## Install
61
50
 
62
- To verify that your vips install is working, try:
51
+ It's just:
63
52
 
64
- ```bash
65
- $ vips --version
66
- vips-8.2.1
67
53
  ```
68
-
69
- ### Other platforms
70
-
71
- Check your package manager and see if the libvips on your system is new enough.
72
- `ruby-vips` needs libvips 8.2 or later.
73
-
74
- If it's too old, you'll need to build libvips from source.
75
- Download a tarball from the
76
- [libvips website](https://jcupitt.github.io/libvips), or build
77
- from [the git repository](https://github.com/jcupitt/libvips) and see the
78
- README.
79
-
80
- ## Installing the gem.
81
-
82
- ```bash
83
- $ gem install ruby-vips
54
+ $ gem install ruby-vips
84
55
  ```
85
56
 
86
- or include it in Gemfile:
57
+ or include it in `Gemfile`:
87
58
 
88
59
  ```ruby
89
60
  gem 'ruby-vips'
90
61
  ```
91
62
 
92
- And take a look in `examples/`. There is full yard documentation, take a look
63
+ On Windows, you'll need to set the `RUBY_DLL_PATH` environment variable to
64
+ point to the libvips bin directory.
65
+
66
+ Take a look in `examples/`. There is full yard documentation, take a look
93
67
  there too.
94
68
 
95
69
  # Example
@@ -103,7 +77,7 @@ im = Vips::Image.new_from_file filename
103
77
  # make the other pixels in the image by mirroring im up / down /
104
78
  # left / right, see
105
79
  # https://jcupitt.github.io/libvips/API/current/libvips-conversion.html#vips-embed
106
- im = im.embed 100, 100, 3000, 3000, :extend => :mirror
80
+ im = im.embed 100, 100, 3000, 3000, extend: :mirror
107
81
 
108
82
  # multiply the green (middle) band by 2, leave the other two alone
109
83
  im *= [1, 2, 1]
@@ -113,76 +87,19 @@ mask = Vips::Image.new_from_array [
113
87
  [-1, -1, -1],
114
88
  [-1, 16, -1],
115
89
  [-1, -1, -1]], 8
116
- im = im.conv mask
90
+ im = im.conv mask, precision: :integer
117
91
 
118
92
  # finally, write the result back to a file on disk
119
93
  im.write_to_file output_filename
120
94
  ```
121
95
 
122
- # Why the API break?
123
-
124
- There's been a `ruby-vips` for a few years now.
125
- It was written by a Ruby
126
- expert, it works well, it includes a test-suite, and has pretty full
127
- documentation. Why rewrite?
128
-
129
- `ruby-vips` 0.3 was based on the old vips7 API. There's now vips8,
130
- which adds several
131
- very useful new features:
132
-
133
- * [GObject](https://developer.gnome.org/gobject/stable/)-based API with full
134
- introspection. You can discover the vips8 API at runtime. This means that if
135
- libvips gets a new operator, any binding that goes via vips8 will
136
- get the new thing immediately. With vips7, whenever libvips was changed, all
137
- the bindings needed to be changed too.
138
-
139
- * No C required. Thanks to
140
- [gobject-introspection](https://wiki.gnome.org/Projects/GObjectIntrospection)
141
- you can write the binding in Ruby itself, there's no need for any C. This
142
- makes it a lot smaller and more portable.
143
-
144
- * vips7 probably won't get new features. vips7 doesn't really exist any more:
145
- the API is still there, but now just a thin compatibility layer over vips8.
146
- New features may well not get added to the vips7 API.
147
-
148
- There are some more minor pluses as well:
149
-
150
- * Named and optional arguments. vips8 lets you have optional and required
151
- arguments, both input and output, and optional arguments can have default
152
- values.
153
-
154
- * Operation cache. vips8 keeps track of the last 1,000 or so operations and
155
- will automatically reuse results when it can. This can give a huge speedup
156
- in some cases.
157
-
158
- * vips8 is much simpler and more regular. For example,
159
- ruby-vips had to work hard to offer a nice loader system, but that's all
160
- built into vips8. It can do things like load and save formatted images to
161
- and from memory buffers as well, which just wasn't possible before.
162
-
163
- This binding adds some extra useful features over the old `ruby-vips` binding.
164
-
165
- * Full set of arithmetic operator overloads.
166
-
167
- * Automatic constant expansion. You can write things like
168
- `image.bandjoin(255)` and the 255 will be automatically expanded to an image
169
- and attached as an extra band. You can mix int, float, scalar, vector and
170
- image constants freely.
171
-
172
- # How to update your code
173
-
174
- * `VIPS::` becomes `Vips::`
175
-
176
- * `VIPS::Image.new(filename)` becomes `Vips::Image.new_from_file(filename)`.
177
- `VIPS::Image.jpeg(filename)` also becomes
178
- `Vips::Image.new_from_file(filename)`, similarly for other formats.
96
+ # Older versions
179
97
 
180
- * `#write(filename)` becomes `#write_to_file(filename)`. `#png(filename)` also
181
- becomes `#write_to_file(filename)`, same for all other
182
- formats.
98
+ There are two older versions of this gem.
183
99
 
184
- * Most member functions are unchanged, but check the yard docs. You can also
185
- use the C docs directly, since `ruby-vips` is now a very thin layer over the
186
- C API. See the docs for the `Vips` class for guidance.
100
+ The `0.3-stable` branch is written in C and supports a different API. It still
101
+ works, but is only maintained for compatibility.
187
102
 
188
- * There are lots of nice new features, see the docs and examples.
103
+ The `1.0-stable` branch is based on `gobject-introspection` rather than
104
+ `ffi`. It supports the same API as the current version, but is harder to
105
+ install, less portable, slower, and less stable.
data/TODO CHANGED
@@ -1,11 +1,5 @@
1
1
  # Notes
2
2
 
3
- - mail about the getpoint unimplemented error
4
-
5
- http://sourceforge.net/p/ruby-gnome2/mailman/ruby-gnome2-devel-en/thread/CAGNS0RuZ5N6bha3M7B0%2BYf2M9-oni44idzZO17mtQiykS%2BmJKQ%40mail.gmail.com/#msg34790843
6
-
7
- - still missing a few enum docs
8
-
9
3
  - support complex constants, eg.
10
4
 
11
5
  Complex(1, 2)
@@ -28,3 +22,7 @@
28
22
  - push new gem to rubygems, tag repository with version
29
23
 
30
24
  bundle exec rake release
25
+
26
+ - regenerate docs
27
+
28
+ bundle exec rake yard
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.6
1
+ 2.0.0
@@ -0,0 +1,286 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'ffi'
4
+ require 'forwardable'
5
+
6
+ # this is really very crude logging
7
+
8
+ # @private
9
+ $vips_debug = true
10
+
11
+ # @private
12
+ def log str
13
+ if $vips_debug
14
+ puts str
15
+ end
16
+ end
17
+
18
+ def set_debug debug
19
+ $vips_debug = debug
20
+ end
21
+
22
+ module Libc
23
+ extend FFI::Library
24
+ ffi_lib FFI::Library::LIBC
25
+
26
+ attach_function :malloc, [:size_t], :pointer
27
+ attach_function :free, [:pointer], :void
28
+ end
29
+
30
+ module GLib
31
+ extend FFI::Library
32
+ ffi_lib 'gobject-2.0'
33
+
34
+ # nil being the default
35
+ glib_log_domain = nil
36
+
37
+ def self.set_log_domain(domain)
38
+ glib_log_domain = domain
39
+ end
40
+
41
+ # we have a set of things we need to inherit in different ways:
42
+ #
43
+ # - we want to be able to subclass GObject in a simple way
44
+ # - the layouts of the nested structs
45
+ # - casting between structs which share a base
46
+ # - gobject refcounting
47
+ #
48
+ # the solution is to split the class into four areas which we treat
49
+ # differently:
50
+ #
51
+ # - we have a "wrapper" Ruby class to allow easy subclassing ... this has a
52
+ # @struct member which holds the actual pointer
53
+ # - we use "forwardable" to forward the various ffi methods on to the
54
+ # @struct member ... we arrange things so that subclasses do not need to
55
+ # do the forwarding themselves
56
+ # - we have two versions of the struct: a plain one which we can use for
57
+ # casting that will not change the refcounts
58
+ # - and a managed one with an unref which we just use for .new
59
+ # - we separate the struct layout into a separate module to avoid repeating
60
+ # ourselves
61
+
62
+ class GObject
63
+ extend Forwardable
64
+ extend SingleForwardable
65
+
66
+ def_instance_delegators :@struct, :[], :to_ptr
67
+ def_single_delegators :ffi_struct, :ptr
68
+
69
+ # the layout of the GObject struct
70
+ module GObjectLayout
71
+ def self.included(base)
72
+ base.class_eval do
73
+ layout :g_type_instance, :pointer,
74
+ :ref_count, :uint,
75
+ :qdata, :pointer
76
+ end
77
+ end
78
+ end
79
+
80
+ # the struct with unref ... manage object lifetime with this
81
+ class ManagedStruct < FFI::ManagedStruct
82
+ include GObjectLayout
83
+
84
+ def initialize(ptr)
85
+ log "GLib::GObject::ManagedStruct.new: #{ptr}"
86
+ super
87
+ end
88
+
89
+ def self.release(ptr)
90
+ log "GLib::GObject::ManagedStruct.release: unreffing #{ptr}"
91
+ GLib::g_object_unref(ptr) unless ptr.null?
92
+ end
93
+
94
+ end
95
+
96
+ # the plain struct ... cast with this
97
+ class Struct < FFI::Struct
98
+ include GObjectLayout
99
+
100
+ def initialize(ptr)
101
+ log "GLib::GObject::Struct.new: #{ptr}"
102
+ super
103
+ end
104
+
105
+ end
106
+
107
+ # don't allow ptr == nil, we never want to allocate a GObject struct
108
+ # ourselves, we just want to wrap GLib-allocated GObjects
109
+ #
110
+ # here we use ManagedStruct, not Struct, since this is the ref that will
111
+ # need the unref
112
+ def initialize(ptr)
113
+ log "GLib::GObject.initialize: ptr = #{ptr}"
114
+ @struct = ffi_managed_struct.new(ptr)
115
+ end
116
+
117
+ # access to the cast struct for this class
118
+ def ffi_struct
119
+ self.class.ffi_struct
120
+ end
121
+
122
+ class << self
123
+ def ffi_struct
124
+ self.const_get(:Struct)
125
+ end
126
+ end
127
+
128
+ # access to the lifetime managed struct for this class
129
+ def ffi_managed_struct
130
+ self.class.ffi_managed_struct
131
+ end
132
+
133
+ class << self
134
+ def ffi_managed_struct
135
+ self.const_get(:ManagedStruct)
136
+ end
137
+ end
138
+
139
+ end
140
+
141
+ # :gtype will usually be 64-bit, but will be 32-bit on 32-bit Windows
142
+ typedef :ulong, :GType
143
+
144
+ end
145
+
146
+ module Vips
147
+ extend FFI::Library
148
+ ffi_lib 'vips'
149
+
150
+ LOG_DOMAIN = "VIPS"
151
+ GLib::set_log_domain(LOG_DOMAIN)
152
+
153
+ # need to repeat this
154
+ typedef :ulong, :GType
155
+
156
+ attach_function :vips_init, [:string], :int
157
+ attach_function :vips_shutdown, [], :void
158
+
159
+ attach_function :vips_error_buffer, [], :string
160
+ attach_function :vips_error_clear, [], :void
161
+
162
+ def self.get_error
163
+ errstr = Vips::vips_error_buffer
164
+ Vips::vips_error_clear
165
+ errstr
166
+ end
167
+
168
+ if Vips::vips_init($0) != 0
169
+ puts Vips::get_error
170
+ exit 1
171
+ end
172
+
173
+ at_exit {
174
+ Vips::vips_shutdown
175
+ }
176
+
177
+ attach_function :vips_object_print_all, [], :void
178
+ attach_function :vips_leak_set, [:int], :void
179
+
180
+ def self.showall
181
+ if $vips_debug
182
+ GC.start
183
+ vips_object_print_all
184
+ end
185
+ end
186
+
187
+ if $vips_debug
188
+ vips_leak_set 1
189
+ end
190
+
191
+ class VipsObject < GLib::GObject
192
+
193
+ # the layout of the VipsObject struct
194
+ module VipsObjectLayout
195
+ def self.included(base)
196
+ base.class_eval do
197
+ # don't actually need most of these, remove them later
198
+ layout :parent, GLib::GObject::Struct,
199
+ :constructed, :int,
200
+ :static_object, :int,
201
+ :argument_table, :pointer,
202
+ :nickname, :string,
203
+ :description, :string,
204
+ :preclose, :int,
205
+ :close, :int,
206
+ :postclose, :int,
207
+ :local_memory, :size_t
208
+ end
209
+ end
210
+ end
211
+
212
+ class Struct < GLib::GObject::Struct
213
+ include VipsObjectLayout
214
+
215
+ def initialize(ptr)
216
+ log "Vips::VipsObject::Struct.new: #{ptr}"
217
+ super
218
+ end
219
+
220
+ end
221
+
222
+ class ManagedStruct < GLib::GObject::ManagedStruct
223
+ include VipsObjectLayout
224
+
225
+ def initialize(ptr)
226
+ log "Vips::VipsObject::ManagedStruct.new: #{ptr}"
227
+ super
228
+ end
229
+
230
+ end
231
+
232
+ end
233
+
234
+ class VipsImage < VipsObject
235
+
236
+ # the layout of the VipsImage struct
237
+ module VipsImageLayout
238
+ def self.included(base)
239
+ base.class_eval do
240
+ layout :parent, VipsObject::Struct
241
+ # rest opaque
242
+ end
243
+ end
244
+ end
245
+
246
+ class Struct < VipsObject::Struct
247
+ include VipsImageLayout
248
+
249
+ def initialize(ptr)
250
+ log "Vips::VipsImage::Struct.new: #{ptr}"
251
+ super
252
+ end
253
+
254
+ end
255
+
256
+ class ManagedStruct < VipsObject::ManagedStruct
257
+ include VipsImageLayout
258
+
259
+ def initialize(ptr)
260
+ log "Vips::VipsImage::ManagedStruct.new: #{ptr}"
261
+ super
262
+ end
263
+
264
+ end
265
+
266
+ def self.new_partial
267
+ VipsImage.new(Vips::vips_image_new)
268
+ end
269
+
270
+ end
271
+
272
+ attach_function :vips_image_new, [], :pointer
273
+
274
+ end
275
+
276
+ puts "creating image"
277
+ begin
278
+ x = Vips::VipsImage.new_partial
279
+ puts "x = #{x}"
280
+ puts ""
281
+ puts "x[:parent] = #{x[:parent]}"
282
+ puts ""
283
+ puts "x[:parent][:description] = #{x[:parent][:description]}"
284
+ puts ""
285
+ end
286
+