Image orientation and validation with Paperclip?
-
18-09-2019 - |
Question
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.
Solution
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
OTHER TIPS
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.
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!