¡Método indefinado Crop! Uso de CarrierWave con minimagick en Rails 3.1.3
-
29-10-2019 - |
Pregunta
Estaba pasando mucho tiempo haciendo que esto funcione, y todavía lo estoy. Llegaré al corazón. Estoy siguiendo el tutorial de Ryan Bates para hacer que el cultivo funcione usando JCROP y CarrierWave. He optado por usar Minimagick porque incluso después de reinstalar ImageMagick y Rmagick en mi máquina recibo un error que mata el servidor Rails en mi máquina local. De todos modos, cambiar a Minimagick lo solucionó. Entonces todo es realmente agradable hasta este punto. Tengo imágenes de diferentes tamaños que se están produciendo, y se están cargando con éxito. Pero una vez que intento recortar, recibo este error:
undefined method `crop!' for #<MiniMagick::CommandBuilder:0x000001052e4608>
Esto me confunde porque estoy usando prácticamente exactamente el mismo código que 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
De todos modos, es ese método de cultivo el que está fallando. Así que pensé para mí mismo, ese es un comando ImageMagick ... así que miré el Doco ImageMagick, y no pude encontrar el método de cultivo con la explosión, así que lo probé sin y luego el error se convierte en esto:
No such file or directory - /var/folders/dF/dFNM2+Y7FVScn4+OxVHKOU+++TI/-Tmp-/mini_magick20111207-34409-1tnaa07.jpg
De todos modos, algo no tiene mucho sentido para mí, ¡cualquier ayuda sería apreciada! ¡Gracias por leer!
Solución
Tenía los mismos problemas, mi solución era este método
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
Simplemente modifique mi método para su caso.
La clave es en la que el formato pasa las variables al método de cultivo, espero que esto lo ayude.
Otros consejos
En breve:
img.crop("#{size}#{offset}") # Doesn't return an image...
img # ...so you'll need to call it yourself
Aquí hay una mejor explicación de por qué Esto sucedió en lugar de una solución de estilo de corte/pasta.
Rmagick y Minimagick no son intercambiables. RMAGICK tiene un DSL muy rubí y, como tal, emplea métodos que toman múltiples argumentos:
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, en su lugar, genera dinámicamente métodos por iterando a través de una lista de MOGRIFY_COMMANDS
que coinciden con numerosas opciones prefijadas en el tablero especificadas en ImageMagick mogrify
documentación. Cada uno de esos métodos pasa sus argumentos directamente a mogrify
y ninguno devuelve un objeto de imagen:
minimagick_image.crop('100x200') # Translates to `mogrify -crop 100x200 image.ext`
minimagick_image.polaroid('12') # Executes `mogrify -polaroid 12 image.ext`
En especie, Rmagick tiene crop!
Y Minimagick no lo hace.
Según los documentos de ImageMagick, mogrify -crop
Toma una discusión geometry
. los geometry
Se explica el argumento aquí. Notarás que todos de esos argumentos son cadenas, por lo que en lugar de crop(100,200)
USTED USARÍA crop('100x200')
o crop('100%)
. No es muy parecido a un rubí, pero eso es parte de lo que hace que Minimagick sea tan liviano.
Con ese conocimiento, podemos deducir cómo recortar con minimismo. mogrify -crop
puede tomar una geometría como cadena width
Xheight
+xoffset
+yoffset
, por lo que solo necesitamos construir una cadena similar.
Dado w
,h
,x
, y y
Puede usar el siguiente de lo siguiente que encuentre más legible:
# 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}"
Aquí hay un ejemplo completo:
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
Pude hacer que esto funcionara agregando los parámetros X e Y al comando de cultivo como lo indica @Mikhail-Nikalyukin
def crop
manipulate! do |img|
img.crop "750x600+0+0"
img.strip
img = yield(img) if block_given?
img
end
end