packages feed

hsexif 0.6.0.10 → 0.6.1.0

raw patch · 4 files changed

+86/−18 lines, 4 filesdep ~basePVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base

API changes (from Hackage documentation)

Files

Graphics/HsExif.hs view
@@ -185,13 +185,15 @@  getExif :: Get (Map ExifTag ExifValue) getExif = do-    header <- getWord16be-    unless (header == 0xffd8)-        $ fail "Not a JPEG file"-    findAndParseExifBlock+    firstBytes <- lookAhead $ (,) <$> getWord16be <*> getWord16be+    case firstBytes of+        (0xffd8,_ ) -> getWord16be >> findAndParseExifBlockJPEG+        (0x4d4d,42) -> findAndParseExifBlockNEF+        (0x4949,42) -> findAndParseExifBlockNEF+        _           -> fail "Not a JPEG or NEF file" -findAndParseExifBlock :: Get (Map ExifTag ExifValue)-findAndParseExifBlock = do+findAndParseExifBlockJPEG :: Get (Map ExifTag ExifValue)+findAndParseExifBlockJPEG = do     markerNumber <- getWord16be     dataSize <- fromIntegral . toInteger <$> getWord16be     case markerNumber of@@ -199,8 +201,11 @@         -- ffda is Start Of Stream => image         -- I expect no more EXIF data after this point.         0xffda -> fail "No EXIF in JPEG"-        _ -> skip (dataSize-2) >> findAndParseExifBlock+        _ -> skip (dataSize-2) >> findAndParseExifBlockJPEG +findAndParseExifBlockNEF :: Get (Map ExifTag ExifValue)+findAndParseExifBlockNEF = parseTiff+ data ByteAlign = Intel | Motorola  getWord16 :: ByteAlign -> Get Word16@@ -221,6 +226,10 @@     nul <- toInteger <$> getWord16be     unless (header == Char8.pack "Exif" && nul == 0)         $ fail "invalid EXIF header"+    parseTiff++parseTiff :: Get (Map ExifTag ExifValue)+parseTiff = do     tiffHeaderStart <- fromIntegral <$> bytesRead     byteAlign <- parseTiffHeader     let subIfdParse = parseSubIFD byteAlign tiffHeaderStart
hsexif.cabal view
@@ -1,5 +1,5 @@ name:                hsexif-version:             0.6.0.10+version:             0.6.1.0 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.@@ -11,7 +11,7 @@ -- copyright: category:            Graphics build-type:          Simple-extra-source-files:  tests/*.jpg tests/*.png+extra-source-files:  tests/*.jpg tests/*.png tests/*.NEF cabal-version:       >=1.10  Flag iconv
+ tests/RAW_NIKON_D1.NEF view

file too large to diff

tests/Tests.hs view
@@ -5,6 +5,7 @@ import qualified Data.ByteString.Lazy as B import qualified Data.ByteString as BS import Data.Text (Text)+import qualified Data.Text as T import qualified Data.Map as Map import Data.Map (Map) import Data.Time.LocalTime@@ -21,16 +22,18 @@ main = do     imageContents <- B.readFile "tests/test.jpg"     noExif <- B.readFile "tests/noexif.jpg"-    png <- B.readFile "tests/test.png"-    gps <- B.readFile "tests/gps.jpg"+    png  <- B.readFile "tests/test.png"+    gps  <- B.readFile "tests/gps.jpg"     gps2 <- B.readFile "tests/gps2.jpg"     gps3 <- B.readFile "tests/gps3.jpg"     partial <- B.readFile "tests/partial_exif.jpg"-    let parseExifM = hush . parseExif-    let exifData = parseExifM imageContents-    let gpsExifData = parseExifM gps+    tiff <- B.readFile "tests/RAW_NIKON_D1.NEF"+    let parseExifM   = hush . parseExif+    let exifData     = parseExifM imageContents+    let gpsExifData  = parseExifM gps     let gps2ExifData = parseExifM gps2     let gps3ExifData = parseExifM gps3+    let tiffExifData = parseExifM tiff     hspec $ do         describe "not a JPG" $ testNotAJpeg png         describe "no EXIF" $ testNoExif noExif@@ -46,10 +49,11 @@         describe "pretty printing" $ testPrettyPrint gpsExifData exifData gps2ExifData         describe "flash fired" $ testFlashFired exifData         describe "partial exif data" $ testPartialExif partial+        describe "tiff file" $ testNef tiffExifData  testNotAJpeg :: B.ByteString -> Spec testNotAJpeg imageContents = it "returns empty list if not a JPEG" $-    assertEqual' (Left "Not a JPEG file") (parseExif imageContents)+    assertEqual' (Left "Not a JPEG or NEF file") (parseExif imageContents)  testNoExif :: B.ByteString -> Spec testNoExif imageContents = it "returns empty list if no EXIF" $@@ -206,14 +210,69 @@ testPartialExif imageContents = it "parses a partial exif JPEG" $     assertEqual' (Right []) (Map.toList <$> parseExif imageContents) +testNef :: Maybe (Map ExifTag ExifValue) -> Spec+testNef Nothing = it "parses EXIF from a NEF file" $+                   assertBool "failed to parse EXIF from nef" False+testNef (Just exifMap) = it "parses EXIF from a NEF file" $ do+    let makerNoteV = Map.lookup makerNote exifMap >>= getUndefMaybe+    -- test only the length of the maker note+    assertEqual' (Just 394) (BS.length <$> makerNoteV)+    let cleanedExifMap = filter ((/=makerNote) . fst) (Map.toList exifMap)+    assertEqualListDebug+        (sort [(exposureTime, ExifRational 10 2500),+                (fnumber, ExifRational 76 10),+                (exposureProgram, ExifNumber 2),+                (dateTimeOriginal, ExifText "2000:11:19 13:01:50"),+                (dateTimeDigitized, ExifText "2000:11:19 13:01:50"),+                (exposureBiasValue, ExifRational 0 6),+                (maxApertureValue, ExifRational 30 10),+                (meteringMode, ExifNumber 5),+                (focalLength, ExifRational 200 10),+                (userComment, ExifUndefined $ BS.concat $ replicate 48 "\NUL"),+                (subSecTime, ExifText "24"),+                (subSecTimeOriginal, ExifText "24"),+                (subSecTimeDigitized, ExifText "24"),+                (sensingMethod, ExifNumber 2),+                (fileSource, ExifUndefined "\ETX"),+                (sceneType, ExifUndefined "\SOH"),+                (cfaPattern, ExifUndefined "\NUL\STX\NUL\STX\STX\SOH\SOH\NUL"),+                (ExifTag IFD0 Nothing 0xfe (T.pack . show), ExifNumber 1),+                (ExifTag IFD0 Nothing 0x100 (T.pack . show), ExifNumber 160),+                (ExifTag IFD0 Nothing 0x101 (T.pack . show), ExifNumber 120),+                (ExifTag IFD0 Nothing 0x102 (T.pack . show), ExifNumberList [8,8,8]),+                (ExifTag IFD0 Nothing 0x103 (T.pack . show), ExifNumber 1),+                (ExifTag IFD0 Nothing 0x106 (T.pack . show), ExifNumber 2),+                (imageDescription, ExifText "                               "),+                (make, ExifText "NIKON CORPORATION"),+                (model, ExifText "NIKON D1 "),+                (ExifTag IFD0 Nothing 0x111 (T.pack . show), ExifNumber 1280),+                (ExifTag IFD0 Nothing 0x115 (T.pack . show), ExifNumber 3),+                (ExifTag IFD0 Nothing 0x116 (T.pack . show), ExifNumber 120),+                (ExifTag IFD0 Nothing 0x117 (T.pack . show), ExifNumber 57600),+                (xResolution, ExifRational 300 1),+                (yResolution, ExifRational 300 1),+                (ExifTag IFD0 Nothing 0x11c (T.pack . show), ExifNumber 1),+                (resolutionUnit, ExifNumber 2),+                (software, ExifText "Ver.1.05\0"),+                (dateTime, ExifText "2000:11:19 13:01:50"),+                (ExifTag IFD0 Nothing 0x14a (T.pack . show), ExifNumber 58880),+                (referenceBlackWhite, ExifRationalList [(0,1),(255,1),(0,1),(255,1),(0,1),(255,1)]),+                (copyright, ExifText "Copyright,NIKON CORPORATION,1999\0"),+                (exifIfdOffset, ExifNumber 528),+                (ExifTag IFD0 Nothing 0x9003 (T.pack . show), ExifText "2000:11:19 13:01:50"),+                (ExifTag IFD0 Nothing 0x9216 (T.pack . show), ExifNumberList [1,0,0,0])+              ])+        (sort cleanedExifMap)+ assertEqualListDebug :: (Show a, Eq a) => [a] -> [a] -> Assertion assertEqualListDebug = assertEqualListDebug' (0 :: Int)     where         assertEqualListDebug' idx (x:xs) (y:ys) = do-            assertEqual ("index " ++ show idx ++ " differs: " ++ show x ++ " /= " ++ show y) x y+            assertEqual ("lengths are off by " ++ show (length ys - length xs) +++                         "; index " ++ show idx ++ " differs: " ++ show x ++ " /= " ++ show y) x y             assertEqualListDebug' (idx+1) xs ys-        assertEqualListDebug' _ (x:_) [] = assertBool ("List lengths differ, expected " ++ show x) False-        assertEqualListDebug' _ [] (y:_) = assertBool ("List lengths differ, got " ++ show y) False+        assertEqualListDebug' _ (x:r) [] = assertBool ("List lengths differ by " ++ show (length r) ++ ", expected " ++ show x) False+        assertEqualListDebug' _ [] (y:r) = assertBool ("List lengths differ by " ++ show (length r) ++ ", got " ++ show y) False         assertEqualListDebug' _ [] [] = assertBool "" True  assertEqual' :: (Show a, Eq a) => a -> a -> Assertion