Carrierwave crop specific version

前端 未结 3 2079
被撕碎了的回忆
被撕碎了的回忆 2021-01-31 12:47

I am working on the ability to crop images using carrierwave and Jcrop. Its a combination of Railscasts episode 182 and 253. I have cropping working but it crops the original.

相关标签:
3条回答
  • 2021-01-31 13:31

    Ryan just updated railscasts #182, it uses CarrierWave now

    http://railscasts.com/episodes/182-cropping-images-revised

    0 讨论(0)
  • 2021-01-31 13:38

    In the railscast, Ryan's solution was to convert the coords to work with the original image by finding the ratio between the large version and the original version. I was able to get it to work with Carrierwave and jCrop by following the same logic. Interesting enough Carrierwave does not store the dimensions of the images. I was able to hack together something from this post: http://code.dblock.org/ShowPost.aspx?Id=194.

    Here is my solution.

    user.rb

    class User < ActiveRecord::Base
    
      attr_accessor :password, :crop_x, :crop_y, :crop_h, :crop_w
      after_update :reprocess_profile, :if => :cropping?
    
      mount_uploader :profile, ProfileUploader
    
      def cropping?
        !crop_x.blank? && !crop_y.blank? && !crop_w.blank? && !crop_h.blank?
      end
    
      def profile_geometry
        img = Magick::Image::read(self.profile.current_path).first
        @geometry = {:width => img.columns, :height => img.rows }
      end
    
      private
    
      def reprocess_profile
        self.profile.recreate_versions!
      end
    
    end
    

    account_controller.rb

    class AccountController < ApplicationController
    
      def crop
        @account = current_user
      end
    
      def crop_update
        @account = current_user
        @account.crop_x = params[:account]["crop_x"]
        @account.crop_y = params[:account]["crop_y"]
        @account.crop_h = params[:account]["crop_h"]
        @account.crop_w = params[:account]["crop_w"]
        @account.save
        redirect_to account_path
      end
    
    end
    

    profile_uploader.rb

    class ProfileUploader < CarrierWave::Uploader::Base
    
      def extension_white_list
        %w(jpg jpeg gif png)
      end
    
      version :large do
        process :resize_to_fit => [500, 500]
      end
    
      version :thumb do
        process :manualcrop
        process :resize_to_fill => [100, 100]
      end
    
      def manualcrop
        return unless model.cropping?
        manipulate! do |img| 
          img = img.crop(model.crop_x.to_i,model.crop_y.to_i,model.crop_h.to_i,model.crop_w.to_i) 
        end 
      end
    
    end
    

    crop.html.erb

    <% content_for :head do %>
    <%= stylesheet_link_tag "jquery.Jcrop" %>
    <%= javascript_include_tag "jquery.Jcrop.min" %>
    <script type="text/javascript" charset="utf-8">
    $(function() {
      $('#cropbox').Jcrop({
        onChange: update_crop,
        onSelect: update_crop,
        setSelect: [0, 0, 500, 500],
        aspectRatio: 1
      });
    });
    
    function update_crop(coords) {
        var rx = 100/coords.w;
        var ry = 100/coords.h;
        var lw = $('#cropbox').width();
        var lh = $('#cropbox').height();
        var ratio = <%= @account.profile_geometry[:width] %> / lw ;
    
      $('#preview').css({
        width: Math.round(rx * lw) + 'px',
        height: Math.round(ry * lh) + 'px',
        marginLeft: '-' + Math.round(rx * coords.x) + 'px',
        marginTop: '-' + Math.round(ry * coords.y) + 'px'
      });
      $("#crop_x").val(Math.round(coords.x * ratio));
      $("#crop_y").val(Math.round(coords.y * ratio));
      $("#crop_w").val(Math.round(coords.w * ratio));
      $("#crop_h").val(Math.round(coords.h * ratio));
    }
    </script>
    <% end %>
    
    <%= image_tag @account.profile_url(:large), :id => "cropbox" %>
    
    <h3>Preview</h3>
    <div class="preview">
        <%= image_tag @account.profile_url(:large), :id => "preview" %>
    </div>
    
    <%= form_for @account, :as => :account, :url => { :action => "crop_update" } do |f| %>
        <% for attribute in [:crop_x, :crop_y, :crop_h, :crop_w] %>
            <%= f.hidden_field attribute, :id => attribute %>
        <% end %>
        <p><%= f.submit "Crop" %></p>
    <% end %>
    

    style.css

    .preview {
        width:100px;
        height:100px;
        overflow:hidden;
    }
    
    0 讨论(0)
  • 2021-01-31 13:40

    If I correctly understand the problem more simple way is to send trueSize option to the Jcrop.

    <% geo = @item.image_geometry %>
    $('#cropbox').Jcrop({boxWidth:656,boxHeight:350,onChange:update_crop,onSelect: update_crop,aspectRatio:656/350,trueSize:[<%= "#{geo[0]}, #{geo[1]}"%>]});
    
    0 讨论(0)
提交回复
热议问题