Неопределенный метод обрезки!Использование Carrierwave с MiniMagick на рельсах 3.1.3 - PullRequest
17 голосов
/ 07 декабря 2011

У меня было чертовски много времени заставить это работать, и до сих пор. Я доберусь до сути этого. Я следую учебнику Райана Бейтса, чтобы сделать кадрирование с использованием Jcrop и Carrierwave. Я решил использовать MiniMagick, потому что даже после переустановки ImageMagick и RMagick на моей машине я получаю ошибку, которая убивает сервер rails на моей локальной машине. В любом случае переключение на MiniMagick исправило это для меня. Так что до этого момента все действительно хорошо. У меня есть изображения разных размеров, и они успешно загружены. Но как только я пытаюсь обрезать, я получаю эту ошибку:

undefined method `crop!' for #<MiniMagick::CommandBuilder:0x000001052e4608>

Это сбивает меня с толку, потому что я использую в точности тот же код, что и Бейтс:

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, и я не смог найти метод кадрирования с ударом, поэтому я попробовал его без, и тогда ошибка превращается в следующее:

No such file or directory - /var/folders/dF/dFNM2+Y7FVScn4+OxVHKOU+++TI/-Tmp-/mini_magick20111207-34409-1tnaa07.jpg

Во всяком случае, что-то не имеет смысла для меня, любая помощь будет оценена! Спасибо за чтение!

Ответы [ 3 ]

47 голосов
/ 01 апреля 2012

Вкратце:

img.crop("#{size}#{offset}") # Doesn't return an image...
img # ...so you'll need to call it yourself

Вот лучшее объяснение почему это произошло в отличие от решения в стиле вырезки / вставки.

RMagick и MiniMagick aren 'т взаимозаменяемы.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, которые соответствуютс многочисленными опциями с префиксом тире, указанными в документации mogrify ImageMagick .Каждый из этих методов передает свои аргументы непосредственно 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
15 голосов
/ 07 декабря 2011

У меня были те же проблемы, мое решение было таким методом

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 голосов
/ 24 января 2012

Мне удалось заставить это работать, добавив параметры 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
...