@@ -55,197 +55,202 @@ ruby-vips has [rdoc documentation](http://rubyvips.holymonkey.com).
55
55
56
56
## Example.
57
57
58
- require 'rubygems'
59
- require 'vips'
60
- include VIPS
58
+ ``` ruby
59
+ require ' rubygems'
60
+ require ' vips'
61
+ include VIPS
61
62
62
- # Create an image object. It will not actually load the image until needed.
63
- im = Image.jpeg('mypic.jpg')
63
+ # Create an image object. It will not actually load the image until needed.
64
+ im = Image .jpeg(' mypic.jpg' )
64
65
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)
66
+ # Shrink the jpeg by a factor of four when loading -- huge speed and CPU
67
+ # improvements on large images.
68
+ im = Image .jpeg(' mypic.jpg' , :shrink_factor => 4 )
68
69
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)
70
+ # Add a shrink by a factor of two to the pipeline. This will not actually be
71
+ # executed yet.
72
+ im_shrink_by_two = im.shrink(2 )
72
73
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)
74
+ # Write out the shrunk image to a PNG file. This is where the image is
75
+ # actually loaded and resized. With images that allow for random access from
76
+ # the hard drive (VIPS native format, tiled OpenEXR, ppm/pbm/pgm/pfm, tiled
77
+ # tiff, and RAW images), the entire image is never read into memory.
78
+ im_shrink_by_two.png(' out.png' , :interlace => true )
78
79
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')
80
+ # All ruby-vips image commands can be chained, so the above sequence could
81
+ # be written as:
82
+ Image .jpeg(' mypic.jpg' , :shrink_factor => 4 ).shrink(2 ).png(' out.png' )
82
83
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.
84
+ # The statement above will load the jpeg (pre-shrunk by a factor of four),
85
+ # shrink the image again by a factor of two, and then save as a png image.
85
86
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')
87
+ # If you want to let vips determine file formats, you can use the generic
88
+ # reader and writer:
89
+ Image .new (' mypic.jpg' ).shrink(2 ).write(' out.png' )
90
+ ```
89
91
90
92
## Longer example
91
93
92
- #!/usr/bin/env ruby
93
-
94
- require 'rubygems'
95
- require 'vips'
96
-
97
- include VIPS
98
-
99
- # sample image shrinker for ruby-vips
100
-
101
- # handy for leak checking, but not actually a complete shrinker. It takes
102
- # no account of things like colour profiles, for example
103
- #
104
- # see vipsthumbnail, part of the standard vips distrubution, for a complete
105
- # shrink program:
106
- #
107
- # https://github.com/jcupitt/libvips/blob/master/tools/vipsthumbnail.c
108
- #
109
- # this demo ought to be worked up to include all that stuff
110
-
111
- # test with:
112
- #
113
- # $ for i in {1..100}; do cp ~/pics/wtc.jpg t_$i.jpg; done
114
- # $ soak.rb t_*.jpg
115
- #
116
- # where wtc.jpg is a 10,000 x 10,000 pixel RGB image
117
- #
118
- # with ruby-vips 0.1.1 and vips-7.28.7 I see a steady ~180mb of memuse as
119
- # this program runs (watching RES in top)
120
- #
121
- # 100mb of this is the vips operation cache, we could disable this to get
122
- # memuse down further if necessary
123
- #
124
- # on my laptop (2009 macbook running ubuntu 12.04):
125
- #
126
- # $ time ./soak.rb t_*.jpg
127
- # real 0m47.809s
128
- # user 0m33.626s
129
- # sys 0m1.516s
130
- #
131
- # ie. about 0.5s real time to do a high-quality shrink of a 10k x 10k
132
- # rgb jpg
133
-
134
- # target size we shrink to ... the image will fit inside a size x size box
135
- size = 100
136
-
137
- # we apply a slight sharpen to thumbnails to make then "pop" a bit
138
- mask = [
139
- [-1, -1, -1],
140
- [-1, 32, -1,],
141
- [-1, -1, -1]
142
- ]
143
- m = Mask.new mask, 24, 0
144
-
145
- # show what we do
146
- # verbose = true
147
- verbose = false
148
-
149
- ARGV.each do |filename|
150
- puts "loop #{filename} ..."
151
-
152
- # get the image size ... ,new() only decompresses pixels on access,
153
- # just opening and getting properties is fast
154
- #
155
- # this will decode small images to a memory buffer, large images to a
156
- # temporary disc file which is then mapped
157
- #
158
- # vips also supports sequential mode access, where the image is
159
- # directly streamed from the source, through the decode library, to
160
- # the destination, but ruby-vips does not yet expose this,
161
- # unfortunately
162
- #
163
- # see
164
- #
165
- # http://libvips.blogspot.co.uk/2012/02/sequential-mode-read.html
166
- #
167
- # enabling this mode would help speed up tiff and png thumbnailing and
168
- # reduce disc traffic, must get around to adding it to ruby-vips
169
- a = Image.new(filename)
170
-
171
- # largest dimension
172
- d = [a.x_size, a.y_size].max
173
-
174
- shrink = d / size.to_f
175
- puts "shrink of #{shrink}" if verbose
176
-
177
- # jpeg images can be shrunk very quickly during load, by a factor of 2,
178
- # 4 or 8
179
- #
180
- # if this is a jpeg, turn on shrink-on-load
181
- #
182
- # a better file type test would be good here :-( vips has a nice one,
183
- # but it's not exposed in ruby-vips yet
184
- if filename.end_with? ".jpg"
185
- if shrink >= 8
186
- load_shrink = 8
187
- elsif shrink >= 4
188
- load_shrink = 4
189
- elsif shrink >= 2
190
- load_shrink = 4
191
- end
192
-
193
- puts "jpeg shrink on load of #{load_shrink}" if verbose
194
-
195
- a = Image.jpeg(filename, :shrink_factor => load_shrink)
196
-
197
- # and recalculate the shrink we need, since the dimensions have changed
198
- d = [a.x_size, a.y_size].max
199
- shrink = d / size.to_f
200
- end
201
-
202
- # we shrink in two stages: we use a box filter (each pixel in output
203
- # is the average of a m x n box of pixels in the input) to shrink by
204
- # the largest integer factor we can, then an affine transform to get
205
- # down to the exact size we need
206
- #
207
- # if you just shrink with the affine, you'll get bad aliasing for large
208
- # shrink factors (more than x2)
209
-
210
- ishrink = shrink.to_i
211
-
212
- # size after int shrink
213
- id = (d / ishrink).to_i
214
-
215
- # therefore residual float scale (note! not shrink)
216
- rscale = size.to_f / id
217
-
218
- puts "block shrink by #{ishrink}" if verbose
219
- puts "residual scale by #{rscale}" if verbose
220
-
221
- # vips has other interpolators, eg. :nohalo ... see the output of
222
- # "vips list classes" at the command-line
223
- #
224
- # :bicubic is well-known and mostly good enough
225
- a = a.shrink(ishrink).affinei_resize(:bicubic, rscale)
226
-
227
- # this will look a little "soft", apply a gentle sharpen
228
- a = a.conv(m)
229
-
230
- # finally ... write to the output
231
- #
232
- # this call will run the pipeline we have built above across all your
233
- # CPUs, though for a simple pipeline like this you'll be spending
234
- # most of your time in the file import / export libraries, which
235
- # are generally single-threaded
236
- a = JPEGWriter.new(a, {:quality => 50})
237
- a.write('test.jpg')
238
-
239
- # force the GC to run and free up any memory vips is hanging on to
240
- #
241
- # without this you'll see memuse slowly climb until ruby runs the GC
242
- # for you
243
- #
244
- # something to make ruby-vips drop refs to vips objects explicitly
245
- # would be nice
246
- GC.start
94
+ ``` ruby
95
+
96
+ # !/usr/bin/env ruby
97
+
98
+ require ' rubygems'
99
+ require ' vips'
100
+
101
+ include VIPS
102
+
103
+ # sample image shrinker for ruby-vips
104
+
105
+ # handy for leak checking, but not actually a complete shrinker. It takes
106
+ # no account of things like colour profiles, for example
107
+ #
108
+ # see vipsthumbnail, part of the standard vips distrubution, for a complete
109
+ # shrink program:
110
+ #
111
+ # https://github.com/jcupitt/libvips/blob/master/tools/vipsthumbnail.c
112
+ #
113
+ # this demo ought to be worked up to include all that stuff
114
+
115
+ # test with:
116
+ #
117
+ # $ for i in {1..100}; do cp ~/pics/wtc.jpg t_$i.jpg; done
118
+ # $ soak.rb t_*.jpg
119
+ #
120
+ # where wtc.jpg is a 10,000 x 10,000 pixel RGB image
121
+ #
122
+ # with ruby-vips 0.1.1 and vips-7.28.7 I see a steady ~180mb of memuse as
123
+ # this program runs (watching RES in top)
124
+ #
125
+ # 100mb of this is the vips operation cache, we could disable this to get
126
+ # memuse down further if necessary
127
+ #
128
+ # on my laptop (2009 macbook running ubuntu 12.04):
129
+ #
130
+ # $ time ./soak.rb t_*.jpg
131
+ # real 0m47.809s
132
+ # user 0m33.626s
133
+ # sys 0m1.516s
134
+ #
135
+ # ie. about 0.5s real time to do a high-quality shrink of a 10k x 10k
136
+ # rgb jpg
137
+
138
+ # target size we shrink to ... the image will fit inside a size x size box
139
+ size = 100
140
+
141
+ # we apply a slight sharpen to thumbnails to make then "pop" a bit
142
+ mask = [
143
+ [- 1 , - 1 , - 1 ],
144
+ [- 1 , 32 , - 1 ,],
145
+ [- 1 , - 1 , - 1 ]
146
+ ]
147
+ m = Mask .new mask, 24 , 0
148
+
149
+ # show what we do
150
+ # verbose = true
151
+ verbose = false
152
+
153
+ ARGV .each do |filename |
154
+ puts " loop #{ filename } ..."
155
+
156
+ # get the image size ... ,new() only decompresses pixels on access,
157
+ # just opening and getting properties is fast
158
+ #
159
+ # this will decode small images to a memory buffer, large images to a
160
+ # temporary disc file which is then mapped
161
+ #
162
+ # vips also supports sequential mode access, where the image is
163
+ # directly streamed from the source, through the decode library, to
164
+ # the destination, but ruby-vips does not yet expose this,
165
+ # unfortunately
166
+ #
167
+ # see
168
+ #
169
+ # http://libvips.blogspot.co.uk/2012/02/sequential-mode-read.html
170
+ #
171
+ # enabling this mode would help speed up tiff and png thumbnailing and
172
+ # reduce disc traffic, must get around to adding it to ruby-vips
173
+ a = Image .new (filename)
174
+
175
+ # largest dimension
176
+ d = [a.x_size, a.y_size].max
177
+
178
+ shrink = d / size.to_f
179
+ puts " shrink of #{ shrink } " if verbose
180
+
181
+ # jpeg images can be shrunk very quickly during load, by a factor of 2,
182
+ # 4 or 8
183
+ #
184
+ # if this is a jpeg, turn on shrink-on-load
185
+ #
186
+ # a better file type test would be good here :-( vips has a nice one,
187
+ # but it's not exposed in ruby-vips yet
188
+ if filename.end_with? " .jpg"
189
+ if shrink >= 8
190
+ load_shrink = 8
191
+ elsif shrink >= 4
192
+ load_shrink = 4
193
+ elsif shrink >= 2
194
+ load_shrink = 4
247
195
end
248
196
197
+ puts " jpeg shrink on load of #{ load_shrink } " if verbose
198
+
199
+ a = Image .jpeg(filename, :shrink_factor => load_shrink)
200
+
201
+ # and recalculate the shrink we need, since the dimensions have changed
202
+ d = [a.x_size, a.y_size].max
203
+ shrink = d / size.to_f
204
+ end
205
+
206
+ # we shrink in two stages: we use a box filter (each pixel in output
207
+ # is the average of a m x n box of pixels in the input) to shrink by
208
+ # the largest integer factor we can, then an affine transform to get
209
+ # down to the exact size we need
210
+ #
211
+ # if you just shrink with the affine, you'll get bad aliasing for large
212
+ # shrink factors (more than x2)
213
+
214
+ ishrink = shrink.to_i
215
+
216
+ # size after int shrink
217
+ id = (d / ishrink).to_i
218
+
219
+ # therefore residual float scale (note! not shrink)
220
+ rscale = size.to_f / id
221
+
222
+ puts " block shrink by #{ ishrink } " if verbose
223
+ puts " residual scale by #{ rscale } " if verbose
224
+
225
+ # vips has other interpolators, eg. :nohalo ... see the output of
226
+ # "vips list classes" at the command-line
227
+ #
228
+ # :bicubic is well-known and mostly good enough
229
+ a = a.shrink(ishrink).affinei_resize(:bicubic , rscale)
230
+
231
+ # this will look a little "soft", apply a gentle sharpen
232
+ a = a.conv(m)
233
+
234
+ # finally ... write to the output
235
+ #
236
+ # this call will run the pipeline we have built above across all your
237
+ # CPUs, though for a simple pipeline like this you'll be spending
238
+ # most of your time in the file import / export libraries, which
239
+ # are generally single-threaded
240
+ a = JPEGWriter .new (a, {:quality => 50 })
241
+ a.write(' test.jpg' )
242
+
243
+ # force the GC to run and free up any memory vips is hanging on to
244
+ #
245
+ # without this you'll see memuse slowly climb until ruby runs the GC
246
+ # for you
247
+ #
248
+ # something to make ruby-vips drop refs to vips objects explicitly
249
+ # would be nice
250
+ GC .start
251
+ end
252
+ ```
253
+
249
254
## Why use ruby-vips?
250
255
251
256
- It supports over 250 low-level image and color manipulation operations.
0 commit comments