Split ConvertImage into three steps
This commit is contained in:
parent
94c2fbfbc9
commit
9c912d2457
|
@ -33,10 +33,13 @@ module DependencyGenerator
|
||||||
, makeTemplate
|
, makeTemplate
|
||||||
, applyTemplate
|
, applyTemplate
|
||||||
, toText
|
, toText
|
||||||
|
, convertImage
|
||||||
|
|
||||||
, listDirectory
|
, listDirectory
|
||||||
, isDirectory
|
, isDirectory
|
||||||
, readTextFile
|
, readTextFile
|
||||||
, convertImage
|
, openImage
|
||||||
|
, saveImage
|
||||||
, saveTextFile
|
, saveTextFile
|
||||||
, copyFile
|
, copyFile
|
||||||
, copyFile'
|
, copyFile'
|
||||||
|
@ -236,6 +239,9 @@ applyTemplate a b = runFunction ApplyTemplate =<< toTupleToken a b
|
||||||
toText :: TokenableTo String a => a -> DepGenM' Text
|
toText :: TokenableTo String a => a -> DepGenM' Text
|
||||||
toText a = runFunction ToText =<< toToken a
|
toText a = runFunction ToText =<< toToken a
|
||||||
|
|
||||||
|
convertImage :: (TokenableTo Image a, TokenableTo ImageConversionSettings b) => a -> b -> DepGenM' Image
|
||||||
|
convertImage a b = runFunction ConvertImage =<< toTupleToken a b
|
||||||
|
|
||||||
listDirectory :: TokenableTo FilePath a => a -> DepGenM' [FilePath]
|
listDirectory :: TokenableTo FilePath a => a -> DepGenM' [FilePath]
|
||||||
listDirectory a = runFunctionIO ListDirectory =<< toToken a
|
listDirectory a = runFunctionIO ListDirectory =<< toToken a
|
||||||
|
|
||||||
|
@ -245,8 +251,11 @@ isDirectory a = runFunctionIO IsDirectory =<< toToken a
|
||||||
readTextFile :: TokenableTo FilePath a => a -> DepGenM' Text
|
readTextFile :: TokenableTo FilePath a => a -> DepGenM' Text
|
||||||
readTextFile a = runFunctionIO ReadTextFile =<< toToken a
|
readTextFile a = runFunctionIO ReadTextFile =<< toToken a
|
||||||
|
|
||||||
convertImage :: (TokenableTo FilePath a, TokenableTo FilePath b, TokenableTo ImageConversionSettings c) => a -> b -> c -> DepGenM ()
|
openImage :: TokenableTo FilePath a => a -> DepGenM' Image
|
||||||
convertImage a b c = runFunctionIO' ConvertImage =<< toTupleToken (toTupleToken a b) c
|
openImage a = runFunctionIO OpenImage =<< toToken a
|
||||||
|
|
||||||
|
saveImage :: (TokenableTo Image a, TokenableTo FilePath b) => a -> b -> DepGenM ()
|
||||||
|
saveImage a b = runFunctionIO' SaveImage =<< toTupleToken a b
|
||||||
|
|
||||||
saveTextFile :: (TokenableTo Text a, TokenableTo FilePath b) => a -> b -> DepGenM ()
|
saveTextFile :: (TokenableTo Text a, TokenableTo FilePath b) => a -> b -> DepGenM ()
|
||||||
saveTextFile a b = runFunctionIO' SaveTextFile =<< toTupleToken a b
|
saveTextFile a b = runFunctionIO' SaveTextFile =<< toTupleToken a b
|
||||||
|
|
|
@ -5,8 +5,11 @@ module Evaluation.Function
|
||||||
import Prelude hiding (String, FilePath)
|
import Prelude hiding (String, FilePath)
|
||||||
import qualified Prelude
|
import qualified Prelude
|
||||||
|
|
||||||
import Types (Function(..), Value(..), String(..), Template(..), fromValue)
|
import Types.Values
|
||||||
|
import Types (Function(..), Value(..), fromValue, makeString, makeImage)
|
||||||
|
|
||||||
|
import qualified Codec.Picture as CP
|
||||||
|
import qualified Codec.Picture.STBIR as CPS
|
||||||
import Data.Char (toLower)
|
import Data.Char (toLower)
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
|
|
||||||
|
@ -17,9 +20,6 @@ fileComponents s =
|
||||||
_ : firstRev' -> (reverse firstRev', reverse lastRev)
|
_ : firstRev' -> (reverse firstRev', reverse lastRev)
|
||||||
[] -> (reverse lastRev, "")
|
[] -> (reverse lastRev, "")
|
||||||
|
|
||||||
makeString :: Prelude.String -> Value
|
|
||||||
makeString = String . StringWrapper
|
|
||||||
|
|
||||||
unStringWrapper :: Value -> Prelude.String
|
unStringWrapper :: Value -> Prelude.String
|
||||||
unStringWrapper = \case
|
unStringWrapper = \case
|
||||||
String (StringWrapper s) -> s
|
String (StringWrapper s) -> s
|
||||||
|
@ -63,5 +63,12 @@ evalFunction f x = case (f, x) of
|
||||||
(ToText, String (StringWrapper s)) ->
|
(ToText, String (StringWrapper s)) ->
|
||||||
Text $ T.pack s
|
Text $ T.pack s
|
||||||
|
|
||||||
|
(ConvertImage, Tuple (Image (ImageWrapper image),
|
||||||
|
ImageConversionSettings (ResizeToWidth widthResized))) ->
|
||||||
|
let sizeFactor :: Double
|
||||||
|
sizeFactor = fromIntegral (CP.imageWidth image) / fromIntegral widthResized
|
||||||
|
heightResized = round (fromIntegral (CP.imageHeight image) / sizeFactor)
|
||||||
|
in makeImage $ CPS.resize CPS.defaultOptions widthResized heightResized image
|
||||||
|
|
||||||
_ ->
|
_ ->
|
||||||
error "unexpected combination of function and argument type"
|
error "unexpected combination of function and argument type"
|
||||||
|
|
|
@ -5,14 +5,13 @@ module Evaluation.FunctionIO
|
||||||
import Prelude hiding (String, FilePath)
|
import Prelude hiding (String, FilePath)
|
||||||
|
|
||||||
import Types.Values
|
import Types.Values
|
||||||
import Types (FunctionIO(..), Value(..), toValue)
|
import Types (FunctionIO(..), Value(..), toValue, makeImage)
|
||||||
|
|
||||||
import qualified Data.Text.Lazy as TL
|
import qualified Data.Text.Lazy as TL
|
||||||
import qualified Data.Text.IO as T
|
import qualified Data.Text.IO as T
|
||||||
import qualified Text.Pandoc as P
|
import qualified Text.Pandoc as P
|
||||||
import qualified Text.Blaze.Html.Renderer.Text as B
|
import qualified Text.Blaze.Html.Renderer.Text as B
|
||||||
import qualified Codec.Picture as CP
|
import qualified Codec.Picture as CP
|
||||||
import qualified Codec.Picture.STBIR as CPS
|
|
||||||
import System.Directory (listDirectory, doesDirectoryExist, createDirectory, copyFile)
|
import System.Directory (listDirectory, doesDirectoryExist, createDirectory, copyFile)
|
||||||
|
|
||||||
evalFunctionIO :: FunctionIO -> Value -> IO Value
|
evalFunctionIO :: FunctionIO -> Value -> IO Value
|
||||||
|
@ -26,17 +25,14 @@ evalFunctionIO f x = case (f, x) of
|
||||||
(ReadTextFile, String (StringWrapper s)) ->
|
(ReadTextFile, String (StringWrapper s)) ->
|
||||||
Text <$> T.readFile s
|
Text <$> T.readFile s
|
||||||
|
|
||||||
(ConvertImage, Tuple (Tuple (String (StringWrapper source), String (StringWrapper target)),
|
(OpenImage, String (StringWrapper s)) -> do
|
||||||
ImageConversionSettings (ResizeToWidth widthResized))) -> do
|
imageOrig <- CP.readImage s
|
||||||
imageOrig <- CP.readImage source
|
case imageOrig of
|
||||||
let imageOrig' = case imageOrig of
|
Left e -> error ("unexpected error: " ++ e)
|
||||||
Left s -> error ("unexpected error: " ++ s)
|
Right image -> pure $ makeImage $ CP.convertRGB8 image
|
||||||
Right image -> CP.convertRGB8 image
|
|
||||||
sizeFactor :: Double
|
(SaveImage, Tuple (Image (ImageWrapper image), String (StringWrapper s))) -> do
|
||||||
sizeFactor = fromIntegral (CP.imageWidth imageOrig') / fromIntegral widthResized
|
CP.saveJpgImage 90 s $ CP.ImageRGB8 image
|
||||||
heightResized = round (fromIntegral (CP.imageHeight imageOrig') / sizeFactor)
|
|
||||||
imageResized = CPS.resize CPS.defaultOptions widthResized heightResized imageOrig'
|
|
||||||
CP.saveJpgImage 90 target $ CP.ImageRGB8 imageResized
|
|
||||||
pure Empty
|
pure Empty
|
||||||
|
|
||||||
(SaveTextFile, Tuple (Text t, String (StringWrapper s))) -> do
|
(SaveTextFile, Tuple (Text t, String (StringWrapper s))) -> do
|
||||||
|
|
|
@ -18,7 +18,8 @@ handleRecipeDir outputDir htmlTemplate indexName dir = do
|
||||||
path `copyTo` outputDir
|
path `copyTo` outputDir
|
||||||
(base, ext) <- untupleDepGenM $ fileComponents name
|
(base, ext) <- untupleDepGenM $ fileComponents name
|
||||||
thumbnailName <- concatStrings [ pure base, inject "-thumbnail.", pure ext ]
|
thumbnailName <- concatStrings [ pure base, inject "-thumbnail.", pure ext ]
|
||||||
convertImage path (joinPaths recipeDirOut thumbnailName) (inject (ResizeToWidth 800))
|
imageResized <- convertImage (openImage path) (inject (ResizeToWidth 800))
|
||||||
|
saveImage imageResized (joinPaths recipeDirOut thumbnailName)
|
||||||
concatTexts [ inject "<p class=\"image\"><a href=\""
|
concatTexts [ inject "<p class=\"image\"><a href=\""
|
||||||
, toText name
|
, toText name
|
||||||
, inject "\"><img src=\""
|
, inject "\"><img src=\""
|
||||||
|
|
|
@ -15,5 +15,6 @@ data Function = AppendStrings
|
||||||
| MakeTemplate
|
| MakeTemplate
|
||||||
| ApplyTemplate
|
| ApplyTemplate
|
||||||
| ToText
|
| ToText
|
||||||
|
| ConvertImage
|
||||||
deriving (Show, Lift)
|
deriving (Show, Lift)
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,8 @@ import Language.Haskell.TH.Syntax (Lift)
|
||||||
data FunctionIO = ListDirectory
|
data FunctionIO = ListDirectory
|
||||||
| IsDirectory
|
| IsDirectory
|
||||||
| ReadTextFile
|
| ReadTextFile
|
||||||
| ConvertImage
|
| OpenImage
|
||||||
|
| SaveImage
|
||||||
| SaveTextFile
|
| SaveTextFile
|
||||||
| CopyFile
|
| CopyFile
|
||||||
| MakeDir
|
| MakeDir
|
||||||
|
|
|
@ -1,22 +1,31 @@
|
||||||
module Types.Value
|
module Types.Value
|
||||||
( Value(..)
|
( Value(..)
|
||||||
, Valuable(..)
|
, Valuable(..)
|
||||||
|
, makeString
|
||||||
|
, makeImage
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Prelude hiding (String)
|
import Prelude hiding (String)
|
||||||
|
import qualified Prelude
|
||||||
|
|
||||||
import Types.Values
|
import Types.Values
|
||||||
|
|
||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
|
import qualified Codec.Picture as CP
|
||||||
import Language.Haskell.TH.Syntax (Lift)
|
import Language.Haskell.TH.Syntax (Lift)
|
||||||
|
|
||||||
-- Note: We use a wrapper for the String type in order to be able to define the
|
-- Note: We use a wrapper for the String type in order to be able to define the
|
||||||
-- general Valuable [a] instance further down. Otherwise it would conflict with
|
-- general Valuable [a] instance further down. Otherwise it would conflict with
|
||||||
-- our Valuable String instance, since the non-wrapped String type is just an
|
-- our Valuable String instance, since the non-wrapped String type is just an
|
||||||
-- alias for [Char].
|
-- alias for [Char].
|
||||||
|
--
|
||||||
|
-- Also note that the Image type does not actually implement Lift, so you
|
||||||
|
-- shouldn't use it with Inject. The better approach would be to split the
|
||||||
|
-- Value type into a compile-time version and a runtime version.
|
||||||
data Value = String String
|
data Value = String String
|
||||||
| Text Text
|
| Text Text
|
||||||
| Bool Bool
|
| Bool Bool
|
||||||
|
| Image Image
|
||||||
| ImageConversionSettings ImageConversionSettings
|
| ImageConversionSettings ImageConversionSettings
|
||||||
| Template Template
|
| Template Template
|
||||||
| Empty
|
| Empty
|
||||||
|
@ -24,6 +33,12 @@ data Value = String String
|
||||||
| List [Value]
|
| List [Value]
|
||||||
deriving (Eq, Show, Lift)
|
deriving (Eq, Show, Lift)
|
||||||
|
|
||||||
|
makeString :: Prelude.String -> Value
|
||||||
|
makeString = String . StringWrapper
|
||||||
|
|
||||||
|
makeImage :: CP.Image CP.PixelRGB8 -> Value
|
||||||
|
makeImage = Image . ImageWrapper
|
||||||
|
|
||||||
class Valuable a where
|
class Valuable a where
|
||||||
toValue :: a -> Value
|
toValue :: a -> Value
|
||||||
fromValue :: Value -> a
|
fromValue :: Value -> a
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
module Types.Values
|
module Types.Values
|
||||||
( String(..)
|
( String(..)
|
||||||
, FilePath
|
, FilePath
|
||||||
|
, Image(..)
|
||||||
, ImageConversionSettings(..)
|
, ImageConversionSettings(..)
|
||||||
, Template(..)
|
, Template(..)
|
||||||
) where
|
) where
|
||||||
|
@ -10,7 +11,8 @@ import qualified Prelude
|
||||||
|
|
||||||
import Data.String (IsString(..))
|
import Data.String (IsString(..))
|
||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
import Language.Haskell.TH.Syntax (Lift)
|
import qualified Codec.Picture as CP
|
||||||
|
import Language.Haskell.TH.Syntax (Lift(..))
|
||||||
|
|
||||||
newtype String = StringWrapper Prelude.String
|
newtype String = StringWrapper Prelude.String
|
||||||
deriving (Eq, Show, Lift)
|
deriving (Eq, Show, Lift)
|
||||||
|
@ -20,6 +22,15 @@ type FilePath = String
|
||||||
instance IsString String where
|
instance IsString String where
|
||||||
fromString = StringWrapper
|
fromString = StringWrapper
|
||||||
|
|
||||||
|
newtype Image = ImageWrapper (CP.Image CP.PixelRGB8)
|
||||||
|
deriving (Eq)
|
||||||
|
|
||||||
|
instance Show Image where
|
||||||
|
show = const "Image"
|
||||||
|
|
||||||
|
instance Lift Image where
|
||||||
|
liftTyped _ = error "cannot lift images"
|
||||||
|
|
||||||
data ImageConversionSettings = ResizeToWidth Int
|
data ImageConversionSettings = ResizeToWidth Int
|
||||||
deriving (Eq, Show, Lift)
|
deriving (Eq, Show, Lift)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue