module Graphics.Hexif.PrettyPrint (prettyPrint) where
import Graphics.Hexif.DataExif
import Graphics.Hexif.PrettyPrintInt
import Graphics.Hexif.PrettyPrintRat
import Text.Printf (printf)
import Data.List(intersperse)
import Data.Char (chr, ord)
prettyPrint :: DataBlock -> [ExifField]
prettyPrint entries = ppEntries entries ++ ppSubEntries entries
where
ppEntries :: DataBlock -> [ExifField]
ppEntries flds = map ppDataEntry (filter (not . isSubBlock) flds)
ppSubEntries :: DataBlock -> [ExifField]
ppSubEntries [] = []
ppSubEntries es =
prettyPrint $ concatMap subBlock (filter isSubBlock es)
subBlock :: DataEntry -> DataBlock
subBlock (DataSub _ b) = b
subBlock _ = []
isSubBlock :: DataEntry -> Bool
isSubBlock (DataSub _ _ ) = True
isSubBlock _ = False
ppDataEntry :: DataEntry -> ExifField
ppDataEntry (DataRat tag _ rats) = ExifField tag (ppRationalValues tag rats)
ppDataEntry (DataNum tag _ nVal) = ExifField tag (ppNumValue tag nVal)
ppDataEntry (DataStr tag _ strVal) = ExifField tag (ppStrValue tag strVal)
ppDataEntry (DataUdf tag _ len strVal) = ExifField tag (ppUndefinedValue tag len strVal)
ppDataEntry (DataSub tag _ ) = error $ "Directory encountered " ++ show tag
ppUndefinedValue :: ExifTag -> Int -> String -> String
ppUndefinedValue TagExifVersion _ value = ppExifVersion value
ppUndefinedValue TagFlashPixVersion _ value = ppFlashPixVersion value
ppUndefinedValue TagComponentsConfiguration _ value = ppComponentsConfiguration value
ppUndefinedValue TagFileSource _ value = ppFileSource value
ppUndefinedValue TagSceneType _ value = ppSceneType value
ppUndefinedValue TagInteroperabilityVersion _ value = value
ppUndefinedValue _ len _ = show len ++ " bytes undefined data"
ppStrValue :: ExifTag -> String -> String
ppStrValue TagXPAuthor strVal = removeNull strVal
ppStrValue TagXPTitle strVal = removeNull strVal
ppStrValue TagGPSVersionID strVal = intersperse '.' strVal
ppStrValue TagGPSAltitudeRef strVal= ppTagGPSAltitudeRef strVal
ppStrValue _ strVal = rtrimX00 strVal
rtrimX00 :: String -> String
rtrimX00 = reverse . dropWhile (\c -> ord c == 0) . reverse
removeNull :: String -> String
removeNull = filter (\c -> ord c /= 00)
ppExifVersion :: String -> String
ppExifVersion value = "Exif Version " ++ show num
where num :: Float = read value / 100.0
ppFlashPixVersion :: String -> String
ppFlashPixVersion value = printf "FlashPix Version %.1f" num
where num :: Float = read value / 100.0
ppComponentsConfiguration :: String -> String
ppComponentsConfiguration conf = unwords $ map ppComps conf
where
ppComps (ord -> 0) = "-"
ppComps (ord -> 1) = "Y"
ppComps (ord -> 2) = "Cb"
ppComps (ord -> 3) = "Cr"
ppComps (ord -> 4) = "R"
ppComps (ord -> 5) = "G"
ppComps (ord -> 6) = "B"
ppComps (ord -> _) = "??"
ppFileSource :: String -> String
ppFileSource value =
if head value == chr 3
then "DSC"
else "(unknown)"
ppSceneType :: String -> String
ppSceneType value =
if head value == chr 1
then "Directly photographed"
else "(unknown)"
ppTagGPSAltitudeRef :: String -> String
ppTagGPSAltitudeRef s = case s of
"0" -> "Sea level"
"1" -> "Below sea level"
_ -> "unknown " ++ s