carrierwave 0.11.2 → 3.1.2
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 +5 -5
- data/README.md +495 -173
- data/lib/carrierwave/compatibility/paperclip.rb +4 -4
- data/lib/carrierwave/downloader/base.rb +101 -0
- data/lib/carrierwave/downloader/remote_file.rb +68 -0
- data/lib/carrierwave/error.rb +1 -0
- data/lib/carrierwave/locale/en.yml +11 -5
- data/lib/carrierwave/mount.rb +217 -182
- data/lib/carrierwave/mounter.rb +257 -0
- data/lib/carrierwave/orm/activerecord.rb +29 -35
- data/lib/carrierwave/processing/mini_magick.rb +169 -84
- data/lib/carrierwave/processing/rmagick.rb +107 -25
- data/lib/carrierwave/processing/vips.rb +315 -0
- data/lib/carrierwave/processing.rb +1 -1
- data/lib/carrierwave/sanitized_file.rb +105 -87
- data/lib/carrierwave/storage/abstract.rb +16 -3
- data/lib/carrierwave/storage/file.rb +71 -3
- data/lib/carrierwave/storage/fog.rb +228 -57
- data/lib/carrierwave/storage.rb +1 -9
- data/lib/carrierwave/test/matchers.rb +88 -19
- data/lib/carrierwave/uploader/cache.rb +75 -45
- data/lib/carrierwave/uploader/callbacks.rb +1 -3
- data/lib/carrierwave/uploader/configuration.rb +84 -16
- data/lib/carrierwave/uploader/content_type_allowlist.rb +62 -0
- data/lib/carrierwave/uploader/content_type_denylist.rb +62 -0
- data/lib/carrierwave/uploader/default_url.rb +3 -5
- data/lib/carrierwave/uploader/dimension.rb +66 -0
- data/lib/carrierwave/uploader/download.rb +4 -74
- data/lib/carrierwave/uploader/extension_allowlist.rb +63 -0
- data/lib/carrierwave/uploader/extension_denylist.rb +64 -0
- data/lib/carrierwave/uploader/file_size.rb +43 -0
- data/lib/carrierwave/uploader/mountable.rb +13 -8
- data/lib/carrierwave/uploader/processing.rb +51 -13
- data/lib/carrierwave/uploader/proxy.rb +20 -9
- data/lib/carrierwave/uploader/remove.rb +0 -2
- data/lib/carrierwave/uploader/serialization.rb +2 -4
- data/lib/carrierwave/uploader/store.rb +85 -28
- data/lib/carrierwave/uploader/url.rb +8 -7
- data/lib/carrierwave/uploader/versions.rb +175 -125
- data/lib/carrierwave/uploader.rb +12 -10
- data/lib/carrierwave/utilities/file_name.rb +47 -0
- data/lib/carrierwave/utilities/uri.rb +14 -12
- data/lib/carrierwave/utilities.rb +1 -3
- data/lib/carrierwave/validations/active_model.rb +7 -11
- data/lib/carrierwave/version.rb +1 -1
- data/lib/carrierwave.rb +48 -21
- data/lib/generators/templates/{uploader.rb → uploader.rb.erb} +8 -11
- data/lib/generators/uploader_generator.rb +3 -3
- metadata +124 -86
- data/lib/carrierwave/locale/cs.yml +0 -11
- data/lib/carrierwave/locale/de.yml +0 -11
- data/lib/carrierwave/locale/el.yml +0 -11
- data/lib/carrierwave/locale/es.yml +0 -11
- data/lib/carrierwave/locale/fr.yml +0 -11
- data/lib/carrierwave/locale/ja.yml +0 -11
- data/lib/carrierwave/locale/nb.yml +0 -11
- data/lib/carrierwave/locale/nl.yml +0 -11
- data/lib/carrierwave/locale/pl.yml +0 -11
- data/lib/carrierwave/locale/pt-BR.yml +0 -11
- data/lib/carrierwave/locale/pt-PT.yml +0 -11
- data/lib/carrierwave/locale/ru.yml +0 -11
- data/lib/carrierwave/locale/sk.yml +0 -11
- data/lib/carrierwave/locale/tr.yml +0 -11
- data/lib/carrierwave/processing/mime_types.rb +0 -74
- data/lib/carrierwave/uploader/content_type_blacklist.rb +0 -48
- data/lib/carrierwave/uploader/content_type_whitelist.rb +0 -48
- data/lib/carrierwave/uploader/extension_blacklist.rb +0 -47
- data/lib/carrierwave/uploader/extension_whitelist.rb +0 -49
- data/lib/carrierwave/utilities/deprecation.rb +0 -18
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
module CarrierWave
|
4
2
|
|
5
3
|
##
|
@@ -23,9 +21,11 @@ module CarrierWave
|
|
23
21
|
# process :resize_to_fit => [200, 200]
|
24
22
|
# end
|
25
23
|
#
|
26
|
-
# Or create your own helpers with the powerful
|
27
|
-
#
|
28
|
-
#
|
24
|
+
# Or create your own helpers with the powerful minimagick! method, which
|
25
|
+
# yields an ImageProcessing::Builder object. Check out the ImageProcessing
|
26
|
+
# docs at http://github.com/janko-m/image_processing and the list of all
|
27
|
+
# available ImageMagick options at
|
28
|
+
# http://www.imagemagick.org/script/command-line-options.php for more info.
|
29
29
|
#
|
30
30
|
# class MyUploader < CarrierWave::Uploader::Base
|
31
31
|
# include CarrierWave::MiniMagick
|
@@ -33,35 +33,30 @@ module CarrierWave
|
|
33
33
|
# process :radial_blur => 10
|
34
34
|
#
|
35
35
|
# def radial_blur(amount)
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
36
|
+
# minimagick! do |builder|
|
37
|
+
# builder.radial_blur(amount)
|
38
|
+
# builder = yield(builder) if block_given?
|
39
|
+
# builder
|
40
40
|
# end
|
41
41
|
# end
|
42
|
+
# end
|
42
43
|
#
|
43
44
|
# === Note
|
44
45
|
#
|
45
|
-
# MiniMagick
|
46
|
-
#
|
46
|
+
# The ImageProcessing gem uses MiniMagick, a mini replacement for RMagick
|
47
|
+
# that uses ImageMagick command-line tools, to build a "convert" command that
|
48
|
+
# performs the processing.
|
47
49
|
#
|
48
50
|
# You can find more information here:
|
49
51
|
#
|
50
|
-
#
|
51
|
-
# and
|
52
|
-
# https://github.com/minimagic/minimagick/
|
52
|
+
# https://github.com/minimagick/minimagick/
|
53
53
|
#
|
54
54
|
#
|
55
55
|
module MiniMagick
|
56
56
|
extend ActiveSupport::Concern
|
57
57
|
|
58
58
|
included do
|
59
|
-
|
60
|
-
require "mini_magick"
|
61
|
-
rescue LoadError => e
|
62
|
-
e.message << " (You may need to install the mini_magick gem)"
|
63
|
-
raise e
|
64
|
-
end
|
59
|
+
require "image_processing/mini_magick"
|
65
60
|
end
|
66
61
|
|
67
62
|
module ClassMethods
|
@@ -81,9 +76,13 @@ module CarrierWave
|
|
81
76
|
process :resize_to_fill => [width, height, gravity]
|
82
77
|
end
|
83
78
|
|
84
|
-
def resize_and_pad(width, height, background=:transparent, gravity
|
79
|
+
def resize_and_pad(width, height, background=:transparent, gravity='Center')
|
85
80
|
process :resize_and_pad => [width, height, background, gravity]
|
86
81
|
end
|
82
|
+
|
83
|
+
def crop(left, top, width, height)
|
84
|
+
process :crop => [left, top, width, height]
|
85
|
+
end
|
87
86
|
end
|
88
87
|
|
89
88
|
##
|
@@ -93,7 +92,7 @@ module CarrierWave
|
|
93
92
|
#
|
94
93
|
# === Parameters
|
95
94
|
#
|
96
|
-
# [format (#to_s)] an
|
95
|
+
# [format (#to_s)] an abbreviation of the format
|
97
96
|
#
|
98
97
|
# === Yields
|
99
98
|
#
|
@@ -103,12 +102,11 @@ module CarrierWave
|
|
103
102
|
#
|
104
103
|
# image.convert(:png)
|
105
104
|
#
|
106
|
-
def convert(format)
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
img
|
105
|
+
def convert(format, page=nil, &block)
|
106
|
+
minimagick!(block) do |builder|
|
107
|
+
builder = builder.convert(format)
|
108
|
+
builder = builder.loader(page: page) if page
|
109
|
+
builder
|
112
110
|
end
|
113
111
|
end
|
114
112
|
|
@@ -122,16 +120,18 @@ module CarrierWave
|
|
122
120
|
#
|
123
121
|
# [width (Integer)] the width to scale the image to
|
124
122
|
# [height (Integer)] the height to scale the image to
|
123
|
+
# [combine_options (Hash)] additional ImageMagick options to apply before resizing
|
125
124
|
#
|
126
125
|
# === Yields
|
127
126
|
#
|
128
127
|
# [MiniMagick::Image] additional manipulations to perform
|
129
128
|
#
|
130
|
-
def resize_to_limit(width, height)
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
129
|
+
def resize_to_limit(width, height, combine_options: {}, &block)
|
130
|
+
width, height = resolve_dimensions(width, height)
|
131
|
+
|
132
|
+
minimagick!(block) do |builder|
|
133
|
+
builder.resize_to_limit(width, height)
|
134
|
+
.apply(combine_options)
|
135
135
|
end
|
136
136
|
end
|
137
137
|
|
@@ -144,16 +144,18 @@ module CarrierWave
|
|
144
144
|
#
|
145
145
|
# [width (Integer)] the width to scale the image to
|
146
146
|
# [height (Integer)] the height to scale the image to
|
147
|
+
# [combine_options (Hash)] additional ImageMagick options to apply before resizing
|
147
148
|
#
|
148
149
|
# === Yields
|
149
150
|
#
|
150
151
|
# [MiniMagick::Image] additional manipulations to perform
|
151
152
|
#
|
152
|
-
def resize_to_fit(width, height)
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
153
|
+
def resize_to_fit(width, height, combine_options: {}, &block)
|
154
|
+
width, height = resolve_dimensions(width, height)
|
155
|
+
|
156
|
+
minimagick!(block) do |builder|
|
157
|
+
builder.resize_to_fit(width, height)
|
158
|
+
.apply(combine_options)
|
157
159
|
end
|
158
160
|
end
|
159
161
|
|
@@ -167,34 +169,18 @@ module CarrierWave
|
|
167
169
|
# [width (Integer)] the width to scale the image to
|
168
170
|
# [height (Integer)] the height to scale the image to
|
169
171
|
# [gravity (String)] the current gravity suggestion (default: 'Center'; options: 'NorthWest', 'North', 'NorthEast', 'West', 'Center', 'East', 'SouthWest', 'South', 'SouthEast')
|
172
|
+
# [combine_options (Hash)] additional ImageMagick options to apply before resizing
|
170
173
|
#
|
171
174
|
# === Yields
|
172
175
|
#
|
173
176
|
# [MiniMagick::Image] additional manipulations to perform
|
174
177
|
#
|
175
|
-
def resize_to_fill(width, height, gravity = 'Center')
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
scale_y = height/rows.to_f
|
182
|
-
if scale_x >= scale_y
|
183
|
-
cols = (scale_x * (cols + 0.5)).round
|
184
|
-
rows = (scale_x * (rows + 0.5)).round
|
185
|
-
cmd.resize "#{cols}"
|
186
|
-
else
|
187
|
-
cols = (scale_y * (cols + 0.5)).round
|
188
|
-
rows = (scale_y * (rows + 0.5)).round
|
189
|
-
cmd.resize "x#{rows}"
|
190
|
-
end
|
191
|
-
end
|
192
|
-
cmd.gravity gravity
|
193
|
-
cmd.background "rgba(255,255,255,0.0)"
|
194
|
-
cmd.extent "#{width}x#{height}" if cols != width || rows != height
|
195
|
-
end
|
196
|
-
img = yield(img) if block_given?
|
197
|
-
img
|
178
|
+
def resize_to_fill(width, height, gravity = 'Center', combine_options: {}, &block)
|
179
|
+
width, height = resolve_dimensions(width, height)
|
180
|
+
|
181
|
+
minimagick!(block) do |builder|
|
182
|
+
builder.resize_to_fill(width, height, gravity: gravity)
|
183
|
+
.apply(combine_options)
|
198
184
|
end
|
199
185
|
end
|
200
186
|
|
@@ -213,33 +199,76 @@ module CarrierWave
|
|
213
199
|
# [height (Integer)] the height to scale the image to
|
214
200
|
# [background (String, :transparent)] the color of the background as a hexcode, like "#ff45de"
|
215
201
|
# [gravity (String)] how to position the image
|
202
|
+
# [combine_options (Hash)] additional ImageMagick options to apply before resizing
|
203
|
+
#
|
204
|
+
# === Yields
|
205
|
+
#
|
206
|
+
# [MiniMagick::Image] additional manipulations to perform
|
207
|
+
#
|
208
|
+
def resize_and_pad(width, height, background=:transparent, gravity='Center', combine_options: {}, &block)
|
209
|
+
width, height = resolve_dimensions(width, height)
|
210
|
+
|
211
|
+
minimagick!(block) do |builder|
|
212
|
+
builder.resize_and_pad(width, height, background: background, gravity: gravity)
|
213
|
+
.apply(combine_options)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
##
|
218
|
+
# Crop the image to the contents of a box positioned at [left] and [top], with the dimensions given
|
219
|
+
# by [width] and [height]. The original image bottom/right edge is preserved if the cropping box falls
|
220
|
+
# outside the image bounds.
|
221
|
+
#
|
222
|
+
# === Parameters
|
223
|
+
#
|
224
|
+
# [left (integer)] left edge of area to extract
|
225
|
+
# [top (integer)] top edge of area to extract
|
226
|
+
# [width (Integer)] width of area to extract
|
227
|
+
# [height (Integer)] height of area to extract
|
216
228
|
#
|
217
229
|
# === Yields
|
218
230
|
#
|
219
231
|
# [MiniMagick::Image] additional manipulations to perform
|
220
232
|
#
|
221
|
-
def
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
else
|
228
|
-
cmd.background background
|
229
|
-
end
|
230
|
-
cmd.gravity gravity
|
231
|
-
cmd.extent "#{width}x#{height}"
|
232
|
-
end
|
233
|
-
img = yield(img) if block_given?
|
234
|
-
img
|
233
|
+
def crop(left, top, width, height, combine_options: {}, &block)
|
234
|
+
width, height = resolve_dimensions(width, height)
|
235
|
+
|
236
|
+
minimagick!(block) do |builder|
|
237
|
+
builder.crop(left, top, width, height)
|
238
|
+
.apply(combine_options)
|
235
239
|
end
|
236
240
|
end
|
237
241
|
|
242
|
+
##
|
243
|
+
# Returns the width of the image in pixels.
|
244
|
+
#
|
245
|
+
# === Returns
|
246
|
+
#
|
247
|
+
# [Integer] the image's width in pixels
|
248
|
+
#
|
249
|
+
def width
|
250
|
+
mini_magick_image[:width]
|
251
|
+
end
|
252
|
+
|
253
|
+
##
|
254
|
+
# Returns the height of the image in pixels.
|
255
|
+
#
|
256
|
+
# === Returns
|
257
|
+
#
|
258
|
+
# [Integer] the image's height in pixels
|
259
|
+
#
|
260
|
+
def height
|
261
|
+
mini_magick_image[:height]
|
262
|
+
end
|
263
|
+
|
238
264
|
##
|
239
265
|
# Manipulate the image with MiniMagick. This method will load up an image
|
240
266
|
# and then pass each of its frames to the supplied block. It will then
|
241
267
|
# save the image to disk.
|
242
268
|
#
|
269
|
+
# NOTE: This method exists mostly for backwards compatibility, you should
|
270
|
+
# probably use #minimagick!.
|
271
|
+
#
|
243
272
|
# === Gotcha
|
244
273
|
#
|
245
274
|
# This method assumes that the object responds to +current_path+.
|
@@ -259,19 +288,75 @@ module CarrierWave
|
|
259
288
|
cache_stored_file! if !cached?
|
260
289
|
image = ::MiniMagick::Image.open(current_path)
|
261
290
|
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
291
|
+
image = yield(image)
|
292
|
+
FileUtils.mv image.path, current_path
|
293
|
+
|
294
|
+
::MiniMagick::Image.new(current_path).identify
|
295
|
+
rescue ::MiniMagick::Error, ::MiniMagick::Invalid => e
|
296
|
+
raise e if e.message =~ /(You must have .+ installed|is not installed|executable not found|delegate failed)/
|
297
|
+
message = I18n.translate(:"errors.messages.processing_error")
|
298
|
+
raise CarrierWave::ProcessingError, message
|
299
|
+
ensure
|
300
|
+
image.destroy! if image
|
301
|
+
end
|
302
|
+
|
303
|
+
# Process the image with MiniMagick, using the ImageProcessing gem. This
|
304
|
+
# method will build a "convert" ImageMagick command and execute it on the
|
305
|
+
# current image.
|
306
|
+
#
|
307
|
+
# === Gotcha
|
308
|
+
#
|
309
|
+
# This method assumes that the object responds to +current_path+.
|
310
|
+
# Any class that this module is mixed into must have a +current_path+ method.
|
311
|
+
# CarrierWave::Uploader does, so you won't need to worry about this in
|
312
|
+
# most cases.
|
313
|
+
#
|
314
|
+
# === Yields
|
315
|
+
#
|
316
|
+
# [ImageProcessing::Builder] use it to define processing to be performed
|
317
|
+
#
|
318
|
+
# === Raises
|
319
|
+
#
|
320
|
+
# [CarrierWave::ProcessingError] if processing failed.
|
321
|
+
def minimagick!(block = nil)
|
322
|
+
builder = ImageProcessing::MiniMagick.source(current_path)
|
323
|
+
builder = yield(builder)
|
324
|
+
|
325
|
+
result = builder.call
|
326
|
+
result.close
|
327
|
+
|
328
|
+
# backwards compatibility (we want to eventually move away from MiniMagick::Image)
|
329
|
+
if block
|
330
|
+
image = ::MiniMagick::Image.new(result.path, result)
|
331
|
+
image = block.call(image)
|
332
|
+
result = image.instance_variable_get(:@tempfile)
|
333
|
+
end
|
334
|
+
|
335
|
+
FileUtils.mv result.path, current_path
|
336
|
+
|
337
|
+
if File.extname(result.path) != File.extname(current_path)
|
338
|
+
move_to = current_path.chomp(File.extname(current_path)) + File.extname(result.path)
|
339
|
+
file.content_type = Marcel::Magic.by_path(move_to).try(:type)
|
340
|
+
file.move_to(move_to, permissions, directory_permissions)
|
269
341
|
end
|
270
342
|
rescue ::MiniMagick::Error, ::MiniMagick::Invalid => e
|
271
|
-
|
272
|
-
message = I18n.translate(:"errors.messages.
|
343
|
+
raise e if e.message =~ /(You must have .+ installed|is not installed|executable not found)/
|
344
|
+
message = I18n.translate(:"errors.messages.processing_error")
|
273
345
|
raise CarrierWave::ProcessingError, message
|
274
346
|
end
|
275
347
|
|
348
|
+
private
|
349
|
+
|
350
|
+
def resolve_dimensions(*dimensions)
|
351
|
+
dimensions.map do |value|
|
352
|
+
next value unless value.instance_of?(Proc)
|
353
|
+
value.arity >= 1 ? value.call(self) : value.call
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
def mini_magick_image
|
358
|
+
::MiniMagick::Image.read(read)
|
359
|
+
end
|
360
|
+
|
276
361
|
end # MiniMagick
|
277
362
|
end # CarrierWave
|
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
module CarrierWave
|
4
2
|
|
5
3
|
##
|
@@ -24,7 +22,7 @@ module CarrierWave
|
|
24
22
|
# end
|
25
23
|
#
|
26
24
|
# Or create your own helpers with the powerful manipulate! method. Check
|
27
|
-
# out the RMagick docs at
|
25
|
+
# out the RMagick docs at https://rmagick.github.io/ for more
|
28
26
|
# info
|
29
27
|
#
|
30
28
|
# class MyUploader < CarrierWave::Uploader::Base
|
@@ -64,11 +62,20 @@ module CarrierWave
|
|
64
62
|
begin
|
65
63
|
require "rmagick"
|
66
64
|
rescue LoadError
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
65
|
+
begin
|
66
|
+
require "RMagick"
|
67
|
+
rescue LoadError => e
|
68
|
+
e.message << " (You may need to install the rmagick gem)"
|
69
|
+
raise e
|
70
|
+
end
|
71
71
|
end
|
72
|
+
|
73
|
+
prepend Module.new {
|
74
|
+
def initialize(*)
|
75
|
+
super
|
76
|
+
@format = nil
|
77
|
+
end
|
78
|
+
}
|
72
79
|
end
|
73
80
|
|
74
81
|
module ClassMethods
|
@@ -95,16 +102,20 @@ module CarrierWave
|
|
95
102
|
def resize_to_geometry_string(geometry_string)
|
96
103
|
process :resize_to_geometry_string => [geometry_string]
|
97
104
|
end
|
105
|
+
|
106
|
+
def crop(left, top, width, height)
|
107
|
+
process :crop => [left, top, width, height]
|
108
|
+
end
|
98
109
|
end
|
99
110
|
|
100
111
|
##
|
101
112
|
# Changes the image encoding format to the given format
|
102
113
|
#
|
103
|
-
# See even
|
114
|
+
# See even https://rmagick.github.io/magick.html#formats
|
104
115
|
#
|
105
116
|
# === Parameters
|
106
117
|
#
|
107
|
-
# [format (#to_s)] an
|
118
|
+
# [format (#to_s)] an abbreviation of the format
|
108
119
|
#
|
109
120
|
# === Yields
|
110
121
|
#
|
@@ -135,6 +146,8 @@ module CarrierWave
|
|
135
146
|
# [Magick::Image] additional manipulations to perform
|
136
147
|
#
|
137
148
|
def resize_to_limit(width, height)
|
149
|
+
width = dimension_from width
|
150
|
+
height = dimension_from height
|
138
151
|
manipulate! do |img|
|
139
152
|
geometry = Magick::Geometry.new(width, height, 0, 0, Magick::GreaterGeometry)
|
140
153
|
new_img = img.change_geometry(geometry) do |new_width, new_height|
|
@@ -152,7 +165,7 @@ module CarrierWave
|
|
152
165
|
# image may be shorter or narrower than specified in the smaller dimension
|
153
166
|
# but will not be larger than the specified values."
|
154
167
|
#
|
155
|
-
# See even
|
168
|
+
# See even https://rmagick.github.io/image3.html#resize_to_fit
|
156
169
|
#
|
157
170
|
# === Parameters
|
158
171
|
#
|
@@ -164,6 +177,8 @@ module CarrierWave
|
|
164
177
|
# [Magick::Image] additional manipulations to perform
|
165
178
|
#
|
166
179
|
def resize_to_fit(width, height)
|
180
|
+
width = dimension_from width
|
181
|
+
height = dimension_from height
|
167
182
|
manipulate! do |img|
|
168
183
|
img.resize_to_fit!(width, height)
|
169
184
|
img = yield(img) if block_given?
|
@@ -176,7 +191,7 @@ module CarrierWave
|
|
176
191
|
# specified dimensions while retaining the aspect ratio of the original
|
177
192
|
# image. If necessary, crop the image in the larger dimension."
|
178
193
|
#
|
179
|
-
# See even
|
194
|
+
# See even https://rmagick.github.io/image3.html#resize_to_fill
|
180
195
|
#
|
181
196
|
# === Parameters
|
182
197
|
#
|
@@ -188,6 +203,8 @@ module CarrierWave
|
|
188
203
|
# [Magick::Image] additional manipulations to perform
|
189
204
|
#
|
190
205
|
def resize_to_fill(width, height, gravity=::Magick::CenterGravity)
|
206
|
+
width = dimension_from width
|
207
|
+
height = dimension_from height
|
191
208
|
manipulate! do |img|
|
192
209
|
img.crop_resized!(width, height, gravity)
|
193
210
|
img = yield(img) if block_given?
|
@@ -213,15 +230,11 @@ module CarrierWave
|
|
213
230
|
# [Magick::Image] additional manipulations to perform
|
214
231
|
#
|
215
232
|
def resize_and_pad(width, height, background=:transparent, gravity=::Magick::CenterGravity)
|
233
|
+
width = dimension_from width
|
234
|
+
height = dimension_from height
|
216
235
|
manipulate! do |img|
|
217
236
|
img.resize_to_fit!(width, height)
|
218
|
-
|
219
|
-
if background == :transparent
|
220
|
-
filled = new_img.matte_floodfill(1, 1)
|
221
|
-
else
|
222
|
-
filled = new_img.color_floodfill(1, 1, ::Magick::Pixel.from_color(background))
|
223
|
-
end
|
224
|
-
destroy_image(new_img)
|
237
|
+
filled = ::Magick::Image.new(width, height) { |image| image.background_color = background == :transparent ? 'rgba(255,255,255,0)' : background.to_s }
|
225
238
|
filled.composite!(img, gravity, ::Magick::OverCompositeOp)
|
226
239
|
destroy_image(img)
|
227
240
|
filled = yield(filled) if block_given?
|
@@ -251,6 +264,55 @@ module CarrierWave
|
|
251
264
|
end
|
252
265
|
end
|
253
266
|
|
267
|
+
##
|
268
|
+
# Crop the image to the contents of a box positioned at [left] and [top], with the dimensions given
|
269
|
+
# by [width] and [height]. The original image bottom/right edge is preserved if the cropping box falls
|
270
|
+
# outside the image bounds.
|
271
|
+
#
|
272
|
+
# === Parameters
|
273
|
+
#
|
274
|
+
# [left (integer)] left edge of area to extract
|
275
|
+
# [top (integer)] top edge of area to extract
|
276
|
+
# [width (Integer)] width of area to extract
|
277
|
+
# [height (Integer)] height of area to extract
|
278
|
+
#
|
279
|
+
# === Yields
|
280
|
+
#
|
281
|
+
# [Magick::Image] additional manipulations to perform
|
282
|
+
#
|
283
|
+
def crop(left, top, width, height, combine_options: {})
|
284
|
+
width = dimension_from width
|
285
|
+
height = dimension_from height
|
286
|
+
|
287
|
+
manipulate! do |img|
|
288
|
+
img.crop!(left, top, width, height)
|
289
|
+
img = yield(img) if block_given?
|
290
|
+
img
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
##
|
295
|
+
# Returns the width of the image.
|
296
|
+
#
|
297
|
+
# === Returns
|
298
|
+
#
|
299
|
+
# [Integer] the image's width in pixels
|
300
|
+
#
|
301
|
+
def width
|
302
|
+
rmagick_image.columns
|
303
|
+
end
|
304
|
+
|
305
|
+
##
|
306
|
+
# Returns the height of the image.
|
307
|
+
#
|
308
|
+
# === Returns
|
309
|
+
#
|
310
|
+
# [Integer] the image's height in pixels
|
311
|
+
#
|
312
|
+
def height
|
313
|
+
rmagick_image.rows
|
314
|
+
end
|
315
|
+
|
254
316
|
##
|
255
317
|
# Manipulate the image with RMagick. This method will load up an image
|
256
318
|
# and then pass each of its frames to the supplied block. It will then
|
@@ -318,33 +380,53 @@ module CarrierWave
|
|
318
380
|
frames = ::Magick::ImageList.new
|
319
381
|
|
320
382
|
image.each_with_index do |frame, index|
|
321
|
-
frame = yield
|
383
|
+
frame = yield(*[frame, index, options].take(block.arity)) if block_given?
|
322
384
|
frames << frame if frame
|
323
385
|
end
|
324
386
|
frames.append(true) if block_given?
|
325
387
|
|
326
388
|
write_block = create_info_block(options[:write])
|
389
|
+
|
327
390
|
if options[:format] || @format
|
328
391
|
frames.write("#{options[:format] || @format}:#{current_path}", &write_block)
|
392
|
+
move_to = current_path.chomp(File.extname(current_path)) + ".#{options[:format] || @format}"
|
393
|
+
file.content_type = Marcel::Magic.by_path(move_to).try(:type)
|
394
|
+
file.move_to(move_to, permissions, directory_permissions)
|
329
395
|
else
|
330
396
|
frames.write(current_path, &write_block)
|
331
397
|
end
|
398
|
+
|
332
399
|
destroy_image(frames)
|
333
|
-
rescue ::Magick::ImageMagickError
|
334
|
-
raise CarrierWave::ProcessingError, I18n.translate(:"errors.messages.
|
400
|
+
rescue ::Magick::ImageMagickError
|
401
|
+
raise CarrierWave::ProcessingError, I18n.translate(:"errors.messages.processing_error")
|
335
402
|
end
|
336
403
|
|
337
404
|
private
|
338
405
|
|
339
406
|
def create_info_block(options)
|
340
407
|
return nil unless options
|
341
|
-
|
342
|
-
|
343
|
-
|
408
|
+
proc do |img|
|
409
|
+
options.each do |k, v|
|
410
|
+
if v.is_a?(String) && (matches = v.match(/^["'](.+)["']/))
|
411
|
+
CarrierWave.deprecator.warn "Passing quoted strings like #{v} to #manipulate! is deprecated, pass them without quoting."
|
412
|
+
v = matches[1]
|
413
|
+
end
|
414
|
+
img.public_send(:"#{k}=", v)
|
415
|
+
end
|
416
|
+
end
|
344
417
|
end
|
345
418
|
|
346
419
|
def destroy_image(image)
|
347
|
-
image.
|
420
|
+
image.try(:destroy!)
|
421
|
+
end
|
422
|
+
|
423
|
+
def dimension_from(value)
|
424
|
+
return value unless value.instance_of?(Proc)
|
425
|
+
value.arity >= 1 ? value.call(self) : value.call
|
426
|
+
end
|
427
|
+
|
428
|
+
def rmagick_image
|
429
|
+
::Magick::Image.from_blob(self.read).first
|
348
430
|
end
|
349
431
|
|
350
432
|
end # RMagick
|