packages feed

imagesize-conduit (empty) → 0.2.0

raw patch · 8 files changed

+186/−0 lines, 8 filesdep +HUnitdep +basedep +bytestringsetup-changedbinary-added

Dependencies added: HUnit, base, bytestring, conduit, hspec, imagesize-conduit

Files

+ Data/Conduit/ImageSize.hs view
@@ -0,0 +1,89 @@+{-# LANGUAGE OverloadedStrings #-}+module Data.Conduit.ImageSize+    ( sinkImageSize+    , Size (..)+    ) where++import qualified Data.ByteString.Lazy as L+import qualified Data.Conduit as C+import qualified Data.Conduit.Binary as CB+import qualified Data.ByteString as S+import Data.ByteString.Char8 ()+import Data.ByteString.Lazy.Char8 ()+import Control.Applicative ((<$>), (<*>))++data Size = Size { width :: Int, height :: Int }+    deriving (Show, Eq, Ord, Read)++sinkImageSize :: C.Resource m => C.Sink S.ByteString m (Maybe Size)+sinkImageSize =+    C.SinkData (pushHeader id) close+  where+    close = return Nothing+    pushHeader front bs'+        | S.length bs >= 11 && S.take 5 (S.drop 6 bs) ==+            S.pack [0x4A, 0x46, 0x49, 0x46, 0x00] =+                C.sinkPush jpg $ S.drop 4 bs+        | S.length bs >= 6 && S.take 6 bs `elem` gifs =+            C.sinkPush gif $ S.drop 6 bs+        | S.length bs >= 8 && S.take 8 bs == S.pack [137, 80, 78, 71, 13, 10, 26, 10] =+            C.sinkPush png $ S.drop 8 bs+        | S.length bs < 11 = do+            return $ C.Processing (pushHeader $ S.append bs) close+        | otherwise = do+            return $ C.Done (Just bs) Nothing+      where+        bs = front bs'++    gifs = ["GIF87a", "GIF89a"]+    gif = do+        b <- CB.take 4+        let go x y = fromIntegral x + (fromIntegral y) * 256+        return $ case L.unpack b of+            [w1, w2, h1, h2] -> Just $ Size (go w1 w2) (go h1 h2)+            _ -> Nothing++    png = do+        _ <- CB.take 4 -- FIXME drop+        hdr <- CB.take 4+        if hdr == "IHDR"+            then do+                mw <- getInt 4 0+                mh <- getInt 4 0+                return $ Size <$> mw <*> mh+            else return Nothing+++    jpg = do+        mi <- getInt 2 0+        case mi of+            Nothing -> return Nothing+            Just i -> do+                _ <- CB.take $ i - 2+                jpgFrame++    jpgFrame = do+        mx <- CB.head+        case mx of+            Just 255 -> do+                my <- CB.head+                case my of+                    Just 0xC0 -> do+                        _ <- CB.take 3+                        h <- getInt 2 0+                        w <- getInt 2 0+                        return $ Size <$> w <*> h+                    Just _ -> jpg+                    Nothing -> return Nothing+            _ -> return Nothing++getInt :: (C.Resource m, Integral i)+       => Int+       -> i+       -> C.Sink S.ByteString m (Maybe i)+getInt 0 i = return $ Just i+getInt len i = do+    mx <- CB.head+    case mx of+        Nothing -> return Nothing+        Just x -> getInt (len - 1) (i * 256 + fromIntegral x)
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c)2011, Michael Snoyman++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Michael Snoyman nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.lhs view
@@ -0,0 +1,7 @@+#!/usr/bin/env runhaskell++> module Main where+> import Distribution.Simple++> main :: IO ()+> main = defaultMain
+ imagesize-conduit.cabal view
@@ -0,0 +1,39 @@+Name:                imagesize-conduit+Version:             0.2.0+Synopsis:            Determine the size of some common image formats.+Description:         Currently supports PNG, GIF, and JPEG. This package provides a Sink that will consume the minimum number of bytes necessary to determine the image dimensions.+License:             BSD3+License-file:        LICENSE+Author:              Michael Snoyman+Maintainer:          michael@snoyman.com+Category:            Graphics, Conduit+Build-type:          Simple+Cabal-version:       >=1.8+Homepage:            http://github.com/snoyberg/conduit+extra-source-files:  test/main.hs+                     test/logo.png+                     test/logo.gif+                     test/logo.jpg++Library+  Exposed-modules:     Data.Conduit.ImageSize+  Build-depends:       base                     >= 4            && < 5+                     , conduit                  >= 0.2          && < 0.3+                     , bytestring               >= 0.9+  ghc-options:     -Wall++test-suite test+    hs-source-dirs: test+    main-is: main.hs+    type: exitcode-stdio-1.0+    build-depends:   conduit+                   , imagesize-conduit+                   , base+                   , hspec+                   , HUnit+                   , bytestring+    ghc-options:     -Wall++source-repository head+  type:     git+  location: git://github.com/snoyberg/conduit.git
+ test/logo.gif view

binary file changed (absent → 3633 bytes)

+ test/logo.jpg view

binary file changed (absent → 10825 bytes)

+ test/logo.png view

binary file changed (absent → 10661 bytes)

+ test/main.hs view
@@ -0,0 +1,21 @@+{-# LANGUAGE OverloadedStrings #-}+import qualified Data.Conduit as C+import qualified Data.Conduit.Binary as CB+import Data.Conduit.ImageSize++import Test.Hspec.Monadic+import Test.Hspec.HUnit ()+import Test.HUnit++main :: IO ()+main = hspecX $ do+    describe "image size" $ do+        it "png" $ check (Just $ Size 271 61) "test/logo.png"+        it "jpg" $ check (Just $ Size 271 61) "test/logo.jpg"+        it "gif" $ check (Just $ Size 271 61) "test/logo.gif"+        it "invalid" $ check Nothing "test/main.hs"++check :: Maybe Size -> FilePath -> Assertion+check ex fp = do+    size <- C.runResourceT $ CB.sourceFile fp C.$$ sinkImageSize+    size @?= ex