Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cropping using Paperclip, ImageMagick, Jcrop and S3 storage: Why won't 'image.reprocess!' reprocess?

I'm (loosely) following RailsCasts tutorial #182, which uses Paperclip, ImageMagick, and Jcrop to allow custom cropping of uploaded images.

As I'm using Amazon S3 for file storage, I've had to rejigger parts of the tutorial to suit. Everything seems to be working perfectly except for the fact that the cropped version of my image isn't being reprocessed (or the result of that reprocess is not re-uploaded to S3)--so after the cropping process, I'm left with the same image I originally uploaded (this is true for all image sizes I store for each image).

Here is my Feature (as in Feature Image) model:

class Feature < ActiveRecord::Base
  require "#{Rails.root}/lib/paperclip_processors/cropper.rb"

  attr_accessible    :image_file_name, :image
  attr_accessor      :crop_x, :crop_y, :crop_w, :crop_h
  after_update       :reprocess_image, :if => :cropping?

  if Rails.env == "production"
  S3_CREDENTIALS = { :access_key_id     => '<REDACTED>',
                     :secret_access_key => '<REDACTED>',
                     :bucket            => "<REDACTED>"}
  else
  S3_CREDENTIALS = { :access_key_id     => '<REDACTED>',
                     :secret_access_key => '<REDACTED>',
                     :bucket            => "<REDACTED>"}
  end

  has_attached_file :image,
                    :styles          => { :small => "240x135>", :croppable => "960x960>", :display => "960x540>" },
                    :processors      => [:cropper],
                    :storage         => :s3,
                    :s3_credentials  => S3_CREDENTIALS,
                    :path            => "features/:id/:style.:extension"

  validates_attachment_content_type :image, :content_type => ['image/jpeg', 'image/gif', 'image/png',
                                                              'image/pjpeg', 'image/x-png'], 
                                            :message => 'must be a JPEG, GIF or PNG image'

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

  def image_geometry(style = :original)
    @geometry ||= {}
    path = (image.options[:storage]==:s3) ? image.url(style) : image.path(style)
    @geometry[style] ||= Paperclip::Geometry.from_file(path)
  end

  private

  def reprocess_image
    image.reprocess!
  end
end

Here is my 'cropper.rb' (Paperclip processor):

module Paperclip
  class Cropper < Thumbnail
    def transformation_command
      if crop_command
        crop_command + super.sub(/ -crop \S+/, '')
      else
        super
      end
    end

    def crop_command
      target = @attachment.instance
      if target.cropping?
        " -crop '#{target.crop_w}x#{target.crop_h}+#{target.crop_x}+#{target.crop_y}'"
      end
    end
  end
end

The relevant actions of my FeaturesController:

class FeaturesController < ApplicationController

  def new
    @feature = Feature.new
  end

  def create
    @feature = Feature.new(params[:feature])
    if @feature.save
      if params[:feature][:image].blank?
        flash[:notice] = "New feature added!"
        redirect_to @feature
      else
        render :crop
      end
    else
      @title = "Add a New Feature"
      render :new
    end
  end

  def edit
    @feature = Feature.find(params[:id])
    @title = "Edit #{@feature.headline}"
  end

  def update
    @feature = Feature.find(params[:id])
    if @feature.update_attributes(params[:feature])
      if params[:feature][:image].blank?
        flash[:notice] = "Feature updated!"
        redirect_to @feature
      else
        render :crop
      end
    else
      @title = "Edit Feature"
      render :edit
    end
  end
end

And the relevant lines of my 'crop.html.erb' view:

<% content_for :javascript_includes do %>
    <%= 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, 960, 540],
            aspectRatio: 960/540
        });
    });

    function update_crop(coords) {
        var ratio = <%= @feature.image_geometry(:original).width %> / <%= @feature.image_geometry(:croppable).width %>;
        $("#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 %>
<% content_for :style_includes do %>
    <%= stylesheet_link_tag 'jquery.Jcrop', :media => 'screen' %>
<% end %>

<%= image_tag @feature.image.url(:croppable), :id => "cropbox" %>

<% form_for @feature do |f| %>
    <% for attribute in [:crop_x, :crop_y, :crop_w, :crop_h] %>
        <%= f.hidden_field attribute, :id => attribute %>
    <% end %>
    <p><%= f.submit "Crop" %></p>
<% end %>

The problem is not that there's an error with the custom crop (offset, crop area, etc.), it's that there is no crop happening when I click 'crop'--I'm just left with the images I got from the original upload/process. It doesn't appear that 'image.reprocess!' is happening at all (or the results of the reprocess aren't being saved to S3).

Why might that be, and what can I do about it?

like image 928
jasonmklug Avatar asked Jul 07 '11 19:07

jasonmklug


2 Answers

Don't know if this is the same but I had a problem with the reprocessing and fixed it by following the answer here:

paperclip error while reporcessing after rails 3 upgrade

like image 101
Chris Edwards Avatar answered Oct 14 '22 05:10

Chris Edwards


Ok, let me try to help :)

Firstly, can you not include your Paperclip processor in the model, let Paperclip handle it.

Secondly, remove the :after_update and replace with a :before_update which should set your image.options[ :crop ] up for the processor. In your processor, try this:

def initialize file, options = {}, attachment = nil
  super
  #......

  @crop = options[ :crop ]

  #......

Thirdly, modify your transformation_command in the processor:

def transformation_command
  if @crop
      trans = " -quality 75"
      trans << " -crop \"#{<YOUR_CODE>}\" +repage" if @crop
      trans
  end
end

And then post your findings :)

like image 27
shashin Avatar answered Oct 14 '22 04:10

shashin