packages feed

hsexif 0.4.0.0 → 0.4.0.1

raw patch · 3 files changed

+68/−33 lines, 3 filesPVP: minor bump suggested

API additions: PVP suggests at least a minor version bump

API changes (from Hackage documentation)

+ Graphics.HsExif: readGpsLatitudeLongitude :: Map ExifTag ExifValue -> Maybe (Double, Double)

Files

Graphics/HsExif.hs view
@@ -13,6 +13,7 @@ 	getOrientation, 	ImageOrientation(..), 	RotationDirection(..),+	readGpsLatitudeLongitude,  	-- * The ExifValue type 	ExifValue(..),@@ -442,37 +443,37 @@ gpsTagOffset		= exifIfd0Tag "gpsTagOffset" 0x8825 printImageMatching	= exifIfd0Tag "printImageMatching" 0xc4a5 -gpsVersionID	= exifGpsTag "gpsVersionID" 0x0000-gpsLatitudeRef	= exifGpsTag "gpsLatitudeRef" 0x0001-gpsLatitude	= exifGpsTag "gpsLatitude" 0x0002-gpsLongitudeRef	= exifGpsTag "gpsLongitudeRef" 0x0003-gpsLongitude	= exifGpsTag "gpsLongitude" 0x0004-gpsAltitudeRef	= exifGpsTag "gpsAltitudeRef" 0x0005-gpsAltitude	= exifGpsTag "gpsAltitude" 0x0006-gpsTimeStamp	= exifGpsTag "gpsTimeStamp" 0x0007-gpsSatellites	= exifGpsTag "gpsSatellites" 0x0008-gpsStatus	= exifGpsTag "gpsStatus" 0x0009-gpsMeasureMode	= exifGpsTag "gpsMeasureMode" 0x000a-gpsDop		= exifGpsTag "gpsDop" 0x000b-gpsSpeedRef	= exifGpsTag "gpsSpeedRef" 0x000c-gpsSpeed	= exifGpsTag "gpsSpeed" 0x000d-gpsTrackRef	= exifGpsTag "gpsTrackRef" 0x000e-gpsTrack	= exifGpsTag "gpsTrack" 0x000f-gpsImgDirectionRef= exifGpsTag "gpsImgDirectionRef" 0x0010-gpsImgDirection	= exifGpsTag "gpsImgDirection" 0x0011-gpsMapDatum	= exifGpsTag "gpsMapDatum" 0x0012-gpsDestLatitudeRef= exifGpsTag "gpsDestLatitudeRef" 0x0013-gpsDestLatitude	= exifGpsTag "gpsDestLatitude" 0x0014-gpsDestLongitudeRef= exifGpsTag "gpsDestLongitudeRef" 0x0015-gpsDestLongitude= exifGpsTag "gpsDestLongitude" 0x0016-gpsDestBearingRef= exifGpsTag "gpsDestBearingRef" 0x0017-gpsDestBearing	= exifGpsTag "gpsDestBearing" 0x0018-gpsDestDistanceRef= exifGpsTag "gpsDestDistanceRef" 0x0019-gpsDestDistance	= exifGpsTag "gpsDestDistance" 0x001a-gpsProcessingMethod= exifGpsTag "gpsProcessingMethod" 0x001b-gpsAreaInformation= exifGpsTag "gpsAreaInformation" 0x001c-gpsDateStamp	= exifGpsTag "gpsDateStamp" 0x001d-gpsDifferential	= exifGpsTag "gpsDifferential" 0x001e+gpsVersionID		= exifGpsTag "gpsVersionID" 0x0000+gpsLatitudeRef		= exifGpsTag "gpsLatitudeRef" 0x0001+gpsLatitude		= exifGpsTag "gpsLatitude" 0x0002+gpsLongitudeRef		= exifGpsTag "gpsLongitudeRef" 0x0003+gpsLongitude		= exifGpsTag "gpsLongitude" 0x0004+gpsAltitudeRef		= exifGpsTag "gpsAltitudeRef" 0x0005+gpsAltitude		= exifGpsTag "gpsAltitude" 0x0006+gpsTimeStamp		= exifGpsTag "gpsTimeStamp" 0x0007+gpsSatellites		= exifGpsTag "gpsSatellites" 0x0008+gpsStatus		= exifGpsTag "gpsStatus" 0x0009+gpsMeasureMode		= exifGpsTag "gpsMeasureMode" 0x000a+gpsDop			= exifGpsTag "gpsDop" 0x000b+gpsSpeedRef		= exifGpsTag "gpsSpeedRef" 0x000c+gpsSpeed		= exifGpsTag "gpsSpeed" 0x000d+gpsTrackRef		= exifGpsTag "gpsTrackRef" 0x000e+gpsTrack		= exifGpsTag "gpsTrack" 0x000f+gpsImgDirectionRef	= exifGpsTag "gpsImgDirectionRef" 0x0010+gpsImgDirection		= exifGpsTag "gpsImgDirection" 0x0011+gpsMapDatum		= exifGpsTag "gpsMapDatum" 0x0012+gpsDestLatitudeRef	= exifGpsTag "gpsDestLatitudeRef" 0x0013+gpsDestLatitude		= exifGpsTag "gpsDestLatitude" 0x0014+gpsDestLongitudeRef	= exifGpsTag "gpsDestLongitudeRef" 0x0015+gpsDestLongitude	= exifGpsTag "gpsDestLongitude" 0x0016+gpsDestBearingRef	= exifGpsTag "gpsDestBearingRef" 0x0017+gpsDestBearing		= exifGpsTag "gpsDestBearing" 0x0018+gpsDestDistanceRef	= exifGpsTag "gpsDestDistanceRef" 0x0019+gpsDestDistance		= exifGpsTag "gpsDestDistance" 0x001a+gpsProcessingMethod	= exifGpsTag "gpsProcessingMethod" 0x001b+gpsAreaInformation	= exifGpsTag "gpsAreaInformation" 0x001c+gpsDateStamp		= exifGpsTag "gpsDateStamp" 0x001d+gpsDifferential		= exifGpsTag "gpsDifferential" 0x001e  allExifTags :: [ExifTag] allExifTags = [exposureTime, fnumber, exposureProgram, isoSpeedRatings,@@ -611,7 +612,6 @@ 			\byteAlign components -> liftM ExifRationalList $ readManyInternal byteAlign components 	} --- ascii string is special for now. valueHandlers :: [ValueHandler] valueHandlers = 	[@@ -749,6 +749,29 @@ 		ExifNumber 7 -> Just $ MirrorRotation Ninety 		ExifNumber 8 -> Just $ Rotation Ninety 		_ -> Nothing++-- | Extract the GPS latitude and longitude where the picture was taken+-- (if it is present in the EXIF)+readGpsLatitudeLongitude :: Map ExifTag ExifValue -> Maybe (Double, Double)+readGpsLatitudeLongitude exifData = do+	(ExifText latRef) <- Map.lookup gpsLatitudeRef exifData+	latDec <- liftM gpsDecodeToDecimalDegrees $ Map.lookup gpsLatitude exifData+	let signedLatDec = case latRef of+		"S" -> -latDec+		_ -> latDec+	(ExifText longRef) <- Map.lookup gpsLongitudeRef exifData+	longDec <- liftM gpsDecodeToDecimalDegrees $ Map.lookup gpsLongitude exifData+	let signedLongDec = case longRef of+		"W" -> -longDec+		_ -> longDec+	return (signedLatDec, signedLongDec)++gpsDecodeToDecimalDegrees :: ExifValue -> Double+gpsDecodeToDecimalDegrees (ExifRationalList intPairs) = floatings !! 0 + floatings !! 1 / 60 + floatings !! 2 / 3600+	where+		floatings = fmap (uncurry intsToFloating) intPairs+		intsToFloating n d = (fromIntegral n) / (fromIntegral d)+gpsDecodeToDecimalDegrees _ = error "gpsDecodeToDecimalDegrees not called on a rational list!?" -- no way to prevent this at compile time???  -- $intro --
hsexif.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/  name:                hsexif-version:             0.4.0.0+version:             0.4.0.1 synopsis:            EXIF handling library in pure Haskell description:         The hsexif library provides functions for working with EXIF data                      contained in JPEG files. Currently it only supports reading the data.
tests/Tests.hs view
@@ -16,8 +16,10 @@ 	imageContents <- B.readFile "tests/test.jpg" 	noExif <- B.readFile "tests/noexif.jpg" 	png <- B.readFile "tests/test.png"+	gps <- B.readFile "tests/gps.jpg" 	let parseExifCorrect = (\(Right x) -> x) . parseExif 	let exifData = parseExifCorrect imageContents+	let gpsExifData = parseExifCorrect gps 	hspec $ do 		describe "not a JPG" $ testNotAJpeg png 		describe "no EXIF" $ testNoExif noExif@@ -25,6 +27,7 @@ 		describe "extract picture date" $ testDate exifData 		describe "image orientation" $ testOrientation exifData 		describe "read exif date time" $ testReadExifDateTime+		describe "read GPS lat long" $ testReadGpsLatLong gpsExifData  testNotAJpeg :: B.ByteString -> Spec testNotAJpeg imageContents = it "returns empty list if not a JPEG" $@@ -108,5 +111,14 @@ 	assertEqual' (Just $ LocalTime (fromGregorian 2013 10 2) (TimeOfDay 20 33 33)) (readExifDateTime "2013:10:02 20:33:33") 	assertEqual' Nothing (readExifDateTime "2013:10:02 20:33:3") +testReadGpsLatLong :: Map ExifTag ExifValue -> Spec+testReadGpsLatLong exifData = it "reads gps latitude longitude" $ do+	let (Just (lat,long)) = readGpsLatitudeLongitude exifData+	assertBool' $ 50.2179 < lat && 50.2180 > lat+	assertBool' $ -5.031 > long && -5.032 < long + assertEqual' :: (Show a, Eq a) => a -> a -> Assertion assertEqual' = assertEqual "doesn't match"++assertBool' :: Bool -> Assertion+assertBool' = assertBool "doesn't match"