Adding Exif data to your Image model with exifr
Posted on · · Tags: paperclip
I’m now using this great little gem called exifr in my project. It’s fairly nimble, but gets the job done. To include it in your rails project, add the following line in your config/environment.rb
config.gem "exifr"
You’ll also want to add some fields to the model you are saving the exif data to. The exif reading is quite fast so you might want to do it on-the-fly, but then you don’t get some new fields on your models for all those cool queries. Let’s add it to our Image model.
class AddExifFieldsToImages < ActiveRecord::Migration
def self.up
add_column :images, :width, :integer
add_column :images, :height, :integer
add_column :images, :camera_brand, :string
add_column :images, :camera_model, :string
add_column :images, :exposure_time, :string
add_column :images, :f_number, :float
add_column :images, :iso_speed_rating, :integer
add_column :images, :focal_length, :float
add_column :images, :shot_date_time, :datetime
end
def self.down
remove_column :images, :width
remove_column :images, :height
remove_column :images, :camera_brand
remove_column :images, :camera_model
remove_column :images, :exposure_time
remove_column :images, :f_number
remove_column :images, :iso_speed_rating
remove_column :images, :focal_length
remove_column :images, :shot_date_time
end
end
These are the fields I normally use, but there are probably more that are worth saving.
In order to get some data into these fields, we create this little method in our Image model:
def set_exif_data
exif = EXIFR::JPEG.new( self.data.path )
return if exif.nil? or not exif.exif?
self.width = exif.width
self.height = exif.height
self.camera_brand = exif.make
self.camera_model = exif.model
self.exposure_time = exif.exposure_time.to_s
self.f_number = exif.f_number.to_f
self.iso_speed_rating = exif.iso_speed_ratings
self.shot_date_time = exif.date_time
self.focal_length = exif.focal_length.to_f
rescue
false
end
In this example I get the path of the file from self.data.path, where data is my paperclip attachment called :data. If you have some other setup, you’ll have to change this to fit your needs.
Calling this method sets the fields to the correct values, but does not save the object. Using the setup with delayed_job from the last article you can a line in your perform() method to get exif data for all new Images, making the method as a whole like this:
def perform
self.processing = false
set_exif_data # this is the line we added
data.reprocess!
save
end
And voila, you now have added exif data to your images! Now it’s time to think out something cool to do with it…