massiv-io 0.1.2.0 → 0.1.3.0
raw patch · 6 files changed
+74/−61 lines, 6 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- massiv-io.cabal +1/−1
- src/Data/Massiv/Array/IO.hs +29/−28
- src/Data/Massiv/Array/IO/Base.hs +7/−2
- src/Data/Massiv/Array/IO/Image.hs +15/−10
- src/Data/Massiv/Array/IO/Image/JuicyPixels.hs +4/−4
- src/Data/Massiv/Array/IO/Image/Netpbm.hs +18/−16
massiv-io.cabal view
@@ -1,5 +1,5 @@ name: massiv-io-version: 0.1.2.0+version: 0.1.3.0 synopsis: Import/export of Image files into massiv Arrays description: This package contains functionality for import/export of arrays into the real world. For now it only has the ability to read/write
src/Data/Massiv/Array/IO.hs view
@@ -14,26 +14,29 @@ -- Stability : experimental -- Portability : non-portable ---module Data.Massiv.Array.IO (- -- * Reading- readArray, readImage, readImageAuto,+module Data.Massiv.Array.IO+ ( -- * Reading+ readArray+ , readImage+ , readImageAuto -- * Writing- writeArray ,writeImage, writeImageAuto,+ , writeArray+ , writeImage+ , writeImageAuto -- * Displaying- ExternalViewer(..),- displayImage,- displayImageUsing,- displayImageFile,+ , ExternalViewer(..)+ , displayImage+ , displayImageUsing+ , displayImageFile -- ** Common viewers- defaultViewer,- eogViewer,- gpicviewViewer,- fehViewer,- gimpViewer,+ , defaultViewer+ , eogViewer+ , gpicviewViewer+ , fehViewer+ , gimpViewer -- * Supported Image Formats- module Data.Massiv.Array.IO.Base,- module Data.Massiv.Array.IO.Image-+ , module Data.Massiv.Array.IO.Base+ , module Data.Massiv.Array.IO.Image -- $supported ) where @@ -55,6 +58,9 @@ import System.IO (hClose, openBinaryTempFile) import System.Process (readProcess) +++ -- | External viewing application to use for displaying images. data ExternalViewer = ExternalViewer FilePath [String] Int@@ -130,13 +136,12 @@ --- | Inverse of the 'readImage', but similarly to it, will guess an output file format from the file--- extension and will write to file any image with the colorspace that is supported by that--- format. Precision of the image might be adjusted using `Elevator` if precision of the source--- array is not supported by the image file format. For instance, <'Image' @r@ 'RGBA' 'Double'>--- being saved as 'PNG' file would be written as <'Image' @r@ 'RGBA' 'Word16'>, thus using highest--- supported precision 'Word16' for that format. If automatic colors space is also desired,--- `writeImageAuto` can be used instead.+-- | This function will guess an output file format from the file extension and will write to file+-- any image with the colorspace that is supported by that format. Precision of the image might be+-- adjusted using `Elevator` if precision of the source array is not supported by the image file+-- format. For instance an @(`Image` r `RGBA` `Double`)@ being saved as `PNG` file would be written as+-- @(`Image` r `RGBA` `Word16`)@, thus using highest supported precision `Word16` for that+-- format. If automatic colors space is also desired, `writeImageAuto` can be used instead. -- -- Can throw `ConvertError`, `EncodeError` and other usual IO errors. --@@ -145,7 +150,7 @@ writeImage path = BL.writeFile path . encodeImage imageWriteFormats path -+-- | Write an image to file while performing all necessary precisiona and color space conversions. writeImageAuto :: ( Source r Ix2 (Pixel cs e) , ColorSpace cs e@@ -161,10 +166,6 @@ -- | An image is written as a @.tiff@ file into an operating system's temporary -- directory and passed as an argument to the external viewer program.--- displayImageUsing :: Writable (Auto TIF) (Image r cs e) =>--- ExternalViewer -- ^ Image viewer program--- -> Bool -- ^ Should a call block the cuurrent thread untul viewer is closed.--- -> Image r cs e -> IO () displayImageUsing :: Writable (Auto TIF) (Image r cs e) => ExternalViewer -- ^ Image viewer program -> Bool -- ^ Should a call block the cuurrent thread untul viewer is closed.
src/Data/Massiv/Array/IO/Base.hs view
@@ -1,8 +1,10 @@ {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-} -- | -- Module : Data.Massiv.Array.IO.Base -- Copyright : (c) Alexey Kuleshevich 2018@@ -29,11 +31,11 @@ , convertEither ) where -import Control.Exception (throw, Exception)-import Data.Massiv.Array (Array, Ix2)+import Control.Exception (Exception, throw) import qualified Data.ByteString as B (ByteString) import qualified Data.ByteString.Lazy as BL (ByteString) import Data.Default (Default (..))+import Data.Massiv.Array import Data.Maybe (fromMaybe) import Data.Typeable import Graphics.ColorSpace (ColorSpace, Pixel)@@ -105,7 +107,9 @@ type WriteOptions (Auto f) = WriteOptions f ext (Auto f) = ext f+ exts (Auto f) = exts f + -- | File formats that can be read into an Array. class Readable f arr where @@ -182,3 +186,4 @@ showsTypeRep (typeRep (Proxy :: Proxy e)) ">")) Right (conv eImg)+
src/Data/Massiv/Array/IO/Image.hs view
@@ -52,12 +52,14 @@ instance Writable (Encode (Image r cs e)) (Image r cs e) where encode (EncodeAs f) _ = encode f (defaultWriteOptions f) -+-- | Encode an image into a lazy `BL.ByteString`, while selecting the appropriate format from the+-- file extension. encodeImage :: (Source r Ix2 (Pixel cs e), ColorSpace cs e)- => [Encode (Image r cs e)]- -> FilePath- -> Image r cs e+ => [Encode (Image r cs e)] -- ^ List of image formats to choose from (useful lists are+ -- `imageWriteFormats` and `imageWriteAutoFormats`+ -> FilePath -- ^ File name with extension, so the format can be inferred+ -> Image r cs e -- ^ Image to encode -> BL.ByteString encodeImage formats path img = do let ext' = P.map toLower . takeExtension $ path@@ -65,7 +67,7 @@ [] -> throw $ EncodeError $ "File format is not supported: " ++ ext' (f:_) -> encode f () img -+-- | List of image formats that can be encoded without any color space conversion. imageWriteFormats :: (Source r Ix2 (Pixel cs e), ColorSpace cs e) => [Encode (Image r cs e)] imageWriteFormats = [ EncodeAs BMP@@ -77,6 +79,7 @@ , EncodeAs TIF ] +-- | List of image formats that can be encoded with any necessary color space conversions. imageWriteAutoFormats :: ( Source r Ix2 (Pixel cs e) , ColorSpace cs e@@ -112,12 +115,13 @@ instance Readable (Decode (Image r cs e)) (Image r cs e) where decode (DecodeAs f) _ = decode f (defaultReadOptions f) -+-- | Decode an image from the strict `ByteString` while inferring format the image is encoded in+-- from the file extension decodeImage :: (Source r Ix2 (Pixel cs e), ColorSpace cs e)- => [Decode (Image r cs e)]- -> FilePath- -> B.ByteString+ => [Decode (Image r cs e)] -- ^ List of available formats to choose from+ -> FilePath -- ^ File name with extension, so format can be inferred+ -> B.ByteString -- ^ Encoded image -> Image r cs e decodeImage formats path bs = do let ext' = P.map toLower . takeExtension $ path@@ -125,7 +129,7 @@ [] -> throw $ DecodeError $ "File format is not supported: " ++ ext' (f:_) -> decode f () bs -+-- | List of image formats decodable with no colorspace conversion imageReadFormats :: (Source S Ix2 (Pixel cs e), ColorSpace cs e) => [Decode (Image S cs e)]@@ -142,6 +146,7 @@ , DecodeAs PPM ] +-- | List of image formats decodable with no colorspace conversion imageReadAutoFormats :: (Mutable r Ix2 (Pixel cs e), ColorSpace cs e) => [Decode (Image r cs e)]
src/Data/Massiv/Array/IO/Image/JuicyPixels.hs view
@@ -76,7 +76,7 @@ import Control.Exception import Control.Monad (guard, msum) import Data.Bifunctor-import qualified Data.ByteString as B (ByteString)+import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as BL (ByteString) import Data.Default (Default (..)) import Data.Massiv.Array as M@@ -84,6 +84,7 @@ import Data.Massiv.Array.Manifest.Vector import Data.Typeable import qualified Data.Vector.Storable as V+import Foreign.Storable (Storable (sizeOf)) import Graphics.ColorSpace -------------------------------------------------------------------------------- -- BMP Format ------------------------------------------------------------------@@ -962,11 +963,10 @@ -- General decoding and helper functions --- | TODO: Validate size-fromJPImageUnsafe :: (Storable (Pixel cs e), JP.Pixel jpx) =>+fromJPImageUnsafe :: forall jpx cs e . (Storable (Pixel cs e), JP.Pixel jpx) => JP.Image jpx -> Maybe (Image S cs e) fromJPImageUnsafe (JP.Image n m !v) = do- guard (n * m /= V.length v)+ guard (n * m * sizeOf (undefined :: Pixel cs e) == V.length v) return $ fromVector Seq (m :. n) $ V.unsafeCast v {-# INLINE fromJPImageUnsafe #-}
src/Data/Massiv/Array/IO/Image/Netpbm.hs view
@@ -109,6 +109,7 @@ instance FileFormat PPM where ext _ = ".ppm"+ exts _ = [".ppm", ".pnm"] instance FileFormat (Sequence PPM) where type WriteOptions (Sequence PPM) = WriteOptions PPM@@ -160,12 +161,11 @@ {-# INLINE decodePPM #-} --- | TODO: validate sizes fromNetpbmImageUnsafe :: (Storable a, Storable (Pixel cs e))- => (Int, Int) -> V.Vector a -> Maybe (Image S cs e)-fromNetpbmImageUnsafe (m, n) v = do- guard (n * m /= V.length v)+ => Int -> Int -> V.Vector a -> Maybe (Image S cs e)+fromNetpbmImageUnsafe m n v = do+ guard (n * m == V.length v) return $ fromVector Seq (m :. n) $ V.unsafeCast v @@ -184,34 +184,36 @@ :: forall cs e . (ColorSpace cs e, V.Storable (Pixel cs e)) => Netpbm.PPM -> Maybe (Image S cs e) fromNetpbmImage Netpbm.PPM {..} = do- let sz = (ppmHeight ppmHeader, ppmWidth ppmHeader)+ let m = ppmHeight ppmHeader+ n = ppmWidth ppmHeader case ppmData of PbmPixelData v -> do Refl <- eqT :: Maybe (Pixel cs e :~: Pixel X Bit)- fromNetpbmImageUnsafe sz v+ fromNetpbmImageUnsafe m n v PgmPixelData8 v -> do Refl <- eqT :: Maybe (Pixel cs e :~: Pixel Y Word8)- fromNetpbmImageUnsafe sz v+ fromNetpbmImageUnsafe m n v PgmPixelData16 v -> do Refl <- eqT :: Maybe (Pixel cs e :~: Pixel Y Word16)- fromNetpbmImageUnsafe sz v+ fromNetpbmImageUnsafe m n v PpmPixelDataRGB8 v -> do Refl <- eqT :: Maybe (Pixel cs e :~: Pixel RGB Word8)- fromNetpbmImageUnsafe sz v+ fromNetpbmImageUnsafe m n v PpmPixelDataRGB16 v -> do Refl <- eqT :: Maybe (Pixel cs e :~: Pixel RGB Word16)- fromNetpbmImageUnsafe sz v+ fromNetpbmImageUnsafe m n v fromNetpbmImageAuto :: forall cs e r . (Mutable r Ix2 (Pixel cs e), ColorSpace cs e, V.Storable (Pixel cs e)) => Netpbm.PPM -> Maybe (Image r cs e) fromNetpbmImageAuto Netpbm.PPM {..} = do- let sz = (ppmHeight ppmHeader, ppmWidth ppmHeader)+ let m = ppmHeight ppmHeader+ n = ppmWidth ppmHeader case ppmData of PbmPixelData v ->- (fromNetpbmImageUnsafe sz v :: Maybe (Image S X Bit)) >>= (toAnyCS . M.map fromPixelBinary)+ (fromNetpbmImageUnsafe m n v :: Maybe (Image S X Bit)) >>= (toAnyCS . M.map fromPixelBinary) PgmPixelData8 v ->- (fromNetpbmImageUnsafe sz v :: Maybe (Image S Y Word8)) >>= toAnyCS+ (fromNetpbmImageUnsafe m n v :: Maybe (Image S Y Word8)) >>= toAnyCS PgmPixelData16 v ->- (fromNetpbmImageUnsafe sz v :: Maybe (Image S Y Word16)) >>= toAnyCS+ (fromNetpbmImageUnsafe m n v :: Maybe (Image S Y Word16)) >>= toAnyCS PpmPixelDataRGB8 v ->- (fromNetpbmImageUnsafe sz v :: Maybe (Image S RGB Word8)) >>= toAnyCS+ (fromNetpbmImageUnsafe m n v :: Maybe (Image S RGB Word8)) >>= toAnyCS PpmPixelDataRGB16 v ->- (fromNetpbmImageUnsafe sz v :: Maybe (Image S RGB Word16)) >>= toAnyCS+ (fromNetpbmImageUnsafe m n v :: Maybe (Image S RGB Word16)) >>= toAnyCS