17

我花了很长时间才能让它工作,现在仍然如此。我会深入到它的核心。我正在按照 Ryan Bates 教程使用 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,找不到有爆炸的crop方法,所以我没有尝试过,然后错误变成了这个:

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

无论如何,有些东西对我来说没有多大意义,任何帮助将不胜感激!谢谢阅读!

4

3 回答 3

48

简而言之:

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_COMMANDSImageMagickmogrify文档中指定的许多以破折号为前缀的选项匹配的列表来动态生成方法。这些方法中的每一个都直接将它们的参数传递给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论点。您会注意到所有这些参数都是字符串,因此您可以使用or代替。它不是很像 Ruby,但这就是 MiniMagick 如此轻量级的部分原因。crop(100,200)crop('100x200')crop('100%)

有了这些知识,我们就可以推断出如何使用 MiniMagick 进行裁剪。可以将几何图形mogrify -crop作为字符串widthx height++,所以我们只需要构建一个类似的字符串。xoffsetyoffset

给定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
于 2012-04-01T02:25:51.000 回答
15

有同样的问题,我的解决方案是这种方法

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

只需针对您的情况修改我的方法即可。
关键是将变量传递给crop方法的格式,希望对您有所帮助。

于 2011-12-07T16:56:06.637 回答
2

如@mikhail-nikalyukin 所示,我可以通过将 X 和 Y 参数添加到裁剪命令中来使其工作

def crop
  manipulate! do |img|
    img.crop "750x600+0+0"
    img.strip

    img = yield(img) if block_given?
    img
  end
end
于 2012-01-23T22:34:01.700 回答