Подтвердить что ты не робот

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

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

4b9b3361

Ответ 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