{-# LANGUAGE FlexibleContexts, TypeFamilies #-}

-----------------------------------------------------------------------------
-- |
-- Module      :  Diagrams.TwoD.Input
-- Copyright   :  (c) 2015 Tillmann Vogt
-- License     :  BSD-style (see LICENSE)
-- Maintainer  :  diagrams-discuss@googlegroups.com
--
-- Importing external images into diagrams.
-----------------------------------------------------------------------------

module Diagrams.TwoD.Input
    ( loadImageEmbedded
    , loadImageExternal
    ) where

import           Control.Monad (msum)
import           Codec.Picture
import           Codec.Picture.Types  (dynamicMap)

import           Data.Semigroup
import           Data.Typeable        (Typeable)

import           Diagrams.Core
import           Diagrams.TwoD.Image
import           Diagrams.TwoD.Size
import           Diagrams.TwoD.Types
import qualified Diagrams.TwoD.Text as TT
import           Diagrams.SVG.ReadSVG (readSVGFile, InputConstraints)
import           Diagrams.SVG.Tree (Place)
import           Filesystem.Path.CurrentOS (decodeString)

-- | Load 2d formats given by a filepath and embed them
loadImageEmbedded :: (InputConstraints b n, Renderable (TT.Text n) b, Read n, n ~ Place) 
                   => String -> IO (Either String (QDiagram b V2 n Any))
loadImageEmbedded :: forall b n.
(InputConstraints b n, Renderable (Text n) b, Read n, n ~ Place) =>
String -> IO (Either String (QDiagram b V2 n Any))
loadImageEmbedded String
path = do
  Either String DynamicImage
dImg <- String -> IO (Either String DynamicImage)
readImage String
path
  Either String (QDiagram b V2 n Any)
svgImg <- forall b n.
(V b ~ V2, N b ~ n, RealFloat n, Renderable (Path V2 n) b,
 Renderable (DImage n Embedded) b, Typeable b, Typeable n, Show n,
 Read n, n ~ Place, Renderable (Text n) b) =>
FilePath -> IO (Either String (Diagram b))
readSVGFile (String -> FilePath
decodeString String
path)
  forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, MonadPlus m) =>
t (m a) -> m a
msum  [ Either String (QDiagram b V2 n Any)
svgImg,
                   forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall n a b.
(TypeableFloat n, Typeable a, Renderable (DImage n a) b) =>
DImage n a -> QDiagram b V2 n Any
imageforall b c a. (b -> c) -> (a -> b) -> a -> c
.forall {a}. Num a => DynamicImage -> DImage a Embedded
rasterImage) Either String DynamicImage
dImg ] -- skip "Left"s and use the first "Right" image
  where
    rasterImage :: DynamicImage -> DImage a Embedded
rasterImage DynamicImage
img = forall b a.
ImageData b -> Int -> Int -> Transformation V2 a -> DImage a b
DImage (DynamicImage -> ImageData Embedded
ImageRaster DynamicImage
img) (forall a.
(forall pixel. Pixel pixel => Image pixel -> a)
-> DynamicImage -> a
dynamicMap forall a. Image a -> Int
imageWidth DynamicImage
img) (forall a.
(forall pixel. Pixel pixel => Image pixel -> a)
-> DynamicImage -> a
dynamicMap forall a. Image a -> Int
imageHeight DynamicImage
img) forall a. Monoid a => a
mempty

-- | Load 2d formats given by a filepath and make a reference
loadImageExternal :: (InputConstraints b n, Renderable (DImage n External) b) 
                   => FilePath -> IO (Either String (QDiagram b V2 n Any))
loadImageExternal :: forall b n.
(InputConstraints b n, Renderable (DImage n External) b) =>
String -> IO (Either String (QDiagram b V2 n Any))
loadImageExternal String
path = do
  Either String DynamicImage
dImg <- String -> IO (Either String DynamicImage)
readImage String
path
--  svgImg <- readSVGFile path
  forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, MonadPlus m) =>
t (m a) -> m a
msum [ forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall n a b.
(TypeableFloat n, Typeable a, Renderable (DImage n a) b) =>
DImage n a -> QDiagram b V2 n Any
imageforall b c a. (b -> c) -> (a -> b) -> a -> c
.DynamicImage -> DImage n External
rasterPath) Either String DynamicImage
dImg ]
--                svgImg ] -- skip "Left"s and use the first "Right" image
  where
    rasterPath :: DynamicImage -> DImage n External
rasterPath DynamicImage
img = forall b a.
ImageData b -> Int -> Int -> Transformation V2 a -> DImage a b
DImage (String -> ImageData External
ImageRef String
path) (forall a.
(forall pixel. Pixel pixel => Image pixel -> a)
-> DynamicImage -> a
dynamicMap forall a. Image a -> Int
imageWidth DynamicImage
img) (forall a.
(forall pixel. Pixel pixel => Image pixel -> a)
-> DynamicImage -> a
dynamicMap forall a. Image a -> Int
imageHeight DynamicImage
img) forall a. Monoid a => a
mempty