aboutsummaryrefslogtreecommitdiffstats
path: root/src/Main.hs
blob: c7c0fbff6f9deb4806c15102437e34d1523605b0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
module Main where

import           Control.Concurrent
import           Criterion
import           Data.Bifunctor       (Bifunctor, bimap)
import qualified Data.ByteString      as B
import qualified Data.ByteString.Lazy as BL
import qualified Data.Text            as T
import           Data.Word            (Word8)
import           PFM
import           System.Directory     (createDirectoryIfMissing)

clamp :: PFMColour -> PPMColour
clamp (PFMColour ri gi bi) =
  PPMColour (f ri) (f gi) (f bi)
  where
    v s = s * 255.0
    f s = if v s > 255.0 then 255 else fromInteger (floor (v s))
clamp _ = undefined

clampImage :: PFMImage -> PPMImage
clampImage (PFMImage w h c) =
  PPMImage w h $ fmap clamp <$> c

bmap :: (Bifunctor f) => (a -> b) -> f a a -> f b b
bmap f = bimap f f

uncurry3 :: (a -> b -> c -> d) -> (a, b, c) -> d
uncurry3 f (a, b, c) = f a b c

colourCorrect :: Double -> Double
colourCorrect = (+0.5) . (/2)

toCircle :: ((Int, Int) -> PFMColour) -> Int -> [[(Int, Int)]] -> [[PFMColour]]
toCircle f v m =
  fmap toCol <$> m
  where
    toCol val = if dist val <= v ^ (2 :: Int)
      then f val
      else PFMColour 0 0 0--0.5 0.5 1.0
    dist = add . bmap ((^(2 :: Int)) . (v-))
    add (an, bn) = an + bn

toColour :: ((Int, Int) -> Vec Double) -> (Int, Int) -> PFMColour
toColour f val = uncurry3 PFMColour (unVec $ realToFrac . colourCorrect <$> f val)

circleImage :: ((Int, Int) -> PFMColour) -> Int -> PFMImage
circleImage f s = PFMImage s s $ toCircle f ((s - 1) `div` 2)
  [ [ (y, x) | x <- [0..s-1] ] | y <- reverse [0..s-1] ]

bench :: IO ()
bench = do
  im <- B.readFile "data/urbanEM_latlong.pfm"
  let urban = revColour $ parse im
  benchmark $ whnf (circleImage (toColour $ normalise 510)) 511
  benchmark $ whnf (circleImage (toColour $ reflect 510 (Vec (0, 0, 1)))) 511
  benchmark $ whnf (circleImage (fromImage 510 (Vec (0, 0, 1)) urban)) 511

indexTwice :: [[a]] -> (Int, Int) -> a
indexTwice c (y, x) = c !! y !! x

fromImage :: Int -> Vec Double -> PFMImage -> (Int, Int) -> PFMColour
fromImage s v (PFMImage w h c) (y, x) =
  indexTwice c . indexLatLong (w - 1) (h - 1) . toSpherical $ reflect s v (y, x)

applyGamma :: Float -> PFMImage -> PFMImage
applyGamma g (PFMImage w h c) =
  PFMImage w h $ fmap gc <$> c
  where
    gc (PFMColour r gr b) = PFMColour (gamma g r) (gamma g gr) (gamma g b)

fromImageF :: (Int, Int) -> PFMImage -> PFMColour
fromImageF (y, x) (PFMImage w h c) =
  c !! y !! x

myForkIO :: IO () -> IO (MVar ())
myForkIO io = do
  mvar <- newEmptyMVar
  _ <- forkFinally io (\_ -> putMVar mvar ())
  return mvar

printInfo :: PFMImage -> PFMImage -> PFMImage  -> PFMImage -> (Int, Int) -> IO ()
printInfo i r f fg coord = do
  let ref = reflect 510 (Vec (0, 0, 1)) coord
  let (y, x) = coord
  print coord
  putStr "  normalise: "
  print $ normalise 510 coord
  putStr "  reflect: "
  print $ ref
  putStr "  Spherical: "
  print $ toSpherical ref
  putStr "  Index: "
  print . indexLatLong 1023 511 $ toSpherical ref
  putStr "  "
  print $ fromImageF coord i
  putStr "  "
  print $ fromImageF coord r
  putStr "  "
  print $ fromImageF coord f
  putStr "  "
  print $ fromImageF coord fg

main :: IO ()
main = do
  im <- B.readFile "data/urbanEM_latlong.pfm"
  let urban = revColour $ parse im
  let i = circleImage (toColour $ normalise 510) 511
  let r = circleImage (toColour $ reflect 510 (Vec (0, 0, 1))) 511
  let f = circleImage (fromImage 510 (Vec (0, 0, 1)) urban) 511
  let fg = applyGamma 2.2 f
  createDirectoryIfMissing True "data"
  let prnti = printInfo i r f fg
  vars <- sequence $ myForkIO <$>
    [ BL.writeFile "data/normal.ppm" . encodePPM . clampImage $ i
    , BL.writeFile "data/normal.pfm" . encode . revColour $ i
    , BL.writeFile "data/reflect.ppm" . encodePPM . clampImage $ r
    , BL.writeFile "data/reflect.pfm" . encode . revColour $ r
    , BL.writeFile "data/final_nogamma.ppm" . encodePPM . clampImage $ f
    , BL.writeFile "data/final_nogamma.pfm" . encode . revColour $ f
    , BL.writeFile "data/final.ppm" . encodePPM . clampImage $ fg
    , BL.writeFile "data/final.pfm" . encode . revColour $ fg
    ]
  sequence_ $ takeMVar <$> vars