Saving the images Dimensions (width and height) in Paperclip?

你说的曾经没有我的故事 提交于 2019-12-03 02:54:12

问题


Any Paperclip wizards out there know if you can when using Paperclip to save an image, also save the image dimensions (width and height) in 2 extra fields? How do you get such data during the Paperclip upload process?


回答1:


Just for the sake of completeness, even though previous answers already show good enough suggestions.

You can utilize Paperclip event handlers instead of Rails callbacks. In this case, size will be recalculated only when image changes. (If you're using S3 for storage, this can save quite some time)

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

Image don't even have to be downloaded from S3 (or read from a file), paperclip provides it to event handler itself.

See Events section of the readme for details.




回答2:


When a user uploads an image with paperclip I process it with the following model:

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

The get_geometry function calls ImageMagick identify to find the geometry of your original and resized images.

I cache the results in a database field. For example if I uploaded an image that was 1024x768 my cached fields would contain:

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



回答3:


You will need to require '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

Not sure how to have it working with the callbacks, though. Maybe something like:

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:


Using Rails 4 I use the following Concern to save image dimensions:

    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

Then in your model:

...

include Dimensions

extract_dimensions_for :image

...

This will save your dimensions to a serialized field called image_dimensions as well as adding a few other methods image_width, image_height and image_dimensions_max(width, height)




回答5:


I found the simplest solution: Fastimage gem (link)

It is fast and very, very simple. Example:

require 'fastimage'

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



回答6:


The paperclip-meta gem caches image dimensions and file size for all image styles. Its referenced in the Paperclip README. The paperclip-meta repo is here: https://github.com/teeparham/paperclip-meta



来源:https://stackoverflow.com/questions/4065295/saving-the-images-dimensions-width-and-height-in-paperclip

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!