Wednesday, December 28, 2011

Image Cropping With Rails 3

I was looking at some options for the Image Cropping functionality with Rails 3 and got many great solutions on the net. This Rails Cast is the best place to start if you have the images stored as local. If you have it as s3 storage there are some changes you need to make.

My main haml file has these contents -

#cropperpopup.lpopup.x 
  %a.ccloser 
  %p.large Image Cropper 
  .cropper 
    = image_tag @user.avatar.url(:medium), :id => :cropbox 
  = form_for @user, :html => {:class => 'edit_user_two'} do |f| 
    - for attrbt in [:crop_x, :crop_y, :crop_w, :crop_h] 
      = f.text_field attrbt, :id => attrbt, :class => :coordinate 
    = f.submit 'Crop'

When on calls the popup, one should call the code for the Jcrop method

$('img#cropbox').Jcrop({ 
  onChange: update_crop, 
  onSelect: update_crop, 
  setSelect: [0, 0, 168, 202], 
  aspectRatio: (168/202) });

My aspect ratio setting is with respect to the configurations I did for the has_attached_file :avatar.

The thing you will have to do specifically for s3 is in the avatar_geometry method.


def cropping? 
  !crop_x.blank? && !crop_y.blank? && !crop_w.blank? && !crop_h.blank? 
end 

def avatar_geometry(style = :medium) 
  @geometry ||= {} 
  path = (avatar.options[:storage]==:s3) ? avatar.url(style).split(' ').join('%20') : avatar.path(style) 
  @geometry[style] ||= Paperclip::Geometry.from_file(path) 
end

Inside the model.

I'm having issues with the cropper processor and its not cropping fine. Will have to fix that. This is the Cropper

module Paperclip 
  class Cropper < Thumbnail 
    def transformation_command 
     if crop_command 
       r = super 
       if r.class == Array 
         r = r.join(' ') 
       end 
       crop_command + r.sub(/ -crop \S+/, '').sub(/-resize \S+/, '') 
     else 
       super 
     end 
   end 
   def crop_command 
     target = @attachment.instance 
     if target.cropping? 
       "-resize \"168x202\" -crop #{target.crop_w}x#{target.crop_h}+#{target.crop_x}+#{target.crop_y} " 
     end 
    end 
  end 
end