【问题标题】:Saving the images Dimensions (width and height) in Paperclip?在回形针中保存图像尺寸(宽度和高度)?
【发布时间】:2010-10-31 21:43:06
【问题描述】:

是否有任何 Paperclip 向导知道您是否可以在使用 Paperclip 保存图像时,还将图像尺寸(宽度和高度)保存在 2 个额外字段中?在 Paperclip 上传过程中如何获取这些数据?

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 paperclip


    【解决方案1】:

    只是为了完整起见,即使以前的答案已经显示了足够好的建议。

    您可以使用 Paperclip 事件处理程序而不是 Rails 回调。在这种情况下,仅当图像更改时才会重新计算大小。 (如果您使用 S3 进行存储,这可以节省相当多的时间)

    has_attached_file :image, :styles => ...
    after_post_process :save_image_dimensions
    
    def save_image_dimensions
      geo = Paperclip::Geometry.from_file(image.queued_for_write[:original])
      self.image_width = geo.width
      self.image_height = geo.height
    end
    

    图像甚至不必从 S3 下载(或从文件中读取),回形针将其提供给事件处理程序本身。

    详情请参阅the readme事件部分。

    【讨论】:

    • 已经下载了 2 个 gem 来尝试(但失败)来实现这一目标。希望我先找到这个简单的 sn-p。非常感谢:)
    【解决方案2】:

    当用户使用回形针上传图片时,我会使用以下模型对其进行处理:

    class Picture < ActiveRecord::Base
      has_attached_file :pic, :styles => { :small => "100x100>" }, :whiny => true
      after_save :save_geometry
    
      def save_geometry
        unless @geometry_saved
          self.original_geometry = get_geometry(:original)
          self.small_geometry = get_geometry(:small)
          @geometry_saved = true
          self.save
        end
      end
    
      def get_geometry(style = :original)
        begin
          Paperclip::Geometry.from_file(pic.path(style)).to_s
        end
      end
    end
    

    get_geometry 函数调用 ImageMagick identify 来查找原始图像和调整大小图像的几何形状。

    我将结果缓存在数据库字段中。例如,如果我上传了一张 1024x768 的图片,我的缓存字段将包含:

    original_geometry = "1024x768"
    small_geometry = "100x75"
    

    【讨论】:

      【解决方案3】:

      你将需要'RMagick'

      uploaded_image = Magick::Image.read(image).first  #image is what you've specified in paperclip to be your image
      width = uploaded_image.columns
      height = uploaded_image.rows
      

      不过,不确定如何让它与回调一起使用。可能是这样的:

      attr_accessor :write_image_dimensions?
      before_save :check_image_changed
      
      def check_image_changed
        self.write_image_dimensions? = image_changed?
      end
      
      after_save :write_image_dimensions, :if => :write_image_dimensions?
      
      def write_image_dimensions
        uploaded_image = Magick::Image.read(image).first  #image is what you've specified in paperclip to be your image
        self.width = uploaded_image.columns
        self.height = uploaded_image.rows
        save
      end
      

      【讨论】:

        【解决方案4】:

        使用 Rails 4 我使用以下 Concern 来保存图像尺寸:

            module Dimensions
        
              extend ActiveSupport::Concern
        
              included do
        
              end
        
              module ClassMethods
        
                def extract_dimensions_for *fields
        
                  define_method(:extract_dimensions_field_list) { fields }
        
                  before_save :extract_dimensions
        
                  fields.each do |f|
                    serialize (f.to_s+"_dimensions"), Hash
        
                    class_eval do
        
                      [:width, :height].each do |axis|
                        define_method("#{f}_#{axis}") do
                          return send(f.to_s+"_dimensions")[axis]
                        end
                      end
        
                      define_method("#{f}_dimensions_max") do |width, height=nil|
                        dims = send(f.to_s+"_dimensions")
                        rw = width.to_f / dims[:width]
                        rh = height.to_f / dims[:height] if height
                        r = (!height || rw < rh) ? rw : rh
                        return {width: (dims[:width] * r).to_i, height: (dims[:height] * r).to_i}
                      end
        
                      define_method("#{f}_is_portrait?") do
                        dims = send(f.to_s+"_dimensions")
                        return dims[:width] <= dims[:height]
                      end
        
                      define_method("#{f}_is_landscape?") do
                        dims = send(f.to_s+"_dimensions")
                        return dims[:width] > dims[:height]
                      end
        
                    end
        
                  end
        
                  class_eval do
        
                    def extract_dimensions
        
                      extract_dimensions_field_list.each do |f|
        
                        tempfile = send(f).queued_for_write[:original]
                        unless tempfile.nil?
                          geometry = Paperclip::Geometry.from_file(tempfile)
                          self.send(f.to_s+"_dimensions=", {width: geometry.width.to_i, height: geometry.height.to_i})
                        end
        
                      end
        
                    end
        
                  end
        
                end
        
              end
        
        
            end
        

        然后在你的模型中:

        ...
        
        include Dimensions
        
        extract_dimensions_for :image
        
        ...
        

        这会将您的维度保存到名为image_dimensions 的序列化字段中,并添加一些其他方法image_widthimage_heightimage_dimensions_max(width, height)

        【讨论】:

          【解决方案5】:

          我找到了最简单的解决方案:Fastimage gem (link)

          它很快而且非常非常简单。 示例:

          require 'fastimage'
          
          FastImage.size("/some/local/file.gif")
          => [266, 56]  # width, height
          FastImage.type("/some/local/file.gif")
          => :gif
          

          【讨论】:

            【解决方案6】:

            回形针元 gem 缓存所有图像样式的图像尺寸和文件大小。它在 Paperclip README 中被引用。回形针元仓库在这里:https://github.com/teeparham/paperclip-meta

            【讨论】: