Crop de méthode non définie! Utilisation de porte-avions avec minimagick sur les rails 3.1.3
-
29-10-2019 - |
Question
J'avais un sacré temps pour que cela fonctionne, et je le suis toujours. Je vais en arriver au cœur. Je suis le tutoriel Ryan Bates pour faire du travail de recadrage en utilisant JCROP et Carrierwave. J'ai choisi d'utiliser Minimagick car même après avoir réinstallé ImageMagick et Rmagick sur ma machine, je reçois une erreur qui tue le serveur Rails sur ma machine locale. Quoi qu'il en soit, le passage à Minimagick a corrigé cela pour moi. Donc, tout est vraiment bien jusqu'à ce point. J'ai des images de différentes tailles produites et elles sont téléchargées avec succès. Mais une fois que j'essaie de recadrer, je reçois cette erreur:
undefined method `crop!' for #<MiniMagick::CommandBuilder:0x000001052e4608>
Cela déroutait le diable de moi parce que j'utilise à peu près exactement le même code 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
Quoi qu'il en soit, c'est cette méthode de récolte qui échoue. Alors je me suis dit, c'est une commande ImageMagick ... alors j'ai regardé le Doco ImageMagick, et je n'ai pas trouvé la méthode de recadrage avec le Bang, alors je l'ai essayé sans, puis l'erreur se tourne à ceci:
No such file or directory - /var/folders/dF/dFNM2+Y7FVScn4+OxVHKOU+++TI/-Tmp-/mini_magick20111207-34409-1tnaa07.jpg
Quoi qu'il en soit, quelque chose n'a pas beaucoup de sens pour moi, toute aide serait appréciée! Merci d'avoir lu!
La solution
Avait les mêmes problèmes, ma solution était cette méthode
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
Modifiez simplement ma méthode pour votre cas.
La clé est dans quel format passe les variables à la méthode de recadrage, j'espère que cela vous aide.
Autres conseils
Bref:
img.crop("#{size}#{offset}") # Doesn't return an image...
img # ...so you'll need to call it yourself
Voici une meilleure explication de Pourquoi Cela s'est produit par opposition à une solution de style coupe / pâte.
Rmagick et Minimagick ne sont pas interchangeables. RMAGICK a un DSL très rubis et, en tant que tel, utilise des méthodes qui prennent plusieurs 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 génère plutôt dynamiquement des méthodes par itérer à travers une liste de MOGRIFY_COMMANDS
qui correspondent à de nombreuses options préfixées par tableau de bord spécifiées dans ImageMagick's mogrify
Documentation. Chacune de ces méthodes transmet ses arguments directement à mogrify
et aucun ne renvoie un objet d'image:
minimagick_image.crop('100x200') # Translates to `mogrify -crop 100x200 image.ext`
minimagick_image.polaroid('12') # Executes `mogrify -polaroid 12 image.ext`
En nature, Rmagick a crop!
Et Minimagick ne le fait pas.
Selon les documents ImageMagick, mogrify -crop
prend un argument geometry
. La geometry
L'argument est expliqué ici. Tu remarques que tout de ces arguments sont des chaînes, donc au lieu de crop(100,200)
vous utiliseriez crop('100x200')
ou crop('100%)
. Ce n'est pas très semblable à un rubis, mais cela fait partie de ce qui rend Minimagick si léger.
Avec ces connaissances, nous pouvons déduire comment recadrer avec Minimagick. mogrify -crop
peut prendre une géométrie comme une chaîne width
Xheight
+xoffset
+yoffset
, nous avons donc juste besoin de construire une chaîne similaire.
Donné w
,h
,x
, et y
Vous pouvez utiliser quel que soit le suivant, vous trouvez le plus lisible:
# 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}"
Voici un exemple complet:
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
J'ai pu faire fonctionner cela en ajoutant les paramètres X et Y à la commande CROP comme indiqué par @ mikhail-nikalyukin
def crop
manipulate! do |img|
img.crop "750x600+0+0"
img.strip
img = yield(img) if block_given?
img
end
end