@@ -53,7 +53,8 @@ imageType :: ByteString -> Maybe ImageType
5353imageType img = case B.take 4 img of
5454 "\x89\x50\x4e\x47" -> return Png
5555 "\x47\x49\x46\x38" -> return Gif
56− "\xff\xd8\xff\xe0" -> return Jpeg
56+ "\xff\xd8\xff\xe0" -> return Jpeg -- JFIF
57+ "\xff\xd8\xff\xe1" -> return Jpeg -- Exif
5758 "%PDF" -> return Pdf
5859 "%!PS"
5960 | (B.take 4 $ B.drop 1 $ B.dropWhile (/=' ') img) == "EPSF"
@@ -139,8 +140,14 @@ gifSize img = do
139140jpegSize :: ByteString -> Maybe ImageSize
140141jpegSize img = do
141142 let (hdr, rest) = B.splitAt 4 img
142− guard $ hdr == "\xff\xd8\xff\xe0"
143143 guard $ B.length rest >= 14
144+ case hdr of
145+ "\xff\xd8\xff\xe0" -> jfifSize rest
146+ "\xff\xd8\xff\xe1" -> exifSize rest
147+ _ -> mzero
148+
149+jfifSize :: ByteString -> Maybe ImageSize
150+jfifSize rest = do
144151 let [dpiDensity,dpix1,dpix2,dpiy1,dpiy2] = map fromIntegral
145152 $ unpack $ B.take 5 $ B.drop 9 $ rest
146153 let factor = case dpiDensity of
@@ -149,11 +156,11 @@ jpegSize img = do
149156 _ -> const 72
150157 let dpix = factor (shift dpix1 8 + dpix2)
151158 let dpiy = factor (shift dpiy1 8 + dpiy2)
152− (w,h) <- findJpegSize rest
159+ (w,h) <- findJfifSize rest
153160 return $ ImageSize { pxX = w, pxY = h, dpiX = dpix, dpiY = dpiy }
154161
155−findJpegSize :: ByteString -> Maybe (Integer,Integer)
156−findJpegSize bs = do
162+findJfifSize :: ByteString -> Maybe (Integer,Integer)
163+findJfifSize bs = do
157164 let bs' = B.dropWhile (=='\xff') $ B.dropWhile (/='\xff') bs
158165 case B.uncons bs' of
159166 Just (c,bs'') | c >= '\xc0' && c <= '\xc3' -> do
@@ -165,8 +172,23 @@ findJpegSize bs = do
165172 [c1,c2] -> do
166173 let len = shift c1 8 + c2
167174 -- skip variables
168− findJpegSize $ B.drop len bs''
175+ findJfifSize $ B.drop len bs''
169176 _ -> fail "JPEG parse error"
170177 Nothing -> fail "Did not find length record"
171178
179+exifSize :: ByteString -> Maybe ImageSize
180+exifSize rest = do
181+ let bs' = B.takeWhile (/='\xff') $ B.drop 8 rest -- exif data
182+ let (_,bs'') = B.breakSubstring "\xa0\x02" bs' -- width
183+ let rawWidth = B.take 2 $ B.drop 10 bs''
184+ let (_,bs''') = B.breakSubstring "\xa0\x03" bs' -- height
185+ let rawHeight = B.take 2 $ B.drop 10 bs'''
186+ let tonum bs = case map fromIntegral $ unpack bs of
187+ [x,y] -> Just $ shift x 8 + y
188+ _ -> Nothing
189+ case (tonum rawWidth, tonum rawHeight) of
190+ (Just w, Just h) ->
191+ return $ ImageSize { pxX = w, pxY = h, dpiX = 72, dpiY = 72 }
192+ _ -> fail "Could not determine exif image size"
193+ -- some day, figure out how to parse dpi from exif
172194