RubyでJPEGファイルのEXIF情報取得

先週末、友達と4人で石川県に旅行に行ってきて、後日みんなで取り合った写真を交換したんだ。で、いざ写真を時系列で整理しようにも、複数のカメラで撮られたたくさんの写真をEXIF情報を参照しながら並び替えて、名前を変更するのは困難だった。そこで、RubyEXIF情報を取得するライブラリを調査して、それを使って撮影時刻順に画像ファイルに名前を振るスクリプトを作成したので、そのメモ。

EXIF情報取得用Rubyライブラリ

ちょっと調べてみたところ、extexif、exifr、ruby-exifなどが見つかった。このうち、extexifは拡張ライブラリを用いた実装、exifr、ruby-exifはピュアRuby実装。ピュアRubyの方が扱いやすい、かつ、最近でもメンテナンスされている点で、今回はexifrを導入した。
RubyForge: EXIF Reader: Project Info

インストール

rubygemsに登録されているので、gemコマンド一発でインストールできる。僕はMacPortsRuby 1.9を使っているので、次のようにコマンドを実行した。

$ sudo gem1.9 install exifr

sudoしなくてもインストールできるけど、その場合実行ユーザのホームディレクトリにインストールされてしまい、次の点で面倒になる。

  • RUBYLIB等のパスを通す必要がある
  • gemアンインストール時に、-iでインストールされているディレクトリを指定する必要がある

まぁ、個人使用のMacBook Proなのでroot権限でインストールしてしまっても問題ないと思って。

使い方

使い方はすごく簡単。次のようにexifrライブラリを読み込んで、EXIFR::JPEGインスタンスを生成するだけ。そのインスタンスに対して、取得したいEXIF属性をメソッドとして呼び出せばOK。

require 'rubygems'
require 'exifr'

puts EXIFR::JPEG::new('PIC01.JPG').date_time

require 'pp'
pp EXIFR::JPEG::new('PIC01.JPG').to_hash

to_hashメソッドを使うと、画像の持つすべてのEXIF属性とその値をハッシュで取得できる。どんな属性を持つか、確認するのに便利。

撮影時刻による画像ファイル並べ替えの実装方針

EXIFR::JPEG#date_timeを呼び出すと(実際にはmethod_missingで処理されている)、Timeインスタンスが取得できる。そこで今回は、次のようなスクリプトを書いた。

  • ディレクトリ内の画像ファイル(名)を配列に保存
  • 各画像ファイル毎にexifrを使って撮影時刻を取り出し、"撮影時刻 => ファイル名"のハッシュに格納
  • このハッシュのキー(撮影時刻)を配列として取り出し、昇順にソート
    • Timeクラスには<=>メソッドが定義されているので、時刻によるソートは簡単
  • 撮影時刻の配列順に、"撮影時刻 => ファイル名"のハッシュからファイル名を取り出し、配列に格納
  • その配列内のファイル名に連番に名前を振る

以前実装したファイル名変更のためのスクリプトの1機能として実装したので、長くなってしまうので、スクリプトの掲載は断念した。