carrierwave-vips 0.9.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.
- 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: []
|