carrierwave-vips 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,9 @@
1
+ # encoding: utf-8
2
+
3
+ module CarrierWave
4
+
5
+ end
6
+
7
+ require 'vips'
8
+ require 'carrierwave/vips'
9
+
@@ -0,0 +1,230 @@
1
+ # encoding: utf-8
2
+
3
+ module CarrierWave
4
+ module Vips
5
+
6
+ SHARPEN_MASK = begin
7
+ conv_mask = [
8
+ [ -1, -1, -1 ],
9
+ [ -1, 16, -1 ],
10
+ [ -1, -1, -1 ]
11
+ ]
12
+ ::VIPS::Mask.new conv_mask, 8
13
+ end
14
+
15
+ def self.included(base)
16
+ base.send(:extend, ClassMethods)
17
+ end
18
+
19
+ module ClassMethods
20
+ def resize_to_limit(width, height)
21
+ process :resize_to_limit => [width, height]
22
+ end
23
+
24
+ def resize_to_fit(width, height)
25
+ process :resize_to_fit => [width, height]
26
+ end
27
+
28
+ def resize_to_fill(width, height)
29
+ process :resize_to_fill => [width, height]
30
+ end
31
+
32
+ def quality(percent)
33
+ process :quality => percent
34
+ end
35
+
36
+ def convert(extension)
37
+ process :convert => extension
38
+ end
39
+ end
40
+
41
+ ##
42
+ # Change quality of the image (if supported by file format)
43
+ #
44
+ #
45
+ # === Parameters
46
+ # [percent (Integer)] quality from 0 to 100
47
+ #
48
+ def quality(percent)
49
+ manipulate! do |image|
50
+ image.quality = percent if image.respond_to?(:quality=)
51
+ image
52
+ end
53
+ end
54
+
55
+ ##
56
+ # Convert the file to a different format
57
+ #
58
+ #
59
+ # === Parameters
60
+ # [f (String)] the format for the file format (jpeg, png, gif)
61
+ # [opts (Hash)] options to be passed to converting function (ie, :interlace => true for png)
62
+ #
63
+ def convert(f, opts = {})
64
+ f = f.to_s.downcase
65
+ allowed = %w(jpeg png gif)
66
+ raise ArgumentError, "Format must be one of: #{allowed.join(',')}" unless allowed.include?(f)
67
+ @_format = f
68
+ @_format_opts = opts
69
+ end
70
+
71
+ ##
72
+ # Resize the image to fit within the specified dimensions while retaining
73
+ # the original aspect ratio. The image may be shorter or narrower than
74
+ # specified in the smaller dimension but will not be larger than the
75
+ # specified values.
76
+ #
77
+ #
78
+ # === Parameters
79
+ #
80
+ # [width (Integer)] the width to scale the image to
81
+ # [height (Integer)] the height to scale the image to
82
+ #
83
+ def resize_to_fit(new_width, new_height)
84
+ manipulate! do |image|
85
+ resize_image(image,new_width,new_height)
86
+ end
87
+ end
88
+
89
+ ##
90
+ # Resize the image to fit within the specified dimensions while retaining
91
+ # the aspect ratio of the original image. If necessary, crop the image in
92
+ # the larger dimension.
93
+ #
94
+ #
95
+ # === Parameters
96
+ #
97
+ # [width (Integer)] the width to scale the image to
98
+ # [height (Integer)] the height to scale the image to
99
+ #
100
+ def resize_to_fill(new_width, new_height)
101
+ manipulate! do |image|
102
+
103
+ image = resize_image image, new_width, new_height, :max
104
+
105
+ if image.x_size > new_width
106
+ top = 0
107
+ left = (image.x_size - new_width) / 2
108
+ elsif image.y_size > new_height
109
+ left = 0
110
+ top = (image.y_size - new_height) / 2
111
+ end
112
+
113
+ image.extract_area(left, top, new_width, new_height)
114
+
115
+ end
116
+ end
117
+
118
+ ##
119
+ # Resize the image to fit within the specified dimensions while retaining
120
+ # the original aspect ratio. Will only resize the image if it is larger than the
121
+ # specified dimensions. The resulting image may be shorter or narrower than specified
122
+ # in the smaller dimension but will not be larger than the specified values.
123
+ #
124
+ # === Parameters
125
+ #
126
+ # [width (Integer)] the width to scale the image to
127
+ # [height (Integer)] the height to scale the image to
128
+ #
129
+ def resize_to_limit(new_width, new_height)
130
+ manipulate! do |image|
131
+ image = resize_image(image,new_width,new_height) if new_width < image.x_size || new_height < image.y_size
132
+ image
133
+ end
134
+ end
135
+
136
+ ##
137
+ # Manipulate the image with Vips. Saving of the image is delayed until after
138
+ # all the process blocks have been called. Make sure you always return an
139
+ # VIPS::Image object from the block
140
+ #
141
+ # === Gotcha
142
+ #
143
+ # This method assumes that the object responds to +current_path+.
144
+ # Any class that this module is mixed into must have a +current_path+ method.
145
+ # CarrierWave::Uploader does, so you won't need to worry about this in
146
+ # most cases.
147
+ #
148
+ # === Yields
149
+ #
150
+ # [VIPS::Image] for further manipulation
151
+ #
152
+ # === Raises
153
+ #
154
+ # [CarrierWave::ProcessingError] if manipulation failed.
155
+ #
156
+
157
+ def manipulate!
158
+ cache_stored_file! if !cached?
159
+ @_vimage ||= VIPS::Image.new(current_path)
160
+ @_vimage = yield @_vimage
161
+ rescue => e
162
+ raise CarrierWave::ProcessingError.new("Failed to manipulate file, maybe it is not an image? Original Error: #{e}")
163
+ end
164
+
165
+ def process!(*)
166
+ ret = super
167
+ if @_vimage
168
+ tmp_name = current_path.sub(/(\.[a-z]+)$/i, '_tmp\1')
169
+ if @_format
170
+ @vimage.send(format, tmp_name, @_format_opts)
171
+ else
172
+ @_vimage.write(tmp_name)
173
+ end
174
+ FileUtils.mv(tmp_name, current_path)
175
+ @_vimage = nil
176
+ @_format = nil
177
+ end
178
+ ret
179
+ end
180
+
181
+ private
182
+
183
+ def resize_image(image, width, height, min_or_max = :min)
184
+
185
+ ratio = get_ratio image, width, height, min_or_max
186
+
187
+ if jpeg? # find the shrink ratio for loading
188
+ shrink_factors = [8,4,2,1]
189
+ shrink_factor = nil
190
+ shrink_factors.each { |sf| shrink_factor = sf if ratio < 1.0 / sf }
191
+ shrink_factor ||= shrink_factors[-1]
192
+ image = VIPS::Image.jpeg current_path, shrink_factor: shrink_factor, sequential: true
193
+ ratio = get_ratio image, width, height, min_or_max
194
+ elsif png?
195
+ image = VIPS::Image.png curren_path, :sequential => true
196
+ end
197
+
198
+ if ratio > 1
199
+ image = image.affinei_resize :nearest, ratio
200
+ elsif ratio < 1
201
+ if ratio <= 0.5
202
+ image = image.shrink((1/ratio).floor)
203
+ ratio = get_ratio image, width, height, min_or_max
204
+ end
205
+ image = image.affinei_resize :bilinear, ratio unless ratio == 1
206
+ image = image.tile_cache(image.x_size, 1, 30)
207
+ image = image.conv SHARPEN_MASK
208
+ end
209
+
210
+ image
211
+
212
+ end
213
+
214
+ def get_ratio(image, width,height, min_or_max = :min)
215
+ width_ratio = width.to_f / image.x_size
216
+ height_ratio = height.to_f / image.y_size
217
+ [width_ratio, height_ratio].send(min_or_max)
218
+ end
219
+
220
+ def jpeg?(path = current_path)
221
+ path =~ /.*jpg$/i or path =~ /.*jpeg$/i
222
+ end
223
+
224
+ def png?(path = current_path)
225
+ path =~ /.*png$/i
226
+ end
227
+
228
+
229
+ end # Vips
230
+ end # CarrierWave
metadata ADDED
@@ -0,0 +1,46 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: carrierwave-vips
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jeremy Nicoll
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-04 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Adds VIPS support to CarrierWave
15
+ email: eltiare@github.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/carrierwave-vips.rb
21
+ - lib/carrierwave/vips.rb
22
+ homepage: http://rubygems.org/gems/carrierwave-vips
23
+ licenses: []
24
+ post_install_message:
25
+ rdoc_options: []
26
+ require_paths:
27
+ - lib
28
+ required_ruby_version: !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ required_rubygems_version: !ruby/object:Gem::Requirement
35
+ none: false
36
+ requirements:
37
+ - - ! '>='
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ requirements: []
41
+ rubyforge_project:
42
+ rubygems_version: 1.8.24
43
+ signing_key:
44
+ specification_version: 3
45
+ summary: Adds VIPS support to CarrierWave
46
+ test_files: []