packages feed

massiv-io 0.4.0.0 → 0.4.1.0

raw patch · 13 files changed

+368/−267 lines, 13 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Data.Massiv.Array.IO: [Decode] :: FileFormat f => f -> (forall m. MonadThrow m => f -> ByteString -> m out) -> Decode out
+ Data.Massiv.Array.IO: [Encode] :: FileFormat f => f -> (forall m. MonadThrow m => f -> out -> m ByteString) -> Encode out
+ Data.Massiv.Array.IO: class Default a
+ Data.Massiv.Array.IO: coerceBinaryImage :: Array S Ix2 (Pixel X Bit) -> Array S Ix2 (Pixel X Word8)
+ Data.Massiv.Array.IO: decodeAdhocM :: MonadThrow m => Decode out -> ByteString -> m out
+ Data.Massiv.Array.IO: def :: Default a => a
+ Data.Massiv.Array.IO: displayImageUsingAdhoc :: MonadIO m => ExternalViewer -> Bool -> Encode img -> img -> m ()
+ Data.Massiv.Array.IO: encodeAdhocM :: MonadThrow m => Encode out -> out -> m ByteString
+ Data.Massiv.Array.IO: readableAdhoc :: Readable f out => f -> Decode out
+ Data.Massiv.Array.IO: selectFileFormat :: (FileFormat f, MonadThrow m) => [f] -> FilePath -> m f
+ Data.Massiv.Array.IO: writableAdhoc :: Writable f out => f -> Encode out

Files

CHANGELOG.md view
@@ -1,3 +1,15 @@+# 0.4.1++* Reexport `Default` class.+* Add support for massiv-0.6+* Expose `Encode` and `Decode` cosntructors+* Add `encodeAdhocM` and `decodeAdhocM`+* Add `writableAdhoc` and `readableAdhoc`+* Add `displayImageUsingAdhoc`+* Add `coerceBinaryImage`+* Add instance for writing binary images: `Image S X Bit` without conversions.+* Add `selectFileFormat`+ # 0.4.0  * Adjust insatnces to account for changes in `Color-0.3.0`, namely improvements to Luma
massiv-io.cabal view
@@ -1,5 +1,5 @@ name:                massiv-io-version:             0.4.0.0+version:             0.4.1.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
@@ -31,6 +31,7 @@   , ExternalViewer(..)   , displayImage   , displayImageUsing+  , displayImageUsingAdhoc   , displayImageFile   -- ** Common viewers   , defaultViewer@@ -53,8 +54,10 @@                                           DecodeError(..), EncodeError(..),                                           FileFormat(..), MonadThrow(..),                                           Readable(..), Sequence(..),-                                          Writable(..), convertEither,-                                          convertImage, decode', decodeError,+                                          Writable(..), Default(..),+                                          convertEither,+                                          convertImage, coerceBinaryImage,+                                          decode', decodeError,                                           defaultWriteOptions,                                           demoteLumaAlphaImage, demoteLumaImage,                                           encode', encodeError,@@ -67,11 +70,11 @@ import Graphics.Pixel.ColorSpace import Prelude import Prelude as P hiding (readFile, writeFile)-import System.FilePath ((</>))+import System.FilePath ((</>), (<.>)) import System.IO (IOMode(..), hClose, openBinaryTempFile) import UnliftIO.Concurrent (forkIO) import UnliftIO.Directory (createDirectoryIfMissing, getTemporaryDirectory)-import UnliftIO.Exception (bracket)+import UnliftIO.Exception (catchAny, bracket) import UnliftIO.IO.File import UnliftIO.Process (readProcess) @@ -262,16 +265,37 @@           -- closed. Supplying `False` is only safe in the ghci session.   -> Image r cs e -- ^ Image to display   -> m ()-displayImageUsing viewer block img =+displayImageUsing viewer block =+  displayImageUsingAdhoc  viewer block (writableAdhoc (Auto TIF))+++-- | Encode an image using an adhoc into an operating system's temporary+-- directory and passed as an argument to the external viewer program.+--+-- @since 4.1.0+displayImageUsingAdhoc ::+     MonadIO m+  => ExternalViewer -- ^ Image viewer program+  -> Bool -- ^ Should this function block the current thread until viewer is+          -- closed. Supplying `False` is only safe in the ghci session.+  -> Encode img+  -> img -- ^ Image to display+  -> m ()+displayImageUsingAdhoc viewer block adhoc img =   liftIO $ do-    bs <- encodeM (Auto TIF) () img-    (if block then id else void . forkIO) $ display bs+    bs <- encodeAdhocM adhoc img+    -- this function is meant to be used in ghci, therefore it is ok to not cleanup+    -- dangling threads after display is called.+    (if block then id else void . forkIO . reportErrors) $ display bs   where+    reportErrors action =+      catchAny action $ \ exc ->+        putStrLn $ "<displayImageUsingAdhoc>: Failed with: " <> displayException exc     display bs = do       tmpDir <- fmap (</> "massiv-io") getTemporaryDirectory       createDirectoryIfMissing True tmpDir       bracket-        (openBinaryTempFile tmpDir "tmp-img.tiff")+        (openBinaryTempFile tmpDir ("tmp-img" <.> ext adhoc))         (hClose . snd)         (\(imgPath, imgHandle) -> do            BL.hPut imgHandle bs@@ -355,7 +379,7 @@  * 'BMP': -    * __read__: ('PixelY' 'Word8'), ('PixelRGB' 'Word8'), ('PixelRGBA' 'Word8')+    * __read__: ('PixelX' 'Bit'), ('PixelY' 'Word8'), ('PixelRGB' 'Word8'), ('PixelRGBA' 'Word8')     * __write__: ('PixelY' 'Word8'), ('PixelRGB' 'Word8'), ('PixelRGBA' 'Word8')  * 'GIF':@@ -378,14 +402,14 @@  * 'PNG': -    * __read__: ('PixelY' 'Word8'), ('PixelY' 'Word16'), ('PixelYA' 'Word8'), ('PixelYA' 'Word16'),+    * __read__: ('PixelX' 'Bit'), ('PixelY' 'Word8'), ('PixelY' 'Word16'), ('PixelYA' 'Word8'), ('PixelYA' 'Word16'),     ('PixelRGB' 'Word8'), ('PixelRGB' 'Word16'), ('PixelRGBA' 'Word8'), ('PixelRGBA' 'Word16')     * __write__: ('PixelY' 'Word8'), ('PixelY' 'Word16'), ('PixelYA' 'Word8'), ('PixelYA' 'Word16'),     ('PixelRGB' 'Word8'), ('PixelRGB' 'Word16'), ('PixelRGBA' 'Word8'), ('PixelRGBA' 'Word16')  * 'TGA': -    * __read__: ('PixelY' 'Word8'), ('PixelRGB' 'Word8'), ('PixelRGBA' 'Word8')+    * __read__: ('PixelX' 'Bit'), ('PixelY' 'Word8'), ('PixelRGB' 'Word8'), ('PixelRGBA' 'Word8')     * __write__: ('PixelY' 'Word8'), ('PixelRGB' 'Word8'), ('PixelRGBA' 'Word8')  * 'TIF':@@ -404,16 +428,16 @@ * 'PBM':      * __read__: ('PixelY' 'Bit')-    * Also supports sequence of images in one file, when read as @['PBM']@+    * Also supports `Sequence` of images in one file, when read as @['PBM']@  * 'PGM':      * __read__: ('PixelY' 'Word8'), ('PixelY' 'Word16')-    * Also supports sequence of images in one file, when read as @['PGM']@+    * Also supports `Sequence` of images in one file, when read as @['PGM']@  * 'PPM':      * __read__: ('PixelRGB' 'Word8'), ('PixelRGB' 'Word16')-    * Also supports sequence of images in one file, when read as @['PPM']@+    * Also supports `Sequence` of images in one file, when read as @['PPM']@  -}
src/Data/Massiv/Array/IO/Base.hs view
@@ -11,7 +11,7 @@ {-# LANGUAGE UndecidableInstances #-} -- | -- Module      : Data.Massiv.Array.IO.Base--- Copyright   : (c) Alexey Kuleshevich 2018-2020+-- Copyright   : (c) Alexey Kuleshevich 2018-2021 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -19,6 +19,7 @@ -- module Data.Massiv.Array.IO.Base   ( FileFormat(..)+  , selectFileFormat   , Readable(..)   , decode'   , Writable(..)@@ -27,11 +28,13 @@   , EncodeError(..)   , DecodeError(..)   , Sequence(..)+  , Default(..)   , Auto(..)   , Image   , convertImage   , toImageBaseModel   , fromImageBaseModel+  , coerceBinaryImage   , demoteLumaImage   , promoteLumaImage   , demoteLumaAlphaImage@@ -52,31 +55,35 @@ import Control.Monad.Catch (MonadThrow(..)) import qualified Data.ByteString as B (ByteString) import qualified Data.ByteString.Lazy as BL (ByteString)+import Data.Char (toLower) import Data.Default.Class (Default(..)) import qualified Data.Massiv.Array as A import Data.Typeable import qualified Data.Vector.Storable as V import Graphics.Pixel as CM import Graphics.Pixel.ColorSpace+import Prelude as P+import System.FilePath (takeExtension) import Unsafe.Coerce #if !MIN_VERSION_massiv(0,5,0) import Data.Massiv.Array.Manifest.Vector #endif type Image r cs e = A.Array r A.Ix2 (Pixel cs e) --- | Conversion error, which is thrown when there is a mismatch between the--- expected array type and the one supported by the file format. It is also--- thrown upon a failure of automatic conversion between those types, in case--- such conversion is utilized.+-- | Conversion error, which is thrown when there is a mismatch between the expected array+-- type and the one supported by the file format. It is also thrown upon a failure of+-- automatic conversion between those types, in case when such conversion is utilized. newtype ConvertError = ConvertError String deriving Show -instance Exception ConvertError+instance Exception ConvertError where+  displayException (ConvertError str) = "ConvertError: " ++ str  -- | This exception can be thrown while reading/decoding a file and indicates an -- error in the file itself. newtype DecodeError = DecodeError String deriving Show -instance Exception DecodeError+instance Exception DecodeError where+  displayException (DecodeError str) = "DecodeError: " ++ str  -- | This exception can be thrown while writing/encoding into a file and -- indicates an error in an array that is being encoded.@@ -125,7 +132,18 @@   ext (Auto f) = ext f   exts (Auto f) = exts f +-- | Try to select a file format by looking at the file extension and matching it to one+-- of the formats in the list+--+-- @since 0.4.1+selectFileFormat :: (FileFormat f, MonadThrow m) => [f] -> FilePath -> m f+selectFileFormat formats path = do+  let ext' = P.map toLower . takeExtension $ path+  case P.dropWhile (not . isFormat ext') formats of+    []    -> throwM $ EncodeError $ "File format is not supported: " ++ ext'+    (f:_) -> pure f + -- | File formats that can be read into arrays. class FileFormat f => Readable f arr where   {-# MINIMAL (decodeM | decodeWithMetadataM) #-}@@ -162,6 +180,7 @@   -- @since 0.2.0   encodeM :: MonadThrow m => f -> WriteOptions f -> arr -> m BL.ByteString + -- | Helper function to create a `Proxy` from the value. toProxy :: a -> Proxy a toProxy _ = Proxy@@ -278,6 +297,11 @@ fromImageBaseModel :: A.Array A.S A.Ix2 (Pixel (BaseModel cs) e) -> A.Array A.S A.Ix2 (Pixel cs e) fromImageBaseModel = unsafeCoerce +-- | Convert Binary image to its Word8 backed pixel without copy+--+-- @since 0.4.1+coerceBinaryImage :: A.Array A.S A.Ix2 (Pixel CM.X Bit) -> A.Array A.S A.Ix2 (Pixel CM.X Word8)+coerceBinaryImage = unsafeCoerce  -- | Cast an array with Luma pixels to an array with pixels in a plain single channel -- `CM.X` color model
src/Data/Massiv/Array/IO/Image.hs view
@@ -16,49 +16,65 @@   ( module Data.Massiv.Array.IO.Image.JuicyPixels   , module Data.Massiv.Array.IO.Image.Netpbm   -- ** Helper image functions-  , Encode+  , selectFileFormat+  , Encode(..)   , encodeImageM+  , encodeAdhocM+  , writableAdhoc   , imageWriteFormats   , imageWriteAutoFormats-  , Decode+  , Decode(..)   , decodeImageM+  , decodeAdhocM+  , readableAdhoc   , imageReadFormats   , imageReadAutoFormats   ) where  import qualified Data.ByteString as B (ByteString) import qualified Data.ByteString.Lazy as BL (ByteString)-import Data.Char (toLower) import Data.Massiv.Array import Data.Massiv.Array.IO.Base import Data.Massiv.Array.IO.Image.JuicyPixels import Data.Massiv.Array.IO.Image.Netpbm import Graphics.Pixel.ColorSpace import Prelude as P-import System.FilePath (takeExtension)   +-- | Adhoc encoder data Encode out where-  EncodeAs+  -- | Provide a custom way to encode a particular file format. This is an alternative+  -- approach to `Writable` class+  --+  -- @since 0.4.1+  Encode     :: FileFormat f     => f-    -> (forall m. MonadThrow m =>-                    f -> out -> m BL.ByteString)+    -> (forall m. MonadThrow m => f -> out -> m BL.ByteString)     -> Encode out  instance Show (Encode out) where-  show (EncodeAs f _) = show f+  show (Encode f _) = show f -instance FileFormat (Encode (Image r cs e)) where-  ext (EncodeAs f _) = ext f+instance FileFormat (Encode out) where+  ext (Encode f _) = ext f -  exts (EncodeAs f _) = exts f+  exts (Encode f _) = exts f -instance Writable (Encode (Image r cs e)) (Image r cs e) where-  encodeM (EncodeAs f enc) _ = enc f+-- | Decode binary data without requiring `Readable` instances+--+-- @since 0.4.1+encodeAdhocM :: MonadThrow m => Encode out -> out -> m BL.ByteString+encodeAdhocM (Encode f enc) = enc f +-- | Utilize a Writable instance in order to construct an adhoc Encode type+--+-- @since 0.4.1+writableAdhoc :: Writable f out => f -> Encode out+writableAdhoc f = Encode f (`encodeM` def) + -- | Encode an image into a lazy `BL.ByteString`, while selecting the appropriate format from the -- file extension. --@@ -71,23 +87,20 @@   -> Image r cs e -- ^ Image to encode   -> m BL.ByteString encodeImageM formats path img = do-  let ext' = P.map toLower . takeExtension $ path-  case P.dropWhile (not . isFormat ext') formats of-    []    -> throwM $ EncodeError $ "File format is not supported: " ++ ext'-    (f:_) -> encodeM f () img-+  f <- selectFileFormat formats path+  encodeAdhocM f img   -- | List of image formats that can be encoded without any color space conversion. imageWriteFormats :: (Source r Ix2 (Pixel cs e), ColorModel cs e) => [Encode (Image r cs e)] imageWriteFormats =-  [ EncodeAs BMP (\ f -> encodeBMP f def . computeSource @S)-  , EncodeAs GIF (\ f -> encodeGIF f def . computeSource @S)-  , EncodeAs HDR (\ f -> encodeHDR f def . computeSource @S)-  , EncodeAs JPG (\ f -> encodeJPG f def . computeSource @S)-  , EncodeAs PNG (\ f -> encodePNG f . computeSource @S)-  , EncodeAs TGA (\ f -> encodeTGA f . computeSource @S)-  , EncodeAs TIF (\ f -> encodeTIF f . computeSource @S)+  [ Encode PNG (\ f -> encodePNG f . computeSource @S)+  , Encode TIF (\ f -> encodeTIF f . computeSource @S)+  , Encode JPG (\ f -> encodeJPG f def . computeSource @S)+  , Encode BMP (\ f -> encodeBMP f def . computeSource @S)+  , Encode GIF (\ f -> encodeGIF f def . computeSource @S)+  , Encode TGA (\ f -> encodeTGA f . computeSource @S)+  , Encode HDR (\ f -> encodeHDR f def . computeSource @S)   ]  -- | List of image formats that can be encoded with any necessary color space conversions.@@ -95,36 +108,50 @@      (Source r Ix2 (Pixel cs e), ColorSpace cs i e, ColorSpace (BaseSpace cs) i e)   => [Encode (Image r cs e)] imageWriteAutoFormats =-  [ EncodeAs (Auto BMP) (\f -> pure . encodeAutoBMP f def)-  , EncodeAs (Auto GIF) (`encodeAutoGIF` def)-  , EncodeAs (Auto HDR) (\f -> pure . encodeAutoHDR f def)-  , EncodeAs (Auto JPG) (\f -> pure . encodeAutoJPG f def)-  , EncodeAs (Auto PNG) (\f -> pure . encodeAutoPNG f)-  , EncodeAs (Auto TGA) (\f -> pure . encodeAutoTGA f)-  , EncodeAs (Auto TIF) (\f -> pure . encodeAutoTIF f)+  [ Encode (Auto PNG) (\f -> pure . encodeAutoPNG f)+  , Encode (Auto TIF) (\f -> pure . encodeAutoTIF f)+  , Encode (Auto JPG) (\f -> pure . encodeAutoJPG f def)+  , Encode (Auto BMP) (\f -> pure . encodeAutoBMP f def)+  , Encode (Auto GIF) (`encodeAutoGIF` def)+  , Encode (Auto HDR) (\f -> pure . encodeAutoHDR f def)+  , Encode (Auto TGA) (\f -> pure . encodeAutoTGA f)   ]  -+-- | Adhoc decoder data Decode out where-  DecodeAs+  -- | Provide a custom way to encode a particular file format. This is an alternative+  -- approach to `Writable` class+  --+  -- @since 0.4.1+  Decode     :: FileFormat f     => f     -> (forall m. MonadThrow m => f -> B.ByteString -> m out)     -> Decode out  instance Show (Decode out) where-  show (DecodeAs f _) = show f+  show (Decode f _) = show f  instance FileFormat (Decode (Image r cs e)) where-  ext (DecodeAs f _) = ext f+  ext (Decode f _) = ext f -  exts (DecodeAs f _) = exts f+  exts (Decode f _) = exts f -instance Readable (Decode (Image r cs e)) (Image r cs e) where-  decodeM (DecodeAs f dec) = dec f+-- | Decode binary data without requiring `Readable` instances+--+-- @since 0.4.1+decodeAdhocM :: MonadThrow m => Decode out -> B.ByteString -> m out+decodeAdhocM (Decode f dec) = dec f  +-- | Utilize a Readable instance in order to construct an adhoc Decode type+--+-- @since 0.4.1+readableAdhoc :: Readable f out => f -> Decode out+readableAdhoc f = Decode f decodeM++ -- | Decode an image from the strict `ByteString` while inferring format the image is encoded in -- from the file extension --@@ -136,24 +163,22 @@   -> B.ByteString -- ^ Encoded image   -> m (Image r cs e) decodeImageM formats path bs = do-  let ext' = P.map toLower . takeExtension $ path-  case P.dropWhile (not . isFormat ext') formats of-    []    -> throwM $ DecodeError $ "File format is not supported: " ++ ext'-    (f:_) -> decodeM f bs+  f <- selectFileFormat formats path+  decodeAdhocM f bs  -- | List of image formats decodable with no color space conversion imageReadFormats :: ColorModel cs e => [Decode (Image S cs e)] imageReadFormats =-  [ DecodeAs BMP decodeBMP-  , DecodeAs GIF decodeGIF-  , DecodeAs HDR decodeHDR-  , DecodeAs JPG decodeJPG-  , DecodeAs PNG decodePNG-  , DecodeAs TGA decodeTGA-  , DecodeAs TIF decodeTIF-  , DecodeAs PBM (\f -> fmap fst . decodeNetpbmImage f)-  , DecodeAs PGM (\f -> fmap fst . decodeNetpbmImage f)-  , DecodeAs PPM (\f -> fmap fst . decodeNetpbmImage f)+  [ Decode PNG decodePNG+  , Decode TIF decodeTIF+  , Decode JPG decodeJPG+  , Decode BMP decodeBMP+  , Decode GIF decodeGIF+  , Decode HDR decodeHDR+  , Decode TGA decodeTGA+  , Decode PBM (\f -> fmap fst . decodeNetpbmImage f)+  , Decode PGM (\f -> fmap fst . decodeNetpbmImage f)+  , Decode PPM (\f -> fmap fst . decodeNetpbmImage f)   ]  -- | List of image formats decodable with automatic colorspace conversion@@ -161,16 +186,16 @@   :: (Mutable r Ix2 (Pixel cs e), ColorSpace cs i e)   => [Decode (Image r cs e)] imageReadAutoFormats =-  [ DecodeAs (Auto BMP) decodeAutoBMP-  , DecodeAs (Auto GIF) decodeAutoGIF-  , DecodeAs (Auto HDR) decodeAutoHDR-  , DecodeAs (Auto JPG) decodeAutoJPG-  , DecodeAs (Auto PNG) decodeAutoPNG-  , DecodeAs (Auto TGA) decodeAutoTGA-  , DecodeAs (Auto TIF) decodeAutoTIF-  , DecodeAs (Auto PBM) (\f -> fmap fst . decodeAutoNetpbmImage f)-  , DecodeAs (Auto PGM) (\f -> fmap fst . decodeAutoNetpbmImage f)-  , DecodeAs (Auto PPM) (\f -> fmap fst . decodeAutoNetpbmImage f)+  [ Decode (Auto PNG) decodeAutoPNG+  , Decode (Auto TIF) decodeAutoTIF+  , Decode (Auto JPG) decodeAutoJPG+  , Decode (Auto BMP) decodeAutoBMP+  , Decode (Auto GIF) decodeAutoGIF+  , Decode (Auto HDR) decodeAutoHDR+  , Decode (Auto TGA) decodeAutoTGA+  , Decode (Auto PBM) (\f -> fmap fst . decodeAutoNetpbmImage f)+  , Decode (Auto PGM) (\f -> fmap fst . decodeAutoNetpbmImage f)+  , Decode (Auto PPM) (\f -> fmap fst . decodeAutoNetpbmImage f)   ]  
src/Data/Massiv/Array/IO/Image/JuicyPixels/BMP.hs view
@@ -62,6 +62,9 @@    ext _ = ".bmp" +instance Writable BMP (Image A.S CM.X Bit) where+  encodeM f opts img = encodeM f opts (coerceBinaryImage img)+ instance Writable BMP (Image S CM.X Word8) where   encodeM BMP BitmapOptions {bitmapMetadata} =     pure . JP.encodeBitmapWithMetadata bitmapMetadata . toJPImageY8@@ -91,7 +94,6 @@          Writable (Auto BMP) (Image r cs e) where   encodeM f opts = pure . encodeAutoBMP f opts - instance Readable BMP (Image S CM.X Word8) where   decodeWithMetadataM = decodeWithMetadataBMP @@ -150,15 +152,19 @@   -> BitmapOptions   -> Image S cs e   -> m BL.ByteString-encodeBMP f BitmapOptions {bitmapMetadata} img =-  fromMaybeEncode f (Proxy :: Proxy (Image S cs e)) $ do-    Refl <- eqT :: Maybe (e :~: Word8)-    msum-      [ JP.encodeBitmapWithMetadata bitmapMetadata <$> maybeJPImageY8 img-      , JP.encodeBitmapWithMetadata bitmapMetadata <$> maybeJPImageRGB8 img-      , do Refl <- eqT :: Maybe (cs :~: Alpha (Opaque cs))-           JP.encodeBitmapWithMetadata bitmapMetadata <$> maybeJPImageRGBA8 img-      ]+encodeBMP f opts@BitmapOptions {bitmapMetadata} img =+  fromMaybeEncode f (Proxy :: Proxy (Image S cs e)) encoded+  where+    encoded+      | Just Refl <- eqT :: Maybe (Pixel cs e :~: Pixel CM.X Bit) = encodeM BMP opts img+      | Just Refl <- eqT :: Maybe (e :~: Word8) = do+        msum+          [ JP.encodeBitmapWithMetadata bitmapMetadata <$> maybeJPImageY8 img+          , JP.encodeBitmapWithMetadata bitmapMetadata <$> maybeJPImageRGB8 img+          , do Refl <- eqT :: Maybe (cs :~: Alpha (Opaque cs))+               JP.encodeBitmapWithMetadata bitmapMetadata <$> maybeJPImageRGBA8 img+          ]+      | otherwise = Nothing   
src/Data/Massiv/Array/IO/Image/JuicyPixels/Base.hs view
@@ -140,110 +140,97 @@   jpImgs <- decodeError ejpImgs   P.traverse fromDynamicImageAuto jpImgs -fromJPImageM ::-     (Storable (Color cs e), Storable e, JP.Pixel px, MonadThrow m)-  => JP.Image px-  -> Maybe (Pixel cs e :~: Pixel cs' e')-  -> m (Maybe (Image S cs e))-fromJPImageM jimg = P.mapM $ \Refl -> fromJPImageUnsafeM jimg -sequenceMaybe :: Monad m => [m (Maybe a)] -> m (Maybe a)-sequenceMaybe [] = pure Nothing-sequenceMaybe (x:xs) =-  x >>= \case-    Nothing -> sequenceMaybe xs-    ma -> pure ma- fromDynamicImageM ::      forall cs e m. (ColorModel cs e, MonadThrow m)   => JP.DynamicImage   -> m (Maybe (Image S cs e)) fromDynamicImageM jpDynImg =   case jpDynImg of-    JP.ImageY8 jimg ->-      sequenceMaybe-        [ fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel CM.X Word8))-        , fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel (Y' SRGB) Word8))-        , fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel (Y D65) Word8))-        ]-    JP.ImageY16 jimg ->-      sequenceMaybe-        [ fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel CM.X Word16))-        , fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel (Y' SRGB) Word16))-        , fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel (Y D65) Word16))-        ]-    JP.ImageY32 jimg ->-      sequenceMaybe-        [ fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel CM.X Word32))-        , fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel (Y' SRGB) Word32))-        , fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel (Y D65) Word32))-        ]-    JP.ImageYF jimg ->-      sequenceMaybe-        [ fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel CM.X Float))-        , fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel (Y' SRGB) Float))-        , fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel (Y D65) Float))-        ]-    JP.ImageYA8 jimg ->-      sequenceMaybe-        [ fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel (Alpha CM.X) Word8))-        , fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel (Alpha (Y' SRGB)) Word8))-        , fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel (Alpha (Y D65)) Word8))-        ]-    JP.ImageYA16 jimg ->-      sequenceMaybe-        [ fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel (Alpha CM.X) Word16))-        , fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel (Alpha (Y' SRGB)) Word16))-        , fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel (Alpha (Y D65)) Word16))-        ]-    JP.ImageRGB8 jimg ->-      sequenceMaybe-        [ fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel CM.RGB Word8))-        , fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel (SRGB 'NonLinear) Word8))-        , fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel (AdobeRGB 'NonLinear) Word8))-        ]-    JP.ImageRGB16 jimg ->-      sequenceMaybe-        [ fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel CM.RGB Word16))-        , fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel (SRGB 'NonLinear) Word16))-        , fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel (AdobeRGB 'NonLinear) Word16))-        ]-    JP.ImageRGBF jimg ->-      sequenceMaybe-        [ fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel CM.RGB Float))-        , fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel (SRGB 'NonLinear) Float))-        , fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel (AdobeRGB 'NonLinear) Float))-        ]-    JP.ImageRGBA8 jimg ->-      sequenceMaybe-        [ fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel (Alpha CM.RGB) Word8))-        , fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel (Alpha (SRGB 'NonLinear)) Word8))-        , fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel (Alpha (AdobeRGB 'NonLinear)) Word8))-        ]-    JP.ImageRGBA16 jimg ->-      sequenceMaybe-        [ fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel (Alpha CM.RGB) Word16))-        , fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel (Alpha (SRGB 'NonLinear)) Word16))-        , fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel (Alpha (AdobeRGB 'NonLinear)) Word16))-        ]-    JP.ImageYCbCr8 jimg ->-      sequenceMaybe-        [ fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel CM.YCbCr Word8))-        , fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel (Y'CbCr SRGB) Word8))-        , fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel (Y'CbCr AdobeRGB) Word8))-        ]-    JP.ImageCMYK8 jimg ->-      sequenceMaybe-        [ fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel CM.CMYK Word8))-        , fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel (CMYK (SRGB 'NonLinear)) Word8))-        , fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel (CMYK (AdobeRGB 'NonLinear)) Word8))-        ]-    JP.ImageCMYK16 jimg ->-      sequenceMaybe-        [ fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel CM.CMYK Word16))-        , fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel (CMYK (SRGB 'NonLinear)) Word16))-        , fromJPImageM jimg (eqT :: Maybe (Pixel cs e :~: Pixel (CMYK (AdobeRGB 'NonLinear)) Word16))-        ]+    JP.ImageY8 jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel (Y' SRGB) Word8)) -> justFromJP jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel (Y D65) Word8)) -> justFromJP jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel CM.X Word8)) -> justFromJP jimg+      | otherwise -> pure Nothing+    JP.ImageY16 jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel (Y' SRGB) Word16)) -> justFromJP jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel (Y D65) Word16)) -> justFromJP jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel CM.X Word16)) -> justFromJP jimg+      | otherwise -> pure Nothing+    JP.ImageY32 jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel (Y' SRGB) Word32)) -> justFromJP jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel (Y D65) Word32)) -> justFromJP jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel CM.X Word32)) -> justFromJP jimg+      | otherwise -> pure Nothing+    JP.ImageYF jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel (Y' SRGB) Float)) -> justFromJP jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel (Y D65) Float)) -> justFromJP jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel CM.X Float)) -> justFromJP jimg+      | otherwise -> pure Nothing+    JP.ImageYA8 jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel (Alpha (Y' SRGB)) Word8)) -> justFromJP jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel (Alpha (Y D65)) Word8)) -> justFromJP jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel (Alpha CM.X) Word8)) -> justFromJP jimg+      | otherwise -> pure Nothing+    JP.ImageYA16 jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel (Alpha (Y' SRGB)) Word16)) -> justFromJP jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel (Alpha (Y D65)) Word16)) -> justFromJP jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel (Alpha CM.X) Word16)) -> justFromJP jimg+      | otherwise -> pure Nothing+    JP.ImageRGB8 jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel (SRGB 'NonLinear) Word8)) -> justFromJP jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel (AdobeRGB 'NonLinear) Word8)) ->+        justFromJP jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel CM.RGB Word8)) -> justFromJP jimg+      | otherwise -> pure Nothing+    JP.ImageRGB16 jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel (SRGB 'NonLinear) Word16)) -> justFromJP jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel (AdobeRGB 'NonLinear) Word16)) ->+        justFromJP jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel CM.RGB Word16)) -> justFromJP jimg+      | otherwise -> pure Nothing+    JP.ImageRGBF jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel (SRGB 'NonLinear) Float)) -> justFromJP jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel (AdobeRGB 'NonLinear) Float)) ->+        justFromJP jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel CM.RGB Float)) -> justFromJP jimg+      | otherwise -> pure Nothing+    JP.ImageRGBA8 jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel (Alpha (SRGB 'NonLinear)) Word8)) ->+        justFromJP jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel (Alpha (AdobeRGB 'NonLinear)) Word8)) ->+        justFromJP jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel (Alpha CM.RGB) Word8)) -> justFromJP jimg+      | otherwise -> pure Nothing+    JP.ImageRGBA16 jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel (Alpha (SRGB 'NonLinear)) Word16)) ->+        justFromJP jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel (Alpha (AdobeRGB 'NonLinear)) Word16)) ->+        justFromJP jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel (Alpha CM.RGB) Word16)) -> justFromJP jimg+      | otherwise -> pure Nothing+    JP.ImageYCbCr8 jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel (Y'CbCr SRGB) Word8)) -> justFromJP jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel (Y'CbCr AdobeRGB) Word8)) -> justFromJP jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel CM.YCbCr Word8)) -> justFromJP jimg+      | otherwise -> pure Nothing+    JP.ImageCMYK8 jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel (CMYK (SRGB 'NonLinear)) Word8)) ->+        justFromJP jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel (CMYK (AdobeRGB 'NonLinear)) Word8)) ->+        justFromJP jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel CM.CMYK Word8)) -> justFromJP jimg+      | otherwise -> pure Nothing+    JP.ImageCMYK16 jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel (CMYK (SRGB 'NonLinear)) Word16)) ->+        justFromJP jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel (CMYK (AdobeRGB 'NonLinear)) Word16)) ->+        justFromJP jimg+      | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel CM.CMYK Word16)) -> justFromJP jimg+      | otherwise -> pure Nothing+  where+    justFromJP :: JP.Pixel px => JP.Image px -> m (Maybe (Image S cs e))+    justFromJP = fmap Just . fromJPImageUnsafeM  fromDynamicImage ::      forall cs e. ColorModel cs e@@ -645,7 +632,7 @@   unless (numComponentsPerPixel == numberOfComponentsFromSize) $     throwM $ ConvertError $     concat-      [ "Mismatched sizes beteen JuicyPixels: "+      [ "Mismatched sizes between JuicyPixels: "       , show numComponentsPerPixel       , " and massiv: "       , show numberOfComponentsFromSize
src/Data/Massiv/Array/IO/Image/JuicyPixels/GIF.hs view
@@ -76,6 +76,9 @@   type Metadata GIF = JP.Metadatas   ext _ = ".gif" +instance Writable GIF (Image A.S CM.X Bit) where+  encodeM f opts img = encodeM f opts (coerceBinaryImage img)+ instance Writable GIF (Image S CM.X Word8) where   encodeM GIF _ =  pure . JP.encodeGifImage . toJPImageY8 @@ -168,13 +171,13 @@       \case         Just bs -> pure bs         Nothing-          | Just Refl <- (eqT :: Maybe (e :~: Word8))-          , Just Refl <- (eqT :: Maybe (cs :~: CM.RGB)) -> encodePalettizedRGB opts img-          | Just Refl <- (eqT :: Maybe (e :~: Word8))-          , Just Refl <- (eqT :: Maybe (cs :~: SRGB 'NonLinear)) ->+          | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel CM.X Bit)) ->+            encodeM f opts img+          | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel CM.RGB Word8)) ->+            encodePalettizedRGB opts img+          | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel (SRGB 'NonLinear) Word8)) ->             encodePalettizedRGB opts $ toImageBaseModel img-          | Just Refl <- (eqT :: Maybe (e :~: Word8))-          , Just Refl <- (eqT :: Maybe (cs :~: AdobeRGB 'NonLinear)) ->+          | Just Refl <- (eqT :: Maybe (Pixel cs e :~: Pixel (AdobeRGB 'NonLinear) Word8)) ->             encodePalettizedRGB opts $ toImageBaseModel img         Nothing -> fromMaybeEncode f (Proxy :: Proxy (Image S cs e)) Nothing @@ -270,6 +273,8 @@   delays <- decodeError $ JP.getDelaysGifImages bs   pure (imgs, delays) +instance Writable (Sequence GIF) (NE.NonEmpty (JP.GifDelay, Image S CM.X Bit)) where+  encodeM f opts imgs = encodeM f opts (fmap (fmap coerceBinaryImage) imgs)  instance Writable (Sequence GIF) (NE.NonEmpty (JP.GifDelay, Image S CM.X Word8)) where   encodeM _ SequenceGifOptions {sequenceGifLooping} gifs =
src/Data/Massiv/Array/IO/Image/JuicyPixels/JPG.hs view
@@ -67,6 +67,9 @@   ext _ = ".jpg"   exts _ = [".jpg", ".jpeg"] +instance Writable JPG (Image A.S CM.X Bit) where+  encodeM f opts img = encodeM f opts (coerceBinaryImage img)+ instance Writable JPG (Image S CM.X Word8) where   encodeM JPG JpegOptions {jpegQuality, jpegMetadata} =     pure . JP.encodeDirectJpegAtQualityWithMetadata jpegQuality jpegMetadata . toJPImageY8@@ -177,16 +180,22 @@   -> JpegOptions   -> Image S cs e   -> m BL.ByteString-encodeJPG f JpegOptions {jpegQuality, jpegMetadata} img =-  fromMaybeEncode f (Proxy :: Proxy (Image S cs e)) $ do-    Refl <- eqT :: Maybe (e :~: Word8)-    msum-      [ JP.encodeDirectJpegAtQualityWithMetadata jpegQuality jpegMetadata <$> maybeJPImageY8 img-      , JP.encodeDirectJpegAtQualityWithMetadata jpegQuality jpegMetadata <$> maybeJPImageRGB8 img-      , JP.encodeDirectJpegAtQualityWithMetadata jpegQuality jpegMetadata <$> maybeJPImageYCbCr8 img-      , JP.encodeDirectJpegAtQualityWithMetadata jpegQuality jpegMetadata <$> maybeJPImageCMYK8 img-      ]-+encodeJPG f opts@JpegOptions {jpegQuality, jpegMetadata} img =+  fromMaybeEncode f (Proxy :: Proxy (Image S cs e)) encoded+  where+    encoded+      | Just Refl <- eqT :: Maybe (Pixel cs e :~: Pixel CM.X Bit) = encodeM JPG opts img+      | Just Refl <- eqT :: Maybe (e :~: Word8) =+        msum+          [ JP.encodeDirectJpegAtQualityWithMetadata jpegQuality jpegMetadata <$> maybeJPImageY8 img+          , JP.encodeDirectJpegAtQualityWithMetadata jpegQuality jpegMetadata <$>+            maybeJPImageRGB8 img+          , JP.encodeDirectJpegAtQualityWithMetadata jpegQuality jpegMetadata <$>+            maybeJPImageYCbCr8 img+          , JP.encodeDirectJpegAtQualityWithMetadata jpegQuality jpegMetadata <$>+            maybeJPImageCMYK8 img+          ]+      | otherwise = Nothing   encodeAutoJPG ::
src/Data/Massiv/Array/IO/Image/JuicyPixels/PNG.hs view
@@ -52,6 +52,9 @@   type Metadata PNG = JP.Metadatas   ext _ = ".png" +instance Writable PNG (Image A.S CM.X Bit) where+  encodeM f opts img = encodeM f opts (coerceBinaryImage img)+ instance Writable PNG (Image S CM.X Word8) where   encodeM PNG _ img = pure $ JP.encodePng (toJPImageY8 img) @@ -215,25 +218,25 @@   => PNG   -> Image S cs e   -> m BL.ByteString-encodePNG f img =-  fromMaybeEncode f (Proxy :: Proxy (Image S cs e)) $-  msum-    [ do Refl <- eqT :: Maybe (e :~: Word8)-         msum-           [ JP.encodePng <$> maybeJPImageY8 img-           , JP.encodePng <$> maybeJPImageRGB8 img-           , do Refl <- eqT :: Maybe (cs :~: Alpha (Opaque cs))-                msum [JP.encodePng <$> maybeJPImageYA8 img, JP.encodePng <$> maybeJPImageRGBA8 img]-           ]-    , do Refl <- eqT :: Maybe (e :~: Word16)-         msum-           [ JP.encodePng <$> maybeJPImageY16 img-           , JP.encodePng <$> maybeJPImageRGB16 img-           , do Refl <- eqT :: Maybe (cs :~: Alpha (Opaque cs))-                msum-                  [JP.encodePng <$> maybeJPImageYA16 img, JP.encodePng <$> maybeJPImageRGBA16 img]-           ]-    ]+encodePNG f img = fromMaybeEncode f (Proxy :: Proxy (Image S cs e)) encoded+  where+    encoded+      | Just Refl <- eqT :: Maybe (Pixel cs e :~: Pixel CM.X Bit) = encodeM PNG () img+      | Just Refl <- eqT :: Maybe (e :~: Word8) =+        msum+          [ JP.encodePng <$> maybeJPImageY8 img+          , JP.encodePng <$> maybeJPImageRGB8 img+          , do Refl <- eqT :: Maybe (cs :~: Alpha (Opaque cs))+               msum [JP.encodePng <$> maybeJPImageYA8 img, JP.encodePng <$> maybeJPImageRGBA8 img]+          ]+      | Just Refl <- eqT :: Maybe (e :~: Word16) =+        msum+          [ JP.encodePng <$> maybeJPImageY16 img+          , JP.encodePng <$> maybeJPImageRGB16 img+          , do Refl <- eqT :: Maybe (cs :~: Alpha (Opaque cs))+               msum [JP.encodePng <$> maybeJPImageYA16 img, JP.encodePng <$> maybeJPImageRGBA16 img]+          ]+      | otherwise = Nothing   encodeAutoPNG ::
src/Data/Massiv/Array/IO/Image/JuicyPixels/TGA.hs view
@@ -53,6 +53,9 @@   type Metadata TGA = JP.Metadatas   ext _ = ".tga" +instance Writable TGA (Image A.S CM.X Bit) where+  encodeM f opts img = encodeM f opts (coerceBinaryImage img)+ instance Writable TGA (Image S CM.X Word8) where   encodeM TGA _ img = pure $ JP.encodeTga (toJPImageY8 img) @@ -139,16 +142,18 @@   => TGA   -> Image S cs e   -> m BL.ByteString-encodeTGA f img =-  fromMaybeEncode f (Proxy :: Proxy (Image S cs e)) $ do-    Refl <- eqT :: Maybe (e :~: Word8)-    msum-      [ JP.encodeTga <$> maybeJPImageY8 img-      , JP.encodeTga <$> maybeJPImageRGB8 img-      , do Refl <- eqT :: Maybe (cs :~: Alpha (Opaque cs))-           JP.encodeTga <$> maybeJPImageRGBA8 img-      ]-+encodeTGA f img = fromMaybeEncode f (Proxy :: Proxy (Image S cs e)) encoded+  where+    encoded+      | Just Refl <- eqT :: Maybe (Pixel cs e :~: Pixel CM.X Bit) = encodeM TGA def img+      | Just Refl <- eqT :: Maybe (e :~: Word8) = do+        msum+          [ JP.encodeTga <$> maybeJPImageY8 img+          , JP.encodeTga <$> maybeJPImageRGB8 img+          , do Refl <- eqT :: Maybe (cs :~: Alpha (Opaque cs))+               JP.encodeTga <$> maybeJPImageRGBA8 img+          ]+      | otherwise = Nothing  encodeAutoTGA ::      forall r cs i e.
src/Data/Massiv/Array/IO/Image/JuicyPixels/TIF.hs view
@@ -60,6 +60,9 @@   ext _ = ".tif"   exts _ = [".tif", ".tiff"] +instance Writable TIF (Image A.S CM.X Bit) where+  encodeM f opts img = encodeM f opts (coerceBinaryImage img)+ instance Writable TIF (Image S CM.X Word8) where   encodeM TIF _ img = pure $ JP.encodeTiff (toJPImageY8 img) @@ -289,33 +292,31 @@   => TIF   -> Image S cs e   -> m BL.ByteString-encodeTIF f img =-  fromMaybeEncode f (Proxy :: Proxy (Image S cs e)) $-  msum-    [ do Refl <- eqT :: Maybe (e :~: Word8)-         msum-           [ JP.encodeTiff <$> maybeJPImageY8 img-           , JP.encodeTiff <$> maybeJPImageRGB8 img-           , do Refl <- eqT :: Maybe (cs :~: Alpha (Opaque cs))-                msum-                  [JP.encodeTiff <$> maybeJPImageYA8 img, JP.encodeTiff <$> maybeJPImageRGBA8 img]-           , JP.encodeTiff <$> maybeJPImageYCbCr8 img-           , JP.encodeTiff <$> maybeJPImageCMYK8 img-           ]-    , do Refl <- eqT :: Maybe (e :~: Word16)-         msum-           [ JP.encodeTiff <$> maybeJPImageY16 img-           , JP.encodeTiff <$> maybeJPImageRGB16 img-           , do Refl <- eqT :: Maybe (cs :~: Alpha (Opaque cs))-                msum-                  [JP.encodeTiff <$> maybeJPImageYA16 img, JP.encodeTiff <$> maybeJPImageRGBA16 img]-           , JP.encodeTiff <$> maybeJPImageCMYK16 img-           ]-    , do Refl <- eqT :: Maybe (e :~: Word32)-         JP.encodeTiff <$> maybeJPImageY32 img-    , do Refl <- eqT :: Maybe (e :~: Float)-         JP.encodeTiff <$> maybeJPImageYF img-    ]+encodeTIF f img = fromMaybeEncode f (Proxy :: Proxy (Image S cs e)) encoded+  where+    encoded+      | Just Refl <- eqT :: Maybe (Pixel cs e :~: Pixel CM.X Bit) = encodeM TIF def img+      | Just Refl <- eqT :: Maybe (e :~: Word8) =+        msum+          [ JP.encodeTiff <$> maybeJPImageY8 img+          , JP.encodeTiff <$> maybeJPImageRGB8 img+          , do Refl <- eqT :: Maybe (cs :~: Alpha (Opaque cs))+               msum [JP.encodeTiff <$> maybeJPImageYA8 img, JP.encodeTiff <$> maybeJPImageRGBA8 img]+          , JP.encodeTiff <$> maybeJPImageYCbCr8 img+          , JP.encodeTiff <$> maybeJPImageCMYK8 img+          ]+      | Just Refl <- eqT :: Maybe (e :~: Word16) =+        msum+          [ JP.encodeTiff <$> maybeJPImageY16 img+          , JP.encodeTiff <$> maybeJPImageRGB16 img+          , do Refl <- eqT :: Maybe (cs :~: Alpha (Opaque cs))+               msum+                 [JP.encodeTiff <$> maybeJPImageYA16 img, JP.encodeTiff <$> maybeJPImageRGBA16 img]+          , JP.encodeTiff <$> maybeJPImageCMYK16 img+          ]+      | Just Refl <- eqT :: Maybe (e :~: Word32) = JP.encodeTiff <$> maybeJPImageY32 img+      | Just Refl <- eqT :: Maybe (e :~: Float) = JP.encodeTiff <$> maybeJPImageYF img+      | otherwise = Nothing   
tests/Test/Massiv/Array/IO/Image/Common.hs view
@@ -6,12 +6,12 @@ {-# LANGUAGE TypeApplications #-} module Test.Massiv.Array.IO.Image.Common where +import qualified Data.ByteString.Lazy as BL import Data.List.NonEmpty as NE (NonEmpty(..)) import Data.Massiv.Array import Data.Massiv.Array.IO-import qualified Data.ByteString.Lazy as BL-import Test.Massiv.Core import System.Random+import Test.Massiv.Core   elevatorGen :: (Random e, Elevator e) => Gen e