Undefined Method crop! Using Carrierwave with MiniMagick on rails 3.1.3

戏子无情 提交于 2019-11-30 03:19:19

Had the same problems, my solution was this method

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

Just modify my method for your case.
The key is in which format pass variables to crop method, hope this helps you.

In short:

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

Here's a better explanation of why this happened as opposed to a cut/paste style solution.

RMagick and MiniMagick aren't interchangeable. RMagick has a very Ruby-like DSL and as such employs methods that take multiple arguments:

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 instead dynamically generates methods by iterating through a list of MOGRIFY_COMMANDS that match up with numerous dash-prefixed options specified in ImageMagick's mogrify documentation. Each of those methods pass their arguments directly to mogrify and none return an image object:

minimagick_image.crop('100x200') # Translates to `mogrify -crop 100x200 image.ext`
minimagick_image.polaroid('12')  # Executes `mogrify -polaroid 12 image.ext`

In kind, RMagick has crop! and MiniMagick doesn't.

According to the ImageMagick docs, mogrify -crop takes an argument geometry. The geometry argument is explained here. You'll notice that all of those arguments are strings, so instead of crop(100,200) you would use crop('100x200') or crop('100%). It's not very Ruby-like, but that's part of what makes MiniMagick so lightweight.

With that knowledge, we can deduce how to crop with MiniMagick. mogrify -crop can take a geometry as a string widthxheight+xoffset+yoffset, so we just need to build a similar string.

Given w,h,x, and y you could use whichever of the following you find most readable:

# 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}"

Here's a complete example:

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

I was able to get this to work by adding the X and Y parameters to the crop command as indicated by @mikhail-nikalyukin

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

    img = yield(img) if block_given?
    img
  end
end
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!