reanimate/videos/color-theory/Grid.hs
David Himmelstrup 4bfafa4d8e Color-theory updates and related API changes. (#50)
Rewamp the scene api, add circle plots, add blender flips, fix caching issue in driver, fix bug in partialSvg.


Former-commit-id: 5cb900521044fee13766dd7474fd9b72c7691686
2020-02-02 09:17:29 +08:00

151 lines
4.5 KiB
Haskell
Executable file

#!/usr/bin/env stack
-- stack --resolver lts-13.14 runghc --package reanimate
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ApplicativeDo #-}
module Grid (gridScene) where
import Control.Lens ()
import Control.Monad
import qualified Data.ByteString as BS
import qualified Data.Map as Map
import Data.Monoid
import qualified Data.Text as T
import Codec.Picture
import Codec.Picture.Jpg
import Codec.Picture.Types
import Data.Maybe
import Data.Word
import Graphics.SvgTree hiding (Image, imageHeight, imageWidth)
import Graphics.SvgTree.Memo
import Numeric
import Reanimate
import Reanimate.Animation
import Reanimate.ColorMap
import Reanimate.ColorSpace
import Reanimate.Constants
import Reanimate.Driver (reanimate)
import Reanimate.Effect
import Reanimate.LaTeX
import Reanimate.Raster
import Reanimate.Scene
import Reanimate.Signal
import Reanimate.Svg
import System.IO.Unsafe
gridScene :: Animation
gridScene = sceneAnimation $ do
sViridis <- monalisaSprite (-1) 1 "viridis"
sCividis <- monalisaSprite 0 1 "cividis"
sParula <- monalisaSprite 1 1 "parula"
sJet <- monalisaSprite (-1) 0 "jet"
sInferno <- monalisaSprite 0 0 "inferno"
sSinebow <- monalisaSprite 1 0 "sinebow"
sTurbo <- monalisaSprite (-1) (-1) "turbo"
sPlasma <- monalisaSprite 0 (-1) "plasma"
sHSV <- monalisaSprite 1 (-1) "hsv"
showMap sViridis
showMap sCividis
showMap sParula
wait 2
showMap sJet
showMap sInferno
showMap sSinebow
wait 2
showMap sTurbo
showMap sPlasma
showMap sHSV
wait 2
return ()
where
showMap hd = do
spriteZ (fst hd) 1
tweenVar (snd hd) 1 $ \v -> fromToS v 1 . curveS 3
wait 1
tweenVar (snd hd) 1 $ \v -> fromToS v 0 . curveS 3
spriteZ (fst hd) 0
maps =
[ ("viridis", viridis)
, ("cividis", cividis)
, ("parula", parula)
, ("jet", jet)
, ("inferno", inferno)
, ("sinebow", sinebow)
, ("turbo", turbo)
, ("plasma", plasma)
, ("hsv", hsv)
]
monalisaSprite :: Double -> Double -> T.Text -> Scene s (Sprite s, Var s Double)
monalisaSprite x y txt = do
highlight <- newVar 0
s <- newSprite $ do
getHighlight <- unVar highlight
return $
translate (screenWidth/3 * x * (1-getHighlight))
(screenHeight/3 * y * (1-getHighlight)) $
scale (fromToS 1 2 (getHighlight)) $
mkGroup
[ scaleToSize (screenWidth/3) (screenHeight/3) $
embedImage $
applyColorMap (fromMaybe jet $ lookup txt maps) monalisa
, translate (-screenWidth/6 + screenWidth*0.005) (screenHeight/6 - screenHeight*0.005) $
scale 0.5 $
withStrokeColor "black" $
withStrokeWidth (defaultStrokeWidth*0.5) $
withFillColor "white" $
latex ("\\texttt{" <> txt <> "}")
]
return (s, highlight)
monalisaPoster :: SVG
monalisaPoster =
mkGroup
[ mkPic (-1) 1 viridis "viridis", mkPic 0 1 cividis "cividis", mkPic 1 1 parula "parula"
, mkPic (-1) 0 jet "jet", mkPic 0 0 inferno "inferno", mkPic 1 0 sinebow "sinebow"
, mkPic (-1) (-1) turbo "turbo", mkPic 0 (-1) plasma "plasma", mkPic 1 (-1) hsv "hsv" ]
where
mkPic x y cm txt =
translate (screenWidth/3 * x) (screenHeight/3 * y) $
mkGroup
[ scaleToSize (screenWidth/3) (screenHeight/3) $ embedImage $
applyColorMap cm monalisa
, translate (-screenWidth/6) (screenHeight/6) $
scale 0.5 $
withStrokeColor "black" $
withStrokeWidth (defaultStrokeWidth*0.5) $
withFillColor "white" $
latex ("\\texttt{" <> txt <> "}")
]
monalisa :: Image PixelRGB8
monalisa = unsafePerformIO $ do
dat <- BS.readFile "monalisa.jpg"
case decodeJpeg dat of
Left err -> error err
Right img -> return $ convertRGB8 img
monalisaLarge :: Image PixelRGB8
monalisaLarge = scaleImage 15 monalisa
scaleImage :: Pixel a => Int -> Image a -> Image a
scaleImage factor img =
generateImage fn (imageWidth img * factor) (imageHeight img * factor)
where
fn x y = pixelAt img (x `div` factor) (y `div` factor)
applyColorMap :: (Double -> PixelRGB8) -> Image PixelRGB8 -> Image PixelRGB8
applyColorMap cmap img =
generateImage fn (imageWidth img) (imageHeight img)
where
fn x y =
case pixelAt img x y of
PixelRGB8 r _ _ -> cmap (fromIntegral r/255)