carrierwave-vips 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/carrierwave-vips.rb +9 -0
- data/lib/carrierwave/vips.rb +230 -0
- metadata +46 -0
@@ -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: []
|