Hey, Great tutorial, but I'm running into an issue. Firstly RMagick didn't work for me. For some reason, every time without fail, it brought down my rails server when the method that does resizing was called. I found a bunch of people with the same issue, but none of the fixes, which generally included reinstalling both RMagick and Imagemagick, worked for me. The solution that got me a step further was switching to MiniMagick. Now images resize and are saved, but the next step is moving on to the actual cropping, this is now where I'm up against a new issue.
This was taken from my pdf_uploader.rb (despite the name PDF I'm currently only using jpegs just to avoid any potential difficulties there). This is my crop method, which looks pretty similar to the one in the tutorial. Someone on stack overflow also had an issue with the way your crop method worked and suggested I try something more like this:
ruby
defcropif model.crop_x.present?
img = MiniMagick::Image.open(model.pdf.path)
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)
img
endend
This doesn't work for me either even though I'm trying to explicitly edit the file. The reason has everything to do with "model.pdf.path" which I was told should do the trick... When I inspect "model.pdf.path" it prints out a tmp directory, rather than the path to where the file actually lives... This results in a big fat show stopping error, and no crop.
Errno::ENOENT in PiecesController#update
No such file or directory - /var/folders/dF/dFNM2+Y7FVScn4+OxVHKOU+++TI/-Tmp-/mini_magick20111208-45803-1027dqf.png
Rails.root: /Users/cory/Documents/Projects/TickiWiki
Application Trace | Framework Trace | Full Trace
app/uploaders/pdf_uploader.rb:78:in crop'
app/models/piece.rb:27:incrop_pdf'
app/controllers/pieces_controller.rb:107:in block in update'
app/controllers/pieces_controller.rb:106:inupdate'
Request
This leads me to a few questions:
1. Why, what did I do to deserve this?
2. How can I get the correct value?
3. Will the correct value even make it work?
4. Is there a better way to do this?
5. Why can't I code as quickly and with as few mistakes as Ryan Bates in a RailsCast?
Anyway, this n00b would love any suggestions anyone has. Thanks!
An update! I got very very frustrated, and tried everything over again on a new machine. I went back to Rmagick and it worked this time. The key thing seemed to be with my setup. I'm not sure specifically what, but it had something to do with Ghostscript and/or MacPorts. Removing macports, reinstalling imagemagick, reinstalling rmagick, reinstalling ghostcript finally did it for me!
Thank you Ryan for this episode. Has anyone used jcrop and carrierwave to mimic how Facbook's does thumbnail . That would be a cool episode maybe a revision of this cast. ;)
Do you think you could explain how this might work with nested objects. My images belong to a subsidiary object and I can't figure out how to crop them.
Ned — My models are set up in a nested fashion also, (Profile has_one Avatar) since I'm using a polymorphic "Photo" object in a couple different ways around the site.
Anyway, I'm running into an interesting issue where I'm successfully re-generating the new versions, but my Profile isn't picking up the updated Thumbnail — it's definitely saved on S3, so the actual cropping process is working very well.
Hrmmm, am I saving it incorrectly? Anyone run into something similar or have an idea?
Basically, you need to re-run save on the parent object after update_attributes has had a chance to do it's thing, such that the object stores the newly-generated filename — assuming you're using digest-esque filenames.
So I turned off the after_update directive and run the cropper manually in the controller, so I can save it easily:
ruby
defcrop
avatar = current_profile.avatar
avatar.crop_x = params[:photo]["crop_x"]
avatar.crop_y = params[:photo]["crop_y"]
avatar.crop_h = params[:photo]["crop_h"]
avatar.crop_w = params[:photo]["crop_w"]
# Must re-save after update to ensure model refers to new version on S3
avatar.crop_avatar
avatar.save!
end
I need some advice from you. Your example works great if all versions of the uploaded image have equal widths and heights (i.e. width == height). In many cases, photos have different width and height, e.g. 640x480. And sometimes it needs to be rotated, so that width is 480px and height is 640px. If I want to have a "normal" version with dimensions 640x480 if picture is landscape and 480x640 if it is a portrait; with another "thumb" version 180x135 landscape and 135x180 portrait. Could you give some advice on how to achieve that?
Have you got any solution for cropping landscape and portrait images ?. I am working on cropping different sizes of images. It is not working for me. Could you help me please. I was struck up with from 2 days.
I get the following error when trying to implement this tutorial. I wanted to get this work and then alter to my needs so I have not made any modifications to the original code. Any one have any suggestions? I would really appreciate the help. Thanks!
Also not sure if this matters but my users system is set up with Devise, I handle roles and permissions with CanCan and I followed the #253 tutorial to get the basic carrierwave uploading working. All of course thanks to Ryan - railscasts is too good! Thanks.
So I figured out most of my errors. I wasn't setting the all the values I needed to.
I set
att_accesible for crop_x , crop_y, crop_w, crop_h
didnt set
attr_accessor for all these same values
I guess I thought these were the same as rails seems to understand connections like user and users - dumb I know, I'm new to ruby and rails but railscasts has been teaching my quite a bit.
My only remaining issue is with the preview function which I have also asked in a stackoverflow question in great detail. But basically the image appears with a second image inside the crop window that stretches and skews as the resizing handles are moved. Any help would be greatly appreciated as this issue has haunted me for about a week now. Thanks!
Alright so I have finally solved this issue with help from stackoverflow. The issue is a conflict when combining jcrop with twitter bootstrap. The solution to my question is linked here. Its embarrassingly simple, apparently TBS sets image max width property to 100% and you simply override with with a style you create to remove this property. I was so focused on jcrop itself that I did ponder anything else causing the problem. Lesson learned, but I figured I would post for anyone elses benefit.
I was unable to get the crop working using RMagick, so I investigated what would be the equivalent using MiniMagick.
Based on this discussion on stackoverflow, I was able to come up with this working solution. This method would be saved in the User model and there is no longer a crop method within the AvatarUploader CarrierWave object.
There is one minor issue with this code, which is that the large version of the image becomes the master copy of that image. If you do not care about keeping the high resolution version of an uploaded image, this issue will not matter to you.
For those of you having problems with mini_magic, this worked for me:
ruby
defcropif model.crop_x.present?
resize_to_limit(600, 600)
manipulate! do |img|
x = model.crop_x
y = model.crop_y
w = model.crop_w
h = model.crop_h
img.crop "#{w}x#{h}+#{x}+#{y}"
img
endendend
After I setting enviorment from Development to Production, the jCrop seems not working correctly. It maybe the problem caused by precompiling and compressing. Any suggestions? Thx!
When you add resize_to_limit(600, 600) to the crop method to solve the problem that the x,y,width,height are relative to the :large image, it seems like you potentially lose some resolution.
It certainly makes sense to scale the image down to something reasonable before displaying it in the cropping UI, but if you're using this to generate a new image that's bigger than a thumbnail, it would be really nice to be cropping from the big image, not the 600x600 one. Seems like it would be better to scale the x, y, width and height values to work with the original image rather than scale the image.
What would be the most efficient way to get the dimensions of the original image in the crop method so that one could scale the values instead of scaling the image?
You can get the dimension of the img using
img.columns, img.rows
I ended up doing something like this to prevent blurring of the cropped image:
ruby
defcropif model.crop_x.present?
#resize_to_limit(300, 3000)
manipulate! do |img|
converted_h = 300.0*img.rows/img.columns
x = (model.crop_x.to_i/300.0*img.columns).to_i
y = (model.crop_y.to_i/converted_h*img.rows).to_i
w = (model.crop_w.to_i/300.0*img.columns).to_i
h = (model.crop_h.to_i/converted_h*img.rows).to_i
#img.crop("#{w}x#{h}+#{x}+#{y}")
img.crop!(x, y, w, h)
img
endendend
I couldn't get cropping to work with mini magick, but after trying some different things I still managed. Seems like someone has switched around on (X, Y) and (W, H).
This should work:
def crop
manipulate! do |img|
img.crop "#{model.width}x#{model.height}+#{model.x}+#{model.y}"
img
end
end
When I call recreate_versions! method a new file is generated and older files are kept on uploads directory. What's the best way to remove older files after recreating versions?
Using virtual attributes like this means the crop location information is lost after the initial crop. This means that a call to 'recreate versions' later will lose all the crop information.
If this is important to you, use database fields for the crop information instead.
(rails >= 3.1.1) When precompiling assets, shouldn't rails include both hashed and non-hashed version of the images?
I prefer Dragonfly, but I really like how you approached this. Great timing too!
Hi Ryan!
Great Episode!
Is there any possibility you could make an episode on jCrop with Paperclip?
Having issues with minimagick. Instead of
I had to do:
img.crop "#{model.crop_x}x#{model.crop_y}+#{model.crop_w}+#{model.crop_h}" img
But the thumb version of the image is not displaying properly.
Hey, Great tutorial, but I'm running into an issue. Firstly RMagick didn't work for me. For some reason, every time without fail, it brought down my rails server when the method that does resizing was called. I found a bunch of people with the same issue, but none of the fixes, which generally included reinstalling both RMagick and Imagemagick, worked for me. The solution that got me a step further was switching to MiniMagick. Now images resize and are saved, but the next step is moving on to the actual cropping, this is now where I'm up against a new issue.
This was taken from my pdf_uploader.rb (despite the name PDF I'm currently only using jpegs just to avoid any potential difficulties there). This is my crop method, which looks pretty similar to the one in the tutorial. Someone on stack overflow also had an issue with the way your crop method worked and suggested I try something more like this:
This doesn't work for me either even though I'm trying to explicitly edit the file. The reason has everything to do with "model.pdf.path" which I was told should do the trick... When I inspect "model.pdf.path" it prints out a tmp directory, rather than the path to where the file actually lives... This results in a big fat show stopping error, and no crop.
This leads me to a few questions:
1. Why, what did I do to deserve this?
2. How can I get the correct value?
3. Will the correct value even make it work?
4. Is there a better way to do this?
5. Why can't I code as quickly and with as few mistakes as Ryan Bates in a RailsCast?
Anyway, this n00b would love any suggestions anyone has. Thanks!
An update! I got very very frustrated, and tried everything over again on a new machine. I went back to Rmagick and it worked this time. The key thing seemed to be with my setup. I'm not sure specifically what, but it had something to do with Ghostscript and/or MacPorts. Removing macports, reinstalling imagemagick, reinstalling rmagick, reinstalling ghostcript finally did it for me!
Thanks!
Thank you Ryan for this episode. Has anyone used jcrop and carrierwave to mimic how Facbook's does thumbnail . That would be a cool episode maybe a revision of this cast. ;)
Good episode!
Do you think you could explain how this might work with nested objects. My images belong to a subsidiary object and I can't figure out how to crop them.
Can you help?
Ned — My models are set up in a nested fashion also, (Profile has_one Avatar) since I'm using a polymorphic "Photo" object in a couple different ways around the site.
Anyway, I'm running into an interesting issue where I'm successfully re-generating the new versions, but my Profile isn't picking up the updated Thumbnail — it's definitely saved on S3, so the actual cropping process is working very well.
Hrmmm, am I saving it incorrectly? Anyone run into something similar or have an idea?
Solved.
Basically, you need to re-run save on the parent object after update_attributes has had a chance to do it's thing, such that the object stores the newly-generated filename — assuming you're using digest-esque filenames.
So I turned off the after_update directive and run the cropper manually in the controller, so I can save it easily:
great episode as always. Thank you!
I need some advice from you. Your example works great if all versions of the uploaded image have equal widths and heights (i.e. width == height). In many cases, photos have different width and height, e.g. 640x480. And sometimes it needs to be rotated, so that width is 480px and height is 640px. If I want to have a "normal" version with dimensions 640x480 if picture is landscape and 480x640 if it is a portrait; with another "thumb" version 180x135 landscape and 135x180 portrait. Could you give some advice on how to achieve that?
Hello Hau,
Have you got any solution for cropping landscape and portrait images ?. I am working on cropping different sizes of images. It is not working for me. Could you help me please. I was struck up with from 2 days.
Can't you do an if statement? If your width if larger than height, X, else, Y. Shouldn't be hard.....
I get the following error when trying to implement this tutorial. I wanted to get this work and then alter to my needs so I have not made any modifications to the original code. Any one have any suggestions? I would really appreciate the help. Thanks!
undefined method `crop_x' for #User:0x007ff7594cb2f8
Rails.root: /Users/thomasbush/Rails/college
Application Trace | Framework Trace | Full Trace
app/uploaders/avatar_uploader.rb:47:in
crop'
update'app/controllers/users_controller.rb:43:in
Also not sure if this matters but my users system is set up with Devise, I handle roles and permissions with CanCan and I followed the #253 tutorial to get the basic carrierwave uploading working. All of course thanks to Ryan - railscasts is too good! Thanks.
So I figured out most of my errors. I wasn't setting the all the values I needed to.
I guess I thought these were the same as rails seems to understand connections like user and users - dumb I know, I'm new to ruby and rails but railscasts has been teaching my quite a bit.
My only remaining issue is with the preview function which I have also asked in a stackoverflow question in great detail. But basically the image appears with a second image inside the crop window that stretches and skews as the resizing handles are moved. Any help would be greatly appreciated as this issue has haunted me for about a week now. Thanks!
Alright so I have finally solved this issue with help from stackoverflow. The issue is a conflict when combining jcrop with twitter bootstrap. The solution to my question is linked here. Its embarrassingly simple, apparently TBS sets image max width property to 100% and you simply override with with a style you create to remove this property. I was so focused on jcrop itself that I did ponder anything else causing the problem. Lesson learned, but I figured I would post for anyone elses benefit.
I was unable to get the crop working using RMagick, so I investigated what would be the equivalent using MiniMagick.
Based on this discussion on stackoverflow, I was able to come up with this working solution. This method would be saved in the User model and there is no longer a crop method within the AvatarUploader CarrierWave object.
There is one minor issue with this code, which is that the large version of the image becomes the master copy of that image. If you do not care about keeping the high resolution version of an uploaded image, this issue will not matter to you.
If you use a random filename for your photos, recreate_versions! won't save them to the model properly. See this: https://github.com/jnicklas/carrierwave/wiki/How-to%3A-Create-random-and-unique-filenames-for-all-versioned-files (specifically search for "recreate")
For those of you having problems with mini_magic, this worked for me:
A year late, but thanks!
When I selecting the are to crop, the selected area always be zoomed a bit. How can I fix this? I don't want the zoom effect.
I am running into the same issue and can't seem to figure out how to fix it, have you been able to figure it out yet?
render :crop brings me up to a BLANK PAGE,
“406 not acceptable” error
I have to wrap this in a format.html{}
Not sure why... but it works
Because if you notice on the outside of the if statment, you have the respond_to block, I ran into the same issue at first as well.
So if you don't wrap it in format.html { }, the action won't know what to do.
Thank you!
Hi there,
can someone offer this tutorial as a "non-square-thumbnail" example?
I ran into render issues when I try to change the parameters to a "rectangle" in the js.coffee file
After I setting enviorment from Development to Production, the jCrop seems not working correctly. It maybe the problem caused by precompiling and compressing. Any suggestions? Thx!
I seperate crop-related.css from application.css, then it works.
I am also running into the same problem - cropping works in Development but not in Production.
In Production, the resizable cropping box does not show up at all. I am running Rails 3.2.8.
@shallwelin do you mind telling me what you did exactly? did you have the same problem I do?
Thanks!
Hello,
I am fresher with ROR so i am trying to crop a picture but i get this error in cropping how to solve this help me?
Can't mass-assign protected attributes: crop_x, crop_y, crop_w, crop_h
attr_accessor :crop_x, :crop_y, :crop_w, :crop_h
attr_accessible :crop_x, :crop_y, :crop_w, :crop_h
When you add resize_to_limit(600, 600) to the crop method to solve the problem that the x,y,width,height are relative to the :large image, it seems like you potentially lose some resolution.
It certainly makes sense to scale the image down to something reasonable before displaying it in the cropping UI, but if you're using this to generate a new image that's bigger than a thumbnail, it would be really nice to be cropping from the big image, not the 600x600 one. Seems like it would be better to scale the x, y, width and height values to work with the original image rather than scale the image.
What would be the most efficient way to get the dimensions of the original image in the crop method so that one could scale the values instead of scaling the image?
You can get the dimension of the img using
img.columns, img.rows
I ended up doing something like this to prevent blurring of the cropped image:
**Noticed this was from 2 years ago...
Anyone have the problem of it occasionally not cropping the image after the upload?
Occasionally one slips by.
All the necessary scripts (jquery, jcrop, avatar.js) are loaded but I'm getting a:
Uncaught TypeError: Object [object Object] has no method 'Jcrop'
I also have bootstrap.js loaded. I cannot figure out what's going on. Does anyone have any idea? Posted my question here, too:
http://stackoverflow.com/questions/14132170/uncaught-typeerror-object-object-object-has-no-method-jcrop
thanks!
Has anyone got jCrop working with ActiveAdmin? If so, how would you pass the instance variable to the render template?
It looks like CarrierWave isn't passing the correct instance to the uploader in recreate_versions. I have opened a ticket here:
https://github.com/jnicklas/carrierwave/issues/1015
Until this is fixed, this method Ryan uses here is currently broken.
Seems to be working just fine for me.
I couldn't get cropping to work with mini magick, but after trying some different things I still managed. Seems like someone has switched around on (X, Y) and (W, H).
This should work:
When I call recreate_versions! method a new file is generated and older files are kept on uploads directory. What's the best way to remove older files after recreating versions?
It seems like the Crop coordinates values are not being set.
This is what I get in my params hash after submitting:
"profile_photo"=>{"crop_x"=>"", "crop_y"=>"", "crop_w"=>"", "crop_h"=>""}, "commit"=>"Crop Photo", "user_id"=>"2", "profile_id"=>"2", "id"=>"7"}
Notice how all the crop_* are empty? What could be the reason?
I have both
attr_accessor :crop_x, :crop_y, :crop_w, :crop_h
attr_accessible :crop_x, :crop_y, :crop_w, :crop_h
set.
There's an updated gem for Rails 4 here.
Has anybody managed to crop images while using porstgresql as a database?
Using virtual attributes like this means the crop location information is lost after the initial crop. This means that a call to 'recreate versions' later will lose all the crop information.
If this is important to you, use database fields for the crop information instead.
Hi Ryan, thanks for the great tutorial. I have successfully implemented this, while asynchronously uploading and displaying the image, than cropping.
It works great when the image dimensions are equal to or less than the crop area. But it seems to offset the crop for larger images.