【Haskell】 HsExifを使い、Exif情報で画像を整理するスクリプトを書いてみた
環境 ghc 7.8.3 CentOS7.0
HaskellでExif情報を使って、写真を整理するスクリプトを書いてみた。
・・・まだExif撮影日時ごとにディレクトリ作成して、画像をコピーするだけ。
Exif取得自体はHsExifといモジュールを使ったが、そもそもHaskell自体がまだまだなので、このスクリプトを書くだけで約5時間かかった。
とりあえず、まだディレクトリを撮影日時から作成して、コピーしているだけなので、時間あるときに少しずつ拡張していく予定。
以下HsExif
使い方
▽インストール
cabal install
で可能。
# cabal install hsexif
ByteString.Lazy
は一緒に使うのでこれもimport。
Applicative
、Monad
は必須ではないが、多分使うのでimport。
import qualified Data.ByteString.Lazy as B import Graphics.HsExif import Control.Applicative import Control.Monad
▽画像からExif情報取り出し
実際にExifを取り出すには、以下のparseFileExif
、parseExif
を使う。
-- 【定義】 -- | Read EXIF data from the file you give. It's a key-value map. parseFileExif :: FilePath -> IO (Either String (Map ExifTag ExifValue)) parseFileExif filename = parseExif <$> B.readFile filename -- | Read EXIF data from a lazy bytestring. parseExif :: B.ByteString -> Either String (Map ExifTag ExifValue) parseExif = runEitherGet getExif
Exif情報だけ必要ならparseFileExif
でファイルを一発読み込みするのが楽。
ただしファイルの中身も必要なら、一度とりだしてやる必要がある。
-- parseFileExif ghci> rightExif <- parseFileExif "Foo.JPG" -- parseExif ghci> file <- return "Foo.JPG" >>= B.readFile ghci> rightExif <- parseExif <$> return file
一度ファイルを取り出すとき、parseExif
が一見、以下でも通りそうに感じる(私だけかな?)が、IO束縛なのでこれはエラーになる。
ghci> rightExif <- return file >>= parseExif <interactive>:28:30: Couldn't match type ‘Either String’ with ‘IO’
▽Exif情報の各情報を抽出
全exif情報のかたまりはRight (Map ExifTag ExifValue)
というデータ型になっている。
Data.Map
なので、lookup
等を駆使して力技で取得する事もできるが、各情報の専用関数が用意されている。
例えば撮影日時だと
-- 撮影日時取得 getDateTimeOriginal :: Map ExifTag ExifValue -> Maybe LocalTime getDateTimeOriginal exifData = Map.lookup dateTimeOriginal exifData >>= readExifDateTime . show
があるのでコレを使う。
ただし、parseExif
はEither
型、各種情報取得系(getDateTimeOriginal等)はMaybe
型になるので、一度取り出してやる。
ghci> let exif = (\(Right x) -> x) rightExif ghci> return exif >>= getDateTimeOriginal Just 2012-01-24 06:45:41
Either
とMaybe
の交換はもっといい手がありそうな気がするが、わからなかったので強引にいった。
日付系はData.Time.LocalTime.LocalTime.LocalTime
が使われているので、これを更に弄るときはimport Data.Time
も必要になる。
githubのTests.hsがとても参考になる。
【参考】HsExif
▽Hacakge
hsexif: EXIF handling library in pure Haskell | Hackage
▽GitHub
emmanueltouzery/hsexif · GitHub