Attachment_fu model With Custom Filename, Square Cropping.

이번 작업을 하면서 필요했던 부분.

Attachment_fu에서 저장되는 파일 명 변경과 함께, 특정 이미지를 골라서 정해준 위치에 맞게 Cropping을 하는 기능이 필요했다. Cropping 관련 메소드는 Kropper에서 빌려옴. ^^

class ArticleImage < ActiveRecord::Base
  belongs_to :article

  @@thumbs = {
    :large => '180x180!',
    :medium => '120x120!',
    :small => '90x90!'
  }

  has_attachment :content_type => :image,
                 :storage => :file_system,
                 :max_size => 20.megabytes,
                 :path_prefix => "public/images/#{table_name}",
                 :resize_to => '600x400>',
                 :processor => "Rmagick",
                 :thumbnails => {
                   :large => '180x180!',
                   :medium => '120x120!',
                   :small => '90x90!'
                 }

  validates_as_attachment

  # Customizing Filename.
  def full_filename(thumbnail = nil)
    file_system_path = (thumbnail ? thumbnail_class : self).attachment_options[:path_prefix].to_s
    @thumb = self.thumbnail unless (@thumb = thumbnail)
    asset = self.parent_id.nil? ? self.id : self.parent_id
    File.join(RAILS_ROOT, file_system_path, *partitioned_path(thumbnail_name_for(@thumb, asset)))
  end

  # Filename Customizing Method
  def thumbnail_name_for(thumbnail = nil, asset = nil)
    suffix = "_#{thumbnail}" unless thumbnail.blank?
    extension = filename.scan(/\.\w+$/)
    return "#{asset}#{suffix}#{extension}"
  end

  # crops the attached image according to the passed left, top, width, and height params.
  # if resize_to_stencil is true, the image is resized to stencil_w x stencil_h.
  # after cropping and resizing, the resulting image is saved back to disk.
  # any thumbnail image the image may have is automatically updated.
  def crop!( options = {} )
    # setup the default params
    options[:crop_left]   ||= 0
    options[:crop_top]    ||= 0
    options[:crop_width]  ||= 100
    options[:crop_height] ||= 100
    options[:stencil_width]  ||= 100
    options[:stencil_height] ||= 100
    options[:resize_to_stencil] ||= false
    # passed params could be strings, so convert them to ints/booleans
    crop_l = options[:crop_left].to_i
    crop_t = options[:crop_top].to_i
    crop_w = options[:crop_width].to_i
    crop_h = options[:crop_height].to_i
    stencil_w = options[:stencil_width].to_i
    stencil_h = options[:stencil_height].to_i
    resize_to_stencil = false if (options[:resize_to_stencil] == false) || (options[:resize_to_stencil] == "false")
    resize_to_stencil = true if (options[:resize_to_stencil] == true) || (options[:resize_to_stencil] == "true")

    # call the appropriate crop method for the image processor we're using with attachment_fu
    if self.class.include?(Technoweenie::AttachmentFu::Processors::RmagickProcessor)
      crop_with_rmagick! crop_l, crop_t, crop_w, crop_h, stencil_w, stencil_h, resize_to_stencil
    else
      raise "You're using an unsupported image processor."
    end
  end

  private

  def crop_with_rmagick!(crop_l, crop_t, crop_w, crop_h, stencil_w, stencil_h, resize_to_stencil)
    # create a temporary cropped version of our image
    cropped_img = nil
    self.with_image do |img|
      if (crop_w <= 0) || (crop_h <= 0) || (crop_l + crop_w <= 0) || (crop_t + crop_h <= 0) || (crop_l >= img.base_columns) || (crop_t >= img.base_rows)
        raise InvalidCropRect
      end
      cropped_img = img.crop(crop_l, crop_t, crop_w, crop_h, true )
      cropped_img.resize!(stencil_w, stencil_h) if resize_to_stencil
    end
    # write the cropped image to a temp file, which attachment_fu will use
    # to replace the existing image file (and thumbnail, if any) on save
    self.temp_path = write_to_temp_file(cropped_img.to_blob)
    @@thumbs.each { |suffix, size| create_or_update_thumbnail(self.temp_path, suffix, *size) }
    #callback_with_args :after_resize, cropped_img
  end

end

Posted by Kenny Wed, 23 Apr 2008 02:10:00 GMT