module Graphics.Exif (Exif, fromFile, fromData, getTag, allTags) where import Graphics.Exif.Internals import Control.Monad import Foreign newtype Exif = Exif (ForeignPtr ExifData) fromFile :: FilePath -> IO Exif fromFile f = dataFromFile f >>= mkExif fromData :: Ptr () -> Int -> IO Exif fromData p c = dataFromData p c >>= mkExif getTag :: Exif -> String -> IO (Maybe String) getTag x s = withExif x f where f d = do t <- tagFromName s es <- dataGetEntries d e <- firstFilterM (entryHasTag t) es maybe (return Nothing) (fmap Just . entryGetValue) e allTags :: Exif -> IO [(String,String)] allTags x = withExif x f where f d = dataGetEntries d >>= mapM g g e = do t <- entryGetTag e n <- tagName t v <- entryGetValue e return (n,v) -- Internal stuff mkExif :: Ptr ExifData -> IO Exif mkExif p | p == nullPtr = fail "mkExif: NULL" | otherwise = liftM Exif $ newForeignPtr dataFree p withExif :: Exif -> (Ptr ExifData -> IO a) -> IO a withExif (Exif e) f = withForeignPtr e f dataGetEntries :: Ptr ExifData -> IO [Ptr ExifEntry] dataGetEntries d = dataGetContents d >>= liftM concat . mapM contentGetEntries entryHasTag :: ExifTag -> Ptr ExifEntry -> IO Bool entryHasTag t e = liftM (==t) $ entryGetTag e -- Utilities firstFilterM :: Monad m => (a -> m Bool) -> [a] -> m (Maybe a) firstFilterM _ [] = return Nothing firstFilterM f (x:xs) = f x >>= \b -> if b then return (Just x) else firstFilterM f xs