Adding Exif data to your Image model with exifr
Exif data is a must-have for browsing through your photos. Adobe Bridge has it, F-Spot has it, and so does about every filebrowser out there, so why not include it in your own database when uploading these photos to your app?
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
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:
1 2 3 4 5 6 |
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…
Write a comment