【问题标题】:Undefined Method crop! Using Carrierwave with MiniMagick on rails 3.1.3未定义的方法裁剪!在 Rails 3.1.3 上使用带有 MiniMagick 的 Carrierwave
【发布时间】:2011-12-07 16:38:57
【问题描述】:

我花了很长时间才能让它工作,现在仍然如此。我会深入到它的核心。我正在按照 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,没找到有bang的crop方法,于是不带试了一下,然后报错就变成了这样:

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

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

【问题讨论】:

  • 更新!我非常非常沮丧,并在一台新机器上重新尝试了一切。我回到了 Rmagick,这次它奏效了。关键似乎与我的设置有关。我不确定具体是什么,但它与 Ghostscript 和/或 MacPorts 有关。删除 macports,重新安装 imagemagick,重新安装 rmagick,重新安装 ghostcript 终于为我做了!谢谢!

标签: ruby-on-rails carrierwave minimagick


【解决方案1】:

简而言之:

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 改为通过iterating through a list of MOGRIFY_COMMANDS 动态生成方法,这些方法与ImageMagick's mogrify documentation 中指定的众多以破折号为前缀的选项相匹配。这些方法中的每一个都将它们的参数直接传递给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 接受一个参数 geometrygeometry 参数解释为 here。您会注意到所有这些参数都是字符串,因此您可以使用crop('100x200')crop('100%) 而不是crop(100,200)。它不是很像 Ruby,但这就是 MiniMagick 如此轻量级的部分原因。

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

鉴于whxy,您可以使用以下任何一个您认为最易读的:

# 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

【讨论】:

  • @faraz 很好地解释了我在查看 MiniMagick 示例时正在考虑的 rMagick 示例时预期会发生的事情。我唯一遇到的问题是生成的大小和偏移量无法从 Rails 将 String 转换为 Integer 错误。
【解决方案2】:

遇到同样的问题,我的解决方法是这个方法

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方法,希望对您有所帮助。

【讨论】:

  • 这看起来很有希望,我刚刚尝试更新我的裁剪方法以包含此图像 = MiniMagick::Image.open(model.pdf_url) 但它向我吐了一个错误。关于我应该使用的密钥有什么建议吗?我得到的错误是没有这样的文件或目录 - /uploads/tmp/20111207-1235-34409-8280/backsideart_stevie.jpg
  • 好吧,我想这是 minimagick [github.com/probablycorey/mini_magick/issues/54] 的问题。我以前有它,但是当我像上面那样重写裁剪方法时它就消失了。奇怪的是你还遇到它。
  • 只是添加...这是我从 Mikhail 的代码中所做的。显而易见的重要事情(正如他正确指出的那样)是(1)用crop替换crop!,并在manipulate!块的末尾返回图像,否则你会得到写错误。ruby def crop if model.crop_x.present? resize_to_limit(600, 600) 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("#{w}x#{h}+#{x}+#{y}") img end end end
【解决方案3】:

如@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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多