Rails 3.1中使用自定义处理器和裁剪功能时的Paperclip错误

3
我在使用Paperclip和自定义处理器时遇到了一个棘手的问题,其中一些样式丢失了。我有一张图片,我用从视图传递过来的坐标进行裁剪,裁剪顺利完成并保存原始图片,但是当运行重新处理以生成其他样式时,我会收到以下错误:
convert: geometry does not contain image `/var/folders/bg/w2mft0x51t933pzhgpvhm5800000gn/T/paperclip-reprocess20111114-3404-13lp780-0' @ warning/transform.c/CropImage/571.

当我遇到这个错误时,原始图像风格丢失
我尝试了回调和paperclip的一些操作,但没有成功。我真的被卡住了,找不到任何相关信息。
我所遵循的示例来自http://railscasts.com/episodes/182-cropping-images 与screencast中的示例不同之处在于,我想裁剪原始图像,然后使用标准的paperclip样式生成缩略图。
以下是我的代码。
我的处理器:
module Paperclip

  class Cropper < Thumbnail
    def transformation_command
      if crop_command
        original_command = super
        if original_command.include?('-crop')
          original_command.delete_at(super.index('-crop') + 1)
          original_command.delete_at(super.index('-crop'))
        end
        crop_command + original_command
      else
        super
      end
    end

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

end

我的模型:

class Item < ActiveRecord::Base

  belongs_to :category
  belongs_to :picture

  validates :picture_id,  :presence => true
  validates :category_id, :presence => true

  validates :title_url,   :presence => true, :uniqueness => { :case_sensitive => false }
  validates :title,       :presence => true, :uniqueness => { :case_sensitive => false }
  validates :information, :presence => true, :uniqueness => { :case_sensitive => false }

  validates :crop_x,      :presence => true, :numericality => { :only_integer => true, :greater_than_or_equal_to => 0 }
  validates :crop_y,      :presence => true, :numericality => { :only_integer => true, :greater_than_or_equal_to => 0 }
  validates :crop_w,      :presence => true, :numericality => { :only_integer => true, :greater_than_or_equal_to => 0 }
  validates :crop_h,      :presence => true, :numericality => { :only_integer => true, :greater_than_or_equal_to => 0 }

  Paperclip.interpolates :title_url do |attachment, style|
    attachment.instance.title_url
  end

  has_attached_file :image,
                    :styles => {
                      :small    => { :format => 'jpg', :quality => 100, :geometry => '100x100#' },
                      :medium   => { :format => 'jpg', :quality => 100, :geometry => '200x200#' },
                      :large    => { :format => 'jpg', :quality => 100, :geometry => '300x300#' },
                      :original => { :format => 'jpg', :quality => 100, :geometry => '', :processors => [:cropper] }
                    },
                    :path => ":rails_root/public/attachments/:class/:attachment/:id_partition/:style/:title_url.:extension",
                    :url  =>                   "/attachments/:class/:attachment/:id_partition/:style/:title_url.:extension"

  before_validation   :strip_attributes
  before_save         :image_assign,    :if => :cropping?
  after_create        :image_reprocess, :if => :cropping?

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

  def image_geometry(style = :original)
    @geometry ||= {}
    @geometry[style] ||= Paperclip::Geometry.from_file(avatar.path(style))
  end

  def calc(width,height)
    # original large side / smalled picture large side
    calc_width  = self.picture.width.to_f  / width
    calc_height = self.picture.height.to_f / height
    if calc_width >= calc_height
      return calc_width
    else
      return calc_height
    end
  end

  private

  def image_assign
    self.image = self.picture.image
  end

  def image_reprocess
    image.reprocess!
  end

  def strip_attributes
    # normalize attributes
    self.title.strip!
    self.title_url = Utility::friendly_url(self.title)
    self.information.strip!
  end

end

我会把":geometry =>''"从:image => :styles => :original中移除...不确定是否有效,但一定有些东西导致原始文件无法保存。嗯。 - drhenner
没有几何图形,即使是基本的设置也会失败。在定义样式时似乎是必需的。 - YavorIvanov
我应该澄清一下(如果上面不清楚),重新处理会破坏原始图像。在调用重新处理之前保存时似乎没问题。 - YavorIvanov
对我来说,是before_validation与paperclip发生了问题。我一直收到“没有大小为nil的类”的方法。注释掉before_validation后,一切都正常运行。 - kikuchiyo
1个回答

4

我注意到至少有一位除了我之外的人遇到了关于裁剪的自定义paperclip处理器的问题,因此我将我的最终解决方案分享出来。其中包括图片居中裁剪等内容。我相信这远非完美,但已经可靠地工作了一年。

module Paperclip

  class CropperItem < Thumbnail
    def transformation_command
      if crop_command
        original_command = super
        if original_command.include?('-crop')
          original_command.delete_at(super.index('-crop') + 1)
          original_command.delete_at(super.index('-crop'))
        end
        if original_command.include?('-resize')
          crop_command('square') + original_command
        else
          crop_command + original_command
        end
      else
        super
      end
    end

    def crop_command(dimensions = nil)
      target = @attachment.instance
      if target.cropping?
        case dimensions
        when 'square'
          if target.crop_w > target.crop_h
            crop_w = target.crop_w.to_i
            crop_h = target.crop_w.to_i
            crop_x = target.crop_x.to_i
            crop_y = target.crop_y.to_i - ((target.crop_w.to_i-target.crop_h.to_i)/2).to_i
            crop_x = 0 if crop_x < 0
            crop_y = 0 if crop_y < 0
          elsif target.crop_w < target.crop_h
            crop_w = target.crop_h.to_i
            crop_h = target.crop_h.to_i
            crop_x = target.crop_x.to_i - ((target.crop_h.to_i-target.crop_w.to_i)/2).to_i
            crop_y = target.crop_y.to_i
            crop_x = 0 if crop_x < 0
            crop_y = 0 if crop_y < 0
          else
            crop_w = target.crop_w.to_i
            crop_h = target.crop_h.to_i
            crop_x = target.crop_x.to_i
            crop_y = target.crop_y.to_i
          end
          ["-crop", "#{crop_w}x#{crop_h}+#{crop_x}+#{crop_y}", "+repage"]
        else
          ["-crop", "#{target.crop_w.to_i}x#{target.crop_h.to_i}+#{target.crop_x.to_i}+#{target.crop_y.to_i}", "+repage"]
        end
      end
    end
  end

end

最终我在模型中使用了类似于以下的内容。

has_attached_file :photo,
                  :styles => {
                    :small        => { :format => 'jpg', :quality => 100, :geometry => '50x50^'   },
                    :thumb_small  => { :format => 'jpg', :quality => 100, :geometry => '110x110^' },
                    :thumb_medium => { :format => 'jpg', :quality => 100, :geometry => '150x150^' },
                    :medium       => { :format => 'jpg', :quality => 100, :geometry => '240x160^' },
                    :banner_small => { :format => 'jpg', :quality => 100, :geometry => '200x120#' },
                    :banner       => { :format => 'jpg', :quality => 100, :geometry => '300x250^' },
                    :focus_crop   => { :format => 'jpg', :quality => 100, :geometry => '400x400>' },
                    :focus_orig   => { :format => 'jpg', :quality => 100, :geometry => '' }
                  },
                  :convert_options => {
                    :thumb_small  => "-gravity Center -extent 50x50",
                    :thumb_small  => "-gravity Center -extent 110x110",
                    :thumb_medium => "-gravity Center -extent 150x150",
                    :medium       => "-gravity Center -extent 240x160",
                    :banner_small => "-gravity Center -extent 200x120",
                    :banner       => "-gravity Center -extent 300x250",
                    :focus_crop   => "-gravity Center"
                  },
                  :processors => [:cropper_item],
                  :path => PAPERCLIP_PATH,
                  :url  => PAPERCLIP_URL

希望这篇文章能对某些人有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接