{"id":22558623,"url":"https://github.com/jschwindt/rjcrop","last_synced_at":"2025-04-10T06:33:31.548Z","repository":{"id":499881,"uuid":"126864","full_name":"jschwindt/rjcrop","owner":"jschwindt","description":"Sample Rails app for image cropping using Paperclip and Jcrop","archived":false,"fork":false,"pushed_at":"2010-09-30T13:14:23.000Z","size":296,"stargazers_count":166,"open_issues_count":1,"forks_count":10,"subscribers_count":7,"default_branch":"master","last_synced_at":"2024-04-08T15:57:38.741Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://schwindt.org/","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jschwindt.png","metadata":{"files":{"readme":"README.rdoc","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2009-02-11T19:29:37.000Z","updated_at":"2024-02-29T17:44:41.000Z","dependencies_parsed_at":"2022-07-07T14:51:19.693Z","dependency_job_id":null,"html_url":"https://github.com/jschwindt/rjcrop","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jschwindt%2Frjcrop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jschwindt%2Frjcrop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jschwindt%2Frjcrop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jschwindt%2Frjcrop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jschwindt","download_url":"https://codeload.github.com/jschwindt/rjcrop/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228651824,"owners_count":17951897,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-07T20:16:21.320Z","updated_at":"2024-12-07T20:16:22.381Z","avatar_url":"https://github.com/jschwindt.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"=RJCrop\n\nThis is a sample application that shows how to implement image cropping using \nthe popular Paperclip Rails plugin and the Jcrop jQuery plugin for selecting \nthe cropping area.\n\n*Paperclip* project page: http://github.com/thoughtbot/paperclip/tree/master \n*Jcrop* home page: http://deepliquid.com/content/Jcrop.html\n\nMost of the inspiration for this application was taken from this thread: \nhttp://groups.google.com/group/paperclip-plugin/browse_thread/thread/817266ea5b37580c\nand especially this helpful piece of code: http://groups.google.com/group/paperclip-plugin/msg/5b6dd7ade3ba6b87?hl=en\n\n==Downloading and testing the application\n\n git clone git://github.com/jschwindt/rjcrop.git\n cd rjcrop\n rake db:migrate\n git submodule init\n git submodule update\n ./script/server\n\nAfter that you can point your browser to http://localhost:3000, upload an image and see how easy is to create a cropped image that can be used as an avatar.\n\n==How does it work?\n\nThis application was featured by Ryan Bates on his Railscast #182 http://railscasts.com/episodes/182-cropping-images\n\nThe tricky part creating this application was to find a simple way of interacting with Paperclip in order to create the cropped images after the model was saved. In fact it was necessary to reprocess the attachments after they were initially loaded by the plugin.\n\n===The model\n\n  class User \u003c ActiveRecord::Base\n  \n    has_attached_file :avatar,\n          :styles =\u003e { :normal =\u003e \"240x240\u003e\",\n                       :small = \u003e \"55x55#\" },\n          :processors =\u003e [:jcropper]\n  \n    attr_accessor :crop_x, :crop_y, :crop_w, :crop_h\n  \n    after_update :reprocess_avatar, :if =\u003e :cropping?\n  \n    def cropping?\n      !crop_x.blank? \u0026\u0026 !crop_y.blank? \u0026\u0026 !crop_w.blank? \u0026\u0026 !crop_h.blank?\n    end\n\n    # helper method used by the cropper view to get the real image geometry\n    def avatar_geometry(style = :original)\n      @geometry ||= {}\n      @geometry[style] ||= Paperclip::Geometry.from_file avatar.path(style)\n    end\n\n    private\n\n    def reprocess_avatar\n      avatar.reprocess!\n    end\n\n  end\n\nThe model includes the +has_attached_file+ as usual but it specifies a custom processor +jcropper+ that is slightly different from the original thumbnail.rb processor provided by Paperclip.\n\nThe process of creating the avatar works like this:\n\n- The user uploads an image and Paperclip creates the :normal and the :small version and because none of the :crop_x, :crop_y, :crop_w, :crop_h are defined +cropping?+ returns false. This way the +jcropper+ processor works just like the original +thumbnail+ processor.\n \n- Then the user is presented with the +normal+ thumbnail that is used to choose the cropping rectangle.\n \n- Finally when the user model is updated and +cropping?+ returns true, the Paperclip reprocess! method is invoked and the +jcropper+ processor crop the original image according to the cropping rectangle.\n\nBecause now the cropping rectangle parameters are provided by the view, then the +crop_command+ specifies how to crop the original image. The string looks like: \"-crop 500x500+125+450\" that in the ImageMagick convert command means \"crop the original image at offset 125,450 with a size of 500x500\". Finally the images are resized using :normal =\u003e \"240x240\u003e\" and  :small = \u003e \"55x55\" parameters.\n\n===The lib/papercli_processors/jcropper.rb\n\n  # Jcropper paperclip processor\n  #\n  # This processor very slightly changes the default thumbnail processor in order to work properly with Jcrop\n  # the jQuery cropper plugin.\n \n  module Paperclip\n    # Handles thumbnailing images that are uploaded.\n    class Jcropper \u003c Thumbnail\n    \n      def transformation_command\n        if crop_command\n          crop_command + super.sub(/ -crop \\S+/, '')\n        else\n          super\n        end\n      end\n    \n      def crop_command\n        target = @attachment.instance\n        if target.cropping?\n          \" -crop '#{target.crop_w.to_i}x#{target.crop_h.to_i}+#{target.crop_x.to_i}+#{target.crop_y.to_i}'\"\n        end\n      end\n  \n    end\n   \n  end\n\nThe +jcropper+ processor inherits from the original +Thumbnail+ processor but redefines the +transformation_command+ in order to get the cropping rectangle from the model if it is defined.\nOtherwise it works just like the original thumbnail processor.\n\n===The Jcrop and jQuery magic\n\nAll the magic happens in cropping.html.erb view and it should be easy to understand it by reading the Jcrop documentation. One important thing to remark is how the +ratio+ between the original image and the normal thumbnail is computed using the +avatar_geometry+ helper method from the model:\n\n  function showPreview(coords)\n  {\n    :\n    var ratio = \u003c%= @user.avatar_geometry(:original).width %\u003e / \u003c%= @user.avatar_geometry(:normal).width %\u003e; \n    :\n  }\n\n==Author\n\n*Juan* *Schwindt*\njuan(at)schwindt.org\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjschwindt%2Frjcrop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjschwindt%2Frjcrop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjschwindt%2Frjcrop/lists"}