Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Image orientation and validation with Paperclip?

I'm looking for a way to determine image orientation preferably with Paperclip, but is it even possible or do I need to user RMagick or another image library for this?

Case scenario: When a user uploads an image i want to check the orientation/size/dimensions to determine if the image is in portrait/landscape or square and save this attribute to the model.

like image 595
Antony Sastre Avatar asked Dec 09 '09 15:12

Antony Sastre


3 Answers

Here's what I generally do in my image models. Perhaps it will help:

  • I use IM's -auto-orient option when converting. This ensures images are always rotated properly after upload
  • I read the EXIF data after processing and get the width and height (among other things)
  • You can then just have an instance method that outputs an orientation string based on width and height
has_attached_file :attachment, 
  :styles => {
    :large => "900x600>",
    :medium => "600x400>",
    :square => "100x100#", 
    :small => "300x200>" },
  :convert_options => { :all => '-auto-orient' },   
  :storage => :s3,
  :s3_credentials => "#{RAILS_ROOT}/config/s3.yml",
  :s3_permissions => 'public-read',
  :s3_protocol => 'https',
  :path => "images/:id_partition/:basename_:style.:extension"

after_attachment_post_process  :post_process_photo 

def post_process_photo
  imgfile = EXIFR::JPEG.new(attachment.queued_for_write[:original].path)
  return unless imgfile

  self.width         = imgfile.width             
  self.height        = imgfile.height            
  self.model         = imgfile.model             
  self.date_time     = imgfile.date_time         
  self.exposure_time = imgfile.exposure_time.to_s
  self.f_number      = imgfile.f_number.to_f     
  self.focal_length  = imgfile.focal_length.to_s
  self.description   = imgfile.image_description
end
like image 72
Callmeed Avatar answered Nov 10 '22 17:11

Callmeed


Thanks for the answer jonnii.

Although I did find what I was looking for in the PaperClip::Geometry module.

This worked find:

class Image < ActiveRecord::Base
  after_save :set_orientation

  has_attached_file :data, :styles => { :large => "685x", :thumb => "100x100#" }
  validates_attachment_content_type :data, :content_type => ['image/jpeg', 'image/pjpeg'], :message => "has to be in jpeg format"

  private
  def set_orientation
    self.orientation = Paperclip::Geometry.from_file(self.data.to_file).horizontal? ? 'horizontal' : 'vertical'
  end
end

This of course makes both vertical and square images have the vertical attribute but that's what I wanted anyway.

like image 31
Antony Sastre Avatar answered Nov 10 '22 17:11

Antony Sastre


When I take a photo with my camera the dimensions of the image are the same regardless if the photo is landscape or portrait. However, my camera is smart enough to rotate the image for me! How thoughtful! The way this work is that is uses something called exif data which is meta data placed on the image by the camera. It includes stuff like: the type of camera, when the photo was taken, orientation etc...

With paperclip you can set up callbacks, specifically what you'll want to do is have a callback on before_post_process that checks the orientation of the image by reading the exif data using a library (you can find a list here: http://blog.simplificator.com/2008/01/14/ruby-and-exif-data/), and then rotating the image clockwise or counterclockwise 90 degrees (you won't know which way they rotated the camera when they took the photo).

I hope this helps!

like image 33
jonnii Avatar answered Nov 10 '22 16:11

jonnii