chriswarbo-net: d2f9a8065d5c15a08d3da554e6b97b419d085ad9
1: module Pic where
2:
3: -- Constants
4: scale = 7
5: dim = 2 ^ scale
6: pixels = [(x, y) | x <- [0..dim - 1], y <- [0..dim - 1]]
7:
8: -- Types
9: type Bits = [Bool]
10: type Pixel = (Int, Int)
11: type Mono = Bool
12: type Grey = Int
13: type RGB = (Int, Int, Int)
14:
15: -- Conversions
16: showMono :: Mono -> String
17: showMono True = "1"
18: showMono False = "0"
19:
20: showGrey :: Grey -> String
21: showGrey = show
22:
23: showRGB :: RGB -> String
24: showRGB (r,g,b) = show r ++ " " ++ show g ++ " " ++ show b
25:
26: toBits' :: Int -> Bits
27: toBits' 0 = [False]
28: toBits' 1 = [True]
29: toBits' n = let (d, m) = n `divMod` 2
30: in toBits' m ++ toBits' d
31:
32: toBits :: Int -> Bits
33: toBits n = take scale $ toBits' n ++ repeat False
34:
35: fromBits :: Bits -> Int
36: fromBits [] = 0
37: fromBits (True :xs) = 1 + fromBits (False:xs)
38: fromBits (False:xs) = 2 * fromBits xs
39:
40: -- Image
41: header :: Int -> Int -> String
42: header p c = unlines ["P" ++ show p, -- Format
43: show dim, -- Width
44: show dim, -- Height
45: if c > 0 then show c -- Colour range
46: else ""]
47:
48: monoHeader = header 1 0
49: greyHeader = header 2 dim
50: colourHeader = header 3 dim
51:
52: renderMono :: (Int -> Int -> Mono) -> Pixel -> String
53: renderMono f (x, y) = showMono (f x y)
54:
55: renderGrey :: (Int -> Int -> Grey) -> Pixel -> String
56: renderGrey f (x, y) = showGrey (f x y)
57:
58: renderColour :: (Int -> Int -> RGB) -> Pixel -> String
59: renderColour f (x, y) = showRGB (f x y)
60:
61: monoFrom f = unlines $ monoHeader : map (renderMono f) pixels
62: greyFrom f = unlines $ greyHeader : map (renderGrey f) pixels
63: colourFrom f = unlines $ colourHeader : map (renderColour f) pixels
64:
65: -- Helpers
66: bitWise :: (Bits -> Bits -> Bits) -> Int -> Int -> Int
67: bitWise f x y = fromBits (f (toBits x) (toBits y))
68:
69: toRGB :: Bits -> RGB
70: toRGB bs = (fromBits (take scale bs),
71: fromBits (take scale (drop scale bs)),
72: fromBits (take scale (drop (2 * scale) bs)))
73:
74: chunk :: Int -> [a] -> [[a]]
75: chunk 0 xs = []
76: chunk 1 xs = [xs]
77: chunk n xs = let m = length xs `div` n
78: in take m xs : chunk (n - 1) (drop m xs)
79:
80: hue :: Float -> (Float, Float, Float)
81: hue h = let (i, f) = properFraction (h * 6)
82: q = (1 - f)
83: in case i of
84: 0 -> (1, f, 0)
85: 1 -> (q, 1, 0)
86: 2 -> (0, 1, f)
87: 3 -> (0, q, 1)
88: 4 -> (f, 0, 1)
89: 5 -> (1, 0, q)
90:
91: hues :: Int -> [RGB]
92: hues n = map (toScaleRGB . hue . (/ fromIntegral n) . fromIntegral) [0..n-1]
93:
94: toScale :: Float -> Grey
95: toScale = floor . (fromIntegral dim *)
96:
97: toScaleRGB :: (Float, Float, Float) -> RGB
98: toScaleRGB (x, y, z) = (toScale x, toScale y, toScale z)
99:
100: cols' :: Int -> [(Float, Float, Float)]
101: cols' n = let n' = n `div` 8
102: xs = map ((/ fromIntegral n') . fromIntegral) [1..n']
103: in concatMap (`map` xs) [\b -> (0, 0, b),
104: \g -> (0, g, 1),
105: \b -> (0, 1, b),
106: \r -> (r, 1, 0),
107: \b -> (1, 1, b),
108: \g -> (1, g, 1),
109: \b -> (1, 0, b),
110: \r -> (r, 0, 0)]
111:
112: cols :: Int -> [RGB]
113: cols = map toScaleRGB . cols'
Generated by git2html.