{-# LANGUAGE FlexibleContexts, TypeFamilies, TypeOperators #-}

-----------------------------------------------------------------------------
-- |
-- 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.Either (isRight)
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) 
                   => FilePath -> IO (Either String (QDiagram b V2 n Any))
loadImageEmbedded :: forall b n.
(InputConstraints b n, Renderable (Text n) b, Read n, n ~ Place) =>
FilePath -> IO (Either FilePath (QDiagram b V2 n Any))
loadImageEmbedded FilePath
path = do
  Either FilePath DynamicImage
dImg <- FilePath -> IO (Either FilePath DynamicImage)
readImage FilePath
path
  Either FilePath (QDiagram b V2 n Any)
svgImg <- FilePath -> IO (Either FilePath (Diagram b))
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 FilePath (Diagram b))
readSVGFile (FilePath -> FilePath
decodeString FilePath
path)
  Either FilePath (QDiagram b V2 n Any)
-> IO (Either FilePath (QDiagram b V2 n Any))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either FilePath (QDiagram b V2 n Any)
 -> IO (Either FilePath (QDiagram b V2 n Any)))
-> Either FilePath (QDiagram b V2 n Any)
-> IO (Either FilePath (QDiagram b V2 n Any))
forall a b. (a -> b) -> a -> b
$ if Either FilePath (QDiagram b V2 n Any) -> Bool
forall a b. Either a b -> Bool
isRight Either FilePath (QDiagram b V2 n Any)
svgImg then Either FilePath (QDiagram b V2 n Any)
svgImg else (DynamicImage -> QDiagram b V2 n Any)
-> Either FilePath DynamicImage
-> Either FilePath (QDiagram b V2 n Any)
forall a b. (a -> b) -> Either FilePath a -> Either FilePath b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (DImage n Embedded -> QDiagram b V2 n Any
forall n a b.
(TypeableFloat n, Typeable a, Renderable (DImage n a) b) =>
DImage n a -> QDiagram b V2 n Any
image(DImage n Embedded -> QDiagram b V2 n Any)
-> (DynamicImage -> DImage n Embedded)
-> DynamicImage
-> QDiagram b V2 n Any
forall b c a. (b -> c) -> (a -> b) -> a -> c
.DynamicImage -> DImage n Embedded
forall {a}. Num a => DynamicImage -> DImage a Embedded
rasterImage) Either FilePath DynamicImage
dImg
 where
   rasterImage :: DynamicImage -> DImage a Embedded
rasterImage DynamicImage
img = ImageData Embedded
-> Int -> Int -> Transformation V2 a -> DImage a Embedded
forall b a.
ImageData b -> Int -> Int -> Transformation V2 a -> DImage a b
DImage (DynamicImage -> ImageData Embedded
ImageRaster DynamicImage
img) ((forall pixel. Pixel pixel => Image pixel -> Int)
-> DynamicImage -> Int
forall a.
(forall pixel. Pixel pixel => Image pixel -> a)
-> DynamicImage -> a
dynamicMap Image pixel -> Int
forall pixel. Pixel pixel => Image pixel -> Int
forall a. Image a -> Int
imageWidth DynamicImage
img) ((forall pixel. Pixel pixel => Image pixel -> Int)
-> DynamicImage -> Int
forall a.
(forall pixel. Pixel pixel => Image pixel -> a)
-> DynamicImage -> a
dynamicMap Image pixel -> Int
forall pixel. Pixel pixel => Image pixel -> Int
forall a. Image a -> Int
imageHeight DynamicImage
img) Transformation V2 a
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) =>
FilePath -> IO (Either FilePath (QDiagram b V2 n Any))
loadImageExternal FilePath
path = do
  --  svgImg <- readSVGFile (decodeString path)
  Either FilePath DynamicImage
dImg <- FilePath -> IO (Either FilePath DynamicImage)
readImage FilePath
path
  Either FilePath (QDiagram b V2 n Any)
-> IO (Either FilePath (QDiagram b V2 n Any))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either FilePath (QDiagram b V2 n Any)
 -> IO (Either FilePath (QDiagram b V2 n Any)))
-> Either FilePath (QDiagram b V2 n Any)
-> IO (Either FilePath (QDiagram b V2 n Any))
forall a b. (a -> b) -> a -> b
$ (DynamicImage -> QDiagram b V2 n Any)
-> Either FilePath DynamicImage
-> Either FilePath (QDiagram b V2 n Any)
forall a b. (a -> b) -> Either FilePath a -> Either FilePath b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (DImage n External -> QDiagram b V2 n Any
forall n a b.
(TypeableFloat n, Typeable a, Renderable (DImage n a) b) =>
DImage n a -> QDiagram b V2 n Any
image(DImage n External -> QDiagram b V2 n Any)
-> (DynamicImage -> DImage n External)
-> DynamicImage
-> QDiagram b V2 n Any
forall b c a. (b -> c) -> (a -> b) -> a -> c
.DynamicImage -> DImage n External
rasterPath) Either FilePath DynamicImage
dImg
 where
   rasterPath :: DynamicImage -> DImage n External
rasterPath DynamicImage
img = ImageData External
-> Int -> Int -> Transformation V2 n -> DImage n External
forall b a.
ImageData b -> Int -> Int -> Transformation V2 a -> DImage a b
DImage (FilePath -> ImageData External
ImageRef FilePath
path) ((forall pixel. Pixel pixel => Image pixel -> Int)
-> DynamicImage -> Int
forall a.
(forall pixel. Pixel pixel => Image pixel -> a)
-> DynamicImage -> a
dynamicMap Image pixel -> Int
forall pixel. Pixel pixel => Image pixel -> Int
forall a. Image a -> Int
imageWidth DynamicImage
img) ((forall pixel. Pixel pixel => Image pixel -> Int)
-> DynamicImage -> Int
forall a.
(forall pixel. Pixel pixel => Image pixel -> a)
-> DynamicImage -> a
dynamicMap Image pixel -> Int
forall pixel. Pixel pixel => Image pixel -> Int
forall a. Image a -> Int
imageHeight DynamicImage
img) Transformation V2 n
forall a. Monoid a => a
mempty