Undefined Метод обрезки! Использование Carrierwave с MiniMagick на рейках 3.1.3
У меня было чертовски время заставить это работать, и все еще есть. Я доберусь до сути. Я следую учебнику Райана Бэйтса, чтобы сделать работу по обрезке с помощью Jcrop и Carrierwave. Я решил использовать MiniMagick, потому что даже после переустановки ImageMagick и RMagick на моем компьютере я получаю сообщение об ошибке, которое убивает сервер rails на моей локальной машине. В любом случае, переход на MiniMagick исправил это для меня.
Так что до настоящего момента все очень хорошо. Я получаю изображения разных размеров, и они загружаются успешно.
Но как только я пытаюсь обрезать, я получаю эту ошибку:
undefined method `crop!' for #<MiniMagick::CommandBuilder:0x000001052e4608>
Это сбивает меня с толку, потому что я использую почти тот же код, что и Bates:
def crop
if model.crop_x.present?
resize_to_limit(700, 700)
manipulate! do |img|
x = model.crop_x.to_i
y = model.crop_y.to_i
w = model.crop_w.to_i
h = model.crop_h.to_i
img.crop!(x, y, w, h)
end
end
end
В любом случае, это метод урожая, который не работает. Поэтому я подумал про себя, что команда ImageMagick... Поэтому я посмотрел на ImageMagick doco, и я не смог найти метод обрезки с ударом, поэтому я пробовал его без него, а затем ошибка обращается к этому:
No such file or directory - /var/folders/dF/dFNM2+Y7FVScn4+OxVHKOU+++TI/-Tmp-/mini_magick20111207-34409-1tnaa07.jpg
В любом случае, что-то не придает мне смысла, любая помощь будет оценена!
Спасибо за чтение!
Ответы
Ответ 1
Имели те же проблемы, моим решением был этот метод
def cropped_image(params)
image = MiniMagick::Image.open(self.image.path)
crop_params = "#{params[:w]}x#{params[:h]}+#{params[:x]}+#{params[:y]}"
image.crop(crop_params)
image
end
Просто измените мой метод для вашего дела.
Ключ в том, в каком формате передать переменные методу обрезки, надеюсь, что это поможет вам.
Ответ 2
Короче:
img.crop("#{size}#{offset}") # Doesn't return an image...
img # ...so you'll need to call it yourself
Вот лучшее объяснение, почему это произошло, в отличие от решения стиля вырезать/вставить.
RMagick и MiniMagick не являются взаимозаменяемыми. RMagick имеет очень похожий на Ruby DSL и, как таковой, использует методы, которые принимают несколько аргументов:
rmagick_image.crop(x_offset, y_offset, width, height) # Returns an image object
rmagick_image.crop!(x_offset, y_offset, width, height) # Edits object in place
MiniMagick вместо этого динамически генерирует методы итерации через список MOGRIFY_COMMANDS
, которые соответствуют многочисленным опциям с префиксами, указанными в ImageMagick mogrify
. Каждый из этих методов передает свои аргументы непосредственно в mogrify
, и ни один из них не возвращает объект изображения:
minimagick_image.crop('100x200') # Translates to `mogrify -crop 100x200 image.ext`
minimagick_image.polaroid('12') # Executes `mogrify -polaroid 12 image.ext`
В натуральном выражении RMagick имеет crop!
, а MiniMagick этого не делает.
Согласно документам ImageMagick, mogrify -crop
принимает аргумент geometry
. Аргумент geometry
объясняется здесь. Вы заметите, что все эти аргументы являются строками, поэтому вместо crop(100,200)
вы должны использовать crop('100x200')
или crop('100%)
. Это не очень похоже на Ruby, но та часть, которая делает MiniMagick таким легким.
С помощью этих знаний мы можем определить, как обрезать MiniMagick. mogrify -crop
может принимать геометрию как строку width
x height
+ xoffset
+ yoffset
, поэтому нам просто нужно построить подобную строку.
Учитывая w
, h
, x
и y
, вы можете использовать любое из следующего, которое вы найдете наиболее читаемым:
# Concatenating plus signs with plus signs is atrociously confusing.
# Recommended only if you want to drive your future self insane.
mogrify_arg = w + 'x' + h + '+' + x + '+' + y
# Readable but inefficient
mogrify_arg = [ w, 'x', h, '+', x, '+', y ].join('')
# Questionable readability
mogrify_arg = "#{w}x#{h}+#{x}+#{y}"
# Slick, performant, but potentially risky: `<<` modifies the receiving object in place
# `w` is actually changing here to "WxH+X+Y"...
mogrify_arg = w << 'x' << h << '+' << x << '+' << y
# A lovely, self-documenting version
size = w << 'x' << h
offset = '+' << x '+' << y
mogrify_arg = "#{size}#{offset}"
Вот полный пример:
def crop
if model.crop_x.present?
resize_to_limit(700, 700)
manipulate! do |img|
x = model.crop_x
y = model.crop_y
w = model.crop_w
h = model.crop_h
size = w << 'x' << h
offset = '+' << x << '+' << y
img.crop("#{size}#{offset}") # Doesn't return an image...
img # ...so you'll need to call it yourself
end
end
end
Ответ 3
Мне удалось заставить это работать, добавив параметры X и Y в команду обрезки, как указано @mikhail-nikalyukin
def crop
manipulate! do |img|
img.crop "750x600+0+0"
img.strip
img = yield(img) if block_given?
img
end
end